@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.
- package/README.md +37 -5
- package/dist/ExportDialog-7LDIXJZ3.js +10 -0
- package/dist/ExportDialog-7LDIXJZ3.js.map +1 -0
- package/dist/ExportToolbarControls-GHAOJMH6.js +508 -0
- package/dist/ExportToolbarControls-GHAOJMH6.js.map +1 -0
- package/dist/GitToolbarControl-GNMRVKWQ.js +136 -0
- package/dist/GitToolbarControl-GNMRVKWQ.js.map +1 -0
- package/dist/GitUI-VHOBQY43.js +1133 -0
- package/dist/GitUI-VHOBQY43.js.map +1 -0
- package/dist/LazyEditorShell-EF2BWRXU.js +6 -0
- package/dist/LazyEditorShell-EF2BWRXU.js.map +1 -0
- package/dist/ShareDialog-63ENBEDZ.js +213 -0
- package/dist/ShareDialog-63ENBEDZ.js.map +1 -0
- package/dist/chunk-4XXSWN3T.js +13 -0
- package/dist/chunk-4XXSWN3T.js.map +1 -0
- package/dist/chunk-57ZJJOC5.js +89 -0
- package/dist/chunk-57ZJJOC5.js.map +1 -0
- package/dist/chunk-5A4KEWKT.js +97 -0
- package/dist/chunk-5A4KEWKT.js.map +1 -0
- package/dist/chunk-DD4VFJQI.js +51 -0
- package/dist/chunk-DD4VFJQI.js.map +1 -0
- package/dist/chunk-FEWQUQML.js +256 -0
- package/dist/chunk-FEWQUQML.js.map +1 -0
- package/dist/chunk-FMGTHSTX.js +110 -0
- package/dist/chunk-FMGTHSTX.js.map +1 -0
- package/dist/chunk-UNYZQXWR.js +324 -0
- package/dist/chunk-UNYZQXWR.js.map +1 -0
- package/dist/chunk-VHDP4IPL.js +70 -0
- package/dist/chunk-VHDP4IPL.js.map +1 -0
- package/dist/chunk-ZI56BNB7.js +270 -0
- package/dist/chunk-ZI56BNB7.js.map +1 -0
- package/dist/editor.d.ts +11 -0
- package/dist/editor.js +9 -0
- package/dist/editor.js.map +1 -0
- package/dist/export/index.d.ts +93 -0
- package/dist/export/index.js +27 -0
- package/dist/export/index.js.map +1 -0
- package/dist/index.d.ts +346 -18
- package/dist/index.js +6169 -18
- package/dist/index.js.map +1 -1
- package/dist/run-export-ICTZITXC.js +10 -0
- package/dist/run-export-ICTZITXC.js.map +1 -0
- package/dist/settings/index.d.ts +36 -0
- package/dist/settings/index.js +14 -0
- package/dist/settings/index.js.map +1 -0
- package/package.json +33 -13
- package/src/styles/docblocks.css +2738 -132
- package/dist/AppMenu/AppMenu.d.ts +0 -26
- package/dist/AppMenu/AppMenu.d.ts.map +0 -1
- package/dist/AppMenu/AppMenu.js +0 -28
- package/dist/AppMenu/AppMenu.js.map +0 -1
- package/dist/AppMenu/index.d.ts +0 -3
- package/dist/AppMenu/index.d.ts.map +0 -1
- package/dist/AppMenu/index.js +0 -2
- package/dist/AppMenu/index.js.map +0 -1
- package/dist/DocBlocksShell/DocBlocksShell.d.ts +0 -36
- package/dist/DocBlocksShell/DocBlocksShell.d.ts.map +0 -1
- package/dist/DocBlocksShell/DocBlocksShell.js +0 -1351
- package/dist/DocBlocksShell/DocBlocksShell.js.map +0 -1
- package/dist/DocBlocksShell/index.d.ts +0 -3
- package/dist/DocBlocksShell/index.d.ts.map +0 -1
- package/dist/DocBlocksShell/index.js +0 -2
- package/dist/DocBlocksShell/index.js.map +0 -1
- package/dist/Export/ExportDialog.d.ts +0 -16
- package/dist/Export/ExportDialog.d.ts.map +0 -1
- package/dist/Export/ExportDialog.js +0 -158
- package/dist/Export/ExportDialog.js.map +0 -1
- package/dist/Export/ExportToolbarControls.d.ts +0 -17
- package/dist/Export/ExportToolbarControls.d.ts.map +0 -1
- package/dist/Export/ExportToolbarControls.js +0 -200
- package/dist/Export/ExportToolbarControls.js.map +0 -1
- package/dist/Export/export-options.d.ts +0 -53
- package/dist/Export/export-options.d.ts.map +0 -1
- package/dist/Export/export-options.js +0 -49
- package/dist/Export/export-options.js.map +0 -1
- package/dist/Export/index.d.ts +0 -6
- package/dist/Export/index.d.ts.map +0 -1
- package/dist/Export/index.js +0 -3
- package/dist/Export/index.js.map +0 -1
- package/dist/Export/run-export.d.ts +0 -8
- package/dist/Export/run-export.d.ts.map +0 -1
- package/dist/Export/run-export.js +0 -296
- package/dist/Export/run-export.js.map +0 -1
- package/dist/Export/transform-summaries.d.ts +0 -7
- package/dist/Export/transform-summaries.d.ts.map +0 -1
- package/dist/Export/transform-summaries.js +0 -6
- package/dist/Export/transform-summaries.js.map +0 -1
- package/dist/FileExplorer/FileExplorer.d.ts +0 -21
- package/dist/FileExplorer/FileExplorer.d.ts.map +0 -1
- package/dist/FileExplorer/FileExplorer.js +0 -140
- package/dist/FileExplorer/FileExplorer.js.map +0 -1
- package/dist/FileExplorer/FileTreeNode.d.ts +0 -18
- package/dist/FileExplorer/FileTreeNode.d.ts.map +0 -1
- package/dist/FileExplorer/FileTreeNode.js +0 -112
- package/dist/FileExplorer/FileTreeNode.js.map +0 -1
- package/dist/FileExplorer/index.d.ts +0 -6
- package/dist/FileExplorer/index.d.ts.map +0 -1
- package/dist/FileExplorer/index.js +0 -4
- package/dist/FileExplorer/index.js.map +0 -1
- package/dist/FileExplorer/useFileTree.d.ts +0 -35
- package/dist/FileExplorer/useFileTree.d.ts.map +0 -1
- package/dist/FileExplorer/useFileTree.js +0 -124
- package/dist/FileExplorer/useFileTree.js.map +0 -1
- package/dist/WorkspacePicker/WorkspacePicker.d.ts +0 -17
- package/dist/WorkspacePicker/WorkspacePicker.d.ts.map +0 -1
- package/dist/WorkspacePicker/WorkspacePicker.js +0 -63
- package/dist/WorkspacePicker/WorkspacePicker.js.map +0 -1
- package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts +0 -11
- package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts.map +0 -1
- package/dist/WorkspacePicker/WorkspaceSettingsButton.js +0 -27
- package/dist/WorkspacePicker/WorkspaceSettingsButton.js.map +0 -1
- package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts +0 -20
- package/dist/WorkspacePicker/WorkspaceSettingsDialog.d.ts.map +0 -1
- package/dist/WorkspacePicker/WorkspaceSettingsDialog.js +0 -36
- package/dist/WorkspacePicker/WorkspaceSettingsDialog.js.map +0 -1
- package/dist/WorkspacePicker/index.d.ts +0 -3
- package/dist/WorkspacePicker/index.d.ts.map +0 -1
- package/dist/WorkspacePicker/index.js +0 -2
- package/dist/WorkspacePicker/index.js.map +0 -1
- package/dist/hooks/index.d.ts +0 -2
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -2
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/useAutoSave.d.ts +0 -15
- package/dist/hooks/useAutoSave.d.ts.map +0 -1
- package/dist/hooks/useAutoSave.js +0 -83
- package/dist/hooks/useAutoSave.js.map +0 -1
- package/dist/icons.d.ts +0 -7
- package/dist/icons.d.ts.map +0 -1
- package/dist/icons.js +0 -27
- package/dist/icons.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/monaco-slim.d.ts +0 -19
- package/dist/monaco-slim.d.ts.map +0 -1
- package/dist/monaco-slim.js +0 -19
- package/dist/monaco-slim.js.map +0 -1
- package/dist/preferences/versioning.d.ts +0 -27
- package/dist/preferences/versioning.d.ts.map +0 -1
- package/dist/preferences/versioning.js +0 -62
- package/dist/preferences/versioning.js.map +0 -1
- package/src/AppMenu/AppMenu.tsx +0 -264
- package/src/AppMenu/index.ts +0 -2
- package/src/DocBlocksShell/DocBlocksShell.tsx +0 -1778
- package/src/DocBlocksShell/index.ts +0 -2
- package/src/Export/ExportDialog.tsx +0 -383
- package/src/Export/ExportToolbarControls.tsx +0 -313
- package/src/Export/export-options.ts +0 -99
- package/src/Export/index.ts +0 -5
- package/src/Export/run-export.ts +0 -349
- package/src/Export/transform-summaries.ts +0 -14
- package/src/FileExplorer/FileExplorer.tsx +0 -282
- package/src/FileExplorer/FileTreeNode.tsx +0 -214
- package/src/FileExplorer/index.ts +0 -5
- package/src/FileExplorer/useFileTree.ts +0 -178
- package/src/WorkspacePicker/WorkspacePicker.tsx +0 -137
- package/src/WorkspacePicker/WorkspaceSettingsButton.tsx +0 -88
- package/src/WorkspacePicker/WorkspaceSettingsDialog.tsx +0 -121
- package/src/WorkspacePicker/index.ts +0 -2
- package/src/fonts/fonts.css +0 -362
- package/src/fonts/licenses/LICENSE-cormorant-garamond.txt +0 -93
- package/src/fonts/licenses/LICENSE-crimson-text.txt +0 -93
- package/src/fonts/licenses/LICENSE-dm-sans.txt +0 -93
- package/src/fonts/licenses/LICENSE-dm-serif-display.txt +0 -93
- package/src/fonts/licenses/LICENSE-hanken-grotesk.txt +0 -94
- package/src/fonts/licenses/LICENSE-ibm-plex-sans.txt +0 -93
- package/src/fonts/licenses/LICENSE-inter.txt +0 -93
- package/src/fonts/licenses/LICENSE-jetbrains-mono.txt +0 -93
- package/src/fonts/licenses/LICENSE-lora.txt +0 -93
- package/src/fonts/licenses/LICENSE-merriweather.txt +0 -93
- package/src/fonts/licenses/LICENSE-oswald.txt +0 -93
- package/src/fonts/licenses/LICENSE-playfair-display.txt +0 -93
- package/src/fonts/licenses/LICENSE-pt-serif.txt +0 -93
- package/src/fonts/licenses/LICENSE-roboto.txt +0 -93
- package/src/fonts/licenses/LICENSE-source-serif-4.txt +0 -93
- package/src/fonts/woff2/cormorant-garamond-400.woff2 +0 -0
- package/src/fonts/woff2/cormorant-garamond-700.woff2 +0 -0
- package/src/fonts/woff2/crimson-text-400.woff2 +0 -0
- package/src/fonts/woff2/crimson-text-400i.woff2 +0 -0
- package/src/fonts/woff2/crimson-text-700.woff2 +0 -0
- package/src/fonts/woff2/dm-sans-400.woff2 +0 -0
- package/src/fonts/woff2/dm-sans-400i.woff2 +0 -0
- package/src/fonts/woff2/dm-sans-500.woff2 +0 -0
- package/src/fonts/woff2/dm-sans-700.woff2 +0 -0
- package/src/fonts/woff2/dm-serif-display-400.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-400.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-400i.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-500.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-600.woff2 +0 -0
- package/src/fonts/woff2/hanken-grotesk-700.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-400.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-400i.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-500.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-600.woff2 +0 -0
- package/src/fonts/woff2/ibm-plex-sans-700.woff2 +0 -0
- package/src/fonts/woff2/inter-400.woff2 +0 -0
- package/src/fonts/woff2/inter-400i.woff2 +0 -0
- package/src/fonts/woff2/inter-500.woff2 +0 -0
- package/src/fonts/woff2/inter-600.woff2 +0 -0
- package/src/fonts/woff2/inter-700.woff2 +0 -0
- package/src/fonts/woff2/jetbrains-mono-400.woff2 +0 -0
- package/src/fonts/woff2/jetbrains-mono-400i.woff2 +0 -0
- package/src/fonts/woff2/jetbrains-mono-700.woff2 +0 -0
- package/src/fonts/woff2/lora-400.woff2 +0 -0
- package/src/fonts/woff2/lora-400i.woff2 +0 -0
- package/src/fonts/woff2/lora-700.woff2 +0 -0
- package/src/fonts/woff2/merriweather-400.woff2 +0 -0
- package/src/fonts/woff2/merriweather-700.woff2 +0 -0
- package/src/fonts/woff2/oswald-400.woff2 +0 -0
- package/src/fonts/woff2/oswald-700.woff2 +0 -0
- package/src/fonts/woff2/playfair-display-400.woff2 +0 -0
- package/src/fonts/woff2/playfair-display-700.woff2 +0 -0
- package/src/fonts/woff2/pt-serif-400.woff2 +0 -0
- package/src/fonts/woff2/pt-serif-700.woff2 +0 -0
- package/src/fonts/woff2/roboto-400.woff2 +0 -0
- package/src/fonts/woff2/roboto-400i.woff2 +0 -0
- package/src/fonts/woff2/roboto-700.woff2 +0 -0
- package/src/fonts/woff2/source-serif-4-400.woff2 +0 -0
- package/src/fonts/woff2/source-serif-4-400i.woff2 +0 -0
- package/src/fonts/woff2/source-serif-4-700.woff2 +0 -0
- package/src/hooks/index.ts +0 -1
- package/src/hooks/useAutoSave.ts +0 -116
- package/src/icons.tsx +0 -70
- package/src/index.ts +0 -31
- package/src/monaco-slim.ts +0 -20
- 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 `
|
|
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,
|
|
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
|
-
### `
|
|
87
|
+
### `useDocumentSession(delay?)`
|
|
58
88
|
|
|
59
|
-
|
|
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
|
|
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 @@
|
|
|
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 ×\n </button>\n </div>\n <div className=\"db-dialog-body\">\n <p className=\"db-export-hint\">{videoLoadError ?? 'Loading...'}</p>\n </div>\n </div>\n </div>\n )}\n\n {videoModalOpen &&\n videoModules &&\n LoadedVideoExportModal &&\n videoDoc &&\n !videoLoading &&\n !videoLoadError && (\n <LoadedVideoExportModal\n doc={videoDoc}\n playerScript={videoModules.playerScript}\n colorScheme={colorScheme}\n uiPalette={videoExportPalette}\n onClose={handleCloseVideoModal}\n />\n )}\n </>\n );\n}\n\nfunction ExportGlyph() {\n return (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M4.5 1.75h4.25L12 5v7.25a1.5 1.5 0 0 1-1.5 1.5h-6A1.5 1.5 0 0 1 3 12.25v-9a1.5 1.5 0 0 1 1.5-1.5z\" />\n <path d=\"M8.75 1.75V5h3.25\" />\n <path d=\"M6 8.75h4.5\" />\n <path d=\"M8.75 7 10.5 8.75 8.75 10.5\" />\n </svg>\n );\n}\n\nfunction ShareGlyph() {\n return (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M8 10.5V1.75\" />\n <path d=\"M5.25 4.5 8 1.75l2.75 2.75\" />\n <path d=\"M4.25 6.75h-1a1.5 1.5 0 0 0-1.5 1.5v4.5a1.5 1.5 0 0 0 1.5 1.5h9.5a1.5 1.5 0 0 0 1.5-1.5v-4.5a1.5 1.5 0 0 0-1.5-1.5h-1\" />\n </svg>\n );\n}\n"],"mappings":"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","names":[]}
|