@bendyline/docblocks-react 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/README.md +6 -0
  2. package/dist/{ExportDialog-MEUISWZX.js → ExportDialog-7LDIXJZ3.js} +3 -2
  3. package/dist/{ExportToolbarControls-D2YDWOXW.js → ExportToolbarControls-GHAOJMH6.js} +147 -12
  4. package/dist/ExportToolbarControls-GHAOJMH6.js.map +1 -0
  5. package/dist/{GitToolbarControl-LMIR4R7I.js → GitToolbarControl-GNMRVKWQ.js} +62 -43
  6. package/dist/GitToolbarControl-GNMRVKWQ.js.map +1 -0
  7. package/dist/{GitUI-KGF5MSNV.js → GitUI-VHOBQY43.js} +225 -140
  8. package/dist/GitUI-VHOBQY43.js.map +1 -0
  9. package/dist/ShareDialog-63ENBEDZ.js +213 -0
  10. package/dist/ShareDialog-63ENBEDZ.js.map +1 -0
  11. package/dist/chunk-57ZJJOC5.js +89 -0
  12. package/dist/chunk-57ZJJOC5.js.map +1 -0
  13. package/dist/chunk-FEWQUQML.js +256 -0
  14. package/dist/chunk-FEWQUQML.js.map +1 -0
  15. package/dist/chunk-FMGTHSTX.js +110 -0
  16. package/dist/chunk-FMGTHSTX.js.map +1 -0
  17. package/dist/chunk-UNYZQXWR.js +324 -0
  18. package/dist/chunk-UNYZQXWR.js.map +1 -0
  19. package/dist/editor.d.ts +5 -4
  20. package/dist/editor.js +8 -69
  21. package/dist/editor.js.map +1 -1
  22. package/dist/export/index.d.ts +7 -1
  23. package/dist/export/index.js +2 -1
  24. package/dist/index.d.ts +346 -21
  25. package/dist/index.js +6169 -20
  26. package/dist/index.js.map +1 -1
  27. package/dist/settings/index.d.ts +9 -1
  28. package/dist/settings/index.js +6 -4
  29. package/package.json +18 -13
  30. package/src/styles/docblocks.css +537 -26
  31. package/dist/AppMenu/AppMenu.d.ts +0 -53
  32. package/dist/AppMenu/AppMenu.d.ts.map +0 -1
  33. package/dist/AppMenu/AppMenu.js +0 -67
  34. package/dist/AppMenu/AppMenu.js.map +0 -1
  35. package/dist/AppMenu/index.d.ts +0 -3
  36. package/dist/AppMenu/index.d.ts.map +0 -1
  37. package/dist/AppMenu/index.js +0 -2
  38. package/dist/AppMenu/index.js.map +0 -1
  39. package/dist/DocBlocksShell/DocBlocksShell.d.ts +0 -49
  40. package/dist/DocBlocksShell/DocBlocksShell.d.ts.map +0 -1
  41. package/dist/DocBlocksShell/DocBlocksShell.js +0 -2730
  42. package/dist/DocBlocksShell/DocBlocksShell.js.map +0 -1
  43. package/dist/DocBlocksShell/LazyEditorShell.d.ts +0 -3
  44. package/dist/DocBlocksShell/LazyEditorShell.d.ts.map +0 -1
  45. package/dist/DocBlocksShell/LazyEditorShell.js +0 -3
  46. package/dist/DocBlocksShell/LazyEditorShell.js.map +0 -1
  47. package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts +0 -13
  48. package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts.map +0 -1
  49. package/dist/DocBlocksShell/UpdateAvailableNotice.js +0 -16
  50. package/dist/DocBlocksShell/UpdateAvailableNotice.js.map +0 -1
  51. package/dist/DocBlocksShell/document-title.d.ts +0 -3
  52. package/dist/DocBlocksShell/document-title.d.ts.map +0 -1
  53. package/dist/DocBlocksShell/document-title.js +0 -17
  54. package/dist/DocBlocksShell/document-title.js.map +0 -1
  55. package/dist/DocBlocksShell/index.d.ts +0 -3
  56. package/dist/DocBlocksShell/index.d.ts.map +0 -1
  57. package/dist/DocBlocksShell/index.js +0 -2
  58. package/dist/DocBlocksShell/index.js.map +0 -1
  59. package/dist/DocBlocksShell/workspace-authority-barrier.d.ts +0 -14
  60. package/dist/DocBlocksShell/workspace-authority-barrier.d.ts.map +0 -1
  61. package/dist/DocBlocksShell/workspace-authority-barrier.js +0 -23
  62. package/dist/DocBlocksShell/workspace-authority-barrier.js.map +0 -1
  63. package/dist/Export/DeferredExportToolbarControls.d.ts +0 -5
  64. package/dist/Export/DeferredExportToolbarControls.d.ts.map +0 -1
  65. package/dist/Export/DeferredExportToolbarControls.js +0 -10
  66. package/dist/Export/DeferredExportToolbarControls.js.map +0 -1
  67. package/dist/Export/ExportDialog.d.ts +0 -25
  68. package/dist/Export/ExportDialog.d.ts.map +0 -1
  69. package/dist/Export/ExportDialog.js +0 -160
  70. package/dist/Export/ExportDialog.js.map +0 -1
  71. package/dist/Export/ExportToolbarControls.d.ts +0 -37
  72. package/dist/Export/ExportToolbarControls.d.ts.map +0 -1
  73. package/dist/Export/ExportToolbarControls.js +0 -285
  74. package/dist/Export/ExportToolbarControls.js.map +0 -1
  75. package/dist/Export/export-destination.d.ts +0 -3
  76. package/dist/Export/export-destination.d.ts.map +0 -1
  77. package/dist/Export/export-destination.js +0 -32
  78. package/dist/Export/export-destination.js.map +0 -1
  79. package/dist/Export/export-options.d.ts +0 -53
  80. package/dist/Export/export-options.d.ts.map +0 -1
  81. package/dist/Export/export-options.js +0 -49
  82. package/dist/Export/export-options.js.map +0 -1
  83. package/dist/Export/index.d.ts +0 -10
  84. package/dist/Export/index.d.ts.map +0 -1
  85. package/dist/Export/index.js +0 -6
  86. package/dist/Export/index.js.map +0 -1
  87. package/dist/Export/public-api.d.ts +0 -12
  88. package/dist/Export/public-api.d.ts.map +0 -1
  89. package/dist/Export/public-api.js +0 -9
  90. package/dist/Export/public-api.js.map +0 -1
  91. package/dist/Export/run-export.d.ts +0 -10
  92. package/dist/Export/run-export.d.ts.map +0 -1
  93. package/dist/Export/run-export.js +0 -313
  94. package/dist/Export/run-export.js.map +0 -1
  95. package/dist/Export/transform-summaries.d.ts +0 -7
  96. package/dist/Export/transform-summaries.d.ts.map +0 -1
  97. package/dist/Export/transform-summaries.js +0 -6
  98. package/dist/Export/transform-summaries.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/Settings/Settings.d.ts +0 -23
  187. package/dist/Settings/Settings.d.ts.map +0 -1
  188. package/dist/Settings/Settings.js +0 -22
  189. package/dist/Settings/Settings.js.map +0 -1
  190. package/dist/Settings/public-api.d.ts +0 -3
  191. package/dist/Settings/public-api.d.ts.map +0 -1
  192. package/dist/Settings/public-api.js +0 -2
  193. package/dist/Settings/public-api.js.map +0 -1
  194. package/dist/WorkspacePicker/WorkspacePicker.d.ts +0 -22
  195. package/dist/WorkspacePicker/WorkspacePicker.d.ts.map +0 -1
  196. package/dist/WorkspacePicker/WorkspacePicker.js +0 -74
  197. package/dist/WorkspacePicker/WorkspacePicker.js.map +0 -1
  198. package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts +0 -11
  199. package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts.map +0 -1
  200. package/dist/WorkspacePicker/WorkspaceSettingsButton.js +0 -27
  201. package/dist/WorkspacePicker/WorkspaceSettingsButton.js.map +0 -1
  202. package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts +0 -20
  203. package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts.map +0 -1
  204. package/dist/WorkspacePicker/WorkspaceSettingsDialog.js +0 -36
  205. package/dist/WorkspacePicker/WorkspaceSettingsDialog.js.map +0 -1
  206. package/dist/WorkspacePicker/index.d.ts +0 -3
  207. package/dist/WorkspacePicker/index.d.ts.map +0 -1
  208. package/dist/WorkspacePicker/index.js +0 -2
  209. package/dist/WorkspacePicker/index.js.map +0 -1
  210. package/dist/chunk-3SAXDU2U.js +0 -157
  211. package/dist/chunk-3SAXDU2U.js.map +0 -1
  212. package/dist/chunk-AOVTHZU7.js +0 -321
  213. package/dist/chunk-AOVTHZU7.js.map +0 -1
  214. package/dist/chunk-GSNZSCIK.js +0 -55
  215. package/dist/chunk-GSNZSCIK.js.map +0 -1
  216. package/dist/components/Dialog.d.ts +0 -22
  217. package/dist/components/Dialog.d.ts.map +0 -1
  218. package/dist/components/Dialog.js +0 -33
  219. package/dist/components/Dialog.js.map +0 -1
  220. package/dist/editor.d.ts.map +0 -1
  221. package/dist/hooks/index.d.ts +0 -3
  222. package/dist/hooks/index.d.ts.map +0 -1
  223. package/dist/hooks/index.js +0 -2
  224. package/dist/hooks/index.js.map +0 -1
  225. package/dist/hooks/useDocumentSession.d.ts +0 -16
  226. package/dist/hooks/useDocumentSession.d.ts.map +0 -1
  227. package/dist/hooks/useDocumentSession.js +0 -18
  228. package/dist/hooks/useDocumentSession.js.map +0 -1
  229. package/dist/icons.d.ts +0 -12
  230. package/dist/icons.d.ts.map +0 -1
  231. package/dist/icons.js +0 -28
  232. package/dist/icons.js.map +0 -1
  233. package/dist/index.d.ts.map +0 -1
  234. package/dist/preferences/theme.d.ts +0 -18
  235. package/dist/preferences/theme.d.ts.map +0 -1
  236. package/dist/preferences/theme.js +0 -63
  237. package/dist/preferences/theme.js.map +0 -1
  238. package/dist/preferences/versioning.d.ts +0 -27
  239. package/dist/preferences/versioning.d.ts.map +0 -1
  240. package/dist/preferences/versioning.js +0 -62
  241. package/dist/preferences/versioning.js.map +0 -1
  242. package/dist/provider-lease.d.ts +0 -10
  243. package/dist/provider-lease.d.ts.map +0 -1
  244. package/dist/provider-lease.js +0 -42
  245. package/dist/provider-lease.js.map +0 -1
  246. package/src/AppMenu/AppMenu.tsx +0 -334
  247. package/src/AppMenu/index.ts +0 -2
  248. package/src/DocBlocksShell/DocBlocksShell.tsx +0 -3398
  249. package/src/DocBlocksShell/LazyEditorShell.ts +0 -2
  250. package/src/DocBlocksShell/UpdateAvailableNotice.tsx +0 -60
  251. package/src/DocBlocksShell/document-title.ts +0 -19
  252. package/src/DocBlocksShell/index.ts +0 -2
  253. package/src/DocBlocksShell/workspace-authority-barrier.ts +0 -26
  254. package/src/Export/DeferredExportToolbarControls.tsx +0 -23
  255. package/src/Export/ExportDialog.tsx +0 -437
  256. package/src/Export/ExportToolbarControls.tsx +0 -511
  257. package/src/Export/export-destination.ts +0 -30
  258. package/src/Export/export-options.ts +0 -99
  259. package/src/Export/index.ts +0 -19
  260. package/src/Export/public-api.ts +0 -17
  261. package/src/Export/run-export.ts +0 -374
  262. package/src/Export/transform-summaries.ts +0 -14
  263. package/src/FileExplorer/FileExplorer.tsx +0 -528
  264. package/src/FileExplorer/FileTreeNode.tsx +0 -306
  265. package/src/FileExplorer/index.ts +0 -5
  266. package/src/FileExplorer/useFileTree.ts +0 -352
  267. package/src/Git/GitAuthGuidanceDialog.tsx +0 -84
  268. package/src/Git/GitBranchesDialog.tsx +0 -144
  269. package/src/Git/GitCloneDialog.tsx +0 -200
  270. package/src/Git/GitCommitDialog.tsx +0 -119
  271. package/src/Git/GitConflictsDialog.tsx +0 -62
  272. package/src/Git/GitContext.tsx +0 -88
  273. package/src/Git/GitDiffDialog.tsx +0 -147
  274. package/src/Git/GitDiffView.tsx +0 -105
  275. package/src/Git/GitHistoryDialog.tsx +0 -195
  276. package/src/Git/GitStatusBar.tsx +0 -157
  277. package/src/Git/GitToolbarControl.tsx +0 -123
  278. package/src/Git/GitUI.tsx +0 -68
  279. package/src/Git/commit-selection.ts +0 -63
  280. package/src/Git/git-clone-utils.ts +0 -23
  281. package/src/Git/git-status.ts +0 -113
  282. package/src/Git/useGit.ts +0 -279
  283. package/src/Git/useGitStatus.ts +0 -78
  284. package/src/Settings/Settings.tsx +0 -118
  285. package/src/Settings/public-api.ts +0 -8
  286. package/src/WorkspacePicker/WorkspacePicker.tsx +0 -191
  287. package/src/WorkspacePicker/WorkspaceSettingsButton.tsx +0 -88
  288. package/src/WorkspacePicker/WorkspaceSettingsDialog.tsx +0 -121
  289. package/src/WorkspacePicker/index.ts +0 -2
  290. package/src/components/Dialog.tsx +0 -81
  291. package/src/editor.ts +0 -72
  292. package/src/hooks/index.ts +0 -2
  293. package/src/hooks/useDocumentSession.ts +0 -37
  294. package/src/icons.tsx +0 -48
  295. package/src/index.ts +0 -61
  296. package/src/preferences/theme.ts +0 -67
  297. package/src/preferences/versioning.ts +0 -69
  298. package/src/provider-lease.ts +0 -52
  299. package/src/types/pwa-dom.d.ts +0 -31
  300. /package/dist/{ExportDialog-MEUISWZX.js.map → ExportDialog-7LDIXJZ3.js.map} +0 -0
