@bendyline/docblocks-react 2.0.0 → 2.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 (310) hide show
  1. package/README.md +18 -3
  2. package/dist/ExportDialog-VYATD5UC.js +9 -0
  3. package/dist/{ExportToolbarControls-D2YDWOXW.js → ExportToolbarControls-5HUE3LSX.js} +206 -42
  4. package/dist/{GitToolbarControl-LMIR4R7I.js → GitToolbarControl-FW3BZFXV.js} +62 -44
  5. package/dist/{GitUI-KGF5MSNV.js → GitUI-GMH3PAYL.js} +225 -141
  6. package/dist/{LazyEditorShell-EF2BWRXU.js → LazyEditorShell-RF54B5UD.js} +0 -1
  7. package/dist/ShareDialog-PAMOQQFB.js +212 -0
  8. package/dist/chunk-3CZ27FOA.js +359 -0
  9. package/dist/chunk-3QSZY74C.js +255 -0
  10. package/{src/Export/export-destination.ts → dist/chunk-BI7NVU6T.js} +16 -15
  11. package/dist/{chunk-VHDP4IPL.js → chunk-BPGEBGAN.js} +0 -1
  12. package/dist/{chunk-DD4VFJQI.js → chunk-EBWYGTN7.js} +2 -1
  13. package/dist/{chunk-ZI56BNB7.js → chunk-GHQ4X7KM.js} +27 -7
  14. package/dist/{chunk-5A4KEWKT.js → chunk-HFYPTTCH.js} +0 -1
  15. package/dist/chunk-LG6HAWCK.js +109 -0
  16. package/dist/chunk-TFMO7EVO.js +88 -0
  17. package/dist/{chunk-4XXSWN3T.js → chunk-YBEYTVU2.js} +0 -1
  18. package/dist/editor.d.ts +5 -4
  19. package/dist/editor.js +8 -70
  20. package/dist/export/index.d.ts +24 -8
  21. package/dist/export/index.js +10 -6
  22. package/dist/index.d.ts +355 -21
  23. package/dist/index.js +6419 -21
  24. package/dist/run-export-Z5BVFLIR.js +9 -0
  25. package/dist/settings/index.d.ts +9 -1
  26. package/dist/settings/index.js +6 -5
  27. package/package.json +18 -13
  28. package/src/styles/docblocks.css +985 -35
  29. package/dist/AppMenu/AppMenu.d.ts +0 -53
  30. package/dist/AppMenu/AppMenu.d.ts.map +0 -1
  31. package/dist/AppMenu/AppMenu.js +0 -67
  32. package/dist/AppMenu/AppMenu.js.map +0 -1
  33. package/dist/AppMenu/index.d.ts +0 -3
  34. package/dist/AppMenu/index.d.ts.map +0 -1
  35. package/dist/AppMenu/index.js +0 -2
  36. package/dist/AppMenu/index.js.map +0 -1
  37. package/dist/DocBlocksShell/DocBlocksShell.d.ts +0 -49
  38. package/dist/DocBlocksShell/DocBlocksShell.d.ts.map +0 -1
  39. package/dist/DocBlocksShell/DocBlocksShell.js +0 -2730
  40. package/dist/DocBlocksShell/DocBlocksShell.js.map +0 -1
  41. package/dist/DocBlocksShell/LazyEditorShell.d.ts +0 -3
  42. package/dist/DocBlocksShell/LazyEditorShell.d.ts.map +0 -1
  43. package/dist/DocBlocksShell/LazyEditorShell.js +0 -3
  44. package/dist/DocBlocksShell/LazyEditorShell.js.map +0 -1
  45. package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts +0 -13
  46. package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts.map +0 -1
  47. package/dist/DocBlocksShell/UpdateAvailableNotice.js +0 -16
  48. package/dist/DocBlocksShell/UpdateAvailableNotice.js.map +0 -1
  49. package/dist/DocBlocksShell/document-title.d.ts +0 -3
  50. package/dist/DocBlocksShell/document-title.d.ts.map +0 -1
  51. package/dist/DocBlocksShell/document-title.js +0 -17
  52. package/dist/DocBlocksShell/document-title.js.map +0 -1
  53. package/dist/DocBlocksShell/index.d.ts +0 -3
  54. package/dist/DocBlocksShell/index.d.ts.map +0 -1
  55. package/dist/DocBlocksShell/index.js +0 -2
  56. package/dist/DocBlocksShell/index.js.map +0 -1
  57. package/dist/DocBlocksShell/workspace-authority-barrier.d.ts +0 -14
  58. package/dist/DocBlocksShell/workspace-authority-barrier.d.ts.map +0 -1
  59. package/dist/DocBlocksShell/workspace-authority-barrier.js +0 -23
  60. package/dist/DocBlocksShell/workspace-authority-barrier.js.map +0 -1
  61. package/dist/Export/DeferredExportToolbarControls.d.ts +0 -5
  62. package/dist/Export/DeferredExportToolbarControls.d.ts.map +0 -1
  63. package/dist/Export/DeferredExportToolbarControls.js +0 -10
  64. package/dist/Export/DeferredExportToolbarControls.js.map +0 -1
  65. package/dist/Export/ExportDialog.d.ts +0 -25
  66. package/dist/Export/ExportDialog.d.ts.map +0 -1
  67. package/dist/Export/ExportDialog.js +0 -160
  68. package/dist/Export/ExportDialog.js.map +0 -1
  69. package/dist/Export/ExportToolbarControls.d.ts +0 -37
  70. package/dist/Export/ExportToolbarControls.d.ts.map +0 -1
  71. package/dist/Export/ExportToolbarControls.js +0 -285
  72. package/dist/Export/ExportToolbarControls.js.map +0 -1
  73. package/dist/Export/export-destination.d.ts +0 -3
  74. package/dist/Export/export-destination.d.ts.map +0 -1
  75. package/dist/Export/export-destination.js +0 -32
  76. package/dist/Export/export-destination.js.map +0 -1
  77. package/dist/Export/export-options.d.ts +0 -53
  78. package/dist/Export/export-options.d.ts.map +0 -1
  79. package/dist/Export/export-options.js +0 -49
  80. package/dist/Export/export-options.js.map +0 -1
  81. package/dist/Export/index.d.ts +0 -10
  82. package/dist/Export/index.d.ts.map +0 -1
  83. package/dist/Export/index.js +0 -6
  84. package/dist/Export/index.js.map +0 -1
  85. package/dist/Export/public-api.d.ts +0 -12
  86. package/dist/Export/public-api.d.ts.map +0 -1
  87. package/dist/Export/public-api.js +0 -9
  88. package/dist/Export/public-api.js.map +0 -1
  89. package/dist/Export/run-export.d.ts +0 -10
  90. package/dist/Export/run-export.d.ts.map +0 -1
  91. package/dist/Export/run-export.js +0 -313
  92. package/dist/Export/run-export.js.map +0 -1
  93. package/dist/Export/transform-summaries.d.ts +0 -7
  94. package/dist/Export/transform-summaries.d.ts.map +0 -1
  95. package/dist/Export/transform-summaries.js +0 -6
  96. package/dist/Export/transform-summaries.js.map +0 -1
  97. package/dist/ExportDialog-MEUISWZX.js +0 -9
  98. package/dist/ExportDialog-MEUISWZX.js.map +0 -1
  99. package/dist/ExportToolbarControls-D2YDWOXW.js.map +0 -1
  100. package/dist/FileExplorer/FileExplorer.d.ts +0 -43
  101. package/dist/FileExplorer/FileExplorer.d.ts.map +0 -1
  102. package/dist/FileExplorer/FileExplorer.js +0 -315
  103. package/dist/FileExplorer/FileExplorer.js.map +0 -1
  104. package/dist/FileExplorer/FileTreeNode.d.ts +0 -39
  105. package/dist/FileExplorer/FileTreeNode.d.ts.map +0 -1
  106. package/dist/FileExplorer/FileTreeNode.js +0 -131
  107. package/dist/FileExplorer/FileTreeNode.js.map +0 -1
  108. package/dist/FileExplorer/index.d.ts +0 -6
  109. package/dist/FileExplorer/index.d.ts.map +0 -1
  110. package/dist/FileExplorer/index.js +0 -4
  111. package/dist/FileExplorer/index.js.map +0 -1
  112. package/dist/FileExplorer/useFileTree.d.ts +0 -37
  113. package/dist/FileExplorer/useFileTree.d.ts.map +0 -1
  114. package/dist/FileExplorer/useFileTree.js +0 -284
  115. package/dist/FileExplorer/useFileTree.js.map +0 -1
  116. package/dist/Git/GitAuthGuidanceDialog.d.ts +0 -18
  117. package/dist/Git/GitAuthGuidanceDialog.d.ts.map +0 -1
  118. package/dist/Git/GitAuthGuidanceDialog.js +0 -27
  119. package/dist/Git/GitAuthGuidanceDialog.js.map +0 -1
  120. package/dist/Git/GitBranchesDialog.d.ts +0 -13
  121. package/dist/Git/GitBranchesDialog.d.ts.map +0 -1
  122. package/dist/Git/GitBranchesDialog.js +0 -59
  123. package/dist/Git/GitBranchesDialog.js.map +0 -1
  124. package/dist/Git/GitCloneDialog.d.ts +0 -14
  125. package/dist/Git/GitCloneDialog.d.ts.map +0 -1
  126. package/dist/Git/GitCloneDialog.js +0 -79
  127. package/dist/Git/GitCloneDialog.js.map +0 -1
  128. package/dist/Git/GitCommitDialog.d.ts +0 -12
  129. package/dist/Git/GitCommitDialog.d.ts.map +0 -1
  130. package/dist/Git/GitCommitDialog.js +0 -38
  131. package/dist/Git/GitCommitDialog.js.map +0 -1
  132. package/dist/Git/GitConflictsDialog.d.ts +0 -12
  133. package/dist/Git/GitConflictsDialog.d.ts.map +0 -1
  134. package/dist/Git/GitConflictsDialog.js +0 -17
  135. package/dist/Git/GitConflictsDialog.js.map +0 -1
  136. package/dist/Git/GitContext.d.ts +0 -89
  137. package/dist/Git/GitContext.d.ts.map +0 -1
  138. package/dist/Git/GitContext.js +0 -15
  139. package/dist/Git/GitContext.js.map +0 -1
  140. package/dist/Git/GitDiffDialog.d.ts +0 -20
  141. package/dist/Git/GitDiffDialog.d.ts.map +0 -1
  142. package/dist/Git/GitDiffDialog.js +0 -100
  143. package/dist/Git/GitDiffDialog.js.map +0 -1
  144. package/dist/Git/GitDiffView.d.ts +0 -23
  145. package/dist/Git/GitDiffView.d.ts.map +0 -1
  146. package/dist/Git/GitDiffView.js +0 -77
  147. package/dist/Git/GitDiffView.js.map +0 -1
  148. package/dist/Git/GitHistoryDialog.d.ts +0 -15
  149. package/dist/Git/GitHistoryDialog.d.ts.map +0 -1
  150. package/dist/Git/GitHistoryDialog.js +0 -107
  151. package/dist/Git/GitHistoryDialog.js.map +0 -1
  152. package/dist/Git/GitStatusBar.d.ts +0 -8
  153. package/dist/Git/GitStatusBar.d.ts.map +0 -1
  154. package/dist/Git/GitStatusBar.js +0 -49
  155. package/dist/Git/GitStatusBar.js.map +0 -1
  156. package/dist/Git/GitToolbarControl.d.ts +0 -15
  157. package/dist/Git/GitToolbarControl.d.ts.map +0 -1
  158. package/dist/Git/GitToolbarControl.js +0 -51
  159. package/dist/Git/GitToolbarControl.js.map +0 -1
  160. package/dist/Git/GitUI.d.ts +0 -14
  161. package/dist/Git/GitUI.d.ts.map +0 -1
  162. package/dist/Git/GitUI.js +0 -21
  163. package/dist/Git/GitUI.js.map +0 -1
  164. package/dist/Git/commit-selection.d.ts +0 -22
  165. package/dist/Git/commit-selection.d.ts.map +0 -1
  166. package/dist/Git/commit-selection.js +0 -47
  167. package/dist/Git/commit-selection.js.map +0 -1
  168. package/dist/Git/git-clone-utils.d.ts +0 -8
  169. package/dist/Git/git-clone-utils.d.ts.map +0 -1
  170. package/dist/Git/git-clone-utils.js +0 -26
  171. package/dist/Git/git-clone-utils.js.map +0 -1
  172. package/dist/Git/git-status.d.ts +0 -24
  173. package/dist/Git/git-status.d.ts.map +0 -1
  174. package/dist/Git/git-status.js +0 -105
  175. package/dist/Git/git-status.js.map +0 -1
  176. package/dist/Git/useGit.d.ts +0 -15
  177. package/dist/Git/useGit.d.ts.map +0 -1
  178. package/dist/Git/useGit.js +0 -206
  179. package/dist/Git/useGit.js.map +0 -1
  180. package/dist/Git/useGitStatus.d.ts +0 -17
  181. package/dist/Git/useGitStatus.d.ts.map +0 -1
  182. package/dist/Git/useGitStatus.js +0 -63
  183. package/dist/Git/useGitStatus.js.map +0 -1
  184. package/dist/GitToolbarControl-LMIR4R7I.js.map +0 -1
  185. package/dist/GitUI-KGF5MSNV.js.map +0 -1
  186. package/dist/LazyEditorShell-EF2BWRXU.js.map +0 -1
  187. package/dist/Settings/Settings.d.ts +0 -23
  188. package/dist/Settings/Settings.d.ts.map +0 -1
  189. package/dist/Settings/Settings.js +0 -22
  190. package/dist/Settings/Settings.js.map +0 -1
  191. package/dist/Settings/public-api.d.ts +0 -3
  192. package/dist/Settings/public-api.d.ts.map +0 -1
  193. package/dist/Settings/public-api.js +0 -2
  194. package/dist/Settings/public-api.js.map +0 -1
  195. package/dist/WorkspacePicker/WorkspacePicker.d.ts +0 -22
  196. package/dist/WorkspacePicker/WorkspacePicker.d.ts.map +0 -1
  197. package/dist/WorkspacePicker/WorkspacePicker.js +0 -74
  198. package/dist/WorkspacePicker/WorkspacePicker.js.map +0 -1
  199. package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts +0 -11
  200. package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts.map +0 -1
  201. package/dist/WorkspacePicker/WorkspaceSettingsButton.js +0 -27
  202. package/dist/WorkspacePicker/WorkspaceSettingsButton.js.map +0 -1
  203. package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts +0 -20
  204. package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts.map +0 -1
  205. package/dist/WorkspacePicker/WorkspaceSettingsDialog.js +0 -36
  206. package/dist/WorkspacePicker/WorkspaceSettingsDialog.js.map +0 -1
  207. package/dist/WorkspacePicker/index.d.ts +0 -3
  208. package/dist/WorkspacePicker/index.d.ts.map +0 -1
  209. package/dist/WorkspacePicker/index.js +0 -2
  210. package/dist/WorkspacePicker/index.js.map +0 -1
  211. package/dist/chunk-3SAXDU2U.js +0 -157
  212. package/dist/chunk-3SAXDU2U.js.map +0 -1
  213. package/dist/chunk-4XXSWN3T.js.map +0 -1
  214. package/dist/chunk-5A4KEWKT.js.map +0 -1
  215. package/dist/chunk-AOVTHZU7.js +0 -321
  216. package/dist/chunk-AOVTHZU7.js.map +0 -1
  217. package/dist/chunk-DD4VFJQI.js.map +0 -1
  218. package/dist/chunk-GSNZSCIK.js +0 -55
  219. package/dist/chunk-GSNZSCIK.js.map +0 -1
  220. package/dist/chunk-VHDP4IPL.js.map +0 -1
  221. package/dist/chunk-ZI56BNB7.js.map +0 -1
  222. package/dist/components/Dialog.d.ts +0 -22
  223. package/dist/components/Dialog.d.ts.map +0 -1
  224. package/dist/components/Dialog.js +0 -33
  225. package/dist/components/Dialog.js.map +0 -1
  226. package/dist/editor.d.ts.map +0 -1
  227. package/dist/editor.js.map +0 -1
  228. package/dist/export/index.js.map +0 -1
  229. package/dist/hooks/index.d.ts +0 -3
  230. package/dist/hooks/index.d.ts.map +0 -1
  231. package/dist/hooks/index.js +0 -2
  232. package/dist/hooks/index.js.map +0 -1
  233. package/dist/hooks/useDocumentSession.d.ts +0 -16
  234. package/dist/hooks/useDocumentSession.d.ts.map +0 -1
  235. package/dist/hooks/useDocumentSession.js +0 -18
  236. package/dist/hooks/useDocumentSession.js.map +0 -1
  237. package/dist/icons.d.ts +0 -12
  238. package/dist/icons.d.ts.map +0 -1
  239. package/dist/icons.js +0 -28
  240. package/dist/icons.js.map +0 -1
  241. package/dist/index.d.ts.map +0 -1
  242. package/dist/index.js.map +0 -1
  243. package/dist/preferences/theme.d.ts +0 -18
  244. package/dist/preferences/theme.d.ts.map +0 -1
  245. package/dist/preferences/theme.js +0 -63
  246. package/dist/preferences/theme.js.map +0 -1
  247. package/dist/preferences/versioning.d.ts +0 -27
  248. package/dist/preferences/versioning.d.ts.map +0 -1
  249. package/dist/preferences/versioning.js +0 -62
  250. package/dist/preferences/versioning.js.map +0 -1
  251. package/dist/provider-lease.d.ts +0 -10
  252. package/dist/provider-lease.d.ts.map +0 -1
  253. package/dist/provider-lease.js +0 -42
  254. package/dist/provider-lease.js.map +0 -1
  255. package/dist/run-export-ICTZITXC.js +0 -10
  256. package/dist/run-export-ICTZITXC.js.map +0 -1
  257. package/dist/settings/index.js.map +0 -1
  258. package/src/AppMenu/AppMenu.tsx +0 -334
  259. package/src/AppMenu/index.ts +0 -2
  260. package/src/DocBlocksShell/DocBlocksShell.tsx +0 -3398
  261. package/src/DocBlocksShell/LazyEditorShell.ts +0 -2
  262. package/src/DocBlocksShell/UpdateAvailableNotice.tsx +0 -60
  263. package/src/DocBlocksShell/document-title.ts +0 -19
  264. package/src/DocBlocksShell/index.ts +0 -2
  265. package/src/DocBlocksShell/workspace-authority-barrier.ts +0 -26
  266. package/src/Export/DeferredExportToolbarControls.tsx +0 -23
  267. package/src/Export/ExportDialog.tsx +0 -437
  268. package/src/Export/ExportToolbarControls.tsx +0 -511
  269. package/src/Export/export-options.ts +0 -99
  270. package/src/Export/index.ts +0 -19
  271. package/src/Export/public-api.ts +0 -17
  272. package/src/Export/run-export.ts +0 -374
  273. package/src/Export/transform-summaries.ts +0 -14
  274. package/src/FileExplorer/FileExplorer.tsx +0 -528
  275. package/src/FileExplorer/FileTreeNode.tsx +0 -306
  276. package/src/FileExplorer/index.ts +0 -5
  277. package/src/FileExplorer/useFileTree.ts +0 -352
  278. package/src/Git/GitAuthGuidanceDialog.tsx +0 -84
  279. package/src/Git/GitBranchesDialog.tsx +0 -144
  280. package/src/Git/GitCloneDialog.tsx +0 -200
  281. package/src/Git/GitCommitDialog.tsx +0 -119
  282. package/src/Git/GitConflictsDialog.tsx +0 -62
  283. package/src/Git/GitContext.tsx +0 -88
  284. package/src/Git/GitDiffDialog.tsx +0 -147
  285. package/src/Git/GitDiffView.tsx +0 -105
  286. package/src/Git/GitHistoryDialog.tsx +0 -195
  287. package/src/Git/GitStatusBar.tsx +0 -157
  288. package/src/Git/GitToolbarControl.tsx +0 -123
  289. package/src/Git/GitUI.tsx +0 -68
  290. package/src/Git/commit-selection.ts +0 -63
  291. package/src/Git/git-clone-utils.ts +0 -23
  292. package/src/Git/git-status.ts +0 -113
  293. package/src/Git/useGit.ts +0 -279
  294. package/src/Git/useGitStatus.ts +0 -78
  295. package/src/Settings/Settings.tsx +0 -118
  296. package/src/Settings/public-api.ts +0 -8
  297. package/src/WorkspacePicker/WorkspacePicker.tsx +0 -191
  298. package/src/WorkspacePicker/WorkspaceSettingsButton.tsx +0 -88
  299. package/src/WorkspacePicker/WorkspaceSettingsDialog.tsx +0 -121
  300. package/src/WorkspacePicker/index.ts +0 -2
  301. package/src/components/Dialog.tsx +0 -81
  302. package/src/editor.ts +0 -72
  303. package/src/hooks/index.ts +0 -2
  304. package/src/hooks/useDocumentSession.ts +0 -37
  305. package/src/icons.tsx +0 -48
  306. package/src/index.ts +0 -61
  307. package/src/preferences/theme.ts +0 -67
  308. package/src/preferences/versioning.ts +0 -69
  309. package/src/provider-lease.ts +0 -52
  310. package/src/types/pwa-dom.d.ts +0 -31
