@rightkit/document-workspace 0.0.0-stage → 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 (262) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +51 -2
  5. package/dist/app/App.d.ts +1 -0
  6. package/dist/app/App.js +6 -0
  7. package/dist/app/AppDialogs.d.ts +52 -0
  8. package/dist/app/AppDialogs.js +23 -0
  9. package/dist/app/AppDialogsHost.d.ts +31 -0
  10. package/dist/app/AppDialogsHost.js +30 -0
  11. package/dist/app/AppLifecycle.d.ts +19 -0
  12. package/dist/app/AppLifecycle.js +87 -0
  13. package/dist/app/AppProvider.d.ts +317 -0
  14. package/dist/app/AppProvider.js +217 -0
  15. package/dist/app/AppRoot.d.ts +8 -0
  16. package/dist/app/AppRoot.js +159 -0
  17. package/dist/app/AppShell.d.ts +2 -0
  18. package/dist/app/AppShell.js +81 -0
  19. package/dist/app/CommandPalette.d.ts +13 -0
  20. package/dist/app/CommandPalette.js +47 -0
  21. package/dist/app/DocActionBar.d.ts +36 -0
  22. package/dist/app/DocActionBar.js +300 -0
  23. package/dist/app/DocumentContextMenu.d.ts +29 -0
  24. package/dist/app/DocumentContextMenu.js +122 -0
  25. package/dist/app/DocumentPane.d.ts +52 -0
  26. package/dist/app/DocumentPane.js +30 -0
  27. package/dist/app/DocumentRouterTable.d.ts +58 -0
  28. package/dist/app/DocumentRouterTable.js +143 -0
  29. package/dist/app/ErrorBoundary.d.ts +12 -0
  30. package/dist/app/ErrorBoundary.js +16 -0
  31. package/dist/app/FindBar.d.ts +12 -0
  32. package/dist/app/FindBar.js +199 -0
  33. package/dist/app/LiveTitle.d.ts +14 -0
  34. package/dist/app/LiveTitle.js +14 -0
  35. package/dist/app/OpeningProgress.d.ts +13 -0
  36. package/dist/app/OpeningProgress.js +21 -0
  37. package/dist/app/PrintPreviewWindow.d.ts +2 -0
  38. package/dist/app/PrintPreviewWindow.js +57 -0
  39. package/dist/app/ShortcutHelp.d.ts +3 -0
  40. package/dist/app/ShortcutHelp.js +99 -0
  41. package/dist/app/Sidebar.d.ts +36 -0
  42. package/dist/app/Sidebar.js +121 -0
  43. package/dist/app/ToastViewport.d.ts +1 -0
  44. package/dist/app/ToastViewport.js +31 -0
  45. package/dist/app/Toolbar.d.ts +26 -0
  46. package/dist/app/Toolbar.js +63 -0
  47. package/dist/app/activeFormatSavers.d.ts +7 -0
  48. package/dist/app/activeFormatSavers.js +4 -0
  49. package/dist/app/clipboardPaths.d.ts +1 -0
  50. package/dist/app/clipboardPaths.js +31 -0
  51. package/dist/app/documentDrafts.d.ts +17 -0
  52. package/dist/app/documentDrafts.js +104 -0
  53. package/dist/app/draftResolution.d.ts +5 -0
  54. package/dist/app/draftResolution.js +25 -0
  55. package/dist/app/markdownPaletteActions.d.ts +8 -0
  56. package/dist/app/markdownPaletteActions.js +107 -0
  57. package/dist/app/resourceCensusDev.d.ts +41 -0
  58. package/dist/app/resourceCensusDev.js +518 -0
  59. package/dist/app/setupRecovery.d.ts +34 -0
  60. package/dist/app/setupRecovery.js +70 -0
  61. package/dist/app/shell/DocStatsPill.d.ts +18 -0
  62. package/dist/app/shell/DocStatsPill.js +32 -0
  63. package/dist/app/shell/DocumentTools.d.ts +9 -0
  64. package/dist/app/shell/DocumentTools.js +73 -0
  65. package/dist/app/shell/InfoInspector.d.ts +9 -0
  66. package/dist/app/shell/InfoInspector.js +67 -0
  67. package/dist/app/shell/StartPage.d.ts +9 -0
  68. package/dist/app/shell/StartPage.js +49 -0
  69. package/dist/app/shell/readEdit.d.ts +6 -0
  70. package/dist/app/shell/readEdit.js +6 -0
  71. package/dist/app/sidebar/SidebarDocumentMenu.d.ts +20 -0
  72. package/dist/app/sidebar/SidebarDocumentMenu.js +56 -0
  73. package/dist/app/sidebar/SidebarExpandedPanel.d.ts +9 -0
  74. package/dist/app/sidebar/SidebarExpandedPanel.js +78 -0
  75. package/dist/app/sidebar/SidebarIcons.d.ts +3 -0
  76. package/dist/app/sidebar/SidebarIcons.js +18 -0
  77. package/dist/app/sidebar/SidebarMenus.d.ts +19 -0
  78. package/dist/app/sidebar/SidebarMenus.js +64 -0
  79. package/dist/app/sidebar/SidebarPathUtils.d.ts +10 -0
  80. package/dist/app/sidebar/SidebarPathUtils.js +55 -0
  81. package/dist/app/sidebar/SidebarPrimitives.d.ts +12 -0
  82. package/dist/app/sidebar/SidebarPrimitives.js +45 -0
  83. package/dist/app/sidebar/SidebarRail.d.ts +5 -0
  84. package/dist/app/sidebar/SidebarRail.js +37 -0
  85. package/dist/app/sidebar/explorer/ExplorerRowMenu.d.ts +21 -0
  86. package/dist/app/sidebar/explorer/ExplorerRowMenu.js +37 -0
  87. package/dist/app/sidebar/explorer/ExplorerSections.d.ts +16 -0
  88. package/dist/app/sidebar/explorer/ExplorerSections.js +259 -0
  89. package/dist/app/sidebar/explorer/ExplorerTree.d.ts +46 -0
  90. package/dist/app/sidebar/explorer/ExplorerTree.js +387 -0
  91. package/dist/app/sidebar/explorer/explorerState.d.ts +37 -0
  92. package/dist/app/sidebar/explorer/explorerState.js +135 -0
  93. package/dist/app/tabMountPolicy.d.ts +45 -0
  94. package/dist/app/tabMountPolicy.js +104 -0
  95. package/dist/app/tabWarmOrder.d.ts +7 -0
  96. package/dist/app/tabWarmOrder.js +48 -0
  97. package/dist/app/tabs/TabFuseCurves.d.ts +3 -0
  98. package/dist/app/tabs/TabFuseCurves.js +15 -0
  99. package/dist/app/tabs/TabOverview.d.ts +24 -0
  100. package/dist/app/tabs/TabOverview.js +121 -0
  101. package/dist/app/tabs/TabStrip.d.ts +42 -0
  102. package/dist/app/tabs/TabStrip.js +380 -0
  103. package/dist/app/tabs/tabIds.d.ts +5 -0
  104. package/dist/app/tabs/tabIds.js +7 -0
  105. package/dist/app/tabs/useTabDirty.d.ts +3 -0
  106. package/dist/app/tabs/useTabDirty.js +11 -0
  107. package/dist/app/useAppChromeState.d.ts +21 -0
  108. package/dist/app/useAppChromeState.js +48 -0
  109. package/dist/app/useAppCommands.d.ts +66 -0
  110. package/dist/app/useAppCommands.js +71 -0
  111. package/dist/app/useAppDocumentCore.d.ts +210 -0
  112. package/dist/app/useAppDocumentCore.js +40 -0
  113. package/dist/app/useAppEffects.d.ts +18 -0
  114. package/dist/app/useAppEffects.js +52 -0
  115. package/dist/app/useAppPaneSearch.d.ts +37 -0
  116. package/dist/app/useAppPaneSearch.js +74 -0
  117. package/dist/app/useAppShellSetup.d.ts +40 -0
  118. package/dist/app/useAppShellSetup.js +52 -0
  119. package/dist/app/useAppSlots.d.ts +28 -0
  120. package/dist/app/useAppSlots.js +40 -0
  121. package/dist/app/useAppTabChrome.d.ts +51 -0
  122. package/dist/app/useAppTabChrome.js +66 -0
  123. package/dist/app/useAutoSave.d.ts +34 -0
  124. package/dist/app/useAutoSave.js +116 -0
  125. package/dist/app/useCloseAll.d.ts +52 -0
  126. package/dist/app/useCloseAll.js +295 -0
  127. package/dist/app/useClosedTabEviction.d.ts +10 -0
  128. package/dist/app/useClosedTabEviction.js +38 -0
  129. package/dist/app/useCommandPalette.d.ts +44 -0
  130. package/dist/app/useCommandPalette.js +254 -0
  131. package/dist/app/useCrossDocSearch.d.ts +7 -0
  132. package/dist/app/useCrossDocSearch.js +94 -0
  133. package/dist/app/useDistractionFree.d.ts +21 -0
  134. package/dist/app/useDistractionFree.js +73 -0
  135. package/dist/app/useDocumentCreation.d.ts +18 -0
  136. package/dist/app/useDocumentCreation.js +63 -0
  137. package/dist/app/useDocumentDirty.d.ts +31 -0
  138. package/dist/app/useDocumentDirty.js +46 -0
  139. package/dist/app/useDocumentLoader.d.ts +55 -0
  140. package/dist/app/useDocumentLoader.js +267 -0
  141. package/dist/app/useDocumentOutputActions.d.ts +6 -0
  142. package/dist/app/useDocumentOutputActions.js +45 -0
  143. package/dist/app/useDocumentRuntimeEffects.d.ts +36 -0
  144. package/dist/app/useDocumentRuntimeEffects.js +458 -0
  145. package/dist/app/useDocumentSaver.d.ts +58 -0
  146. package/dist/app/useDocumentSaver.js +511 -0
  147. package/dist/app/useDocumentTabs.d.ts +41 -0
  148. package/dist/app/useDocumentTabs.js +207 -0
  149. package/dist/app/useDocumentWatcher.d.ts +83 -0
  150. package/dist/app/useDocumentWatcher.js +393 -0
  151. package/dist/app/useDocumentZoom.d.ts +24 -0
  152. package/dist/app/useDocumentZoom.js +104 -0
  153. package/dist/app/useDocuments.d.ts +169 -0
  154. package/dist/app/useDocuments.js +455 -0
  155. package/dist/app/useDraftConfirmGate.d.ts +27 -0
  156. package/dist/app/useDraftConfirmGate.js +47 -0
  157. package/dist/app/useFileDragOverlay.d.ts +12 -0
  158. package/dist/app/useFileDragOverlay.js +49 -0
  159. package/dist/app/useFormatApis.d.ts +13 -0
  160. package/dist/app/useFormatApis.js +62 -0
  161. package/dist/app/useFormatDirtyState.d.ts +29 -0
  162. package/dist/app/useFormatDirtyState.js +81 -0
  163. package/dist/app/useGlobalShortcuts.d.ts +47 -0
  164. package/dist/app/useGlobalShortcuts.js +359 -0
  165. package/dist/app/useHtmlSession.d.ts +68 -0
  166. package/dist/app/useHtmlSession.js +463 -0
  167. package/dist/app/useHtmlSessionProps.d.ts +33 -0
  168. package/dist/app/useHtmlSessionProps.js +57 -0
  169. package/dist/app/useLibrary.d.ts +21 -0
  170. package/dist/app/useLibrary.js +81 -0
  171. package/dist/app/useOpenFromClipboard.d.ts +7 -0
  172. package/dist/app/useOpenFromClipboard.js +44 -0
  173. package/dist/app/usePaneLiveness.d.ts +29 -0
  174. package/dist/app/usePaneLiveness.js +199 -0
  175. package/dist/app/usePendingSavePaths.d.ts +19 -0
  176. package/dist/app/usePendingSavePaths.js +67 -0
  177. package/dist/app/useReadyShow.d.ts +12 -0
  178. package/dist/app/useReadyShow.js +142 -0
  179. package/dist/app/useSearchController.d.ts +22 -0
  180. package/dist/app/useSearchController.js +114 -0
  181. package/dist/app/useSetupRecovery.d.ts +41 -0
  182. package/dist/app/useSetupRecovery.js +153 -0
  183. package/dist/app/useTabChrome.d.ts +40 -0
  184. package/dist/app/useTabChrome.js +115 -0
  185. package/dist/app/useViewState.d.ts +27 -0
  186. package/dist/app/useViewState.js +160 -0
  187. package/dist/appName.d.ts +2 -0
  188. package/dist/appName.js +8 -0
  189. package/dist/documents/DocumentRouter.d.ts +102 -0
  190. package/dist/documents/DocumentRouter.js +153 -0
  191. package/dist/documents/FileTypeIcon.d.ts +6 -0
  192. package/dist/documents/FileTypeIcon.js +93 -0
  193. package/dist/documents/ImageDocument.d.ts +14 -0
  194. package/dist/documents/ImageDocument.js +61 -0
  195. package/dist/documents/capabilities.d.ts +17 -0
  196. package/dist/documents/capabilities.js +18 -0
  197. package/dist/documents/html/HtmlDocument.d.ts +15 -0
  198. package/dist/documents/html/HtmlDocument.js +584 -0
  199. package/dist/documents/html/HtmlDocumentLayout.d.ts +87 -0
  200. package/dist/documents/html/HtmlDocumentLayout.js +25 -0
  201. package/dist/documents/html/HtmlDocumentProps.d.ts +60 -0
  202. package/dist/documents/html/HtmlDocumentProps.js +1 -0
  203. package/dist/documents/html/HtmlDocumentSource.d.ts +34 -0
  204. package/dist/documents/html/HtmlDocumentSource.js +28 -0
  205. package/dist/documents/markdown/MarkdownSplitPane.d.ts +115 -0
  206. package/dist/documents/markdown/MarkdownSplitPane.js +352 -0
  207. package/dist/documents/mdx/MdxSplitPane.d.ts +32 -0
  208. package/dist/documents/mdx/MdxSplitPane.js +60 -0
  209. package/dist/documents/txt/LinkDialog.d.ts +8 -0
  210. package/dist/documents/txt/LinkDialog.js +34 -0
  211. package/dist/documents/txt/MarkdownSourceToolbar.d.ts +8 -0
  212. package/dist/documents/txt/MarkdownSourceToolbar.js +25 -0
  213. package/dist/documents/txt/SourceEditorToolbar.d.ts +12 -0
  214. package/dist/documents/txt/SourceEditorToolbar.js +4 -0
  215. package/dist/documents/txt/TxtEditor.d.ts +39 -0
  216. package/dist/documents/txt/TxtEditor.js +186 -0
  217. package/dist/documents/txt/sourceEditorTypes.d.ts +49 -0
  218. package/dist/documents/txt/sourceEditorTypes.js +1 -0
  219. package/dist/documents/txt/sourceExtensions.d.ts +38 -0
  220. package/dist/documents/txt/sourceExtensions.js +444 -0
  221. package/dist/documents/txt/sourceFormatting.d.ts +18 -0
  222. package/dist/documents/txt/sourceFormatting.js +183 -0
  223. package/dist/documents/txt/sourceTheme.d.ts +5 -0
  224. package/dist/documents/txt/sourceTheme.js +220 -0
  225. package/dist/documents/txt/useCodeMirrorSourceEditor.d.ts +69 -0
  226. package/dist/documents/txt/useCodeMirrorSourceEditor.js +546 -0
  227. package/dist/documents/txt/useSourceSearch.d.ts +39 -0
  228. package/dist/documents/txt/useSourceSearch.js +122 -0
  229. package/dist/documents/txt/useTextEditorCommands.d.ts +26 -0
  230. package/dist/documents/txt/useTextEditorCommands.js +151 -0
  231. package/dist/documents/web/LivePreviewPane.d.ts +11 -0
  232. package/dist/documents/web/LivePreviewPane.js +58 -0
  233. package/dist/env.d.ts +66 -0
  234. package/dist/index.d.ts +121 -0
  235. package/dist/index.js +123 -0
  236. package/dist/settings/AppearanceMenu.d.ts +9 -0
  237. package/dist/settings/AppearanceMenu.js +54 -0
  238. package/dist/settings/SettingsPanel.d.ts +7 -0
  239. package/dist/settings/SettingsPanel.js +104 -0
  240. package/dist/settings/publishedSections.d.ts +22 -0
  241. package/dist/settings/publishedSections.js +79 -0
  242. package/dist/settings/sections/AboutSection.d.ts +1 -0
  243. package/dist/settings/sections/AboutSection.js +13 -0
  244. package/dist/settings/sections/DiagnosticsSection.d.ts +1 -0
  245. package/dist/settings/sections/DiagnosticsSection.js +42 -0
  246. package/dist/settings/sections/PrivacySection.d.ts +3 -0
  247. package/dist/settings/sections/PrivacySection.js +51 -0
  248. package/dist/settings/sections/UpdateLicenseBlock.d.ts +10 -0
  249. package/dist/settings/sections/UpdateLicenseBlock.js +158 -0
  250. package/dist/state/explorer.d.ts +32 -0
  251. package/dist/state/explorer.js +111 -0
  252. package/dist/state/legal.d.ts +51 -0
  253. package/dist/state/legal.js +130 -0
  254. package/dist/state/library.d.ts +33 -0
  255. package/dist/state/library.js +110 -0
  256. package/dist/state/updateLicense.d.ts +31 -0
  257. package/dist/state/updateLicense.js +340 -0
  258. package/dist/styles/explorer.css +219 -0
  259. package/dist/styles/index.css +1477 -0
  260. package/dist/styles/tabs.css +467 -0
  261. package/dist/styles.css +6 -0
  262. package/package.json +88 -3