package/README.md CHANGED
@@ -74,6 +74,12 @@ import {
74
74
  } from '@bendyline/docblocks-react/export';
75
75
  ```
76
76
 
77
+ The shell overflow also offers **Share link with content embedded**. It creates
78
+ a bounded `#shared(<base64>)` URL containing a compressed, Markdown-only copy
79
+ and an optional initial Use mode. Opening the URL creates a session-only
80
+ workspace; generated links warn after 4,096 characters and are capped at
81
+ 32,768 characters.
82
+
77
83
  The export flow: quick re-export of the last configuration plus the full dialog — format (PDF, Word, PowerPoint, HTML, Markdown), visual theme, and page size.
78
84
 
79
85
  ## Hooks
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  ExportDialog
3
- } from "./chunk-AOVTHZU7.js";
3
+ } from "./chunk-UNYZQXWR.js";
4
4
  import "./chunk-4XXSWN3T.js";
5
+ import "./chunk-FMGTHSTX.js";
5
6
  import "./chunk-DD4VFJQI.js";
6
7
  export {
7
8
  ExportDialog
8
9
  };
9
- //# sourceMappingURL=ExportDialog-MEUISWZX.js.map
10
+ //# sourceMappingURL=ExportDialog-7LDIXJZ3.js.map
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  loadTransformStyleSummaries
3
3
  } from "./chunk-4XXSWN3T.js";
