@sutrata/editor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. package/LICENSE +674 -0
  2. package/dist/ai/OnboardingDialog.d.ts +6 -0
  3. package/dist/ai/OnboardingDialog.js +115 -0
  4. package/dist/ai/VoiceConfirmDialog.d.ts +9 -0
  5. package/dist/ai/VoiceConfirmDialog.js +37 -0
  6. package/dist/ai/VoiceToolbar.d.ts +2 -0
  7. package/dist/ai/VoiceToolbar.js +177 -0
  8. package/dist/ai/ai-client.d.ts +71 -0
  9. package/dist/ai/ai-client.js +494 -0
  10. package/dist/ai/commands.d.ts +12 -0
  11. package/dist/ai/commands.js +140 -0
  12. package/dist/ai/generated-providers.json +3696 -0
  13. package/dist/ai/prompts.d.ts +25 -0
  14. package/dist/ai/prompts.js +59 -0
  15. package/dist/ai/voice-service.d.ts +15 -0
  16. package/dist/ai/voice-service.js +81 -0
  17. package/dist/autocomplete/AutocompletePlugin.d.ts +2 -0
  18. package/dist/autocomplete/AutocompletePlugin.js +19 -0
  19. package/dist/autocomplete/suggestions.d.ts +25 -0
  20. package/dist/autocomplete/suggestions.js +126 -0
  21. package/dist/context/DocumentContext.d.ts +68 -0
  22. package/dist/context/DocumentContext.js +605 -0
  23. package/dist/desktop-api.d.ts +40 -0
  24. package/dist/editor/EditorView.d.ts +2 -0
  25. package/dist/editor/EditorView.js +78 -0
  26. package/dist/editor/SelectionMenu.d.ts +2 -0
  27. package/dist/editor/SelectionMenu.js +102 -0
  28. package/dist/editor/attr-pencil-plugin.d.ts +17 -0
  29. package/dist/editor/attr-pencil-plugin.js +158 -0
  30. package/dist/editor/character-decoration-plugin.d.ts +26 -0
  31. package/dist/editor/character-decoration-plugin.js +77 -0
  32. package/dist/editor/character-view.d.ts +35 -0
  33. package/dist/editor/character-view.js +112 -0
  34. package/dist/editor/editor-bus.d.ts +14 -0
  35. package/dist/editor/editor-bus.js +39 -0
  36. package/dist/editor/find-highlight-plugin.d.ts +7 -0
  37. package/dist/editor/find-highlight-plugin.js +57 -0
  38. package/dist/editor/frontmatter-field-view.d.ts +10 -0
  39. package/dist/editor/frontmatter-field-view.js +48 -0
  40. package/dist/editor/frontmatter-field.d.ts +21 -0
  41. package/dist/editor/frontmatter-field.js +116 -0
  42. package/dist/editor/grapheme-cursor.d.ts +10 -0
  43. package/dist/editor/grapheme-cursor.js +104 -0
  44. package/dist/editor/ime-plugin.d.ts +18 -0
  45. package/dist/editor/ime-plugin.js +71 -0
  46. package/dist/editor/insert-helper.d.ts +1 -0
  47. package/dist/editor/insert-helper.js +42 -0
  48. package/dist/editor/keymap.d.ts +3 -0
  49. package/dist/editor/keymap.js +131 -0
  50. package/dist/editor/language-class-plugin.d.ts +7 -0
  51. package/dist/editor/language-class-plugin.js +75 -0
  52. package/dist/editor/plugins.d.ts +1 -0
  53. package/dist/editor/plugins.js +25 -0
  54. package/dist/editor/prosemirror-to-sutra.d.ts +2 -0
  55. package/dist/editor/prosemirror-to-sutra.js +208 -0
  56. package/dist/editor/scene-heading-view.d.ts +27 -0
  57. package/dist/editor/scene-heading-view.js +136 -0
  58. package/dist/editor/schema.d.ts +3 -0
  59. package/dist/editor/schema.js +135 -0
  60. package/dist/editor/sutra-to-prosemirror.d.ts +3 -0
  61. package/dist/editor/sutra-to-prosemirror.js +154 -0
  62. package/dist/editor/transliterate-input.d.ts +10 -0
  63. package/dist/editor/transliterate-input.js +88 -0
  64. package/dist/extensions/storage-adapter.d.ts +59 -0
  65. package/dist/extensions/storage-adapter.js +9 -0
  66. package/dist/extensions/types.d.ts +73 -0
  67. package/dist/extensions/types.js +12 -0
  68. package/dist/file/docx-exporter.d.ts +8 -0
  69. package/dist/file/docx-exporter.js +494 -0
  70. package/dist/file/docx-importer.d.ts +10 -0
  71. package/dist/file/docx-importer.js +283 -0
  72. package/dist/file/print-paginator.d.ts +29 -0
  73. package/dist/file/print-paginator.js +289 -0
  74. package/dist/file/templates.d.ts +2 -0
  75. package/dist/file/templates.js +66 -0
  76. package/dist/file/workflow-reports.d.ts +34 -0
  77. package/dist/file/workflow-reports.js +719 -0
  78. package/dist/findreplace/FindReplace.d.ts +2 -0
  79. package/dist/findreplace/FindReplace.js +164 -0
  80. package/dist/findreplace/find-engine.d.ts +29 -0
  81. package/dist/findreplace/find-engine.js +69 -0
  82. package/dist/findreplace/scroll-to-match.d.ts +29 -0
  83. package/dist/findreplace/scroll-to-match.js +74 -0
  84. package/dist/fonts/tofu-detect.d.ts +1 -0
  85. package/dist/fonts/tofu-detect.js +48 -0
  86. package/dist/i18n/LanguageContext.d.ts +10 -0
  87. package/dist/i18n/LanguageContext.js +174 -0
  88. package/dist/i18n/language-detect.d.ts +1 -0
  89. package/dist/i18n/language-detect.js +58 -0
  90. package/dist/i18n/useTranslation.d.ts +11 -0
  91. package/dist/i18n/useTranslation.js +60 -0
  92. package/dist/index.d.ts +11 -0
  93. package/dist/index.js +5 -0
  94. package/dist/locales/bn.json +143 -0
  95. package/dist/locales/en.json +143 -0
  96. package/dist/locales/gu.json +143 -0
  97. package/dist/locales/hi.json +143 -0
  98. package/dist/locales/kn.json +143 -0
  99. package/dist/locales/ml.json +143 -0
  100. package/dist/locales/mr.json +143 -0
  101. package/dist/locales/or.json +143 -0
  102. package/dist/locales/pa.json +143 -0
  103. package/dist/locales/si.json +143 -0
  104. package/dist/locales/ta.json +143 -0
  105. package/dist/locales/te.json +143 -0
  106. package/dist/navigator/SceneNavigator.d.ts +2 -0
  107. package/dist/navigator/SceneNavigator.js +612 -0
  108. package/dist/navigator/StatisticsDialog.d.ts +6 -0
  109. package/dist/navigator/StatisticsDialog.js +146 -0
  110. package/dist/navigator/scene-list.d.ts +16 -0
  111. package/dist/navigator/scene-list.js +70 -0
  112. package/dist/settings/SettingsDialog.d.ts +6 -0
  113. package/dist/settings/SettingsDialog.js +147 -0
  114. package/dist/shell/AppBar.d.ts +2 -0
  115. package/dist/shell/AppBar.js +34 -0
  116. package/dist/shell/AppShell.d.ts +2 -0
  117. package/dist/shell/AppShell.js +30 -0
  118. package/dist/shell/ConfirmDialog.d.ts +16 -0
  119. package/dist/shell/ConfirmDialog.js +23 -0
  120. package/dist/shell/ElementToolbar.d.ts +2 -0
  121. package/dist/shell/ElementToolbar.js +30 -0
  122. package/dist/shell/LanguageStatus.d.ts +2 -0
  123. package/dist/shell/LanguageStatus.js +65 -0
  124. package/dist/shell/StatusBar.d.ts +2 -0
  125. package/dist/shell/StatusBar.js +54 -0
  126. package/dist/shell/SutrataLogo.d.ts +8 -0
  127. package/dist/shell/SutrataLogo.js +7 -0
  128. package/dist/shell/Toast.d.ts +12 -0
  129. package/dist/shell/Toast.js +21 -0
  130. package/dist/shell/ToolbarButton.d.ts +11 -0
  131. package/dist/shell/ToolbarButton.js +4 -0
  132. package/dist/shell/VersionHistory.d.ts +12 -0
  133. package/dist/shell/VersionHistory.js +89 -0
  134. package/dist/shell/Watermark.d.ts +3 -0
  135. package/dist/shell/Watermark.js +10 -0
  136. package/dist/shell/fonts/fonts.css +1133 -0
  137. package/dist/shell/icons.d.ts +45 -0
  138. package/dist/shell/icons.js +51 -0
  139. package/dist/shell/toolbar-actions.d.ts +6 -0
  140. package/dist/shell/toolbar-actions.js +58 -0
  141. package/dist/source/SourceView.d.ts +1 -0
  142. package/dist/source/SourceView.js +106 -0
  143. package/dist/source/find-highlight-source.d.ts +14 -0
  144. package/dist/source/find-highlight-source.js +47 -0
  145. package/dist/source/sutra-lang.d.ts +2 -0
  146. package/dist/source/sutra-lang.js +97 -0
  147. package/dist/spellcheck/dictionaries.d.ts +9 -0
  148. package/dist/spellcheck/dictionaries.js +16 -0
  149. package/dist/spellcheck/hunspell.d.ts +23 -0
  150. package/dist/spellcheck/hunspell.js +94 -0
  151. package/dist/spellcheck/spellcheck-plugin.d.ts +18 -0
  152. package/dist/spellcheck/spellcheck-plugin.js +75 -0
  153. package/dist/styles/StyleDialog.d.ts +6 -0
  154. package/dist/styles/StyleDialog.js +63 -0
  155. package/dist/styles/builtin-styles.d.ts +43 -0
  156. package/dist/styles/builtin-styles.js +131 -0
  157. package/dist/styles/css-adapter.d.ts +32 -0
  158. package/dist/styles/css-adapter.js +71 -0
  159. package/dist/styles/docx-adapter.d.ts +7 -0
  160. package/dist/styles/docx-adapter.js +84 -0
  161. package/dist/styles/embed-fonts.d.ts +20 -0
  162. package/dist/styles/embed-fonts.js +81 -0
  163. package/dist/styles/pagination.d.ts +19 -0
  164. package/dist/styles/pagination.js +22 -0
  165. package/dist/styles/print-adapter.d.ts +6 -0
  166. package/dist/styles/print-adapter.js +288 -0
  167. package/dist/styles/registry.d.ts +6 -0
  168. package/dist/styles/registry.js +14 -0
  169. package/dist/styles/screenplay.css +3006 -0
  170. package/dist/styles/script-ranges.d.ts +6 -0
  171. package/dist/styles/script-ranges.js +17 -0
  172. package/dist/styles/types.d.ts +93 -0
  173. package/dist/styles/types.js +18 -0
  174. package/dist/styles/validate.d.ts +12 -0
  175. package/dist/styles/validate.js +105 -0
  176. package/dist/templates/templates.d.ts +10 -0
  177. package/dist/templates/templates.js +181 -0
  178. package/dist/titlepage/ExportDialog.d.ts +1 -0
  179. package/dist/titlepage/ExportDialog.js +152 -0
  180. package/dist/titlepage/TitlePageDialog.d.ts +6 -0
  181. package/dist/titlepage/TitlePageDialog.js +96 -0
  182. package/dist/titlepage/frontmatter-form.d.ts +56 -0
  183. package/dist/titlepage/frontmatter-form.js +245 -0
  184. package/dist/titlepage/languages.d.ts +10 -0
  185. package/dist/titlepage/languages.js +31 -0
  186. package/dist/types.d.ts +6 -0
  187. package/dist/types.js +1 -0
  188. package/package.json +47 -0
  189. package/scripts/copy-assets.mjs +16 -0
  190. package/scripts/generate-providers.mjs +127 -0
  191. package/src/ai/OnboardingDialog.tsx +390 -0
  192. package/src/ai/VoiceConfirmDialog.tsx +137 -0
  193. package/src/ai/VoiceToolbar.tsx +321 -0
  194. package/src/ai/ai-client.ts +596 -0
  195. package/src/ai/commands.ts +164 -0
  196. package/src/ai/generated-providers.json +3696 -0
  197. package/src/ai/prompts.ts +62 -0
  198. package/src/ai/voice-service.ts +96 -0
  199. package/src/autocomplete/AutocompletePlugin.ts +21 -0
  200. package/src/autocomplete/suggestions.ts +147 -0
  201. package/src/context/DocumentContext.tsx +648 -0
  202. package/src/desktop-api.d.ts +40 -0
  203. package/src/editor/EditorView.tsx +82 -0
  204. package/src/editor/SelectionMenu.tsx +152 -0
  205. package/src/editor/attr-pencil-plugin.ts +172 -0
  206. package/src/editor/character-decoration-plugin.ts +104 -0
  207. package/src/editor/editor-bus.ts +51 -0
  208. package/src/editor/find-highlight-plugin.ts +68 -0
  209. package/src/editor/frontmatter-field-view.ts +52 -0
  210. package/src/editor/frontmatter-field.ts +115 -0
  211. package/src/editor/grapheme-cursor.ts +99 -0
  212. package/src/editor/ime-plugin.ts +85 -0
  213. package/src/editor/insert-helper.ts +43 -0
  214. package/src/editor/keymap.ts +124 -0
  215. package/src/editor/language-class-plugin.ts +91 -0
  216. package/src/editor/plugins.ts +26 -0
  217. package/src/editor/prosemirror-to-sutra.ts +192 -0
  218. package/src/editor/scene-heading-view.ts +147 -0
  219. package/src/editor/schema.ts +156 -0
  220. package/src/editor/sutra-to-prosemirror.ts +156 -0
  221. package/src/extensions/storage-adapter.ts +65 -0
  222. package/src/extensions/types.ts +60 -0
  223. package/src/file/docx-exporter.ts +585 -0
  224. package/src/file/docx-importer.ts +313 -0
  225. package/src/file/print-paginator.ts +301 -0
  226. package/src/file/templates.ts +73 -0
  227. package/src/file/workflow-reports.ts +820 -0
  228. package/src/findreplace/FindReplace.tsx +242 -0
  229. package/src/findreplace/find-engine.ts +97 -0
  230. package/src/findreplace/scroll-to-match.ts +89 -0
  231. package/src/fonts/tofu-detect.ts +53 -0
  232. package/src/i18n/LanguageContext.tsx +207 -0
  233. package/src/i18n/language-detect.ts +73 -0
  234. package/src/i18n/useTranslation.tsx +74 -0
  235. package/src/index.ts +27 -0
  236. package/src/locales/bn.json +143 -0
  237. package/src/locales/en.json +143 -0
  238. package/src/locales/gu.json +143 -0
  239. package/src/locales/hi.json +143 -0
  240. package/src/locales/kn.json +143 -0
  241. package/src/locales/ml.json +143 -0
  242. package/src/locales/mr.json +143 -0
  243. package/src/locales/or.json +143 -0
  244. package/src/locales/pa.json +143 -0
  245. package/src/locales/si.json +143 -0
  246. package/src/locales/ta.json +143 -0
  247. package/src/locales/te.json +143 -0
  248. package/src/navigator/SceneNavigator.tsx +844 -0
  249. package/src/navigator/StatisticsDialog.tsx +249 -0
  250. package/src/navigator/scene-list.ts +84 -0
  251. package/src/settings/SettingsDialog.tsx +303 -0
  252. package/src/shell/AppBar.tsx +354 -0
  253. package/src/shell/AppShell.tsx +71 -0
  254. package/src/shell/ConfirmDialog.tsx +71 -0
  255. package/src/shell/ElementToolbar.tsx +175 -0
  256. package/src/shell/LanguageStatus.tsx +101 -0
  257. package/src/shell/StatusBar.tsx +135 -0
  258. package/src/shell/SutrataLogo.tsx +89 -0
  259. package/src/shell/Toast.tsx +46 -0
  260. package/src/shell/ToolbarButton.tsx +30 -0
  261. package/src/shell/VersionHistory.tsx +212 -0
  262. package/src/shell/Watermark.tsx +9 -0
  263. package/src/shell/fonts/fonts.css +1133 -0
  264. package/src/shell/icons.tsx +335 -0
  265. package/src/shell/toolbar-actions.ts +59 -0
  266. package/src/source/SourceView.tsx +111 -0
  267. package/src/source/find-highlight-source.ts +57 -0
  268. package/src/source/sutra-lang.ts +121 -0
  269. package/src/spellcheck/dictionaries.ts +21 -0
  270. package/src/spellcheck/hunspell.ts +110 -0
  271. package/src/spellcheck/spellcheck-plugin.ts +83 -0
  272. package/src/styles/StyleDialog.tsx +148 -0
  273. package/src/styles/builtin-styles.ts +139 -0
  274. package/src/styles/css-adapter.ts +76 -0
  275. package/src/styles/docx-adapter.ts +109 -0
  276. package/src/styles/embed-fonts.ts +81 -0
  277. package/src/styles/pagination.ts +27 -0
  278. package/src/styles/print-adapter.ts +288 -0
  279. package/src/styles/registry.ts +20 -0
  280. package/src/styles/screenplay.css +3006 -0
  281. package/src/styles/script-ranges.ts +17 -0
  282. package/src/styles/types.ts +104 -0
  283. package/src/styles/validate.ts +114 -0
  284. package/src/templates/templates.ts +194 -0
  285. package/src/titlepage/ExportDialog.tsx +494 -0
  286. package/src/titlepage/TitlePageDialog.tsx +312 -0
  287. package/src/titlepage/frontmatter-form.ts +280 -0
  288. package/src/titlepage/languages.ts +37 -0
  289. package/src/types.ts +7 -0
  290. package/tests/AppBar.test.tsx +35 -0
  291. package/tests/AppShell.test.tsx +22 -0
  292. package/tests/ElementToolbar.test.tsx +36 -0
  293. package/tests/LanguageStatus.test.tsx +129 -0
  294. package/tests/SelectionMenu.test.tsx +71 -0
  295. package/tests/ToolbarButton.test.tsx +24 -0
  296. package/tests/ai-onboarding.test.ts +102 -0
  297. package/tests/ai-status.test.tsx +72 -0
  298. package/tests/ai-structured.test.ts +94 -0
  299. package/tests/autocomplete/AutocompletePlugin.test.ts +20 -0
  300. package/tests/autocomplete/suggestions.test.ts +106 -0
  301. package/tests/document-context.test.tsx +565 -0
  302. package/tests/docx-importer.test.ts +160 -0
  303. package/tests/editor/character-decoration-plugin.test.ts +101 -0
  304. package/tests/editor/character-extension.test.ts +44 -0
  305. package/tests/editor/grapheme-cursor.test.ts +118 -0
  306. package/tests/editor/ime-plugin.test.ts +72 -0
  307. package/tests/editor/inline-note-bridge.test.ts +32 -0
  308. package/tests/editor/language-class-plugin.test.ts +265 -0
  309. package/tests/editor/title-page.test.ts +124 -0
  310. package/tests/embed-fonts.test.ts +17 -0
  311. package/tests/exporters.test.ts +365 -0
  312. package/tests/findreplace/FindReplace.test.tsx +391 -0
  313. package/tests/findreplace/find-engine.test.ts +86 -0
  314. package/tests/findreplace/scroll-to-match.test.ts +50 -0
  315. package/tests/fonts/tofu-detect.test.ts +122 -0
  316. package/tests/i18n/LanguageContext.test.tsx +146 -0
  317. package/tests/i18n/language-detect.test.ts +54 -0
  318. package/tests/i18n/locale-parity.test.ts +25 -0
  319. package/tests/i18n/useTranslation.test.tsx +45 -0
  320. package/tests/keymap.test.ts +18 -0
  321. package/tests/navigator/SceneNavigator.test.tsx +177 -0
  322. package/tests/navigator/StatisticsDialog.test.tsx +63 -0
  323. package/tests/navigator/scene-list.test.ts +71 -0
  324. package/tests/print-paginator.test.ts +82 -0
  325. package/tests/shell/VersionHistory.test.tsx +129 -0
  326. package/tests/spellcheck/hunspell.test.ts +82 -0
  327. package/tests/spellcheck/spellcheck-plugin.test.ts +56 -0
  328. package/tests/styles.test.ts +315 -0
  329. package/tests/templates/templates.test.ts +83 -0
  330. package/tests/titlepage/TitlePageDialog.test.tsx +90 -0
  331. package/tests/titlepage/apply-title-page.test.ts +61 -0
  332. package/tests/titlepage/frontmatter-form.test.ts +115 -0
  333. package/tests/toolbar-actions.test.ts +93 -0
  334. package/tests/voice-commands.test.ts +58 -0
  335. package/tsconfig.json +17 -0
  336. package/vitest.config.ts +11 -0
  337. package/vitest.setup.ts +65 -0
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect, useRef } from 'react';
3
+ import { useLanguage } from '../i18n/LanguageContext';
4
+ import { useDocument } from '../context/DocumentContext';
5
+ import { getEditorView } from '../editor/editor-bus';
6
+ const LANG_NAMES = {
7
+ en: 'English',
8
+ hi: 'Hindi (Devanagari)',
9
+ ta: 'Tamil',
10
+ te: 'Telugu',
11
+ kn: 'Kannada',
12
+ ml: 'Malayalam',
13
+ bn: 'Bengali',
14
+ gu: 'Gujarati',
15
+ pa: 'Gurmukhi',
16
+ or: 'Odia',
17
+ si: 'Sinhala',
18
+ };
19
+ export function LanguageStatus() {
20
+ const { currentLanguage } = useLanguage();
21
+ const { text, setText } = useDocument();
22
+ const [menuOpen, setMenuOpen] = useState(false);
23
+ const menuRef = useRef(null);
24
+ const langName = LANG_NAMES[currentLanguage] ?? currentLanguage;
25
+ useEffect(() => {
26
+ if (!menuOpen)
27
+ return;
28
+ const handleClickOutside = (e) => {
29
+ if (menuRef.current && !menuRef.current.contains(e.target)) {
30
+ setMenuOpen(false);
31
+ }
32
+ };
33
+ const handleKeyDown = (e) => {
34
+ if (e.key === 'Escape')
35
+ setMenuOpen(false);
36
+ };
37
+ document.addEventListener('mousedown', handleClickOutside);
38
+ document.addEventListener('keydown', handleKeyDown);
39
+ return () => {
40
+ document.removeEventListener('mousedown', handleClickOutside);
41
+ document.removeEventListener('keydown', handleKeyDown);
42
+ };
43
+ }, [menuOpen]);
44
+ const handleSelectLanguage = (code) => {
45
+ const view = getEditorView();
46
+ if (view) {
47
+ const { state, dispatch } = view;
48
+ const { from, to } = state.selection;
49
+ const tagText = `{lang=${code}}`;
50
+ dispatch(state.tr.insertText(tagText, from, to));
51
+ view.focus();
52
+ }
53
+ else {
54
+ setText(text + `\n{lang=${code}}`);
55
+ }
56
+ setMenuOpen(false);
57
+ };
58
+ return (_jsxs("div", { className: "cs-lang-status", ref: menuRef, children: [_jsxs("button", { type: "button", className: "cs-lang-status-btn cs-lang-pill", title: `Script language at caret: ${langName} (${currentLanguage.toUpperCase()})`, "aria-label": `Script language: ${langName}`, "aria-haspopup": "menu", "aria-expanded": menuOpen, onClick: () => setMenuOpen(!menuOpen), children: [_jsx("span", { className: "cs-lang-pill-script", children: "\u0905/A" }), _jsx("span", { className: "cs-lang-code", children: currentLanguage.toUpperCase() })] }), menuOpen && (_jsx("div", { className: "cs-lang-menu", role: "menu", "aria-label": "Script languages", children: Object.entries(LANG_NAMES).map(([code, name]) => {
59
+ const isActive = currentLanguage === code;
60
+ return (_jsxs("button", { type: "button", role: "menuitem", className: `cs-lang-option${isActive ? ' cs-lang-active' : ''}`, onClick: (e) => {
61
+ e.stopPropagation();
62
+ handleSelectLanguage(code);
63
+ }, children: [_jsx("span", { children: name }), _jsx("span", { className: "cs-lang-code", style: { fontSize: '10px', opacity: 0.7 }, children: code.toUpperCase() })] }, code));
64
+ }) }))] }));
65
+ }
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare function StatusBar(): React.JSX.Element;
@@ -0,0 +1,54 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useMemo, useState, useEffect } from 'react';
3
+ import { useDocument } from '../context/DocumentContext';
4
+ import { LanguageStatus } from './LanguageStatus';
5
+ import { buildSceneList } from '../navigator/scene-list';
6
+ import { StatisticsDialog } from '../navigator/StatisticsDialog';
7
+ import { VersionHistory } from './VersionHistory';
8
+ import { StatsIcon, HistoryIcon } from './icons';
9
+ import { subscribeToAICalls, formatActiveCalls } from '../ai/ai-client';
10
+ import { useTranslation } from '../i18n/useTranslation';
11
+ function AIStatusBarStatus() {
12
+ const [activeCalls, setActiveCalls] = useState([]);
13
+ useEffect(() => {
14
+ return subscribeToAICalls(setActiveCalls);
15
+ }, []);
16
+ if (activeCalls.length === 0)
17
+ return null;
18
+ return (_jsxs("div", { className: "cs-ai-status-indicator", style: {
19
+ display: 'inline-flex',
20
+ alignItems: 'center',
21
+ gap: '6px',
22
+ color: 'var(--cs-ui-accent, #c4760a)',
23
+ fontWeight: 600,
24
+ fontSize: '11px',
25
+ marginRight: '8px',
26
+ }, children: [_jsx("span", { className: "cs-spinner", style: { width: '10px', height: '10px', borderWidth: '1.5px' } }), _jsx("span", { children: formatActiveCalls(activeCalls) })] }));
27
+ }
28
+ export function StatusBar() {
29
+ const { text, isDirty, lastSaveTarget, filePath, versions, versionHistoryVisible, setVersionHistoryVisible, restoreVersion, clearVersionHistory } = useDocument();
30
+ const { t } = useTranslation();
31
+ const [statsOpen, setStatsOpen] = useState(false);
32
+ // VS Code-style: a local autosave backs the content up but never counts as
33
+ // "saved" in the main label — only a real write to the file (saveFile/
34
+ // saveFileAs, which clears isDirty) does. While still dirty, the tooltip
35
+ // says whether that local backup has caught up with the latest edits yet.
36
+ const saveLabel = isDirty
37
+ ? t('statusbar.unsavedChanges')
38
+ : lastSaveTarget === 'file' ? t('statusbar.savedToFile')
39
+ : t('statusbar.allChangesSaved');
40
+ const saveTooltip = isDirty
41
+ ? lastSaveTarget === 'local' ? t('statusbar.savedLocallyTooltip') : undefined
42
+ : lastSaveTarget === 'file' ? t('statusbar.savedToFileTooltip')
43
+ : undefined;
44
+ const scenes = useMemo(() => buildSceneList(text), [text]);
45
+ const { wordCount, pageEstimate } = useMemo(() => {
46
+ const trimmed = text.trim();
47
+ const words = trimmed ? trimmed.split(/\s+/).length : 0;
48
+ // Standard screenplay rule: ~54 lines or ~200-250 words per page
49
+ const lines = text.split('\n').length;
50
+ const estPages = Math.max(1, Math.round(lines / 54));
51
+ return { wordCount: words, pageEstimate: estPages };
52
+ }, [text]);
53
+ return (_jsxs(_Fragment, { children: [_jsxs("footer", { className: "cs-status-bar", role: "contentinfo", "aria-label": "Status bar", children: [_jsxs("div", { className: "cs-sb-left", children: [_jsxs("span", { className: "cs-sb-metric cs-sb-metric-scenes", title: t('statusbar.scenesTooltip'), children: [_jsx("strong", { children: scenes.length }), " ", _jsx("span", { className: "cs-sb-metric-label", children: scenes.length === 1 ? t('statusbar.scene') : t('statusbar.scenes') })] }), _jsx("span", { className: "cs-sb-sep", children: "\u2022" }), _jsxs("span", { className: "cs-sb-metric cs-sb-metric-pages", title: t('statusbar.pagesTooltip'), children: [_jsxs("strong", { children: ["~", pageEstimate] }), " ", _jsx("span", { className: "cs-sb-metric-label", children: pageEstimate === 1 ? t('statusbar.page') : t('statusbar.pages') })] }), _jsx("span", { className: "cs-sb-sep cs-sb-words-sep", children: "\u2022" }), _jsxs("span", { className: "cs-sb-metric cs-sb-metric-words", title: t('statusbar.wordsTooltip'), children: [_jsx("strong", { children: wordCount.toLocaleString() }), " ", _jsx("span", { className: "cs-sb-metric-label", children: t('statusbar.words') })] })] }), _jsx("div", { className: "cs-sb-center", children: _jsxs("div", { className: "cs-sb-save", role: "status", "aria-live": "polite", title: saveTooltip, children: [_jsx("span", { className: `cs-sb-dot ${isDirty ? 'cs-sb-dot-dirty' : 'cs-sb-dot-clean'}` }), _jsx("span", { className: isDirty ? 'cs-sb-save-dirty' : 'cs-sb-save-clean', children: saveLabel })] }) }), _jsxs("div", { className: "cs-sb-right", children: [_jsx(AIStatusBarStatus, {}), filePath && versions.length > 0 && (_jsxs("button", { type: "button", className: "cs-nav-action-btn", onClick: () => setVersionHistoryVisible(true), title: `${versions.length} version${versions.length === 1 ? '' : 's'} saved`, style: { fontSize: '11px', gap: '4px', padding: '2px 6px' }, children: [_jsx(HistoryIcon, { size: 13 }), _jsx("span", { children: versions.length })] })), _jsxs("button", { type: "button", className: "cs-nav-action-btn", onClick: () => setStatsOpen(true), title: t('statusbar.statsTooltip'), style: { fontSize: '11px', gap: '4px', padding: '2px 6px' }, children: [_jsx(StatsIcon, { size: 13 }), _jsx("span", { children: t('statusbar.statsButton') })] }), _jsx(LanguageStatus, {})] })] }), statsOpen && _jsx(StatisticsDialog, { onClose: () => setStatsOpen(false) }), filePath && (_jsx(VersionHistory, { versions: versions, filePath: filePath, onRestore: restoreVersion, onClearAll: clearVersionHistory, visible: versionHistoryVisible, onClose: () => setVersionHistoryVisible(false) }))] }));
54
+ }
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ interface LogoProps {
3
+ size?: number;
4
+ className?: string;
5
+ showText?: boolean;
6
+ }
7
+ export declare function SutrataLogo({ size, className, showText }: LogoProps): React.JSX.Element;
8
+ export {};
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const MONOGRAM_ASPECT = 231.65818 / 324.60373;
3
+ export function SutrataLogo({ size = 20, className = '', showText = true }) {
4
+ const height = size;
5
+ const width = size * MONOGRAM_ASPECT;
6
+ return (_jsxs("div", { className: `cs-brand-mark ${className}`, style: { display: 'inline-flex', alignItems: 'center', gap: '7px', userSelect: 'none' }, children: [_jsx("svg", { width: width, height: height, viewBox: "0 0 231.65818 324.60373", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", style: { flexShrink: 0 }, children: _jsxs("g", { transform: "translate(-3.0466903,-3.069361)", children: [_jsxs("g", { children: [_jsx("path", { fill: "#502308", d: "M 76.35291,222.53041 C 75.478969,209.22098 71.352034,194.29907 56.664655,177.24787 35.352192,152.22995 46.850499,139.85601 62.978003,130.13046 L 3.6899176,150.4351 c 5.0786411,20.05339 13.9650544,36.08746 28.6678214,45.98205 16.601069,11.28577 30.572578,19.06546 43.995171,26.11326 z" }), _jsx("path", { fill: "#92400e", d: "m 213.6921,3.069361 c 0,0 0.96049,32.353598 -0.14192,43.494212 -1.10241,11.140614 -14.06146,22.120287 -23.28179,26.493068 -26.78003,12.700542 -124.035721,55.394599 -124.035721,55.394599 0,0 -7.314493,3.8005 -14.852175,9.23243 -7.537682,5.43193 -23.670324,18.71663 -28.098707,33.71845 -1.670439,5.65887 -2.408461,14.04935 -2.408461,14.04935 C 8.2528446,173.99227 -4.2995876,149.42142 8.2289074,120.92479 18.129451,103.32842 31.24605,87.051456 55.796006,75.465101 101.11959,52.013746 150.99666,33.115884 198.69801,12.042303 Z" }), _jsxs("g", { children: [_jsx("path", { fill: "#fbbf24", d: "m 157.01648,44.42498 c 14.17698,-5.71484 11.14517,-6.35429 11.1893,10.23596 -0.40601,13.28313 2.27097,11.17087 -9.33278,16.05641 -13.29184,4.92069 -12.50077,7.73152 -12.14266,-9.03173 -0.29088,-15.61229 -1.75968,-11.39786 10.28614,-17.26064 z" }), _jsx("path", { fill: "#fbbf24", d: "m 118.47741,61.789741 c 14.17699,-5.71484 11.14518,-6.35429 11.18931,10.23596 -0.40601,13.28313 2.27097,11.17087 -9.33279,16.05641 -13.29183,4.92069 -12.50076,7.73152 -12.14265,-9.03173 -0.29089,-15.61229 -1.75968,-11.39786 10.28613,-17.26064 z" }), _jsx("path", { fill: "#fbbf24", d: "m 80.42697,79.119631 c 14.176988,-5.71484 11.145175,-6.35429 11.189307,10.23596 -0.406014,13.283129 2.27097,11.170869 -9.332786,16.056409 -13.291838,4.92069 -12.500765,7.73152 -12.142656,-9.031729 -0.290884,-15.61229 -1.759682,-11.39786 10.286135,-17.26064 z" })] })] }), _jsxs("g", { transform: "rotate(180,118.87578,165.37123)", children: [_jsx("path", { fill: "#502308", d: "M 76.35291,222.53041 C 75.478969,209.22098 71.352034,194.29907 56.664655,177.24787 35.352192,152.22995 46.850499,139.85601 62.978003,130.13046 L 3.6899176,150.4351 c 5.0786411,20.05339 13.9650544,36.08746 28.6678214,45.98205 16.601069,11.28577 30.572578,19.06546 43.995171,26.11326 z" }), _jsx("path", { fill: "#92400e", d: "m 213.6921,3.069361 c 0,0 0.96049,32.353598 -0.14192,43.494212 -1.10241,11.140614 -14.06146,22.120287 -23.28179,26.493068 -26.78003,12.700542 -124.035721,55.394599 -124.035721,55.394599 0,0 -7.314493,3.8005 -14.852175,9.23243 -7.537682,5.43193 -23.670324,18.71663 -28.098707,33.71845 -1.670439,5.65887 -2.408461,14.04935 -2.408461,14.04935 C 8.2528446,173.99227 -4.2995876,149.42142 8.2289074,120.92479 18.129451,103.32842 31.24605,87.051456 55.796006,75.465101 101.11959,52.013746 150.99666,33.115884 198.69801,12.042303 Z" }), _jsxs("g", { children: [_jsx("path", { fill: "#fbbf24", d: "m 157.01648,44.42498 c 14.17698,-5.71484 11.14517,-6.35429 11.1893,10.23596 -0.40601,13.28313 2.27097,11.17087 -9.33278,16.05641 -13.29184,4.92069 -12.50077,7.73152 -12.14266,-9.03173 -0.29088,-15.61229 -1.75968,-11.39786 10.28614,-17.26064 z" }), _jsx("path", { fill: "#fbbf24", d: "m 118.47741,61.789741 c 14.17699,-5.71484 11.14518,-6.35429 11.18931,10.23596 -0.40601,13.28313 2.27097,11.17087 -9.33279,16.05641 -13.29183,4.92069 -12.50076,7.73152 -12.14265,-9.03173 -0.29089,-15.61229 -1.75968,-11.39786 10.28613,-17.26064 z" }), _jsx("path", { fill: "#fbbf24", d: "m 80.42697,79.119631 c 14.176988,-5.71484 11.145175,-6.35429 11.189307,10.23596 -0.406014,13.283129 2.27097,11.170869 -9.332786,16.056409 -13.291838,4.92069 -12.500765,7.73152 -12.142656,-9.031729 -0.290884,-15.61229 -1.759682,-11.39786 10.286135,-17.26064 z" })] })] }), _jsxs("g", { transform: "matrix(1.1983554,-0.06280315,0.06280315,1.1983554,-34.773977,-29.239318)", children: [_jsx("path", { fill: "#fbbf24", d: "m 90.317275,164.77885 48.369915,-17.86274 c -6.75724,-6.27184 -19.73649,-10.33577 -32.1128,-4.41552 -11.797753,5.74748 -14.462218,13.89845 -16.257115,22.27826 z" }), _jsx("path", { fill: "#fbbf24", d: "M 148.18495,171.26956 99.815045,189.1323 c 6.757235,6.27184 19.736485,10.33577 32.112795,4.41552 11.79775,-5.74748 14.46221,-13.89845 16.25711,-22.27826 z" }), _jsx("path", { fill: "#fbbf24", d: "m 90.417628,169.79648 51.882262,-19.36804 c 3.81102,4.8999 5.68801,10.3205 6.02115,16.15676 l -52.032789,19.06698 c -3.269689,-4.15996 -5.408353,-9.28938 -5.870623,-15.8557 z" })] })] }) }), showText && (_jsx("span", { className: "cs-brand-text", style: { fontWeight: 700, fontSize: '11px', letterSpacing: '1.2px', textTransform: 'uppercase', color: 'var(--cs-ui-accent-badge, #d97706)' }, children: "Sutrata" }))] }));
7
+ }
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ export interface ToastItem {
3
+ id: string;
4
+ message: string;
5
+ type?: 'info' | 'success' | 'warn' | 'error';
6
+ }
7
+ interface ToastContainerProps {
8
+ toasts: ToastItem[];
9
+ onDismiss: (id: string) => void;
10
+ }
11
+ export declare function ToastContainer({ toasts, onDismiss }: ToastContainerProps): React.JSX.Element;
12
+ export {};
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ export function ToastContainer({ toasts, onDismiss }) {
4
+ return (_jsx("div", { className: "cs-toast-container", "aria-live": "polite", "aria-atomic": "true", children: toasts.map((toast) => (_jsx(ToastMessage, { toast: toast, onDismiss: onDismiss }, toast.id))) }));
5
+ }
6
+ function ToastMessage({ toast, onDismiss }) {
7
+ useEffect(() => {
8
+ const timer = setTimeout(() => {
9
+ onDismiss(toast.id);
10
+ }, 3500);
11
+ return () => clearTimeout(timer);
12
+ }, [toast.id, onDismiss]);
13
+ const typeClass = toast.type === 'success'
14
+ ? 'cs-toast-success'
15
+ : toast.type === 'error'
16
+ ? 'cs-toast-error'
17
+ : toast.type === 'warn'
18
+ ? 'cs-toast-warn'
19
+ : 'cs-toast-info';
20
+ return (_jsx("div", { className: `cs-toast ${typeClass}`, role: "status", children: _jsx("span", { children: toast.message }) }));
21
+ }
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ interface ToolbarButtonProps {
3
+ label: string;
4
+ sigil?: string;
5
+ shortcut?: string;
6
+ active?: boolean;
7
+ onClick: () => void;
8
+ children: React.ReactNode;
9
+ }
10
+ export declare function ToolbarButton({ label, sigil, shortcut, active, onClick, children }: ToolbarButtonProps): React.JSX.Element;
11
+ export {};
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function ToolbarButton({ label, sigil, shortcut, active, onClick, children }) {
3
+ return (_jsxs("button", { type: "button", "aria-label": label, className: `cs-tb-btn${active ? ' cs-tb-active' : ''}`, onClick: onClick, children: [_jsx("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%' }, children: children }), _jsxs("span", { className: "cs-tb-tip", role: "tooltip", children: [_jsx("span", { children: label }), sigil ? _jsx("span", { className: "cs-tb-sigil", children: sigil }) : null, shortcut ? _jsx("span", { className: "cs-tb-key", children: shortcut }) : null] })] }));
4
+ }
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { VersionEntry } from '../types';
3
+ interface VersionHistoryProps {
4
+ versions: VersionEntry[];
5
+ filePath: string | null;
6
+ onRestore: (entry: VersionEntry) => void;
7
+ onClearAll: () => Promise<void>;
8
+ visible: boolean;
9
+ onClose: () => void;
10
+ }
11
+ export declare function VersionHistory({ versions, filePath, onRestore, onClearAll, visible, onClose }: VersionHistoryProps): React.JSX.Element | null;
12
+ export {};
@@ -0,0 +1,89 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useLayoutEffect, useMemo, useRef, useState } from 'react';
3
+ import { diffWordsWithSpace } from 'diff';
4
+ // Word-level diff over the full text (not line-bucketed): if only one word in
5
+ // a sentence changed, only that word is marked added/removed — the rest of
6
+ // the sentence comes back as an unchanged, unstyled Change chunk. Whitespace
7
+ // (including newlines) is treated as part of the diff so line breaks survive.
8
+ function computeDiff(oldText, newText) {
9
+ return diffWordsWithSpace(oldText, newText);
10
+ }
11
+ // Two markers within this many pixels of each other collapse into one, so a
12
+ // tight run of word edits doesn't paint a solid wall of ticks.
13
+ const CLUSTER_PX = 10;
14
+ function formatTimestamp(ts) {
15
+ return new Date(ts).toLocaleString(undefined, {
16
+ month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit',
17
+ });
18
+ }
19
+ export function VersionHistory({ versions, filePath, onRestore, onClearAll, visible, onClose }) {
20
+ const [selectedId, setSelectedId] = useState(null);
21
+ const diffScrollRef = useRef(null);
22
+ // Maps a diff-part index (only added/removed parts) to its rendered <span>,
23
+ // so marker positions come from real layout instead of a text-based estimate —
24
+ // screenplay format has wildly uneven character density per line (short
25
+ // character cues and blank lines vs. long action paragraphs), which threw
26
+ // off an earlier character-offset heuristic by a page or more.
27
+ const spanRefMap = useRef(new Map());
28
+ const [markers, setMarkers] = useState([]);
29
+ const currentVersion = versions[0] ?? null;
30
+ const selectedVersion = useMemo(() => versions.find(v => v.id === selectedId) ?? null, [versions, selectedId]);
31
+ const diff = useMemo(() => {
32
+ if (!selectedVersion || !currentVersion || selectedVersion.id === currentVersion.id)
33
+ return null;
34
+ return computeDiff(selectedVersion.content, currentVersion.content);
35
+ }, [selectedVersion, currentVersion]);
36
+ useLayoutEffect(() => {
37
+ const container = diffScrollRef.current;
38
+ if (!container || !diff) {
39
+ setMarkers([]);
40
+ return;
41
+ }
42
+ const raw = [];
43
+ diff.forEach((part, i) => {
44
+ if (!part.added && !part.removed)
45
+ return;
46
+ const span = spanRefMap.current.get(i);
47
+ if (!span)
48
+ return;
49
+ raw.push({ type: part.added ? 'added' : 'removed', top: span.offsetTop });
50
+ });
51
+ raw.sort((a, b) => a.top - b.top);
52
+ const scrollHeight = container.scrollHeight || 1;
53
+ const clustered = [];
54
+ let lastTop = -Infinity;
55
+ let lastType = null;
56
+ for (const m of raw) {
57
+ if (lastType === m.type && m.top - lastTop < CLUSTER_PX)
58
+ continue;
59
+ clustered.push({ type: m.type, position: m.top / scrollHeight });
60
+ lastTop = m.top;
61
+ lastType = m.type;
62
+ }
63
+ setMarkers(clustered);
64
+ }, [diff]);
65
+ const scrollToMarker = (position) => {
66
+ const el = diffScrollRef.current;
67
+ if (!el)
68
+ return;
69
+ const target = Math.max(0, position * el.scrollHeight - el.clientHeight / 2);
70
+ if (typeof el.scrollTo === 'function')
71
+ el.scrollTo({ top: target, behavior: 'smooth' });
72
+ else
73
+ el.scrollTop = target;
74
+ };
75
+ if (!visible || !filePath)
76
+ return null;
77
+ return (_jsx("div", { className: "cs-dialog-overlay", role: "presentation", onClick: e => { if (e.target === e.currentTarget)
78
+ onClose(); }, children: _jsxs("div", { className: "cs-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "cs-version-dialog-title", style: { maxWidth: '620px', width: '92%', maxHeight: '80vh', display: 'flex', flexDirection: 'column' }, children: [_jsxs("div", { className: "cs-panel-header", children: [_jsx("span", { id: "cs-version-dialog-title", className: "cs-panel-title", children: "Version History" }), _jsx("button", { className: "cs-panel-close", onClick: onClose, "aria-label": "Close", children: "\u00D7" })] }), _jsxs("div", { className: "cs-version-body", children: [_jsx("div", { className: "cs-version-list", children: versions.length === 0 ? (_jsx("div", { className: "cs-version-empty", children: "No versions saved yet" })) : (versions.map((v, idx) => (_jsxs("button", { type: "button", className: `cs-version-list-item${selectedId === v.id ? ' cs-version-list-item-active' : ''}`, onClick: () => setSelectedId(v.id), children: [_jsx("div", { className: "cs-version-list-item-label", children: idx === 0 ? 'Current' : formatTimestamp(v.timestamp) }), idx !== 0 && _jsx("div", { className: "cs-version-list-item-date", children: formatTimestamp(v.timestamp) })] }, v.id)))) }), _jsxs("div", { className: "cs-version-diff-wrap", children: [_jsx("div", { className: "cs-version-diff", ref: diffScrollRef, children: !selectedVersion ? (_jsx("div", { className: "cs-version-empty", children: "Select a version to compare against the current document" })) : selectedVersion.id === currentVersion?.id ? (_jsx("div", { className: "cs-version-empty", children: "This is the current version" })) : diff ? (diff.every(part => !part.added && !part.removed) ? (_jsx("div", { className: "cs-version-empty", children: "No differences from the current version" })) : (_jsx("div", { className: "cs-version-diff-content", children: diff.map((part, i) => {
79
+ const isChange = part.added || part.removed;
80
+ return (_jsx("span", { ref: isChange ? (el) => {
81
+ if (el)
82
+ spanRefMap.current.set(i, el);
83
+ else
84
+ spanRefMap.current.delete(i);
85
+ } : undefined, className: part.added ? 'cs-version-diff-added'
86
+ : part.removed ? 'cs-version-diff-removed'
87
+ : undefined, children: part.value }, i));
88
+ }) }))) : null }), _jsx("div", { className: "cs-version-diff-minimap", "aria-hidden": "true", children: markers.map((m, i) => (_jsx("button", { type: "button", className: `cs-version-diff-marker cs-version-diff-marker-${m.type}`, style: { top: `${m.position * 100}%` }, title: m.type === 'added' ? 'Jump to added text' : 'Jump to removed text', onClick: () => scrollToMarker(m.position) }, i))) })] })] }), _jsxs("div", { className: "cs-version-footer", children: [_jsx("button", { type: "button", className: "cs-confirm-btn-cancel cs-version-clear-btn", onClick: () => void onClearAll(), disabled: versions.length === 0, children: "Delete Version History" }), _jsxs("div", { style: { display: 'flex', gap: '10px' }, children: [_jsx("button", { type: "button", className: "cs-confirm-btn-cancel", onClick: onClose, children: "Close" }), selectedVersion && selectedVersion.id !== currentVersion?.id && (_jsx("button", { type: "button", className: "cs-confirm-btn-primary", onClick: () => onRestore(selectedVersion), children: "Restore This Version" }))] })] })] }) }));
89
+ }
@@ -0,0 +1,3 @@
1
+ /** Renders the document's frontmatter `watermark:` text.
2
+ * Hidden in the screen editor UI, visible only in print output. */
3
+ export declare function Watermark(): import("react").JSX.Element | null;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useDocument } from '../context/DocumentContext';
3
+ /** Renders the document's frontmatter `watermark:` text.
4
+ * Hidden in the screen editor UI, visible only in print output. */
5
+ export function Watermark() {
6
+ const { watermarkText } = useDocument();
7
+ if (!watermarkText)
8
+ return null;
9
+ return _jsx("div", { className: "cs-watermark", "aria-hidden": "true", children: watermarkText });
10
+ }