@@ -0,0 +1,300 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { memo } from "react";
3
+ import { MARKDOWN_FORMAT_EVENT } from "@rightkit/document-core/app/shell/nativeMenu";
4
+ import { useSettings } from "@rightkit/document-core/settings/settings";
5
+ import { capabilitiesFor } from "../documents/capabilities.js";
6
+ import { Dropdown, Item } from "@rightkit/document-core/documents/toolbarPrimitives";
7
+ import { shortcutLabel, isMac } from "@rightkit/document-core/platform";
8
+ import { nativeMenuActive, useNativeDocumentMenu, } from "@rightkit/document-core/app/shell/nativeMenu";
9
+ import { hostAppName } from "../appName.js";
10
+ export const DocumentMenus = memo(DocumentMenusImpl);
11
+ /** Menu title that hides the Windows-style Alt-letter accelerator hint on macOS. */
12
+ function menuTitle(label, accelerator) {
13
+ return isMac() ? label : `${label} (Alt+${accelerator})`;
14
+ }
15
+ function DocumentMenusImpl({ doc, view, onSave, onSaveAs, onPrint, onClose, onChangeView, onEditImageExternal, docxMenu, readOnly = false, }) {
16
+ // macOS: these commands live in the system menu bar, not in the window.
17
+ if (nativeMenuActive())
18
+ return (_jsx(NativeDocumentMenus, { doc: doc, view: view, onSave: onSave, onSaveAs: onSaveAs, onPrint: onPrint, onClose: onClose, onChangeView: onChangeView, onEditImageExternal: onEditImageExternal, docxMenu: docxMenu, readOnly: readOnly }));
19
+ if (doc.format === "docx" && docxMenu)
20
+ return _jsx(DocxMenus, { api: docxMenu, onSaveAs: onSaveAs, onClose: onClose, readOnly: readOnly });
21
+ if (doc.format === "web")
22
+ return null;
23
+ return (_jsx(TextMenus, { doc: doc, view: view, onSave: onSave, onSaveAs: onSaveAs, onPrint: onPrint, onClose: onClose, onChangeView: onChangeView, onEditImageExternal: onEditImageExternal, readOnly: readOnly }));
24
+ }
25
+ /** Commands the in-window menus offer for this document, for the macOS menu bar. Mirrors the
26
+ * visibility rules of DocxMenus/TextMenus below so both platforms expose the same actions. */
27
+ export function documentMenuCommands({ doc, view, onChangeView, onEditImageExternal, docxMenu, readOnly = false, spellcheck, wordWrap, toggleSpellcheck, toggleWordWrap, }) {
28
+ if (doc.format === "web")
29
+ return [];
30
+ if (doc.format === "docx" && docxMenu) {
31
+ const api = docxMenu;
32
+ const commands = [{ id: "page-setup", run: () => api.pageSetup() }];
33
+ if (readOnly)
34
+ return commands;
35
+ const fmt = (id, action) => ({
36
+ id,
37
+ run: () => api.format(action),
38
+ });
39
+ return [
40
+ ...commands,
41
+ fmt("bold", "bold"),
42
+ fmt("italic", "italic"),
43
+ fmt("underline", "underline"),
44
+ fmt("strikethrough", "strikethrough"),
45
+ fmt("superscript", "superscript"),
46
+ fmt("subscript", "subscript"),
47
+ fmt("clear-formatting", "clearFormatting"),
48
+ { id: "insert-table", run: () => api.insertTable(3, 3) },
49
+ { id: "insert-image", run: () => api.insertImage() },
50
+ fmt("insert-link", "insertLink"),
51
+ { id: "insert-page-break", run: () => api.insertPageBreak() },
52
+ { id: "insert-toc", run: () => api.insertTOC() },
53
+ ];
54
+ }
55
+ const cap = capabilitiesFor(doc.format);
56
+ const editable = cap.canReplace;
57
+ const commands = [];
58
+ if (doc.format === "image" && onEditImageExternal)
59
+ commands.push({ id: "edit-image-external", run: onEditImageExternal });
60
+ if (cap.canSwitchView && doc.format === "html") {
61
+ commands.push({
62
+ id: "view-interactive",
63
+ run: () => onChangeView("interactive"),
64
+ checked: view === "interactive",
65
+ });
66
+ commands.push({
67
+ id: "view-safe",
68
+ run: () => onChangeView("preview"),
69
+ checked: view === "preview",
70
+ });
71
+ }
72
+ if (doc.format === "md" && !readOnly) {
73
+ // The Markdown editor applies these; the menu just forwards the command id.
74
+ const md = (id) => ({
75
+ id,
76
+ run: () => window.dispatchEvent(new CustomEvent(MARKDOWN_FORMAT_EVENT, { detail: id })),
77
+ });
78
+ commands.push(md("bold"), md("italic"), md("strikethrough"));
79
+ commands.push(md("insert-link"), md("insert-table"), md("insert-image"));
80
+ }
81
+ if (cap.canSwitchView && doc.format === "md" && !readOnly)
82
+ commands.push({
83
+ id: "view-raw-source",
84
+ run: () => onChangeView(view === "source" ? "preview" : "source"),
85
+ checked: view === "source",
86
+ });
87
+ if (cap.canSwitchView && doc.format === "mdx" && !readOnly) {
88
+ commands.push({
89
+ id: "view-preview",
90
+ run: () => onChangeView("preview"),
91
+ checked: view === "preview",
92
+ });
93
+ commands.push({
94
+ id: "view-source",
95
+ run: () => onChangeView("source"),
96
+ checked: view === "source",
97
+ });
98
+ }
99
+ if (editable) {
100
+ commands.push({ id: "spellcheck", run: toggleSpellcheck, checked: spellcheck });
101
+ commands.push({ id: "word-wrap", run: toggleWordWrap, checked: wordWrap });
102
+ }
103
+ return commands;
104
+ }
105
+ function NativeDocumentMenus(props) {
106
+ const { settings, update } = useSettings();
107
+ useNativeDocumentMenu(documentMenuCommands({
108
+ ...props,
109
+ spellcheck: settings.spellcheck,
110
+ wordWrap: settings.wordWrap,
111
+ toggleSpellcheck: () => update({ spellcheck: !settings.spellcheck }),
112
+ toggleWordWrap: () => update({ wordWrap: !settings.wordWrap }),
113
+ }));
114
+ return null;
115
+ }
116
+ export const DocumentModeControls = memo(DocumentModeControlsImpl);
117
+ // Right-side toolbar controls group into 38px capsules (.vr-capsule): frosted panel glass, hairline
118
+ // border, soft shadow. The switch inside is a 32px round pill; its active state is the primary
119
+ // token at ~14% fill with the accent foreground (text-copper-hi resolves to paper inside chrome).
120
+ function DocumentModeControlsImpl({ doc, view, onChangeView, readOnly = false, }) {
121
+ // Read mode: the md "source" button and the mdx preview/source switch only reach editing
122
+ // surfaces — hide them. HTML's scripts ON/OFF knob is a viewing control and stays.
123
+ // Markdown's format bar carries its own Source button, so the title bar only offers the way back
124
+ // to the live editor while the raw source is open. Read-only MDX hides its switch too.
125
+ // One fixed view switch (right capsule of the document bar) in every mode — it never moves
126
+ // between the format bar and the title bar. Read-only MDX hides it.
127
+ const hideViewSwitch = readOnly && doc.format === "mdx";
128
+ return (_jsxs("div", { className: "flex min-w-0 items-center gap-2 font-sans text-chrome-sm text-muted-2", children: [!hideViewSwitch && (_jsx(ViewSwitch, { format: doc.format, view: view, onChangeView: onChangeView })), _jsx(ScriptsSwitch, { format: doc.format, view: view, onChangeView: onChangeView })] }));
129
+ }
130
+ /** the host app own DOCX menu bar (File/Format/Insert) — drives the lifted bridge API, no Eigenpal UI.
131
+ * No "Open…" here: opening is the app-level brokered Open (DocActionBar/sidebar/Ctrl+O). The vendor's
132
+ * in-editor picker is intentionally never surfaced — it swapped the editor buffer without changing
133
+ * the active doc.path, so a later Save would write the new content over the original file. */
134
+ function DocxMenus({ api, onSaveAs, onClose, readOnly = false, }) {
135
+ const fmt = (a) => () => api.format(a);
136
+ return (_jsxs("div", { className: "-ml-2 flex items-center font-sans text-chrome-sm", children: [_jsx(Dropdown, { variant: "menu", label: "File", title: menuTitle("File", "F"), panelWidth: 176, accelerator: "f", children: (close) => (_jsxs(_Fragment, { children: [_jsx(Item, { hint: shortcutLabel("mod+s"), onRun: () => {
137
+ api.save();
138
+ close();
139
+ }, children: "Save" }), _jsx(Item, { hint: shortcutLabel("mod+shift+s"), onRun: () => {
140
+ onSaveAs();
141
+ close();
142
+ }, children: "Save As\u2026" }), _jsx(Item, { onRun: () => {
143
+ api.pageSetup();
144
+ close();
145
+ }, children: "Page setup\u2026" }), _jsx(Item, { hint: shortcutLabel("mod+p"), onRun: () => {
146
+ api.print();
147
+ close();
148
+ }, children: "Print" }), _jsx(Item, { hint: shortcutLabel("mod+w"), onRun: () => {
149
+ onClose();
150
+ close();
151
+ }, children: "Close" })] })) }), !readOnly && (_jsxs(_Fragment, { children: [_jsx(Dropdown, { variant: "menu", label: "Format", title: menuTitle("Format", "O"), panelWidth: 158, accelerator: "o", children: (close) => (_jsxs(_Fragment, { children: [_jsx(Item, { hint: shortcutLabel("mod+b"), onRun: () => {
152
+ fmt("bold")();
153
+ close();
154
+ }, children: "Bold" }), _jsx(Item, { hint: shortcutLabel("mod+i"), onRun: () => {
155
+ fmt("italic")();
156
+ close();
157
+ }, children: "Italic" }), _jsx(Item, { hint: shortcutLabel("mod+u"), onRun: () => {
158
+ fmt("underline")();
159
+ close();
160
+ }, children: "Underline" }), _jsx(Item, { onRun: () => {
161
+ fmt("strikethrough")();
162
+ close();
163
+ }, children: "Strikethrough" }), _jsx(Item, { onRun: () => {
164
+ fmt("superscript")();
165
+ close();
166
+ }, children: "Superscript" }), _jsx(Item, { onRun: () => {
167
+ fmt("subscript")();
168
+ close();
169
+ }, children: "Subscript" }), _jsx(Item, { onRun: () => {
170
+ fmt("clearFormatting")();
171
+ close();
172
+ }, children: "Clear formatting" })] })) }), _jsx(Dropdown, { variant: "menu", label: "Insert", title: menuTitle("Insert", "N"), panelWidth: 170, accelerator: "n", children: (close) => (_jsxs(_Fragment, { children: [_jsx(Item, { onRun: () => {
173
+ api.insertTable(3, 3);
174
+ close();
175
+ }, children: "Table (3 \u00D7 3)" }), _jsx(Item, { onRun: () => {
176
+ api.insertImage();
177
+ close();
178
+ }, children: "Image\u2026" }), _jsx(Item, { onRun: () => {
179
+ fmt("insertLink")();
180
+ close();
181
+ }, children: "Link\u2026" }), _jsx(Item, { onRun: () => {
182
+ api.insertPageBreak();
183
+ close();
184
+ }, children: "Page break" }), _jsx(Item, { onRun: () => {
185
+ api.insertTOC();
186
+ close();
187
+ }, children: "Table of contents" })] })) })] }))] }));
188
+ }
189
+ /** Menu bar for text + pdf formats. File always; Edit for editable text; View for render-switchable. */
190
+ function TextMenus({ doc, view, onSave, onSaveAs, onPrint, onClose, onChangeView, onEditImageExternal, readOnly = false, }) {
191
+ const { settings, update } = useSettings();
192
+ const cap = capabilitiesFor(doc.format);
193
+ // Text-only Edit menu: image is saveable but edits in its own viewer shell, so canReplace
194
+ // (txt/md/mdx/html) is the right gate here, not canEdit.
195
+ const editable = cap.canReplace;
196
+ const saveable = cap.canEdit;
197
+ const saveAs = cap.canSaveAs;
198
+ const viewSwitch = cap.canSwitchView;
199
+ // execCommand acts on the focused source editor; the menu items are
200
+ // focus-safe (onMouseDown), so the editor keeps focus + selection while the menu is used.
201
+ const exec = (cmd) => () => document.execCommand(cmd);
202
+ const dispatchEditorCommand = (type) => () => {
203
+ window.dispatchEvent(new Event(type, { cancelable: true }));
204
+ };
205
+ const selectAll = () => {
206
+ if (doc.format === "html") {
207
+ const event = new Event("viewright:html-select-all", { cancelable: true });
208
+ window.dispatchEvent(event);
209
+ if (event.defaultPrevented)
210
+ return;
211
+ }
212
+ document.execCommand("selectAll");
213
+ };
214
+ return (_jsxs("div", { className: "-ml-2 flex items-center font-sans text-chrome-sm", children: [_jsx(Dropdown, { variant: "menu", label: "File", title: menuTitle("File", "F"), panelWidth: 176, accelerator: "f", children: (close) => (_jsxs(_Fragment, { children: [saveable && (_jsx(Item, { hint: shortcutLabel("mod+s"), onRun: () => {
215
+ onSave();
216
+ close();
217
+ }, children: "Save" })), saveAs && (_jsx(Item, { hint: shortcutLabel("mod+shift+s"), onRun: () => {
218
+ onSaveAs();
219
+ close();
220
+ }, children: "Save As\u2026" })), doc.format === "image" && onEditImageExternal && (_jsx(Item, { onRun: () => {
221
+ onEditImageExternal();
222
+ close();
223
+ }, children: "Edit image externally\u2026" })), _jsx(Item, { hint: shortcutLabel("mod+p"), onRun: () => {
224
+ onPrint();
225
+ close();
226
+ }, children: "Print" }), _jsx(Item, { hint: shortcutLabel("mod+w"), onRun: () => {
227
+ onClose();
228
+ close();
229
+ }, children: "Close" })] })) }), editable && !readOnly && (_jsx(Dropdown, { variant: "menu", label: "Edit", title: menuTitle("Edit", "E"), panelWidth: 140, accelerator: "e", children: (close) => (_jsxs(_Fragment, { children: [_jsx(Item, { hint: shortcutLabel("mod+z"), onRun: () => {
230
+ dispatchEditorCommand("viewright:undo")();
231
+ close();
232
+ }, children: "Undo" }), _jsx(Item, { hint: shortcutLabel("mod+y"), onRun: () => {
233
+ dispatchEditorCommand("viewright:redo")();
234
+ close();
235
+ }, children: "Redo" }), _jsx(Item, { hint: shortcutLabel("mod+x"), onRun: () => {
236
+ exec("cut")();
237
+ close();
238
+ }, children: "Cut" }), _jsx(Item, { hint: shortcutLabel("mod+c"), onRun: () => {
239
+ exec("copy")();
240
+ close();
241
+ }, children: "Copy" }), _jsx(Item, { hint: shortcutLabel("mod+v"), onRun: () => {
242
+ exec("paste")();
243
+ close();
244
+ }, children: "Paste" }), _jsx(Item, { hint: shortcutLabel("mod+a"), onRun: () => {
245
+ selectAll();
246
+ close();
247
+ }, children: "Select all" })] })) })), (viewSwitch || editable) && (_jsx(Dropdown, { variant: "menu", label: "View", title: menuTitle("View", "V"), panelWidth: 150, accelerator: "v", children: (close) => (_jsxs(_Fragment, { children: [viewSwitch && doc.format === "html" && (_jsxs(_Fragment, { children: [_jsx(Item, { active: view === "interactive", onRun: () => {
248
+ onChangeView("interactive");
249
+ close();
250
+ }, children: "Interactive" }), _jsx(Item, { active: view === "preview", onRun: () => {
251
+ onChangeView("preview");
252
+ close();
253
+ }, children: "Safe" })] })), viewSwitch && doc.format === "md" && !readOnly && (_jsx(Item, { active: view === "source", onRun: () => {
254
+ onChangeView(view === "source" ? "preview" : "source");
255
+ close();
256
+ }, children: view === "source" ? "Return to live editor" : "Raw source" })), viewSwitch && doc.format === "mdx" && !readOnly && (_jsxs(_Fragment, { children: [_jsx(Item, { active: view === "preview", onRun: () => {
257
+ onChangeView("preview");
258
+ close();
259
+ }, children: "Preview" }), _jsx(Item, { active: view === "source", onRun: () => {
260
+ onChangeView("source");
261
+ close();
262
+ }, children: "Source" })] })), editable && (_jsxs(_Fragment, { children: [_jsx(Item, { active: settings.spellcheck, onRun: () => {
263
+ update({ spellcheck: !settings.spellcheck });
264
+ close();
265
+ }, children: "Spell check" }), _jsx(Item, { active: settings.wordWrap, onRun: () => {
266
+ update({ wordWrap: !settings.wordWrap });
267
+ close();
268
+ }, children: "Word wrap" })] }))] })) }))] }));
269
+ }
270
+ /** Markdown keeps one live editor; raw source is its fallback drawer. MDX retains its preview/source
271
+ * switch because executable MDX cannot mount in the app's editable React tree. */
272
+ function ViewSwitch({ format, view, onChangeView, }) {
273
+ // Segmented two-way switch that stays in one place: Markdown Editor | Source, MDX Preview | Source.
274
+ if (format !== "md" && format !== "mdx")
275
+ return null;
276
+ const first = format === "md" ? "Editor" : "Preview";
277
+ const sourceOpen = view === "source";
278
+ const seg = (on) => `vr-press vr-focus h-7 rounded-full px-2.5 ${on ? "bg-copper/[0.14] text-copper-hi" : "text-muted-2 hover:bg-ink/40 hover:text-paper"}`;
279
+ return (_jsxs("div", { role: "group", "aria-label": "View", className: "flex items-center gap-0.5 select-none", children: [_jsx("button", { type: "button", "aria-pressed": !sourceOpen, "aria-label": format === "md" ? "Show live editor" : "Show MDX preview", title: format === "md" ? "Live editor" : "Preview", onClick: () => onChangeView("preview"), className: seg(!sourceOpen), children: first }), _jsx("button", { type: "button", "aria-pressed": sourceOpen, "aria-label": format === "md" ? "Show raw Markdown source" : "Show MDX source", title: format === "md" ? "Raw Markdown source" : "MDX source", onClick: () => onChangeView("source"), className: seg(sourceOpen), children: "Source" })] }));
280
+ }
281
+ /** HTML scripts ON/OFF toggle (Interactive ↔ Safe), md-switch styling: label + sliding knob + state.
282
+ * ON (Interactive, page JS runs) is RED; OFF (Safe, scriptless render) is GREEN. Lives here in the
283
+ * action bar — same place/feel as md's preview/source switch — not in the page URL chrome. Returns
284
+ * null for every non-HTML format. HTML's `view` is only ever "interactive" or "preview" (the source
285
+ * drawer is separate internal state), so `view !== "preview"` cleanly means scripts ON. */
286
+ function ScriptsSwitch({ format, view, onChangeView, }) {
287
+ if (format !== "html")
288
+ return null;
289
+ // Mirror HtmlDocument's `mode` (view === "preview" ? Safe : Interactive) exactly, so the knob never
290
+ // disagrees with what the preview is actually doing — a stale/odd ViewMode reads as Interactive in
291
+ // both places. Red dot = ON (scripts run), green = OFF (Safe); the colour + position carry state.
292
+ const interactive = view !== "preview";
293
+ return (_jsxs("div", { className: "flex items-center gap-2 px-1.5 select-none", title: interactive
294
+ ? `Scripts ON — the page runs like a browser tab (remote scripts, fonts, network), but in an origin-isolated sandbox that can't touch ${hostAppName()} or your files. Click for Safe (scriptless render).`
295
+ : "Scripts OFF — Safe scriptless render. Click to run the page (Interactive).", children: [_jsx("span", { className: "text-muted-2", children: "scripts" }), _jsx("button", { type: "button", role: "switch", "aria-checked": interactive, "aria-label": interactive
296
+ ? "Scripts on (Interactive). Switch to Safe."
297
+ : "Scripts off (Safe). Switch to Interactive.", onClick: () => onChangeView(interactive ? "preview" : "interactive"), className: `vr-focus flex h-4 w-8 shrink-0 items-center rounded-full border px-0.5 ${interactive
298
+ ? "justify-end border-[color:color-mix(in_srgb,var(--danger)_60%,var(--line))] bg-[color:color-mix(in_srgb,var(--danger)_20%,transparent)]"
299
+ : "justify-start border-[color:color-mix(in_srgb,var(--accent-2)_60%,var(--line))] bg-[color:color-mix(in_srgb,var(--accent-2)_20%,transparent)]"}`, children: _jsx("span", { className: `h-2.5 w-2.5 rounded-full transition-all duration-150 ${interactive ? "bg-danger-hi" : "bg-accent2"}` }) })] }));
300
+ }
@@ -0,0 +1,29 @@
1
+ export interface DocContextMenu {
2
+ x: number;
3
+ y: number;
4
+ editable: boolean;
5
+ hasSelection: boolean;
6
+ editableEl: HTMLElement | null;
7
+ contentRoot: HTMLElement | null;
8
+ }
9
+ export type DocMenuItemId = "cut" | "copy" | "paste" | "selectAll" | "copyContents";
10
+ export interface DocMenuItem {
11
+ id: DocMenuItemId;
12
+ label: string;
13
+ disabled: boolean;
14
+ separatorBefore?: boolean;
15
+ }
16
+ export declare function documentMenuItems(opts: {
17
+ editable: boolean;
18
+ hasSelection: boolean;
19
+ canCopyContents: boolean;
20
+ }): DocMenuItem[];
21
+ export declare function useDocumentContextMenu(): {
22
+ menu: DocContextMenu | null;
23
+ close: () => void;
24
+ };
25
+ export declare function DocumentContextMenu({ menu, onClose, onCopyContents, }: {
26
+ menu: DocContextMenu;
27
+ onClose: () => void;
28
+ onCopyContents: (() => void) | null;
29
+ }): import("react").JSX.Element;
@@ -0,0 +1,122 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // Right-click menu for the document content plane. The app globally suppresses the raw WebView2
3
+ // context menu (`blockNativeContextMenu`, installed in main.tsx) so the chrome never shows browser junk; this restores a curated,
4
+ // cross-platform Edit menu (Cut / Copy / Paste / Select all, plus Copy contents) on the actual document
5
+ // surfaces — markdown preview, source/CodeMirror, DOCX, HTML, PDF text, images. Scoped by the
6
+ // `[data-vr-content-plane]` marker so a right-click on the sidebar/toolbar still gets nothing.
7
+ import { useCallback, useEffect, useState } from "react";
8
+ import { ContextMenu } from "@rightkit/react-shell/react";
9
+ import { compactMenuItemClass } from "./sidebar/SidebarPrimitives.js";
10
+ const EDITABLE_SELECTOR = '.cm-content, .ProseMirror, [contenteditable="true"], textarea, input:not([type="checkbox"]):not([type="radio"]):not([type="button"])';
11
+ // Pure item composition, kept separate so the menu shape is unit-testable without a DOM or clipboard.
12
+ // Cut/Paste appear only on editable surfaces; Copy/Cut are disabled without a selection; Copy contents
13
+ // appears only when the caller can supply the whole-document text (text-like formats).
14
+ export function documentMenuItems(opts) {
15
+ const items = [];
16
+ if (opts.editable)
17
+ items.push({ id: "cut", label: "Cut", disabled: !opts.hasSelection });
18
+ items.push({ id: "copy", label: "Copy", disabled: !opts.hasSelection });
19
+ if (opts.editable)
20
+ items.push({ id: "paste", label: "Paste", disabled: false });
21
+ items.push({ id: "selectAll", label: "Select all", disabled: false, separatorBefore: true });
22
+ if (opts.canCopyContents)
23
+ items.push({ id: "copyContents", label: "Copy contents", disabled: false });
24
+ return items;
25
+ }
26
+ // Non-HTML document surfaces use the host app curated menu on plain or Shift+right-click. HTML iframe
27
+ // events never reach this parent listener; those frames retain their own exact-node inspect menus.
28
+ export function useDocumentContextMenu() {
29
+ const [menu, setMenu] = useState(null);
30
+ useEffect(() => {
31
+ const onCtx = (e) => {
32
+ const target = e.target;
33
+ if (!target || typeof target.closest !== "function")
34
+ return;
35
+ const contentRoot = target.closest("[data-vr-content-plane]");
36
+ if (!contentRoot)
37
+ return; // chrome right-click → no document menu
38
+ // Never shadow an HTML preview iframe. Right-clicks INSIDE the iframe are a separate document
39
+ // and never reach this listener; this only guards the edge case where the iframe element itself
40
+ // is the target. The HTML previews own their own menus — WebView2's native menu + the Rust-grafted
41
+ // "View source"/Inspect on the interactive (about:srcdoc) frame, and HtmlViewer's inspect menu on
42
+ // the safe (allow-same-origin) frame — and must stay authoritative there.
43
+ if (target.closest("iframe"))
44
+ return;
45
+ e.preventDefault();
46
+ const editableEl = target.closest(EDITABLE_SELECTOR);
47
+ const editable = !!editableEl && !editableEl.closest('[contenteditable="false"]');
48
+ const sel = typeof window.getSelection === "function" ? window.getSelection() : null;
49
+ const hasSelection = !!sel && !sel.isCollapsed && sel.toString().trim().length > 0;
50
+ setMenu({
51
+ x: e.clientX,
52
+ y: e.clientY,
53
+ editable,
54
+ hasSelection,
55
+ editableEl: editableEl ?? null,
56
+ contentRoot,
57
+ });
58
+ };
59
+ document.addEventListener("contextmenu", onCtx, { capture: true });
60
+ return () => document.removeEventListener("contextmenu", onCtx, { capture: true });
61
+ }, []);
62
+ return { menu, close: useCallback(() => setMenu(null), []) };
63
+ }
64
+ export function DocumentContextMenu({ menu, onClose, onCopyContents, }) {
65
+ const items = documentMenuItems({
66
+ editable: menu.editable,
67
+ hasSelection: menu.hasSelection,
68
+ canCopyContents: !!onCopyContents,
69
+ });
70
+ const run = (id) => {
71
+ switch (id) {
72
+ case "cut":
73
+ document.execCommand("cut");
74
+ break;
75
+ case "copy":
76
+ document.execCommand("copy");
77
+ break;
78
+ case "paste":
79
+ void (async () => {
80
+ try {
81
+ const text = await navigator.clipboard.readText();
82
+ menu.editableEl?.focus();
83
+ document.execCommand("insertText", false, text);
84
+ }
85
+ catch {
86
+ /* clipboard unavailable / denied — nothing to paste */
87
+ }
88
+ })();
89
+ break;
90
+ case "selectAll":
91
+ if (menu.editableEl) {
92
+ menu.editableEl.focus();
93
+ document.execCommand("selectAll");
94
+ }
95
+ else if (menu.contentRoot) {
96
+ const sel = window.getSelection();
97
+ sel?.removeAllRanges();
98
+ const range = document.createRange();
99
+ range.selectNodeContents(menu.contentRoot);
100
+ sel?.addRange(range);
101
+ }
102
+ break;
103
+ case "copyContents":
104
+ onCopyContents?.();
105
+ break;
106
+ }
107
+ };
108
+ // The shell menu keeps the document selection (no focus steal, no mousedown default), handles
109
+ // arrows/Home/End/Enter/Space/Escape from the window, closes on scrim press or context-menu
110
+ // gesture, and fits itself to the viewport.
111
+ const menuItems = items.map((item) => ({
112
+ id: item.id,
113
+ label: item.label,
114
+ disabled: item.disabled,
115
+ separatorBefore: item.separatorBefore,
116
+ run: () => run(item.id),
117
+ }));
118
+ return (_jsx(ContextMenu, { x: menu.x, y: menu.y, items: menuItems, onClose: onClose, label: "Document actions", width: 176, itemAs: "button", autoFocus: false, showLead: false, renderItem: (item) => item.label, className: "vr-pop no-print overflow-x-hidden rounded-lg border border-line bg-panel-2 py-0.5 shadow-2xl", scrimClassName: "no-print", slots: {
119
+ item: `${compactMenuItemClass} [&.is-active]:bg-ink/50 [&.is-active]:text-paper [&.is-disabled]:cursor-default [&.is-disabled]:opacity-40 [&.is-disabled]:hover:bg-transparent`,
120
+ separator: "my-1 h-px bg-line",
121
+ } }));
122
+ }
@@ -0,0 +1,52 @@
1
+ import type { ComponentProps, ReactNode } from "react";
2
+ import { DocStatsPill } from "./shell/DocStatsPill.js";
3
+ import { DocumentTools } from "./shell/DocumentTools.js";
4
+ import { StartPage } from "./shell/StartPage.js";
5
+ import { BlockDraftProvider } from "@rightkit/document-core/app/BlockDraftContext";
6
+ import { DocumentRouterTable } from "./DocumentRouterTable.js";
7
+ import type { useSettings } from "@rightkit/document-core/settings/settings";
8
+ import type { LoadedDocument } from "@rightkit/document-core/documents/types";
9
+ import type { DocxMenuApi } from "@rightkit/docx-editor/documents/docx/menuApi";
10
+ type StatsProps = ComponentProps<typeof DocStatsPill>;
11
+ type RouterProps = ComponentProps<typeof DocumentRouterTable>;
12
+ export type DocumentPaneProps = {
13
+ active: LoadedDocument | null;
14
+ activeIndex: number;
15
+ activeEditable: boolean;
16
+ view: ComponentProps<typeof DocumentTools>["view"];
17
+ distractionFree: boolean;
18
+ docBarSlot: HTMLElement | null;
19
+ setDocBarSlot: (el: HTMLElement | null) => void;
20
+ modeSlot: ReactNode;
21
+ inspectorOpen: boolean;
22
+ toggleInspector: () => void;
23
+ closeInspector: () => void;
24
+ findBarEl: ReactNode;
25
+ zoom: {
26
+ zoomHud: ReactNode;
27
+ zoomedAwayFromDefault: boolean;
28
+ zoomPercentLabel: string;
29
+ resetDocumentZoom: () => void;
30
+ };
31
+ openingPath: string | null;
32
+ restoringSession: boolean;
33
+ openDocs: LoadedDocument[];
34
+ startPage: ComponentProps<typeof StartPage>;
35
+ blockDrafts: ComponentProps<typeof BlockDraftProvider>["registry"];
36
+ router: RouterProps;
37
+ subscribeEdits: StatsProps["subscribeEdits"];
38
+ getEditSnapshot: StatsProps["getEditSnapshot"];
39
+ dirtyPaths: Set<string>;
40
+ isDirty: (doc: LoadedDocument) => boolean;
41
+ subscribeDirty: (path: string, listener: () => void) => () => void;
42
+ docxMenu: DocxMenuApi | null;
43
+ onHtmlSave: (path: string) => unknown;
44
+ onSave: (doc: LoadedDocument) => unknown;
45
+ settings: ReturnType<typeof useSettings>["settings"];
46
+ update: ReturnType<typeof useSettings>["update"];
47
+ };
48
+ /** The document column: docked format bar, the content plane (find bar, zoom pill, opening/restore
49
+ * indicators, start page, router table), the status row, and the Info inspector. Extracted
50
+ * verbatim from App.tsx. */
51
+ export declare function DocumentPane(p: DocumentPaneProps): import("react").JSX.Element;
52
+ export {};
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { tabDomId } from "./tabs/tabIds.js";
3
+ import { DocStatsPill } from "./shell/DocStatsPill.js";
4
+ import { DocumentTools } from "./shell/DocumentTools.js";
5
+ import { DocBarSlotContext } from "@rightkit/document-core/app/shell/docBar";
6
+ import { InfoInspector } from "./shell/InfoInspector.js";
7
+ import { StartPage } from "./shell/StartPage.js";
8
+ import { OpeningProgress } from "./OpeningProgress.js";
9
+ import { BlockDraftProvider } from "@rightkit/document-core/app/BlockDraftContext";
10
+ import { DocumentRouterTable } from "./DocumentRouterTable.js";
11
+ /** The document column: docked format bar, the content plane (find bar, zoom pill, opening/restore
12
+ * indicators, start page, router table), the status row, and the Info inspector. Extracted
13
+ * verbatim from App.tsx. */
14
+ export function DocumentPane(p) {
15
+ const { active, distractionFree, zoom } = p;
16
+ return (_jsxs("div", { className: "flex min-h-0 min-w-0 flex-1", children: [_jsxs("div", { className: "relative flex min-h-0 min-w-0 flex-1 flex-col", children: [_jsx("svg", { "data-vr-content-corner": true, viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: "M0 24V0H24A24 24 0 0 0 0 24Z" }) }), active && !distractionFree && (_jsxs("div", { "data-vr-doc-bar": true, className: "no-print relative z-30 flex shrink-0 items-center gap-2 border-b border-[color-mix(in_srgb,var(--reader-line)_62%,transparent)] bg-[var(--reader-surface)] py-1 pl-3.5 pr-3", children: [_jsx("div", { ref: p.setDocBarSlot, className: "flex min-w-0 flex-1 items-center" }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [p.modeSlot, p.modeSlot && _jsx("span", { "aria-hidden": "true", className: "mx-0.5 h-4 w-px bg-line" }), _jsx(DocumentTools, { doc: active, view: p.view, inspectorOpen: p.inspectorOpen, onToggleInspector: p.toggleInspector })] })] })), _jsx(DocBarSlotContext.Provider, { value: distractionFree ? null : p.docBarSlot, children: _jsxs("div", { "data-vr-content-plane": true, id: "vr-doc-pane", role: "tabpanel", "aria-labelledby": active ? tabDomId(active) : undefined, className: "relative min-h-0 min-w-0 flex-1 overflow-hidden bg-[var(--reader-surface)]", children: [p.findBarEl && (_jsx("div", { "data-vr-toolbar-find": "", className: "no-print vr-chrome absolute top-2 z-50 overflow-y-auto max-h-[calc(100%-1rem)]", children: p.findBarEl })), zoom.zoomedAwayFromDefault ? (_jsxs("button", { type: "button", onClick: zoom.resetDocumentZoom, "aria-label": "Reset zoom to 100%", className: "no-print absolute right-4 top-4 z-50 rounded border border-line bg-panel-2 px-2 py-1 font-mono text-xs text-muted shadow-xl hover:text-fg", children: [zoom.zoomPercentLabel, " \u00B7 Reset"] })) : (zoom.zoomHud && (_jsx("div", { className: "no-print pointer-events-none absolute right-4 top-4 z-50 rounded border border-line bg-panel-2 px-2 py-1 font-mono text-xs text-muted shadow-xl", children: zoom.zoomHud }))), p.openingPath && (_jsx(OpeningProgress, { fileName: p.openingPath.split(/[\\/]/).pop() || "document" }, p.openingPath)), !active && p.restoringSession && p.openDocs.length > 0 && (_jsx("div", { role: "status", "aria-live": "polite", "data-testid": "restoring-session", className: "absolute inset-0 flex items-center justify-center bg-[var(--reader-surface)] outline-none", children: _jsxs("div", { className: "flex items-center gap-3 font-sans text-sm text-muted", children: [_jsx("span", { className: "h-2 w-2 animate-pulse rounded-full bg-copper", "aria-hidden": true }), "Restoring session\u2026"] }) })), !active && (!p.restoringSession || p.openDocs.length === 0) && (_jsx("div", { className: "absolute inset-0 overflow-auto bg-[var(--reader-surface)] outline-none", children: _jsx(StartPage, { ...p.startPage }) })), _jsx(BlockDraftProvider, { registry: p.blockDrafts, children: _jsx(DocumentRouterTable, { ...p.router }) })] }) }), active && !distractionFree && (_jsxs("div", { "data-vr-doc-status-bar": true, className: "no-print shrink-0 justify-between font-sans", children: [_jsx("div", { className: "vr-doc-path min-w-0 flex-1 opacity-80", children: active.path }), _jsx(DocStatsPill, { doc: active, subscribeEdits: p.subscribeEdits, getEditSnapshot: p.getEditSnapshot, status: p.activeEditable
17
+ ? {
18
+ dirtyHint: p.dirtyPaths.has(active.path),
19
+ isDirty: p.isDirty,
20
+ subscribeDirty: p.subscribeDirty,
21
+ onSave: () => active.format === "docx" && p.docxMenu
22
+ ? p.docxMenu.save()
23
+ : active.format === "html"
24
+ ? p.onHtmlSave(active.path)
25
+ : p.onSave(active),
26
+ autoSave: p.settings.autoSave,
27
+ onToggleAutoSave: () => p.update({ autoSave: !p.settings.autoSave }),
28
+ }
29
+ : undefined })] }))] }), p.inspectorOpen && active && !distractionFree && (_jsx(InfoInspector, { doc: active, onClose: p.closeInspector, subscribeEdits: p.subscribeEdits, getEditSnapshot: p.getEditSnapshot }))] }));
30
+ }
@@ -0,0 +1,58 @@
1
+ import { type ComponentProps, type RefObject } from "react";
2
+ import { DocumentRouter } from "../documents/DocumentRouter.js";
3
+ import type { LoadedDocument, SearchProvider, ViewMeta, ViewMode } from "@rightkit/document-core/documents/types";
4
+ import type { DocxMenuApi } from "@rightkit/docx-editor/documents/docx/menuApi";
5
+ import type { ImageSaveFunction } from "@rightkit/media-ui";
6
+ import type { MarkdownExportApi } from "@rightkit/markdown-editor/documents/markdown/export/markdownExportTypes";
7
+ import type { SourceEditorViewState } from "../documents/txt/TxtEditor.js";
8
+ import type { PdfSaveFunction } from "@rightkit/document-core/documents/pdf/pdfEditor";
9
+ import type { PdfSavePlan } from "@rightkit/document-core/documents/pdf/pdfEditModel";
10
+ declare function DocumentRouterTableImpl({ mountedDocs, activePath, livePaths, renderedPaths, views, contentScrollRef, onContentScroll, onDocumentWheel, subscribeEdits, getEditSnapshot, getExternalSeq, sourceViewStateRef, onTxtChange, onSave, onDocxSaveAs, onDocxSave, onDocxChange, docxSaver, imageSaver, docxSaversRef, pdfSaversRef, pdfSavePlansRef, imageSaversRef, setDocxMenu, setPdfPrint, setMarkdownExport, onImageChange, onPdfDirtyChange, openImageSibling, registerSearchProviderFor, onPdfViewState, findBarEl, findMode, canReplaceSearch, onChangeView, toggleFind, closeFind, onOpenPath, trackMdxGrant, htmlPropsFor, }: {
11
+ mountedDocs: LoadedDocument[];
12
+ activePath: string | null;
13
+ /** Paths currently allowed to own a heavy DocumentRouter tree. */
14
+ livePaths: ReadonlySet<string>;
15
+ renderedPaths: Set<string>;
16
+ views: Record<string, ViewMode>;
17
+ /** Wave 2 ephemeral per-doc Read/Edit modes — absent means "read". */
18
+ contentScrollRef: RefObject<HTMLDivElement | null>;
19
+ onContentScroll: (e: React.UIEvent<HTMLDivElement>) => void;
20
+ onDocumentWheel: (e: React.WheelEvent<HTMLDivElement>) => void;
21
+ subscribeEdits: (path: string, cb: () => void) => () => void;
22
+ getEditSnapshot: (path: string) => string | undefined;
23
+ getExternalSeq: (path: string) => number;
24
+ /** App-owned source selection/scroll survives a dirty router shell + cold remount. */
25
+ sourceViewStateRef: RefObject<Record<string, SourceEditorViewState>>;
26
+ onTxtChange: (path: string, prevContent: string, text: string) => void;
27
+ onSave: (doc: LoadedDocument) => void;
28
+ onDocxSaveAs: (doc: LoadedDocument, buf: ArrayBuffer) => void;
29
+ onDocxSave: (path: string, buf: ArrayBuffer) => void;
30
+ onDocxChange: (path: string) => void;
31
+ docxSaver: RefObject<(() => Promise<ArrayBuffer | null>) | null>;
32
+ imageSaver: RefObject<ImageSaveFunction | null>;
33
+ docxSaversRef: RefObject<Map<string, () => Promise<ArrayBuffer | null>>>;
34
+ pdfSaversRef: RefObject<Map<string, PdfSaveFunction>>;
35
+ pdfSavePlansRef: RefObject<Map<string, () => Promise<PdfSavePlan>>>;
36
+ imageSaversRef: RefObject<Map<string, ImageSaveFunction>>;
37
+ setDocxMenu: (api: DocxMenuApi | null) => void;
38
+ setPdfPrint: (fn: (() => Promise<boolean>) | null) => void;
39
+ setMarkdownExport: (api: MarkdownExportApi | null) => void;
40
+ onImageChange: (path: string) => void;
41
+ onPdfDirtyChange: (path: string, dirty: boolean) => void;
42
+ openImageSibling: (currentPath: string, targetPath: string) => void;
43
+ registerSearchProviderFor: (path: string) => (provider: SearchProvider | null) => void;
44
+ onPdfViewState: (m: ViewMeta) => void;
45
+ findBarEl: React.ReactNode;
46
+ findMode?: "find" | "replace";
47
+ canReplaceSearch: boolean;
48
+ onChangeView: (view: ViewMode) => void;
49
+ toggleFind: (replace: boolean) => void;
50
+ closeFind: () => void;
51
+ onOpenPath: (path: string, opts?: {
52
+ background?: boolean;
53
+ }) => void;
54
+ trackMdxGrant: (entryPath: string, grantedPath: string) => void;
55
+ htmlPropsFor: (entryPath: string) => ComponentProps<typeof DocumentRouter>["html"] | undefined;
56
+ }): import("react").JSX.Element;
57
+ export declare const DocumentRouterTable: import("react").MemoExoticComponent<typeof DocumentRouterTableImpl>;
58
+ export {};