4
+ import {
5
+ Dialog
6
+ } from "./chunk-FMGTHSTX.js";
4
7
  import {
5
8
  DEFAULT_OPTIONS,
6
9
  FORMAT_EXTENSIONS,
@@ -18,18 +21,40 @@ import {
18
21
  useRef,
19
22
  useMemo
20
23
  } from "react";
21
- import { useEditorContext } from "@bendyline/squisq-editor-react";
24
+ import { useEditorContext, usePreviewSettings } from "@bendyline/squisq-editor-react";
22
25
  import { getThemeSummaries } from "@bendyline/squisq/schemas";
23
26
  import { parseMarkdown } from "@bendyline/squisq/markdown";
24
27
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
25
28
  var ExportDialog = lazy(
26
- () => import("./ExportDialog-MEUISWZX.js").then((module) => ({ default: module.ExportDialog }))
29
+ () => import("./ExportDialog-7LDIXJZ3.js").then((module) => ({ default: module.ExportDialog }))
30
+ );
31
+ var ShareDialog = lazy(
32
+ () => import("./ShareDialog-63ENBEDZ.js").then((module) => ({ default: module.ShareDialog }))
27
33
  );
28
34
  var runExportModulePromise = null;
29
35
  function loadRunExportModule() {
30
36
  runExportModulePromise ?? (runExportModulePromise = import("./run-export-ICTZITXC.js"));
31
37
  return runExportModulePromise;
32
38
  }
39
+ var SHARED_USE_MODES = Object.freeze({
40
+ slideshow: "slideshow",
41
+ video: "video",
42
+ page: "linear",
43
+ document: "page",
44
+ narrate: "narrate"
45
+ });
46
+ function SharedModeInitializer({ mode }) {
47
+ const appliedRef = useRef(false);
48
+ const { setActiveView } = useEditorContext();
49
+ const { setSelectedDisplayMode } = usePreviewSettings();
50
+ useEffect(() => {
51
+ if (appliedRef.current) return;
52
+ appliedRef.current = true;
53
+ setSelectedDisplayMode(SHARED_USE_MODES[mode]);
54
+ setActiveView("preview");
55
+ }, [mode, setActiveView, setSelectedDisplayMode]);
56
+ return null;
57
+ }
33
58
  var videoExportModulesPromise = null;
34
59
  function loadVideoExportModules() {
35
60
  videoExportModulesPromise ?? (videoExportModulesPromise = Promise.all([
@@ -43,6 +68,10 @@ function loadVideoExportModules() {
43
68
  })));
44
69
  return videoExportModulesPromise;
45
70
  }
71
+ function exportErrorMessage(caught) {
72
+ const detail = caught instanceof Error ? caught.message.trim() : "";
73
+ return detail ? `Export failed: ${detail}` : "Export failed. The document could not be exported.";
74
+ }
46
75
  function quickLabel(opts, transformSummaries) {
47
76
  const baseExt = FORMAT_EXTENSIONS[opts.format].toUpperCase().replace(".", "");
48
77
  const isRecursiveHtml = opts.format === "html" && opts.includeLinkedDocs;
@@ -73,11 +102,16 @@ function ExportToolbarControls({
73
102
  saveBlob,
74
103
  destinationAdapter,
75
104
  trigger = "menu",
76
- showVideoExport = true
105
+ showVideoExport = true,
106
+ colorScheme = "light",
107
+ videoExportPalette,
108
+ shareBaseUrl,
109
+ initialSharedMode = null
77
110
  }) {
78
111
  const { markdownSource, markdownDoc } = useEditorContext();
79
112
  const [menuOpen, setMenuOpen] = useState(false);
80
113
  const [dialogOpen, setDialogOpen] = useState(false);
114
+ const [shareDialogOpen, setShareDialogOpen] = useState(false);
81
115
  const [videoModalOpen, setVideoModalOpen] = useState(false);
82
116
  const [videoLoading, setVideoLoading] = useState(false);
83
117
  const [videoLoadError, setVideoLoadError] = useState(null);
@@ -85,6 +119,7 @@ function ExportToolbarControls({
85
119
  const [videoDoc, setVideoDoc] = useState(null);
86
120
  const [transformSummaries, setTransformSummaries] = useState([]);
87
121
  const [exporting, setExporting] = useState(false);
122
+ const [exportError, setExportError] = useState(null);
88
123
  const [destinationTarget, setDestinationTarget] = useState(null);
89
124
  const destinationRequestRef = useRef(0);
90
125
  const menuRef = useRef(null);
@@ -147,11 +182,20 @@ function ExportToolbarControls({
147
182
  );
148
183
  const handleOpenDialog = useCallback(() => {
149
184
  setMenuOpen(false);
185
+ setExportError(null);
150
186
  setDialogOpen(true);
151
187
  void refreshDestination(dialogInitial);
152
188
  }, [dialogInitial, refreshDestination]);
153
189
  const handleCloseDialog = useCallback(() => {
154
190
  setDialogOpen(false);
191
+ setExportError(null);
192
+ }, []);
193
+ const handleOpenShareDialog = useCallback(() => {
194
+ setMenuOpen(false);
195
+ setShareDialogOpen(true);
196
+ }, []);
197
+ const handleCloseShareDialog = useCallback(() => {
198
+ setShareDialogOpen(false);
155
199
  }, []);
156
200
  const handleOpenVideoModal = useCallback(async () => {
157
201
  setMenuOpen(false);
@@ -210,6 +254,7 @@ function ExportToolbarControls({
210
254
  const handleExport = useCallback(
211
255
  async (opts) => {
212
256
  setExporting(true);
257
+ setExportError(null);
213
258
  try {
214
259
  const { runExport } = await loadRunExportModule();
215
260
  await runExport(
@@ -219,9 +264,11 @@ function ExportToolbarControls({
219
264
  mediaContainer,
220
265
  destinationAdapter ? handleDestinationSaveBlob : saveBlob
221
266
  );
267
+ setDialogOpen(false);
268
+ } catch (caught) {
269
+ setExportError(exportErrorMessage(caught));
222
270
  } finally {
223
271
  setExporting(false);
224
- setDialogOpen(false);
225
272
  }
226
273
  },
227
274
  [
@@ -237,6 +284,7 @@ function ExportToolbarControls({
237
284
  if (!lastOptions) return;
238
285
  setMenuOpen(false);
239
286
  setExporting(true);
287
+ setExportError(null);
240
288
  try {
241
289
  saveExportOptions(lastOptions);
242
290
  const { runExport } = await loadRunExportModule();
@@ -254,6 +302,8 @@ function ExportToolbarControls({
254
302
  mediaContainer,
255
303
  destinationAdapter ? async (blob, filename) => saveToDestination(blob, filename, quickTarget) : saveBlob
256
304
  );
305
+ } catch (caught) {
306
+ setExportError(exportErrorMessage(caught));
257
307
  } finally {
258
308
  setExporting(false);
259
309
  }
@@ -266,8 +316,12 @@ function ExportToolbarControls({
266
316
  saveToDestination,
267
317
  selectedFile
268
318
  ]);
319
+ const handleDismissExportError = useCallback(() => {
320
+ setExportError(null);
321
+ }, []);
269
322
  const LoadedVideoExportModal = videoModules?.Modal;
270
323
  return /* @__PURE__ */ jsxs(Fragment, { children: [
324
+ initialSharedMode && /* @__PURE__ */ jsx(SharedModeInitializer, { mode: initialSharedMode }),
271
325
  trigger === "button" ? /* @__PURE__ */ jsx(
272
326
  "button",
273
327
  {
@@ -283,27 +337,60 @@ function ExportToolbarControls({
283
337
  /* @__PURE__ */ jsx(
284
338
  "button",
285
339
  {
340
+ type: "button",
286
341
  className: "db-toolbar-menu-trigger",
287
342
  onClick: handleToggleMenu,
288
- "aria-label": "More actions",
289
- title: "More actions",
290
- children: "\xB7\xB7\xB7"
343
+ "aria-label": "Export and share",
344
+ "aria-haspopup": "menu",
345
+ "aria-expanded": menuOpen,
346
+ title: "Export and share",
347
+ children: /* @__PURE__ */ jsx(ShareGlyph, {})
291
348
  }
292
349
  ),
293
- menuOpen && /* @__PURE__ */ jsxs("div", { className: "db-toolbar-menu-dropdown", children: [
350
+ menuOpen && /* @__PURE__ */ jsxs("div", { className: "db-toolbar-menu-dropdown", role: "menu", children: [
294
351
  lastOptions && /* @__PURE__ */ jsx(
295
352
  "button",
296
353
  {
354
+ type: "button",
355
+ role: "menuitem",
297
356
  className: "db-toolbar-menu-item",
298
357
  onClick: handleQuickExport,
299
358
  disabled: exporting,
300
359
  children: quickLabel(lastOptions, transformSummaries)
301
360
  }
302
361
  ),
303
- /* @__PURE__ */ jsx("button", { className: "db-toolbar-menu-item", onClick: handleOpenDialog, children: "Export..." }),
362
+ /* @__PURE__ */ jsx(
363
+ "button",
364
+ {
365
+ type: "button",
366
+ role: "menuitem",
367
+ className: "db-toolbar-menu-item",
368
+ onClick: handleOpenDialog,
369
+ children: "Export..."
370
+ }
371
+ ),
372
+ /* @__PURE__ */ jsx(
373
+ "button",
374
+ {
375
+ type: "button",
376
+ role: "menuitem",
377
+ className: "db-toolbar-menu-item",
378
+ onClick: handleOpenShareDialog,
379
+ children: "Share link with content embedded..."
380
+ }
381
+ ),
304
382
  showVideoExport && /* @__PURE__ */ jsxs(Fragment, { children: [
305
- /* @__PURE__ */ jsx("div", { className: "db-toolbar-menu-divider" }),
306
- /* @__PURE__ */ jsx("button", { className: "db-toolbar-menu-item", onClick: handleOpenVideoModal, children: "Export Video..." })
383
+ /* @__PURE__ */ jsx("div", { className: "db-toolbar-menu-divider", role: "separator" }),
384
+ /* @__PURE__ */ jsx(
385
+ "button",
386
+ {
387
+ type: "button",
388
+ role: "menuitem",
389
+ className: "db-toolbar-menu-item",
390
+ onClick: handleOpenVideoModal,
391
+ children: "Export Video..."
392
+ }
393
+ )
307
394
  ] })
308
395
  ] })
309
396
  ] }),
@@ -312,6 +399,7 @@ function ExportToolbarControls({
312
399
  {
313
400
  initial: dialogInitial,
314
401
  exporting,
402
+ error: exportError,
315
403
  destination: destinationAdapter ? {
316
404
  value: destinationTarget?.displayPath ?? "",
317
405
  onPick: handlePickDestination,
@@ -322,6 +410,32 @@ function ExportToolbarControls({
322
410
  onClose: handleCloseDialog
323
411
  }
324
412
  ) }),
413
+ exportError && !dialogOpen && /* @__PURE__ */ jsx(
414
+ Dialog,
415
+ {
416
+ title: "Export Document",
417
+ onClose: handleDismissExportError,
418
+ footer: /* @__PURE__ */ jsx(
419
+ "button",
420
+ {
421
+ type: "button",
422
+ className: "db-export-btn db-export-btn--secondary",
423
+ onClick: handleDismissExportError,
424
+ children: "Close"
425
+ }
426
+ ),
427
+ children: /* @__PURE__ */ jsx("p", { className: "db-export-error", role: "alert", children: exportError })
428
+ }
429
+ ),
430
+ shareDialogOpen && /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
431
+ ShareDialog,
432
+ {
433
+ markdown: markdownSource,
434
+ selectedFile,
435
+ baseUrl: shareBaseUrl ?? (typeof window === "undefined" ? "https://bendyline.github.io/docblocks/" : window.location.href),
436
+ onClose: handleCloseShareDialog
437
+ }
438
+ ) }),
325
439
  videoModalOpen && (videoLoading || videoLoadError) && /* @__PURE__ */ jsx("div", { className: "db-dialog-overlay", children: /* @__PURE__ */ jsxs("div", { className: "db-dialog", children: [
326
440
  /* @__PURE__ */ jsxs("div", { className: "db-dialog-header", children: [
327
441
  /* @__PURE__ */ jsx("h2", { className: "db-dialog-title", children: "Export Video" }),
@@ -342,6 +456,8 @@ function ExportToolbarControls({
342
456
  {
343
457
  doc: videoDoc,
344
458
  playerScript: videoModules.playerScript,
459
+ colorScheme,
460
+ uiPalette: videoExportPalette,
345
461
  onClose: handleCloseVideoModal
346
462
  }
347
463
  )
@@ -367,7 +483,26 @@ function ExportGlyph() {
367
483
  }
368
484
  );
369
485
  }
486
+ function ShareGlyph() {
487
+ return /* @__PURE__ */ jsxs(
488
+ "svg",
489
+ {
490
+ viewBox: "0 0 16 16",
491
+ fill: "none",
492
+ stroke: "currentColor",
493
+ strokeWidth: "1.5",
494
+ strokeLinecap: "round",
495
+ strokeLinejoin: "round",
496
+ "aria-hidden": "true",
497
+ children: [
498
+ /* @__PURE__ */ jsx("path", { d: "M8 10.5V1.75" }),
499
+ /* @__PURE__ */ jsx("path", { d: "M5.25 4.5 8 1.75l2.75 2.75" }),
500
+ /* @__PURE__ */ jsx("path", { d: "M4.25 6.75h-1a1.5 1.5 0 0 0-1.5 1.5v4.5a1.5 1.5 0 0 0 1.5 1.5h9.5a1.5 1.5 0 0 0 1.5-1.5v-4.5a1.5 1.5 0 0 0-1.5-1.5h-1" })
501
+ ]
502
+ }
503
+ );
504
+ }
370
505
  export {
371
506
  ExportToolbarControls
372
507
  };
373
- //# sourceMappingURL=ExportToolbarControls-D2YDWOXW.js.map
508
+ //# sourceMappingURL=ExportToolbarControls-GHAOJMH6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/Export/ExportToolbarControls.tsx"],"sourcesContent":["/**\n * ExportToolbarControls — toolbar-right slot content.\n *\n * Renders an export/share menu on the right side of the toolbar containing\n * document export, sharing, and video export actions.\n *\n * Must be rendered inside <EditorProvider> so useEditorContext() works.\n */\n\nimport {\n lazy,\n Suspense,\n useState,\n useCallback,\n useEffect,\n useRef,\n useMemo,\n type ComponentType,\n} from 'react';\nimport { useEditorContext, usePreviewSettings } from '@bendyline/squisq-editor-react';\nimport type { SharedDocumentMode } from '@bendyline/docblocks/share';\nimport { getThemeSummaries } from '@bendyline/squisq/schemas';\nimport { parseMarkdown } from '@bendyline/squisq/markdown';\nimport type { ContentContainer } from '@bendyline/squisq/storage';\nimport type { DisplayMode } from '@bendyline/squisq-react';\nimport type { VideoExportModalProps } from '@bendyline/squisq-video-react';\nimport type { ExportOptions } from './export-options.js';\nimport {\n DEFAULT_OPTIONS,\n FORMAT_EXTENSIONS,\n loadLastExportOptions,\n saveExportOptions,\n} from './export-options.js';\nimport type { ExportBlobSaver } from './run-export.js';\nimport { loadTransformStyleSummaries, type ExportSummaryOption } from './transform-summaries.js';\nimport { Dialog } from '../components/Dialog.js';\n\nconst ExportDialog = lazy(() =>\n import('./ExportDialog.js').then((module) => ({ default: module.ExportDialog })),\n);\nconst ShareDialog = lazy(() =>\n import('./ShareDialog.js').then((module) => ({ default: module.ShareDialog })),\n);\n\nlet runExportModulePromise: Promise<typeof import('./run-export.js')> | null = null;\n\nfunction loadRunExportModule(): Promise<typeof import('./run-export.js')> {\n runExportModulePromise ??= import('./run-export.js');\n return runExportModulePromise;\n}\n\nexport interface ExportToolbarControlsProps {\n /** Currently selected file path — used to derive the download filename. */\n selectedFile: string | null;\n /** Media container for resolving images during export. */\n mediaContainer?: ContentContainer | null;\n /** Override the default browser download behavior for host-provided save flows. */\n saveBlob?: ExportBlobSaver;\n /** Optional host adapter for displaying, picking, and saving to a native target path. */\n destinationAdapter?: ExportDestinationAdapter;\n /** Render the trigger as a direct Export button instead of the overflow menu. */\n trigger?: 'menu' | 'button';\n /** Whether to show video export in the overflow menu. */\n showVideoExport?: boolean;\n /** Resolved host color scheme for the video export dialog. */\n colorScheme?: 'light' | 'dark';\n /** Host palette overrides for the video export dialog and progress UI. */\n videoExportPalette?: VideoExportModalProps['uiPalette'];\n /** HTTP(S) DocBlocks page used as the base of generated shared links. */\n shareBaseUrl?: string;\n /** One-time Use mode supplied by an opened shared document link. */\n initialSharedMode?: SharedDocumentMode | null;\n}\n\n/** Host-specific operations behind the shared export destination control. */\nexport interface ExportDestinationTarget {\n grantId: string | null;\n displayPath: string;\n}\n\nexport interface ExportDestinationAdapter {\n resolveTarget: (filename: string) => Promise<ExportDestinationTarget>;\n pickTarget: (\n filename: string,\n currentTarget?: ExportDestinationTarget | null,\n ) => Promise<ExportDestinationTarget | null>;\n saveBlob: (\n blob: Blob,\n filename: string,\n target?: ExportDestinationTarget | null,\n ) => Promise<ExportDestinationTarget | null>;\n hint?: string;\n}\n\ntype ParsedMarkdown = ReturnType<typeof parseMarkdown>;\n\ninterface VideoExportModules {\n Modal: ComponentType<VideoExportModalProps>;\n markdownToDoc: (doc: ParsedMarkdown) => VideoExportModalProps['doc'];\n playerScript: string;\n}\n\nconst SHARED_USE_MODES: Readonly<Record<SharedDocumentMode, DisplayMode>> = Object.freeze({\n slideshow: 'slideshow',\n video: 'video',\n page: 'linear',\n document: 'page',\n narrate: 'narrate',\n});\n\nfunction SharedModeInitializer({ mode }: { mode: SharedDocumentMode }) {\n const appliedRef = useRef(false);\n const { setActiveView } = useEditorContext();\n const { setSelectedDisplayMode } = usePreviewSettings();\n\n useEffect(() => {\n if (appliedRef.current) return;\n appliedRef.current = true;\n setSelectedDisplayMode(SHARED_USE_MODES[mode]);\n setActiveView('preview');\n }, [mode, setActiveView, setSelectedDisplayMode]);\n\n return null;\n}\n\nlet videoExportModulesPromise: Promise<VideoExportModules> | null = null;\n\nfunction loadVideoExportModules(): Promise<VideoExportModules> {\n videoExportModulesPromise ??= Promise.all([\n import('@bendyline/squisq/doc'),\n import('@bendyline/squisq-video-react'),\n import('@bendyline/squisq-react/standalone-source'),\n ]).then(([docModule, videoModule, playerModule]) => ({\n Modal: videoModule.VideoExportModal,\n markdownToDoc: docModule.markdownToDoc,\n playerScript: playerModule.PLAYER_BUNDLE,\n }));\n return videoExportModulesPromise;\n}\n\n/**\n * Turn whatever `runExport` rejected with into something a user can act on.\n * The pipeline throws real `Error`s (unreadable image, converter failure,\n * destination write refused) whose messages are already user-facing.\n */\nfunction exportErrorMessage(caught: unknown): string {\n const detail = caught instanceof Error ? caught.message.trim() : '';\n return detail ? `Export failed: ${detail}` : 'Export failed. The document could not be exported.';\n}\n\n/** Build the quick-export label from saved options. */\nfunction quickLabel(opts: ExportOptions, transformSummaries: ExportSummaryOption[]): string {\n const baseExt = FORMAT_EXTENSIONS[opts.format].toUpperCase().replace('.', '');\n // Recursive HTML always emits a ZIP (multi-doc tree), regardless of\n // the saved `htmlBundle` value. Applies to both plain and rendered\n // styles since both now ship recursive bundle helpers.\n const isRecursiveHtml = opts.format === 'html' && opts.includeLinkedDocs;\n const ext =\n opts.format === 'html' && (opts.htmlBundle === 'zip' || isRecursiveHtml) ? 'ZIP' : baseExt;\n const parts: string[] = [];\n\n if (opts.format === 'html' && opts.htmlStyle === 'rendered') {\n parts.push('rendered');\n }\n if (isRecursiveHtml) {\n parts.push('linked docs');\n }\n // Plain HTML also applies themes now (squisq's `markdownDocToPlainHtml`\n // emits theme-driven CSS), so include the theme name in the quick-\n // export label for every HTML style — not just rendered.\n if (opts.themeId !== 'standard') {\n const theme = getThemeSummaries().find((t) => t.id === opts.themeId);\n if (theme) parts.push(theme.name);\n }\n if (opts.format === 'pptx' && opts.transformStyle) {\n const transform = transformSummaries.find((t) => t.id === opts.transformStyle);\n if (transform) parts.push(transform.name);\n }\n\n if (parts.length > 0) {\n return `Export ${ext} with ${parts.join(' + ')}`;\n }\n return `Export ${ext}`;\n}\n\nexport function ExportToolbarControls({\n selectedFile,\n mediaContainer,\n saveBlob,\n destinationAdapter,\n trigger = 'menu',\n showVideoExport = true,\n colorScheme = 'light',\n videoExportPalette,\n shareBaseUrl,\n initialSharedMode = null,\n}: ExportToolbarControlsProps) {\n const { markdownSource, markdownDoc } = useEditorContext();\n const [menuOpen, setMenuOpen] = useState(false);\n const [dialogOpen, setDialogOpen] = useState(false);\n const [shareDialogOpen, setShareDialogOpen] = useState(false);\n const [videoModalOpen, setVideoModalOpen] = useState(false);\n const [videoLoading, setVideoLoading] = useState(false);\n const [videoLoadError, setVideoLoadError] = useState<string | null>(null);\n const [videoModules, setVideoModules] = useState<VideoExportModules | null>(null);\n const [videoDoc, setVideoDoc] = useState<VideoExportModalProps['doc'] | null>(null);\n const [transformSummaries, setTransformSummaries] = useState<ExportSummaryOption[]>([]);\n const [exporting, setExporting] = useState(false);\n const [exportError, setExportError] = useState<string | null>(null);\n const [destinationTarget, setDestinationTarget] = useState<ExportDestinationTarget | null>(null);\n const destinationRequestRef = useRef(0);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const lastOptions = loadLastExportOptions();\n\n /** Doc's currently-set squisq theme, pulled from the markdown\n * frontmatter. The Document Settings dialog and Theme Customizer\n * write the theme under `squisq-theme` (canonical) or `theme`\n * (legacy); some older docs persist it as `themeId`. We honor all\n * three so an author who set their theme anywhere upstream sees it\n * pre-selected in the export dialog. */\n const docThemeId = useMemo(() => {\n const fm = markdownDoc?.frontmatter as Record<string, unknown> | undefined;\n if (!fm) return null;\n const candidates = [fm['squisq-theme'], fm['theme'], fm['themeId']];\n for (const v of candidates) {\n if (typeof v === 'string' && v.trim()) return v.trim();\n }\n return null;\n }, [markdownDoc]);\n\n /** Options used to populate the export dialog. Layered: built-in\n * defaults → user's last-chosen export options (if any) → doc's\n * current frontmatter theme (wins). The frontmatter override\n * guarantees that \"set theme in the editor, then export\" pre-selects\n * the right theme instead of resurrecting whatever the user picked\n * for some unrelated previous doc. */\n const dialogInitial = useMemo(() => {\n const base = lastOptions ?? DEFAULT_OPTIONS;\n return docThemeId ? { ...base, themeId: docThemeId } : base;\n }, [lastOptions, docThemeId]);\n\n // Close menu on outside click\n useEffect(() => {\n if (!menuOpen) return;\n const onPointerDown = (e: PointerEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setMenuOpen(false);\n }\n };\n document.addEventListener('pointerdown', onPointerDown);\n return () => document.removeEventListener('pointerdown', onPointerDown);\n }, [menuOpen]);\n\n useEffect(() => {\n if (\n !menuOpen ||\n lastOptions?.format !== 'pptx' ||\n !lastOptions.transformStyle ||\n transformSummaries.length > 0\n ) {\n return;\n }\n\n let cancelled = false;\n loadTransformStyleSummaries()\n .then((nextSummaries) => {\n if (!cancelled) setTransformSummaries(nextSummaries);\n })\n .catch(() => {\n if (!cancelled) setTransformSummaries([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [lastOptions?.format, lastOptions?.transformStyle, menuOpen, transformSummaries.length]);\n\n const handleToggleMenu = useCallback(() => {\n setMenuOpen((prev) => !prev);\n }, []);\n\n const refreshDestination = useCallback(\n async (options: ExportOptions) => {\n if (!destinationAdapter) return;\n\n const requestId = destinationRequestRef.current + 1;\n destinationRequestRef.current = requestId;\n\n try {\n const { buildExportFilename } = await loadRunExportModule();\n const filename = buildExportFilename(selectedFile, options);\n const target = await destinationAdapter.resolveTarget(filename);\n if (destinationRequestRef.current === requestId) setDestinationTarget(target);\n } catch {\n if (destinationRequestRef.current === requestId) setDestinationTarget(null);\n }\n },\n [destinationAdapter, selectedFile],\n );\n\n const handleOpenDialog = useCallback(() => {\n setMenuOpen(false);\n setExportError(null);\n setDialogOpen(true);\n void refreshDestination(dialogInitial);\n }, [dialogInitial, refreshDestination]);\n\n const handleCloseDialog = useCallback(() => {\n setDialogOpen(false);\n setExportError(null);\n }, []);\n\n const handleOpenShareDialog = useCallback(() => {\n setMenuOpen(false);\n setShareDialogOpen(true);\n }, []);\n\n const handleCloseShareDialog = useCallback(() => {\n setShareDialogOpen(false);\n }, []);\n\n const handleOpenVideoModal = useCallback(async () => {\n setMenuOpen(false);\n setVideoModalOpen(true);\n setVideoLoading(true);\n setVideoLoadError(null);\n\n try {\n const modules = videoModules ?? (await loadVideoExportModules());\n setVideoModules(modules);\n setVideoDoc(modules.markdownToDoc(parseMarkdown(markdownSource)));\n } catch {\n setVideoLoadError('Video export could not be loaded.');\n } finally {\n setVideoLoading(false);\n }\n }, [markdownSource, videoModules]);\n\n const handleCloseVideoModal = useCallback(() => {\n setVideoModalOpen(false);\n setVideoDoc(null);\n setVideoLoadError(null);\n }, []);\n\n const handleOptionsChange = useCallback(\n (options: ExportOptions) => {\n void refreshDestination(options);\n },\n [refreshDestination],\n );\n\n const handlePickDestination = useCallback(\n async (options: ExportOptions) => {\n if (!destinationAdapter) return;\n try {\n const { buildExportFilename } = await loadRunExportModule();\n const filename = buildExportFilename(selectedFile, options);\n const pickedTarget = await destinationAdapter.pickTarget(filename, destinationTarget);\n if (pickedTarget === null) return;\n setDestinationTarget(pickedTarget);\n } catch {\n // Native hosts surface picker failures through their own UI channel.\n }\n },\n [destinationAdapter, destinationTarget, selectedFile],\n );\n\n const saveToDestination = useCallback(\n async (blob: Blob, filename: string, target: ExportDestinationTarget | null) => {\n if (!destinationAdapter) return;\n const savedTarget = await destinationAdapter.saveBlob(blob, filename, target);\n if (savedTarget) setDestinationTarget(savedTarget);\n },\n [destinationAdapter],\n );\n\n const handleDestinationSaveBlob = useCallback(\n async (blob: Blob, filename: string) => {\n await saveToDestination(blob, filename, destinationTarget);\n },\n [destinationTarget, saveToDestination],\n );\n\n const handleExport = useCallback(\n async (opts: ExportOptions) => {\n setExporting(true);\n setExportError(null);\n try {\n const { runExport } = await loadRunExportModule();\n await runExport(\n markdownSource,\n selectedFile,\n opts,\n mediaContainer,\n destinationAdapter ? handleDestinationSaveBlob : saveBlob,\n );\n // Only a completed export dismisses the dialog. Closing in a\n // `finally` used to make a failure look exactly like a success.\n setDialogOpen(false);\n } catch (caught: unknown) {\n setExportError(exportErrorMessage(caught));\n } finally {\n setExporting(false);\n }\n },\n [\n markdownSource,\n selectedFile,\n mediaContainer,\n destinationAdapter,\n handleDestinationSaveBlob,\n saveBlob,\n ],\n );\n\n const handleQuickExport = useCallback(async () => {\n if (!lastOptions) return;\n setMenuOpen(false);\n setExporting(true);\n setExportError(null);\n try {\n saveExportOptions(lastOptions);\n const { runExport } = await loadRunExportModule();\n let quickTarget: ExportDestinationTarget | null = null;\n if (destinationAdapter) {\n const { buildExportFilename } = await loadRunExportModule();\n quickTarget = await destinationAdapter.resolveTarget(\n buildExportFilename(selectedFile, lastOptions),\n );\n }\n await runExport(\n markdownSource,\n selectedFile,\n lastOptions,\n mediaContainer,\n destinationAdapter\n ? async (blob, filename) => saveToDestination(blob, filename, quickTarget)\n : saveBlob,\n );\n } catch (caught: unknown) {\n // No dialog is open on this path, so the failure gets its own —\n // same shape as the video-export load failure below.\n setExportError(exportErrorMessage(caught));\n } finally {\n setExporting(false);\n }\n }, [\n destinationAdapter,\n lastOptions,\n markdownSource,\n mediaContainer,\n saveBlob,\n saveToDestination,\n selectedFile,\n ]);\n\n const handleDismissExportError = useCallback(() => {\n setExportError(null);\n }, []);\n\n const LoadedVideoExportModal = videoModules?.Modal;\n\n return (\n <>\n {initialSharedMode && <SharedModeInitializer mode={initialSharedMode} />}\n {trigger === 'button' ? (\n <button\n type=\"button\"\n className=\"squisq-toolbar-button db-toolbar-export-trigger\"\n onClick={handleOpenDialog}\n disabled={exporting}\n aria-label=\"Export document\"\n data-tooltip={exporting ? 'Exporting...' : 'Export document'}\n >\n <ExportGlyph />\n </button>\n ) : (\n <div className=\"db-toolbar-menu\" ref={menuRef}>\n <button\n type=\"button\"\n className=\"db-toolbar-menu-trigger\"\n onClick={handleToggleMenu}\n aria-label=\"Export and share\"\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n title=\"Export and share\"\n >\n <ShareGlyph />\n </button>\n\n {menuOpen && (\n <div className=\"db-toolbar-menu-dropdown\" role=\"menu\">\n {lastOptions && (\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"db-toolbar-menu-item\"\n onClick={handleQuickExport}\n disabled={exporting}\n >\n {quickLabel(lastOptions, transformSummaries)}\n </button>\n )}\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"db-toolbar-menu-item\"\n onClick={handleOpenDialog}\n >\n Export...\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"db-toolbar-menu-item\"\n onClick={handleOpenShareDialog}\n >\n Share link with content embedded...\n </button>\n {showVideoExport && (\n <>\n <div className=\"db-toolbar-menu-divider\" role=\"separator\" />\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"db-toolbar-menu-item\"\n onClick={handleOpenVideoModal}\n >\n Export Video...\n </button>\n </>\n )}\n </div>\n )}\n </div>\n )}\n\n {dialogOpen && (\n <Suspense fallback={null}>\n <ExportDialog\n initial={dialogInitial}\n exporting={exporting}\n error={exportError}\n destination={\n destinationAdapter\n ? {\n value: destinationTarget?.displayPath ?? '',\n onPick: handlePickDestination,\n hint: destinationAdapter.hint,\n }\n : undefined\n }\n onExport={handleExport}\n onOptionsChange={destinationAdapter ? handleOptionsChange : undefined}\n onClose={handleCloseDialog}\n />\n </Suspense>\n )}\n\n {/* Quick export fails with no dialog open — give the failure its own,\n mirroring the video-export load-failure surface below. */}\n {exportError && !dialogOpen && (\n <Dialog\n title=\"Export Document\"\n onClose={handleDismissExportError}\n footer={\n <button\n type=\"button\"\n className=\"db-export-btn db-export-btn--secondary\"\n onClick={handleDismissExportError}\n >\n Close\n </button>\n }\n >\n <p className=\"db-export-error\" role=\"alert\">\n {exportError}\n </p>\n </Dialog>\n )}\n\n {shareDialogOpen && (\n <Suspense fallback={null}>\n <ShareDialog\n markdown={markdownSource}\n selectedFile={selectedFile}\n baseUrl={\n shareBaseUrl ??\n (typeof window === 'undefined'\n ? 'https://bendyline.github.io/docblocks/'\n : window.location.href)\n }\n onClose={handleCloseShareDialog}\n />\n </Suspense>\n )}\n\n {videoModalOpen && (videoLoading || videoLoadError) && (\n <div className=\"db-dialog-overlay\">\n <div className=\"db-dialog\">\n <div className=\"db-dialog-header\">\n <h2 className=\"db-dialog-title\">Export Video</h2>\n <button\n className=\"db-dialog-close\"\n onClick={handleCloseVideoModal}\n aria-label=\"Close\"\n >\n &times;\n </button>\n </div>\n <div className=\"db-dialog-body\">\n <p className=\"db-export-hint\">{videoLoadError ?? 'Loading...'}</p>\n </div>\n </div>\n </div>\n )}\n\n {videoModalOpen &&\n videoModules &&\n LoadedVideoExportModal &&\n videoDoc &&\n !videoLoading &&\n !videoLoadError && (\n <LoadedVideoExportModal\n doc={videoDoc}\n playerScript={videoModules.playerScript}\n colorScheme={colorScheme}\n uiPalette={videoExportPalette}\n onClose={handleCloseVideoModal}\n />\n )}\n </>\n );\n}\n\nfunction ExportGlyph() {\n return (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M4.5 1.75h4.25L12 5v7.25a1.5 1.5 0 0 1-1.5 1.5h-6A1.5 1.5 0 0 1 3 12.25v-9a1.5 1.5 0 0 1 1.5-1.5z\" />\n <path d=\"M8.75 1.75V5h3.25\" />\n <path d=\"M6 8.75h4.5\" />\n <path d=\"M8.75 7 10.5 8.75 8.75 10.5\" />\n </svg>\n );\n}\n\nfunction ShareGlyph() {\n return (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M8 10.5V1.75\" />\n <path d=\"M5.25 4.5 8 1.75l2.75 2.75\" />\n <path d=\"M4.25 6.75h-1a1.5 1.5 0 0 0-1.5 1.5v4.5a1.5 1.5 0 0 0 1.5 1.5h9.5a1.5 1.5 0 0 0 1.5-1.5v-4.5a1.5 1.5 0 0 0-1.5-1.5h-1\" />\n </svg>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,3 +1,6 @@
1
+ import {
2
+ useMenuKeyboard
3
+ } from "./chunk-57ZJJOC5.js";
1
4
  import {
2
5
  isFileDirty,
3
6
  useGitContext
@@ -9,11 +12,12 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
12
  function GitToolbarControl({ selectedFile }) {
10
13
  const git = useGitContext();
11
14
  const [menuOpen, setMenuOpen] = useState(false);
12
- const menuRef = useRef(null);
15
+ const rootRef = useRef(null);
16
+ const { menuRef, triggerRef, handleMenuKeyDown, handleTriggerKeyDown, closeMenu } = useMenuKeyboard(menuOpen, setMenuOpen);
13
17
  useEffect(() => {
14
18
  if (!menuOpen) return;
15
19
  const onPointerDown = (e) => {
16
- if (menuRef.current && !menuRef.current.contains(e.target)) {
20
+ if (rootRef.current && !rootRef.current.contains(e.target)) {
17
21
  setMenuOpen(false);
18
22
  }
19
23
  };
@@ -24,24 +28,26 @@ function GitToolbarControl({ selectedFile }) {
24
28
  const dirty = isFileDirty(git.status, selectedFile);
25
29
  const label = dirty ? "Git actions (file modified)" : "Git actions";
26
30
  const openDiff = () => {
27
- setMenuOpen(false);
31
+ closeMenu(false);
28
32
  git.openDialog({ kind: "diff", path: selectedFile });
29
33
  };
30
34
  const openHistory = () => {
31
- setMenuOpen(false);
35
+ closeMenu(false);
32
36
  git.openDialog({ kind: "history", path: selectedFile });
33
37
  };
34
38
  const openOnRemote = () => {
35
- setMenuOpen(false);
39
+ closeMenu(false);
36
40
  git.openOnRemote(selectedFile);
37
41
  };
38
- return /* @__PURE__ */ jsxs("div", { className: "db-toolbar-menu", ref: menuRef, children: [
42
+ return /* @__PURE__ */ jsxs("div", { className: "db-toolbar-menu", ref: rootRef, children: [
39
43
  /* @__PURE__ */ jsxs(
40
44
  "button",
41
45
  {
46
+ ref: triggerRef,
42
47
  type: "button",
43
48
  className: "squisq-toolbar-button db-git-toolbar-trigger",
44
49
  onClick: () => setMenuOpen((prev) => !prev),
50
+ onKeyDown: handleTriggerKeyDown,
45
51
  "aria-label": label,
46
52
  "aria-haspopup": "menu",
47
53
  "aria-expanded": menuOpen,
@@ -52,42 +58,55 @@ function GitToolbarControl({ selectedFile }) {
52
58
  ]
53
59
  }
54
60
  ),
55
- menuOpen && /* @__PURE__ */ jsxs("div", { className: "db-toolbar-menu-dropdown", role: "menu", children: [
56
- /* @__PURE__ */ jsx(
57
- "button",
58
- {
59
- type: "button",
60
- role: "menuitem",
61
- className: "db-toolbar-menu-item",
62
- disabled: !dirty,
63
- onClick: openDiff,
64
- children: "View changes"
65
- }
66
- ),
67
- /* @__PURE__ */ jsx(
68
- "button",
69
- {
70
- type: "button",
71
- role: "menuitem",
72
- className: "db-toolbar-menu-item",
73
- onClick: openHistory,
74
- children: "File history\u2026"
75
- }
76
- ),
77
- git.remoteWeb && /* @__PURE__ */ jsxs(
78
- "button",
79
- {
80
- type: "button",
81
- role: "menuitem",
82
- className: "db-toolbar-menu-item",
83
- onClick: openOnRemote,
84
- children: [
85
- "Open on ",
86
- git.remoteWeb.host
87
- ]
88
- }
89
- )
90
- ] })
61
+ menuOpen && /* @__PURE__ */ jsxs(
62
+ "div",
63
+ {
64
+ ref: menuRef,
65
+ className: "db-toolbar-menu-dropdown",
66
+ role: "menu",
67
+ "aria-label": label,
68
+ onKeyDown: handleMenuKeyDown,
69
+ children: [
70
+ /* @__PURE__ */ jsx(
71
+ "button",
72
+ {
73
+ type: "button",
74
+ role: "menuitem",
75
+ tabIndex: -1,
76
+ className: "db-toolbar-menu-item",
77
+ disabled: !dirty,
78
+ onClick: openDiff,
79
+ children: "View changes"
80
+ }
81
+ ),
82
+ /* @__PURE__ */ jsx(
83
+ "button",
84
+ {
85
+ type: "button",
86
+ role: "menuitem",
87
+ tabIndex: -1,
88
+ className: "db-toolbar-menu-item",
89
+ onClick: openHistory,
90
+ children: "File history\u2026"
91
+ }
92
+ ),
93
+ git.remoteWeb && /* @__PURE__ */ jsxs(
94
+ "button",
95
+ {
96
+ type: "button",
97
+ role: "menuitem",
98
+ tabIndex: -1,
99
+ className: "db-toolbar-menu-item",
100
+ onClick: openOnRemote,
101
+ children: [
102
+ "Open on ",
103
+ git.remoteWeb.host
104
+ ]
105
+ }
106
+ )
107
+ ]
108
+ }
109
+ )
91
110
  ] });
92
111
  }
93
112
  function BranchGlyph() {
@@ -114,4 +133,4 @@ function BranchGlyph() {
114
133
  export {
115
134
  GitToolbarControl
116
135
  };
117
- //# sourceMappingURL=GitToolbarControl-LMIR4R7I.js.map
136
+ //# sourceMappingURL=GitToolbarControl-GNMRVKWQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/Git/GitToolbarControl.tsx"],"sourcesContent":["/**\n * GitToolbarControl — per-file git actions in the editor toolbar.\n *\n * A single branch-glyph button (styled like the export trigger) opening a\n * small dropdown: view working-tree changes, per-file history, and \"Open\n * on <host>\" when a web remote is known. A dot overlay marks the selected\n * file as modified. Null-renders without a git context, a repository, or a\n * selected file. Deliberately has no editor dependency.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport { useGitContext } from './GitContext.js';\nimport { isFileDirty } from './git-status.js';\nimport { useMenuKeyboard } from './useMenuKeyboard.js';\n\nexport interface GitToolbarControlProps {\n /** Currently selected file path (slash-prefixed), or null. */\n selectedFile: string | null;\n}\n\nexport function GitToolbarControl({ selectedFile }: GitToolbarControlProps) {\n const git = useGitContext();\n const [menuOpen, setMenuOpen] = useState(false);\n /** Wraps trigger + menu — the outside-click hit test, not the menu itself. */\n const rootRef = useRef<HTMLDivElement>(null);\n const { menuRef, triggerRef, handleMenuKeyDown, handleTriggerKeyDown, closeMenu } =\n useMenuKeyboard(menuOpen, setMenuOpen);\n\n // Close on outside click (same pointerdown pattern as ExportToolbarControls).\n useEffect(() => {\n if (!menuOpen) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) {\n setMenuOpen(false);\n }\n };\n document.addEventListener('pointerdown', onPointerDown);\n return () => document.removeEventListener('pointerdown', onPointerDown);\n }, [menuOpen]);\n\n if (!git || !git.repo || !selectedFile) return null;\n\n const dirty = isFileDirty(git.status, selectedFile);\n const label = dirty ? 'Git actions (file modified)' : 'Git actions';\n\n // Each of these replaces the menu with a dialog, so focus belongs there,\n // not back on the trigger.\n const openDiff = () => {\n closeMenu(false);\n git.openDialog({ kind: 'diff', path: selectedFile });\n };\n const openHistory = () => {\n closeMenu(false);\n git.openDialog({ kind: 'history', path: selectedFile });\n };\n const openOnRemote = () => {\n closeMenu(false);\n git.openOnRemote(selectedFile);\n };\n\n return (\n <div className=\"db-toolbar-menu\" ref={rootRef}>\n <button\n ref={triggerRef}\n type=\"button\"\n className=\"squisq-toolbar-button db-git-toolbar-trigger\"\n onClick={() => setMenuOpen((prev) => !prev)}\n onKeyDown={handleTriggerKeyDown}\n aria-label={label}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n data-tooltip={label}\n >\n <BranchGlyph />\n {dirty && <span className=\"db-git-toolbar-dot\" aria-hidden=\"true\" />}\n </button>\n\n {menuOpen && (\n <div\n ref={menuRef}\n className=\"db-toolbar-menu-dropdown\"\n role=\"menu\"\n aria-label={label}\n onKeyDown={handleMenuKeyDown}\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-toolbar-menu-item\"\n disabled={!dirty}\n onClick={openDiff}\n >\n View changes\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-toolbar-menu-item\"\n onClick={openHistory}\n >\n File history…\n </button>\n {git.remoteWeb && (\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-toolbar-menu-item\"\n onClick={openOnRemote}\n >\n Open on {git.remoteWeb.host}\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction BranchGlyph() {\n return (\n <svg\n viewBox=\"0 0 16 16\"\n width=\"16\"\n height=\"16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <circle cx=\"4.5\" cy=\"12\" r=\"2\" />\n <circle cx=\"11.5\" cy=\"4\" r=\"2\" />\n <path d=\"M4.5 10V7.5A2.5 2.5 0 0 1 7 5h2.5\" />\n </svg>\n );\n}\n"],"mappings":"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","names":[]}