@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
@@ -1,511 +0,0 @@
1
- /**
2
- * ExportToolbarControls — toolbar-right slot content.
3
- *
4
- * Renders a "..." overflow menu on the right side of the toolbar
5
- * containing export actions (document export + video export).
6
- *
7
- * Must be rendered inside <EditorProvider> so useEditorContext() works.
8
- */
9
-
10
- import {
11
- lazy,
12
- Suspense,
13
- useState,
14
- useCallback,
15
- useEffect,
16
- useRef,
17
- useMemo,
18
- type ComponentType,
19
- } from 'react';
20
- import { useEditorContext } from '@bendyline/squisq-editor-react';
21
- import { getThemeSummaries } from '@bendyline/squisq/schemas';
22
- import { parseMarkdown } from '@bendyline/squisq/markdown';
23
- import type { ContentContainer } from '@bendyline/squisq/storage';
24
- import type { VideoExportModalProps } from '@bendyline/squisq-video-react';
25
- import type { ExportOptions } from './export-options.js';
26
- import {
27
- DEFAULT_OPTIONS,
28
- FORMAT_EXTENSIONS,
29
- loadLastExportOptions,
30
- saveExportOptions,
31
- } from './export-options.js';
32
- import type { ExportBlobSaver } from './run-export.js';
33
- import { loadTransformStyleSummaries, type ExportSummaryOption } from './transform-summaries.js';
34
-
35
- const ExportDialog = lazy(() =>
36
- import('./ExportDialog.js').then((module) => ({ default: module.ExportDialog })),
37
- );
38
-
39
- let runExportModulePromise: Promise<typeof import('./run-export.js')> | null = null;
40
-
41
- function loadRunExportModule(): Promise<typeof import('./run-export.js')> {
42
- runExportModulePromise ??= import('./run-export.js');
43
- return runExportModulePromise;
44
- }
45
-
46
- export interface ExportToolbarControlsProps {
47
- /** Currently selected file path — used to derive the download filename. */
48
- selectedFile: string | null;
49
- /** Media container for resolving images during export. */
50
- mediaContainer?: ContentContainer | null;
51
- /** Override the default browser download behavior for host-provided save flows. */
52
- saveBlob?: ExportBlobSaver;
53
- /** Optional host adapter for displaying, picking, and saving to a native target path. */
54
- destinationAdapter?: ExportDestinationAdapter;
55
- /** Render the trigger as a direct Export button instead of the overflow menu. */
56
- trigger?: 'menu' | 'button';
57
- /** Whether to show video export in the overflow menu. */
58
- showVideoExport?: boolean;
59
- }
60
-
61
- /** Host-specific operations behind the shared export destination control. */
62
- export interface ExportDestinationTarget {
63
- grantId: string | null;
64
- displayPath: string;
65
- }
66
-
67
- export interface ExportDestinationAdapter {
68
- resolveTarget: (filename: string) => Promise<ExportDestinationTarget>;
69
- pickTarget: (
70
- filename: string,
71
- currentTarget?: ExportDestinationTarget | null,
72
- ) => Promise<ExportDestinationTarget | null>;
73
- saveBlob: (
74
- blob: Blob,
75
- filename: string,
76
- target?: ExportDestinationTarget | null,
77
- ) => Promise<ExportDestinationTarget | null>;
78
- hint?: string;
79
- }
80
-
81
- type ParsedMarkdown = ReturnType<typeof parseMarkdown>;
82
-
83
- interface VideoExportModules {
84
- Modal: ComponentType<VideoExportModalProps>;
85
- markdownToDoc: (doc: ParsedMarkdown) => VideoExportModalProps['doc'];
86
- playerScript: string;
87
- }
88
-
89
- let videoExportModulesPromise: Promise<VideoExportModules> | null = null;
90
-
91
- function loadVideoExportModules(): Promise<VideoExportModules> {
92
- videoExportModulesPromise ??= Promise.all([
93
- import('@bendyline/squisq/doc'),
94
- import('@bendyline/squisq-video-react'),
95
- import('@bendyline/squisq-react/standalone-source'),
96
- ]).then(([docModule, videoModule, playerModule]) => ({
97
- Modal: videoModule.VideoExportModal,
98
- markdownToDoc: docModule.markdownToDoc,
99
- playerScript: playerModule.PLAYER_BUNDLE,
100
- }));
101
- return videoExportModulesPromise;
102
- }
103
-
104
- /** Build the quick-export label from saved options. */
105
- function quickLabel(opts: ExportOptions, transformSummaries: ExportSummaryOption[]): string {
106
- const baseExt = FORMAT_EXTENSIONS[opts.format].toUpperCase().replace('.', '');
107
- // Recursive HTML always emits a ZIP (multi-doc tree), regardless of
108
- // the saved `htmlBundle` value. Applies to both plain and rendered
109
- // styles since both now ship recursive bundle helpers.
110
- const isRecursiveHtml = opts.format === 'html' && opts.includeLinkedDocs;
111
- const ext =
112
- opts.format === 'html' && (opts.htmlBundle === 'zip' || isRecursiveHtml) ? 'ZIP' : baseExt;
113
- const parts: string[] = [];
114
-
115
- if (opts.format === 'html' && opts.htmlStyle === 'rendered') {
116
- parts.push('rendered');
117
- }
118
- if (isRecursiveHtml) {
119
- parts.push('linked docs');
120
- }
121
- // Plain HTML also applies themes now (squisq's `markdownDocToPlainHtml`
122
- // emits theme-driven CSS), so include the theme name in the quick-
123
- // export label for every HTML style — not just rendered.
124
- if (opts.themeId !== 'standard') {
125
- const theme = getThemeSummaries().find((t) => t.id === opts.themeId);
126
- if (theme) parts.push(theme.name);
127
- }
128
- if (opts.format === 'pptx' && opts.transformStyle) {
129
- const transform = transformSummaries.find((t) => t.id === opts.transformStyle);
130
- if (transform) parts.push(transform.name);
131
- }
132
-
133
- if (parts.length > 0) {
134
- return `Export ${ext} with ${parts.join(' + ')}`;
135
- }
136
- return `Export ${ext}`;
137
- }
138
-
139
- export function ExportToolbarControls({
140
- selectedFile,
141
- mediaContainer,
142
- saveBlob,
143
- destinationAdapter,
144
- trigger = 'menu',
145
- showVideoExport = true,
146
- }: ExportToolbarControlsProps) {
147
- const { markdownSource, markdownDoc } = useEditorContext();
148
- const [menuOpen, setMenuOpen] = useState(false);
149
- const [dialogOpen, setDialogOpen] = useState(false);
150
- const [videoModalOpen, setVideoModalOpen] = useState(false);
151
- const [videoLoading, setVideoLoading] = useState(false);
152
- const [videoLoadError, setVideoLoadError] = useState<string | null>(null);
153
- const [videoModules, setVideoModules] = useState<VideoExportModules | null>(null);
154
- const [videoDoc, setVideoDoc] = useState<VideoExportModalProps['doc'] | null>(null);
155
- const [transformSummaries, setTransformSummaries] = useState<ExportSummaryOption[]>([]);
156
- const [exporting, setExporting] = useState(false);
157
- const [destinationTarget, setDestinationTarget] = useState<ExportDestinationTarget | null>(null);
158
- const destinationRequestRef = useRef(0);
159
- const menuRef = useRef<HTMLDivElement>(null);
160
-
161
- const lastOptions = loadLastExportOptions();
162
-
163
- /** Doc's currently-set squisq theme, pulled from the markdown
164
- * frontmatter. The Document Settings dialog and Theme Customizer
165
- * write the theme under `squisq-theme` (canonical) or `theme`
166
- * (legacy); some older docs persist it as `themeId`. We honor all
167
- * three so an author who set their theme anywhere upstream sees it
168
- * pre-selected in the export dialog. */
169
- const docThemeId = useMemo(() => {
170
- const fm = markdownDoc?.frontmatter as Record<string, unknown> | undefined;
171
- if (!fm) return null;
172
- const candidates = [fm['squisq-theme'], fm['theme'], fm['themeId']];
173
- for (const v of candidates) {
174
- if (typeof v === 'string' && v.trim()) return v.trim();
175
- }
176
- return null;
177
- }, [markdownDoc]);
178
-
179
- /** Options used to populate the export dialog. Layered: built-in
180
- * defaults → user's last-chosen export options (if any) → doc's
181
- * current frontmatter theme (wins). The frontmatter override
182
- * guarantees that "set theme in the editor, then export" pre-selects
183
- * the right theme instead of resurrecting whatever the user picked
184
- * for some unrelated previous doc. */
185
- const dialogInitial = useMemo(() => {
186
- const base = lastOptions ?? DEFAULT_OPTIONS;
187
- return docThemeId ? { ...base, themeId: docThemeId } : base;
188
- }, [lastOptions, docThemeId]);
189
-
190
- // Close menu on outside click
191
- useEffect(() => {
192
- if (!menuOpen) return;
193
- const onPointerDown = (e: PointerEvent) => {
194
- if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
195
- setMenuOpen(false);
196
- }
197
- };
198
- document.addEventListener('pointerdown', onPointerDown);
199
- return () => document.removeEventListener('pointerdown', onPointerDown);
200
- }, [menuOpen]);
201
-
202
- useEffect(() => {
203
- if (
204
- !menuOpen ||
205
- lastOptions?.format !== 'pptx' ||
206
- !lastOptions.transformStyle ||
207
- transformSummaries.length > 0
208
- ) {
209
- return;
210
- }
211
-
212
- let cancelled = false;
213
- loadTransformStyleSummaries()
214
- .then((nextSummaries) => {
215
- if (!cancelled) setTransformSummaries(nextSummaries);
216
- })
217
- .catch(() => {
218
- if (!cancelled) setTransformSummaries([]);
219
- });
220
-
221
- return () => {
222
- cancelled = true;
223
- };
224
- }, [lastOptions?.format, lastOptions?.transformStyle, menuOpen, transformSummaries.length]);
225
-
226
- const handleToggleMenu = useCallback(() => {
227
- setMenuOpen((prev) => !prev);
228
- }, []);
229
-
230
- const refreshDestination = useCallback(
231
- async (options: ExportOptions) => {
232
- if (!destinationAdapter) return;
233
-
234
- const requestId = destinationRequestRef.current + 1;
235
- destinationRequestRef.current = requestId;
236
-
237
- try {
238
- const { buildExportFilename } = await loadRunExportModule();
239
- const filename = buildExportFilename(selectedFile, options);
240
- const target = await destinationAdapter.resolveTarget(filename);
241
- if (destinationRequestRef.current === requestId) setDestinationTarget(target);
242
- } catch {
243
- if (destinationRequestRef.current === requestId) setDestinationTarget(null);
244
- }
245
- },
246
- [destinationAdapter, selectedFile],
247
- );
248
-
249
- const handleOpenDialog = useCallback(() => {
250
- setMenuOpen(false);
251
- setDialogOpen(true);
252
- void refreshDestination(dialogInitial);
253
- }, [dialogInitial, refreshDestination]);
254
-
255
- const handleCloseDialog = useCallback(() => {
256
- setDialogOpen(false);
257
- }, []);
258
-
259
- const handleOpenVideoModal = useCallback(async () => {
260
- setMenuOpen(false);
261
- setVideoModalOpen(true);
262
- setVideoLoading(true);
263
- setVideoLoadError(null);
264
-
265
- try {
266
- const modules = videoModules ?? (await loadVideoExportModules());
267
- setVideoModules(modules);
268
- setVideoDoc(modules.markdownToDoc(parseMarkdown(markdownSource)));
269
- } catch {
270
- setVideoLoadError('Video export could not be loaded.');
271
- } finally {
272
- setVideoLoading(false);
273
- }
274
- }, [markdownSource, videoModules]);
275
-
276
- const handleCloseVideoModal = useCallback(() => {
277
- setVideoModalOpen(false);
278
- setVideoDoc(null);
279
- setVideoLoadError(null);
280
- }, []);
281
-
282
- const handleOptionsChange = useCallback(
283
- (options: ExportOptions) => {
284
- void refreshDestination(options);
285
- },
286
- [refreshDestination],
287
- );
288
-
289
- const handlePickDestination = useCallback(
290
- async (options: ExportOptions) => {
291
- if (!destinationAdapter) return;
292
- try {
293
- const { buildExportFilename } = await loadRunExportModule();
294
- const filename = buildExportFilename(selectedFile, options);
295
- const pickedTarget = await destinationAdapter.pickTarget(filename, destinationTarget);
296
- if (pickedTarget === null) return;
297
- setDestinationTarget(pickedTarget);
298
- } catch {
299
- // Native hosts surface picker failures through their own UI channel.
300
- }
301
- },
302
- [destinationAdapter, destinationTarget, selectedFile],
303
- );
304
-
305
- const saveToDestination = useCallback(
306
- async (blob: Blob, filename: string, target: ExportDestinationTarget | null) => {
307
- if (!destinationAdapter) return;
308
- const savedTarget = await destinationAdapter.saveBlob(blob, filename, target);
309
- if (savedTarget) setDestinationTarget(savedTarget);
310
- },
311
- [destinationAdapter],
312
- );
313
-
314
- const handleDestinationSaveBlob = useCallback(
315
- async (blob: Blob, filename: string) => {
316
- await saveToDestination(blob, filename, destinationTarget);
317
- },
318
- [destinationTarget, saveToDestination],
319
- );
320
-
321
- const handleExport = useCallback(
322
- async (opts: ExportOptions) => {
323
- setExporting(true);
324
- try {
325
- const { runExport } = await loadRunExportModule();
326
- await runExport(
327
- markdownSource,
328
- selectedFile,
329
- opts,
330
- mediaContainer,
331
- destinationAdapter ? handleDestinationSaveBlob : saveBlob,
332
- );
333
- } finally {
334
- setExporting(false);
335
- setDialogOpen(false);
336
- }
337
- },
338
- [
339
- markdownSource,
340
- selectedFile,
341
- mediaContainer,
342
- destinationAdapter,
343
- handleDestinationSaveBlob,
344
- saveBlob,
345
- ],
346
- );
347
-
348
- const handleQuickExport = useCallback(async () => {
349
- if (!lastOptions) return;
350
- setMenuOpen(false);
351
- setExporting(true);
352
- try {
353
- saveExportOptions(lastOptions);
354
- const { runExport } = await loadRunExportModule();
355
- let quickTarget: ExportDestinationTarget | null = null;
356
- if (destinationAdapter) {
357
- const { buildExportFilename } = await loadRunExportModule();
358
- quickTarget = await destinationAdapter.resolveTarget(
359
- buildExportFilename(selectedFile, lastOptions),
360
- );
361
- }
362
- await runExport(
363
- markdownSource,
364
- selectedFile,
365
- lastOptions,
366
- mediaContainer,
367
- destinationAdapter
368
- ? async (blob, filename) => saveToDestination(blob, filename, quickTarget)
369
- : saveBlob,
370
- );
371
- } finally {
372
- setExporting(false);
373
- }
374
- }, [
375
- destinationAdapter,
376
- lastOptions,
377
- markdownSource,
378
- mediaContainer,
379
- saveBlob,
380
- saveToDestination,
381
- selectedFile,
382
- ]);
383
-
384
- const LoadedVideoExportModal = videoModules?.Modal;
385
-
386
- return (
387
- <>
388
- {trigger === 'button' ? (
389
- <button
390
- type="button"
391
- className="squisq-toolbar-button db-toolbar-export-trigger"
392
- onClick={handleOpenDialog}
393
- disabled={exporting}
394
- aria-label="Export document"
395
- data-tooltip={exporting ? 'Exporting...' : 'Export document'}
396
- >
397
- <ExportGlyph />
398
- </button>
399
- ) : (
400
- <div className="db-toolbar-menu" ref={menuRef}>
401
- <button
402
- className="db-toolbar-menu-trigger"
403
- onClick={handleToggleMenu}
404
- aria-label="More actions"
405
- title="More actions"
406
- >
407
- &middot;&middot;&middot;
408
- </button>
409
-
410
- {menuOpen && (
411
- <div className="db-toolbar-menu-dropdown">
412
- {lastOptions && (
413
- <button
414
- className="db-toolbar-menu-item"
415
- onClick={handleQuickExport}
416
- disabled={exporting}
417
- >
418
- {quickLabel(lastOptions, transformSummaries)}
419
- </button>
420
- )}
421
- <button className="db-toolbar-menu-item" onClick={handleOpenDialog}>
422
- Export...
423
- </button>
424
- {showVideoExport && (
425
- <>
426
- <div className="db-toolbar-menu-divider" />
427
- <button className="db-toolbar-menu-item" onClick={handleOpenVideoModal}>
428
- Export Video...
429
- </button>
430
- </>
431
- )}
432
- </div>
433
- )}
434
- </div>
435
- )}
436
-
437
- {dialogOpen && (
438
- <Suspense fallback={null}>
439
- <ExportDialog
440
- initial={dialogInitial}
441
- exporting={exporting}
442
- destination={
443
- destinationAdapter
444
- ? {
445
- value: destinationTarget?.displayPath ?? '',
446
- onPick: handlePickDestination,
447
- hint: destinationAdapter.hint,
448
- }
449
- : undefined
450
- }
451
- onExport={handleExport}
452
- onOptionsChange={destinationAdapter ? handleOptionsChange : undefined}
453
- onClose={handleCloseDialog}
454
- />
455
- </Suspense>
456
- )}
457
-
458
- {videoModalOpen && (videoLoading || videoLoadError) && (
459
- <div className="db-dialog-overlay">
460
- <div className="db-dialog">
461
- <div className="db-dialog-header">
462
- <h2 className="db-dialog-title">Export Video</h2>
463
- <button
464
- className="db-dialog-close"
465
- onClick={handleCloseVideoModal}
466
- aria-label="Close"
467
- >
468
- &times;
469
- </button>
470
- </div>
471
- <div className="db-dialog-body">
472
- <p className="db-export-hint">{videoLoadError ?? 'Loading...'}</p>
473
- </div>
474
- </div>
475
- </div>
476
- )}
477
-
478
- {videoModalOpen &&
479
- videoModules &&
480
- LoadedVideoExportModal &&
481
- videoDoc &&
482
- !videoLoading &&
483
- !videoLoadError && (
484
- <LoadedVideoExportModal
485
- doc={videoDoc}
486
- playerScript={videoModules.playerScript}
487
- onClose={handleCloseVideoModal}
488
- />
489
- )}
490
- </>
491
- );
492
- }
493
-
494
- function ExportGlyph() {
495
- return (
496
- <svg
497
- viewBox="0 0 16 16"
498
- fill="none"
499
- stroke="currentColor"
500
- strokeWidth="1.5"
501
- strokeLinecap="round"
502
- strokeLinejoin="round"
503
- aria-hidden="true"
504
- >
505
- <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" />
506
- <path d="M8.75 1.75V5h3.25" />
507
- <path d="M6 8.75h4.5" />
508
- <path d="M8.75 7 10.5 8.75 8.75 10.5" />
509
- </svg>
510
- );
511
- }
@@ -1,30 +0,0 @@
1
- /** Keep a user-edited target name while switching the selected export format. */
2
- export function updateExportTargetExtension(targetPath: string, suggestedFilename: string): string {
3
- const nextExtension = extensionOf(suggestedFilename);
4
- if (!nextExtension) return targetPath;
5
- if (!targetPath.trim()) return suggestedFilename;
6
-
7
- const suffixIndex = firstSuffixIndex(targetPath);
8
- const pathPart = suffixIndex === -1 ? targetPath : targetPath.slice(0, suffixIndex);
9
- const suffix = suffixIndex === -1 ? '' : targetPath.slice(suffixIndex);
10
- const separatorIndex = Math.max(pathPart.lastIndexOf('/'), pathPart.lastIndexOf('\\'));
11
- const dotIndex = pathPart.lastIndexOf('.');
12
- const stem = dotIndex > separatorIndex ? pathPart.slice(0, dotIndex) : pathPart;
13
- return `${stem}${nextExtension}${suffix}`;
14
- }
15
-
16
- function extensionOf(value: string): string {
17
- const suffixIndex = firstSuffixIndex(value);
18
- const pathPart = suffixIndex === -1 ? value : value.slice(0, suffixIndex);
19
- const separatorIndex = Math.max(pathPart.lastIndexOf('/'), pathPart.lastIndexOf('\\'));
20
- const dotIndex = pathPart.lastIndexOf('.');
21
- return dotIndex > separatorIndex ? pathPart.slice(dotIndex) : '';
22
- }
23
-
24
- function firstSuffixIndex(value: string): number {
25
- const query = value.indexOf('?');
26
- const fragment = value.indexOf('#');
27
- if (query === -1) return fragment;
28
- if (fragment === -1) return query;
29
- return Math.min(query, fragment);
30
- }
@@ -1,99 +0,0 @@
1
- /**
2
- * Export option types and localStorage persistence for quick-export.
3
- */
4
-
5
- export type ExportFormat = 'docx' | 'pdf' | 'pptx' | 'md' | 'html';
6
-
7
- /** Visual style for HTML export. */
8
- export type HtmlStyle =
9
- /** Render via SquisqPlayer (themed, embeds player bundle). */
10
- | 'rendered'
11
- /** Plain semantic HTML — small, no JS, no playback. */
12
- | 'plain';
13
-
14
- /** Packaging for HTML export. */
15
- export type HtmlBundle =
16
- /** Single self-contained .html file (images base64-embedded). */
17
- | 'single'
18
- /** ZIP containing index.html + asset files. */
19
- | 'zip';
20
-
21
- export interface ExportOptions {
22
- format: ExportFormat;
23
- themeId: string;
24
- /** Transform style for PPTX — controls how content is segmented and styled. */
25
- transformStyle: string;
26
- /** Only applies to PDF */
27
- pageSize: 'letter' | 'a4';
28
- /** HTML rendering style. Only applies to format=html. */
29
- htmlStyle: HtmlStyle;
30
- /** HTML bundle layout. Only applies to format=html. */
31
- htmlBundle: HtmlBundle;
32
- /**
33
- * Recursive HTML bundle: walk relative `.md` links from the entry
34
- * document, render every reachable sibling/child page, and rewrite
35
- * cross-doc links from `.md` → `.html`. The output is a ZIP
36
- * regardless of `htmlBundle` because multi-doc output needs a
37
- * directory tree. Supported for both plain (`markdownDocsToPlainHtmlBundle`)
38
- * and rendered (`markdownDocsToHtmlBundle`) HTML styles. Only
39
- * meaningful when `format === 'html'`.
40
- */
41
- includeLinkedDocs: boolean;
42
- /**
43
- * Rename the entry page from `<basename>.html` to `index.html` so the
44
- * export drops straight into a static-site host that expects an
45
- * `index.html` landing page. For recursive bundles, cross-doc links
46
- * targeting the entry also rewrite to `index.html` so siblings don't
47
- * 404. For a single-doc HTML download, this just renames the file.
48
- * Only meaningful when `format === 'html'`.
49
- */
50
- entryAsIndex: boolean;
51
- }
52
-
53
- export const FORMAT_LABELS: Record<ExportFormat, string> = {
54
- docx: 'Word Document (.docx)',
55
- pdf: 'PDF (.pdf)',
56
- pptx: 'PowerPoint (.pptx)',
57
- md: 'Markdown (.md)',
58
- html: 'HTML (.html)',
59
- };
60
-
61
- export const FORMAT_EXTENSIONS: Record<ExportFormat, string> = {
62
- docx: '.docx',
63
- pdf: '.pdf',
64
- pptx: '.pptx',
65
- md: '.md',
66
- html: '.html',
67
- };
68
-
69
- const STORAGE_KEY = 'docblocks-export-options';
70
-
71
- export const DEFAULT_OPTIONS: ExportOptions = {
72
- format: 'pdf',
73
- themeId: 'standard',
74
- transformStyle: 'documentary',
75
- pageSize: 'letter',
76
- htmlStyle: 'plain',
77
- htmlBundle: 'single',
78
- includeLinkedDocs: false,
79
- entryAsIndex: false,
80
- };
81
-
82
- export function loadLastExportOptions(): ExportOptions | null {
83
- try {
84
- const raw = localStorage.getItem(STORAGE_KEY);
85
- if (!raw) return null;
86
- const parsed = JSON.parse(raw) as Partial<ExportOptions>;
87
- return { ...DEFAULT_OPTIONS, ...parsed };
88
- } catch {
89
- return null;
90
- }
91
- }
92
-
93
- export function saveExportOptions(options: ExportOptions): void {
94
- try {
95
- localStorage.setItem(STORAGE_KEY, JSON.stringify(options));
96
- } catch {
97
- // Ignore storage errors
98
- }
99
- }
@@ -1,19 +0,0 @@
1
- export { ExportToolbarControls } from './DeferredExportToolbarControls.js';
2
- export type {
3
- ExportDestinationAdapter,
4
- ExportDestinationTarget,
5
- ExportToolbarControlsProps,
6
- } from './DeferredExportToolbarControls.js';
7
- export { ExportDialog } from './ExportDialog.js';
8
- export type { ExportDestinationControl, ExportDialogProps } from './ExportDialog.js';
9
- export {
10
- DEFAULT_OPTIONS,
11
- FORMAT_EXTENSIONS,
12
- FORMAT_LABELS,
13
- loadLastExportOptions,
14
- saveExportOptions,
15
- } from './export-options.js';
16
- export type { ExportFormat, ExportOptions, HtmlBundle, HtmlStyle } from './export-options.js';
17
- export { buildExportFilename, runExport } from './run-export.js';
18
- export { updateExportTargetExtension } from './export-destination.js';
19
- export type { ExportBlobSaver } from './run-export.js';
@@ -1,17 +0,0 @@
1
- /**
2
- * Narrow public export pipeline for hosts that provide their own editor shell.
3
- * Keep toolbar/video controls out of this entry so consumers such as the VS
4
- * Code webview do not eagerly transform the video worker graph.
5
- */
6
- export { ExportDialog } from './ExportDialog.js';
7
- export type { ExportDestinationControl, ExportDialogProps } from './ExportDialog.js';
8
- export {
9
- DEFAULT_OPTIONS,
10
- FORMAT_EXTENSIONS,
11
- FORMAT_LABELS,
12
- loadLastExportOptions,
13
- saveExportOptions,
14
- } from './export-options.js';
15
- export type { ExportFormat, ExportOptions, HtmlBundle, HtmlStyle } from './export-options.js';
16
- export { buildExportFilename, runExport } from './run-export.js';
17
- export type { ExportBlobSaver } from './run-export.js';