@bendyline/docblocks-react 0.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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/AppMenu/AppMenu.d.ts +11 -0
- package/dist/AppMenu/AppMenu.d.ts.map +1 -0
- package/dist/AppMenu/AppMenu.js +27 -0
- package/dist/AppMenu/AppMenu.js.map +1 -0
- package/dist/AppMenu/index.d.ts +3 -0
- package/dist/AppMenu/index.d.ts.map +1 -0
- package/dist/AppMenu/index.js +2 -0
- package/dist/AppMenu/index.js.map +1 -0
- package/dist/DocBlocksShell/DocBlocksShell.d.ts +16 -0
- package/dist/DocBlocksShell/DocBlocksShell.d.ts.map +1 -0
- package/dist/DocBlocksShell/DocBlocksShell.js +487 -0
- package/dist/DocBlocksShell/DocBlocksShell.js.map +1 -0
- package/dist/DocBlocksShell/index.d.ts +3 -0
- package/dist/DocBlocksShell/index.d.ts.map +1 -0
- package/dist/DocBlocksShell/index.js +2 -0
- package/dist/DocBlocksShell/index.js.map +1 -0
- package/dist/Export/ExportDialog.d.ts +16 -0
- package/dist/Export/ExportDialog.d.ts.map +1 -0
- package/dist/Export/ExportDialog.js +42 -0
- package/dist/Export/ExportDialog.js.map +1 -0
- package/dist/Export/ExportToolbarControls.d.ts +17 -0
- package/dist/Export/ExportToolbarControls.d.ts.map +1 -0
- package/dist/Export/ExportToolbarControls.js +109 -0
- package/dist/Export/ExportToolbarControls.js.map +1 -0
- package/dist/Export/export-options.d.ts +18 -0
- package/dist/Export/export-options.d.ts.map +1 -0
- package/dist/Export/export-options.js +44 -0
- package/dist/Export/export-options.js.map +1 -0
- package/dist/Export/index.d.ts +6 -0
- package/dist/Export/index.d.ts.map +1 -0
- package/dist/Export/index.js +3 -0
- package/dist/Export/index.js.map +1 -0
- package/dist/Export/run-export.d.ts +8 -0
- package/dist/Export/run-export.d.ts.map +1 -0
- package/dist/Export/run-export.js +208 -0
- package/dist/Export/run-export.js.map +1 -0
- package/dist/FileExplorer/FileExplorer.d.ts +21 -0
- package/dist/FileExplorer/FileExplorer.d.ts.map +1 -0
- package/dist/FileExplorer/FileExplorer.js +125 -0
- package/dist/FileExplorer/FileExplorer.js.map +1 -0
- package/dist/FileExplorer/FileTreeNode.d.ts +18 -0
- package/dist/FileExplorer/FileTreeNode.d.ts.map +1 -0
- package/dist/FileExplorer/FileTreeNode.js +86 -0
- package/dist/FileExplorer/FileTreeNode.js.map +1 -0
- package/dist/FileExplorer/index.d.ts +6 -0
- package/dist/FileExplorer/index.d.ts.map +1 -0
- package/dist/FileExplorer/index.js +4 -0
- package/dist/FileExplorer/index.js.map +1 -0
- package/dist/FileExplorer/useFileTree.d.ts +35 -0
- package/dist/FileExplorer/useFileTree.d.ts.map +1 -0
- package/dist/FileExplorer/useFileTree.js +124 -0
- package/dist/FileExplorer/useFileTree.js.map +1 -0
- package/dist/WorkspacePicker/WorkspacePicker.d.ts +17 -0
- package/dist/WorkspacePicker/WorkspacePicker.d.ts.map +1 -0
- package/dist/WorkspacePicker/WorkspacePicker.js +57 -0
- package/dist/WorkspacePicker/WorkspacePicker.js.map +1 -0
- package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts +10 -0
- package/dist/WorkspacePicker/WorkspaceSettingsButton.d.ts.map +1 -0
- package/dist/WorkspacePicker/WorkspaceSettingsButton.js +27 -0
- package/dist/WorkspacePicker/WorkspaceSettingsButton.js.map +1 -0
- package/dist/WorkspacePicker/index.d.ts +3 -0
- package/dist/WorkspacePicker/index.d.ts.map +1 -0
- package/dist/WorkspacePicker/index.js +2 -0
- package/dist/WorkspacePicker/index.js.map +1 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useAutoSave.d.ts +9 -0
- package/dist/hooks/useAutoSave.d.ts.map +1 -0
- package/dist/hooks/useAutoSave.js +48 -0
- package/dist/hooks/useAutoSave.js.map +1 -0
- package/dist/icons.d.ts +6 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +24 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/package.json +65 -0
- package/src/AppMenu/AppMenu.tsx +124 -0
- package/src/AppMenu/index.ts +2 -0
- package/src/DocBlocksShell/DocBlocksShell.tsx +662 -0
- package/src/DocBlocksShell/index.ts +2 -0
- package/src/Export/ExportDialog.tsx +173 -0
- package/src/Export/ExportToolbarControls.tsx +183 -0
- package/src/Export/export-options.ts +57 -0
- package/src/Export/index.ts +5 -0
- package/src/Export/run-export.ts +238 -0
- package/src/FileExplorer/FileExplorer.tsx +260 -0
- package/src/FileExplorer/FileTreeNode.tsx +172 -0
- package/src/FileExplorer/index.ts +5 -0
- package/src/FileExplorer/useFileTree.ts +178 -0
- package/src/WorkspacePicker/WorkspacePicker.tsx +126 -0
- package/src/WorkspacePicker/WorkspaceSettingsButton.tsx +79 -0
- package/src/WorkspacePicker/index.ts +2 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useAutoSave.ts +58 -0
- package/src/icons.tsx +60 -0
- package/src/index.ts +31 -0
- package/src/styles/docblocks.css +961 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkspacePicker — dropdown for switching between workspaces
|
|
3
|
+
* (IndexedDB-based or native folder via File System Access API).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
7
|
+
import type { WorkspaceDescriptor } from '@bendyline/docblocks/workspace';
|
|
8
|
+
import { listWorkspaces, saveWorkspace, touchWorkspace } from '@bendyline/docblocks/workspace';
|
|
9
|
+
import { isNativeFileSystemSupported } from '@bendyline/docblocks/filesystem';
|
|
10
|
+
|
|
11
|
+
export interface WorkspacePickerProps {
|
|
12
|
+
/** Currently active workspace id. */
|
|
13
|
+
activeWorkspaceId: string | null;
|
|
14
|
+
/** Called when the user picks a different workspace. */
|
|
15
|
+
onSelect: (descriptor: WorkspaceDescriptor) => void;
|
|
16
|
+
/** Called when the user chooses "Open Folder" (native FS). */
|
|
17
|
+
onOpenFolder: () => void;
|
|
18
|
+
/** Optional className. */
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function WorkspacePicker({
|
|
23
|
+
activeWorkspaceId,
|
|
24
|
+
onSelect,
|
|
25
|
+
onOpenFolder,
|
|
26
|
+
className,
|
|
27
|
+
}: WorkspacePickerProps) {
|
|
28
|
+
const [workspaces, setWorkspaces] = useState<WorkspaceDescriptor[]>([]);
|
|
29
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
30
|
+
const pickerRef = useRef<HTMLDivElement>(null);
|
|
31
|
+
|
|
32
|
+
// Close dropdown on outside click
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!isOpen) return;
|
|
35
|
+
function handleOutsideClick(e: MouseEvent) {
|
|
36
|
+
if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {
|
|
37
|
+
setIsOpen(false);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
document.addEventListener('mousedown', handleOutsideClick);
|
|
41
|
+
return () => document.removeEventListener('mousedown', handleOutsideClick);
|
|
42
|
+
}, [isOpen]);
|
|
43
|
+
|
|
44
|
+
const refresh = useCallback(async () => {
|
|
45
|
+
const list = await listWorkspaces();
|
|
46
|
+
setWorkspaces(list);
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
refresh();
|
|
51
|
+
}, [refresh, activeWorkspaceId]);
|
|
52
|
+
|
|
53
|
+
const handleSelect = useCallback(
|
|
54
|
+
async (ws: WorkspaceDescriptor) => {
|
|
55
|
+
await touchWorkspace(ws.id);
|
|
56
|
+
onSelect(ws);
|
|
57
|
+
setIsOpen(false);
|
|
58
|
+
},
|
|
59
|
+
[onSelect],
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const handleCreateNew = useCallback(async () => {
|
|
63
|
+
const name = `Workspace ${workspaces.length + 1}`;
|
|
64
|
+
const id = `ws-${Date.now()}`;
|
|
65
|
+
const descriptor: WorkspaceDescriptor = {
|
|
66
|
+
id,
|
|
67
|
+
name,
|
|
68
|
+
type: 'indexeddb',
|
|
69
|
+
lastOpened: new Date().toISOString(),
|
|
70
|
+
};
|
|
71
|
+
await saveWorkspace(descriptor);
|
|
72
|
+
await refresh();
|
|
73
|
+
onSelect(descriptor);
|
|
74
|
+
setIsOpen(false);
|
|
75
|
+
}, [workspaces.length, onSelect, refresh]);
|
|
76
|
+
|
|
77
|
+
const activeWs = workspaces.find((w) => w.id === activeWorkspaceId);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<div ref={pickerRef} className={`db-workspace-picker ${className ?? ''}`}>
|
|
81
|
+
<button
|
|
82
|
+
className="db-workspace-picker-btn"
|
|
83
|
+
onClick={() => setIsOpen(!isOpen)}
|
|
84
|
+
title="Switch workspace"
|
|
85
|
+
>
|
|
86
|
+
{activeWs?.name ?? 'No workspace'}
|
|
87
|
+
<span className="db-workspace-picker-caret">{isOpen ? '\u25B4' : '\u25BE'}</span>
|
|
88
|
+
</button>
|
|
89
|
+
|
|
90
|
+
{isOpen && (
|
|
91
|
+
<div className="db-workspace-dropdown">
|
|
92
|
+
{workspaces.map((ws) => (
|
|
93
|
+
<button
|
|
94
|
+
key={ws.id}
|
|
95
|
+
className={`db-workspace-dropdown-item ${
|
|
96
|
+
ws.id === activeWorkspaceId ? 'db-workspace-dropdown-item--active' : ''
|
|
97
|
+
}`}
|
|
98
|
+
onClick={() => handleSelect(ws)}
|
|
99
|
+
>
|
|
100
|
+
{ws.name}
|
|
101
|
+
<span className="db-workspace-type">{ws.type === 'native' ? '(folder)' : ''}</span>
|
|
102
|
+
</button>
|
|
103
|
+
))}
|
|
104
|
+
|
|
105
|
+
<div className="db-workspace-dropdown-divider" />
|
|
106
|
+
|
|
107
|
+
<button className="db-workspace-dropdown-item" onClick={handleCreateNew}>
|
|
108
|
+
+ New Workspace
|
|
109
|
+
</button>
|
|
110
|
+
|
|
111
|
+
{isNativeFileSystemSupported() && (
|
|
112
|
+
<button
|
|
113
|
+
className="db-workspace-dropdown-item"
|
|
114
|
+
onClick={() => {
|
|
115
|
+
setIsOpen(false);
|
|
116
|
+
onOpenFolder();
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
Open Folder...
|
|
120
|
+
</button>
|
|
121
|
+
)}
|
|
122
|
+
</div>
|
|
123
|
+
)}
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkspaceSettingsButton — gear icon dropdown for workspace actions.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useState, useCallback, useRef, useEffect } from 'react';
|
|
6
|
+
import { WorkspaceIcon } from '../icons.js';
|
|
7
|
+
|
|
8
|
+
export interface WorkspaceSettingsButtonProps {
|
|
9
|
+
onRename: () => void;
|
|
10
|
+
onDownload: () => void;
|
|
11
|
+
onRemove: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function WorkspaceSettingsButton({
|
|
15
|
+
onRename,
|
|
16
|
+
onDownload,
|
|
17
|
+
onRemove,
|
|
18
|
+
}: WorkspaceSettingsButtonProps) {
|
|
19
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
20
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!isOpen) return;
|
|
24
|
+
function handleOutsideClick(e: MouseEvent) {
|
|
25
|
+
if (ref.current && !ref.current.contains(e.target as Node)) {
|
|
26
|
+
setIsOpen(false);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
document.addEventListener('mousedown', handleOutsideClick);
|
|
30
|
+
return () => document.removeEventListener('mousedown', handleOutsideClick);
|
|
31
|
+
}, [isOpen]);
|
|
32
|
+
|
|
33
|
+
const handleAction = useCallback((action: () => void) => {
|
|
34
|
+
setIsOpen(false);
|
|
35
|
+
action();
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div ref={ref} className="db-ws-settings">
|
|
40
|
+
<button
|
|
41
|
+
className="db-ws-settings-btn"
|
|
42
|
+
onClick={() => setIsOpen(!isOpen)}
|
|
43
|
+
aria-expanded={isOpen}
|
|
44
|
+
aria-haspopup="true"
|
|
45
|
+
aria-label="Workspace settings"
|
|
46
|
+
title="Workspace settings"
|
|
47
|
+
>
|
|
48
|
+
<WorkspaceIcon />
|
|
49
|
+
</button>
|
|
50
|
+
|
|
51
|
+
{isOpen && (
|
|
52
|
+
<div className="db-ws-settings-dropdown" role="menu">
|
|
53
|
+
<button
|
|
54
|
+
className="db-ws-settings-item"
|
|
55
|
+
role="menuitem"
|
|
56
|
+
onClick={() => handleAction(onRename)}
|
|
57
|
+
>
|
|
58
|
+
Rename workspace
|
|
59
|
+
</button>
|
|
60
|
+
<button
|
|
61
|
+
className="db-ws-settings-item"
|
|
62
|
+
role="menuitem"
|
|
63
|
+
onClick={() => handleAction(onDownload)}
|
|
64
|
+
>
|
|
65
|
+
Download workspace
|
|
66
|
+
</button>
|
|
67
|
+
<div className="db-ws-settings-divider" />
|
|
68
|
+
<button
|
|
69
|
+
className="db-ws-settings-item db-ws-settings-item--danger"
|
|
70
|
+
role="menuitem"
|
|
71
|
+
onClick={() => handleAction(onRemove)}
|
|
72
|
+
>
|
|
73
|
+
Remove workspace
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useAutoSave } from './useAutoSave.js';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useAutoSave — debounced auto-save hook.
|
|
3
|
+
*
|
|
4
|
+
* Writes content to the FileSystemProvider after a delay
|
|
5
|
+
* whenever the content changes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useEffect, useRef, useCallback } from 'react';
|
|
9
|
+
import type { FileSystemProvider } from '@bendyline/docblocks/filesystem';
|
|
10
|
+
|
|
11
|
+
export function useAutoSave(
|
|
12
|
+
provider: FileSystemProvider | null,
|
|
13
|
+
filePath: string | null,
|
|
14
|
+
content: string,
|
|
15
|
+
delayMs = 500,
|
|
16
|
+
): void {
|
|
17
|
+
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
18
|
+
const lastSavedRef = useRef<string>(content);
|
|
19
|
+
|
|
20
|
+
const save = useCallback(async () => {
|
|
21
|
+
if (!provider || !filePath) return;
|
|
22
|
+
if (content === lastSavedRef.current) return;
|
|
23
|
+
lastSavedRef.current = content;
|
|
24
|
+
await provider.writeFile(filePath, content);
|
|
25
|
+
}, [provider, filePath, content]);
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!provider || !filePath) return;
|
|
29
|
+
|
|
30
|
+
if (timerRef.current) {
|
|
31
|
+
clearTimeout(timerRef.current);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
timerRef.current = setTimeout(() => {
|
|
35
|
+
save();
|
|
36
|
+
}, delayMs);
|
|
37
|
+
|
|
38
|
+
return () => {
|
|
39
|
+
if (timerRef.current) {
|
|
40
|
+
clearTimeout(timerRef.current);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}, [content, delayMs, save, provider, filePath]);
|
|
44
|
+
|
|
45
|
+
// Flush on unmount
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
return () => {
|
|
48
|
+
if (timerRef.current) {
|
|
49
|
+
clearTimeout(timerRef.current);
|
|
50
|
+
}
|
|
51
|
+
// Sync save on unmount is best-effort
|
|
52
|
+
if (provider && filePath && content !== lastSavedRef.current) {
|
|
53
|
+
provider.writeFile(filePath, content);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
57
|
+
}, []);
|
|
58
|
+
}
|
package/src/icons.tsx
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { SVGProps } from 'react';
|
|
2
|
+
|
|
3
|
+
const defaults: SVGProps<SVGSVGElement> = {
|
|
4
|
+
width: 16,
|
|
5
|
+
height: 16,
|
|
6
|
+
viewBox: '0 0 16 16',
|
|
7
|
+
fill: 'none',
|
|
8
|
+
stroke: 'currentColor',
|
|
9
|
+
strokeWidth: 1.5,
|
|
10
|
+
strokeLinecap: 'round' as const,
|
|
11
|
+
strokeLinejoin: 'round' as const,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function NewFileIcon(props: SVGProps<SVGSVGElement>) {
|
|
15
|
+
return (
|
|
16
|
+
<svg {...defaults} {...props}>
|
|
17
|
+
{/* Page outline */}
|
|
18
|
+
<path d="M9.5 1.5H4a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V5l-3.5-3.5Z" />
|
|
19
|
+
{/* Fold */}
|
|
20
|
+
<path d="M9.5 1.5V5H13" />
|
|
21
|
+
{/* Plus sign */}
|
|
22
|
+
<line x1="6.5" y1="10" x2="9.5" y2="10" />
|
|
23
|
+
<line x1="8" y1="8.5" x2="8" y2="11.5" />
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function NewFolderIcon(props: SVGProps<SVGSVGElement>) {
|
|
29
|
+
return (
|
|
30
|
+
<svg {...defaults} {...props}>
|
|
31
|
+
{/* Folder outline */}
|
|
32
|
+
<path d="M2 3.5a1 1 0 0 1 1-1h3l1.5 1.5H13a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5Z" />
|
|
33
|
+
{/* Plus sign */}
|
|
34
|
+
<line x1="6" y1="8.5" x2="10" y2="8.5" />
|
|
35
|
+
<line x1="8" y1="6.5" x2="8" y2="10.5" />
|
|
36
|
+
</svg>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function RefreshIcon(props: SVGProps<SVGSVGElement>) {
|
|
41
|
+
return (
|
|
42
|
+
<svg {...defaults} {...props}>
|
|
43
|
+
<path d="M13.5 8A5.5 5.5 0 1 1 8 2.5" />
|
|
44
|
+
<polyline points="13.5 3 13.5 6.5 10 6.5" />
|
|
45
|
+
</svg>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function WorkspaceIcon(props: SVGProps<SVGSVGElement>) {
|
|
50
|
+
return (
|
|
51
|
+
<svg {...defaults} {...props}>
|
|
52
|
+
{/* Desk surface (top-down rectangle) */}
|
|
53
|
+
<rect x="1.5" y="2.5" width="13" height="11" rx="1" />
|
|
54
|
+
{/* Blotter/pad with two vertical lines */}
|
|
55
|
+
<rect x="4" y="4.5" width="8" height="7" rx="0.5" />
|
|
56
|
+
<line x1="6.5" y1="5.5" x2="6.5" y2="10.5" strokeWidth="1" />
|
|
57
|
+
<line x1="9.5" y1="5.5" x2="9.5" y2="10.5" strokeWidth="1" />
|
|
58
|
+
</svg>
|
|
59
|
+
);
|
|
60
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @bendyline/docblocks-react — React components for DocBlocks
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// FileExplorer
|
|
6
|
+
export { FileExplorer } from './FileExplorer/index.js';
|
|
7
|
+
export type { FileExplorerProps } from './FileExplorer/index.js';
|
|
8
|
+
export { FileTreeNode } from './FileExplorer/index.js';
|
|
9
|
+
export type { FileTreeNodeProps } from './FileExplorer/index.js';
|
|
10
|
+
export { useFileTree } from './FileExplorer/index.js';
|
|
11
|
+
|
|
12
|
+
// WorkspacePicker
|
|
13
|
+
export { WorkspacePicker } from './WorkspacePicker/index.js';
|
|
14
|
+
export type { WorkspacePickerProps } from './WorkspacePicker/index.js';
|
|
15
|
+
|
|
16
|
+
// DocBlocksShell
|
|
17
|
+
export { DocBlocksShell } from './DocBlocksShell/index.js';
|
|
18
|
+
export type { DocBlocksShellProps } from './DocBlocksShell/index.js';
|
|
19
|
+
|
|
20
|
+
// AppMenu
|
|
21
|
+
export { AppMenu } from './AppMenu/index.js';
|
|
22
|
+
export type { AppMenuProps } from './AppMenu/index.js';
|
|
23
|
+
|
|
24
|
+
// Export
|
|
25
|
+
export { ExportToolbarControls } from './Export/index.js';
|
|
26
|
+
export type { ExportToolbarControlsProps, ExportFormat, ExportOptions } from './Export/index.js';
|
|
27
|
+
export { ExportDialog } from './Export/index.js';
|
|
28
|
+
export type { ExportDialogProps } from './Export/index.js';
|
|
29
|
+
|
|
30
|
+
// Hooks
|
|
31
|
+
export { useAutoSave } from './hooks/index.js';
|