@bendyline/docblocks-react 1.1.2 → 2.0.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 +31 -5
- package/dist/AppMenu/AppMenu.d.ts +29 -2
- package/dist/AppMenu/AppMenu.d.ts.map +1 -1
- package/dist/AppMenu/AppMenu.js +41 -2
- package/dist/AppMenu/AppMenu.js.map +1 -1
- package/dist/AppMenu/index.d.ts +1 -1
- package/dist/AppMenu/index.d.ts.map +1 -1
- package/dist/DocBlocksShell/DocBlocksShell.d.ts +15 -2
- package/dist/DocBlocksShell/DocBlocksShell.d.ts.map +1 -1
- package/dist/DocBlocksShell/DocBlocksShell.js +1677 -298
- package/dist/DocBlocksShell/DocBlocksShell.js.map +1 -1
- package/dist/DocBlocksShell/LazyEditorShell.d.ts +3 -0
- package/dist/DocBlocksShell/LazyEditorShell.d.ts.map +1 -0
- package/dist/DocBlocksShell/LazyEditorShell.js +3 -0
- package/dist/DocBlocksShell/LazyEditorShell.js.map +1 -0
- package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts +13 -0
- package/dist/DocBlocksShell/UpdateAvailableNotice.d.ts.map +1 -0
- package/dist/DocBlocksShell/UpdateAvailableNotice.js +16 -0
- package/dist/DocBlocksShell/UpdateAvailableNotice.js.map +1 -0
- package/dist/DocBlocksShell/document-title.d.ts +3 -0
- package/dist/DocBlocksShell/document-title.d.ts.map +1 -0
- package/dist/DocBlocksShell/document-title.js +17 -0
- package/dist/DocBlocksShell/document-title.js.map +1 -0
- package/dist/DocBlocksShell/workspace-authority-barrier.d.ts +14 -0
- package/dist/DocBlocksShell/workspace-authority-barrier.d.ts.map +1 -0
- package/dist/DocBlocksShell/workspace-authority-barrier.js +23 -0
- package/dist/DocBlocksShell/workspace-authority-barrier.js.map +1 -0
- package/dist/Export/DeferredExportToolbarControls.d.ts +5 -0
- package/dist/Export/DeferredExportToolbarControls.d.ts.map +1 -0
- package/dist/Export/DeferredExportToolbarControls.js +10 -0
- package/dist/Export/DeferredExportToolbarControls.js.map +1 -0
- package/dist/Export/ExportDialog.d.ts +10 -1
- package/dist/Export/ExportDialog.d.ts.map +1 -1
- package/dist/Export/ExportDialog.js +20 -18
- package/dist/Export/ExportDialog.js.map +1 -1
- package/dist/Export/ExportToolbarControls.d.ts +21 -1
- package/dist/Export/ExportToolbarControls.d.ts.map +1 -1
- package/dist/Export/ExportToolbarControls.js +96 -11
- package/dist/Export/ExportToolbarControls.js.map +1 -1
- package/dist/Export/export-destination.d.ts +3 -0
- package/dist/Export/export-destination.d.ts.map +1 -0
- package/dist/Export/export-destination.js +32 -0
- package/dist/Export/export-destination.js.map +1 -0
- package/dist/Export/index.d.ts +8 -4
- package/dist/Export/index.d.ts.map +1 -1
- package/dist/Export/index.js +4 -1
- package/dist/Export/index.js.map +1 -1
- package/dist/Export/public-api.d.ts +12 -0
- package/dist/Export/public-api.d.ts.map +1 -0
- package/dist/Export/public-api.js +9 -0
- package/dist/Export/public-api.js.map +1 -0
- package/dist/Export/run-export.d.ts +3 -1
- package/dist/Export/run-export.d.ts.map +1 -1
- package/dist/Export/run-export.js +30 -13
- package/dist/Export/run-export.js.map +1 -1
- package/dist/ExportDialog-MEUISWZX.js +9 -0
- package/dist/ExportDialog-MEUISWZX.js.map +1 -0
- package/dist/ExportToolbarControls-D2YDWOXW.js +373 -0
- package/dist/ExportToolbarControls-D2YDWOXW.js.map +1 -0
- package/dist/FileExplorer/FileExplorer.d.ts +26 -4
- package/dist/FileExplorer/FileExplorer.d.ts.map +1 -1
- package/dist/FileExplorer/FileExplorer.js +204 -29
- package/dist/FileExplorer/FileExplorer.js.map +1 -1
- package/dist/FileExplorer/FileTreeNode.d.ts +24 -3
- package/dist/FileExplorer/FileTreeNode.d.ts.map +1 -1
- package/dist/FileExplorer/FileTreeNode.js +27 -8
- package/dist/FileExplorer/FileTreeNode.js.map +1 -1
- package/dist/FileExplorer/index.d.ts +1 -1
- package/dist/FileExplorer/index.d.ts.map +1 -1
- package/dist/FileExplorer/useFileTree.d.ts +5 -3
- package/dist/FileExplorer/useFileTree.d.ts.map +1 -1
- package/dist/FileExplorer/useFileTree.js +173 -13
- package/dist/FileExplorer/useFileTree.js.map +1 -1
- package/dist/Git/GitAuthGuidanceDialog.d.ts +18 -0
- package/dist/Git/GitAuthGuidanceDialog.d.ts.map +1 -0
- package/dist/Git/GitAuthGuidanceDialog.js +27 -0
- package/dist/Git/GitAuthGuidanceDialog.js.map +1 -0
- package/dist/Git/GitBranchesDialog.d.ts +13 -0
- package/dist/Git/GitBranchesDialog.d.ts.map +1 -0
- package/dist/Git/GitBranchesDialog.js +59 -0
- package/dist/Git/GitBranchesDialog.js.map +1 -0
- package/dist/Git/GitCloneDialog.d.ts +14 -0
- package/dist/Git/GitCloneDialog.d.ts.map +1 -0
- package/dist/Git/GitCloneDialog.js +79 -0
- package/dist/Git/GitCloneDialog.js.map +1 -0
- package/dist/Git/GitCommitDialog.d.ts +12 -0
- package/dist/Git/GitCommitDialog.d.ts.map +1 -0
- package/dist/Git/GitCommitDialog.js +38 -0
- package/dist/Git/GitCommitDialog.js.map +1 -0
- package/dist/Git/GitConflictsDialog.d.ts +12 -0
- package/dist/Git/GitConflictsDialog.d.ts.map +1 -0
- package/dist/Git/GitConflictsDialog.js +17 -0
- package/dist/Git/GitConflictsDialog.js.map +1 -0
- package/dist/Git/GitContext.d.ts +89 -0
- package/dist/Git/GitContext.d.ts.map +1 -0
- package/dist/Git/GitContext.js +15 -0
- package/dist/Git/GitContext.js.map +1 -0
- package/dist/Git/GitDiffDialog.d.ts +20 -0
- package/dist/Git/GitDiffDialog.d.ts.map +1 -0
- package/dist/Git/GitDiffDialog.js +100 -0
- package/dist/Git/GitDiffDialog.js.map +1 -0
- package/dist/Git/GitDiffView.d.ts +23 -0
- package/dist/Git/GitDiffView.d.ts.map +1 -0
- package/dist/Git/GitDiffView.js +77 -0
- package/dist/Git/GitDiffView.js.map +1 -0
- package/dist/Git/GitHistoryDialog.d.ts +15 -0
- package/dist/Git/GitHistoryDialog.d.ts.map +1 -0
- package/dist/Git/GitHistoryDialog.js +107 -0
- package/dist/Git/GitHistoryDialog.js.map +1 -0
- package/dist/Git/GitStatusBar.d.ts +8 -0
- package/dist/Git/GitStatusBar.d.ts.map +1 -0
- package/dist/Git/GitStatusBar.js +49 -0
- package/dist/Git/GitStatusBar.js.map +1 -0
- package/dist/Git/GitToolbarControl.d.ts +15 -0
- package/dist/Git/GitToolbarControl.d.ts.map +1 -0
- package/dist/Git/GitToolbarControl.js +51 -0
- package/dist/Git/GitToolbarControl.js.map +1 -0
- package/dist/Git/GitUI.d.ts +14 -0
- package/dist/Git/GitUI.d.ts.map +1 -0
- package/dist/Git/GitUI.js +21 -0
- package/dist/Git/GitUI.js.map +1 -0
- package/dist/Git/commit-selection.d.ts +22 -0
- package/dist/Git/commit-selection.d.ts.map +1 -0
- package/dist/Git/commit-selection.js +47 -0
- package/dist/Git/commit-selection.js.map +1 -0
- package/dist/Git/git-clone-utils.d.ts +8 -0
- package/dist/Git/git-clone-utils.d.ts.map +1 -0
- package/dist/Git/git-clone-utils.js +26 -0
- package/dist/Git/git-clone-utils.js.map +1 -0
- package/dist/Git/git-status.d.ts +24 -0
- package/dist/Git/git-status.d.ts.map +1 -0
- package/dist/Git/git-status.js +105 -0
- package/dist/Git/git-status.js.map +1 -0
- package/dist/Git/useGit.d.ts +15 -0
- package/dist/Git/useGit.d.ts.map +1 -0
- package/dist/Git/useGit.js +206 -0
- package/dist/Git/useGit.js.map +1 -0
- package/dist/Git/useGitStatus.d.ts +17 -0
- package/dist/Git/useGitStatus.d.ts.map +1 -0
- package/dist/Git/useGitStatus.js +63 -0
- package/dist/Git/useGitStatus.js.map +1 -0
- package/dist/GitToolbarControl-LMIR4R7I.js +117 -0
- package/dist/GitToolbarControl-LMIR4R7I.js.map +1 -0
- package/dist/GitUI-KGF5MSNV.js +1048 -0
- package/dist/GitUI-KGF5MSNV.js.map +1 -0
- package/dist/LazyEditorShell-EF2BWRXU.js +6 -0
- package/dist/LazyEditorShell-EF2BWRXU.js.map +1 -0
- package/dist/Settings/Settings.d.ts +23 -0
- package/dist/Settings/Settings.d.ts.map +1 -0
- package/dist/Settings/Settings.js +22 -0
- package/dist/Settings/Settings.js.map +1 -0
- package/dist/Settings/public-api.d.ts +3 -0
- package/dist/Settings/public-api.d.ts.map +1 -0
- package/dist/Settings/public-api.js +2 -0
- package/dist/Settings/public-api.js.map +1 -0
- package/dist/WorkspacePicker/WorkspacePicker.d.ts +6 -1
- package/dist/WorkspacePicker/WorkspacePicker.d.ts.map +1 -1
- package/dist/WorkspacePicker/WorkspacePicker.js +16 -5
- package/dist/WorkspacePicker/WorkspacePicker.js.map +1 -1
- package/dist/chunk-3SAXDU2U.js +157 -0
- package/dist/chunk-3SAXDU2U.js.map +1 -0
- package/dist/chunk-4XXSWN3T.js +13 -0
- package/dist/chunk-4XXSWN3T.js.map +1 -0
- package/dist/chunk-5A4KEWKT.js +97 -0
- package/dist/chunk-5A4KEWKT.js.map +1 -0
- package/dist/chunk-AOVTHZU7.js +321 -0
- package/dist/chunk-AOVTHZU7.js.map +1 -0
- package/dist/chunk-DD4VFJQI.js +51 -0
- package/dist/chunk-DD4VFJQI.js.map +1 -0
- package/dist/chunk-GSNZSCIK.js +55 -0
- package/dist/chunk-GSNZSCIK.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/components/Dialog.d.ts +22 -0
- package/dist/components/Dialog.d.ts.map +1 -0
- package/dist/components/Dialog.js +33 -0
- package/dist/components/Dialog.js.map +1 -0
- package/dist/editor.d.ts +10 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +70 -0
- package/dist/editor.js.map +1 -0
- package/dist/export/index.d.ts +87 -0
- package/dist/export/index.js +26 -0
- package/dist/export/index.js.map +1 -0
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useDocumentSession.d.ts +16 -0
- package/dist/hooks/useDocumentSession.d.ts.map +1 -0
- package/dist/hooks/useDocumentSession.js +18 -0
- package/dist/hooks/useDocumentSession.js.map +1 -0
- package/dist/icons.d.ts +11 -6
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +21 -20
- package/dist/icons.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/preferences/theme.d.ts +18 -0
- package/dist/preferences/theme.d.ts.map +1 -0
- package/dist/preferences/theme.js +63 -0
- package/dist/preferences/theme.js.map +1 -0
- package/dist/provider-lease.d.ts +10 -0
- package/dist/provider-lease.d.ts.map +1 -0
- package/dist/provider-lease.js +42 -0
- package/dist/provider-lease.js.map +1 -0
- package/dist/run-export-ICTZITXC.js +10 -0
- package/dist/run-export-ICTZITXC.js.map +1 -0
- package/dist/settings/index.d.ts +28 -0
- package/dist/settings/index.js +12 -0
- package/dist/settings/index.js.map +1 -0
- package/package.json +24 -9
- package/src/AppMenu/AppMenu.tsx +169 -99
- package/src/AppMenu/index.ts +1 -1
- package/src/DocBlocksShell/DocBlocksShell.tsx +2157 -537
- package/src/DocBlocksShell/LazyEditorShell.ts +2 -0
- package/src/DocBlocksShell/UpdateAvailableNotice.tsx +60 -0
- package/src/DocBlocksShell/document-title.ts +19 -0
- package/src/DocBlocksShell/workspace-authority-barrier.ts +26 -0
- package/src/Export/DeferredExportToolbarControls.tsx +23 -0
- package/src/Export/ExportDialog.tsx +74 -20
- package/src/Export/ExportToolbarControls.tsx +238 -40
- package/src/Export/export-destination.ts +30 -0
- package/src/Export/index.ts +18 -4
- package/src/Export/public-api.ts +17 -0
- package/src/Export/run-export.ts +36 -11
- package/src/FileExplorer/FileExplorer.tsx +284 -38
- package/src/FileExplorer/FileTreeNode.tsx +100 -8
- package/src/FileExplorer/index.ts +1 -1
- package/src/FileExplorer/useFileTree.ts +190 -16
- package/src/Git/GitAuthGuidanceDialog.tsx +84 -0
- package/src/Git/GitBranchesDialog.tsx +144 -0
- package/src/Git/GitCloneDialog.tsx +200 -0
- package/src/Git/GitCommitDialog.tsx +119 -0
- package/src/Git/GitConflictsDialog.tsx +62 -0
- package/src/Git/GitContext.tsx +88 -0
- package/src/Git/GitDiffDialog.tsx +147 -0
- package/src/Git/GitDiffView.tsx +105 -0
- package/src/Git/GitHistoryDialog.tsx +195 -0
- package/src/Git/GitStatusBar.tsx +157 -0
- package/src/Git/GitToolbarControl.tsx +123 -0
- package/src/Git/GitUI.tsx +68 -0
- package/src/Git/commit-selection.ts +63 -0
- package/src/Git/git-clone-utils.ts +23 -0
- package/src/Git/git-status.ts +113 -0
- package/src/Git/useGit.ts +279 -0
- package/src/Git/useGitStatus.ts +78 -0
- package/src/Settings/Settings.tsx +118 -0
- package/src/Settings/public-api.ts +8 -0
- package/src/WorkspacePicker/WorkspacePicker.tsx +62 -8
- package/src/components/Dialog.tsx +81 -0
- package/src/editor.ts +72 -0
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useDocumentSession.ts +37 -0
- package/src/icons.tsx +33 -55
- package/src/index.ts +35 -5
- package/src/preferences/theme.ts +67 -0
- package/src/provider-lease.ts +52 -0
- package/src/styles/docblocks.css +2174 -79
- package/src/types/pwa-dom.d.ts +31 -0
- 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/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/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/useAutoSave.ts +0 -116
- package/src/monaco-slim.ts +0 -20
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useGitStatus — subscribes to the host's owner-scoped repository stream.
|
|
3
|
+
*
|
|
4
|
+
* Dedupes identical payloads so a permanently-dirty working tree (normal
|
|
5
|
+
* under the manual-commit model) doesn't repaint the tree on every push
|
|
6
|
+
* from the main process.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
10
|
+
import type { DocBlocksHostGitAPI, GitStatus } from '@bendyline/docblocks/host';
|
|
11
|
+
|
|
12
|
+
const SCHEDULE_REFRESH_MS = 1500;
|
|
13
|
+
|
|
14
|
+
function statusKey(status: GitStatus): string {
|
|
15
|
+
return JSON.stringify(status);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface UseGitStatusResult {
|
|
19
|
+
status: GitStatus | null;
|
|
20
|
+
/** Fetch a fresh status immediately (after a renderer-initiated git op). */
|
|
21
|
+
refresh: () => void;
|
|
22
|
+
/** Trailing-debounced refresh (after autosave writes). */
|
|
23
|
+
scheduleRefresh: () => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function useGitStatus(
|
|
27
|
+
gitApi: DocBlocksHostGitAPI | null,
|
|
28
|
+
repositoryId: string | null,
|
|
29
|
+
enabled: boolean,
|
|
30
|
+
): UseGitStatusResult {
|
|
31
|
+
const [status, setStatus] = useState<GitStatus | null>(null);
|
|
32
|
+
const lastKeyRef = useRef<string | null>(null);
|
|
33
|
+
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
34
|
+
|
|
35
|
+
const apply = useCallback((next: GitStatus) => {
|
|
36
|
+
const key = statusKey(next);
|
|
37
|
+
if (key === lastKeyRef.current) return;
|
|
38
|
+
lastKeyRef.current = key;
|
|
39
|
+
setStatus(next);
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
lastKeyRef.current = null;
|
|
44
|
+
setStatus(null);
|
|
45
|
+
if (!gitApi || !repositoryId || !enabled) return;
|
|
46
|
+
let cancelled = false;
|
|
47
|
+
const unsubscribe = gitApi.onStatusChanged(repositoryId, (next) => {
|
|
48
|
+
if (!cancelled) apply(next);
|
|
49
|
+
});
|
|
50
|
+
return () => {
|
|
51
|
+
cancelled = true;
|
|
52
|
+
unsubscribe();
|
|
53
|
+
};
|
|
54
|
+
}, [gitApi, repositoryId, enabled, apply]);
|
|
55
|
+
|
|
56
|
+
const refresh = useCallback(() => {
|
|
57
|
+
if (!gitApi || !repositoryId || !enabled) return;
|
|
58
|
+
void gitApi.status(repositoryId).then((result) => {
|
|
59
|
+
if (result.ok) apply(result.value);
|
|
60
|
+
});
|
|
61
|
+
}, [gitApi, repositoryId, enabled, apply]);
|
|
62
|
+
|
|
63
|
+
const scheduleRefresh = useCallback(() => {
|
|
64
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
65
|
+
timerRef.current = setTimeout(() => {
|
|
66
|
+
timerRef.current = null;
|
|
67
|
+
refresh();
|
|
68
|
+
}, SCHEDULE_REFRESH_MS);
|
|
69
|
+
}, [refresh]);
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
return () => {
|
|
73
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
74
|
+
};
|
|
75
|
+
}, []);
|
|
76
|
+
|
|
77
|
+
return { status, refresh, scheduleRefresh };
|
|
78
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/** Shared controls used by the app and host-specific DocBlocks settings dialogs. */
|
|
2
|
+
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
import { Dialog } from '../components/Dialog.js';
|
|
5
|
+
import { ACCENT_COLORS, type AccentColor, type ThemePreference } from '../preferences/theme.js';
|
|
6
|
+
|
|
7
|
+
export type { AccentColor, ThemePreference } from '../preferences/theme.js';
|
|
8
|
+
|
|
9
|
+
const ACCENT_LABELS: Record<AccentColor, string> = {
|
|
10
|
+
brown: 'Brown',
|
|
11
|
+
green: 'Green',
|
|
12
|
+
blue: 'Blue',
|
|
13
|
+
purple: 'Purple',
|
|
14
|
+
maroon: 'Maroon',
|
|
15
|
+
orange: 'Orange',
|
|
16
|
+
gray: 'Gray',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export interface SettingsDialogProps {
|
|
20
|
+
title?: string;
|
|
21
|
+
onClose: () => void;
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function SettingsDialog({ title = 'Settings', onClose, children }: SettingsDialogProps) {
|
|
26
|
+
return (
|
|
27
|
+
<Dialog title={title} onClose={onClose}>
|
|
28
|
+
{children}
|
|
29
|
+
</Dialog>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ThemeSettingsProps {
|
|
34
|
+
value: ThemePreference;
|
|
35
|
+
onChange: (theme: ThemePreference) => void;
|
|
36
|
+
name?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function ThemeSettings({ value, onChange, name = 'theme' }: ThemeSettingsProps) {
|
|
40
|
+
return (
|
|
41
|
+
<fieldset className="db-settings-fieldset">
|
|
42
|
+
<legend className="db-settings-legend">Theme</legend>
|
|
43
|
+
<label className="db-settings-radio">
|
|
44
|
+
<input
|
|
45
|
+
type="radio"
|
|
46
|
+
name={name}
|
|
47
|
+
value="auto"
|
|
48
|
+
checked={value === 'auto'}
|
|
49
|
+
onChange={() => onChange('auto')}
|
|
50
|
+
/>
|
|
51
|
+
System default
|
|
52
|
+
</label>
|
|
53
|
+
<label className="db-settings-radio">
|
|
54
|
+
<input
|
|
55
|
+
type="radio"
|
|
56
|
+
name={name}
|
|
57
|
+
value="light"
|
|
58
|
+
checked={value === 'light'}
|
|
59
|
+
onChange={() => onChange('light')}
|
|
60
|
+
/>
|
|
61
|
+
Light
|
|
62
|
+
</label>
|
|
63
|
+
<label className="db-settings-radio">
|
|
64
|
+
<input
|
|
65
|
+
type="radio"
|
|
66
|
+
name={name}
|
|
67
|
+
value="dark"
|
|
68
|
+
checked={value === 'dark'}
|
|
69
|
+
onChange={() => onChange('dark')}
|
|
70
|
+
/>
|
|
71
|
+
Dark
|
|
72
|
+
</label>
|
|
73
|
+
</fieldset>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface AccentColorSettingsProps {
|
|
78
|
+
value: AccentColor;
|
|
79
|
+
onChange: (color: AccentColor) => void;
|
|
80
|
+
name?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function AccentColorSettings({
|
|
84
|
+
value,
|
|
85
|
+
onChange,
|
|
86
|
+
name = 'accent-color',
|
|
87
|
+
}: AccentColorSettingsProps) {
|
|
88
|
+
return (
|
|
89
|
+
<fieldset className="db-settings-fieldset">
|
|
90
|
+
<legend className="db-settings-legend">Accent color</legend>
|
|
91
|
+
<p className="db-settings-hint">Used in both light and dark appearances.</p>
|
|
92
|
+
<div className="db-settings-accent-grid">
|
|
93
|
+
{ACCENT_COLORS.map((color) => (
|
|
94
|
+
<label
|
|
95
|
+
className={`db-settings-accent${
|
|
96
|
+
value === color ? ' db-settings-accent--selected' : ''
|
|
97
|
+
}`}
|
|
98
|
+
key={color}
|
|
99
|
+
>
|
|
100
|
+
<input
|
|
101
|
+
className="db-settings-accent-input"
|
|
102
|
+
type="radio"
|
|
103
|
+
name={name}
|
|
104
|
+
value={color}
|
|
105
|
+
checked={value === color}
|
|
106
|
+
onChange={() => onChange(color)}
|
|
107
|
+
/>
|
|
108
|
+
<span
|
|
109
|
+
className={`db-settings-accent-swatch db-settings-accent-swatch--${color}`}
|
|
110
|
+
aria-hidden="true"
|
|
111
|
+
/>
|
|
112
|
+
<span>{ACCENT_LABELS[color]}</span>
|
|
113
|
+
</label>
|
|
114
|
+
))}
|
|
115
|
+
</div>
|
|
116
|
+
</fieldset>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -3,11 +3,18 @@
|
|
|
3
3
|
* (IndexedDB-based or native folder via File System Access API).
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
6
|
+
import { Fragment, useState, useEffect, useCallback, useRef } from 'react';
|
|
7
7
|
import type { WorkspaceDescriptor } from '@bendyline/docblocks/workspace';
|
|
8
8
|
import { listWorkspaces, saveWorkspace, touchWorkspace } from '@bendyline/docblocks/workspace';
|
|
9
|
-
import { isNativeFileSystemSupported } from '@bendyline/docblocks/filesystem';
|
|
10
9
|
import { isElectronHost } from '@bendyline/docblocks/host';
|
|
10
|
+
import { FolderIcon, NewFolderIcon } from '../icons.js';
|
|
11
|
+
|
|
12
|
+
function isNativeFileSystemSupported(): boolean {
|
|
13
|
+
return (
|
|
14
|
+
typeof globalThis !== 'undefined' &&
|
|
15
|
+
typeof (globalThis as { showDirectoryPicker?: unknown }).showDirectoryPicker === 'function'
|
|
16
|
+
);
|
|
17
|
+
}
|
|
11
18
|
|
|
12
19
|
export interface WorkspacePickerProps {
|
|
13
20
|
/** Currently active workspace id. */
|
|
@@ -16,14 +23,29 @@ export interface WorkspacePickerProps {
|
|
|
16
23
|
onSelect: (descriptor: WorkspaceDescriptor) => void;
|
|
17
24
|
/** Called when the user chooses "Open Folder" (native FS). */
|
|
18
25
|
onOpenFolder: () => void;
|
|
26
|
+
/**
|
|
27
|
+
* Called when the user chooses "Clone Git repository". Only provided on
|
|
28
|
+
* the desktop when git is available — omitted, the item is hidden.
|
|
29
|
+
*/
|
|
30
|
+
onCloneRepository?: () => void;
|
|
19
31
|
/** Optional className. */
|
|
20
32
|
className?: string;
|
|
21
33
|
}
|
|
22
34
|
|
|
35
|
+
function WorkspacePath({ path }: { path: string }) {
|
|
36
|
+
return path.split(/([\\/])/).map((segment, index) => (
|
|
37
|
+
<Fragment key={index}>
|
|
38
|
+
{segment}
|
|
39
|
+
{(segment === '\\' || segment === '/') && <wbr />}
|
|
40
|
+
</Fragment>
|
|
41
|
+
));
|
|
42
|
+
}
|
|
43
|
+
|
|
23
44
|
export function WorkspacePicker({
|
|
24
45
|
activeWorkspaceId,
|
|
25
46
|
onSelect,
|
|
26
47
|
onOpenFolder,
|
|
48
|
+
onCloneRepository,
|
|
27
49
|
className,
|
|
28
50
|
}: WorkspacePickerProps) {
|
|
29
51
|
const [workspaces, setWorkspaces] = useState<WorkspaceDescriptor[]>([]);
|
|
@@ -82,6 +104,7 @@ export function WorkspacePicker({
|
|
|
82
104
|
}, [workspaces.length, onSelect, refresh]);
|
|
83
105
|
|
|
84
106
|
const activeWs = workspaces.find((w) => w.id === activeWorkspaceId);
|
|
107
|
+
const activeWorkspaceName = activeWs?.name ?? 'No workspace';
|
|
85
108
|
|
|
86
109
|
return (
|
|
87
110
|
<div ref={pickerRef} className={`db-workspace-picker ${className ?? ''}`}>
|
|
@@ -89,9 +112,16 @@ export function WorkspacePicker({
|
|
|
89
112
|
className="db-workspace-picker-btn"
|
|
90
113
|
onClick={() => setIsOpen(!isOpen)}
|
|
91
114
|
title="Switch workspace"
|
|
115
|
+
aria-label={`Switch workspace, current: ${activeWorkspaceName}`}
|
|
92
116
|
>
|
|
93
|
-
|
|
94
|
-
<span className="db-workspace-picker-
|
|
117
|
+
<span className="db-workspace-picker-label">{activeWorkspaceName}</span>
|
|
118
|
+
<span className="db-workspace-picker-compact-icon">
|
|
119
|
+
<FolderIcon />
|
|
120
|
+
</span>
|
|
121
|
+
<span
|
|
122
|
+
className={`db-workspace-picker-caret${isOpen ? ' db-workspace-picker-caret--open' : ''}`}
|
|
123
|
+
aria-hidden="true"
|
|
124
|
+
/>
|
|
95
125
|
</button>
|
|
96
126
|
|
|
97
127
|
{isOpen && (
|
|
@@ -104,9 +134,18 @@ export function WorkspacePicker({
|
|
|
104
134
|
}`}
|
|
105
135
|
onClick={() => handleSelect(ws)}
|
|
106
136
|
>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
137
|
+
<span className="db-workspace-details">
|
|
138
|
+
<span className="db-workspace-heading">
|
|
139
|
+
<span>{ws.name}</span>
|
|
140
|
+
{(ws.type === 'native' || ws.type === 'electron-native') && (
|
|
141
|
+
<span className="db-workspace-type">(folder)</span>
|
|
142
|
+
)}
|
|
143
|
+
</span>
|
|
144
|
+
{ws.rootPath && (
|
|
145
|
+
<span className="db-workspace-path" title={ws.rootPath}>
|
|
146
|
+
<WorkspacePath path={ws.rootPath} />
|
|
147
|
+
</span>
|
|
148
|
+
)}
|
|
110
149
|
</span>
|
|
111
150
|
</button>
|
|
112
151
|
))}
|
|
@@ -115,7 +154,10 @@ export function WorkspacePicker({
|
|
|
115
154
|
|
|
116
155
|
{!electron && (
|
|
117
156
|
<button className="db-workspace-dropdown-item" onClick={handleCreateNew}>
|
|
118
|
-
|
|
157
|
+
<span className="db-workspace-dropdown-action-label">
|
|
158
|
+
<NewFolderIcon />
|
|
159
|
+
<span>New Workspace</span>
|
|
160
|
+
</span>
|
|
119
161
|
</button>
|
|
120
162
|
)}
|
|
121
163
|
|
|
@@ -130,6 +172,18 @@ export function WorkspacePicker({
|
|
|
130
172
|
Open Folder...
|
|
131
173
|
</button>
|
|
132
174
|
)}
|
|
175
|
+
|
|
176
|
+
{onCloneRepository && (
|
|
177
|
+
<button
|
|
178
|
+
className="db-workspace-dropdown-item"
|
|
179
|
+
onClick={() => {
|
|
180
|
+
setIsOpen(false);
|
|
181
|
+
onCloneRepository();
|
|
182
|
+
}}
|
|
183
|
+
>
|
|
184
|
+
Clone Git Repository...
|
|
185
|
+
</button>
|
|
186
|
+
)}
|
|
133
187
|
</div>
|
|
134
188
|
)}
|
|
135
189
|
</div>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dialog — shared modal primitive.
|
|
3
|
+
*
|
|
4
|
+
* Promotes the `db-dialog-overlay` / `db-dialog` pattern used by the
|
|
5
|
+
* settings dialogs into a reusable component, adding aria-modal and
|
|
6
|
+
* initial focus. Escape and (by default) backdrop clicks close it.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
10
|
+
|
|
11
|
+
export interface DialogProps {
|
|
12
|
+
title: string;
|
|
13
|
+
onClose: () => void;
|
|
14
|
+
/** default 380px / wide 560px / full min(1100px, 94vw) column. */
|
|
15
|
+
size?: 'default' | 'wide' | 'full';
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
/** Right-aligned action row below the body. */
|
|
18
|
+
footer?: React.ReactNode;
|
|
19
|
+
/** Element to focus on open; defaults to the close button. */
|
|
20
|
+
initialFocusRef?: React.RefObject<HTMLElement | null>;
|
|
21
|
+
/** Set false when a stray backdrop click would lose user input. */
|
|
22
|
+
closeOnBackdrop?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function Dialog({
|
|
26
|
+
title,
|
|
27
|
+
onClose,
|
|
28
|
+
size = 'default',
|
|
29
|
+
children,
|
|
30
|
+
footer,
|
|
31
|
+
initialFocusRef,
|
|
32
|
+
closeOnBackdrop = true,
|
|
33
|
+
}: DialogProps) {
|
|
34
|
+
const closeButtonRef = useRef<HTMLButtonElement>(null);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const onKey = (e: KeyboardEvent) => {
|
|
38
|
+
if (e.key === 'Escape') onClose();
|
|
39
|
+
};
|
|
40
|
+
window.addEventListener('keydown', onKey);
|
|
41
|
+
return () => window.removeEventListener('keydown', onKey);
|
|
42
|
+
}, [onClose]);
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const target = initialFocusRef?.current ?? closeButtonRef.current;
|
|
46
|
+
target?.focus();
|
|
47
|
+
// Focus only on mount — refocusing on every re-render would fight the user.
|
|
48
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
const handleBackdropClick = useCallback(
|
|
52
|
+
(e: React.MouseEvent) => {
|
|
53
|
+
if (closeOnBackdrop && e.target === e.currentTarget) onClose();
|
|
54
|
+
},
|
|
55
|
+
[closeOnBackdrop, onClose],
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const sizeClass =
|
|
59
|
+
size === 'wide' ? ' db-dialog--wide' : size === 'full' ? ' db-dialog--full' : '';
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="db-dialog-overlay" onClick={handleBackdropClick}>
|
|
63
|
+
<div className={`db-dialog${sizeClass}`} role="dialog" aria-modal="true" aria-label={title}>
|
|
64
|
+
<div className="db-dialog-header">
|
|
65
|
+
<h2 className="db-dialog-title">{title}</h2>
|
|
66
|
+
<button
|
|
67
|
+
ref={closeButtonRef}
|
|
68
|
+
type="button"
|
|
69
|
+
className="db-dialog-close"
|
|
70
|
+
onClick={onClose}
|
|
71
|
+
aria-label="Close"
|
|
72
|
+
>
|
|
73
|
+
×
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
<div className="db-dialog-body">{children}</div>
|
|
77
|
+
{footer && <div className="db-dialog-footer">{footer}</div>}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
package/src/editor.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placeholder prompts shown by DocBlocks when a Markdown document is empty.
|
|
3
|
+
* Hosts pick one prompt for each mounted document generation and pass it to
|
|
4
|
+
* Squisq, so the copy remains stable while that document is open.
|
|
5
|
+
*/
|
|
6
|
+
export const EMPTY_DOCUMENT_PROMPTS = [
|
|
7
|
+
'Start typing your content, or drop images on top of me...',
|
|
8
|
+
'Write anything -- paste markdown, drag in images, or just start typing...',
|
|
9
|
+
'Type away. Markdown syntax works too...',
|
|
10
|
+
'Chapter 1 begins here...',
|
|
11
|
+
'Once upon a time...',
|
|
12
|
+
"A blank page. Exciting, isn't it?",
|
|
13
|
+
'The first word is always the hardest...',
|
|
14
|
+
'Plot twist: this is where it all starts...',
|
|
15
|
+
'Write something the future you will thank you for...',
|
|
16
|
+
'Begin at the beginning...',
|
|
17
|
+
"Let's begin.",
|
|
18
|
+
'We can be heroes...',
|
|
19
|
+
'Here comes the sun...',
|
|
20
|
+
'And so it begins...',
|
|
21
|
+
'Let it be, let it be...',
|
|
22
|
+
"Don't stop believing...",
|
|
23
|
+
'Started from the bottom...',
|
|
24
|
+
'This is the start of something new...',
|
|
25
|
+
'Ground control to Major Tom...',
|
|
26
|
+
'Come as you are...',
|
|
27
|
+
'Every new beginning...',
|
|
28
|
+
"Hello, is it me you're looking for?",
|
|
29
|
+
'Imagine all the people...',
|
|
30
|
+
'Anything you want, you got it...',
|
|
31
|
+
'Rise above...',
|
|
32
|
+
'Do you have the time...',
|
|
33
|
+
'Here we are now, entertain us...',
|
|
34
|
+
'All the small things...',
|
|
35
|
+
'Should I stay or should I go?',
|
|
36
|
+
'I am a patient boy -- I wait, I wait, I wait...',
|
|
37
|
+
'Destination unknown...',
|
|
38
|
+
'Easy like Sunday morning...',
|
|
39
|
+
'Dance, dance, dance to the radio...',
|
|
40
|
+
'New day rising...',
|
|
41
|
+
'Visit the world...',
|
|
42
|
+
'Positive mental attitude...',
|
|
43
|
+
'Better I sing than I cry...',
|
|
44
|
+
'Disconnect for a minute...',
|
|
45
|
+
'We need new noise...',
|
|
46
|
+
'Shoot the moon...',
|
|
47
|
+
"I'll surprise you sometime -- I'll come around...",
|
|
48
|
+
'Coming out of my cage, and doing just fine...',
|
|
49
|
+
"Throw me to the wolves -- I'll come back, leading the pack...",
|
|
50
|
+
'There comes a time -- no excuses...',
|
|
51
|
+
"It's up to me now, turn on the bright lights...",
|
|
52
|
+
'Do what you want...',
|
|
53
|
+
'Fingers crossed...',
|
|
54
|
+
'This is the start of how it all ends...',
|
|
55
|
+
'It has to start somewhere, it has to start sometime -- what better place than here? what better time than now?',
|
|
56
|
+
"I know myself, and I'll begin again...",
|
|
57
|
+
'Dig me out, dig me in...',
|
|
58
|
+
"Everybody's full of sugar, honey, ice and tea...",
|
|
59
|
+
"Take time with a wounded hand, 'cause it likes to heal...",
|
|
60
|
+
'Grab a brush and put on a little makeup...',
|
|
61
|
+
'Amber is the color of your energy...',
|
|
62
|
+
"Wait -- they don't love it like I love it...",
|
|
63
|
+
"A world's been buried, where love is the law; a you-topia...",
|
|
64
|
+
] as const;
|
|
65
|
+
|
|
66
|
+
export type EmptyDocumentPrompt = (typeof EMPTY_DOCUMENT_PROMPTS)[number];
|
|
67
|
+
|
|
68
|
+
/** Pick a prompt using the supplied random source, or `Math.random`. */
|
|
69
|
+
export function pickEmptyDocumentPrompt(random: () => number = Math.random): EmptyDocumentPrompt {
|
|
70
|
+
const index = Math.floor(random() * EMPTY_DOCUMENT_PROMPTS.length);
|
|
71
|
+
return EMPTY_DOCUMENT_PROMPTS[index] ?? EMPTY_DOCUMENT_PROMPTS[0];
|
|
72
|
+
}
|
package/src/hooks/index.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { useDocumentSession } from './useDocumentSession.js';
|
|
2
|
+
export type { UseDocumentSessionResult } from './useDocumentSession.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useState, useSyncExternalStore } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
DocumentRecoveryJournal,
|
|
4
|
+
DocumentSession,
|
|
5
|
+
getDefaultDocumentRecoveryStorage,
|
|
6
|
+
type DocumentSessionSnapshot,
|
|
7
|
+
} from '@bendyline/docblocks/document';
|
|
8
|
+
|
|
9
|
+
export interface UseDocumentSessionResult {
|
|
10
|
+
/** Stable controller for the lifetime of the mounted shell/panel. */
|
|
11
|
+
session: DocumentSession;
|
|
12
|
+
/** React snapshot of dirty/saving/saved/error/conflict state. */
|
|
13
|
+
snapshot: DocumentSessionSnapshot;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* React binding for the framework-neutral DocumentSession engine.
|
|
18
|
+
*
|
|
19
|
+
* The hook deliberately does not infer target transitions from props.
|
|
20
|
+
* Callers must use transitionTo(), retarget(), or delete() before changing
|
|
21
|
+
* their view state so persistence ordering remains explicit.
|
|
22
|
+
*/
|
|
23
|
+
export function useDocumentSession(autoSaveDelayMs = 500): UseDocumentSessionResult {
|
|
24
|
+
const [session] = useState(
|
|
25
|
+
() =>
|
|
26
|
+
new DocumentSession({
|
|
27
|
+
autoSaveDelayMs,
|
|
28
|
+
recoveryJournal: new DocumentRecoveryJournal(getDefaultDocumentRecoveryStorage()),
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
const snapshot = useSyncExternalStore(
|
|
32
|
+
session.subscribe,
|
|
33
|
+
session.getSnapshot,
|
|
34
|
+
session.getSnapshot,
|
|
35
|
+
);
|
|
36
|
+
return { session, snapshot };
|
|
37
|
+
}
|
package/src/icons.tsx
CHANGED
|
@@ -1,70 +1,48 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* DocBlocks shell icons use the Font Awesome Free webfont bundled by
|
|
3
|
+
* `@bendyline/squisq-editor-react/styles`. Controls provide the accessible
|
|
4
|
+
* name, so the glyphs themselves stay decorative.
|
|
5
|
+
*/
|
|
2
6
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
};
|
|
7
|
+
function FontAwesomeIcon({ icon }: { icon: string }) {
|
|
8
|
+
return <i className={icon} aria-hidden="true" />;
|
|
9
|
+
}
|
|
13
10
|
|
|
14
|
-
export function NewFileIcon(
|
|
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
|
-
);
|
|
11
|
+
export function NewFileIcon() {
|
|
12
|
+
return <FontAwesomeIcon icon="fa-solid fa-file-circle-plus" />;
|
|
26
13
|
}
|
|
27
14
|
|
|
28
|
-
export function NewFolderIcon(
|
|
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
|
-
);
|
|
15
|
+
export function NewFolderIcon() {
|
|
16
|
+
return <FontAwesomeIcon icon="fa-solid fa-folder-plus" />;
|
|
38
17
|
}
|
|
39
18
|
|
|
40
|
-
export function
|
|
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
|
-
);
|
|
19
|
+
export function FolderIcon() {
|
|
20
|
+
return <FontAwesomeIcon icon="fa-solid fa-folder" />;
|
|
47
21
|
}
|
|
48
22
|
|
|
49
|
-
export function MoreIcon(
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
</svg>
|
|
56
|
-
);
|
|
23
|
+
export function MoreIcon() {
|
|
24
|
+
return <FontAwesomeIcon icon="fa-solid fa-ellipsis" />;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function WorkspaceIcon() {
|
|
28
|
+
return <FontAwesomeIcon icon="fa-solid fa-gear" />;
|
|
57
29
|
}
|
|
58
30
|
|
|
59
|
-
export function
|
|
31
|
+
export function SplitViewIcon() {
|
|
60
32
|
return (
|
|
61
|
-
<svg
|
|
62
|
-
|
|
33
|
+
<svg
|
|
34
|
+
width="16"
|
|
35
|
+
height="16"
|
|
36
|
+
viewBox="0 0 16 16"
|
|
37
|
+
fill="none"
|
|
38
|
+
stroke="currentColor"
|
|
39
|
+
strokeWidth="1.5"
|
|
40
|
+
strokeLinecap="round"
|
|
41
|
+
strokeLinejoin="round"
|
|
42
|
+
aria-hidden="true"
|
|
43
|
+
>
|
|
63
44
|
<rect x="1.5" y="2.5" width="13" height="11" rx="1" />
|
|
64
|
-
|
|
65
|
-
<rect x="4" y="4.5" width="8" height="7" rx="0.5" />
|
|
66
|
-
<line x1="6.5" y1="5.5" x2="6.5" y2="10.5" strokeWidth="1" />
|
|
67
|
-
<line x1="9.5" y1="5.5" x2="9.5" y2="10.5" strokeWidth="1" />
|
|
45
|
+
<line x1="6" y1="2.5" x2="6" y2="13.5" />
|
|
68
46
|
</svg>
|
|
69
47
|
);
|
|
70
48
|
}
|