@@ -1,78 +0,0 @@
1
- /**
2
- * useGitStatus — subscribes to the host's owner-scoped repository stream.
3
- *
4
- * Dedupes identical payloads so a permanently-dirty working tree (normal
5
- * under the manual-commit model) doesn't repaint the tree on every push
6
- * from the main process.
7
- */
8
-
9
- import { useCallback, useEffect, useRef, useState } from 'react';
10
- import type { DocBlocksHostGitAPI, GitStatus } from '@bendyline/docblocks/host';
11
-
12
- const SCHEDULE_REFRESH_MS = 1500;
13
-
14
- function statusKey(status: GitStatus): string {
15
- return JSON.stringify(status);
16
- }
17
-
18
- export interface UseGitStatusResult {
19
- status: GitStatus | null;
20
- /** Fetch a fresh status immediately (after a renderer-initiated git op). */
21
- refresh: () => void;
22
- /** Trailing-debounced refresh (after autosave writes). */
23
- scheduleRefresh: () => void;
24
- }
25
-
26
- export function useGitStatus(
27
- gitApi: DocBlocksHostGitAPI | null,
28
- repositoryId: string | null,
29
- enabled: boolean,
30
- ): UseGitStatusResult {
31
- const [status, setStatus] = useState<GitStatus | null>(null);
32
- const lastKeyRef = useRef<string | null>(null);
33
- const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
34
-
35
- const apply = useCallback((next: GitStatus) => {
36
- const key = statusKey(next);
37
- if (key === lastKeyRef.current) return;
38
- lastKeyRef.current = key;
39
- setStatus(next);
40
- }, []);
41
-
42
- useEffect(() => {
43
- lastKeyRef.current = null;
44
- setStatus(null);
45
- if (!gitApi || !repositoryId || !enabled) return;
46
- let cancelled = false;
47
- const unsubscribe = gitApi.onStatusChanged(repositoryId, (next) => {
48
- if (!cancelled) apply(next);
49
- });
50
- return () => {
51
- cancelled = true;
52
- unsubscribe();
53
- };
54
- }, [gitApi, repositoryId, enabled, apply]);
55
-
56
- const refresh = useCallback(() => {
57
- if (!gitApi || !repositoryId || !enabled) return;
58
- void gitApi.status(repositoryId).then((result) => {
59
- if (result.ok) apply(result.value);
60
- });
61
- }, [gitApi, repositoryId, enabled, apply]);
62
-
63
- const scheduleRefresh = useCallback(() => {
64
- if (timerRef.current) clearTimeout(timerRef.current);
65
- timerRef.current = setTimeout(() => {
66
- timerRef.current = null;
67
- refresh();
68
- }, SCHEDULE_REFRESH_MS);
69
- }, [refresh]);
70
-
71
- useEffect(() => {
72
- return () => {
73
- if (timerRef.current) clearTimeout(timerRef.current);
74
- };
75
- }, []);
76
-
77
- return { status, refresh, scheduleRefresh };
78
- }
@@ -1,118 +0,0 @@
1
- /** Shared controls used by the app and host-specific DocBlocks settings dialogs. */
2
-
3
- import type { ReactNode } from 'react';
4
- import { Dialog } from '../components/Dialog.js';
5
- import { ACCENT_COLORS, type AccentColor, type ThemePreference } from '../preferences/theme.js';
6
-
7
- export type { AccentColor, ThemePreference } from '../preferences/theme.js';
8
-
9
- const ACCENT_LABELS: Record<AccentColor, string> = {
10
- brown: 'Brown',
11
- green: 'Green',
12
- blue: 'Blue',
13
- purple: 'Purple',
14
- maroon: 'Maroon',
15
- orange: 'Orange',
16
- gray: 'Gray',
17
- };
18
-
19
- export interface SettingsDialogProps {
20
- title?: string;
21
- onClose: () => void;
22
- children: ReactNode;
23
- }
24
-
25
- export function SettingsDialog({ title = 'Settings', onClose, children }: SettingsDialogProps) {
26
- return (
27
- <Dialog title={title} onClose={onClose}>
28
- {children}
29
- </Dialog>
30
- );
31
- }
32
-
33
- export interface ThemeSettingsProps {
34
- value: ThemePreference;
35
- onChange: (theme: ThemePreference) => void;
36
- name?: string;
37
- }
38
-
39
- export function ThemeSettings({ value, onChange, name = 'theme' }: ThemeSettingsProps) {
40
- return (
41
- <fieldset className="db-settings-fieldset">
42
- <legend className="db-settings-legend">Theme</legend>
43
- <label className="db-settings-radio">
44
- <input
45
- type="radio"
46
- name={name}
47
- value="auto"
48
- checked={value === 'auto'}
49
- onChange={() => onChange('auto')}
50
- />
51
- System default
52
- </label>
53
- <label className="db-settings-radio">
54
- <input
55
- type="radio"
56
- name={name}
57
- value="light"
58
- checked={value === 'light'}
59
- onChange={() => onChange('light')}
60
- />
61
- Light
62
- </label>
63
- <label className="db-settings-radio">
64
- <input
65
- type="radio"
66
- name={name}
67
- value="dark"
68
- checked={value === 'dark'}
69
- onChange={() => onChange('dark')}
70
- />
71
- Dark
72
- </label>
73
- </fieldset>
74
- );
75
- }
76
-
77
- export interface AccentColorSettingsProps {
78
- value: AccentColor;
79
- onChange: (color: AccentColor) => void;
80
- name?: string;
81
- }
82
-
83
- export function AccentColorSettings({
84
- value,
85
- onChange,
86
- name = 'accent-color',
87
- }: AccentColorSettingsProps) {
88
- return (
89
- <fieldset className="db-settings-fieldset">
90
- <legend className="db-settings-legend">Accent color</legend>
91
- <p className="db-settings-hint">Used in both light and dark appearances.</p>
92
- <div className="db-settings-accent-grid">
93
- {ACCENT_COLORS.map((color) => (
94
- <label
95
- className={`db-settings-accent${
96
- value === color ? ' db-settings-accent--selected' : ''
97
- }`}
98
- key={color}
99
- >
100
- <input
101
- className="db-settings-accent-input"
102
- type="radio"
103
- name={name}
104
- value={color}
105
- checked={value === color}
106
- onChange={() => onChange(color)}
107
- />
108
- <span
109
- className={`db-settings-accent-swatch db-settings-accent-swatch--${color}`}
110
- aria-hidden="true"
111
- />
112
- <span>{ACCENT_LABELS[color]}</span>
113
- </label>
114
- ))}
115
- </div>
116
- </fieldset>
117
- );
118
- }
@@ -1,8 +0,0 @@
1
- export { AccentColorSettings, SettingsDialog, ThemeSettings } from './Settings.js';
2
- export type {
3
- AccentColor,
4
- AccentColorSettingsProps,
5
- SettingsDialogProps,
6
- ThemePreference,
7
- ThemeSettingsProps,
8
- } from './Settings.js';
@@ -1,191 +0,0 @@
1
- /**
2
- * WorkspacePicker — dropdown for switching between workspaces
3
- * (IndexedDB-based or native folder via File System Access API).
4
- */
5
-
6
- import { Fragment, useState, useEffect, useCallback, useRef } from 'react';
7
- import type { WorkspaceDescriptor } from '@bendyline/docblocks/workspace';
8
- import { listWorkspaces, saveWorkspace, touchWorkspace } from '@bendyline/docblocks/workspace';
9
- import { isElectronHost } from '@bendyline/docblocks/host';
10
- import { FolderIcon, NewFolderIcon } from '../icons.js';
11
-
12
- function isNativeFileSystemSupported(): boolean {
13
- return (
14
- typeof globalThis !== 'undefined' &&
15
- typeof (globalThis as { showDirectoryPicker?: unknown }).showDirectoryPicker === 'function'
16
- );
17
- }
18
-
19
- export interface WorkspacePickerProps {
20
- /** Currently active workspace id. */
21
- activeWorkspaceId: string | null;
22
- /** Called when the user picks a different workspace. */
23
- onSelect: (descriptor: WorkspaceDescriptor) => void;
24
- /** Called when the user chooses "Open Folder" (native FS). */
25
- onOpenFolder: () => void;
26
- /**
27
- * Called when the user chooses "Clone Git repository". Only provided on
28
- * the desktop when git is available — omitted, the item is hidden.
29
- */
30
- onCloneRepository?: () => void;
31
- /** Optional className. */
32
- className?: string;
33
- }
34
-
35
- function WorkspacePath({ path }: { path: string }) {
36
- return path.split(/([\\/])/).map((segment, index) => (
37
- <Fragment key={index}>
38
- {segment}
39
- {(segment === '\\' || segment === '/') && <wbr />}
40
- </Fragment>
41
- ));
42
- }
43
-
44
- export function WorkspacePicker({
45
- activeWorkspaceId,
46
- onSelect,
47
- onOpenFolder,
48
- onCloneRepository,
49
- className,
50
- }: WorkspacePickerProps) {
51
- const [workspaces, setWorkspaces] = useState<WorkspaceDescriptor[]>([]);
52
- const [isOpen, setIsOpen] = useState(false);
53
- const pickerRef = useRef<HTMLDivElement>(null);
54
-
55
- // Close dropdown on outside click
56
- useEffect(() => {
57
- if (!isOpen) return;
58
- function handleOutsideClick(e: MouseEvent) {
59
- if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {
60
- setIsOpen(false);
61
- }
62
- }
63
- document.addEventListener('mousedown', handleOutsideClick);
64
- return () => document.removeEventListener('mousedown', handleOutsideClick);
65
- }, [isOpen]);
66
-
67
- const electron = isElectronHost();
68
-
69
- const refresh = useCallback(async () => {
70
- const list = await listWorkspaces();
71
- // On desktop, hide web-only workspaces (indexeddb/native).
72
- const filtered = electron
73
- ? list.filter((w) => w.type === 'electron-native')
74
- : list.filter((w) => w.type !== 'electron-native');
75
- setWorkspaces(filtered);
76
- }, [electron]);
77
-
78
- useEffect(() => {
79
- refresh();
80
- }, [refresh, activeWorkspaceId]);
81
-
82
- const handleSelect = useCallback(
83
- async (ws: WorkspaceDescriptor) => {
84
- await touchWorkspace(ws.id);
85
- onSelect(ws);
86
- setIsOpen(false);
87
- },
88
- [onSelect],
89
- );
90
-
91
- const handleCreateNew = useCallback(async () => {
92
- const name = `Workspace ${workspaces.length + 1}`;
93
- const id = `ws-${Date.now()}`;
94
- const descriptor: WorkspaceDescriptor = {
95
- id,
96
- name,
97
- type: 'indexeddb',
98
- lastOpened: new Date().toISOString(),
99
- };
100
- await saveWorkspace(descriptor);
101
- await refresh();
102
- onSelect(descriptor);
103
- setIsOpen(false);
104
- }, [workspaces.length, onSelect, refresh]);
105
-
106
- const activeWs = workspaces.find((w) => w.id === activeWorkspaceId);
107
- const activeWorkspaceName = activeWs?.name ?? 'No workspace';
108
-
109
- return (
110
- <div ref={pickerRef} className={`db-workspace-picker ${className ?? ''}`}>
111
- <button
112
- className="db-workspace-picker-btn"
113
- onClick={() => setIsOpen(!isOpen)}
114
- title="Switch workspace"
115
- aria-label={`Switch workspace, current: ${activeWorkspaceName}`}
116
- >
117
- <span className="db-workspace-picker-label">{activeWorkspaceName}</span>
118
- <span className="db-workspace-picker-compact-icon">
119
- <FolderIcon />
120
- </span>
121
- <span
122
- className={`db-workspace-picker-caret${isOpen ? ' db-workspace-picker-caret--open' : ''}`}
123
- aria-hidden="true"
124
- />
125
- </button>
126
-
127
- {isOpen && (
128
- <div className="db-workspace-dropdown">
129
- {workspaces.map((ws) => (
130
- <button
131
- key={ws.id}
132
- className={`db-workspace-dropdown-item ${
133
- ws.id === activeWorkspaceId ? 'db-workspace-dropdown-item--active' : ''
134
- }`}
135
- onClick={() => handleSelect(ws)}
136
- >
137
- <span className="db-workspace-details">
138
- <span className="db-workspace-heading">
139
- <span>{ws.name}</span>
140
- {(ws.type === 'native' || ws.type === 'electron-native') && (
141
- <span className="db-workspace-type">(folder)</span>
142
- )}
143
- </span>
144
- {ws.rootPath && (
145
- <span className="db-workspace-path" title={ws.rootPath}>
146
- <WorkspacePath path={ws.rootPath} />
147
- </span>
148
- )}
149
- </span>
150
- </button>
151
- ))}
152
-
153
- <div className="db-workspace-dropdown-divider" />
154
-
155
- {!electron && (
156
- <button className="db-workspace-dropdown-item" onClick={handleCreateNew}>
157
- <span className="db-workspace-dropdown-action-label">
158
- <NewFolderIcon />
159
- <span>New Workspace</span>
160
- </span>
161
- </button>
162
- )}
163
-
164
- {(electron || isNativeFileSystemSupported()) && (
165
- <button
166
- className="db-workspace-dropdown-item"
167
- onClick={() => {
168
- setIsOpen(false);
169
- onOpenFolder();
170
- }}
171
- >
172
- Open Folder...
173
- </button>
174
- )}
175
-
176
- {onCloneRepository && (
177
- <button
178
- className="db-workspace-dropdown-item"
179
- onClick={() => {
180
- setIsOpen(false);
181
- onCloneRepository();
182
- }}
183
- >
184
- Clone Git Repository...
185
- </button>
186
- )}
187
- </div>
188
- )}
189
- </div>
190
- );
191
- }
@@ -1,88 +0,0 @@
1
- /**
2
- * WorkspaceSettingsButton — gear icon dropdown for workspace actions.
3
- */
4
-
5
- import { useState, useCallback, useRef, useEffect } from 'react';
6
- import { WorkspaceIcon } from '../icons.js';
7
-
8
- export interface WorkspaceSettingsButtonProps {
9
- onSettings: () => void;
10
- onRename: () => void;
11
- onDownload: () => void;
12
- onRemove: () => void;
13
- }
14
-
15
- export function WorkspaceSettingsButton({
16
- onSettings,
17
- onRename,
18
- onDownload,
19
- onRemove,
20
- }: WorkspaceSettingsButtonProps) {
21
- const [isOpen, setIsOpen] = useState(false);
22
- const ref = useRef<HTMLDivElement>(null);
23
-
24
- useEffect(() => {
25
- if (!isOpen) return;
26
- function handleOutsideClick(e: MouseEvent) {
27
- if (ref.current && !ref.current.contains(e.target as Node)) {
28
- setIsOpen(false);
29
- }
30
- }
31
- document.addEventListener('mousedown', handleOutsideClick);
32
- return () => document.removeEventListener('mousedown', handleOutsideClick);
33
- }, [isOpen]);
34
-
35
- const handleAction = useCallback((action: () => void) => {
36
- setIsOpen(false);
37
- action();
38
- }, []);
39
-
40
- return (
41
- <div ref={ref} className="db-ws-settings">
42
- <button
43
- className="db-ws-settings-btn"
44
- onClick={() => setIsOpen(!isOpen)}
45
- aria-expanded={isOpen}
46
- aria-haspopup="true"
47
- aria-label="Workspace settings"
48
- title="Workspace settings"
49
- >
50
- <WorkspaceIcon />
51
- </button>
52
-
53
- {isOpen && (
54
- <div className="db-ws-settings-dropdown" role="menu">
55
- <button
56
- className="db-ws-settings-item"
57
- role="menuitem"
58
- onClick={() => handleAction(onSettings)}
59
- >
60
- Workspace settings…
61
- </button>
62
- <button
63
- className="db-ws-settings-item"
64
- role="menuitem"
65
- onClick={() => handleAction(onRename)}
66
- >
67
- Rename workspace
68
- </button>
69
- <button
70
- className="db-ws-settings-item"
71
- role="menuitem"
72
- onClick={() => handleAction(onDownload)}
73
- >
74
- Download workspace
75
- </button>
76
- <div className="db-ws-settings-divider" />
77
- <button
78
- className="db-ws-settings-item db-ws-settings-item--danger"
79
- role="menuitem"
80
- onClick={() => handleAction(onRemove)}
81
- >
82
- Remove workspace
83
- </button>
84
- </div>
85
- )}
86
- </div>
87
- );
88
- }
@@ -1,121 +0,0 @@
1
- /**
2
- * WorkspaceSettingsDialog — per-workspace settings modal.
3
- *
4
- * Lets the user override the global versioning preference for a single
5
- * workspace (or fall back to inheriting it). The override is stored on
6
- * the WorkspaceDescriptor and persisted via `saveWorkspace`.
7
- */
8
-
9
- import { useCallback, useEffect } from 'react';
10
- import type { WorkspaceDescriptor } from '@bendyline/docblocks/workspace';
11
- import {
12
- isLocalWorkspaceType,
13
- resolveVersioningEnabled,
14
- type VersioningPreference,
15
- } from '../preferences/versioning.js';
16
-
17
- export type WorkspaceVersioningOverride = NonNullable<WorkspaceDescriptor['versioningOverride']>;
18
-
19
- export interface WorkspaceSettingsDialogProps {
20
- workspace: WorkspaceDescriptor;
21
- /** Current global versioning preference — used to label "Inherit". */
22
- globalVersioningPreference: VersioningPreference;
23
- /** Apply a new override and close the dialog. */
24
- onChange: (override: WorkspaceVersioningOverride) => void;
25
- onClose: () => void;
26
- }
27
-
28
- const VERSIONING_LABELS: Record<VersioningPreference, string> = {
29
- on: 'on',
30
- 'browser-only': 'on for browser workspaces, off for local folders',
31
- off: 'off',
32
- };
33
-
34
- export function WorkspaceSettingsDialog({
35
- workspace,
36
- globalVersioningPreference,
37
- onChange,
38
- onClose,
39
- }: WorkspaceSettingsDialogProps) {
40
- // Treat absent/undefined as 'inherit' for the radio state.
41
- const current: WorkspaceVersioningOverride = workspace.versioningOverride ?? 'inherit';
42
-
43
- useEffect(() => {
44
- const onKey = (e: KeyboardEvent) => {
45
- if (e.key === 'Escape') onClose();
46
- };
47
- window.addEventListener('keydown', onKey);
48
- return () => window.removeEventListener('keydown', onKey);
49
- }, [onClose]);
50
-
51
- const handleBackdropClick = useCallback(
52
- (e: React.MouseEvent) => {
53
- if (e.target === e.currentTarget) onClose();
54
- },
55
- [onClose],
56
- );
57
-
58
- const isLocal = isLocalWorkspaceType(workspace.type);
59
- const inheritedEnabled = resolveVersioningEnabled(
60
- { ...workspace, versioningOverride: 'inherit' },
61
- globalVersioningPreference,
62
- );
63
- const inheritLabel = `Inherit default — currently ${VERSIONING_LABELS[globalVersioningPreference]} (${inheritedEnabled ? 'on' : 'off'} for this workspace)`;
64
-
65
- return (
66
- <div className="db-dialog-overlay" onClick={handleBackdropClick}>
67
- <div className="db-dialog" role="dialog" aria-label="Workspace settings">
68
- <div className="db-dialog-header">
69
- <h2 className="db-dialog-title">Workspace settings</h2>
70
- <button type="button" className="db-dialog-close" onClick={onClose} aria-label="Close">
71
- &times;
72
- </button>
73
- </div>
74
- <div className="db-dialog-body">
75
- <p className="db-settings-hint">
76
- <strong>{workspace.name}</strong> &middot;{' '}
77
- {isLocal ? 'Local folder workspace' : 'Browser workspace'}
78
- </p>
79
-
80
- <fieldset className="db-settings-fieldset">
81
- <legend className="db-settings-legend">Version history</legend>
82
- <p className="db-settings-hint">
83
- Controls whether DocBlocks keeps prior revisions in{' '}
84
- <code>&lt;name&gt;_files/.versions/</code> for documents in this workspace.
85
- </p>
86
- <label className="db-settings-radio">
87
- <input
88
- type="radio"
89
- name="ws-versioning"
90
- value="inherit"
91
- checked={current === 'inherit'}
92
- onChange={() => onChange('inherit')}
93
- />
94
- {inheritLabel}
95
- </label>
96
- <label className="db-settings-radio">
97
- <input
98
- type="radio"
99
- name="ws-versioning"
100
- value="on"
101
- checked={current === 'on'}
102
- onChange={() => onChange('on')}
103
- />
104
- On for this workspace
105
- </label>
106
- <label className="db-settings-radio">
107
- <input
108
- type="radio"
109
- name="ws-versioning"
110
- value="off"
111
- checked={current === 'off'}
112
- onChange={() => onChange('off')}
113
- />
114
- Off for this workspace
115
- </label>
116
- </fieldset>
117
- </div>
118
- </div>
119
- </div>
120
- );
121
- }
@@ -1,2 +0,0 @@
1
- export { WorkspacePicker } from './WorkspacePicker.js';
2
- export type { WorkspacePickerProps } from './WorkspacePicker.js';
@@ -1,81 +0,0 @@
1
- /**
2
- * Dialog — shared modal primitive.
3
- *
4
- * Promotes the `db-dialog-overlay` / `db-dialog` pattern used by the
5
- * settings dialogs into a reusable component, adding aria-modal and
6
- * initial focus. Escape and (by default) backdrop clicks close it.
7
- */
8
-
9
- import { useCallback, useEffect, useRef } from 'react';
10
-
11
- export interface DialogProps {
12
- title: string;
13
- onClose: () => void;
14
- /** default 380px / wide 560px / full min(1100px, 94vw) column. */
15
- size?: 'default' | 'wide' | 'full';
16
- children: React.ReactNode;
17
- /** Right-aligned action row below the body. */
18
- footer?: React.ReactNode;
19
- /** Element to focus on open; defaults to the close button. */
20
- initialFocusRef?: React.RefObject<HTMLElement | null>;
21
- /** Set false when a stray backdrop click would lose user input. */
22
- closeOnBackdrop?: boolean;
23
- }
24
-
25
- export function Dialog({
26
- title,
27
- onClose,
28
- size = 'default',
29
- children,
30
- footer,
31
- initialFocusRef,
32
- closeOnBackdrop = true,
33
- }: DialogProps) {
34
- const closeButtonRef = useRef<HTMLButtonElement>(null);
35
-
36
- useEffect(() => {
37
- const onKey = (e: KeyboardEvent) => {
38
- if (e.key === 'Escape') onClose();
39
- };
40
- window.addEventListener('keydown', onKey);
41
- return () => window.removeEventListener('keydown', onKey);
42
- }, [onClose]);
43
-
44
- useEffect(() => {
45
- const target = initialFocusRef?.current ?? closeButtonRef.current;
46
- target?.focus();
47
- // Focus only on mount — refocusing on every re-render would fight the user.
48
- // eslint-disable-next-line react-hooks/exhaustive-deps
49
- }, []);
50
-
51
- const handleBackdropClick = useCallback(
52
- (e: React.MouseEvent) => {
53
- if (closeOnBackdrop && e.target === e.currentTarget) onClose();
54
- },
55
- [closeOnBackdrop, onClose],
56
- );
57
-
58
- const sizeClass =
59
- size === 'wide' ? ' db-dialog--wide' : size === 'full' ? ' db-dialog--full' : '';
60
-
61
- return (
62
- <div className="db-dialog-overlay" onClick={handleBackdropClick}>
63
- <div className={`db-dialog${sizeClass}`} role="dialog" aria-modal="true" aria-label={title}>
64
- <div className="db-dialog-header">
65
- <h2 className="db-dialog-title">{title}</h2>
66
- <button
67
- ref={closeButtonRef}
68
- type="button"
69
- className="db-dialog-close"
70
- onClick={onClose}
71
- aria-label="Close"
72
- >
73
- &times;
74
- </button>
75
- </div>
76
- <div className="db-dialog-body">{children}</div>
77
- {footer && <div className="db-dialog-footer">{footer}</div>}
78
- </div>
79
- </div>
80
- );
81
- }