@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Git/GitStatusBar.tsx","../src/Git/GitCommitDialog.tsx","../src/Git/commit-selection.ts","../src/Git/GitBranchesDialog.tsx","../src/Git/GitHistoryDialog.tsx","../src/Git/GitDiffDialog.tsx","../src/Git/GitDiffView.tsx","../src/Git/GitCloneDialog.tsx","../src/Git/git-clone-utils.ts","../src/Git/GitAuthGuidanceDialog.tsx","../src/Git/GitConflictsDialog.tsx","../src/Git/GitUI.tsx"],"sourcesContent":["/**\n * GitStatusBar — slim sidebar row showing branch, ahead/behind, and dirty\n * count, with the repo actions menu (commit, sync, branches, history,\n * remote conveniences). Renders nothing unless the active workspace is a\n * git repository.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useGitContext } from './GitContext.js';\nimport { formatAheadBehind, summarizeDirty } from './git-status.js';\nimport { useMenuKeyboard } from './useMenuKeyboard.js';\n\nexport function GitStatusBar() {\n const git = useGitContext();\n const [menuOpen, setMenuOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n const { menuRef, triggerRef, handleMenuKeyDown, handleTriggerKeyDown, closeMenu } =\n useMenuKeyboard(menuOpen, setMenuOpen);\n\n useEffect(() => {\n if (!menuOpen) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.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 const runItem = useCallback(\n (action: () => void) => {\n // The item is going away; don't yank focus back to the trigger.\n closeMenu(false);\n action();\n },\n [closeMenu],\n );\n\n if (!git || !git.repo || !git.status) return null;\n\n const { status } = git;\n const branchLabel = status.detached ? 'detached HEAD' : (status.branch ?? 'no branch');\n const aheadBehind = formatAheadBehind(status);\n const dirty = summarizeDirty(status);\n const merging = status.operation === 'merge';\n const chipLabelParts = [`Git: branch ${branchLabel}`];\n if (status.ahead > 0) chipLabelParts.push(`${status.ahead} ahead`);\n if (status.behind > 0) chipLabelParts.push(`${status.behind} behind`);\n if (dirty) chipLabelParts.push(dirty);\n if (merging) chipLabelParts.push('merge in progress');\n\n const canCreatePr =\n git.capabilities?.ghAvailable === true && git.remoteWeb?.host === 'github.com';\n\n return (\n <div ref={rootRef} className=\"db-git-statusbar\">\n <button\n ref={triggerRef}\n type=\"button\"\n className=\"db-git-statusbar-chip\"\n onClick={() => setMenuOpen((open) => !open)}\n onKeyDown={handleTriggerKeyDown}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n aria-label={chipLabelParts.join(', ')}\n title={chipLabelParts.join(', ')}\n >\n <span className=\"db-git-branch-glyph\" aria-hidden=\"true\">\n {'⎇'}\n </span>\n <span className=\"db-git-statusbar-branch\">{branchLabel}</span>\n {aheadBehind && <span className=\"db-git-statusbar-counts\">{aheadBehind}</span>}\n {dirty && <span className=\"db-git-statusbar-dirty\">{dirty}</span>}\n {merging && <span className=\"db-git-statusbar-merge\">merging</span>}\n {git.busy && (\n <span className=\"db-git-statusbar-busy\" aria-hidden=\"true\">\n {'…'}\n </span>\n )}\n </button>\n\n {menuOpen && (\n <div\n ref={menuRef}\n className=\"db-git-menu\"\n role=\"menu\"\n aria-label=\"Git actions\"\n onKeyDown={handleMenuKeyDown}\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-git-menu-item\"\n disabled={status.changes.length === 0 && !merging}\n onClick={() => runItem(() => git.openDialog({ kind: 'commit' }))}\n >\n {merging ? 'Commit merge…' : 'Commit…'}\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-git-menu-item\"\n disabled={git.busy !== null}\n onClick={() => runItem(() => void git.push())}\n >\n {status.upstream === null && !status.unborn ? 'Publish branch' : 'Push'}\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-git-menu-item\"\n disabled={git.busy !== null}\n onClick={() => runItem(() => void git.pull())}\n >\n Pull\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-git-menu-item\"\n disabled={git.busy !== null}\n onClick={() => runItem(() => void git.fetchRemote())}\n >\n Fetch\n </button>\n <div className=\"db-git-menu-divider\" role=\"separator\" />\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-git-menu-item\"\n onClick={() => runItem(() => git.openDialog({ kind: 'branches' }))}\n >\n Branches…\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-git-menu-item\"\n onClick={() => runItem(() => git.openDialog({ kind: 'history' }))}\n >\n Commit history…\n </button>\n {(git.remoteWeb || canCreatePr) && (\n <div className=\"db-git-menu-divider\" role=\"separator\" />\n )}\n {git.remoteWeb && (\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-git-menu-item\"\n onClick={() => runItem(() => git.openOnRemote())}\n >\n Open on {git.remoteWeb.host}\n </button>\n )}\n {canCreatePr && (\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-git-menu-item\"\n disabled={git.busy !== null}\n onClick={() => runItem(() => void git.createPullRequest())}\n >\n Create pull request\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * GitCommitDialog — message + per-file selection for committing changes.\n *\n * All changed files are included by default. While git has an operation in\n * progress (merge, rebase, cherry-pick, revert) the host must record the\n * whole index — git forbids a pathspec commit mid-operation — so every row\n * is locked and the dialog says so, rather than offering checkboxes whose\n * state the commit would ignore. Selection logic lives in\n * commit-selection.ts so it stays unit-testable.\n */\n\nimport { useMemo, useRef, useState } from 'react';\nimport { Dialog } from '../components/Dialog.js';\nimport { useGitContext } from './GitContext.js';\nimport { BADGE_LABELS, badgeKindFor } from './git-status.js';\nimport {\n allSelected,\n canCommit,\n commitsWholeIndex,\n isIncluded,\n isLocked,\n isMergeCommit,\n NO_OVERRIDES,\n resolveSelection,\n selectedPaths,\n setAllOverrides,\n toggleOverride,\n type CommitOverrides,\n} from './commit-selection.js';\n\n/** Human-readable name for the in-progress operation, for the hint line. */\nconst OPERATION_LABELS: Record<string, string> = {\n merge: 'merge',\n rebase: 'rebase',\n 'cherry-pick': 'cherry-pick',\n revert: 'revert',\n bisect: 'bisect',\n};\n\nexport function GitCommitDialog({ onClose }: { onClose: () => void }) {\n const git = useGitContext();\n const status = git?.status ?? null;\n const merging = isMergeCommit(status);\n /** Mid-operation: the commit records the index whole, so nothing unticks. */\n const wholeIndex = commitsWholeIndex(status);\n const changes = status?.changes;\n\n const [message, setMessage] = useState('');\n /** Only the user's explicit choices persist across status refreshes. */\n const [overrides, setOverrides] = useState<CommitOverrides>(NO_OVERRIDES);\n const messageRef = useRef<HTMLTextAreaElement>(null);\n\n // Resolved every render against the live change list: a file that appears\n // while the dialog is open (autosave triggers a status refresh every\n // 1.5s) is rendered checked *and* committed, rather than rendered checked\n // and silently dropped from a mount-time snapshot.\n const selection = useMemo(\n () => resolveSelection(changes ?? [], wholeIndex, overrides),\n [changes, wholeIndex, overrides],\n );\n\n if (!git || !status) return null;\n\n const allOn = allSelected(selection);\n const commitDisabled = !canCommit(message, selection) || git.busy !== null;\n\n const handleCommit = async () => {\n const ok = await git.commit(message, selectedPaths(selection));\n if (ok) onClose();\n };\n\n return (\n <Dialog\n title={merging ? 'Commit merge' : 'Commit changes'}\n onClose={onClose}\n size=\"wide\"\n closeOnBackdrop={false}\n initialFocusRef={messageRef}\n footer={\n <>\n <button type=\"button\" className=\"db-git-secondary-btn\" onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"db-git-primary-btn\"\n disabled={commitDisabled}\n onClick={() => void handleCommit()}\n >\n Commit\n </button>\n </>\n }\n >\n {wholeIndex && (\n <p className=\"db-settings-hint\">\n {merging\n ? 'You’re completing a merge. Committing will conclude it.'\n : `A ${OPERATION_LABELS[status.operation ?? ''] ?? 'git operation'} is in progress.`}{' '}\n Git records every change below in this commit — files cannot be left out until the{' '}\n {merging ? 'merge' : 'operation'} is finished.\n </p>\n )}\n <textarea\n ref={messageRef}\n className=\"db-git-commit-message\"\n value={message}\n onChange={(e) => setMessage(e.target.value)}\n placeholder=\"Commit message\"\n aria-label=\"Commit message\"\n rows={3}\n />\n {/* Nothing is selectable mid-operation, so the bulk toggle would be a\n no-op control. Hide it rather than render a dead button. */}\n {!wholeIndex && (\n <div className=\"db-git-form-row\">\n <button\n type=\"button\"\n className=\"db-git-secondary-btn\"\n onClick={() => setOverrides(setAllOverrides(selection, !allOn))}\n >\n {allOn ? 'Select none' : 'Select all'}\n </button>\n </div>\n )}\n <ul className=\"db-git-file-list\">\n {status.changes.map((change) => {\n const kind = badgeKindFor(change);\n const locked = isLocked(selection, change.path);\n const checked = isIncluded(selection, change.path);\n return (\n <li key={change.path} className=\"db-git-file-row\">\n <label>\n <input\n type=\"checkbox\"\n checked={checked}\n disabled={locked}\n title={\n locked\n ? `Included automatically while the ${merging ? 'merge' : 'operation'} is in progress`\n : undefined\n }\n onChange={() => setOverrides((o) => toggleOverride(o, selection, change.path))}\n />\n <span>{change.path.replace(/^\\/+/, '')}</span>\n </label>\n <span className=\"db-git-file-kind\">{BADGE_LABELS[kind]}</span>\n </li>\n );\n })}\n </ul>\n {git.lastResult?.tone === 'error' && (\n <p className=\"db-git-form-error\" role=\"alert\">\n {git.lastResult.message}\n </p>\n )}\n </Dialog>\n );\n}\n","/**\n * Commit-dialog selection state — pure helpers, unit-testable.\n *\n * All changed files are included by default, *except* while git has an\n * operation in progress (merge, rebase, cherry-pick, revert, bisect). Git\n * forbids a pathspec commit mid-operation, so the host drops the pathspec\n * and records the whole index — see `commit()` in\n * desktop/main/git/commands.ts. Every changed file is therefore committed\n * whatever the user ticks, and the whole list is locked rather than\n * rendering checkboxes that silently do nothing.\n *\n * The selection is *derived* from the live change list on every render\n * rather than snapshotted when the dialog mounts. Git status refreshes\n * (autosave pushes one every 1.5s) can add or drop files while the dialog\n * is open, and a snapshot would leave those rows rendering a checkbox that\n * no longer corresponds to what gets committed. The user's explicit\n * include/exclude choices are the only thing carried across refreshes —\n * see `CommitOverrides`.\n */\n\nimport type { GitFileChange, GitStatus } from '@bendyline/docblocks/host';\n\n/**\n * A changed file with no explicit user choice is committed. Stated once,\n * here, so the checkbox, `selectedPaths`, and the toggle all agree instead\n * of each re-deriving \"included\" from a key being absent.\n */\nexport const INCLUDED_BY_DEFAULT = true;\n\n/**\n * The user's explicit include/exclude choices, keyed by normalised path.\n * A path absent from this map has never been touched by the user and\n * therefore takes `INCLUDED_BY_DEFAULT`. Overrides may name paths that are\n * not currently changed (a file toggled off, saved back to its committed\n * contents, then changed again keeps the user's choice); `resolveSelection`\n * ignores those until they reappear in the change list.\n */\nexport type CommitOverrides = ReadonlyMap<string, boolean>;\n\nexport interface CommitSelection {\n /**\n * Normalised path → include in the commit. Covers exactly the paths in\n * the change list it was resolved from, so what the dialog renders and\n * what `selectedPaths` returns cannot drift apart.\n */\n included: Map<string, boolean>;\n /** Paths the user cannot exclude (every change while mid-operation). */\n locked: Set<string>;\n}\n\nfunction normalise(path: string): string {\n return path.startsWith('/') ? path : `/${path}`;\n}\n\nexport const NO_OVERRIDES: CommitOverrides = new Map<string, boolean>();\n\n/**\n * Resolve the live change list plus the user's choices into the selection\n * the dialog renders and commits. Pure — call it on every render.\n *\n * `wholeIndex` (see `commitsWholeIndex`) locks *every* changed file, not\n * just the conflicted ones: the host cannot honour a pathspec while an\n * operation is in progress, so an unticked file would be committed anyway.\n * Locking the whole list is what makes the checkboxes honest.\n */\nexport function resolveSelection(\n changes: readonly GitFileChange[],\n wholeIndex: boolean,\n overrides: CommitOverrides = NO_OVERRIDES,\n): CommitSelection {\n const included = new Map<string, boolean>();\n const locked = new Set<string>();\n for (const change of changes) {\n const path = normalise(change.path);\n if (wholeIndex) locked.add(path);\n included.set(path, wholeIndex ? true : (overrides.get(path) ?? INCLUDED_BY_DEFAULT));\n }\n return { included, locked };\n}\n\n/** Whether `path` (raw or normalised) is committed under this selection. */\nexport function isIncluded(selection: CommitSelection, path: string): boolean {\n return selection.included.get(normalise(path)) ?? INCLUDED_BY_DEFAULT;\n}\n\n/** Whether `path` (raw or normalised) is force-included and cannot be toggled. */\nexport function isLocked(selection: CommitSelection, path: string): boolean {\n return selection.locked.has(normalise(path));\n}\n\n/**\n * Flip one path, returning the next overrides map. Reads the *current*\n * resolved state rather than the raw override, so the first click on a\n * never-touched (default-included) file excludes it — one click, matching\n * what its checkbox shows.\n */\nexport function toggleOverride(\n overrides: CommitOverrides,\n selection: CommitSelection,\n path: string,\n): CommitOverrides {\n const key = normalise(path);\n if (isLocked(selection, key)) return overrides;\n const next = new Map(overrides);\n next.set(key, !isIncluded(selection, key));\n return next;\n}\n\n/**\n * Explicitly set every currently-changed file. Locked paths are left to\n * `resolveSelection`, which force-includes them regardless.\n */\nexport function setAllOverrides(selection: CommitSelection, value: boolean): CommitOverrides {\n const next = new Map<string, boolean>();\n for (const key of selection.included.keys()) {\n if (!selection.locked.has(key)) next.set(key, value);\n }\n return next;\n}\n\n/** True when every currently-changed file is included. */\nexport function allSelected(selection: CommitSelection): boolean {\n return [...selection.included.values()].every(Boolean);\n}\n\nexport function selectedPaths(selection: CommitSelection): string[] {\n return [...selection.included.entries()].filter(([, on]) => on).map(([path]) => path);\n}\n\nexport function canCommit(message: string, selection: CommitSelection): boolean {\n return message.trim().length > 0 && selectedPaths(selection).length > 0;\n}\n\n/** True when committing concludes an in-progress merge. */\nexport function isMergeCommit(status: GitStatus | null): boolean {\n return status?.operation === 'merge';\n}\n\n/**\n * True when the commit will record the entire index regardless of the\n * paths passed to it — i.e. git has an operation in progress. Mirrors the\n * host's `if (rels && operation === null)` pathspec guard, so it is *any*\n * operation and not merge alone: a cherry-pick or revert drops the\n * pathspec exactly the same way.\n */\nexport function commitsWholeIndex(status: GitStatus | null): boolean {\n return status !== null && status.operation !== null;\n}\n","/**\n * GitBranchesDialog — switch between local branches or create a new one.\n *\n * Loads the branch list once from the host git API on mount. Remote\n * branches are display-only in v1 (a collapsed disclosure); switching and\n * creating go through the GitValue actions so errors (e.g. uncommitted\n * changes blocking a checkout) surface inline via lastResult.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { GitBranchInfo } from '@bendyline/docblocks/host';\nimport { Dialog } from '../components/Dialog.js';\nimport { useGitContext } from './GitContext.js';\n\nexport function GitBranchesDialog({\n createFocus,\n onClose,\n}: {\n createFocus?: boolean;\n onClose: () => void;\n}) {\n const git = useGitContext();\n const gitApi = git?.gitApi ?? null;\n const repositoryId = git?.repositoryId ?? null;\n\n const [branches, setBranches] = useState<GitBranchInfo[] | null>(null);\n const [loadError, setLoadError] = useState<string | null>(null);\n const [newName, setNewName] = useState('');\n const createInputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (!gitApi || !repositoryId) return;\n let cancelled = false;\n void gitApi.listBranches(repositoryId).then(\n (result) => {\n if (cancelled) return;\n if (result.ok) setBranches(result.value);\n else setLoadError(result.error.message || 'Could not list branches');\n },\n // A rejected call (the host went away) left the dialog on\n // \"Loading branches…\" forever. Fail visibly instead.\n (error: unknown) => {\n if (cancelled) return;\n setLoadError(error instanceof Error ? error.message : 'Could not list branches');\n },\n );\n return () => {\n cancelled = true;\n };\n }, [gitApi, repositoryId]);\n\n if (!git) return null;\n\n const locals = branches?.filter((b) => b.kind === 'local') ?? [];\n const remotes = branches?.filter((b) => b.kind === 'remote') ?? [];\n const canCreate = newName.trim().length > 0 && git.busy === null;\n\n const handleSwitch = async (name: string) => {\n const ok = await git.switchBranch(name);\n if (ok) onClose();\n };\n\n const handleCreate = async () => {\n if (!canCreate) return;\n const ok = await git.createBranch(newName.trim());\n if (ok) onClose();\n };\n\n return (\n <Dialog\n title=\"Branches\"\n onClose={onClose}\n initialFocusRef={createFocus ? createInputRef : undefined}\n >\n {branches === null && loadError === null && <p className=\"db-git-hint\">Loading branches…</p>}\n {loadError !== null && (\n <p className=\"db-git-form-error\" role=\"alert\">\n {loadError}\n </p>\n )}\n {branches !== null && (\n <div className=\"db-git-branch-list\">\n {locals.map((branch) =>\n branch.current ? (\n <span\n key={branch.name}\n className=\"db-git-branch-row db-git-branch-row--current\"\n aria-current=\"true\"\n >\n {branch.name}\n </span>\n ) : (\n <button\n key={branch.name}\n type=\"button\"\n className=\"db-git-branch-row\"\n disabled={git.busy !== null}\n onClick={() => void handleSwitch(branch.name)}\n >\n {branch.name}\n </button>\n ),\n )}\n </div>\n )}\n {git.lastResult?.tone === 'error' && (\n <p className=\"db-git-form-error\" role=\"alert\">\n {git.lastResult.message}\n </p>\n )}\n <hr />\n <div className=\"db-git-form-row\">\n <label className=\"db-git-form-label\" htmlFor=\"db-git-new-branch-name\">\n New branch\n </label>\n <input\n id=\"db-git-new-branch-name\"\n ref={createInputRef}\n className=\"db-git-form-input\"\n type=\"text\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') void handleCreate();\n }}\n placeholder=\"feature/my-branch\"\n spellCheck={false}\n />\n <button\n type=\"button\"\n className=\"db-git-primary-btn\"\n disabled={!canCreate}\n onClick={() => void handleCreate()}\n >\n Create\n </button>\n </div>\n {remotes.length > 0 && (\n <details>\n <summary>Remote branches ({remotes.length})</summary>\n <div className=\"db-git-branch-list\">\n {remotes.map((branch) => (\n <span key={branch.name} className=\"db-git-branch-row\">\n {branch.name}\n </span>\n ))}\n </div>\n </details>\n )}\n </Dialog>\n );\n}\n","/**\n * GitHistoryDialog — paged commit log for the repository or a single file.\n *\n * Pages `git log` 50 commits at a time; a row expands (one at a time) to\n * show the full message body and the files changed in that commit — each\n * file opens the commit-vs-parent diff dialog (which replaces this one;\n * acceptable for v1).\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { GitFileChange, GitLogEntry } from '@bendyline/docblocks/host';\nimport { Dialog } from '../components/Dialog.js';\nimport { useGitContext } from './GitContext.js';\nimport { BADGE_GLYPHS, BADGE_LABELS, badgeKindFor } from './git-status.js';\n\nexport interface GitHistoryDialogProps {\n /** Slash-prefixed workspace-relative path; absent → whole-repo history. */\n path?: string;\n onClose: () => void;\n}\n\nconst PAGE_SIZE = 50;\n\ntype CommitDetail = { body: string; files: GitFileChange[] } | { error: string };\n\n/** Message body beyond the subject line, or '' when it adds nothing. */\nfunction extraBody(body: string, subject: string): string {\n const trimmedBody = body.trim();\n const trimmedSubject = subject.trim();\n if (!trimmedBody || trimmedBody === trimmedSubject) return '';\n if (trimmedBody.startsWith(trimmedSubject)) {\n return trimmedBody.slice(trimmedSubject.length).trim();\n }\n return trimmedBody;\n}\n\nfunction formatDate(iso: string): string {\n const date = new Date(iso);\n return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;\n}\n\nexport function GitHistoryDialog({ path, onClose }: GitHistoryDialogProps) {\n const git = useGitContext();\n const gitApi = git?.gitApi ?? null;\n const repositoryId = git?.repositoryId ?? null;\n\n const [entries, setEntries] = useState<GitLogEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [hasMore, setHasMore] = useState(false);\n const [expandedSha, setExpandedSha] = useState<string | null>(null);\n const [details, setDetails] = useState<ReadonlyMap<string, CommitDetail>>(new Map());\n /**\n * Bumped whenever the repository or file being logged changes. A slow\n * page from the previous repo/file resolving afterwards would otherwise\n * append the wrong repository's commits to the new list.\n */\n const generationRef = useRef(0);\n\n const loadPage = useCallback(\n async (skip: number) => {\n if (!gitApi || !repositoryId) return;\n const generation = generationRef.current;\n const stale = () => generation !== generationRef.current;\n setLoading(true);\n setError(null);\n try {\n const result = await gitApi.log(repositoryId, { path, maxCount: PAGE_SIZE, skip });\n if (stale()) return;\n if (!result.ok) {\n setError(result.error.message);\n return;\n }\n setEntries((prev) => (skip === 0 ? result.value : [...prev, ...result.value]));\n setHasMore(result.value.length === PAGE_SIZE);\n } catch (caught: unknown) {\n // A rejected log left the dialog claiming \"No commits yet\".\n if (stale()) return;\n setError(caught instanceof Error ? caught.message : 'Could not load history');\n } finally {\n if (!stale()) setLoading(false);\n }\n },\n [gitApi, repositoryId, path],\n );\n\n useEffect(() => {\n generationRef.current += 1;\n setEntries([]);\n setExpandedSha(null);\n setDetails(new Map());\n setHasMore(false);\n setLoading(false);\n void loadPage(0);\n }, [loadPage]);\n\n const handleRowClick = (sha: string) => {\n if (expandedSha === sha) {\n setExpandedSha(null);\n return;\n }\n setExpandedSha(sha);\n if (!gitApi || !repositoryId || details.has(sha)) return;\n const generation = generationRef.current;\n const record = (detail: CommitDetail) => {\n // The row renders \"Loading…\" until a detail lands, so a rejection\n // that recorded nothing left it spinning for the dialog's lifetime.\n if (generation !== generationRef.current) return;\n setDetails((prev) => {\n const next = new Map(prev);\n next.set(sha, detail);\n return next;\n });\n };\n void gitApi.commitFiles(repositoryId, sha).then(\n (result) => record(result.ok ? result.value : { error: result.error.message }),\n (error: unknown) =>\n record({\n error: error instanceof Error ? error.message : 'Could not load this commit',\n }),\n );\n };\n\n if (!git) return null;\n\n const baseName = path ? path.replace(/^\\/+/, '').split('/').pop() : null;\n const title = baseName ? `History — ${baseName}` : 'Commit history';\n\n return (\n <Dialog title={title} size=\"wide\" onClose={onClose}>\n {error && (\n <p className=\"db-git-form-error\" role=\"alert\">\n {error}\n </p>\n )}\n {!error && entries.length === 0 && loading && <p className=\"db-git-hint\">Loading history…</p>}\n {!error && entries.length === 0 && !loading && <p className=\"db-git-hint\">No commits yet.</p>}\n {entries.length > 0 && (\n <ul className=\"db-git-history-list\">\n {entries.map((entry) => {\n const expanded = expandedSha === entry.sha;\n const detail = details.get(entry.sha);\n const meta = [\n entry.authorName,\n entry.sha.slice(0, 7),\n formatDate(entry.authorDate),\n entry.refs.join(', '),\n ]\n .filter(Boolean)\n .join(' · ');\n const body =\n detail && !('error' in detail) ? extraBody(detail.body, entry.subject) : '';\n return (\n <li key={entry.sha} className=\"db-git-history-item\">\n <button\n type=\"button\"\n className=\"db-git-history-toggle\"\n aria-expanded={expanded}\n onClick={() => handleRowClick(entry.sha)}\n >\n <span className=\"db-git-history-subject\">{entry.subject}</span>\n <span className=\"db-git-history-meta\">{meta}</span>\n </button>\n {expanded && !detail && <p className=\"db-git-hint\">Loading…</p>}\n {expanded && detail && 'error' in detail && (\n <p className=\"db-git-form-error\" role=\"alert\">\n {detail.error}\n </p>\n )}\n {expanded && detail && !('error' in detail) && (\n <>\n {body && <pre className=\"db-git-history-body\">{body}</pre>}\n <ul className=\"db-git-history-files\">\n {detail.files.map((file) => {\n const kind = badgeKindFor(file);\n return (\n <li key={file.path}>\n <button\n type=\"button\"\n className=\"db-git-history-file\"\n onClick={() =>\n git.openDialog({\n kind: 'diff',\n path: file.path,\n revision: { sha: entry.sha },\n })\n }\n >\n <span\n className=\"db-git-file-kind\"\n aria-label={BADGE_LABELS[kind]}\n title={BADGE_LABELS[kind]}\n >\n {BADGE_GLYPHS[kind]}\n </span>\n {file.path.replace(/^\\/+/, '')}\n </button>\n </li>\n );\n })}\n </ul>\n </>\n )}\n </li>\n );\n })}\n </ul>\n )}\n {hasMore && (\n <button\n type=\"button\"\n className=\"db-git-secondary-btn\"\n disabled={loading}\n onClick={() => void loadPage(entries.length)}\n >\n Show older commits\n </button>\n )}\n </Dialog>\n );\n}\n","/**\n * GitDiffDialog — full-size modal showing a file diff.\n *\n * Without a revision: working tree vs HEAD (HEAD side via the git host API,\n * working side via the workspace FileSystemProvider). With a revision: that\n * commit vs its parent, both sides via readFileAtRevision. Absent sides\n * render as empty text with an \"(absent)\" label; binary files short-circuit\n * to a hint since there is no text diff to show.\n */\n\nimport { useEffect, useState } from 'react';\nimport { getFileSystemProviderV2, parseWorkspacePath } from '@bendyline/docblocks/filesystem';\nimport { Dialog } from '../components/Dialog.js';\nimport { useGitContext } from './GitContext.js';\nimport { GitDiffView } from './GitDiffView.js';\n\nexport interface GitDiffDialogProps {\n /** Slash-prefixed workspace-relative path. */\n path: string;\n /** Absent → working tree vs HEAD; present → that commit vs its parent. */\n revision?: { sha: string };\n onClose: () => void;\n}\n\ntype DiffLoadState =\n | { phase: 'loading' }\n | { phase: 'error'; message: string }\n | { phase: 'binary' }\n | {\n phase: 'ready';\n original: string;\n modified: string;\n labels: { original: string; modified: string };\n };\n\nexport function GitDiffDialog({ path, revision, onClose }: GitDiffDialogProps) {\n const git = useGitContext();\n const gitApi = git?.gitApi ?? null;\n const provider = git?.provider ?? null;\n const repositoryId = git?.repositoryId ?? null;\n const sha = revision?.sha ?? null;\n\n const [state, setState] = useState<DiffLoadState>({ phase: 'loading' });\n\n useEffect(() => {\n if (!gitApi || !repositoryId) {\n setState({ phase: 'error', message: 'Git is not available for this workspace.' });\n return;\n }\n let cancelled = false;\n setState({ phase: 'loading' });\n\n const load = async (): Promise<DiffLoadState> => {\n if (sha) {\n const short = sha.slice(0, 7);\n const [parent, at] = await Promise.all([\n gitApi.readFileAtRevision(repositoryId, path, { kind: 'parent-of', sha }),\n gitApi.readFileAtRevision(repositoryId, path, { kind: 'commit', sha }),\n ]);\n if (!parent.ok) return { phase: 'error', message: parent.error.message };\n if (!at.ok) return { phase: 'error', message: at.error.message };\n if (\n (parent.value.content === null && parent.value.binary) ||\n (at.value.content === null && at.value.binary)\n ) {\n return { phase: 'binary' };\n }\n return {\n phase: 'ready',\n original: parent.value.content ?? '',\n modified: at.value.content ?? '',\n labels: {\n original: parent.value.content === null ? `${short}^ (absent)` : `${short}^`,\n modified: at.value.content === null ? `${short} (absent)` : short,\n },\n };\n }\n\n if (!provider) {\n return { phase: 'error', message: 'Workspace files are not available.' };\n }\n const providerV2 = getFileSystemProviderV2(provider);\n const [head, working] = await Promise.all([\n gitApi.readFileAtRevision(repositoryId, path, { kind: 'head' }),\n providerV2\n ? providerV2\n .readFile(parseWorkspacePath(path))\n .then((file) => (file ? new TextDecoder().decode(file.data) : null))\n : provider.readFile(path),\n ]);\n if (!head.ok) return { phase: 'error', message: head.error.message };\n if (head.value.content === null && head.value.binary) return { phase: 'binary' };\n return {\n phase: 'ready',\n original: head.value.content ?? '',\n modified: working ?? '',\n labels: {\n original: head.value.content === null ? 'HEAD (absent)' : 'HEAD',\n modified: working === null ? 'Working tree (absent)' : 'Working tree',\n },\n };\n };\n\n load()\n .catch(\n (err: unknown): DiffLoadState => ({\n phase: 'error',\n message: err instanceof Error ? err.message : 'Failed to load the diff',\n }),\n )\n .then((next) => {\n if (!cancelled) setState(next);\n });\n return () => {\n cancelled = true;\n };\n }, [gitApi, provider, repositoryId, path, sha]);\n\n if (!git) return null;\n\n const fullPath = path.replace(/^\\/+/, '');\n const baseName = fullPath.split('/').pop() || fullPath;\n\n return (\n <Dialog title={baseName} size=\"full\" onClose={onClose}>\n <p className=\"db-settings-hint\">{fullPath}</p>\n {state.phase === 'loading' && <p className=\"db-git-hint\">Loading changes…</p>}\n {state.phase === 'error' && (\n <p className=\"db-git-form-error\" role=\"alert\">\n {state.message}\n </p>\n )}\n {state.phase === 'binary' && (\n <p className=\"db-git-hint\">Binary file — no text diff available.</p>\n )}\n {state.phase === 'ready' && (\n <GitDiffView\n original={state.original}\n modified={state.modified}\n fileName={baseName}\n theme={git.theme}\n labels={state.labels}\n />\n )}\n </Dialog>\n );\n}\n","/**\n * GitDiffView — read-only Monaco side-by-side diff.\n *\n * Monaco is never statically imported: squisq's useMonacoLoader() lazily\n * imports the editor bundle once per page and hands back the namespace.\n * The diff editor and both text models are created imperatively into a\n * host div and disposed on unmount (the classic Monaco leak). Content and\n * theme changes update the existing editor without recreating it.\n */\n\nimport { useEffect, useRef } from 'react';\nimport {\n detectLanguageFromFileName,\n useMonacoLoader,\n type UseMonacoLoaderResult,\n} from '@bendyline/squisq-editor-react';\n\ntype MonacoModule = NonNullable<UseMonacoLoaderResult['monaco']>;\ntype DiffEditorInstance = ReturnType<MonacoModule['editor']['createDiffEditor']>;\ntype TextModel = ReturnType<MonacoModule['editor']['createModel']>;\n\nexport interface GitDiffViewProps {\n original: string;\n modified: string;\n /** Used for language detection (markdown for .md, plain text otherwise). */\n fileName: string;\n theme: 'light' | 'dark';\n /** Optional column headers rendered above the two panes. */\n labels?: { original: string; modified: string };\n}\n\nfunction languageFor(fileName: string): string {\n const detected = detectLanguageFromFileName(fileName);\n if (detected) return detected;\n return fileName.toLowerCase().endsWith('.md') ? 'markdown' : 'plaintext';\n}\n\nexport function GitDiffView({ original, modified, fileName, theme, labels }: GitDiffViewProps) {\n const { monaco, ready } = useMonacoLoader();\n const hostRef = useRef<HTMLDivElement | null>(null);\n const editorRef = useRef<DiffEditorInstance | null>(null);\n const modelsRef = useRef<{ original: TextModel; modified: TextModel } | null>(null);\n\n const language = languageFor(fileName);\n\n // Create the editor once monaco settles; dispose editor AND models on unmount.\n useEffect(() => {\n const host = hostRef.current;\n if (!monaco || !host) return;\n const originalModel = monaco.editor.createModel('', 'plaintext');\n const modifiedModel = monaco.editor.createModel('', 'plaintext');\n const editor = monaco.editor.createDiffEditor(host, {\n readOnly: true,\n renderSideBySide: true,\n automaticLayout: true,\n minimap: { enabled: false },\n wordWrap: 'on',\n scrollBeyondLastLine: false,\n renderOverviewRuler: false,\n });\n editor.setModel({ original: originalModel, modified: modifiedModel });\n editorRef.current = editor;\n modelsRef.current = { original: originalModel, modified: modifiedModel };\n return () => {\n editorRef.current = null;\n modelsRef.current = null;\n editor.dispose();\n originalModel.dispose();\n modifiedModel.dispose();\n };\n }, [monaco]);\n\n // Sync content + language into the existing models — never recreate the editor.\n useEffect(() => {\n if (!monaco) return;\n const models = modelsRef.current;\n if (!models) return;\n if (models.original.getValue() !== original) models.original.setValue(original);\n if (models.modified.getValue() !== modified) models.modified.setValue(modified);\n monaco.editor.setModelLanguage(models.original, language);\n monaco.editor.setModelLanguage(models.modified, language);\n }, [monaco, original, modified, language]);\n\n // React to theme prop changes.\n useEffect(() => {\n if (!monaco) return;\n monaco.editor.setTheme(theme === 'dark' ? 'vs-dark' : 'vs');\n }, [monaco, theme]);\n\n if (!ready) {\n return <div className=\"db-git-diff-loading\">Loading diff…</div>;\n }\n\n return (\n <>\n {labels && (\n <div className=\"db-git-diff-labels\">\n <span>{labels.original}</span>\n <span>{labels.modified}</span>\n </div>\n )}\n <div ref={hostRef} className=\"db-git-diff-host\" />\n </>\n );\n}\n","/**\n * GitCloneDialog — clone a remote repository into a new local workspace.\n *\n * The renderer only collects the URL; the main process shows the native\n * destination picker, streams progress back, and registers the clone as a\n * workspace. An auth failure swaps the body to the shared credential\n * guidance copy (no credentials are ever collected here).\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type {\n ElectronWorkspaceInfo,\n GitCloneHandle,\n GitCloneProgress,\n} from '@bendyline/docblocks/host';\nimport { Dialog } from '../components/Dialog.js';\nimport { useGitContext } from './GitContext.js';\nimport { deriveCloneFolderName, isLikelyGitUrl } from './git-clone-utils.js';\nimport { GitCredentialGuidance } from './GitAuthGuidanceDialog.js';\n\nexport function GitCloneDialog({\n onClose,\n onCloned,\n}: {\n onClose: () => void;\n onCloned: (info: ElectronWorkspaceInfo) => void;\n}) {\n const git = useGitContext();\n const gitApi = git?.gitApi ?? null;\n\n const [url, setUrl] = useState('');\n const [cloning, setCloning] = useState(false);\n const [progress, setProgress] = useState<GitCloneProgress | null>(null);\n const [error, setError] = useState<string | null>(null);\n /** Non-null → show embedded credential guidance instead of the form. */\n const [authDetail, setAuthDetail] = useState<{ detail?: string } | null>(null);\n const handleRef = useRef<GitCloneHandle | null>(null);\n const urlInputRef = useRef<HTMLInputElement>(null);\n\n // Closing the dialog mid-clone abandons it — kill git and clean up.\n useEffect(\n () => () => {\n handleRef.current?.cancel();\n },\n [],\n );\n\n if (!gitApi || typeof gitApi.clone !== 'function') return null;\n\n const canClone = isLikelyGitUrl(url) && !cloning;\n\n const handleClone = async () => {\n if (!canClone) return;\n setCloning(true);\n setError(null);\n setProgress(null);\n const handle = gitApi.clone(url.trim(), (p) => setProgress(p));\n handleRef.current = handle;\n const result = await handle.result;\n handleRef.current = null;\n setCloning(false);\n setProgress(null);\n if (!result.ok) {\n switch (result.error.code) {\n case 'invalid-url':\n setError('That doesn’t look like a valid repository URL.');\n break;\n case 'destination-exists':\n setError('A folder with that name already exists there. Pick a different location.');\n break;\n case 'auth-failed':\n setAuthDetail({ detail: result.error.message });\n break;\n case 'cancelled':\n break; // user cancelled — just return to the form\n default:\n setError(result.error.message);\n }\n return;\n }\n if (result.value === null) return; // user cancelled the destination picker\n onCloned(result.value);\n };\n\n const progressPercent = progress?.percent ?? null;\n const progressText =\n progress !== null\n ? `${progress.phase}…${progressPercent !== null ? ` ${Math.round(progressPercent)}%` : ''}`\n : 'Starting clone…';\n\n if (authDetail !== null) {\n return (\n <Dialog\n title=\"Clone repository\"\n onClose={onClose}\n footer={\n <>\n <button\n type=\"button\"\n className=\"db-git-secondary-btn\"\n onClick={() => setAuthDetail(null)}\n >\n Back\n </button>\n <button type=\"button\" className=\"db-git-primary-btn\" onClick={onClose}>\n Close\n </button>\n </>\n }\n >\n <p className=\"db-settings-hint\">Git could not authenticate with that remote.</p>\n <GitCredentialGuidance detail={authDetail.detail} />\n </Dialog>\n );\n }\n\n return (\n <Dialog\n title=\"Clone repository\"\n onClose={onClose}\n closeOnBackdrop={!cloning}\n initialFocusRef={urlInputRef}\n footer={\n <>\n <button\n type=\"button\"\n className=\"db-git-secondary-btn\"\n onClick={onClose}\n disabled={cloning}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"db-git-primary-btn\"\n disabled={!canClone}\n onClick={() => void handleClone()}\n >\n Clone\n </button>\n </>\n }\n >\n <div className=\"db-git-form-row\">\n <label className=\"db-git-form-label\" htmlFor=\"db-git-clone-url\">\n Repository URL\n </label>\n <input\n id=\"db-git-clone-url\"\n ref={urlInputRef}\n className=\"db-git-form-input\"\n type=\"text\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') void handleClone();\n }}\n placeholder=\"https://github.com/owner/repo.git\"\n disabled={cloning}\n spellCheck={false}\n />\n </div>\n {isLikelyGitUrl(url) && (\n <p className=\"db-git-hint\">\n Will clone into: <b>{deriveCloneFolderName(url)}</b> — you’ll pick where next\n </p>\n )}\n <p className=\"db-git-hint\">\n HTTPS and SSH URLs both work. You’ll choose the destination folder in the next step.\n </p>\n {error !== null && (\n <p className=\"db-git-form-error\" role=\"alert\">\n {error}\n </p>\n )}\n {cloning && (\n <div className=\"db-git-progress\">\n {progressPercent !== null && (\n <div\n className=\"db-git-progress-bar\"\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(progressPercent)}\n style={{ width: `${progressPercent}%` }}\n />\n )}\n <p className=\"db-git-progress-text\">{progressText}</p>\n <button\n type=\"button\"\n className=\"db-git-secondary-btn\"\n onClick={() => handleRef.current?.cancel()}\n >\n Cancel\n </button>\n </div>\n )}\n </Dialog>\n );\n}\n","/**\n * Clone-dialog helpers — pure URL utilities, unit-testable.\n */\n\n/** Folder name a clone of this URL will produce (mirrors the host's rule). */\nexport function deriveCloneFolderName(url: string): string {\n const trimmed = url.trim().replace(/\\/+$/, '');\n const lastSegment = trimmed.split(/[/:\\\\]/).pop() ?? '';\n const withoutGit = lastSegment.replace(/\\.git$/i, '');\n const sanitized = withoutGit.replace(/[^A-Za-z0-9._-]/g, '-');\n return sanitized.length > 0 ? sanitized : 'repository';\n}\n\n/** Loose shape check for enabling the Clone button — the host re-validates. */\nexport function isLikelyGitUrl(url: string): boolean {\n const trimmed = url.trim();\n if (trimmed.length === 0 || /\\s/.test(trimmed)) return false;\n if (trimmed.startsWith('-') || trimmed.toLowerCase().startsWith('file:')) return false;\n if (/^(https?|ssh|git):\\/\\/\\S+\\/\\S+/i.test(trimmed)) return true;\n // scp-like: user@host:owner/repo\n if (/^[\\w.-]+@[\\w.-]+:\\S+/.test(trimmed)) return true;\n return false;\n}\n","/**\n * GitAuthGuidanceDialog — shown when a git operation fails to authenticate.\n *\n * DocBlocks deliberately never collects or stores credentials, so this\n * dialog only explains the three supported sign-in routes (credential\n * helper, GitHub CLI, SSH key). The copy is exported as a standalone\n * component so the clone dialog can embed it after an auth failure.\n */\n\nimport { maybeGetDocBlocksHost } from '@bendyline/docblocks/host';\nimport { Dialog } from '../components/Dialog.js';\n\nconst LEARN_MORE_URL =\n 'https://docs.github.com/en/get-started/getting-started-with-git/caching-your-github-credentials-in-git';\n\nconst OPERATION_LABELS: Record<'push' | 'pull' | 'fetch' | 'clone' | 'pr', string> = {\n push: 'push',\n pull: 'pull',\n fetch: 'fetch',\n clone: 'clone',\n pr: 'create the pull request',\n};\n\n/** The credential guidance copy, reusable outside this dialog (clone flow). */\nexport function GitCredentialGuidance({ detail }: { detail?: string }) {\n return (\n <>\n <p className=\"db-settings-hint\">\n DocBlocks never stores Git credentials. Sign in with one of these, then try again:\n </p>\n <ul className=\"db-git-hint\">\n <li>\n A git credential helper (<code>git config credential.helper</code>)\n </li>\n <li>\n The GitHub CLI (<code>gh auth login</code>)\n </li>\n <li>An SSH key registered with your remote</li>\n </ul>\n {detail && (\n <details>\n <summary>Details</summary>\n <p className=\"db-git-hint\">{detail}</p>\n </details>\n )}\n </>\n );\n}\n\nexport function GitAuthGuidanceDialog({\n operation,\n detail,\n onClose,\n}: {\n operation: 'push' | 'pull' | 'fetch' | 'clone' | 'pr';\n detail?: string;\n onClose: () => void;\n}) {\n return (\n <Dialog\n title=\"Git needs credentials\"\n onClose={onClose}\n footer={\n <>\n <button\n type=\"button\"\n className=\"db-git-secondary-btn\"\n onClick={() => void maybeGetDocBlocksHost()?.shell.openExternal(LEARN_MORE_URL)}\n >\n Learn more\n </button>\n <button type=\"button\" className=\"db-git-primary-btn\" onClick={onClose}>\n Close\n </button>\n </>\n }\n >\n <p className=\"db-settings-hint\">\n Git could not authenticate with the remote while trying to {OPERATION_LABELS[operation]}.\n </p>\n <GitCredentialGuidance detail={detail} />\n </Dialog>\n );\n}\n","/**\n * GitConflictsDialog — lists conflicted files after a pull hits a merge\n * conflict. Each row opens the file in the editor so the user can resolve\n * the markers; the primary action hands off to the commit dialog, which\n * concludes the merge.\n */\n\nimport { Dialog } from '../components/Dialog.js';\nimport { useGitContext } from './GitContext.js';\n\nexport function GitConflictsDialog({\n paths,\n onOpenFile,\n onClose,\n}: {\n paths: string[];\n onOpenFile: (path: string) => void;\n onClose: () => void;\n}) {\n const git = useGitContext();\n\n return (\n <Dialog\n title=\"Merge conflicts\"\n onClose={onClose}\n footer={\n <>\n <button type=\"button\" className=\"db-git-secondary-btn\" onClick={onClose}>\n Close\n </button>\n <button\n type=\"button\"\n className=\"db-git-primary-btn\"\n onClick={() => git?.openDialog({ kind: 'commit' })}\n >\n Open commit dialog\n </button>\n </>\n }\n >\n <p className=\"db-settings-hint\">\n These files contain conflict markers. Edit each one to resolve the conflicts, then commit to\n complete the merge.\n </p>\n <ul className=\"db-git-file-list\">\n {paths.map((path) => (\n <li key={path} className=\"db-git-file-row\">\n <button\n type=\"button\"\n onClick={() => {\n onOpenFile(path);\n onClose();\n }}\n >\n {path.replace(/^\\/+/, '')}\n </button>\n </li>\n ))}\n </ul>\n </Dialog>\n );\n}\n","/**\n * GitUI — single mount point for the git status bar, the aria-live\n * operation result line, and every git dialog. Dialog visibility lives in\n * GitContext so the file tree, toolbar, and native menu can all open them.\n */\n\nimport type { ElectronWorkspaceInfo } from '@bendyline/docblocks/host';\nimport { useGitContext } from './GitContext.js';\nimport { GitStatusBar } from './GitStatusBar.js';\nimport { GitCommitDialog } from './GitCommitDialog.js';\nimport { GitBranchesDialog } from './GitBranchesDialog.js';\nimport { GitHistoryDialog } from './GitHistoryDialog.js';\nimport { GitDiffDialog } from './GitDiffDialog.js';\nimport { GitCloneDialog } from './GitCloneDialog.js';\nimport { GitAuthGuidanceDialog } from './GitAuthGuidanceDialog.js';\nimport { GitConflictsDialog } from './GitConflictsDialog.js';\n\nexport interface GitUIProps {\n /** Open a workspace file in the editor (from conflicts/history dialogs). */\n onOpenFile: (path: string) => void;\n /** A clone finished and its folder is registered — open the workspace. */\n onWorkspaceCloned?: (info: ElectronWorkspaceInfo) => void;\n}\n\nexport function GitUI({ onOpenFile, onWorkspaceCloned }: GitUIProps) {\n const git = useGitContext();\n if (!git || !git.available) return null;\n\n const { dialog, closeDialog } = git;\n\n return (\n <>\n <GitStatusBar />\n {git.repo && (\n <span className=\"db-git-inline-status\" role=\"status\" aria-live=\"polite\">\n {git.lastResult?.message ?? ''}\n </span>\n )}\n {dialog.kind === 'commit' && <GitCommitDialog onClose={closeDialog} />}\n {dialog.kind === 'branches' && (\n <GitBranchesDialog createFocus={dialog.createFocus} onClose={closeDialog} />\n )}\n {dialog.kind === 'history' && <GitHistoryDialog path={dialog.path} onClose={closeDialog} />}\n {dialog.kind === 'diff' && (\n <GitDiffDialog path={dialog.path} revision={dialog.revision} onClose={closeDialog} />\n )}\n {dialog.kind === 'clone' && (\n <GitCloneDialog\n onClose={closeDialog}\n onCloned={(info) => {\n closeDialog();\n onWorkspaceCloned?.(info);\n }}\n />\n )}\n {dialog.kind === 'auth-guidance' && (\n <GitAuthGuidanceDialog\n operation={dialog.operation}\n detail={dialog.detail}\n onClose={closeDialog}\n />\n )}\n {dialog.kind === 'conflicts' && (\n <GitConflictsDialog paths={dialog.paths} onOpenFile={onOpenFile} onClose={closeDialog} />\n )}\n </>\n );\n}\n"],"mappings":"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","names":["useRef","useState","jsx","jsxs","useState","useRef","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","useCallback","useEffect","useRef","useState","Fragment","jsx","jsxs","useState","useRef","useCallback","useEffect","error","useEffect","useState","useEffect","useRef","Fragment","jsx","jsxs","jsx","jsxs","useState","useEffect","useEffect","useRef","useState","Fragment","jsx","jsxs","OPERATION_LABELS","Fragment","jsx","jsxs","useState","useRef","useEffect","Fragment","jsx","jsxs","Fragment","jsx","jsxs"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/DocBlocksShell/LazyEditorShell.ts"],"sourcesContent":["/** Deferred boundary for the large Squisq editor implementation. */\nexport { EditorShell as default } from '@bendyline/squisq-editor-react';\n"],"mappings":";AACA,SAAwB,mBAAe;","names":[]}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// src/Export/ShareDialog.tsx
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { SHARED_DOCUMENT_LIMITS as SHARED_DOCUMENT_LIMITS2 } from "@bendyline/docblocks/share";
|
|
4
|
+
|
|
5
|
+
// src/Export/shared-document.ts
|
|
6
|
+
import {
|
|
7
|
+
SHARED_DOCUMENT_LIMITS,
|
|
8
|
+
createSharedDocumentUrl
|
|
9
|
+
} from "@bendyline/docblocks/share";
|
|
10
|
+
var PUBLIC_DOCBLOCKS_SHARE_URL = "https://bendyline.github.io/docblocks/";
|
|
11
|
+
function resolveSharedDocumentBaseUrl(currentUrl) {
|
|
12
|
+
try {
|
|
13
|
+
const current = new URL(currentUrl);
|
|
14
|
+
if (current.protocol === "http:" || current.protocol === "https:") {
|
|
15
|
+
current.hash = "";
|
|
16
|
+
current.searchParams.delete("action");
|
|
17
|
+
return current.toString();
|
|
18
|
+
}
|
|
19
|
+
} catch {
|
|
20
|
+
}
|
|
21
|
+
return PUBLIC_DOCBLOCKS_SHARE_URL;
|
|
22
|
+
}
|
|
23
|
+
function sharedDocumentFilename(selectedFile) {
|
|
24
|
+
const basename = selectedFile?.replace(/\\/gu, "/").split("/").pop() ?? "shared.md";
|
|
25
|
+
const stem = basename.replace(/\.md$/iu, "").replace(/[^A-Za-z0-9._-]+/gu, "-");
|
|
26
|
+
const bounded = stem.replace(/^-+|-+$/gu, "").slice(0, 80) || "shared";
|
|
27
|
+
return `${bounded}.md`;
|
|
28
|
+
}
|
|
29
|
+
async function createSharedDocumentArchive(markdown, selectedFile) {
|
|
30
|
+
const encoded = new TextEncoder().encode(markdown);
|
|
31
|
+
if (encoded.byteLength > SHARED_DOCUMENT_LIMITS.markdownBytes) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`This document is too large for a shared URL (maximum ${SHARED_DOCUMENT_LIMITS.markdownBytes.toLocaleString()} UTF-8 bytes).`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const [{ MemoryContentContainer }, { containerToZip }] = await Promise.all([
|
|
37
|
+
import("@bendyline/squisq/storage"),
|
|
38
|
+
import("@bendyline/squisq-formats/container")
|
|
39
|
+
]);
|
|
40
|
+
const container = new MemoryContentContainer();
|
|
41
|
+
await container.writeFile(sharedDocumentFilename(selectedFile), encoded, "text/markdown");
|
|
42
|
+
const blob = await containerToZip(container, { compression: "DEFLATE", compressionLevel: 9 });
|
|
43
|
+
return new Uint8Array(await blob.arrayBuffer());
|
|
44
|
+
}
|
|
45
|
+
function buildSharedDocumentUrl(baseUrl, archive, mode) {
|
|
46
|
+
return createSharedDocumentUrl(resolveSharedDocumentBaseUrl(baseUrl), archive, mode);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/Export/ShareDialog.tsx
|
|
50
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
51
|
+
var MODES = [
|
|
52
|
+
{ value: "", label: "Write (no default)" },
|
|
53
|
+
{ value: "slideshow", label: "Slideshow" },
|
|
54
|
+
{ value: "video", label: "Video" },
|
|
55
|
+
{ value: "page", label: "Page" },
|
|
56
|
+
{ value: "document", label: "Document" },
|
|
57
|
+
{ value: "narrate", label: "Narrate" }
|
|
58
|
+
];
|
|
59
|
+
function ShareDialog({ markdown, selectedFile, baseUrl, onClose }) {
|
|
60
|
+
const [mode, setMode] = useState("");
|
|
61
|
+
const [archive, setArchive] = useState(null);
|
|
62
|
+
const [archiveError, setArchiveError] = useState(null);
|
|
63
|
+
const [copyStatus, setCopyStatus] = useState("idle");
|
|
64
|
+
const linkRef = useRef(null);
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
let cancelled = false;
|
|
67
|
+
setArchive(null);
|
|
68
|
+
setArchiveError(null);
|
|
69
|
+
void createSharedDocumentArchive(markdown, selectedFile).then((nextArchive) => {
|
|
70
|
+
if (!cancelled) setArchive(nextArchive);
|
|
71
|
+
}).catch((error) => {
|
|
72
|
+
if (!cancelled) {
|
|
73
|
+
setArchiveError(
|
|
74
|
+
error instanceof Error ? error.message : "DocBlocks could not create the shared link."
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return () => {
|
|
79
|
+
cancelled = true;
|
|
80
|
+
};
|
|
81
|
+
}, [markdown, selectedFile]);
|
|
82
|
+
const linkResult = useMemo(() => {
|
|
83
|
+
if (!archive) return { url: "", error: archiveError };
|
|
84
|
+
try {
|
|
85
|
+
return { url: buildSharedDocumentUrl(baseUrl, archive, mode || null), error: null };
|
|
86
|
+
} catch (error) {
|
|
87
|
+
return {
|
|
88
|
+
url: "",
|
|
89
|
+
error: error instanceof Error ? error.message : "DocBlocks could not create the shared link."
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}, [archive, archiveError, baseUrl, mode]);
|
|
93
|
+
useEffect(() => setCopyStatus("idle"), [linkResult.url]);
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
const handleKeyDown = (event) => {
|
|
96
|
+
if (event.key === "Escape") onClose();
|
|
97
|
+
};
|
|
98
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
99
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
100
|
+
}, [onClose]);
|
|
101
|
+
const copyLink = useCallback(async () => {
|
|
102
|
+
if (!linkResult.url) return;
|
|
103
|
+
try {
|
|
104
|
+
if (navigator.clipboard?.writeText) {
|
|
105
|
+
await navigator.clipboard.writeText(linkResult.url);
|
|
106
|
+
} else {
|
|
107
|
+
linkRef.current?.focus();
|
|
108
|
+
linkRef.current?.select();
|
|
109
|
+
if (typeof document.execCommand !== "function" || !document.execCommand("copy")) {
|
|
110
|
+
throw new Error("Clipboard access is unavailable.");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
setCopyStatus("copied");
|
|
114
|
+
} catch {
|
|
115
|
+
linkRef.current?.focus();
|
|
116
|
+
linkRef.current?.select();
|
|
117
|
+
setCopyStatus("failed");
|
|
118
|
+
}
|
|
119
|
+
}, [linkResult.url]);
|
|
120
|
+
const isLong = linkResult.url.length > SHARED_DOCUMENT_LIMITS2.portableUrlCharacters;
|
|
121
|
+
return /* @__PURE__ */ jsx(
|
|
122
|
+
"div",
|
|
123
|
+
{
|
|
124
|
+
className: "db-dialog-overlay",
|
|
125
|
+
onClick: (event) => {
|
|
126
|
+
if (event.target === event.currentTarget) onClose();
|
|
127
|
+
},
|
|
128
|
+
children: /* @__PURE__ */ jsxs(
|
|
129
|
+
"div",
|
|
130
|
+
{
|
|
131
|
+
className: "db-dialog db-export-dialog db-share-dialog",
|
|
132
|
+
role: "dialog",
|
|
133
|
+
"aria-modal": "true",
|
|
134
|
+
"aria-labelledby": "db-share-dialog-title",
|
|
135
|
+
children: [
|
|
136
|
+
/* @__PURE__ */ jsxs("div", { className: "db-dialog-header", children: [
|
|
137
|
+
/* @__PURE__ */ jsx("h2", { className: "db-dialog-title", id: "db-share-dialog-title", children: "Share document via URL" }),
|
|
138
|
+
/* @__PURE__ */ jsx("button", { className: "db-dialog-close", type: "button", onClick: onClose, "aria-label": "Close", children: "\xD7" })
|
|
139
|
+
] }),
|
|
140
|
+
/* @__PURE__ */ jsxs("div", { className: "db-dialog-body", children: [
|
|
141
|
+
/* @__PURE__ */ jsx("div", { className: "db-share-warning", role: "note", children: "The contents of this document are embedded in the URL. Anyone with the link receives a copy of the document, so do not use it for secrets." }),
|
|
142
|
+
/* @__PURE__ */ jsxs("div", { className: "db-export-field", children: [
|
|
143
|
+
/* @__PURE__ */ jsx("label", { className: "db-export-label", htmlFor: "db-share-mode", children: "Default mode (optional)" }),
|
|
144
|
+
/* @__PURE__ */ jsx(
|
|
145
|
+
"select",
|
|
146
|
+
{
|
|
147
|
+
id: "db-share-mode",
|
|
148
|
+
className: "db-export-select",
|
|
149
|
+
value: mode,
|
|
150
|
+
onChange: (event) => setMode(event.target.value),
|
|
151
|
+
children: MODES.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, option.value || "write"))
|
|
152
|
+
}
|
|
153
|
+
),
|
|
154
|
+
/* @__PURE__ */ jsx("span", { className: "db-export-hint", children: "Without a default, the copied document opens in Write. Other choices open directly in Use." })
|
|
155
|
+
] }),
|
|
156
|
+
/* @__PURE__ */ jsxs("div", { className: "db-export-field", children: [
|
|
157
|
+
/* @__PURE__ */ jsx("label", { className: "db-export-label", htmlFor: "db-share-link", children: "Share link" }),
|
|
158
|
+
/* @__PURE__ */ jsx(
|
|
159
|
+
"textarea",
|
|
160
|
+
{
|
|
161
|
+
ref: linkRef,
|
|
162
|
+
id: "db-share-link",
|
|
163
|
+
className: "db-share-link",
|
|
164
|
+
value: linkResult.url,
|
|
165
|
+
readOnly: true,
|
|
166
|
+
rows: 3,
|
|
167
|
+
spellCheck: false,
|
|
168
|
+
"aria-describedby": "db-share-link-status",
|
|
169
|
+
placeholder: linkResult.error ? "" : "Creating link..."
|
|
170
|
+
}
|
|
171
|
+
),
|
|
172
|
+
/* @__PURE__ */ jsx(
|
|
173
|
+
"span",
|
|
174
|
+
{
|
|
175
|
+
id: "db-share-link-status",
|
|
176
|
+
className: `db-export-hint${isLong ? " db-share-length-warning" : ""}`,
|
|
177
|
+
children: linkResult.error ? linkResult.error : linkResult.url ? isLong ? `${linkResult.url.length.toLocaleString()} characters. Links longer than 4,096 characters may be truncated by messaging or email tools.` : `${linkResult.url.length.toLocaleString()} characters.` : "Compressing this document into a Markdown-only DBK..."
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
] }),
|
|
181
|
+
/* @__PURE__ */ jsx("p", { className: "db-share-temporary-note", children: "Opening the link creates a temporary workspace. Changes there do not alter this document or the link." })
|
|
182
|
+
] }),
|
|
183
|
+
/* @__PURE__ */ jsxs("div", { className: "db-export-footer", children: [
|
|
184
|
+
/* @__PURE__ */ jsx(
|
|
185
|
+
"button",
|
|
186
|
+
{
|
|
187
|
+
className: "db-export-btn db-export-btn--secondary",
|
|
188
|
+
type: "button",
|
|
189
|
+
onClick: onClose,
|
|
190
|
+
children: "Close"
|
|
191
|
+
}
|
|
192
|
+
),
|
|
193
|
+
/* @__PURE__ */ jsx(
|
|
194
|
+
"button",
|
|
195
|
+
{
|
|
196
|
+
className: "db-export-btn db-export-btn--primary",
|
|
197
|
+
type: "button",
|
|
198
|
+
onClick: () => void copyLink(),
|
|
199
|
+
disabled: !linkResult.url,
|
|
200
|
+
children: copyStatus === "copied" ? "Copied" : copyStatus === "failed" ? "Select and copy" : "Copy link"
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
] })
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
export {
|
|
211
|
+
ShareDialog
|
|
212
|
+
};
|
|
213
|
+
//# sourceMappingURL=ShareDialog-63ENBEDZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Export/ShareDialog.tsx","../src/Export/shared-document.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { SHARED_DOCUMENT_LIMITS, type SharedDocumentMode } from '@bendyline/docblocks/share';\nimport { buildSharedDocumentUrl, createSharedDocumentArchive } from './shared-document.js';\n\nexport interface ShareDialogProps {\n markdown: string;\n selectedFile: string | null;\n baseUrl: string;\n onClose: () => void;\n}\n\nconst MODES: ReadonlyArray<{ value: SharedDocumentMode | ''; label: string }> = [\n { value: '', label: 'Write (no default)' },\n { value: 'slideshow', label: 'Slideshow' },\n { value: 'video', label: 'Video' },\n { value: 'page', label: 'Page' },\n { value: 'document', label: 'Document' },\n { value: 'narrate', label: 'Narrate' },\n];\n\nexport function ShareDialog({ markdown, selectedFile, baseUrl, onClose }: ShareDialogProps) {\n const [mode, setMode] = useState<SharedDocumentMode | ''>('');\n const [archive, setArchive] = useState<Uint8Array | null>(null);\n const [archiveError, setArchiveError] = useState<string | null>(null);\n const [copyStatus, setCopyStatus] = useState<'idle' | 'copied' | 'failed'>('idle');\n const linkRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n let cancelled = false;\n setArchive(null);\n setArchiveError(null);\n void createSharedDocumentArchive(markdown, selectedFile)\n .then((nextArchive) => {\n if (!cancelled) setArchive(nextArchive);\n })\n .catch((error: unknown) => {\n if (!cancelled) {\n setArchiveError(\n error instanceof Error ? error.message : 'DocBlocks could not create the shared link.',\n );\n }\n });\n return () => {\n cancelled = true;\n };\n }, [markdown, selectedFile]);\n\n const linkResult = useMemo(() => {\n if (!archive) return { url: '', error: archiveError };\n try {\n return { url: buildSharedDocumentUrl(baseUrl, archive, mode || null), error: null };\n } catch (error: unknown) {\n return {\n url: '',\n error:\n error instanceof Error ? error.message : 'DocBlocks could not create the shared link.',\n };\n }\n }, [archive, archiveError, baseUrl, mode]);\n\n useEffect(() => setCopyStatus('idle'), [linkResult.url]);\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') onClose();\n };\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [onClose]);\n\n const copyLink = useCallback(async () => {\n if (!linkResult.url) return;\n try {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(linkResult.url);\n } else {\n linkRef.current?.focus();\n linkRef.current?.select();\n if (typeof document.execCommand !== 'function' || !document.execCommand('copy')) {\n throw new Error('Clipboard access is unavailable.');\n }\n }\n setCopyStatus('copied');\n } catch {\n linkRef.current?.focus();\n linkRef.current?.select();\n setCopyStatus('failed');\n }\n }, [linkResult.url]);\n\n const isLong = linkResult.url.length > SHARED_DOCUMENT_LIMITS.portableUrlCharacters;\n\n return (\n <div\n className=\"db-dialog-overlay\"\n onClick={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n className=\"db-dialog db-export-dialog db-share-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"db-share-dialog-title\"\n >\n <div className=\"db-dialog-header\">\n <h2 className=\"db-dialog-title\" id=\"db-share-dialog-title\">\n Share document via URL\n </h2>\n <button className=\"db-dialog-close\" type=\"button\" onClick={onClose} aria-label=\"Close\">\n ×\n </button>\n </div>\n\n <div className=\"db-dialog-body\">\n <div className=\"db-share-warning\" role=\"note\">\n The contents of this document are embedded in the URL. Anyone with the link receives a\n copy of the document, so do not use it for secrets.\n </div>\n\n <div className=\"db-export-field\">\n <label className=\"db-export-label\" htmlFor=\"db-share-mode\">\n Default mode (optional)\n </label>\n <select\n id=\"db-share-mode\"\n className=\"db-export-select\"\n value={mode}\n onChange={(event) => setMode(event.target.value as SharedDocumentMode | '')}\n >\n {MODES.map((option) => (\n <option key={option.value || 'write'} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n <span className=\"db-export-hint\">\n Without a default, the copied document opens in Write. Other choices open directly in\n Use.\n </span>\n </div>\n\n <div className=\"db-export-field\">\n <label className=\"db-export-label\" htmlFor=\"db-share-link\">\n Share link\n </label>\n <textarea\n ref={linkRef}\n id=\"db-share-link\"\n className=\"db-share-link\"\n value={linkResult.url}\n readOnly\n rows={3}\n spellCheck={false}\n aria-describedby=\"db-share-link-status\"\n placeholder={linkResult.error ? '' : 'Creating link...'}\n />\n <span\n id=\"db-share-link-status\"\n className={`db-export-hint${isLong ? ' db-share-length-warning' : ''}`}\n >\n {linkResult.error\n ? linkResult.error\n : linkResult.url\n ? isLong\n ? `${linkResult.url.length.toLocaleString()} characters. Links longer than 4,096 characters may be truncated by messaging or email tools.`\n : `${linkResult.url.length.toLocaleString()} characters.`\n : 'Compressing this document into a Markdown-only DBK...'}\n </span>\n </div>\n\n <p className=\"db-share-temporary-note\">\n Opening the link creates a temporary workspace. Changes there do not alter this document\n or the link.\n </p>\n </div>\n\n <div className=\"db-export-footer\">\n <button\n className=\"db-export-btn db-export-btn--secondary\"\n type=\"button\"\n onClick={onClose}\n >\n Close\n </button>\n <button\n className=\"db-export-btn db-export-btn--primary\"\n type=\"button\"\n onClick={() => void copyLink()}\n disabled={!linkResult.url}\n >\n {copyStatus === 'copied'\n ? 'Copied'\n : copyStatus === 'failed'\n ? 'Select and copy'\n : 'Copy link'}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import {\n SHARED_DOCUMENT_LIMITS,\n createSharedDocumentUrl,\n type SharedDocumentMode,\n} from '@bendyline/docblocks/share';\n\nexport const PUBLIC_DOCBLOCKS_SHARE_URL = 'https://bendyline.github.io/docblocks/';\n\n/** Use the current web deployment, but never emit an unopenable app:// link. */\nexport function resolveSharedDocumentBaseUrl(currentUrl: string): string {\n try {\n const current = new URL(currentUrl);\n if (current.protocol === 'http:' || current.protocol === 'https:') {\n current.hash = '';\n current.searchParams.delete('action');\n return current.toString();\n }\n } catch {\n // Fall through to the canonical public site.\n }\n return PUBLIC_DOCBLOCKS_SHARE_URL;\n}\n\nexport function sharedDocumentFilename(selectedFile: string | null): string {\n const basename = selectedFile?.replace(/\\\\/gu, '/').split('/').pop() ?? 'shared.md';\n const stem = basename.replace(/\\.md$/iu, '').replace(/[^A-Za-z0-9._-]+/gu, '-');\n const bounded = stem.replace(/^-+|-+$/gu, '').slice(0, 80) || 'shared';\n return `${bounded}.md`;\n}\n\n/** Create a compressed DBK containing exactly one bounded Markdown file. */\nexport async function createSharedDocumentArchive(\n markdown: string,\n selectedFile: string | null,\n): Promise<Uint8Array> {\n const encoded = new TextEncoder().encode(markdown);\n if (encoded.byteLength > SHARED_DOCUMENT_LIMITS.markdownBytes) {\n throw new Error(\n `This document is too large for a shared URL (maximum ${SHARED_DOCUMENT_LIMITS.markdownBytes.toLocaleString()} UTF-8 bytes).`,\n );\n }\n\n const [{ MemoryContentContainer }, { containerToZip }] = await Promise.all([\n import('@bendyline/squisq/storage'),\n import('@bendyline/squisq-formats/container'),\n ]);\n const container = new MemoryContentContainer();\n await container.writeFile(sharedDocumentFilename(selectedFile), encoded, 'text/markdown');\n const blob = await containerToZip(container, { compression: 'DEFLATE', compressionLevel: 9 });\n return new Uint8Array(await blob.arrayBuffer());\n}\n\nexport function buildSharedDocumentUrl(\n baseUrl: string,\n archive: Uint8Array,\n mode: SharedDocumentMode | null,\n): string {\n return createSharedDocumentUrl(resolveSharedDocumentBaseUrl(baseUrl), archive, mode);\n}\n"],"mappings":"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","names":["SHARED_DOCUMENT_LIMITS","SHARED_DOCUMENT_LIMITS"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/Export/transform-summaries.ts
|
|
2
|
+
var transformStyleSummariesPromise = null;
|
|
3
|
+
function loadTransformStyleSummaries() {
|
|
4
|
+
transformStyleSummariesPromise ?? (transformStyleSummariesPromise = import("@bendyline/squisq/transform").then(
|
|
5
|
+
({ getTransformStyleSummaries }) => getTransformStyleSummaries()
|
|
6
|
+
));
|
|
7
|
+
return transformStyleSummariesPromise;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
loadTransformStyleSummaries
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=chunk-4XXSWN3T.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Export/transform-summaries.ts"],"sourcesContent":["export interface ExportSummaryOption {\n id: string;\n name: string;\n description?: string;\n}\n\nlet transformStyleSummariesPromise: Promise<ExportSummaryOption[]> | null = null;\n\nexport function loadTransformStyleSummaries(): Promise<ExportSummaryOption[]> {\n transformStyleSummariesPromise ??= import('@bendyline/squisq/transform').then(\n ({ getTransformStyleSummaries }) => getTransformStyleSummaries(),\n );\n return transformStyleSummariesPromise;\n}\n"],"mappings":";AAMA,IAAI,iCAAwE;AAErE,SAAS,8BAA8D;AAC5E,sEAAmC,OAAO,6BAA6B,EAAE;AAAA,IACvE,CAAC,EAAE,2BAA2B,MAAM,2BAA2B;AAAA,EACjE;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/Git/useMenuKeyboard.ts
|
|
2
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
3
|
+
function useMenuKeyboard(open, setOpen) {
|
|
4
|
+
const menuRef = useRef(null);
|
|
5
|
+
const triggerRef = useRef(null);
|
|
6
|
+
const pendingFocusRef = useRef("none");
|
|
7
|
+
const items = useCallback(
|
|
8
|
+
() => [...menuRef.current?.querySelectorAll('[role="menuitem"]') ?? []].filter(
|
|
9
|
+
(item) => !item.disabled
|
|
10
|
+
),
|
|
11
|
+
[]
|
|
12
|
+
);
|
|
13
|
+
const focusItem = useCallback(
|
|
14
|
+
(index) => {
|
|
15
|
+
const all = items();
|
|
16
|
+
if (all.length === 0) return;
|
|
17
|
+
all[(index % all.length + all.length) % all.length]?.focus({ preventScroll: true });
|
|
18
|
+
},
|
|
19
|
+
[items]
|
|
20
|
+
);
|
|
21
|
+
const closeMenu = useCallback(
|
|
22
|
+
(returnFocus) => {
|
|
23
|
+
pendingFocusRef.current = "none";
|
|
24
|
+
setOpen(false);
|
|
25
|
+
if (returnFocus) triggerRef.current?.focus();
|
|
26
|
+
},
|
|
27
|
+
[setOpen]
|
|
28
|
+
);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!open || pendingFocusRef.current === "none") return;
|
|
31
|
+
const where = pendingFocusRef.current;
|
|
32
|
+
pendingFocusRef.current = "none";
|
|
33
|
+
focusItem(where === "last" ? items().length - 1 : 0);
|
|
34
|
+
}, [open, focusItem, items]);
|
|
35
|
+
const handleTriggerKeyDown = useCallback(
|
|
36
|
+
(event) => {
|
|
37
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
38
|
+
event.preventDefault();
|
|
39
|
+
pendingFocusRef.current = event.key === "ArrowUp" ? "last" : "first";
|
|
40
|
+
setOpen(true);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
44
|
+
if (!open) pendingFocusRef.current = "first";
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
[open, setOpen]
|
|
48
|
+
);
|
|
49
|
+
const handleMenuKeyDown = useCallback(
|
|
50
|
+
(event) => {
|
|
51
|
+
if (event.key === "Escape" || event.key === "Tab") {
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
event.stopPropagation();
|
|
54
|
+
closeMenu(true);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const all = items();
|
|
58
|
+
if (all.length === 0) return;
|
|
59
|
+
const current = all.indexOf(document.activeElement);
|
|
60
|
+
switch (event.key) {
|
|
61
|
+
case "ArrowDown":
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
focusItem(current + 1);
|
|
64
|
+
break;
|
|
65
|
+
case "ArrowUp":
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
focusItem(current - 1);
|
|
68
|
+
break;
|
|
69
|
+
case "Home":
|
|
70
|
+
event.preventDefault();
|
|
71
|
+
focusItem(0);
|
|
72
|
+
break;
|
|
73
|
+
case "End":
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
focusItem(all.length - 1);
|
|
76
|
+
break;
|
|
77
|
+
default:
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
[closeMenu, focusItem, items]
|
|
82
|
+
);
|
|
83
|
+
return { menuRef, triggerRef, handleMenuKeyDown, handleTriggerKeyDown, closeMenu };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
useMenuKeyboard
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=chunk-57ZJJOC5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Git/useMenuKeyboard.ts"],"sourcesContent":["/**\n * useMenuKeyboard — the WAI-ARIA menu-button key contract for a trigger +\n * `role=\"menu\"` dropdown pair.\n *\n * Trigger: ArrowDown / ArrowUp / Enter / Space open the menu and focus\n * its first (or last) item.\n * Menu: ArrowDown/ArrowUp cycle, Home/End jump, Escape closes and\n * returns focus to the trigger, Tab closes.\n *\n * Items are not tab stops (`tabIndex={-1}`); the trigger is the single tab\n * stop, and focus moves within the menu by arrow key.\n *\n * NOTE: five dropdowns in this package share this contract — the two git\n * ones (which use this), plus AppMenu, ExportToolbarControls and\n * WorkspaceSettingsButton, which are owned elsewhere and still lack it.\n * This hook lives under Git/ only because that is the scope it was written\n * in; it has no git dependency and should be lifted to a shared location\n * and applied to the other three.\n */\n\nimport { useCallback, useEffect, useRef } from 'react';\n\nexport interface MenuKeyboard {\n /** Attach to the `role=\"menu\"` element. */\n menuRef: React.RefObject<HTMLDivElement>;\n /** Attach to the button that opens the menu. */\n triggerRef: React.RefObject<HTMLButtonElement>;\n handleMenuKeyDown: (event: React.KeyboardEvent) => void;\n handleTriggerKeyDown: (event: React.KeyboardEvent) => void;\n /** Close from a click handler without stealing focus back. */\n closeMenu: (returnFocus: boolean) => void;\n}\n\nexport function useMenuKeyboard(open: boolean, setOpen: (open: boolean) => void): MenuKeyboard {\n const menuRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n /** Where to land when the menu opens: keyboard users must go inside it. */\n const pendingFocusRef = useRef<'none' | 'first' | 'last'>('none');\n\n const items = useCallback(\n () =>\n [...(menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]') ?? [])].filter(\n (item) => !item.disabled,\n ),\n [],\n );\n\n const focusItem = useCallback(\n (index: number) => {\n const all = items();\n if (all.length === 0) return;\n all[((index % all.length) + all.length) % all.length]?.focus({ preventScroll: true });\n },\n [items],\n );\n\n const closeMenu = useCallback(\n (returnFocus: boolean) => {\n pendingFocusRef.current = 'none';\n setOpen(false);\n if (returnFocus) triggerRef.current?.focus();\n },\n [setOpen],\n );\n\n // Land inside the menu once it has rendered, but only when the keyboard\n // opened it — a pointer user's focus should stay where they clicked.\n useEffect(() => {\n if (!open || pendingFocusRef.current === 'none') return;\n const where = pendingFocusRef.current;\n pendingFocusRef.current = 'none';\n focusItem(where === 'last' ? items().length - 1 : 0);\n }, [open, focusItem, items]);\n\n const handleTriggerKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n pendingFocusRef.current = event.key === 'ArrowUp' ? 'last' : 'first';\n setOpen(true);\n return;\n }\n // Enter/Space already activate the button (which toggles the menu);\n // this only says where focus should land when they do.\n if (event.key === 'Enter' || event.key === ' ') {\n if (!open) pendingFocusRef.current = 'first';\n }\n },\n [open, setOpen],\n );\n\n const handleMenuKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === 'Escape' || event.key === 'Tab') {\n event.preventDefault();\n event.stopPropagation();\n closeMenu(true);\n return;\n }\n const all = items();\n if (all.length === 0) return;\n const current = all.indexOf(document.activeElement as HTMLButtonElement);\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusItem(current + 1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusItem(current - 1);\n break;\n case 'Home':\n event.preventDefault();\n focusItem(0);\n break;\n case 'End':\n event.preventDefault();\n focusItem(all.length - 1);\n break;\n default:\n break;\n }\n },\n [closeMenu, focusItem, items],\n );\n\n return { menuRef, triggerRef, handleMenuKeyDown, handleTriggerKeyDown, closeMenu };\n}\n"],"mappings":";AAoBA,SAAS,aAAa,WAAW,cAAc;AAaxC,SAAS,gBAAgB,MAAe,SAAgD;AAC7F,QAAM,UAAU,OAAuB,IAAI;AAC3C,QAAM,aAAa,OAA0B,IAAI;AAEjD,QAAM,kBAAkB,OAAkC,MAAM;AAEhE,QAAM,QAAQ;AAAA,IACZ,MACE,CAAC,GAAI,QAAQ,SAAS,iBAAoC,mBAAmB,KAAK,CAAC,CAAE,EAAE;AAAA,MACrF,CAAC,SAAS,CAAC,KAAK;AAAA,IAClB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,YAAY;AAAA,IAChB,CAAC,UAAkB;AACjB,YAAM,MAAM,MAAM;AAClB,UAAI,IAAI,WAAW,EAAG;AACtB,WAAM,QAAQ,IAAI,SAAU,IAAI,UAAU,IAAI,MAAM,GAAG,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,IACtF;AAAA,IACA,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,YAAY;AAAA,IAChB,CAAC,gBAAyB;AACxB,sBAAgB,UAAU;AAC1B,cAAQ,KAAK;AACb,UAAI,YAAa,YAAW,SAAS,MAAM;AAAA,IAC7C;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAIA,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ,gBAAgB,YAAY,OAAQ;AACjD,UAAM,QAAQ,gBAAgB;AAC9B,oBAAgB,UAAU;AAC1B,cAAU,UAAU,SAAS,MAAM,EAAE,SAAS,IAAI,CAAC;AAAA,EACrD,GAAG,CAAC,MAAM,WAAW,KAAK,CAAC;AAE3B,QAAM,uBAAuB;AAAA,IAC3B,CAAC,UAA+B;AAC9B,UAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;AACxD,cAAM,eAAe;AACrB,wBAAgB,UAAU,MAAM,QAAQ,YAAY,SAAS;AAC7D,gBAAQ,IAAI;AACZ;AAAA,MACF;AAGA,UAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;AAC9C,YAAI,CAAC,KAAM,iBAAgB,UAAU;AAAA,MACvC;AAAA,IACF;AAAA,IACA,CAAC,MAAM,OAAO;AAAA,EAChB;AAEA,QAAM,oBAAoB;AAAA,IACxB,CAAC,UAA+B;AAC9B,UAAI,MAAM,QAAQ,YAAY,MAAM,QAAQ,OAAO;AACjD,cAAM,eAAe;AACrB,cAAM,gBAAgB;AACtB,kBAAU,IAAI;AACd;AAAA,MACF;AACA,YAAM,MAAM,MAAM;AAClB,UAAI,IAAI,WAAW,EAAG;AACtB,YAAM,UAAU,IAAI,QAAQ,SAAS,aAAkC;AACvE,cAAQ,MAAM,KAAK;AAAA,QACjB,KAAK;AACH,gBAAM,eAAe;AACrB,oBAAU,UAAU,CAAC;AACrB;AAAA,QACF,KAAK;AACH,gBAAM,eAAe;AACrB,oBAAU,UAAU,CAAC;AACrB;AAAA,QACF,KAAK;AACH,gBAAM,eAAe;AACrB,oBAAU,CAAC;AACX;AAAA,QACF,KAAK;AACH,gBAAM,eAAe;AACrB,oBAAU,IAAI,SAAS,CAAC;AACxB;AAAA,QACF;AACE;AAAA,MACJ;AAAA,IACF;AAAA,IACA,CAAC,WAAW,WAAW,KAAK;AAAA,EAC9B;AAEA,SAAO,EAAE,SAAS,YAAY,mBAAmB,sBAAsB,UAAU;AACnF;","names":[]}
|