@bendyline/docblocks-react 1.1.1 → 2.0.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 (335) hide show
  1. package/README.md +50 -15
  2. package/dist/AppMenu/AppMenu.d.ts +29 -2
  3. package/dist/AppMenu/AppMenu.d.ts.map +1 -1
  4. package/dist/AppMenu/AppMenu.js +41 -2
  5. package/dist/AppMenu/AppMenu.js.map +1 -1
  6. package/dist/AppMenu/index.d.ts +1 -1
  7. package/dist/AppMenu/index.d.ts.map +1 -1
  8. package/dist/DocBlocksShell/DocBlocksShell.d.ts +17 -4
  9. package/dist/DocBlocksShell/DocBlocksShell.d.ts.map +1 -1
  10. package/dist/DocBlocksShell/DocBlocksShell.js +1710 -299
  11. package/dist/DocBlocksShell/DocBlocksShell.js.map +1 -1
  12. package/dist/DocBlocksShell/LazyEditorShell.d.ts +3 -0
  13. package/dist/DocBlocksShell/LazyEditorShell.d.ts.map +1 -0
  14. package/dist/DocBlocksShell/LazyEditorShell.js +3 -0
  15. package/dist/DocBlocksShell/LazyEditorShell.js.map +1 -0
  16. package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts +13 -0
  17. package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts.map +1 -0
  18. package/dist/DocBlocksShell/UpdateAvailableNotice.js +16 -0
  19. package/dist/DocBlocksShell/UpdateAvailableNotice.js.map +1 -0
  20. package/dist/DocBlocksShell/document-title.d.ts +3 -0
  21. package/dist/DocBlocksShell/document-title.d.ts.map +1 -0
  22. package/dist/DocBlocksShell/document-title.js +17 -0
  23. package/dist/DocBlocksShell/document-title.js.map +1 -0
  24. package/dist/DocBlocksShell/workspace-authority-barrier.d.ts +14 -0
  25. package/dist/DocBlocksShell/workspace-authority-barrier.d.ts.map +1 -0
  26. package/dist/DocBlocksShell/workspace-authority-barrier.js +23 -0
  27. package/dist/DocBlocksShell/workspace-authority-barrier.js.map +1 -0
  28. package/dist/Export/DeferredExportToolbarControls.d.ts +5 -0
  29. package/dist/Export/DeferredExportToolbarControls.d.ts.map +1 -0
  30. package/dist/Export/DeferredExportToolbarControls.js +10 -0
  31. package/dist/Export/DeferredExportToolbarControls.js.map +1 -0
  32. package/dist/Export/ExportDialog.d.ts +10 -1
  33. package/dist/Export/ExportDialog.d.ts.map +1 -1
  34. package/dist/Export/ExportDialog.js +39 -20
  35. package/dist/Export/ExportDialog.js.map +1 -1
  36. package/dist/Export/ExportToolbarControls.d.ts +21 -1
  37. package/dist/Export/ExportToolbarControls.d.ts.map +1 -1
  38. package/dist/Export/ExportToolbarControls.js +161 -26
  39. package/dist/Export/ExportToolbarControls.js.map +1 -1
  40. package/dist/Export/export-destination.d.ts +3 -0
  41. package/dist/Export/export-destination.d.ts.map +1 -0
  42. package/dist/Export/export-destination.js +32 -0
  43. package/dist/Export/export-destination.js.map +1 -0
  44. package/dist/Export/index.d.ts +8 -4
  45. package/dist/Export/index.d.ts.map +1 -1
  46. package/dist/Export/index.js +4 -1
  47. package/dist/Export/index.js.map +1 -1
  48. package/dist/Export/public-api.d.ts +12 -0
  49. package/dist/Export/public-api.d.ts.map +1 -0
  50. package/dist/Export/public-api.js +9 -0
  51. package/dist/Export/public-api.js.map +1 -0
  52. package/dist/Export/run-export.d.ts +3 -1
  53. package/dist/Export/run-export.d.ts.map +1 -1
  54. package/dist/Export/run-export.js +58 -25
  55. package/dist/Export/run-export.js.map +1 -1
  56. package/dist/Export/transform-summaries.d.ts +7 -0
  57. package/dist/Export/transform-summaries.d.ts.map +1 -0
  58. package/dist/Export/transform-summaries.js +6 -0
  59. package/dist/Export/transform-summaries.js.map +1 -0
  60. package/dist/ExportDialog-MEUISWZX.js +9 -0
  61. package/dist/ExportDialog-MEUISWZX.js.map +1 -0
  62. package/dist/ExportToolbarControls-D2YDWOXW.js +373 -0
  63. package/dist/ExportToolbarControls-D2YDWOXW.js.map +1 -0
  64. package/dist/FileExplorer/FileExplorer.d.ts +26 -4
  65. package/dist/FileExplorer/FileExplorer.d.ts.map +1 -1
  66. package/dist/FileExplorer/FileExplorer.js +204 -29
  67. package/dist/FileExplorer/FileExplorer.js.map +1 -1
  68. package/dist/FileExplorer/FileTreeNode.d.ts +24 -3
  69. package/dist/FileExplorer/FileTreeNode.d.ts.map +1 -1
  70. package/dist/FileExplorer/FileTreeNode.js +27 -8
  71. package/dist/FileExplorer/FileTreeNode.js.map +1 -1
  72. package/dist/FileExplorer/index.d.ts +1 -1
  73. package/dist/FileExplorer/index.d.ts.map +1 -1
  74. package/dist/FileExplorer/useFileTree.d.ts +5 -3
  75. package/dist/FileExplorer/useFileTree.d.ts.map +1 -1
  76. package/dist/FileExplorer/useFileTree.js +173 -13
  77. package/dist/FileExplorer/useFileTree.js.map +1 -1
  78. package/dist/Git/GitAuthGuidanceDialog.d.ts +18 -0
  79. package/dist/Git/GitAuthGuidanceDialog.d.ts.map +1 -0
  80. package/dist/Git/GitAuthGuidanceDialog.js +27 -0
  81. package/dist/Git/GitAuthGuidanceDialog.js.map +1 -0
  82. package/dist/Git/GitBranchesDialog.d.ts +13 -0
  83. package/dist/Git/GitBranchesDialog.d.ts.map +1 -0
  84. package/dist/Git/GitBranchesDialog.js +59 -0
  85. package/dist/Git/GitBranchesDialog.js.map +1 -0
  86. package/dist/Git/GitCloneDialog.d.ts +14 -0
  87. package/dist/Git/GitCloneDialog.d.ts.map +1 -0
  88. package/dist/Git/GitCloneDialog.js +79 -0
  89. package/dist/Git/GitCloneDialog.js.map +1 -0
  90. package/dist/Git/GitCommitDialog.d.ts +12 -0
  91. package/dist/Git/GitCommitDialog.d.ts.map +1 -0
  92. package/dist/Git/GitCommitDialog.js +38 -0
  93. package/dist/Git/GitCommitDialog.js.map +1 -0
  94. package/dist/Git/GitConflictsDialog.d.ts +12 -0
  95. package/dist/Git/GitConflictsDialog.d.ts.map +1 -0
  96. package/dist/Git/GitConflictsDialog.js +17 -0
  97. package/dist/Git/GitConflictsDialog.js.map +1 -0
  98. package/dist/Git/GitContext.d.ts +89 -0
  99. package/dist/Git/GitContext.d.ts.map +1 -0
  100. package/dist/Git/GitContext.js +15 -0
  101. package/dist/Git/GitContext.js.map +1 -0
  102. package/dist/Git/GitDiffDialog.d.ts +20 -0
  103. package/dist/Git/GitDiffDialog.d.ts.map +1 -0
  104. package/dist/Git/GitDiffDialog.js +100 -0
  105. package/dist/Git/GitDiffDialog.js.map +1 -0
  106. package/dist/Git/GitDiffView.d.ts +23 -0
  107. package/dist/Git/GitDiffView.d.ts.map +1 -0
  108. package/dist/Git/GitDiffView.js +77 -0
  109. package/dist/Git/GitDiffView.js.map +1 -0
  110. package/dist/Git/GitHistoryDialog.d.ts +15 -0
  111. package/dist/Git/GitHistoryDialog.d.ts.map +1 -0
  112. package/dist/Git/GitHistoryDialog.js +107 -0
  113. package/dist/Git/GitHistoryDialog.js.map +1 -0
  114. package/dist/Git/GitStatusBar.d.ts +8 -0
  115. package/dist/Git/GitStatusBar.d.ts.map +1 -0
  116. package/dist/Git/GitStatusBar.js +49 -0
  117. package/dist/Git/GitStatusBar.js.map +1 -0
  118. package/dist/Git/GitToolbarControl.d.ts +15 -0
  119. package/dist/Git/GitToolbarControl.d.ts.map +1 -0
  120. package/dist/Git/GitToolbarControl.js +51 -0
  121. package/dist/Git/GitToolbarControl.js.map +1 -0
  122. package/dist/Git/GitUI.d.ts +14 -0
  123. package/dist/Git/GitUI.d.ts.map +1 -0
  124. package/dist/Git/GitUI.js +21 -0
  125. package/dist/Git/GitUI.js.map +1 -0
  126. package/dist/Git/commit-selection.d.ts +22 -0
  127. package/dist/Git/commit-selection.d.ts.map +1 -0
  128. package/dist/Git/commit-selection.js +47 -0
  129. package/dist/Git/commit-selection.js.map +1 -0
  130. package/dist/Git/git-clone-utils.d.ts +8 -0
  131. package/dist/Git/git-clone-utils.d.ts.map +1 -0
  132. package/dist/Git/git-clone-utils.js +26 -0
  133. package/dist/Git/git-clone-utils.js.map +1 -0
  134. package/dist/Git/git-status.d.ts +24 -0
  135. package/dist/Git/git-status.d.ts.map +1 -0
  136. package/dist/Git/git-status.js +105 -0
  137. package/dist/Git/git-status.js.map +1 -0
  138. package/dist/Git/useGit.d.ts +15 -0
  139. package/dist/Git/useGit.d.ts.map +1 -0
  140. package/dist/Git/useGit.js +206 -0
  141. package/dist/Git/useGit.js.map +1 -0
  142. package/dist/Git/useGitStatus.d.ts +17 -0
  143. package/dist/Git/useGitStatus.d.ts.map +1 -0
  144. package/dist/Git/useGitStatus.js +63 -0
  145. package/dist/Git/useGitStatus.js.map +1 -0
  146. package/dist/GitToolbarControl-LMIR4R7I.js +117 -0
  147. package/dist/GitToolbarControl-LMIR4R7I.js.map +1 -0
  148. package/dist/GitUI-KGF5MSNV.js +1048 -0
  149. package/dist/GitUI-KGF5MSNV.js.map +1 -0
  150. package/dist/LazyEditorShell-EF2BWRXU.js +6 -0
  151. package/dist/LazyEditorShell-EF2BWRXU.js.map +1 -0
  152. package/dist/Settings/Settings.d.ts +23 -0
  153. package/dist/Settings/Settings.d.ts.map +1 -0
  154. package/dist/Settings/Settings.js +22 -0
  155. package/dist/Settings/Settings.js.map +1 -0
  156. package/dist/Settings/public-api.d.ts +3 -0
  157. package/dist/Settings/public-api.d.ts.map +1 -0
  158. package/dist/Settings/public-api.js +2 -0
  159. package/dist/Settings/public-api.js.map +1 -0
  160. package/dist/WorkspacePicker/WorkspacePicker.d.ts +6 -1
  161. package/dist/WorkspacePicker/WorkspacePicker.d.ts.map +1 -1
  162. package/dist/WorkspacePicker/WorkspacePicker.js +16 -5
  163. package/dist/WorkspacePicker/WorkspacePicker.js.map +1 -1
  164. package/dist/chunk-3SAXDU2U.js +157 -0
  165. package/dist/chunk-3SAXDU2U.js.map +1 -0
  166. package/dist/chunk-4XXSWN3T.js +13 -0
  167. package/dist/chunk-4XXSWN3T.js.map +1 -0
  168. package/dist/chunk-5A4KEWKT.js +97 -0
  169. package/dist/chunk-5A4KEWKT.js.map +1 -0
  170. package/dist/chunk-AOVTHZU7.js +321 -0
  171. package/dist/chunk-AOVTHZU7.js.map +1 -0
  172. package/dist/chunk-DD4VFJQI.js +51 -0
  173. package/dist/chunk-DD4VFJQI.js.map +1 -0
  174. package/dist/chunk-GSNZSCIK.js +55 -0
  175. package/dist/chunk-GSNZSCIK.js.map +1 -0
  176. package/dist/chunk-VHDP4IPL.js +70 -0
  177. package/dist/chunk-VHDP4IPL.js.map +1 -0
  178. package/dist/chunk-ZI56BNB7.js +270 -0
  179. package/dist/chunk-ZI56BNB7.js.map +1 -0
  180. package/dist/components/Dialog.d.ts +22 -0
  181. package/dist/components/Dialog.d.ts.map +1 -0
  182. package/dist/components/Dialog.js +33 -0
  183. package/dist/components/Dialog.js.map +1 -0
  184. package/dist/editor.d.ts +10 -0
  185. package/dist/editor.d.ts.map +1 -0
  186. package/dist/editor.js +70 -0
  187. package/dist/editor.js.map +1 -0
  188. package/dist/export/index.d.ts +87 -0
  189. package/dist/export/index.js +26 -0
  190. package/dist/export/index.js.map +1 -0
  191. package/dist/hooks/index.d.ts +2 -1
  192. package/dist/hooks/index.d.ts.map +1 -1
  193. package/dist/hooks/index.js +1 -1
  194. package/dist/hooks/index.js.map +1 -1
  195. package/dist/hooks/useDocumentSession.d.ts +16 -0
  196. package/dist/hooks/useDocumentSession.d.ts.map +1 -0
  197. package/dist/hooks/useDocumentSession.js +18 -0
  198. package/dist/hooks/useDocumentSession.js.map +1 -0
  199. package/dist/icons.d.ts +11 -6
  200. package/dist/icons.d.ts.map +1 -1
  201. package/dist/icons.js +21 -20
  202. package/dist/icons.js.map +1 -1
  203. package/dist/index.d.ts +8 -5
  204. package/dist/index.d.ts.map +1 -1
  205. package/dist/index.js +4 -2
  206. package/dist/index.js.map +1 -1
  207. package/dist/preferences/theme.d.ts +18 -0
  208. package/dist/preferences/theme.d.ts.map +1 -0
  209. package/dist/preferences/theme.js +63 -0
  210. package/dist/preferences/theme.js.map +1 -0
  211. package/dist/provider-lease.d.ts +10 -0
  212. package/dist/provider-lease.d.ts.map +1 -0
  213. package/dist/provider-lease.js +42 -0
  214. package/dist/provider-lease.js.map +1 -0
  215. package/dist/run-export-ICTZITXC.js +10 -0
  216. package/dist/run-export-ICTZITXC.js.map +1 -0
  217. package/dist/settings/index.d.ts +28 -0
  218. package/dist/settings/index.js +12 -0
  219. package/dist/settings/index.js.map +1 -0
  220. package/package.json +27 -10
  221. package/src/AppMenu/AppMenu.tsx +169 -99
  222. package/src/AppMenu/index.ts +1 -1
  223. package/src/DocBlocksShell/DocBlocksShell.tsx +2183 -516
  224. package/src/DocBlocksShell/LazyEditorShell.ts +2 -0
  225. package/src/DocBlocksShell/UpdateAvailableNotice.tsx +60 -0
  226. package/src/DocBlocksShell/document-title.ts +19 -0
  227. package/src/DocBlocksShell/workspace-authority-barrier.ts +26 -0
  228. package/src/Export/DeferredExportToolbarControls.tsx +23 -0
  229. package/src/Export/ExportDialog.tsx +102 -27
  230. package/src/Export/ExportToolbarControls.tsx +343 -57
  231. package/src/Export/export-destination.ts +30 -0
  232. package/src/Export/index.ts +18 -4
  233. package/src/Export/public-api.ts +17 -0
  234. package/src/Export/run-export.ts +66 -29
  235. package/src/Export/transform-summaries.ts +14 -0
  236. package/src/FileExplorer/FileExplorer.tsx +284 -38
  237. package/src/FileExplorer/FileTreeNode.tsx +100 -8
  238. package/src/FileExplorer/index.ts +1 -1
  239. package/src/FileExplorer/useFileTree.ts +190 -16
  240. package/src/Git/GitAuthGuidanceDialog.tsx +84 -0
  241. package/src/Git/GitBranchesDialog.tsx +144 -0
  242. package/src/Git/GitCloneDialog.tsx +200 -0
  243. package/src/Git/GitCommitDialog.tsx +119 -0
  244. package/src/Git/GitConflictsDialog.tsx +62 -0
  245. package/src/Git/GitContext.tsx +88 -0
  246. package/src/Git/GitDiffDialog.tsx +147 -0
  247. package/src/Git/GitDiffView.tsx +105 -0
  248. package/src/Git/GitHistoryDialog.tsx +195 -0
  249. package/src/Git/GitStatusBar.tsx +157 -0
  250. package/src/Git/GitToolbarControl.tsx +123 -0
  251. package/src/Git/GitUI.tsx +68 -0
  252. package/src/Git/commit-selection.ts +63 -0
  253. package/src/Git/git-clone-utils.ts +23 -0
  254. package/src/Git/git-status.ts +113 -0
  255. package/src/Git/useGit.ts +279 -0
  256. package/src/Git/useGitStatus.ts +78 -0
  257. package/src/Settings/Settings.tsx +118 -0
  258. package/src/Settings/public-api.ts +8 -0
  259. package/src/WorkspacePicker/WorkspacePicker.tsx +62 -8
  260. package/src/components/Dialog.tsx +81 -0
  261. package/src/editor.ts +72 -0
  262. package/src/hooks/index.ts +2 -1
  263. package/src/hooks/useDocumentSession.ts +37 -0
  264. package/src/icons.tsx +33 -55
  265. package/src/index.ts +35 -5
  266. package/src/preferences/theme.ts +67 -0
  267. package/src/provider-lease.ts +52 -0
  268. package/src/styles/docblocks.css +2247 -77
  269. package/src/types/pwa-dom.d.ts +31 -0
  270. package/dist/hooks/useAutoSave.d.ts +0 -15
  271. package/dist/hooks/useAutoSave.d.ts.map +0 -1
  272. package/dist/hooks/useAutoSave.js +0 -83
  273. package/dist/hooks/useAutoSave.js.map +0 -1
  274. package/src/fonts/fonts.css +0 -362
  275. package/src/fonts/licenses/LICENSE-cormorant-garamond.txt +0 -93
  276. package/src/fonts/licenses/LICENSE-crimson-text.txt +0 -93
  277. package/src/fonts/licenses/LICENSE-dm-sans.txt +0 -93
  278. package/src/fonts/licenses/LICENSE-dm-serif-display.txt +0 -93
  279. package/src/fonts/licenses/LICENSE-hanken-grotesk.txt +0 -94
  280. package/src/fonts/licenses/LICENSE-ibm-plex-sans.txt +0 -93
  281. package/src/fonts/licenses/LICENSE-inter.txt +0 -93
  282. package/src/fonts/licenses/LICENSE-jetbrains-mono.txt +0 -93
  283. package/src/fonts/licenses/LICENSE-lora.txt +0 -93
  284. package/src/fonts/licenses/LICENSE-merriweather.txt +0 -93
  285. package/src/fonts/licenses/LICENSE-oswald.txt +0 -93
  286. package/src/fonts/licenses/LICENSE-playfair-display.txt +0 -93
  287. package/src/fonts/licenses/LICENSE-pt-serif.txt +0 -93
  288. package/src/fonts/licenses/LICENSE-roboto.txt +0 -93
  289. package/src/fonts/licenses/LICENSE-source-serif-4.txt +0 -93
  290. package/src/fonts/woff2/cormorant-garamond-400.woff2 +0 -0
  291. package/src/fonts/woff2/cormorant-garamond-700.woff2 +0 -0
  292. package/src/fonts/woff2/crimson-text-400.woff2 +0 -0
  293. package/src/fonts/woff2/crimson-text-400i.woff2 +0 -0
  294. package/src/fonts/woff2/crimson-text-700.woff2 +0 -0
  295. package/src/fonts/woff2/dm-sans-400.woff2 +0 -0
  296. package/src/fonts/woff2/dm-sans-400i.woff2 +0 -0
  297. package/src/fonts/woff2/dm-sans-500.woff2 +0 -0
  298. package/src/fonts/woff2/dm-sans-700.woff2 +0 -0
  299. package/src/fonts/woff2/dm-serif-display-400.woff2 +0 -0
  300. package/src/fonts/woff2/hanken-grotesk-400.woff2 +0 -0
  301. package/src/fonts/woff2/hanken-grotesk-400i.woff2 +0 -0
  302. package/src/fonts/woff2/hanken-grotesk-500.woff2 +0 -0
  303. package/src/fonts/woff2/hanken-grotesk-600.woff2 +0 -0
  304. package/src/fonts/woff2/hanken-grotesk-700.woff2 +0 -0
  305. package/src/fonts/woff2/ibm-plex-sans-400.woff2 +0 -0
  306. package/src/fonts/woff2/ibm-plex-sans-400i.woff2 +0 -0
  307. package/src/fonts/woff2/ibm-plex-sans-500.woff2 +0 -0
  308. package/src/fonts/woff2/ibm-plex-sans-600.woff2 +0 -0
  309. package/src/fonts/woff2/ibm-plex-sans-700.woff2 +0 -0
  310. package/src/fonts/woff2/inter-400.woff2 +0 -0
  311. package/src/fonts/woff2/inter-400i.woff2 +0 -0
  312. package/src/fonts/woff2/inter-500.woff2 +0 -0
  313. package/src/fonts/woff2/inter-600.woff2 +0 -0
  314. package/src/fonts/woff2/inter-700.woff2 +0 -0
  315. package/src/fonts/woff2/jetbrains-mono-400.woff2 +0 -0
  316. package/src/fonts/woff2/jetbrains-mono-400i.woff2 +0 -0
  317. package/src/fonts/woff2/jetbrains-mono-700.woff2 +0 -0
  318. package/src/fonts/woff2/lora-400.woff2 +0 -0
  319. package/src/fonts/woff2/lora-400i.woff2 +0 -0
  320. package/src/fonts/woff2/lora-700.woff2 +0 -0
  321. package/src/fonts/woff2/merriweather-400.woff2 +0 -0
  322. package/src/fonts/woff2/merriweather-700.woff2 +0 -0
  323. package/src/fonts/woff2/oswald-400.woff2 +0 -0
  324. package/src/fonts/woff2/oswald-700.woff2 +0 -0
  325. package/src/fonts/woff2/playfair-display-400.woff2 +0 -0
  326. package/src/fonts/woff2/playfair-display-700.woff2 +0 -0
  327. package/src/fonts/woff2/pt-serif-400.woff2 +0 -0
  328. package/src/fonts/woff2/pt-serif-700.woff2 +0 -0
  329. package/src/fonts/woff2/roboto-400.woff2 +0 -0
  330. package/src/fonts/woff2/roboto-400i.woff2 +0 -0
  331. package/src/fonts/woff2/roboto-700.woff2 +0 -0
  332. package/src/fonts/woff2/source-serif-4-400.woff2 +0 -0
  333. package/src/fonts/woff2/source-serif-4-400i.woff2 +0 -0
  334. package/src/fonts/woff2/source-serif-4-700.woff2 +0 -0
  335. package/src/hooks/useAutoSave.ts +0 -116
