@rightkit/document-workspace 0.0.0-stage → 0.1.1

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 +11 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +74 -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,159 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useMemo, useRef } from "react";
3
+ import { Onboarding } from "@rightkit/onboarding";
4
+ import { getCurrentWindow, LogicalSize } from "@tauri-apps/api/window";
5
+ import { isTauri } from "@rightkit/platform-ui";
6
+ import { useSettings } from "@rightkit/document-core/settings/settings";
7
+ import { LEGAL_GATE_DOCUMENTS, LEGAL_MATERIAL_SHA256, REQUIRED_LEGAL_ACCEPTANCE_VERSION, createOnboardingSettingsBackend, legalAcceptanceCurrent, legalReceiptFields, legalReceiptRecord, legalRecordCurrent, } from "../state/legal.js";
8
+ import { App } from "./App.js";
9
+ import { useReadyShow } from "./useReadyShow.js";
10
+ import { logError } from "@rightkit/document-core/state/diagnostics";
11
+ import { getShell, isBrowserQaMode } from "@rightkit/document-core/state/tauriBridge";
12
+ import { hostAppName } from "../appName.js";
13
+ // Locked (Adrian, 2026-07-17): the gate is its own fixed 960x560 window, independent of whatever
14
+ // size the user last left the main 1100x750 workspace at. See memory
15
+ // "legal-gate-fixed-960x560-own-window".
16
+ const GATE_WIDTH = 960;
17
+ const GATE_HEIGHT = 560;
18
+ const TRUST_LINE = `${hostAppName()} works on the documents already on your disk. Nothing is uploaded to open or edit them.`;
19
+ const AGREEMENT_STATEMENT = `I have read and agree to the ${hostAppName()} License, End User License Agreement, Acceptable Use Policy, and Product Schedule.`;
20
+ // Transcribed from .claude/rules/brands.md (Right Suite — App Identities — the host app) LIGHT tokens.
21
+ // The legal gate is locked to light mode for every app regardless of the app's own theme setting.
22
+ const RIGHTKIT_LEGAL_GATE_THEME = {
23
+ bg: "#F7F3EC",
24
+ surface: "#FFFDF8",
25
+ border: "#E2DAD1",
26
+ text: "#211C18",
27
+ muted: "#6E665F",
28
+ accent: "#0C6AA5",
29
+ accentContrast: "#FFFFFF",
30
+ fontDisplay: "Tanker, 'Arial Narrow', sans-serif",
31
+ fontBody: "Geist, 'Hanken Grotesk', sans-serif",
32
+ };
33
+ const LEGAL_STEP = {
34
+ theme: RIGHTKIT_LEGAL_GATE_THEME,
35
+ appName: hostAppName(),
36
+ trustLine: TRUST_LINE,
37
+ documents: LEGAL_GATE_DOCUMENTS,
38
+ agreementStatement: AGREEMENT_STATEMENT,
39
+ onQuit: () => void destroyWindow(),
40
+ wordmarkFontUrl: "/fonts/Tanker-400.woff2",
41
+ };
42
+ async function resizeWindow(width, height) {
43
+ if (!isTauri())
44
+ return;
45
+ try {
46
+ const win = getCurrentWindow();
47
+ await win.setSize(new LogicalSize(width, height));
48
+ await win.center();
49
+ }
50
+ catch (error) {
51
+ // Never swallow this silently. Tauri rejects setSize/center unless the capability grants
52
+ // core:window:allow-set-size and allow-center — and a swallowed rejection is invisible: every
53
+ // test passes while the real app ignores the resize and renders the gate at the full workspace
54
+ // size. That is exactly how this shipped wrong once (2026-07-17). The reveal must still proceed,
55
+ // so log rather than throw. logError, NOT logEvent: an event reaches the exported diagnostics
56
+ // bundle as an anonymous info-level `renderer_event`, which is its own kind of silence.
57
+ try {
58
+ logError("legal-gate:resize-failed");
59
+ }
60
+ catch {
61
+ console.error("legal-gate: window resize failed", error);
62
+ }
63
+ }
64
+ }
65
+ // The shell's `fullscreen` action only toggles, so leave fullscreen through the window API.
66
+ const exitFullscreen = () => getCurrentWindow().setFullscreen(false);
67
+ async function tryWindowAction(label, action) {
68
+ try {
69
+ await action();
70
+ }
71
+ catch (error) {
72
+ try {
73
+ logError(label);
74
+ }
75
+ catch {
76
+ console.error(`${label}: ${String(error)}`);
77
+ }
78
+ }
79
+ }
80
+ /** Put the first-run gate into its exact, fixed-size state before revealing the hidden window. */
81
+ async function prepareLegalGateWindow() {
82
+ if (!isTauri())
83
+ return;
84
+ const win = getShell().window;
85
+ // A prior native state (including macOS fullscreen) must not survive into the legal gate.
86
+ await tryWindowAction("legal-gate:fullscreen-exit-failed", exitFullscreen);
87
+ await tryWindowAction("legal-gate:unmaximize-failed", () => win.do("unmaximize"));
88
+ await tryWindowAction("legal-gate:resizable-failed", () => getCurrentWindow().setResizable(false));
89
+ await tryWindowAction("legal-gate:maximizable-failed", () => getCurrentWindow().setMaximizable(false));
90
+ await resizeWindow(GATE_WIDTH, GATE_HEIGHT);
91
+ }
92
+ /** Restore normal controls & maximize workspace before the accepted app shell mounts. */
93
+ async function prepareWorkspaceWindow() {
94
+ if (!isTauri())
95
+ return;
96
+ const win = getShell().window;
97
+ await tryWindowAction("workspace:fullscreen-exit-failed", exitFullscreen);
98
+ await tryWindowAction("workspace:resizable-failed", () => getCurrentWindow().setResizable(true));
99
+ await tryWindowAction("workspace:maximizable-failed", () => getCurrentWindow().setMaximizable(true));
100
+ await tryWindowAction("workspace:maximize-failed", () => win.do("maximize"));
101
+ }
102
+ async function destroyWindow() {
103
+ if (!isTauri())
104
+ return;
105
+ try {
106
+ await getCurrentWindow().destroy();
107
+ }
108
+ catch {
109
+ // Outside Tauri there is no window to destroy.
110
+ }
111
+ }
112
+ /**
113
+ * Top-level shell: renders the shared Right Suite legal gate in place of the document workspace
114
+ * until the acceptance receipt in settings is current, then swaps to <App/>. Owns the one call to
115
+ * useReadyShow() for BOTH paths — the gate's own window (960x560, fixed) must reveal itself just
116
+ * like the main app window does, or a real first-run user launching the installer-hidden window
117
+ * sees nothing at all.
118
+ */
119
+ export function AppRoot() {
120
+ const { settings, update, updateAsync } = useSettings();
121
+ // Browser QA runs against a fresh profile every launch, so the legal gate would otherwise block
122
+ // every automated run behind a manual click. QA mode is a deterministic harness, never a shipped
123
+ // build (isBrowserQaMode is false in production), so skip the gate there — mirrors how dev-native
124
+ // bypasses the license gate. Real users always see the gate until they accept.
125
+ // Browser QA normally bypasses the first-run gate so unattended document journeys can mount.
126
+ // The explicit qaLegal switch exercises the shipped gate itself with the same browser fixtures;
127
+ // it is only honored in QA/dev builds because isBrowserQaMode() is false in production.
128
+ const qaLegalGate = isBrowserQaMode() &&
129
+ typeof window !== "undefined" &&
130
+ new URLSearchParams(window.location.search).get("qaLegal") === "1";
131
+ const needsGate = (!isBrowserQaMode() || qaLegalGate) && !legalAcceptanceCurrent(settings);
132
+ // Configure native state before reveal. The gate is exact 960x560 and fixed; accepted/current
133
+ // workspace launches with normal controls and maximized geometry.
134
+ const beforeShow = useCallback(() => (needsGate ? prepareLegalGateWindow() : prepareWorkspaceWindow()), [needsGate]);
135
+ useReadyShow(beforeShow);
136
+ // Stable ports: onboarding reloads when either identity changes, so they read the live settings
137
+ // through refs instead of closing over each render's values.
138
+ const settingsRef = useRef(settings);
139
+ settingsRef.current = settings;
140
+ const updateRef = useRef(update);
141
+ updateRef.current = update;
142
+ const updateAsyncRef = useRef(updateAsync);
143
+ updateAsyncRef.current = updateAsync;
144
+ const onboardingSettings = useMemo(() => createOnboardingSettingsBackend(), []);
145
+ const legalReceipt = useMemo(() => ({
146
+ read: () => legalReceiptRecord(settingsRef.current),
147
+ write: async (record) => {
148
+ // Restore native controls & maximize BEFORE settings swaps in <App/>, so app never mounts in
149
+ // fixed legal-gate state even for a single frame.
150
+ await prepareWorkspaceWindow();
151
+ await updateAsyncRef.current(legalReceiptFields(record));
152
+ },
153
+ }), []);
154
+ if (!needsGate)
155
+ return _jsx(App, {});
156
+ // Onboarding's legal step comes first and wraps the shared LegalGate; with no further steps,
157
+ // accepting the receipt is the whole first run and the settings swap above mounts <App/>.
158
+ return (_jsx(Onboarding, { settings: onboardingSettings, legal: LEGAL_STEP, legalReceipt: legalReceipt, requiredVersion: REQUIRED_LEGAL_ACCEPTANCE_VERSION, requiredDocumentsHash: LEGAL_MATERIAL_SHA256, isAccepted: (state) => legalRecordCurrent(state.legalAcceptance), onComplete: () => { } }));
159
+ }
@@ -0,0 +1,2 @@
1
+ /** Layout shell: renders the sidebar, toolbar, document pane, and dialogs from the composed app state. */
2
+ export declare function AppShell(): import("react").JSX.Element;
@@ -0,0 +1,81 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { AppFrame, Plane } from "@rightkit/react-shell/react";
3
+ import { Sidebar } from "./Sidebar.js";
4
+ import { Toolbar } from "./Toolbar.js";
5
+ import { DocumentContextMenu } from "./DocumentContextMenu.js";
6
+ import { ToastViewport } from "./ToastViewport.js";
7
+ import { AppDialogsHost } from "./AppDialogsHost.js";
8
+ import { DocumentPane } from "./DocumentPane.js";
9
+ import { DropOverlay } from "./useFileDragOverlay.js";
10
+ import { useAppContext } from "./AppProvider.js";
11
+ /** Layout shell: renders the sidebar, toolbar, document pane, and dialogs from the composed app state. */
12
+ export function AppShell() {
13
+ const { dragOver, rootDragProps, distractionFree, activePath, openPathsSet, recents, pinnedPaths, pinnedEntries, activate, openRecent, openExplorerPath, onTogglePin, library, onOpenDialog, openUrl, openFromClipboard, newDocument, handleOpenSettings, setSidebarCollapsed, menuSlot, modeSlot, active, activeIndex, activeEditable, titleBarTitle, titleBarTitleFor, subscribeEdits, getEditSnapshot, getExternalSeq, sidebarCollapsed, isDirty, dirtyPaths, subscribeDirty, tabStripProps, view, docBarSlot, setDocBarSlot, inspectorOpen, toggleInspector, closeInspector, findBarEl, zoom, docs, restoringSession, openDocs, blockDrafts, livePaths, renderedPaths, views, contentScrollRef, viewState, onSave, setDocxMenu, registerPdfPrint, registerMarkdownExport, findMode, searchProvider, toggleFind, closeFind, onChangeView, registerSearchProviderFor, onOpenPathForRouter, htmlPropsFor, sourceViewStateRef, docxMenu, settings, update, docContextMenu, closeDocContextMenu, copyContents, paletteItems, settingsOpen, setSettingsOpen, paletteOpen, setPaletteOpen, helpOpen, setHelpOpen, openUrlDialog, setOpenUrlDialog, quitDirtyDocs, open, openLiveUrl, fullscreenConfirm } = useAppContext();
14
+ return (_jsx(AppFrame, { children: _jsxs("div", { className: "vr-app-root flex h-full w-full bg-[var(--chrome)] text-paper", ...rootDragProps, children: [dragOver && _jsx(DropOverlay, {}), _jsx("a", { href: "#vr-doc-pane", className: "vr-skip-link", children: "Skip to content" }), !distractionFree && (_jsx(Sidebar, { activePath: activePath, openPaths: openPathsSet, recents: recents, pinnedPaths: pinnedPaths, pinnedEntries: pinnedEntries, onActivate: activate, onOpenRecent: openRecent, onOpenPath: openExplorerPath, onTogglePin: onTogglePin, onTogglePinDir: library.onTogglePinDir, onClearRecents: library.onClearRecents, onOpenDialog: onOpenDialog, onOpenUrl: openUrl, onOpenClipboard: openFromClipboard, onNew: newDocument, onOpenSettings: handleOpenSettings, onCollapsedChange: setSidebarCollapsed, titlebarSlot: menuSlot })), _jsx(Plane, { className: "min-w-0 flex-1 overflow-visible", children: _jsxs("main", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [!distractionFree && (_jsx(Toolbar, { doc: active, title: titleBarTitle, compute: titleBarTitleFor, subscribeEdits: subscribeEdits, getEditSnapshot: getEditSnapshot, sidebarCollapsed: sidebarCollapsed, menuSlot: menuSlot, isDirty: isDirty, dirtyPaths: dirtyPaths, subscribeDirty: subscribeDirty, tabs: tabStripProps })), _jsx(DocumentPane, { active: active, activeIndex: activeIndex, activeEditable: activeEditable, view: view, distractionFree: distractionFree, docBarSlot: docBarSlot, setDocBarSlot: setDocBarSlot, modeSlot: modeSlot, inspectorOpen: inspectorOpen, toggleInspector: toggleInspector, closeInspector: closeInspector, findBarEl: findBarEl, zoom: zoom, openingPath: docs.openingPath, restoringSession: restoringSession, openDocs: openDocs, startPage: {
15
+ onNew: newDocument,
16
+ onOpenDialog,
17
+ onOpenUrl: openUrl,
18
+ onOpenClipboard: openFromClipboard,
19
+ recents,
20
+ onOpenRecent: openRecent,
21
+ }, blockDrafts: blockDrafts, router: {
22
+ mountedDocs: openDocs,
23
+ activePath,
24
+ livePaths,
25
+ renderedPaths,
26
+ views,
27
+ contentScrollRef,
28
+ onContentScroll: viewState.onContentScroll,
29
+ onDocumentWheel: zoom.onDocumentWheel,
30
+ subscribeEdits,
31
+ getEditSnapshot,
32
+ getExternalSeq,
33
+ sourceViewStateRef,
34
+ onTxtChange: docs.onTxtChange,
35
+ onSave,
36
+ onDocxSaveAs: docs.onDocxSaveAs,
37
+ onDocxSave: docs.onDocxSave,
38
+ onDocxChange: docs.onDocxChange,
39
+ docxSaver: docs.docxSaver,
40
+ imageSaver: docs.imageSaver,
41
+ docxSaversRef: docs.docxSaversRef,
42
+ pdfSaversRef: docs.pdfSaversRef,
43
+ pdfSavePlansRef: docs.pdfSavePlansRef,
44
+ imageSaversRef: docs.imageSaversRef,
45
+ setDocxMenu,
46
+ setPdfPrint: registerPdfPrint,
47
+ setMarkdownExport: registerMarkdownExport,
48
+ onImageChange: docs.onImageChange,
49
+ onPdfDirtyChange: docs.onPdfDirtyChange,
50
+ openImageSibling: docs.openImageSibling,
51
+ registerSearchProviderFor,
52
+ onPdfViewState: viewState.onPdfViewState,
53
+ findBarEl: null,
54
+ findMode,
55
+ canReplaceSearch: !!searchProvider?.canReplace,
56
+ onChangeView,
57
+ toggleFind,
58
+ closeFind,
59
+ onOpenPath: onOpenPathForRouter,
60
+ trackMdxGrant: docs.trackMdxGrant,
61
+ htmlPropsFor,
62
+ }, subscribeEdits: subscribeEdits, getEditSnapshot: getEditSnapshot, dirtyPaths: dirtyPaths, isDirty: isDirty, subscribeDirty: subscribeDirty, docxMenu: docxMenu, onHtmlSave: docs.onHtmlSaveShortcut, onSave: onSave, settings: settings, update: update })] }) }), docContextMenu && (_jsx(DocumentContextMenu, { menu: docContextMenu, onClose: closeDocContextMenu, onCopyContents: copyContents })), _jsx(ToastViewport, {}), _jsx(AppDialogsHost, { docs: docs, openDocs: openDocs, quitDirtyDocs: quitDirtyDocs, paletteItems: paletteItems, overlays: {
63
+ settingsOpen,
64
+ setSettingsOpen,
65
+ paletteOpen,
66
+ setPaletteOpen,
67
+ helpOpen,
68
+ setHelpOpen,
69
+ openUrlDialog,
70
+ setOpenUrlDialog,
71
+ }, onHistoryPurged: library.onHistoryPurged, open: open, openLiveUrl: openLiveUrl, viewConfirm: viewState.pendingViewChange
72
+ ? {
73
+ onDone: () => void viewState.confirmViewChange("done"),
74
+ onDiscard: () => void viewState.confirmViewChange("discard"),
75
+ onStay: () => void viewState.confirmViewChange("stay"),
76
+ error: viewState.pendingViewChange.drafts.find((d) => d.error)?.error ??
77
+ viewState.pendingViewChange.drafts.find((d) => d.reason)?.reason ??
78
+ null,
79
+ }
80
+ : null, fullscreenConfirm: fullscreenConfirm })] }) }));
81
+ }
@@ -0,0 +1,13 @@
1
+ import { type ReactNode } from "react";
2
+ export interface PaletteItem {
3
+ id: string;
4
+ label: string;
5
+ hint?: string;
6
+ icon?: ReactNode;
7
+ run: () => void;
8
+ }
9
+ /** Ctrl+Shift+P quick-open + command runner. Thin adapter over the shell's CommandPalette. */
10
+ export declare function CommandPalette({ items, onClose }: {
11
+ items: PaletteItem[];
12
+ onClose: () => void;
13
+ }): import("react").JSX.Element;
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo, useRef } from "react";
3
+ import { MagnifyingGlass } from "@phosphor-icons/react/dist/icons/MagnifyingGlass";
4
+ import { rankItems as rankByScore } from "@rightkit/platform-ui/headless";
5
+ import { CommandPalette as ShellCommandPalette } from "@rightkit/react-shell/react";
6
+ const isDocument = (it) => it.id.startsWith("tab:") || it.id.startsWith("recent:");
7
+ // Keeps the app's ranking: subsequence score within each section, Documents (open tabs + recents)
8
+ // ahead of Commands. The shell groups by first-seen order, so documents must come first here.
9
+ function rankPaletteItems(commands, query, limit) {
10
+ const ranked = rankByScore(commands, query);
11
+ const documents = ranked.filter((c) => c.group === "Documents");
12
+ const rest = ranked.filter((c) => c.group !== "Documents");
13
+ return [...documents, ...rest].slice(0, limit);
14
+ }
15
+ /** Ctrl+Shift+P quick-open + command runner. Thin adapter over the shell's CommandPalette. */
16
+ export function CommandPalette({ items, onClose }) {
17
+ // A command runs once per open palette: a second Enter or click during the exit animation is dropped.
18
+ const ran = useRef(false);
19
+ const commands = useMemo(() => items.map((it) => ({
20
+ id: it.id,
21
+ label: it.label,
22
+ hint: it.hint,
23
+ icon: it.icon,
24
+ group: isDocument(it) ? "Documents" : "Commands",
25
+ run: () => {
26
+ if (ran.current)
27
+ return;
28
+ ran.current = true;
29
+ it.run();
30
+ },
31
+ })), [items]);
32
+ return (_jsx(ShellCommandPalette, { commands: commands, onClose: onClose, rank: rankPaletteItems, limit: 50, paletteWidth: 680, enterDelayMs: 80, labels: {
33
+ placeholder: "Go to a file or run a command…",
34
+ inputAriaLabel: "Search files and commands",
35
+ title: "Command palette",
36
+ results: "Results",
37
+ empty: "No matches.",
38
+ }, className: "vr-pop vr-pop-modal vr-glass-panel max-w-[92vw] overflow-hidden rounded-[28px]", slots: {
39
+ field: "h-[62px] gap-3 border-b border-line px-5",
40
+ input: "vr-focus min-w-0 flex-1 bg-transparent font-sans text-[22px] text-paper placeholder:text-muted-2",
41
+ list: "max-h-[min(56vh,520px)] overflow-auto px-2.5 pb-2.5 pt-1.5",
42
+ group: "px-3 pb-1 pt-2.5 font-sans text-chrome-xs font-semibold text-muted-2",
43
+ option: "vr-palette-opt vr-focus h-[42px] w-full gap-3 rounded-xl px-3 font-sans text-paper/85 hover:bg-ink/30 [&.is-active]:bg-copper/[0.16] [&.is-active]:text-paper",
44
+ icon: "h-7 w-7 rounded-lg bg-ink/40 text-muted [.is-active_&]:bg-copper/20 [.is-active_&]:text-copper-hi",
45
+ empty: "px-4 py-3 font-sans text-xs text-muted-2",
46
+ }, searchIcon: _jsx(MagnifyingGlass, { size: 20, weight: "regular", "aria-hidden": "true", className: "shrink-0 text-muted" }) }));
47
+ }
@@ -0,0 +1,36 @@
1
+ import type { LoadedDocument, ViewMode } from "@rightkit/document-core/documents/types";
2
+ import type { DocxMenuApi } from "@rightkit/docx-editor/documents/docx/menuApi";
3
+ import { type NativeMenuCommand } from "@rightkit/document-core/app/shell/nativeMenu";
4
+ interface Props {
5
+ doc: LoadedDocument;
6
+ view: ViewMode;
7
+ onSave: () => void;
8
+ onSaveAs: () => void;
9
+ onPrint: () => void;
10
+ onClose: () => void;
11
+ onChangeView: (v: ViewMode) => void;
12
+ onEditImageExternal?: () => void;
13
+ /** Present once a DOCX editor is mounted — drives docx's menus + save/print. */
14
+ docxMenu?: DocxMenuApi | null;
15
+ /** Wave 2 Read mode — menu/view-switch editing affordances hide; file + viewing actions stay. */
16
+ readOnly?: boolean;
17
+ }
18
+ export declare const DocumentMenus: import("react").MemoExoticComponent<typeof DocumentMenusImpl>;
19
+ declare function DocumentMenusImpl({ doc, view, onSave, onSaveAs, onPrint, onClose, onChangeView, onEditImageExternal, docxMenu, readOnly, }: Pick<Props, "doc" | "view" | "onSave" | "onSaveAs" | "onPrint" | "onClose" | "onChangeView" | "onEditImageExternal" | "docxMenu" | "readOnly">): import("react").JSX.Element | null;
20
+ /** Commands the in-window menus offer for this document, for the macOS menu bar. Mirrors the
21
+ * visibility rules of DocxMenus/TextMenus below so both platforms expose the same actions. */
22
+ export declare function documentMenuCommands({ doc, view, onChangeView, onEditImageExternal, docxMenu, readOnly, spellcheck, wordWrap, toggleSpellcheck, toggleWordWrap, }: {
23
+ doc: LoadedDocument;
24
+ view: ViewMode;
25
+ onChangeView: (v: ViewMode) => void;
26
+ onEditImageExternal?: () => void;
27
+ docxMenu?: DocxMenuApi | null;
28
+ readOnly?: boolean;
29
+ spellcheck: boolean;
30
+ wordWrap: boolean;
31
+ toggleSpellcheck: () => void;
32
+ toggleWordWrap: () => void;
33
+ }): NativeMenuCommand[];
34
+ export declare const DocumentModeControls: import("react").MemoExoticComponent<typeof DocumentModeControlsImpl>;
35
+ declare function DocumentModeControlsImpl({ doc, view, onChangeView, readOnly, }: Pick<Props, "doc" | "view" | "onChangeView" | "readOnly">): import("react").JSX.Element;
36
+ export {};