@bendyline/docblocks-react 1.1.2 → 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 (225) hide show
  1. package/README.md +37 -5
  2. package/dist/ExportDialog-7LDIXJZ3.js +10 -0
  3. package/dist/ExportDialog-7LDIXJZ3.js.map +1 -0
  4. package/dist/ExportToolbarControls-GHAOJMH6.js +508 -0
  5. package/dist/ExportToolbarControls-GHAOJMH6.js.map +1 -0
  6. package/dist/GitToolbarControl-GNMRVKWQ.js +136 -0
  7. package/dist/GitToolbarControl-GNMRVKWQ.js.map +1 -0
  8. package/dist/GitUI-VHOBQY43.js +1133 -0
  9. package/dist/GitUI-VHOBQY43.js.map +1 -0
  10. package/dist/LazyEditorShell-EF2BWRXU.js +6 -0
  11. package/dist/LazyEditorShell-EF2BWRXU.js.map +1 -0
  12. package/dist/ShareDialog-63ENBEDZ.js +213 -0
  13. package/dist/ShareDialog-63ENBEDZ.js.map +1 -0
  14. package/dist/chunk-4XXSWN3T.js +13 -0
  15. package/dist/chunk-4XXSWN3T.js.map +1 -0
  16. package/dist/chunk-57ZJJOC5.js +89 -0
  17. package/dist/chunk-57ZJJOC5.js.map +1 -0
  18. package/dist/chunk-5A4KEWKT.js +97 -0
  19. package/dist/chunk-5A4KEWKT.js.map +1 -0
  20. package/dist/chunk-DD4VFJQI.js +51 -0
  21. package/dist/chunk-DD4VFJQI.js.map +1 -0
  22. package/dist/chunk-FEWQUQML.js +256 -0
  23. package/dist/chunk-FEWQUQML.js.map +1 -0
  24. package/dist/chunk-FMGTHSTX.js +110 -0
  25. package/dist/chunk-FMGTHSTX.js.map +1 -0
  26. package/dist/chunk-UNYZQXWR.js +324 -0
  27. package/dist/chunk-UNYZQXWR.js.map +1 -0
  28. package/dist/chunk-VHDP4IPL.js +70 -0
  29. package/dist/chunk-VHDP4IPL.js.map +1 -0
  30. package/dist/chunk-ZI56BNB7.js +270 -0
  31. package/dist/chunk-ZI56BNB7.js.map +1 -0
  32. package/dist/editor.d.ts +11 -0
  33. package/dist/editor.js +9 -0
  34. package/dist/editor.js.map +1 -0
  35. package/dist/export/index.d.ts +93 -0
  36. package/dist/export/index.js +27 -0
  37. package/dist/export/index.js.map +1 -0
  38. package/dist/index.d.ts +346 -18
  39. package/dist/index.js +6169 -18
  40. package/dist/index.js.map +1 -1
  41. package/dist/run-export-ICTZITXC.js +10 -0
  42. package/dist/run-export-ICTZITXC.js.map +1 -0
  43. package/dist/settings/index.d.ts +36 -0
  44. package/dist/settings/index.js +14 -0
  45. package/dist/settings/index.js.map +1 -0
  46. package/package.json +33 -13
  47. package/src/styles/docblocks.css +2738 -132
  48. package/dist/AppMenu/AppMenu.d.ts +0 -26
  49. package/dist/AppMenu/AppMenu.d.ts.map +0 -1
  50. package/dist/AppMenu/AppMenu.js +0 -28
  51. package/dist/AppMenu/AppMenu.js.map +0 -1
  52. package/dist/AppMenu/index.d.ts +0 -3
  53. package/dist/AppMenu/index.d.ts.map +0 -1
  54. package/dist/AppMenu/index.js +0 -2
  55. package/dist/AppMenu/index.js.map +0 -1
  56. package/dist/DocBlocksShell/DocBlocksShell.d.ts +0 -36
  57. package/dist/DocBlocksShell/DocBlocksShell.d.ts.map +0 -1
  58. package/dist/DocBlocksShell/DocBlocksShell.js +0 -1351
  59. package/dist/DocBlocksShell/DocBlocksShell.js.map +0 -1
  60. package/dist/DocBlocksShell/index.d.ts +0 -3
  61. package/dist/DocBlocksShell/index.d.ts.map +0 -1
  62. package/dist/DocBlocksShell/index.js +0 -2
  63. package/dist/DocBlocksShell/index.js.map +0 -1
  64. package/dist/Export/ExportDialog.d.ts +0 -16
  65. package/dist/Export/ExportDialog.d.ts.map +0 -1
  66. package/dist/Export/ExportDialog.js +0 -158
  67. package/dist/Export/ExportDialog.js.map +0 -1
  68. package/dist/Export/ExportToolbarControls.d.ts +0 -17
  69. package/dist/Export/ExportToolbarControls.d.ts.map +0 -1
  70. package/dist/Export/ExportToolbarControls.js +0 -200
  71. package/dist/Export/ExportToolbarControls.js.map +0 -1
  72. package/dist/Export/export-options.d.ts +0 -53
  73. package/dist/Export/export-options.d.ts.map +0 -1
  74. package/dist/Export/export-options.js +0 -49
  75. package/dist/Export/export-options.js.map +0 -1
  76. package/dist/Export/index.d.ts +0 -6
  77. package/dist/Export/index.d.ts.map +0 -1
  78. package/dist/Export/index.js +0 -3
  79. package/dist/Export/index.js.map +0 -1
  80. package/dist/Export/run-export.d.ts +0 -8
  81. package/dist/Export/run-export.d.ts.map +0 -1
  82. package/dist/Export/run-export.js +0 -296
  83. package/dist/Export/run-export.js.map +0 -1
  84. package/dist/Export/transform-summaries.d.ts +0 -7
  85. package/dist/Export/transform-summaries.d.ts.map +0 -1
  86. package/dist/Export/transform-summaries.js +0 -6
  87. package/dist/Export/transform-summaries.js.map +0 -1
  88. package/dist/FileExplorer/FileExplorer.d.ts +0 -21
  89. package/dist/FileExplorer/FileExplorer.d.ts.map +0 -1
  90. package/dist/FileExplorer/FileExplorer.js +0 -140
  91. package/dist/FileExplorer/FileExplorer.js.map +0 -1
  92. package/dist/FileExplorer/FileTreeNode.d.ts +0 -18
  93. package/dist/FileExplorer/FileTreeNode.d.ts.map +0 -1
  94. package/dist/FileExplorer/FileTreeNode.js +0 -112
  95. package/dist/FileExplorer/FileTreeNode.js.map +0 -1
  96. package/dist/FileExplorer/index.d.ts +0 -6
  97. package/dist/FileExplorer/index.d.ts.map +0 -1
  98. package/dist/FileExplorer/index.js +0 -4
  99. package/dist/FileExplorer/index.js.map +0 -1
  100. package/dist/FileExplorer/useFileTree.d.ts +0 -35
  101. package/dist/FileExplorer/useFileTree.d.ts.map +0 -1
  102. package/dist/FileExplorer/useFileTree.js +0 -124
  103. package/dist/FileExplorer/useFileTree.js.map +0 -1
  104. package/dist/WorkspacePicker/WorkspacePicker.d.ts +0 -17
  105. package/dist/WorkspacePicker/WorkspacePicker.d.ts.map +0 -1
  106. package/dist/WorkspacePicker/WorkspacePicker.js +0 -63
  107. package/dist/WorkspacePicker/WorkspacePicker.js.map +0 -1
  108. package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts +0 -11
  109. package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts.map +0 -1
  110. package/dist/WorkspacePicker/WorkspaceSettingsButton.js +0 -27
  111. package/dist/WorkspacePicker/WorkspaceSettingsButton.js.map +0 -1
  112. package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts +0 -20
  113. package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts.map +0 -1
  114. package/dist/WorkspacePicker/WorkspaceSettingsDialog.js +0 -36
  115. package/dist/WorkspacePicker/WorkspaceSettingsDialog.js.map +0 -1
  116. package/dist/WorkspacePicker/index.d.ts +0 -3
  117. package/dist/WorkspacePicker/index.d.ts.map +0 -1
  118. package/dist/WorkspacePicker/index.js +0 -2
  119. package/dist/WorkspacePicker/index.js.map +0 -1
  120. package/dist/hooks/index.d.ts +0 -2
  121. package/dist/hooks/index.d.ts.map +0 -1
  122. package/dist/hooks/index.js +0 -2
  123. package/dist/hooks/index.js.map +0 -1
  124. package/dist/hooks/useAutoSave.d.ts +0 -15
  125. package/dist/hooks/useAutoSave.d.ts.map +0 -1
  126. package/dist/hooks/useAutoSave.js +0 -83
  127. package/dist/hooks/useAutoSave.js.map +0 -1
  128. package/dist/icons.d.ts +0 -7
  129. package/dist/icons.d.ts.map +0 -1
  130. package/dist/icons.js +0 -27
  131. package/dist/icons.js.map +0 -1
  132. package/dist/index.d.ts.map +0 -1
  133. package/dist/monaco-slim.d.ts +0 -19
  134. package/dist/monaco-slim.d.ts.map +0 -1
  135. package/dist/monaco-slim.js +0 -19
  136. package/dist/monaco-slim.js.map +0 -1
  137. package/dist/preferences/versioning.d.ts +0 -27
  138. package/dist/preferences/versioning.d.ts.map +0 -1
  139. package/dist/preferences/versioning.js +0 -62
  140. package/dist/preferences/versioning.js.map +0 -1
  141. package/src/AppMenu/AppMenu.tsx +0 -264
  142. package/src/AppMenu/index.ts +0 -2
  143. package/src/DocBlocksShell/DocBlocksShell.tsx +0 -1778
  144. package/src/DocBlocksShell/index.ts +0 -2
  145. package/src/Export/ExportDialog.tsx +0 -383
  146. package/src/Export/ExportToolbarControls.tsx +0 -313
  147. package/src/Export/export-options.ts +0 -99
  148. package/src/Export/index.ts +0 -5
  149. package/src/Export/run-export.ts +0 -349
  150. package/src/Export/transform-summaries.ts +0 -14
  151. package/src/FileExplorer/FileExplorer.tsx +0 -282
  152. package/src/FileExplorer/FileTreeNode.tsx +0 -214
  153. package/src/FileExplorer/index.ts +0 -5
  154. package/src/FileExplorer/useFileTree.ts +0 -178
  155. package/src/WorkspacePicker/WorkspacePicker.tsx +0 -137
  156. package/src/WorkspacePicker/WorkspaceSettingsButton.tsx +0 -88
  157. package/src/WorkspacePicker/WorkspaceSettingsDialog.tsx +0 -121
  158. package/src/WorkspacePicker/index.ts +0 -2
  159. package/src/fonts/fonts.css +0 -362
  160. package/src/fonts/licenses/LICENSE-cormorant-garamond.txt +0 -93
  161. package/src/fonts/licenses/LICENSE-crimson-text.txt +0 -93
  162. package/src/fonts/licenses/LICENSE-dm-sans.txt +0 -93
  163. package/src/fonts/licenses/LICENSE-dm-serif-display.txt +0 -93
  164. package/src/fonts/licenses/LICENSE-hanken-grotesk.txt +0 -94
  165. package/src/fonts/licenses/LICENSE-ibm-plex-sans.txt +0 -93
  166. package/src/fonts/licenses/LICENSE-inter.txt +0 -93
  167. package/src/fonts/licenses/LICENSE-jetbrains-mono.txt +0 -93
  168. package/src/fonts/licenses/LICENSE-lora.txt +0 -93
  169. package/src/fonts/licenses/LICENSE-merriweather.txt +0 -93
  170. package/src/fonts/licenses/LICENSE-oswald.txt +0 -93
  171. package/src/fonts/licenses/LICENSE-playfair-display.txt +0 -93
  172. package/src/fonts/licenses/LICENSE-pt-serif.txt +0 -93
  173. package/src/fonts/licenses/LICENSE-roboto.txt +0 -93
  174. package/src/fonts/licenses/LICENSE-source-serif-4.txt +0 -93
  175. package/src/fonts/woff2/cormorant-garamond-400.woff2 +0 -0
  176. package/src/fonts/woff2/cormorant-garamond-700.woff2 +0 -0
  177. package/src/fonts/woff2/crimson-text-400.woff2 +0 -0
  178. package/src/fonts/woff2/crimson-text-400i.woff2 +0 -0
  179. package/src/fonts/woff2/crimson-text-700.woff2 +0 -0
  180. package/src/fonts/woff2/dm-sans-400.woff2 +0 -0
  181. package/src/fonts/woff2/dm-sans-400i.woff2 +0 -0
  182. package/src/fonts/woff2/dm-sans-500.woff2 +0 -0
  183. package/src/fonts/woff2/dm-sans-700.woff2 +0 -0
  184. package/src/fonts/woff2/dm-serif-display-400.woff2 +0 -0
  185. package/src/fonts/woff2/hanken-grotesk-400.woff2 +0 -0
  186. package/src/fonts/woff2/hanken-grotesk-400i.woff2 +0 -0
  187. package/src/fonts/woff2/hanken-grotesk-500.woff2 +0 -0
  188. package/src/fonts/woff2/hanken-grotesk-600.woff2 +0 -0
  189. package/src/fonts/woff2/hanken-grotesk-700.woff2 +0 -0
  190. package/src/fonts/woff2/ibm-plex-sans-400.woff2 +0 -0
  191. package/src/fonts/woff2/ibm-plex-sans-400i.woff2 +0 -0
  192. package/src/fonts/woff2/ibm-plex-sans-500.woff2 +0 -0
  193. package/src/fonts/woff2/ibm-plex-sans-600.woff2 +0 -0
  194. package/src/fonts/woff2/ibm-plex-sans-700.woff2 +0 -0
  195. package/src/fonts/woff2/inter-400.woff2 +0 -0
  196. package/src/fonts/woff2/inter-400i.woff2 +0 -0
  197. package/src/fonts/woff2/inter-500.woff2 +0 -0
  198. package/src/fonts/woff2/inter-600.woff2 +0 -0
  199. package/src/fonts/woff2/inter-700.woff2 +0 -0
  200. package/src/fonts/woff2/jetbrains-mono-400.woff2 +0 -0
  201. package/src/fonts/woff2/jetbrains-mono-400i.woff2 +0 -0
  202. package/src/fonts/woff2/jetbrains-mono-700.woff2 +0 -0
  203. package/src/fonts/woff2/lora-400.woff2 +0 -0
  204. package/src/fonts/woff2/lora-400i.woff2 +0 -0
  205. package/src/fonts/woff2/lora-700.woff2 +0 -0
  206. package/src/fonts/woff2/merriweather-400.woff2 +0 -0
  207. package/src/fonts/woff2/merriweather-700.woff2 +0 -0
  208. package/src/fonts/woff2/oswald-400.woff2 +0 -0
  209. package/src/fonts/woff2/oswald-700.woff2 +0 -0
  210. package/src/fonts/woff2/playfair-display-400.woff2 +0 -0
  211. package/src/fonts/woff2/playfair-display-700.woff2 +0 -0
  212. package/src/fonts/woff2/pt-serif-400.woff2 +0 -0
  213. package/src/fonts/woff2/pt-serif-700.woff2 +0 -0
  214. package/src/fonts/woff2/roboto-400.woff2 +0 -0
  215. package/src/fonts/woff2/roboto-400i.woff2 +0 -0
  216. package/src/fonts/woff2/roboto-700.woff2 +0 -0
  217. package/src/fonts/woff2/source-serif-4-400.woff2 +0 -0
  218. package/src/fonts/woff2/source-serif-4-400i.woff2 +0 -0
  219. package/src/fonts/woff2/source-serif-4-700.woff2 +0 -0
  220. package/src/hooks/index.ts +0 -1
  221. package/src/hooks/useAutoSave.ts +0 -116
  222. package/src/icons.tsx +0 -70
  223. package/src/index.ts +0 -31
  224. package/src/monaco-slim.ts +0 -20
  225. package/src/preferences/versioning.ts +0 -69