@@ -4,8 +4,10 @@
4
4
 
5
5
  import { useState, useCallback, useRef, useEffect } from 'react';
6
6
  import type { VersioningPreference } from '../preferences/versioning.js';
7
+ import type { AccentColor, ThemePreference } from '../preferences/theme.js';
8
+ import { AccentColorSettings, SettingsDialog, ThemeSettings } from '../Settings/Settings.js';
7
9
 
8
- export type ThemePreference = 'auto' | 'light' | 'dark';
10
+ export type { AccentColor, ThemePreference } from '../preferences/theme.js';
9
11
 
10
12
  export interface AppMenuProps {
11
13
  /** URL for the about page. */
@@ -16,6 +18,10 @@ export interface AppMenuProps {
16
18
  themePreference?: ThemePreference;
17
19
  /** Called when the user changes the theme preference. */
18
20
  onThemeChange?: (theme: ThemePreference) => void;
21
+ /** Current accent color. */
22
+ accentColor?: AccentColor;
23
+ /** Called when the user changes the accent color. */
24
+ onAccentColorChange?: (color: AccentColor) => void;
19
25
  /** Current global versioning preference. */
20
26
  versioningPreference?: VersioningPreference;
21
27
  /** Called when the user changes the global versioning preference. */
@@ -25,6 +31,37 @@ export interface AppMenuProps {
25
31
  * the menu item is hidden.
26
32
  */
27
33
  onDownloadAllWorkspaces?: () => void | Promise<void>;
34
+ /**
35
+ * Called when the user asks the browser to keep origin storage persistent.
36
+ * When omitted, the menu item is hidden.
37
+ */
38
+ onKeepBrowserData?: () => void | Promise<void>;
39
+ /**
40
+ * Called when the user clicks "Install DocBlocks…" (browser PWA install).
41
+ * When omitted — Electron, unsupported browsers, or already installed —
42
+ * the menu item is hidden.
43
+ */
44
+ onInstallApp?: () => void | Promise<void>;
45
+ /**
46
+ * Async origin storage usage/quota for the Settings "Storage" section
47
+ * (fetched when the dialog opens). When omitted — Electron, or browsers
48
+ * without `navigator.storage.estimate` — the section is hidden.
49
+ */
50
+ getStorageEstimate?: () => Promise<{ usage: number; quota: number } | null>;
51
+ /** Whether the browser has marked origin storage persistent (Settings display). */
52
+ storagePersistent?: boolean;
53
+ }
54
+
55
+ function formatBytes(bytes: number): string {
56
+ if (!Number.isFinite(bytes) || bytes < 0) return '—';
57
+ let value = bytes;
58
+ let unit = 'B';
59
+ for (const next of ['KB', 'MB', 'GB', 'TB']) {
60
+ if (value < 1024) break;
61
+ value /= 1024;
62
+ unit = next;
63
+ }
64
+ return `${value >= 100 || unit === 'B' ? Math.round(value) : value.toFixed(1)} ${unit}`;
28
65
  }
29
66
 
30
67
  export function AppMenu({
@@ -32,14 +69,40 @@ export function AppMenu({
32
69
  logoUrl,
33
70
  themePreference = 'auto',
34
71
  onThemeChange,
72
+ accentColor = 'brown',
73
+ onAccentColorChange,
35
74
  versioningPreference = 'browser-only',
36
75
  onVersioningPreferenceChange,
37
76
  onDownloadAllWorkspaces,
77
+ onKeepBrowserData,
78
+ onInstallApp,
79
+ getStorageEstimate,
80
+ storagePersistent,
38
81
  }: AppMenuProps) {
39
82
  const [isOpen, setIsOpen] = useState(false);
40
83
  const [showAbout, setShowAbout] = useState(false);
41
84
  const [showSettings, setShowSettings] = useState(false);
42
85
  const menuRef = useRef<HTMLDivElement>(null);
86
+ const [storageEstimate, setStorageEstimate] = useState<{
87
+ usage: number;
88
+ quota: number;
89
+ } | null>(null);
90
+
91
+ // Refresh the Settings "Storage" figures each time the dialog opens.
92
+ useEffect(() => {
93
+ if (!showSettings || !getStorageEstimate) return;
94
+ let cancelled = false;
95
+ getStorageEstimate()
96
+ .then((estimate) => {
97
+ if (!cancelled) setStorageEstimate(estimate);
98
+ })
99
+ .catch(() => {
100
+ if (!cancelled) setStorageEstimate(null);
101
+ });
102
+ return () => {
103
+ cancelled = true;
104
+ };
105
+ }, [showSettings, getStorageEstimate]);
43
106
 
44
107
  useEffect(() => {
45
108
  if (!isOpen) return;
@@ -71,9 +134,10 @@ export function AppMenu({
71
134
  ) : (
72
135
  <span className="db-app-menu-label">docblocks</span>
73
136
  )}
74
- <span className={`db-app-menu-caret${isOpen ? ' db-app-menu-caret--open' : ''}`}>
75
- {'\u25BE'}
76
- </span>
137
+ <span
138
+ className={`db-app-menu-caret${isOpen ? ' db-app-menu-caret--open' : ''}`}
139
+ aria-hidden="true"
140
+ />
77
141
  </button>
78
142
 
79
143
  {isOpen && (
@@ -85,6 +149,24 @@ export function AppMenu({
85
149
  >
86
150
  Settings
87
151
  </button>
152
+ {onInstallApp && (
153
+ <button
154
+ className="db-app-menu-item"
155
+ role="menuitem"
156
+ onClick={() => handleAction(() => void onInstallApp())}
157
+ >
158
+ Install DocBlocks&hellip;
159
+ </button>
160
+ )}
161
+ {onKeepBrowserData && (
162
+ <button
163
+ className="db-app-menu-item"
164
+ role="menuitem"
165
+ onClick={() => handleAction(() => void onKeepBrowserData())}
166
+ >
167
+ Keep data in browser for longer
168
+ </button>
169
+ )}
88
170
  {onDownloadAllWorkspaces && (
89
171
  <button
90
172
  className="db-app-menu-item"
@@ -107,101 +189,77 @@ export function AppMenu({
107
189
  </div>
108
190
 
109
191
  {showSettings && (
110
- <div className="db-dialog-overlay" onClick={() => setShowSettings(false)}>
111
- <div
112
- className="db-dialog"
113
- role="dialog"
114
- aria-label="Settings"
115
- onClick={(e) => e.stopPropagation()}
116
- >
117
- <div className="db-dialog-header">
118
- <h2 className="db-dialog-title">Settings</h2>
119
- <button
120
- className="db-dialog-close"
121
- onClick={() => setShowSettings(false)}
122
- aria-label="Close"
123
- >
124
- &times;
125
- </button>
126
- </div>
127
- <div className="db-dialog-body">
128
- <fieldset className="db-settings-fieldset">
129
- <legend className="db-settings-legend">Theme</legend>
130
- <label className="db-settings-radio">
131
- <input
132
- type="radio"
133
- name="theme"
134
- value="auto"
135
- checked={themePreference === 'auto'}
136
- onChange={() => onThemeChange?.('auto')}
137
- />
138
- System default
139
- </label>
140
- <label className="db-settings-radio">
141
- <input
142
- type="radio"
143
- name="theme"
144
- value="light"
145
- checked={themePreference === 'light'}
146
- onChange={() => onThemeChange?.('light')}
147
- />
148
- Light
149
- </label>
150
- <label className="db-settings-radio">
151
- <input
152
- type="radio"
153
- name="theme"
154
- value="dark"
155
- checked={themePreference === 'dark'}
156
- onChange={() => onThemeChange?.('dark')}
157
- />
158
- Dark
159
- </label>
160
- </fieldset>
192
+ <SettingsDialog onClose={() => setShowSettings(false)}>
193
+ <ThemeSettings
194
+ value={themePreference}
195
+ onChange={(preference) => onThemeChange?.(preference)}
196
+ />
197
+ <AccentColorSettings
198
+ value={accentColor}
199
+ onChange={(color) => onAccentColorChange?.(color)}
200
+ />
161
201
 
162
- {onVersioningPreferenceChange && (
163
- <fieldset className="db-settings-fieldset">
164
- <legend className="db-settings-legend">Version history</legend>
165
- <p className="db-settings-hint">
166
- When on, DocBlocks keeps prior revisions of each document inside a sibling{' '}
167
- <code>&lt;name&gt;_files/.versions/</code> folder. Individual workspaces can
168
- override this default in their own settings.
169
- </p>
170
- <label className="db-settings-radio">
171
- <input
172
- type="radio"
173
- name="versioning"
174
- value="on"
175
- checked={versioningPreference === 'on'}
176
- onChange={() => onVersioningPreferenceChange('on')}
177
- />
178
- On for all workspaces
179
- </label>
180
- <label className="db-settings-radio">
181
- <input
182
- type="radio"
183
- name="versioning"
184
- value="browser-only"
185
- checked={versioningPreference === 'browser-only'}
186
- onChange={() => onVersioningPreferenceChange('browser-only')}
187
- />
188
- On in browser workspaces, off for local folders
189
- </label>
190
- <label className="db-settings-radio">
191
- <input
192
- type="radio"
193
- name="versioning"
194
- value="off"
195
- checked={versioningPreference === 'off'}
196
- onChange={() => onVersioningPreferenceChange('off')}
197
- />
198
- Off for all workspaces
199
- </label>
200
- </fieldset>
201
- )}
202
- </div>
203
- </div>
204
- </div>
202
+ {getStorageEstimate && (
203
+ <fieldset className="db-settings-fieldset">
204
+ <legend className="db-settings-legend">Storage</legend>
205
+ <p className="db-settings-hint">
206
+ {storageEstimate
207
+ ? `DocBlocks documents and app data are using ${formatBytes(
208
+ storageEstimate.usage,
209
+ )} of the ${formatBytes(
210
+ storageEstimate.quota,
211
+ )} this browser allows for the site.`
212
+ : 'Storage usage is not available in this browser.'}{' '}
213
+ {storagePersistent === undefined
214
+ ? ''
215
+ : storagePersistent
216
+ ? 'Data is marked persistent, so the browser will avoid evicting it.'
217
+ : 'Data is not yet marked persistent — use “Keep data in browser for longer” in the app menu.'}
218
+ </p>
219
+ </fieldset>
220
+ )}
221
+
222
+ {onVersioningPreferenceChange && (
223
+ <fieldset className="db-settings-fieldset">
224
+ <legend className="db-settings-legend">Version history</legend>
225
+ <p className="db-settings-hint">
226
+ When on, DocBlocks keeps prior revisions of each document inside a sibling{' '}
227
+ <code>&lt;name&gt;_files/.versions/</code> folder. Individual workspaces can
228
+ override this default in their own settings.
229
+ </p>
230
+ <label className="db-settings-radio">
231
+ <input
232
+ type="radio"
233
+ name="versioning"
234
+ value="on"
235
+ checked={versioningPreference === 'on'}
236
+ onChange={() => onVersioningPreferenceChange('on')}
237
+ />
238
+ On for all workspaces
239
+ </label>
240
+ <label className="db-settings-radio">
241
+ <input
242
+ type="radio"
243
+ name="versioning"
244
+ value="browser-only"
245
+ checked={versioningPreference === 'browser-only'}
246
+ onChange={() => onVersioningPreferenceChange('browser-only')}
247
+ />
248
+ On in browser workspaces, off for local folders
249
+ </label>
250
+ <label className="db-settings-radio">
251
+ <input
252
+ type="radio"
253
+ name="versioning"
254
+ value="off"
255
+ checked={versioningPreference === 'off'}
256
+ onChange={() => onVersioningPreferenceChange('off')}
257
+ />
258
+ Off for all workspaces
259
+ </label>
260
+ </fieldset>
261
+ )}
262
+ </SettingsDialog>
205
263
  )}
206
264
 
207
265
  {showAbout && (
@@ -236,7 +294,11 @@ export function AppMenu({
236
294
  >
237
295
  squisq
238
296
  </a>{' '}
239
- by Bendyline.
297
+ by{' '}
298
+ <a href="https://bendyline.com" target="_blank" rel="noopener noreferrer">
299
+ Bendyline
300
+ </a>
301
+ .
240
302
  </p>
241
303
  <p className="db-dialog-links">
242
304
  <a
@@ -254,6 +316,14 @@ export function AppMenu({
254
316
  >
255
317
  License (MIT)
256
318
  </a>
319
+ <span className="db-dialog-sep">&middot;</span>
320
+ <a
321
+ href="https://github.com/bendyline/docblocks/blob/main/NOTICE.md"
322
+ target="_blank"
323
+ rel="noopener noreferrer"
324
+ >
325
+ &hearts; built on open source
326
+ </a>
257
327
  </p>
258
328
  </div>
259
329
  </div>
@@ -1,2 +1,2 @@
1
1
  export { AppMenu } from './AppMenu.js';
2
- export type { AppMenuProps, ThemePreference } from './AppMenu.js';
2
+ export type { AccentColor, AppMenuProps, ThemePreference } from './AppMenu.js';