package/README.md CHANGED
@@ -21,6 +21,16 @@ function App() {
21
21
  }
22
22
  ```
23
23
 
24
+ The video-export worker uses module chunks. Vite consumers must retain the
25
+ same worker setting used by the DocBlocks site and desktop renderer:
26
+
27
+ ```ts
28
+ // vite.config.ts
29
+ import { defineConfig } from 'vite';
30
+
31
+ export default defineConfig({ worker: { format: 'es' } });
32
+ ```
33
+
24
34
  ## Components
25
35
 
26
36
  ### DocBlocksShell
@@ -34,11 +44,13 @@ The canonical DocBlocks experience in one component — file explorer, workspace
34
44
  - `theme` — `'light' | 'dark' | 'auto'` (auto follows `prefers-color-scheme`)
35
45
  - `logoUrl` — brand mark for the app menu button
36
46
 
37
- Storage is abstracted behind `FileSystemProvider` from `@bendyline/docblocks/filesystem`: browser-local (IndexedDB), native folders (File System Access API), or the Electron host.
47
+ Storage is abstracted behind the byte-authoritative `FileSystemProviderV2` contract from `@bendyline/docblocks/filesystem`: browser-local (IndexedDB), native folders (File System Access API), transient memory workspaces, or the Electron host. Built-in compatibility facades expose it as `provider.v2`; first-party shell and file-tree operations are v2-first.
38
48
 
39
49
  ### FileExplorer / FileTreeNode
40
50
 
41
- File tree browser with inline create (file + folder), rename, delete, and refresh. Long names truncate gracefully.
51
+ File tree browser with inline create (file + folder), rename, and delete. It follows filesystem
52
+ watch events automatically and re-reads the visible tree when a browser surface resumes. Long
53
+ names truncate gracefully.
42
54
 
43
55
  ### WorkspacePicker
44
56
 
@@ -50,17 +62,37 @@ Top-left brand menu with the app-wide **Settings** dialog (theme preference, glo
50
62
 
51
63
  ### ExportToolbarControls / ExportDialog
52
64
 
65
+ Consumers that need the export pipeline without the complete shell can use the
66
+ public, independently built entry point:
67
+
68
+ ```ts
69
+ import {
70
+ DEFAULT_OPTIONS,
71
+ ExportDialog,
72
+ buildExportFilename,
73
+ runExport,
74
+ } from '@bendyline/docblocks-react/export';
75
+ ```
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
+
53
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.
54
84
 
55
85
  ## Hooks
56
86
 
57
- ### `useAutoSave(content, save, delay?)`
87
+ ### `useDocumentSession(delay?)`
58
88
 
59
- Debounced auto-save (default 500ms).
89
+ React binding for the revisioned `DocumentSession`. Active-document writes,
90
+ transitions, conflicts, and close preparation must flow through this session;
91
+ there is intentionally no independent autosave hook.
60
92
 
61
93
  ### `useFileTree(provider)`
62
94
 
63
- File tree state management over any `FileSystemProvider` — returns the tree, selection, and mutation functions.
95
+ File tree state management over any v2-capable provider — returns the tree, selection, and explicit create/move/remove functions, with a temporary v1 fallback for external providers.
64
96
 
65
97
  ## Styles
66
98
 
@@ -0,0 +1,10 @@
1
+ import {
2
+ ExportDialog
3
+ } from "./chunk-UNYZQXWR.js";
4
+ import "./chunk-4XXSWN3T.js";
5
+ import "./chunk-FMGTHSTX.js";
6
+ import "./chunk-DD4VFJQI.js";
7
+ export {
8
+ ExportDialog
9
+ };
10
+ //# sourceMappingURL=ExportDialog-7LDIXJZ3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,508 @@
1
+ import {
2
+ loadTransformStyleSummaries
3
+ } from "./chunk-4XXSWN3T.js";
4
+ import {
5
+ Dialog
6
+ } from "./chunk-FMGTHSTX.js";
7
+ import {
8
+ DEFAULT_OPTIONS,
9
+ FORMAT_EXTENSIONS,
10
+ loadLastExportOptions,
11
+ saveExportOptions
12
+ } from "./chunk-DD4VFJQI.js";
13
+
14
+ // src/Export/ExportToolbarControls.tsx
15
+ import {
16
+ lazy,
17
+ Suspense,
18
+ useState,
19
+ useCallback,
20
+ useEffect,
21
+ useRef,
22
+ useMemo
23
+ } from "react";
24
+ import { useEditorContext, usePreviewSettings } from "@bendyline/squisq-editor-react";
25
+ import { getThemeSummaries } from "@bendyline/squisq/schemas";
26
+ import { parseMarkdown } from "@bendyline/squisq/markdown";
27
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
28
+ var ExportDialog = lazy(
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 }))
33
+ );
34
+ var runExportModulePromise = null;
35
+ function loadRunExportModule() {
36
+ runExportModulePromise ?? (runExportModulePromise = import("./run-export-ICTZITXC.js"));
37
+ return runExportModulePromise;
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
+ }
58
+ var videoExportModulesPromise = null;
59
+ function loadVideoExportModules() {
60
+ videoExportModulesPromise ?? (videoExportModulesPromise = Promise.all([
61
+ import("@bendyline/squisq/doc"),
62
+ import("@bendyline/squisq-video-react"),
63
+ import("@bendyline/squisq-react/standalone-source")
64
+ ]).then(([docModule, videoModule, playerModule]) => ({
65
+ Modal: videoModule.VideoExportModal,
66
+ markdownToDoc: docModule.markdownToDoc,
67
+ playerScript: playerModule.PLAYER_BUNDLE
68
+ })));
69
+ return videoExportModulesPromise;
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
+ }
75
+ function quickLabel(opts, transformSummaries) {
76
+ const baseExt = FORMAT_EXTENSIONS[opts.format].toUpperCase().replace(".", "");
77
+ const isRecursiveHtml = opts.format === "html" && opts.includeLinkedDocs;
78
+ const ext = opts.format === "html" && (opts.htmlBundle === "zip" || isRecursiveHtml) ? "ZIP" : baseExt;
79
+ const parts = [];
80
+ if (opts.format === "html" && opts.htmlStyle === "rendered") {
81
+ parts.push("rendered");
82
+ }
83
+ if (isRecursiveHtml) {
84
+ parts.push("linked docs");
85
+ }
86
+ if (opts.themeId !== "standard") {
87
+ const theme = getThemeSummaries().find((t) => t.id === opts.themeId);
88
+ if (theme) parts.push(theme.name);
89
+ }
90
+ if (opts.format === "pptx" && opts.transformStyle) {
91
+ const transform = transformSummaries.find((t) => t.id === opts.transformStyle);
92
+ if (transform) parts.push(transform.name);
93
+ }
94
+ if (parts.length > 0) {
95
+ return `Export ${ext} with ${parts.join(" + ")}`;
96
+ }
97
+ return `Export ${ext}`;
98
+ }
99
+ function ExportToolbarControls({
100
+ selectedFile,
101
+ mediaContainer,
102
+ saveBlob,
103
+ destinationAdapter,
104
+ trigger = "menu",
105
+ showVideoExport = true,
106
+ colorScheme = "light",
107
+ videoExportPalette,
108
+ shareBaseUrl,
109
+ initialSharedMode = null
110
+ }) {
111
+ const { markdownSource, markdownDoc } = useEditorContext();
112
+ const [menuOpen, setMenuOpen] = useState(false);
113
+ const [dialogOpen, setDialogOpen] = useState(false);
114
+ const [shareDialogOpen, setShareDialogOpen] = useState(false);
115
+ const [videoModalOpen, setVideoModalOpen] = useState(false);
116
+ const [videoLoading, setVideoLoading] = useState(false);
117
+ const [videoLoadError, setVideoLoadError] = useState(null);
118
+ const [videoModules, setVideoModules] = useState(null);
119
+ const [videoDoc, setVideoDoc] = useState(null);
120
+ const [transformSummaries, setTransformSummaries] = useState([]);
121
+ const [exporting, setExporting] = useState(false);
122
+ const [exportError, setExportError] = useState(null);
123
+ const [destinationTarget, setDestinationTarget] = useState(null);
124
+ const destinationRequestRef = useRef(0);
125
+ const menuRef = useRef(null);
126
+ const lastOptions = loadLastExportOptions();
127
+ const docThemeId = useMemo(() => {
128
+ const fm = markdownDoc?.frontmatter;
129
+ if (!fm) return null;
130
+ const candidates = [fm["squisq-theme"], fm["theme"], fm["themeId"]];
131
+ for (const v of candidates) {
132
+ if (typeof v === "string" && v.trim()) return v.trim();
133
+ }
134
+ return null;
135
+ }, [markdownDoc]);
136
+ const dialogInitial = useMemo(() => {
137
+ const base = lastOptions ?? DEFAULT_OPTIONS;
138
+ return docThemeId ? { ...base, themeId: docThemeId } : base;
139
+ }, [lastOptions, docThemeId]);
140
+ useEffect(() => {
141
+ if (!menuOpen) return;
142
+ const onPointerDown = (e) => {
143
+ if (menuRef.current && !menuRef.current.contains(e.target)) {
144
+ setMenuOpen(false);
145
+ }
146
+ };
147
+ document.addEventListener("pointerdown", onPointerDown);
148
+ return () => document.removeEventListener("pointerdown", onPointerDown);
149
+ }, [menuOpen]);
150
+ useEffect(() => {
151
+ if (!menuOpen || lastOptions?.format !== "pptx" || !lastOptions.transformStyle || transformSummaries.length > 0) {
152
+ return;
153
+ }
154
+ let cancelled = false;
155
+ loadTransformStyleSummaries().then((nextSummaries) => {
156
+ if (!cancelled) setTransformSummaries(nextSummaries);
157
+ }).catch(() => {
158
+ if (!cancelled) setTransformSummaries([]);
159
+ });
160
+ return () => {
161
+ cancelled = true;
162
+ };
163
+ }, [lastOptions?.format, lastOptions?.transformStyle, menuOpen, transformSummaries.length]);
164
+ const handleToggleMenu = useCallback(() => {
165
+ setMenuOpen((prev) => !prev);
166
+ }, []);
167
+ const refreshDestination = useCallback(
168
+ async (options) => {
169
+ if (!destinationAdapter) return;
170
+ const requestId = destinationRequestRef.current + 1;
171
+ destinationRequestRef.current = requestId;
172
+ try {
173
+ const { buildExportFilename } = await loadRunExportModule();
174
+ const filename = buildExportFilename(selectedFile, options);
175
+ const target = await destinationAdapter.resolveTarget(filename);
176
+ if (destinationRequestRef.current === requestId) setDestinationTarget(target);
177
+ } catch {
178
+ if (destinationRequestRef.current === requestId) setDestinationTarget(null);
179
+ }
180
+ },
181
+ [destinationAdapter, selectedFile]
182
+ );
183
+ const handleOpenDialog = useCallback(() => {
184
+ setMenuOpen(false);
185
+ setExportError(null);
186
+ setDialogOpen(true);
187
+ void refreshDestination(dialogInitial);
188
+ }, [dialogInitial, refreshDestination]);
189
+ const handleCloseDialog = useCallback(() => {
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);
199
+ }, []);
200
+ const handleOpenVideoModal = useCallback(async () => {
201
+ setMenuOpen(false);
202
+ setVideoModalOpen(true);
203
+ setVideoLoading(true);
204
+ setVideoLoadError(null);
205
+ try {
206
+ const modules = videoModules ?? await loadVideoExportModules();
207
+ setVideoModules(modules);
208
+ setVideoDoc(modules.markdownToDoc(parseMarkdown(markdownSource)));
209
+ } catch {
210
+ setVideoLoadError("Video export could not be loaded.");
211
+ } finally {
212
+ setVideoLoading(false);
213
+ }
214
+ }, [markdownSource, videoModules]);
215
+ const handleCloseVideoModal = useCallback(() => {
216
+ setVideoModalOpen(false);
217
+ setVideoDoc(null);
218
+ setVideoLoadError(null);
219
+ }, []);
220
+ const handleOptionsChange = useCallback(
221
+ (options) => {
222
+ void refreshDestination(options);
223
+ },
224
+ [refreshDestination]
225
+ );
226
+ const handlePickDestination = useCallback(
227
+ async (options) => {
228
+ if (!destinationAdapter) return;
229
+ try {
230
+ const { buildExportFilename } = await loadRunExportModule();
231
+ const filename = buildExportFilename(selectedFile, options);
232
+ const pickedTarget = await destinationAdapter.pickTarget(filename, destinationTarget);
233
+ if (pickedTarget === null) return;
234
+ setDestinationTarget(pickedTarget);
235
+ } catch {
236
+ }
237
+ },
238
+ [destinationAdapter, destinationTarget, selectedFile]
239
+ );
240
+ const saveToDestination = useCallback(
241
+ async (blob, filename, target) => {
242
+ if (!destinationAdapter) return;
243
+ const savedTarget = await destinationAdapter.saveBlob(blob, filename, target);
244
+ if (savedTarget) setDestinationTarget(savedTarget);
245
+ },
246
+ [destinationAdapter]
247
+ );
248
+ const handleDestinationSaveBlob = useCallback(
249
+ async (blob, filename) => {
250
+ await saveToDestination(blob, filename, destinationTarget);
251
+ },
252
+ [destinationTarget, saveToDestination]
253
+ );
254
+ const handleExport = useCallback(
255
+ async (opts) => {
256
+ setExporting(true);
257
+ setExportError(null);
258
+ try {
259
+ const { runExport } = await loadRunExportModule();
260
+ await runExport(
261
+ markdownSource,
262
+ selectedFile,
263
+ opts,
264
+ mediaContainer,
265
+ destinationAdapter ? handleDestinationSaveBlob : saveBlob
266
+ );
267
+ setDialogOpen(false);
268
+ } catch (caught) {
269
+ setExportError(exportErrorMessage(caught));
270
+ } finally {
271
+ setExporting(false);
272
+ }
273
+ },
274
+ [
275
+ markdownSource,
276
+ selectedFile,
277
+ mediaContainer,
278
+ destinationAdapter,
279
+ handleDestinationSaveBlob,
280
+ saveBlob
281
+ ]
282
+ );
283
+ const handleQuickExport = useCallback(async () => {
284
+ if (!lastOptions) return;
285
+ setMenuOpen(false);
286
+ setExporting(true);
287
+ setExportError(null);
288
+ try {
289
+ saveExportOptions(lastOptions);
290
+ const { runExport } = await loadRunExportModule();
291
+ let quickTarget = null;
292
+ if (destinationAdapter) {
293
+ const { buildExportFilename } = await loadRunExportModule();
294
+ quickTarget = await destinationAdapter.resolveTarget(
295
+ buildExportFilename(selectedFile, lastOptions)
296
+ );
297
+ }
298
+ await runExport(
299
+ markdownSource,
300
+ selectedFile,
301
+ lastOptions,
302
+ mediaContainer,
303
+ destinationAdapter ? async (blob, filename) => saveToDestination(blob, filename, quickTarget) : saveBlob
304
+ );
305
+ } catch (caught) {
306
+ setExportError(exportErrorMessage(caught));
307
+ } finally {
308
+ setExporting(false);
309
+ }
310
+ }, [
311
+ destinationAdapter,
312
+ lastOptions,
313
+ markdownSource,
314
+ mediaContainer,
315
+ saveBlob,
316
+ saveToDestination,
317
+ selectedFile
318
+ ]);
319
+ const handleDismissExportError = useCallback(() => {
320
+ setExportError(null);
321
+ }, []);
322
+ const LoadedVideoExportModal = videoModules?.Modal;
323
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
324
+ initialSharedMode && /* @__PURE__ */ jsx(SharedModeInitializer, { mode: initialSharedMode }),
325
+ trigger === "button" ? /* @__PURE__ */ jsx(
326
+ "button",
327
+ {
328
+ type: "button",
329
+ className: "squisq-toolbar-button db-toolbar-export-trigger",
330
+ onClick: handleOpenDialog,
331
+ disabled: exporting,
332
+ "aria-label": "Export document",
333
+ "data-tooltip": exporting ? "Exporting..." : "Export document",
334
+ children: /* @__PURE__ */ jsx(ExportGlyph, {})
335
+ }
336
+ ) : /* @__PURE__ */ jsxs("div", { className: "db-toolbar-menu", ref: menuRef, children: [
337
+ /* @__PURE__ */ jsx(
338
+ "button",
339
+ {
340
+ type: "button",
341
+ className: "db-toolbar-menu-trigger",
342
+ onClick: handleToggleMenu,
343
+ "aria-label": "Export and share",
344
+ "aria-haspopup": "menu",
345
+ "aria-expanded": menuOpen,
346
+ title: "Export and share",
347
+ children: /* @__PURE__ */ jsx(ShareGlyph, {})
348
+ }
349
+ ),
350
+ menuOpen && /* @__PURE__ */ jsxs("div", { className: "db-toolbar-menu-dropdown", role: "menu", children: [
351
+ lastOptions && /* @__PURE__ */ jsx(
352
+ "button",
353
+ {
354
+ type: "button",
355
+ role: "menuitem",
356
+ className: "db-toolbar-menu-item",
357
+ onClick: handleQuickExport,
358
+ disabled: exporting,
359
+ children: quickLabel(lastOptions, transformSummaries)
360
+ }
361
+ ),
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
+ ),
382
+ showVideoExport && /* @__PURE__ */ jsxs(Fragment, { children: [
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
+ )
394
+ ] })
395
+ ] })
396
+ ] }),
397
+ dialogOpen && /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
398
+ ExportDialog,
399
+ {
400
+ initial: dialogInitial,
401
+ exporting,
402
+ error: exportError,
403
+ destination: destinationAdapter ? {
404
+ value: destinationTarget?.displayPath ?? "",
405
+ onPick: handlePickDestination,
406
+ hint: destinationAdapter.hint
407
+ } : void 0,
408
+ onExport: handleExport,
409
+ onOptionsChange: destinationAdapter ? handleOptionsChange : void 0,
410
+ onClose: handleCloseDialog
411
+ }
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
+ ) }),
439
+ videoModalOpen && (videoLoading || videoLoadError) && /* @__PURE__ */ jsx("div", { className: "db-dialog-overlay", children: /* @__PURE__ */ jsxs("div", { className: "db-dialog", children: [
440
+ /* @__PURE__ */ jsxs("div", { className: "db-dialog-header", children: [
441
+ /* @__PURE__ */ jsx("h2", { className: "db-dialog-title", children: "Export Video" }),
442
+ /* @__PURE__ */ jsx(
443
+ "button",
444
+ {
445
+ className: "db-dialog-close",
446
+ onClick: handleCloseVideoModal,
447
+ "aria-label": "Close",
448
+ children: "\xD7"
449
+ }
450
+ )
451
+ ] }),
452
+ /* @__PURE__ */ jsx("div", { className: "db-dialog-body", children: /* @__PURE__ */ jsx("p", { className: "db-export-hint", children: videoLoadError ?? "Loading..." }) })
453
+ ] }) }),
454
+ videoModalOpen && videoModules && LoadedVideoExportModal && videoDoc && !videoLoading && !videoLoadError && /* @__PURE__ */ jsx(
455
+ LoadedVideoExportModal,
456
+ {
457
+ doc: videoDoc,
458
+ playerScript: videoModules.playerScript,
459
+ colorScheme,
460
+ uiPalette: videoExportPalette,
461
+ onClose: handleCloseVideoModal
462
+ }
463
+ )
464
+ ] });
465
+ }
466
+ function ExportGlyph() {
467
+ return /* @__PURE__ */ jsxs(
468
+ "svg",
469
+ {
470
+ viewBox: "0 0 16 16",
471
+ fill: "none",
472
+ stroke: "currentColor",
473
+ strokeWidth: "1.5",
474
+ strokeLinecap: "round",
475
+ strokeLinejoin: "round",
476
+ "aria-hidden": "true",
477
+ children: [
478
+ /* @__PURE__ */ jsx("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" }),
479
+ /* @__PURE__ */ jsx("path", { d: "M8.75 1.75V5h3.25" }),
480
+ /* @__PURE__ */ jsx("path", { d: "M6 8.75h4.5" }),
481
+ /* @__PURE__ */ jsx("path", { d: "M8.75 7 10.5 8.75 8.75 10.5" })
482
+ ]
483
+ }
484
+ );
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
+ }
505
+ export {
506
+ ExportToolbarControls
507
+ };
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":";;;;;;;;;;;;;;AASA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,kBAAkB,0BAA0B;AAErD,SAAS,yBAAyB;AAClC,SAAS,qBAAqB;AA2bF,SAwDZ,UAxDY,KAwDZ,YAxDY;AA5a5B,IAAM,eAAe;AAAA,EAAK,MACxB,OAAO,4BAAmB,EAAE,KAAK,CAAC,YAAY,EAAE,SAAS,OAAO,aAAa,EAAE;AACjF;AACA,IAAM,cAAc;AAAA,EAAK,MACvB,OAAO,2BAAkB,EAAE,KAAK,CAAC,YAAY,EAAE,SAAS,OAAO,YAAY,EAAE;AAC/E;AAEA,IAAI,yBAA2E;AAE/E,SAAS,sBAAiE;AACxE,sDAA2B,OAAO,0BAAiB;AACnD,SAAO;AACT;AAqDA,IAAM,mBAAsE,OAAO,OAAO;AAAA,EACxF,WAAW;AAAA,EACX,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AACX,CAAC;AAED,SAAS,sBAAsB,EAAE,KAAK,GAAiC;AACrE,QAAM,aAAa,OAAO,KAAK;AAC/B,QAAM,EAAE,cAAc,IAAI,iBAAiB;AAC3C,QAAM,EAAE,uBAAuB,IAAI,mBAAmB;AAEtD,YAAU,MAAM;AACd,QAAI,WAAW,QAAS;AACxB,eAAW,UAAU;AACrB,2BAAuB,iBAAiB,IAAI,CAAC;AAC7C,kBAAc,SAAS;AAAA,EACzB,GAAG,CAAC,MAAM,eAAe,sBAAsB,CAAC;AAEhD,SAAO;AACT;AAEA,IAAI,4BAAgE;AAEpE,SAAS,yBAAsD;AAC7D,4DAA8B,QAAQ,IAAI;AAAA,IACxC,OAAO,uBAAuB;AAAA,IAC9B,OAAO,+BAA+B;AAAA,IACtC,OAAO,2CAA2C;AAAA,EACpD,CAAC,EAAE,KAAK,CAAC,CAAC,WAAW,aAAa,YAAY,OAAO;AAAA,IACnD,OAAO,YAAY;AAAA,IACnB,eAAe,UAAU;AAAA,IACzB,cAAc,aAAa;AAAA,EAC7B,EAAE;AACF,SAAO;AACT;AAOA,SAAS,mBAAmB,QAAyB;AACnD,QAAM,SAAS,kBAAkB,QAAQ,OAAO,QAAQ,KAAK,IAAI;AACjE,SAAO,SAAS,kBAAkB,MAAM,KAAK;AAC/C;AAGA,SAAS,WAAW,MAAqB,oBAAmD;AAC1F,QAAM,UAAU,kBAAkB,KAAK,MAAM,EAAE,YAAY,EAAE,QAAQ,KAAK,EAAE;AAI5E,QAAM,kBAAkB,KAAK,WAAW,UAAU,KAAK;AACvD,QAAM,MACJ,KAAK,WAAW,WAAW,KAAK,eAAe,SAAS,mBAAmB,QAAQ;AACrF,QAAM,QAAkB,CAAC;AAEzB,MAAI,KAAK,WAAW,UAAU,KAAK,cAAc,YAAY;AAC3D,UAAM,KAAK,UAAU;AAAA,EACvB;AACA,MAAI,iBAAiB;AACnB,UAAM,KAAK,aAAa;AAAA,EAC1B;AAIA,MAAI,KAAK,YAAY,YAAY;AAC/B,UAAM,QAAQ,kBAAkB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO;AACnE,QAAI,MAAO,OAAM,KAAK,MAAM,IAAI;AAAA,EAClC;AACA,MAAI,KAAK,WAAW,UAAU,KAAK,gBAAgB;AACjD,UAAM,YAAY,mBAAmB,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,cAAc;AAC7E,QAAI,UAAW,OAAM,KAAK,UAAU,IAAI;AAAA,EAC1C;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO,UAAU,GAAG,SAAS,MAAM,KAAK,KAAK,CAAC;AAAA,EAChD;AACA,SAAO,UAAU,GAAG;AACtB;AAEO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,oBAAoB;AACtB,GAA+B;AAC7B,QAAM,EAAE,gBAAgB,YAAY,IAAI,iBAAiB;AACzD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,KAAK;AAC5D,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,KAAK;AAC1D,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAwB,IAAI;AACxE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAoC,IAAI;AAChF,QAAM,CAAC,UAAU,WAAW,IAAI,SAA8C,IAAI;AAClF,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAgC,CAAC,CAAC;AACtF,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAwB,IAAI;AAClE,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAyC,IAAI;AAC/F,QAAM,wBAAwB,OAAO,CAAC;AACtC,QAAM,UAAU,OAAuB,IAAI;AAE3C,QAAM,cAAc,sBAAsB;AAQ1C,QAAM,aAAa,QAAQ,MAAM;AAC/B,UAAM,KAAK,aAAa;AACxB,QAAI,CAAC,GAAI,QAAO;AAChB,UAAM,aAAa,CAAC,GAAG,cAAc,GAAG,GAAG,OAAO,GAAG,GAAG,SAAS,CAAC;AAClE,eAAW,KAAK,YAAY;AAC1B,UAAI,OAAO,MAAM,YAAY,EAAE,KAAK,EAAG,QAAO,EAAE,KAAK;AAAA,IACvD;AACA,WAAO;AAAA,EACT,GAAG,CAAC,WAAW,CAAC;AAQhB,QAAM,gBAAgB,QAAQ,MAAM;AAClC,UAAM,OAAO,eAAe;AAC5B,WAAO,aAAa,EAAE,GAAG,MAAM,SAAS,WAAW,IAAI;AAAA,EACzD,GAAG,CAAC,aAAa,UAAU,CAAC;AAG5B,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,UAAM,gBAAgB,CAAC,MAAoB;AACzC,UAAI,QAAQ,WAAW,CAAC,QAAQ,QAAQ,SAAS,EAAE,MAAc,GAAG;AAClE,oBAAY,KAAK;AAAA,MACnB;AAAA,IACF;AACA,aAAS,iBAAiB,eAAe,aAAa;AACtD,WAAO,MAAM,SAAS,oBAAoB,eAAe,aAAa;AAAA,EACxE,GAAG,CAAC,QAAQ,CAAC;AAEb,YAAU,MAAM;AACd,QACE,CAAC,YACD,aAAa,WAAW,UACxB,CAAC,YAAY,kBACb,mBAAmB,SAAS,GAC5B;AACA;AAAA,IACF;AAEA,QAAI,YAAY;AAChB,gCAA4B,EACzB,KAAK,CAAC,kBAAkB;AACvB,UAAI,CAAC,UAAW,uBAAsB,aAAa;AAAA,IACrD,CAAC,EACA,MAAM,MAAM;AACX,UAAI,CAAC,UAAW,uBAAsB,CAAC,CAAC;AAAA,IAC1C,CAAC;AAEH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,aAAa,QAAQ,aAAa,gBAAgB,UAAU,mBAAmB,MAAM,CAAC;AAE1F,QAAM,mBAAmB,YAAY,MAAM;AACzC,gBAAY,CAAC,SAAS,CAAC,IAAI;AAAA,EAC7B,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB;AAAA,IACzB,OAAO,YAA2B;AAChC,UAAI,CAAC,mBAAoB;AAEzB,YAAM,YAAY,sBAAsB,UAAU;AAClD,4BAAsB,UAAU;AAEhC,UAAI;AACF,cAAM,EAAE,oBAAoB,IAAI,MAAM,oBAAoB;AAC1D,cAAM,WAAW,oBAAoB,cAAc,OAAO;AAC1D,cAAM,SAAS,MAAM,mBAAmB,cAAc,QAAQ;AAC9D,YAAI,sBAAsB,YAAY,UAAW,sBAAqB,MAAM;AAAA,MAC9E,QAAQ;AACN,YAAI,sBAAsB,YAAY,UAAW,sBAAqB,IAAI;AAAA,MAC5E;AAAA,IACF;AAAA,IACA,CAAC,oBAAoB,YAAY;AAAA,EACnC;AAEA,QAAM,mBAAmB,YAAY,MAAM;AACzC,gBAAY,KAAK;AACjB,mBAAe,IAAI;AACnB,kBAAc,IAAI;AAClB,SAAK,mBAAmB,aAAa;AAAA,EACvC,GAAG,CAAC,eAAe,kBAAkB,CAAC;AAEtC,QAAM,oBAAoB,YAAY,MAAM;AAC1C,kBAAc,KAAK;AACnB,mBAAe,IAAI;AAAA,EACrB,GAAG,CAAC,CAAC;AAEL,QAAM,wBAAwB,YAAY,MAAM;AAC9C,gBAAY,KAAK;AACjB,uBAAmB,IAAI;AAAA,EACzB,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyB,YAAY,MAAM;AAC/C,uBAAmB,KAAK;AAAA,EAC1B,GAAG,CAAC,CAAC;AAEL,QAAM,uBAAuB,YAAY,YAAY;AACnD,gBAAY,KAAK;AACjB,sBAAkB,IAAI;AACtB,oBAAgB,IAAI;AACpB,sBAAkB,IAAI;AAEtB,QAAI;AACF,YAAM,UAAU,gBAAiB,MAAM,uBAAuB;AAC9D,sBAAgB,OAAO;AACvB,kBAAY,QAAQ,cAAc,cAAc,cAAc,CAAC,CAAC;AAAA,IAClE,QAAQ;AACN,wBAAkB,mCAAmC;AAAA,IACvD,UAAE;AACA,sBAAgB,KAAK;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,gBAAgB,YAAY,CAAC;AAEjC,QAAM,wBAAwB,YAAY,MAAM;AAC9C,sBAAkB,KAAK;AACvB,gBAAY,IAAI;AAChB,sBAAkB,IAAI;AAAA,EACxB,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAsB;AAAA,IAC1B,CAAC,YAA2B;AAC1B,WAAK,mBAAmB,OAAO;AAAA,IACjC;AAAA,IACA,CAAC,kBAAkB;AAAA,EACrB;AAEA,QAAM,wBAAwB;AAAA,IAC5B,OAAO,YAA2B;AAChC,UAAI,CAAC,mBAAoB;AACzB,UAAI;AACF,cAAM,EAAE,oBAAoB,IAAI,MAAM,oBAAoB;AAC1D,cAAM,WAAW,oBAAoB,cAAc,OAAO;AAC1D,cAAM,eAAe,MAAM,mBAAmB,WAAW,UAAU,iBAAiB;AACpF,YAAI,iBAAiB,KAAM;AAC3B,6BAAqB,YAAY;AAAA,MACnC,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,CAAC,oBAAoB,mBAAmB,YAAY;AAAA,EACtD;AAEA,QAAM,oBAAoB;AAAA,IACxB,OAAO,MAAY,UAAkB,WAA2C;AAC9E,UAAI,CAAC,mBAAoB;AACzB,YAAM,cAAc,MAAM,mBAAmB,SAAS,MAAM,UAAU,MAAM;AAC5E,UAAI,YAAa,sBAAqB,WAAW;AAAA,IACnD;AAAA,IACA,CAAC,kBAAkB;AAAA,EACrB;AAEA,QAAM,4BAA4B;AAAA,IAChC,OAAO,MAAY,aAAqB;AACtC,YAAM,kBAAkB,MAAM,UAAU,iBAAiB;AAAA,IAC3D;AAAA,IACA,CAAC,mBAAmB,iBAAiB;AAAA,EACvC;AAEA,QAAM,eAAe;AAAA,IACnB,OAAO,SAAwB;AAC7B,mBAAa,IAAI;AACjB,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,cAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,qBAAqB,4BAA4B;AAAA,QACnD;AAGA,sBAAc,KAAK;AAAA,MACrB,SAAS,QAAiB;AACxB,uBAAe,mBAAmB,MAAM,CAAC;AAAA,MAC3C,UAAE;AACA,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,oBAAoB,YAAY,YAAY;AAChD,QAAI,CAAC,YAAa;AAClB,gBAAY,KAAK;AACjB,iBAAa,IAAI;AACjB,mBAAe,IAAI;AACnB,QAAI;AACF,wBAAkB,WAAW;AAC7B,YAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAI,cAA8C;AAClD,UAAI,oBAAoB;AACtB,cAAM,EAAE,oBAAoB,IAAI,MAAM,oBAAoB;AAC1D,sBAAc,MAAM,mBAAmB;AAAA,UACrC,oBAAoB,cAAc,WAAW;AAAA,QAC/C;AAAA,MACF;AACA,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,qBACI,OAAO,MAAM,aAAa,kBAAkB,MAAM,UAAU,WAAW,IACvE;AAAA,MACN;AAAA,IACF,SAAS,QAAiB;AAGxB,qBAAe,mBAAmB,MAAM,CAAC;AAAA,IAC3C,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,2BAA2B,YAAY,MAAM;AACjD,mBAAe,IAAI;AAAA,EACrB,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyB,cAAc;AAE7C,SACE,iCACG;AAAA,yBAAqB,oBAAC,yBAAsB,MAAM,mBAAmB;AAAA,IACrE,YAAY,WACX;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS;AAAA,QACT,UAAU;AAAA,QACV,cAAW;AAAA,QACX,gBAAc,YAAY,iBAAiB;AAAA,QAE3C,8BAAC,eAAY;AAAA;AAAA,IACf,IAEA,qBAAC,SAAI,WAAU,mBAAkB,KAAK,SACpC;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS;AAAA,UACT,cAAW;AAAA,UACX,iBAAc;AAAA,UACd,iBAAe;AAAA,UACf,OAAM;AAAA,UAEN,8BAAC,cAAW;AAAA;AAAA,MACd;AAAA,MAEC,YACC,qBAAC,SAAI,WAAU,4BAA2B,MAAK,QAC5C;AAAA,uBACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS;AAAA,YACT,UAAU;AAAA,YAET,qBAAW,aAAa,kBAAkB;AAAA;AAAA,QAC7C;AAAA,QAEF;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS;AAAA,YACV;AAAA;AAAA,QAED;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS;AAAA,YACV;AAAA;AAAA,QAED;AAAA,QACC,mBACC,iCACE;AAAA,8BAAC,SAAI,WAAU,2BAA0B,MAAK,aAAY;AAAA,UAC1D;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS;AAAA,cACV;AAAA;AAAA,UAED;AAAA,WACF;AAAA,SAEJ;AAAA,OAEJ;AAAA,IAGD,cACC,oBAAC,YAAS,UAAU,MAClB;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT;AAAA,QACA,OAAO;AAAA,QACP,aACE,qBACI;AAAA,UACE,OAAO,mBAAmB,eAAe;AAAA,UACzC,QAAQ;AAAA,UACR,MAAM,mBAAmB;AAAA,QAC3B,IACA;AAAA,QAEN,UAAU;AAAA,QACV,iBAAiB,qBAAqB,sBAAsB;AAAA,QAC5D,SAAS;AAAA;AAAA,IACX,GACF;AAAA,IAKD,eAAe,CAAC,cACf;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,SAAS;AAAA,QACT,QACE;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS;AAAA,YACV;AAAA;AAAA,QAED;AAAA,QAGF,8BAAC,OAAE,WAAU,mBAAkB,MAAK,SACjC,uBACH;AAAA;AAAA,IACF;AAAA,IAGD,mBACC,oBAAC,YAAS,UAAU,MAClB;AAAA,MAAC;AAAA;AAAA,QACC,UAAU;AAAA,QACV;AAAA,QACA,SACE,iBACC,OAAO,WAAW,cACf,2CACA,OAAO,SAAS;AAAA,QAEtB,SAAS;AAAA;AAAA,IACX,GACF;AAAA,IAGD,mBAAmB,gBAAgB,mBAClC,oBAAC,SAAI,WAAU,qBACb,+BAAC,SAAI,WAAU,aACb;AAAA,2BAAC,SAAI,WAAU,oBACb;AAAA,4BAAC,QAAG,WAAU,mBAAkB,0BAAY;AAAA,QAC5C;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,SAAS;AAAA,YACT,cAAW;AAAA,YACZ;AAAA;AAAA,QAED;AAAA,SACF;AAAA,MACA,oBAAC,SAAI,WAAU,kBACb,8BAAC,OAAE,WAAU,kBAAkB,4BAAkB,cAAa,GAChE;AAAA,OACF,GACF;AAAA,IAGD,kBACC,gBACA,0BACA,YACA,CAAC,gBACD,CAAC,kBACC;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,cAAc,aAAa;AAAA,QAC3B;AAAA,QACA,WAAW;AAAA,QACX,SAAS;AAAA;AAAA,IACX;AAAA,KAEN;AAEJ;AAEA,SAAS,cAAc;AACrB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MAEZ;AAAA,4BAAC,UAAK,GAAE,qGAAoG;AAAA,QAC5G,oBAAC,UAAK,GAAE,qBAAoB;AAAA,QAC5B,oBAAC,UAAK,GAAE,eAAc;AAAA,QACtB,oBAAC,UAAK,GAAE,+BAA8B;AAAA;AAAA;AAAA,EACxC;AAEJ;AAEA,SAAS,aAAa;AACpB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MAEZ;AAAA,4BAAC,UAAK,GAAE,gBAAe;AAAA,QACvB,oBAAC,UAAK,GAAE,8BAA6B;AAAA,QACrC,oBAAC,UAAK,GAAE,yHAAwH;AAAA;AAAA;AAAA,EAClI;AAEJ;","names":[]}