@bendyline/docblocks-react 2.1.0 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +12 -3
  2. package/dist/ExportDialog-VYATD5UC.js +9 -0
  3. package/dist/{ExportToolbarControls-GHAOJMH6.js → ExportToolbarControls-C46GMPKC.js} +70 -41
  4. package/dist/{GitToolbarControl-GNMRVKWQ.js → GitToolbarControl-FW3BZFXV.js} +2 -3
  5. package/dist/{GitUI-VHOBQY43.js → GitUI-GMH3PAYL.js} +3 -4
  6. package/dist/LazyEditorShell-LU4QFPDX.js +5 -0
  7. package/dist/{ShareDialog-63ENBEDZ.js → ShareDialog-PAMOQQFB.js} +0 -1
  8. package/dist/{chunk-UNYZQXWR.js → chunk-3CZ27FOA.js} +45 -10
  9. package/dist/{chunk-FEWQUQML.js → chunk-3QSZY74C.js} +1 -2
  10. package/dist/chunk-BI7NVU6T.js +31 -0
  11. package/dist/{chunk-VHDP4IPL.js → chunk-BPGEBGAN.js} +0 -1
  12. package/dist/{chunk-DD4VFJQI.js → chunk-EBWYGTN7.js} +2 -1
  13. package/dist/{chunk-ZI56BNB7.js → chunk-GHQ4X7KM.js} +27 -7
  14. package/dist/{chunk-5A4KEWKT.js → chunk-HFYPTTCH.js} +0 -1
  15. package/dist/{chunk-FMGTHSTX.js → chunk-LG6HAWCK.js} +0 -1
  16. package/dist/{chunk-57ZJJOC5.js → chunk-TFMO7EVO.js} +0 -1
  17. package/dist/{chunk-4XXSWN3T.js → chunk-YBEYTVU2.js} +0 -1
  18. package/dist/editor.js +1 -2
  19. package/dist/export/index.d.ts +18 -8
  20. package/dist/export/index.js +10 -7
  21. package/dist/index.d.ts +16 -7
  22. package/dist/index.js +359 -103
  23. package/dist/run-export-Z5BVFLIR.js +9 -0
  24. package/dist/settings/index.js +2 -3
  25. package/package.json +8 -8
  26. package/src/styles/docblocks.css +485 -9
  27. package/dist/ExportDialog-7LDIXJZ3.js +0 -10
  28. package/dist/ExportDialog-7LDIXJZ3.js.map +0 -1
  29. package/dist/ExportToolbarControls-GHAOJMH6.js.map +0 -1
  30. package/dist/GitToolbarControl-GNMRVKWQ.js.map +0 -1
  31. package/dist/GitUI-VHOBQY43.js.map +0 -1
  32. package/dist/LazyEditorShell-EF2BWRXU.js +0 -6
  33. package/dist/LazyEditorShell-EF2BWRXU.js.map +0 -1
  34. package/dist/ShareDialog-63ENBEDZ.js.map +0 -1
  35. package/dist/chunk-4XXSWN3T.js.map +0 -1
  36. package/dist/chunk-57ZJJOC5.js.map +0 -1
  37. package/dist/chunk-5A4KEWKT.js.map +0 -1
  38. package/dist/chunk-DD4VFJQI.js.map +0 -1
  39. package/dist/chunk-FEWQUQML.js.map +0 -1
  40. package/dist/chunk-FMGTHSTX.js.map +0 -1
  41. package/dist/chunk-UNYZQXWR.js.map +0 -1
  42. package/dist/chunk-VHDP4IPL.js.map +0 -1
  43. package/dist/chunk-ZI56BNB7.js.map +0 -1
  44. package/dist/editor.js.map +0 -1
  45. package/dist/export/index.js.map +0 -1
  46. package/dist/index.js.map +0 -1
  47. package/dist/run-export-ICTZITXC.js +0 -10
  48. package/dist/run-export-ICTZITXC.js.map +0 -1
  49. package/dist/settings/index.js.map +0 -1
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/FileExplorer/FileExplorer.tsx","../src/FileExplorer/useFileTree.ts","../src/FileExplorer/FileTreeNode.tsx","../src/icons.tsx","../src/FileExplorer/tree-keyboard.ts","../src/WorkspacePicker/WorkspacePicker.tsx","../src/DocBlocksShell/DocBlocksShell.tsx","../src/AppMenu/AppMenu.tsx","../src/WorkspacePicker/WorkspaceSettingsButton.tsx","../src/preferences/versioning.ts","../src/WorkspacePicker/WorkspaceSettingsDialog.tsx","../src/hooks/useDocumentSession.ts","../src/Export/DeferredExportToolbarControls.tsx","../src/Git/useGit.ts","../src/Git/useGitStatus.ts","../src/provider-lease.ts","../src/DocBlocksShell/document-title.ts","../src/DocBlocksShell/dbk-import.ts","../src/DocBlocksShell/import-files.ts","../src/DocBlocksShell/provider-io.ts","../src/components/usePromptDialog.ts","../src/components/PromptDialog.tsx","../src/components/useConfirmDialog.ts","../src/components/ConfirmDialog.tsx","../src/DocBlocksShell/resolve-theme.ts","../src/DocBlocksShell/issue-report.ts","../src/DocBlocksShell/last-state.ts","../src/DocBlocksShell/shell-preferences.ts","../src/DocBlocksShell/UpdateAvailableNotice.tsx","../src/DocBlocksShell/useDocumentLinkProvider.ts","../src/DocBlocksShell/document-links.ts","../src/DocBlocksShell/workspace-authority-barrier.ts","../src/DocBlocksShell/transient-workspace-move.ts","../src/Export/export-destination.ts"],"sourcesContent":["/**\n * FileExplorer — tree component rendering FileSystemProvider contents.\n *\n * Shows a file/folder tree with expand/collapse, selection, and a toolbar\n * for creating new files/folders.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n isFileSystemMoveStateError,\n parseWorkspacePath,\n type FileSystemProvider,\n type FileSystemEntry,\n} from '@bendyline/docblocks/filesystem';\nimport { useFileTree } from './useFileTree.js';\nimport {\n FileTreeNode,\n type FileTreeNodeBadge,\n type FileTreeNodeGitActions,\n} from './FileTreeNode.js';\nimport {\n flattenVisibleRows,\n resolveActiveRow,\n treeKeyAction,\n TREE_NAV_KEYS,\n} from './tree-keyboard.js';\nimport { NewFileIcon, NewFolderIcon } from '../icons.js';\nimport { useGitContext } from '../Git/GitContext.js';\nimport { BADGE_GLYPHS, BADGE_LABELS, isFileDirty } from '../Git/git-status.js';\n\nconst SUPPORTED_EXTENSIONS = new Set(['.txt', '.md', '.docx', '.pdf', '.dbk', '.zip']);\nconst INTERNAL_DRAG_TYPE = 'application/x-docblocks-entry';\n/** Ties the new-item input to its error message for assistive tech. */\nconst NEW_ITEM_ERROR_ID = 'db-new-item-error';\n\nexport type FileTreeChange =\n | { type: 'create'; path: string; kind?: 'file' | 'directory' }\n | { type: 'delete'; path: string; kind: 'file' | 'directory' }\n | {\n type: 'move';\n oldPath: string;\n newPath: string;\n kind: 'file' | 'directory';\n };\n\nexport type FileTreeMutationHandler = (\n change: FileTreeChange,\n mutate: () => Promise<void>,\n) => Promise<void>;\n\nexport interface WorkspaceMoveDestination {\n id: string;\n name: string;\n}\n\nfunction normalisePath(path: string): string {\n return parseWorkspacePath(path);\n}\n\nfunction hasEquivalentPath(paths: ReadonlySet<string>, path: string): boolean {\n const canonical = normalisePath(path);\n return (\n paths.has(path) || paths.has(canonical) || (canonical !== '' && paths.has(`/${canonical}`))\n );\n}\n\nfunction getEquivalentPathValue<T>(values: ReadonlyMap<string, T>, path: string): T | undefined {\n const canonical = normalisePath(path);\n return values.get(path) ?? values.get(canonical) ?? values.get(`/${canonical}`);\n}\n\nfunction parentPath(path: string): string {\n const clean = normalisePath(path);\n const slash = clean.lastIndexOf('/');\n return slash < 0 ? '' : clean.slice(0, slash);\n}\n\nfunction pathInDirectory(entry: FileSystemEntry, directoryPath: string): string {\n const prefix = directoryPath.replace(/\\/+$/, '');\n if (prefix) return `${prefix}/${entry.name}`;\n return entry.path.startsWith('/') ? `/${entry.name}` : entry.name;\n}\n\nfunction canMoveTo(entry: FileSystemEntry, directoryPath: string): boolean {\n const source = normalisePath(entry.path);\n const target = normalisePath(directoryPath);\n if (parentPath(source) === target) return false;\n if (entry.kind === 'directory' && (target === source || target.startsWith(`${source}/`))) {\n return false;\n }\n return true;\n}\n\nfunction isInternalDrag(dataTransfer: DataTransfer): boolean {\n return Array.from(dataTransfer.types).includes(INTERNAL_DRAG_TYPE);\n}\n\n/**\n * Hide dot-entries (`.git`, `.gitignore`, `.DS_Store`, …) — never user\n * documents — and auto-generated `<basename>_files/` companion folders,\n * which hold per-document images and version snapshots (useful to the\n * editor, noisy in the user-facing file list). Everything still exists on\n * disk; we just don't surface it in the explorer.\n */\nfunction isHiddenEntry(entry: FileSystemEntry): boolean {\n const name = entry.path.replace(/^\\/+/, '').split('/').pop() ?? '';\n if (name.startsWith('.')) return true;\n return entry.kind === 'directory' && name.endsWith('_files');\n}\n\nfunction filterVisible(entries: FileSystemEntry[]): FileSystemEntry[] {\n return entries.filter((e) => !isHiddenEntry(e));\n}\n\nexport interface FileExplorerProps {\n /** The filesystem to display. */\n provider: FileSystemProvider | null;\n /** Active document to select and reveal by expanding all ancestor folders. */\n activeFilePath?: string | null;\n /** Called when any entry is selected (file or directory). */\n onSelect?: (path: string, kind: 'file' | 'directory') => void;\n /**\n * Wraps destructive tree mutations so the active document session can\n * flush, cancel, or retarget itself before storage changes.\n */\n onTreeMutation?: FileTreeMutationHandler;\n /** Called after any mutation, with move details when paths change. */\n onTreeChange?: (change?: FileTreeChange) => void;\n /** Called when supported files are dropped onto the explorer. */\n onImportFiles?: (files: File[]) => void;\n /**\n * Ask the user to confirm an irreversible delete. Resolve `false` to abort.\n * Hosts with their own dialog pass it here; otherwise the tree falls back to\n * a native prompt rather than deleting unasked.\n */\n confirmDelete?: (message: string) => boolean | Promise<boolean>;\n /** Persisted workspaces that can receive the current transient workspace. */\n moveDestinations?: readonly WorkspaceMoveDestination[];\n /** When provided, shows the transient-workspace move action above the tree. */\n onMoveToWorkspace?: (workspaceId: string) => Promise<void>;\n /** Optional className for the root element. */\n className?: string;\n}\n\nexport function FileExplorer({\n provider,\n activeFilePath,\n onSelect,\n onTreeMutation,\n onTreeChange,\n onImportFiles,\n confirmDelete,\n moveDestinations = [],\n onMoveToWorkspace,\n className,\n}: FileExplorerProps) {\n const tree = useFileTree(provider);\n const { childEntries } = tree as typeof tree & {\n childEntries: Map<string, FileSystemEntry[]>;\n };\n const { reveal } = tree;\n // Null on surfaces without git (site, tests) — everything degrades.\n const git = useGitContext();\n\n const [newItemName, setNewItemName] = useState('');\n const [newItemType, setNewItemType] = useState<'file' | 'directory' | null>(null);\n const [newItemCreationPending, setNewItemCreationPending] = useState(false);\n const newItemCreationPendingRef = useRef(false);\n /** Failure from the new-file/new-folder form — surfaced beside its input. */\n const [newItemError, setNewItemError] = useState<string | null>(null);\n const [dragOver, setDragOver] = useState(false);\n const [draggedEntry, setDraggedEntry] = useState<FileSystemEntry | null>(null);\n const [dropTarget, setDropTarget] = useState<string | null>(null);\n const [moveError, setMoveError] = useState<string | null>(null);\n const [movePanelOpen, setMovePanelOpen] = useState(false);\n const [moveDestinationId, setMoveDestinationId] = useState(moveDestinations[0]?.id ?? '');\n const [movingToWorkspace, setMovingToWorkspace] = useState(false);\n const [moveWorkspaceError, setMoveWorkspaceError] = useState<string | null>(null);\n const dragCounter = useRef(0);\n /** Row holding the tree's single tab stop; null until one is resolved. */\n const [activePath, setActivePath] = useState<string | null>(null);\n const treeRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (moveDestinations.some((destination) => destination.id === moveDestinationId)) return;\n setMoveDestinationId(moveDestinations[0]?.id ?? '');\n }, [moveDestinationId, moveDestinations]);\n\n useEffect(() => {\n if (activeFilePath) reveal(activeFilePath, 'file');\n }, [activeFilePath, provider, reveal]);\n\n const hasSupported = useCallback((dt: DataTransfer): boolean => {\n for (const item of Array.from(dt.items)) {\n if (item.kind !== 'file') continue;\n const name = (item as DataTransferItem & { getAsFile(): File | null }).getAsFile?.()?.name;\n // During dragover the filename may not be available, so accept broadly\n if (!name) return true;\n const ext = name.slice(name.lastIndexOf('.')).toLowerCase();\n if (SUPPORTED_EXTENSIONS.has(ext)) return true;\n }\n return dt.items.length > 0;\n }, []);\n\n const handleDragEnter = useCallback(\n (e: React.DragEvent) => {\n if (isInternalDrag(e.dataTransfer)) return;\n e.preventDefault();\n dragCounter.current += 1;\n if (hasSupported(e.dataTransfer)) setDragOver(true);\n },\n [hasSupported, dragCounter],\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n if (isInternalDrag(e.dataTransfer)) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n }, []);\n\n const handleDragLeave = useCallback(\n (e: React.DragEvent) => {\n if (isInternalDrag(e.dataTransfer)) return;\n e.preventDefault();\n dragCounter.current -= 1;\n if (dragCounter.current <= 0) {\n dragCounter.current = 0;\n setDragOver(false);\n }\n },\n [dragCounter],\n );\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n if (isInternalDrag(e.dataTransfer)) return;\n e.preventDefault();\n dragCounter.current = 0;\n setDragOver(false);\n const supported = Array.from(e.dataTransfer.files).filter((f) => {\n const ext = f.name.slice(f.name.lastIndexOf('.')).toLowerCase();\n return SUPPORTED_EXTENSIONS.has(ext);\n });\n if (supported.length > 0) onImportFiles?.(supported);\n },\n [onImportFiles],\n );\n\n const handleSelect = useCallback(\n (path: string) => {\n // Determine kind from entries (root + children)\n const findKind = (p: string): 'file' | 'directory' => {\n for (const e of tree.entries) {\n if (e.path === p) return e.kind;\n }\n for (const children of childEntries.values()) {\n for (const e of children) {\n if (e.path === p) return e.kind;\n }\n }\n return 'file';\n };\n const kind = findKind(path);\n tree.select(path, kind);\n onSelect?.(path, kind);\n },\n [tree, onSelect, childEntries],\n );\n\n const handleNewItemSubmit = useCallback(async () => {\n if (newItemCreationPendingRef.current) return;\n if (!newItemName.trim()) {\n setNewItemType(null);\n setNewItemError(null);\n return;\n }\n const name = newItemName.trim();\n const itemType = newItemType;\n // Scope to currently selected folder (or root)\n const prefix =\n tree.selectedKind === 'directory' && tree.selectedPath ? `${tree.selectedPath}/` : '';\n let createdPath = `${prefix}${name}`;\n setNewItemError(null);\n newItemCreationPendingRef.current = true;\n setNewItemCreationPending(true);\n try {\n if (itemType === 'file') {\n const filename = name.endsWith('.md') ? name : `${name}.md`;\n createdPath = `${prefix}${filename}`;\n await tree.createFile(createdPath, '');\n } else if (itemType === 'directory') {\n await tree.createDirectory(createdPath);\n }\n } catch (error: unknown) {\n // `createFile`/`createDirectory` use mode:'create', which rejects\n // with already-exists on a duplicate name. The form used to swallow\n // this and sit there looking idle. Keep the typed name so the user\n // can correct it rather than retype from scratch.\n setNewItemError(error instanceof Error ? error.message : 'Unable to create this item.');\n return;\n } finally {\n newItemCreationPendingRef.current = false;\n setNewItemCreationPending(false);\n }\n setNewItemName('');\n setNewItemType(null);\n onTreeChange?.({ type: 'create', path: createdPath });\n }, [newItemName, newItemType, tree, onTreeChange]);\n\n const handleMoveToWorkspace = useCallback(async () => {\n if (!onMoveToWorkspace || !moveDestinationId || movingToWorkspace) return;\n setMovingToWorkspace(true);\n setMoveWorkspaceError(null);\n try {\n await onMoveToWorkspace(moveDestinationId);\n } catch (error: unknown) {\n setMoveWorkspaceError(\n error instanceof Error ? error.message : 'The temporary document could not be moved.',\n );\n } finally {\n setMovingToWorkspace(false);\n }\n }, [moveDestinationId, movingToWorkspace, onMoveToWorkspace]);\n\n const runTreeMutation = useCallback(\n async (change: FileTreeChange, mutate: () => Promise<void>) => {\n if (onTreeMutation) await onTreeMutation(change, mutate);\n else await mutate();\n onTreeChange?.(change);\n },\n [onTreeMutation, onTreeChange],\n );\n\n const handleDelete = useCallback(\n async (path: string, kind: 'file' | 'directory') => {\n const change: FileTreeChange = { type: 'delete', path, kind };\n await runTreeMutation(change, () => tree.deleteEntry(path));\n },\n [tree, runTreeMutation],\n );\n\n const handleRename = useCallback(\n async (oldPath: string, newPath: string, kind: 'file' | 'directory') => {\n setMoveError(null);\n const change: FileTreeChange = { type: 'move', oldPath, newPath, kind };\n try {\n await runTreeMutation(change, () => tree.renameEntry(oldPath, newPath, kind));\n } catch (error: unknown) {\n await tree.refresh();\n if (isFileSystemMoveStateError(error) && error.documentLocation === 'destination') {\n onTreeChange?.(change);\n }\n setMoveError(error instanceof Error ? error.message : 'Unable to move this entry.');\n }\n },\n [tree, runTreeMutation, onTreeChange],\n );\n\n const handleMove = useCallback(\n async (entry: FileSystemEntry, directoryPath: string) => {\n if (!canMoveTo(entry, directoryPath)) return;\n const newPath = pathInDirectory(entry, directoryPath);\n await handleRename(entry.path, newPath, entry.kind);\n if (directoryPath && !tree.expanded.has(directoryPath)) {\n tree.toggleExpand(directoryPath);\n }\n },\n [handleRename, tree],\n );\n\n const handleInternalDragStart = useCallback((e: React.DragEvent, entry: FileSystemEntry) => {\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData(INTERNAL_DRAG_TYPE, entry.path);\n e.dataTransfer.setData('text/plain', entry.path);\n setDraggedEntry(entry);\n setMoveError(null);\n }, []);\n\n const handleInternalDragEnd = useCallback(() => {\n setDraggedEntry(null);\n setDropTarget(null);\n }, []);\n\n const handleEntryDragOver = useCallback(\n (e: React.DragEvent, entry: FileSystemEntry) => {\n if (!isInternalDrag(e.dataTransfer)) return;\n e.stopPropagation();\n const canDrop =\n entry.kind === 'directory' && draggedEntry && canMoveTo(draggedEntry, entry.path);\n e.dataTransfer.dropEffect = canDrop ? 'move' : 'none';\n if (canDrop) {\n e.preventDefault();\n setDropTarget(entry.path);\n } else {\n setDropTarget(null);\n }\n },\n [draggedEntry],\n );\n\n const handleEntryDrop = useCallback(\n (e: React.DragEvent, entry: FileSystemEntry) => {\n if (!isInternalDrag(e.dataTransfer)) return;\n e.preventDefault();\n e.stopPropagation();\n setDropTarget(null);\n if (entry.kind === 'directory' && draggedEntry) {\n void handleMove(draggedEntry, entry.path);\n }\n },\n [draggedEntry, handleMove],\n );\n\n const handleRootDragOver = useCallback(\n (e: React.DragEvent) => {\n if (!isInternalDrag(e.dataTransfer) || !draggedEntry) return;\n e.preventDefault();\n e.stopPropagation();\n const canDrop = canMoveTo(draggedEntry, '');\n e.dataTransfer.dropEffect = canDrop ? 'move' : 'none';\n setDropTarget(canDrop ? '' : null);\n },\n [draggedEntry],\n );\n\n const handleRootDrop = useCallback(\n (e: React.DragEvent) => {\n if (!isInternalDrag(e.dataTransfer)) return;\n e.preventDefault();\n e.stopPropagation();\n setDropTarget(null);\n if (draggedEntry) void handleMove(draggedEntry, '');\n },\n [draggedEntry, handleMove],\n );\n\n const badgeFor = useCallback(\n (entry: FileSystemEntry): FileTreeNodeBadge | undefined => {\n if (!git?.repo) return undefined;\n const key = entry.path.startsWith('/') ? entry.path : `/${entry.path}`;\n const kind = git.badges.get(key);\n if (!kind) return undefined;\n return { kind, glyph: BADGE_GLYPHS[kind], label: BADGE_LABELS[kind] };\n },\n [git],\n );\n\n const gitActionsFor = useCallback(\n (entry: FileSystemEntry): FileTreeNodeGitActions | undefined => {\n if (!git?.repo || entry.kind !== 'file') return undefined;\n const path = entry.path.startsWith('/') ? entry.path : `/${entry.path}`;\n return {\n viewChanges: isFileDirty(git.status, path)\n ? () => git.openDialog({ kind: 'diff', path })\n : undefined,\n fileHistory: () => git.openDialog({ kind: 'history', path }),\n openOnRemote: git.remoteWeb ? () => git.openOnRemote(path) : undefined,\n };\n },\n [git],\n );\n\n // The same walk renderEntries performs, as data — so arrow keys move\n // through exactly the rows on screen, in the order they appear.\n const visibleRows = useMemo(\n () =>\n flattenVisibleRows({\n roots: tree.entries,\n childrenOf: (dirPath) => getEquivalentPathValue(childEntries, dirPath) ?? [],\n isExpanded: (dirPath) => hasEquivalentPath(tree.expanded, dirPath),\n isVisible: (entry) => !isHiddenEntry(entry),\n }),\n [tree.entries, tree.expanded, childEntries],\n );\n\n // `selectedPath` can be slash-prefixed (reveal() takes the caller's form)\n // while entry paths are not, so match it with the explorer's own\n // equivalence rules and hand tree-keyboard an exact row path.\n const selectedRowPath = useMemo(() => {\n if (!tree.selectedPath) return null;\n const target = normalisePath(tree.selectedPath);\n return visibleRows.find((row) => normalisePath(row.path) === target)?.path ?? null;\n }, [visibleRows, tree.selectedPath]);\n\n // Resolved rather than stored: rows come and go (loads, deletes,\n // collapses), and the tree must never be left without a tab stop.\n const activeRowPath = resolveActiveRow(visibleRows, activePath, selectedRowPath);\n\n /** Move DOM focus to a row. It already exists, so this is safe to call\n synchronously from the keydown that decided to move. */\n const focusRow = useCallback((path: string) => {\n const rows = treeRef.current?.querySelectorAll<HTMLElement>('[role=\"treeitem\"]');\n for (const row of rows ?? []) {\n if (row.dataset.path === path) {\n row.focus();\n return;\n }\n }\n }, []);\n\n const handleTreeKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n // React portals bubble through the component tree, so the row menu's\n // keys would arrive here too. Only real rows navigate.\n const target = e.target as HTMLElement;\n if (!target.classList?.contains('db-tree-row')) return;\n if (!TREE_NAV_KEYS.has(e.key)) return;\n\n const action = treeKeyAction(visibleRows, activeRowPath, e.key);\n if (action.type === 'none') {\n // Still ours: Arrow keys must not scroll the pane out from under\n // the user just because the move was a no-op at an edge.\n e.preventDefault();\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n switch (action.type) {\n case 'focus':\n setActivePath(action.path);\n focusRow(action.path);\n break;\n case 'expand':\n case 'collapse':\n tree.toggleExpand(action.path);\n break;\n }\n },\n [visibleRows, activeRowPath, focusRow, tree],\n );\n\n const renderEntries = useCallback(\n (entries: FileSystemEntry[], depth: number): React.ReactNode => {\n const visible = filterVisible(entries);\n return visible.map((entry, index) => (\n <FileTreeNode\n key={entry.path}\n entry={entry}\n depth={depth}\n focusable={entry.path === activeRowPath}\n posInSet={index + 1}\n setSize={visible.length}\n onRowFocus={setActivePath}\n expanded={hasEquivalentPath(tree.expanded, entry.path)}\n selected={\n tree.selectedPath !== null &&\n normalisePath(tree.selectedPath) === normalisePath(entry.path)\n }\n badge={badgeFor(entry)}\n gitActions={gitActionsFor(entry)}\n onToggle={tree.toggleExpand}\n onSelect={handleSelect}\n confirmDelete={confirmDelete}\n onDelete={handleDelete}\n onRename={handleRename}\n draggable\n dragging={draggedEntry?.path === entry.path}\n dropTarget={dropTarget === entry.path}\n onDragStart={handleInternalDragStart}\n onDragEnd={handleInternalDragEnd}\n onDragOverEntry={handleEntryDragOver}\n onDropEntry={handleEntryDrop}\n renderChildren={(dirPath: string) => {\n const children = getEquivalentPathValue(childEntries, dirPath) ?? [];\n return renderEntries(children, depth + 1);\n }}\n />\n ));\n },\n [\n tree,\n handleSelect,\n confirmDelete,\n handleDelete,\n handleRename,\n childEntries,\n badgeFor,\n gitActionsFor,\n draggedEntry,\n dropTarget,\n handleInternalDragStart,\n handleInternalDragEnd,\n handleEntryDragOver,\n handleEntryDrop,\n activeRowPath,\n ],\n );\n\n return (\n <div\n className={`db-file-explorer ${dragOver ? 'db-file-explorer--drop-active' : ''} ${className ?? ''}`}\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {/* Toolbar */}\n <div className=\"db-explorer-toolbar\">\n <span className=\"db-explorer-title\">Files</span>\n <div className=\"db-explorer-actions\">\n <button\n className=\"db-explorer-btn\"\n disabled={newItemCreationPending}\n onClick={() => {\n setNewItemError(null);\n setNewItemType('file');\n }}\n title=\"New File\"\n aria-label=\"New File\"\n >\n <NewFileIcon />\n </button>\n <button\n className=\"db-explorer-btn\"\n disabled={newItemCreationPending}\n onClick={() => {\n setNewItemError(null);\n setNewItemType('directory');\n }}\n title=\"New Folder\"\n aria-label=\"New Folder\"\n >\n <NewFolderIcon />\n </button>\n </div>\n </div>\n\n {onMoveToWorkspace && (\n <div className=\"db-transient-move\">\n {!movePanelOpen ? (\n <button\n type=\"button\"\n className=\"db-transient-move-trigger\"\n onClick={() => {\n setMoveWorkspaceError(null);\n setMovePanelOpen(true);\n }}\n >\n Move this into a workspace\n </button>\n ) : (\n <form\n className=\"db-transient-move-form\"\n aria-label=\"Move this into a workspace\"\n onSubmit={(event) => {\n event.preventDefault();\n void handleMoveToWorkspace();\n }}\n >\n <label className=\"db-transient-move-label\" htmlFor=\"db-transient-move-destination\">\n Move this document into\n </label>\n <select\n id=\"db-transient-move-destination\"\n className=\"db-transient-move-select\"\n value={moveDestinationId}\n disabled={movingToWorkspace || moveDestinations.length === 0}\n onChange={(event) => {\n setMoveDestinationId(event.currentTarget.value);\n setMoveWorkspaceError(null);\n }}\n >\n {moveDestinations.map((destination) => (\n <option key={destination.id} value={destination.id}>\n {destination.name}\n </option>\n ))}\n </select>\n {moveDestinations.length === 0 && (\n <p className=\"db-transient-move-hint\">Open or create another workspace first.</p>\n )}\n {moveWorkspaceError && (\n <div className=\"db-transient-move-error\" role=\"alert\">\n {moveWorkspaceError}\n </div>\n )}\n <div className=\"db-transient-move-actions\">\n <button\n type=\"button\"\n className=\"db-transient-move-cancel\"\n disabled={movingToWorkspace}\n onClick={() => {\n setMoveWorkspaceError(null);\n setMovePanelOpen(false);\n }}\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n className=\"db-transient-move-submit\"\n disabled={movingToWorkspace || !moveDestinationId}\n >\n {movingToWorkspace ? 'Moving…' : 'Move'}\n </button>\n </div>\n </form>\n )}\n </div>\n )}\n\n {/* New item input */}\n {newItemType && (\n <div className=\"db-new-item\">\n <form\n className=\"db-new-item-row\"\n aria-busy={newItemCreationPending}\n onSubmit={(e) => {\n e.preventDefault();\n void handleNewItemSubmit();\n }}\n >\n <input\n className=\"db-new-item-input\"\n placeholder={newItemType === 'file' ? 'filename' : 'folder-name'}\n value={newItemName}\n aria-label={newItemType === 'file' ? 'New file name' : 'New folder name'}\n aria-invalid={newItemError !== null}\n aria-describedby={newItemError ? NEW_ITEM_ERROR_ID : undefined}\n disabled={newItemCreationPending}\n onChange={(e) => {\n setNewItemName(e.target.value);\n // The name changed, so the previous complaint about it no\n // longer applies.\n setNewItemError(null);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n setNewItemType(null);\n setNewItemName('');\n setNewItemError(null);\n }\n }}\n autoFocus\n />\n {newItemType === 'file' && <span className=\"db-new-item-suffix\">.md</span>}\n <button type=\"submit\" className=\"db-new-item-add\" disabled={newItemCreationPending}>\n {newItemCreationPending ? 'Adding…' : 'Add'}\n </button>\n </form>\n {newItemError && (\n <div id={NEW_ITEM_ERROR_ID} className=\"db-tree-error\" role=\"alert\">\n {newItemError}\n </div>\n )}\n </div>\n )}\n\n {moveError && (\n <div className=\"db-tree-error\" role=\"alert\">\n {moveError}\n </div>\n )}\n\n {tree.error && (\n <div className=\"db-tree-error\" role=\"alert\">\n <span>{tree.error}</span>{' '}\n <button type=\"button\" className=\"db-tree-error-retry\" onClick={() => void tree.refresh()}>\n Retry\n </button>\n </div>\n )}\n\n {/* Tree — role=\"tree\" only when there are real treeitem children; the\n loading/empty states get a status role so axe doesn't flag the\n tree as missing required children. */}\n {tree.loading ? (\n <div className=\"db-tree\" role=\"status\" aria-live=\"polite\">\n <div className=\"db-tree-loading\">Loading...</div>\n </div>\n ) : filterVisible(tree.entries).length === 0 ? (\n <div className=\"db-tree\">\n <div className=\"db-tree-empty\">No files yet</div>\n </div>\n ) : (\n <div\n ref={treeRef}\n className={`db-tree ${dropTarget === '' ? 'db-tree--drop-target' : ''}`}\n role=\"tree\"\n aria-label=\"Files\"\n onDragOver={handleRootDragOver}\n onDrop={handleRootDrop}\n onKeyDown={handleTreeKeyDown}\n >\n {renderEntries(tree.entries, 0)}\n </div>\n )}\n </div>\n );\n}\n","/**\n * useFileTree — hook that reads from a FileSystemProvider,\n * maintains expanded/collapsed state, and provides CRUD operations.\n */\n\nimport { useState, useCallback, useEffect, useRef } from 'react';\nimport {\n FsError,\n getFileSystemProviderV2,\n moveFileSystemEntry,\n parseWorkspacePath,\n type FileSystemProvider,\n type FileSystemEntry,\n} from '@bendyline/docblocks/filesystem';\n\nfunction normalisePath(path: string): string {\n return parseWorkspacePath(path);\n}\n\nfunction relocatePath(path: string, oldPath: string, newPath: string): string {\n const current = normalisePath(path);\n const oldNormalised = normalisePath(oldPath);\n if (current !== oldNormalised && !current.startsWith(`${oldNormalised}/`)) return path;\n const suffix = current.slice(oldNormalised.length);\n return `${newPath.replace(/\\/+$/, '')}${suffix}`;\n}\n\nfunction ancestorPaths(path: string): string[] {\n const canonical = normalisePath(path);\n if (!canonical) return [];\n const segments = canonical.split('/');\n const prefix = /^[\\\\/]/u.test(path) ? '/' : '';\n return segments\n .slice(0, -1)\n .map((_, index) => `${prefix}${segments.slice(0, index + 1).join('/')}`);\n}\n\nfunction equivalentPathKeys(path: string): string[] {\n const canonical = normalisePath(path);\n return canonical ? [path, canonical, `/${canonical}`] : [path, canonical];\n}\n\nfunction hasEquivalentPath(paths: ReadonlySet<string>, path: string): boolean {\n return equivalentPathKeys(path).some((candidate) => paths.has(candidate));\n}\n\nasync function readProviderDirectory(\n provider: FileSystemProvider,\n path: string,\n): Promise<FileSystemEntry[]> {\n const providerV2 = getFileSystemProviderV2(provider);\n if (!providerV2) return provider.readDirectory(path);\n const entries = await providerV2.readDirectory(parseWorkspacePath(path));\n return entries.map((entry) => ({ kind: entry.kind, name: entry.name, path: entry.path }));\n}\n\nexport interface FileTreeState {\n /** Flat list of entries for the current directory view. */\n entries: FileSystemEntry[];\n /** Set of expanded directory paths. */\n expanded: Set<string>;\n /** Currently selected path — file or directory (null if none). */\n selectedPath: string | null;\n /** Kind of the selected entry. */\n selectedKind: 'file' | 'directory' | null;\n /** Whether the tree is loading. */\n loading: boolean;\n /** Latest provider/read/watch failure, cleared by a successful refresh. */\n error: string | null;\n}\n\nexport interface FileTreeActions {\n /** Toggle a directory's expanded state. */\n toggleExpand: (path: string) => void;\n /** Select a file or directory. */\n select: (path: string, kind: 'file' | 'directory') => void;\n /** Select an entry and expand each directory needed to reveal it. */\n reveal: (path: string, kind: 'file' | 'directory') => void;\n /** Create a new file with optional initial content. */\n createFile: (path: string, content?: string) => Promise<void>;\n /** Create a new directory. */\n createDirectory: (path: string) => Promise<void>;\n /** Delete a file or directory. */\n deleteEntry: (path: string) => Promise<void>;\n /** Rename or move a file or directory, including a markdown companion folder. */\n renameEntry: (oldPath: string, newPath: string, kind?: 'file' | 'directory') => Promise<void>;\n /** Force refresh the tree. */\n refresh: () => Promise<void>;\n}\n\nexport function useFileTree(provider: FileSystemProvider | null): FileTreeState & FileTreeActions {\n const [entries, setEntries] = useState<FileSystemEntry[]>([]);\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const [selectedPath, setSelectedPath] = useState<string | null>(null);\n const [selectedKind, setSelectedKind] = useState<'file' | 'directory' | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Track child entries for expanded directories\n const [childEntries, setChildEntries] = useState<Map<string, FileSystemEntry[]>>(new Map());\n\n const providerRef = useRef(provider);\n providerRef.current = provider;\n\n const reportError = useCallback((caught: unknown) => {\n setError(caught instanceof Error ? caught.message : 'Unable to read this workspace.');\n }, []);\n\n const loadRoot = useCallback(async () => {\n const sourceProvider = providerRef.current;\n if (!sourceProvider) {\n setEntries([]);\n setLoading(false);\n return;\n }\n setLoading(true);\n setError(null);\n try {\n const root = await readProviderDirectory(sourceProvider, '');\n if (providerRef.current !== sourceProvider) return;\n setEntries(root);\n } catch (caught: unknown) {\n if (providerRef.current === sourceProvider) reportError(caught);\n } finally {\n if (providerRef.current === sourceProvider) setLoading(false);\n }\n }, [reportError]);\n\n const loadChildren = useCallback(\n async (dirPath: string) => {\n const sourceProvider = providerRef.current;\n if (!sourceProvider) return;\n try {\n const children = await readProviderDirectory(sourceProvider, dirPath);\n if (providerRef.current !== sourceProvider) return;\n setChildEntries((prev) => {\n const next = new Map(prev);\n next.set(dirPath, children);\n return next;\n });\n } catch (caught: unknown) {\n if (providerRef.current === sourceProvider) reportError(caught);\n }\n },\n [reportError],\n );\n\n // Load root on provider change\n useEffect(() => {\n setEntries([]);\n setExpanded(new Set());\n setChildEntries(new Map());\n setSelectedPath(null);\n setSelectedKind(null);\n setError(null);\n void loadRoot();\n }, [provider, loadRoot]);\n\n const toggleExpand = useCallback(\n (path: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (hasEquivalentPath(next, path)) {\n for (const candidate of equivalentPathKeys(path)) next.delete(candidate);\n } else {\n next.add(path);\n // Load children when expanding\n void loadChildren(path);\n }\n return next;\n });\n },\n [loadChildren],\n );\n\n const select = useCallback((path: string, kind: 'file' | 'directory') => {\n setSelectedPath(path);\n setSelectedKind(kind);\n }, []);\n\n const reveal = useCallback(\n (path: string, kind: 'file' | 'directory') => {\n const ancestors = ancestorPaths(path);\n setSelectedPath(path);\n setSelectedKind(kind);\n setExpanded((prev) => {\n const next = new Set(prev);\n for (const ancestor of ancestors) {\n if (!hasEquivalentPath(next, ancestor)) next.add(ancestor);\n }\n return next;\n });\n for (const ancestor of ancestors) {\n void loadChildren(ancestor);\n }\n },\n [loadChildren],\n );\n\n const refresh = useCallback(async () => {\n await loadRoot();\n // Reload all expanded directories\n const expandedPaths = [...expanded];\n for (const dirPath of expandedPaths) {\n await loadChildren(dirPath);\n }\n }, [loadRoot, loadChildren, expanded]);\n\n const refreshRef = useRef(refresh);\n refreshRef.current = refresh;\n\n // Keep the explorer synchronized with provider changes. Watch-capable\n // providers (including Electron's chokidar-backed provider) update in real\n // time. Calls are serialized and coalesced so event bursts cannot publish\n // directory reads out of order.\n useEffect(() => {\n if (!provider) return;\n const providerV2 = getFileSystemProviderV2(provider);\n if (!providerV2?.capabilities.watch) return;\n\n let disposed = false;\n let refreshing = false;\n let refreshAgain = false;\n\n const requestRefresh = () => {\n if (disposed) return;\n if (refreshing) {\n refreshAgain = true;\n return;\n }\n refreshing = true;\n void (async () => {\n try {\n do {\n refreshAgain = false;\n await refreshRef.current();\n } while (refreshAgain && !disposed);\n } catch (caught: unknown) {\n reportError(caught);\n } finally {\n refreshing = false;\n if (refreshAgain && !disposed) requestRefresh();\n }\n })();\n };\n\n const subscription = providerV2.watch(requestRefresh, {\n onError: (caught) => {\n if (disposed) return;\n reportError(caught);\n requestRefresh();\n },\n });\n void subscription.ready.catch((caught: unknown) => {\n if (!disposed) reportError(caught);\n });\n return () => {\n disposed = true;\n void subscription.dispose();\n };\n }, [provider, reportError]);\n\n // File System Access and IndexedDB do not expose a dependable external\n // watcher. Refreshing on resume catches changes made while this surface was\n // in the background without continuously polling the filesystem.\n useEffect(() => {\n if (!provider) return;\n const refreshOnFocus = () => {\n void refreshRef.current().catch(reportError);\n };\n const refreshOnVisibility = () => {\n if (document.visibilityState === 'visible') refreshOnFocus();\n };\n window.addEventListener('focus', refreshOnFocus);\n document.addEventListener('visibilitychange', refreshOnVisibility);\n return () => {\n window.removeEventListener('focus', refreshOnFocus);\n document.removeEventListener('visibilitychange', refreshOnVisibility);\n };\n }, [provider, reportError]);\n\n const createFile = useCallback(\n async (path: string, content = '') => {\n if (!providerRef.current) return;\n const providerV2 = getFileSystemProviderV2(providerRef.current);\n if (providerV2) {\n await providerV2.writeFile(parseWorkspacePath(path), new TextEncoder().encode(content), {\n mode: 'create',\n });\n } else {\n // The v2 path above uses `mode: 'create'`, which refuses to clobber.\n // The legacy seam has no such mode, so enforce the same contract here\n // -- otherwise \"create a new document\" silently truncates whatever is\n // already at `path`. Unreachable with the first-party providers (they\n // all expose v2), but `FileSystemProvider` is a public interface and a\n // consumer's own provider would land here. Mirrors the same guard in\n // `provider-io.ts`'s legacy branch.\n if (await providerRef.current.exists(path)) {\n throw new FsError('already-exists', 'File already exists.', {\n operation: 'write',\n path,\n });\n }\n await providerRef.current.writeFile(path, content);\n }\n await refresh();\n },\n [refresh],\n );\n\n const createDirectory = useCallback(\n async (path: string) => {\n if (!providerRef.current) return;\n const providerV2 = getFileSystemProviderV2(providerRef.current);\n if (providerV2) {\n await providerV2.createDirectory(parseWorkspacePath(path), { mode: 'create' });\n } else {\n await providerRef.current.createDirectory(path);\n }\n await refresh();\n },\n [refresh],\n );\n\n const deleteEntry = useCallback(\n async (path: string) => {\n if (!providerRef.current) return;\n const providerV2 = getFileSystemProviderV2(providerRef.current);\n if (providerV2) {\n const canonical = parseWorkspacePath(path);\n const entry = await providerV2.stat(canonical);\n if (entry) {\n await providerV2.remove(canonical, {\n recursive: entry.kind === 'directory',\n missing: 'error',\n expectedVersion: entry.version,\n });\n }\n } else {\n await providerRef.current.delete(path);\n }\n if (selectedPath === path) {\n setSelectedPath(null);\n setSelectedKind(null);\n }\n await refresh();\n },\n [refresh, selectedPath],\n );\n\n const renameEntry = useCallback(\n async (oldPath: string, newPath: string, kind?: 'file' | 'directory') => {\n if (!providerRef.current) return;\n const oldNormalised = normalisePath(oldPath);\n const knownEntry = [...entries, ...childEntries.values()]\n .flat()\n .find((entry) => normalisePath(entry.path) === oldNormalised);\n const entryKind = kind ?? knownEntry?.kind ?? 'file';\n await moveFileSystemEntry(providerRef.current, oldPath, newPath, entryKind);\n\n if (selectedPath) {\n setSelectedPath(relocatePath(selectedPath, oldPath, newPath));\n }\n\n const nextExpanded = new Set(\n [...expanded].map((path) => relocatePath(path, oldPath, newPath)),\n );\n setExpanded(nextExpanded);\n setChildEntries(new Map());\n await loadRoot();\n for (const dirPath of nextExpanded) {\n await loadChildren(dirPath);\n }\n },\n [selectedPath, entries, childEntries, expanded, loadRoot, loadChildren],\n );\n\n // Merge root entries with child entries for a flat tree representation\n // (consumers use `expanded` and `childEntries` to render recursively)\n\n return {\n entries,\n expanded,\n selectedPath,\n selectedKind,\n loading,\n error,\n toggleExpand,\n select,\n reveal,\n createFile,\n createDirectory,\n deleteEntry,\n renameEntry,\n refresh,\n // Expose child entries for rendering\n ...{ childEntries },\n } as FileTreeState & FileTreeActions & { childEntries: Map<string, FileSystemEntry[]> };\n}\n","/**\n * FileTreeNode — recursive tree node for the file explorer.\n *\n * Keyboard contract (WAI-ARIA tree-view pattern). The tree is a single tab\n * stop: FileExplorer owns the roving tabindex and arrow-key navigation\n * across rows, this node owns the keys that act on the row itself.\n *\n * Enter activate (open file / toggle folder)\n * F2 rename in place\n * Delete delete (with the same confirm as the menu item)\n * Shift+F10 /\n * ContextMenu open the row's actions menu, focused on its first item\n * Escape close the menu and hand focus back to the row\n *\n * The \"More actions\" button stays out of the tab order on purpose — one\n * tab stop per row would make tabbing through a large tree unusable, which\n * is precisely what the tree pattern's roving tabindex exists to avoid.\n */\n\nimport { useCallback, useState, useRef, useEffect, useLayoutEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { FileSystemEntry } from '@bendyline/docblocks/filesystem';\nimport { MoreIcon } from '../icons.js';\n\n/** Git decoration for a row — precomputed by FileExplorer so this node stays context-free. */\nexport interface FileTreeNodeBadge {\n kind: string;\n glyph: string;\n label: string;\n}\n\n/** Git context-menu actions, prebound to this entry's path. */\nexport interface FileTreeNodeGitActions {\n viewChanges?: () => void;\n fileHistory?: () => void;\n openOnRemote?: () => void;\n}\n\n/**\n * Last-resort confirmation for a host that supplies none. Native `confirm` is\n * the wrong look for the product -- `<DocBlocksShell>` passes its own dialog --\n * but silently destroying a document because no host wired one up would be\n * worse than an ugly prompt.\n */\nfunction defaultConfirmDelete(message: string): boolean {\n if (typeof window === 'undefined') return false;\n return window.confirm(message);\n}\n\nexport interface FileTreeNodeProps {\n entry: FileSystemEntry;\n depth: number;\n expanded: boolean;\n selected: boolean;\n badge?: FileTreeNodeBadge;\n gitActions?: FileTreeNodeGitActions;\n children?: FileSystemEntry[];\n /**\n * Roving tabindex: true only for the tree's single tab stop. Defaults to\n * true so a node rendered on its own is still reachable.\n */\n focusable?: boolean;\n /** 1-based position among siblings, for aria-posinset. */\n posInSet?: number;\n /** Number of siblings, for aria-setsize. */\n setSize?: number;\n /** The row took focus (click or arrow key) — move the roving tab stop. */\n onRowFocus?: (path: string) => void;\n onToggle: (path: string) => void;\n onSelect: (path: string) => void;\n /**\n * Ask the user to confirm an irreversible delete. Resolve `false` to abort.\n *\n * Optional so a standalone `<FileTreeNode>` still asks before destroying\n * something; hosts that have their own dialog (as `<DocBlocksShell>` does)\n * pass it here so the prompt matches the product instead of being a native\n * browser/Electron dialog.\n */\n confirmDelete?: (message: string) => boolean | Promise<boolean>;\n onDelete: (path: string, kind: 'file' | 'directory') => Promise<void>;\n onRename: (oldPath: string, newPath: string, kind: 'file' | 'directory') => Promise<void>;\n draggable?: boolean;\n dragging?: boolean;\n dropTarget?: boolean;\n onDragStart?: (event: React.DragEvent, entry: FileSystemEntry) => void;\n onDragEnd?: () => void;\n onDragOverEntry?: (event: React.DragEvent, entry: FileSystemEntry) => void;\n onDropEntry?: (event: React.DragEvent, entry: FileSystemEntry) => void;\n renderChildren?: (dirPath: string) => React.ReactNode;\n}\n\nexport function FileTreeNode({\n entry,\n depth,\n expanded,\n selected,\n badge,\n gitActions,\n focusable = true,\n posInSet,\n setSize,\n onRowFocus,\n onToggle,\n onSelect,\n confirmDelete = defaultConfirmDelete,\n onDelete,\n onRename,\n draggable = false,\n dragging = false,\n dropTarget = false,\n onDragStart,\n onDragEnd,\n onDragOverEntry,\n onDropEntry,\n renderChildren,\n}: FileTreeNodeProps) {\n const [renaming, setRenaming] = useState(false);\n const [renameValue, setRenameValue] = useState(entry.name);\n const [showContext, setShowContext] = useState(false);\n const [contextPos, setContextPos] = useState({ x: 0, y: 0 });\n /** Failure from this row's own async actions (delete/rename). */\n const [actionError, setActionError] = useState<string | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const contextRef = useRef<HTMLDivElement>(null);\n const nodeRef = useRef<HTMLDivElement>(null);\n const rowRef = useRef<HTMLDivElement>(null);\n /**\n * Whether the open menu was summoned by keyboard. A pointer user's focus\n * should stay where they clicked; a keyboard user must land inside the\n * menu, and be returned to the row when it closes.\n */\n const keyboardMenuRef = useRef(false);\n /**\n * Latches once a rename attempt is under way. The input submits from both\n * Enter and blur, and Enter can be followed by a blur (the row re-renders\n * or focus moves while `onRename` is still in flight) — without this the\n * same rename fires twice, the second against an entry that no longer\n * exists.\n */\n const renameSubmittedRef = useRef(false);\n\n const isDir = entry.kind === 'directory';\n const icon = isDir ? (expanded ? '\\u25BE' : '\\u25B8') : '\\u00A0\\u00A0';\n\n const handleClick = useCallback(() => {\n if (isDir) {\n onToggle(entry.path);\n }\n onSelect(entry.path);\n }, [isDir, entry.path, onToggle, onSelect]);\n\n const handleContextMenu = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n keyboardMenuRef.current = false;\n setContextPos({ x: e.clientX, y: e.clientY });\n setShowContext(true);\n }, []);\n\n const handleMoreClick = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n keyboardMenuRef.current = false;\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n setContextPos({ x: rect.right, y: rect.bottom });\n setShowContext(true);\n }, []);\n\n /** Shift+F10 / the ContextMenu key — anchor the menu under the row. */\n const openMenuByKeyboard = useCallback(() => {\n const rect = rowRef.current?.getBoundingClientRect();\n keyboardMenuRef.current = true;\n setContextPos({ x: rect ? rect.left + 16 : 0, y: rect ? rect.bottom : 0 });\n setShowContext(true);\n }, []);\n\n /** Close, optionally handing focus back to the row that owns the menu. */\n const closeMenu = useCallback((returnFocus: boolean) => {\n setShowContext(false);\n keyboardMenuRef.current = false;\n if (returnFocus) rowRef.current?.focus();\n }, []);\n\n const menuItems = useCallback(\n () =>\n [\n ...(contextRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]') ?? []),\n ].filter((item) => !item.disabled),\n [],\n );\n\n const focusMenuItem = useCallback(\n (index: number) => {\n const items = menuItems();\n if (items.length === 0) return;\n // Wrap, so Up from the first item lands on the last.\n const target = items[((index % items.length) + items.length) % items.length];\n // preventScroll: the menu's own scroll listener closes it, and\n // focus()'s default scroll-into-view would trip that immediately.\n target?.focus({ preventScroll: true });\n },\n [menuItems],\n );\n\n const handleMenuKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Escape' || e.key === 'Tab') {\n // Escape must not also reach a dialog/shell handler behind us.\n e.preventDefault();\n e.stopPropagation();\n closeMenu(true);\n return;\n }\n const items = menuItems();\n if (items.length === 0) return;\n const current = items.indexOf(document.activeElement as HTMLButtonElement);\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n focusMenuItem(current + 1);\n break;\n case 'ArrowUp':\n e.preventDefault();\n // -1 (nothing focused yet) wraps to the last item, as it should.\n focusMenuItem(current - 1);\n break;\n case 'Home':\n e.preventDefault();\n focusMenuItem(0);\n break;\n case 'End':\n e.preventDefault();\n focusMenuItem(items.length - 1);\n break;\n default:\n break;\n }\n },\n [closeMenu, focusMenuItem, menuItems],\n );\n\n const handleRenameStart = useCallback(() => {\n renameSubmittedRef.current = false;\n setActionError(null);\n setRenameValue(entry.name);\n setRenaming(true);\n // The rename input focuses itself, so don't pull focus back to the row.\n closeMenu(false);\n }, [entry.name, closeMenu]);\n\n /** Abandon the rename and make sure a trailing blur cannot submit it. */\n const handleRenameCancel = useCallback(() => {\n renameSubmittedRef.current = true;\n setRenaming(false);\n }, []);\n\n const handleRenameSubmit = useCallback(async () => {\n if (renameSubmittedRef.current) return;\n renameSubmittedRef.current = true;\n\n if (renameValue && renameValue !== entry.name) {\n const parentPath = entry.path.includes('/')\n ? entry.path.slice(0, entry.path.lastIndexOf('/'))\n : '';\n const newPath = parentPath ? `${parentPath}/${renameValue}` : renameValue;\n try {\n await onRename(entry.path, newPath, entry.kind);\n } catch (caught: unknown) {\n setActionError(caught instanceof Error ? caught.message : 'Unable to rename this entry.');\n }\n }\n setRenaming(false);\n }, [renameValue, entry.name, entry.path, entry.kind, onRename]);\n\n const handleDeleteClick = useCallback(async () => {\n closeMenu(false);\n setActionError(null);\n const description = entry.kind === 'directory' ? 'folder and everything inside it' : 'document';\n if (\n !(await confirmDelete(`Delete the ${description} \"${entry.name}\"? This cannot be undone.`))\n ) {\n return;\n }\n try {\n await onDelete(entry.path, entry.kind);\n } catch (caught: unknown) {\n // The explorer surfaces rename failures itself but lets delete\n // failures reject; without this the row silently keeps the entry.\n setActionError(caught instanceof Error ? caught.message : 'Unable to delete this entry.');\n }\n }, [entry.name, entry.path, entry.kind, confirmDelete, onDelete, closeMenu]);\n\n // Close context menu on outside click or scroll\n useEffect(() => {\n if (!showContext) return;\n function handleClose(e: Event) {\n if (contextRef.current && !contextRef.current.contains(e.target as Node)) {\n setShowContext(false);\n }\n }\n // Named so the cleanup can actually remove it. An inline arrow left a\n // listener behind on every menu that closed by click rather than\n // scroll, each one firing setState on a possibly-unmounted row.\n function handleScrollClose() {\n setShowContext(false);\n }\n // Use click (not mousedown) so menu button clicks register first\n document.addEventListener('click', handleClose, true);\n document.addEventListener('contextmenu', handleClose, true);\n document.addEventListener('scroll', handleScrollClose, { capture: true, once: true });\n return () => {\n document.removeEventListener('click', handleClose, true);\n document.removeEventListener('contextmenu', handleClose, true);\n document.removeEventListener('scroll', handleScrollClose, true);\n };\n }, [showContext]);\n\n // Focus input when renaming\n useEffect(() => {\n if (renaming && inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, [renaming]);\n\n // A keyboard-opened menu must take focus, or the keys that operate it\n // would go to the row underneath and the menu would be unreachable.\n useEffect(() => {\n if (!showContext || !keyboardMenuRef.current) return;\n focusMenuItem(0);\n }, [showContext, focusMenuItem]);\n\n // Active documents can be revealed after asynchronous ancestor loads. Keep\n // the selected row inside the explorer's scroll viewport once it mounts.\n useEffect(() => {\n if (selected) nodeRef.current?.scrollIntoView?.({ block: 'nearest' });\n }, [selected]);\n\n // Clamp menu inside viewport after it renders\n useLayoutEffect(() => {\n if (!showContext || !contextRef.current) return;\n const menu = contextRef.current;\n const rect = menu.getBoundingClientRect();\n const margin = 4;\n let left = contextPos.x;\n let top = contextPos.y;\n if (rect.right > window.innerWidth - margin) {\n left = Math.max(margin, window.innerWidth - rect.width - margin);\n }\n if (rect.bottom > window.innerHeight - margin) {\n top = Math.max(margin, window.innerHeight - rect.height - margin);\n }\n if (left !== contextPos.x || top !== contextPos.y) {\n menu.style.left = `${left}px`;\n menu.style.top = `${top}px`;\n }\n }, [showContext, contextPos]);\n\n return (\n <div className=\"db-tree-node\" ref={nodeRef}>\n <div\n ref={rowRef}\n className={`db-tree-row ${selected ? 'db-tree-row--selected' : ''} ${dragging ? 'db-tree-row--dragging' : ''} ${dropTarget ? 'db-tree-row--drop-target' : ''}`}\n style={{ paddingLeft: depth * 16 + 4 }}\n onClick={handleClick}\n onContextMenu={handleContextMenu}\n draggable={draggable && !renaming}\n onDragStart={(event) => onDragStart?.(event, entry)}\n onDragEnd={onDragEnd}\n onDragOver={(event) => onDragOverEntry?.(event, entry)}\n onDrop={(event) => onDropEntry?.(event, entry)}\n role=\"treeitem\"\n data-path={entry.path}\n aria-expanded={isDir ? expanded : undefined}\n aria-selected={selected}\n aria-label={badge ? `${entry.name}, ${badge.label}` : undefined}\n // The intermediate .db-tree-node wrapper means nesting alone does\n // not convey depth to assistive tech — state it outright.\n aria-level={depth + 1}\n aria-posinset={posInSet}\n aria-setsize={setSize}\n tabIndex={focusable ? 0 : -1}\n onFocus={(e) => {\n // Ignore focus bubbling out of the More button / rename input.\n if (e.target !== e.currentTarget) return;\n onRowFocus?.(entry.path);\n }}\n onKeyDown={(e) => {\n // Only the row itself acts. Keystrokes from nested controls (the\n // rename input) must not open the row underneath — that raced a\n // rename against a load of the pre-rename path.\n if (e.target !== e.currentTarget) return;\n if (e.key === 'Enter') {\n handleClick();\n return;\n }\n if (e.key === 'F2') {\n e.preventDefault();\n handleRenameStart();\n return;\n }\n if (e.key === 'Delete') {\n e.preventDefault();\n void handleDeleteClick();\n return;\n }\n // The platform gestures for \"open this row's context menu\".\n if (e.key === 'ContextMenu' || (e.key === 'F10' && e.shiftKey)) {\n e.preventDefault();\n openMenuByKeyboard();\n }\n }}\n >\n <span className=\"db-tree-icon\">{icon}</span>\n {renaming ? (\n <input\n ref={inputRef}\n className=\"db-tree-rename-input\"\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onBlur={() => void handleRenameSubmit()}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== 'Escape') return;\n // Belt and braces with the row's own target guard: the row\n // must never see these keys.\n e.preventDefault();\n e.stopPropagation();\n if (e.key === 'Enter') void handleRenameSubmit();\n else handleRenameCancel();\n }}\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <>\n <span className=\"db-tree-label\">\n {entry.name.endsWith('.md') ? entry.name.slice(0, -3) : entry.name}\n </span>\n {badge && (\n <span className={`db-git-badge db-git-badge--${badge.kind}`} aria-hidden=\"true\">\n {badge.glyph}\n </span>\n )}\n <button\n type=\"button\"\n className={`db-tree-more${showContext ? ' db-tree-more--active' : ''}`}\n onClick={handleMoreClick}\n onContextMenu={handleMoreClick}\n aria-label=\"More actions\"\n aria-haspopup=\"menu\"\n aria-expanded={showContext}\n // Advertise the keyboard route, since the tree's roving\n // tabindex deliberately keeps this button out of the tab order.\n aria-keyshortcuts=\"Shift+F10\"\n tabIndex={-1}\n >\n <MoreIcon />\n </button>\n </>\n )}\n </div>\n\n {actionError && (\n <div className=\"db-tree-error\" role=\"alert\">\n {actionError}\n </div>\n )}\n\n {/* Context menu — portaled so ancestor overflow:hidden doesn't clip it */}\n {showContext &&\n createPortal(\n <div\n ref={contextRef}\n className=\"db-tree-context\"\n style={{ left: contextPos.x, top: contextPos.y }}\n role=\"menu\"\n aria-label={`Actions for ${entry.name}`}\n onKeyDown={handleMenuKeyDown}\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-tree-context-item\"\n onClick={handleRenameStart}\n >\n Rename\n </button>\n {gitActions && (gitActions.viewChanges || gitActions.fileHistory) && (\n <>\n <div className=\"db-tree-context-divider\" role=\"separator\" />\n {gitActions.viewChanges && (\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-tree-context-item\"\n onClick={() => {\n closeMenu(false);\n gitActions.viewChanges?.();\n }}\n >\n View changes\n </button>\n )}\n {gitActions.fileHistory && (\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-tree-context-item\"\n onClick={() => {\n closeMenu(false);\n gitActions.fileHistory?.();\n }}\n >\n File history…\n </button>\n )}\n {gitActions.openOnRemote && (\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-tree-context-item\"\n onClick={() => {\n closeMenu(false);\n gitActions.openOnRemote?.();\n }}\n >\n Open on remote\n </button>\n )}\n <div className=\"db-tree-context-divider\" role=\"separator\" />\n </>\n )}\n <button\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className=\"db-tree-context-item db-tree-context-item--danger\"\n onClick={() => void handleDeleteClick()}\n >\n Delete\n </button>\n </div>,\n document.body,\n )}\n\n {/* Render children if directory is expanded */}\n {isDir && expanded && renderChildren && (\n <div className=\"db-tree-children\" role=\"group\">\n {renderChildren(entry.path)}\n </div>\n )}\n </div>\n );\n}\n","/**\n * DocBlocks shell icons use the Font Awesome Free webfont bundled by\n * `@bendyline/squisq-editor-react/styles`. Controls provide the accessible\n * name, so the glyphs themselves stay decorative.\n */\n\nfunction FontAwesomeIcon({ icon }: { icon: string }) {\n return <i className={icon} aria-hidden=\"true\" />;\n}\n\nexport function NewFileIcon() {\n return <FontAwesomeIcon icon=\"fa-solid fa-file-circle-plus\" />;\n}\n\nexport function NewFolderIcon() {\n return <FontAwesomeIcon icon=\"fa-solid fa-folder-plus\" />;\n}\n\nexport function FolderIcon() {\n return <FontAwesomeIcon icon=\"fa-solid fa-folder\" />;\n}\n\nexport function MoreIcon() {\n return <FontAwesomeIcon icon=\"fa-solid fa-ellipsis\" />;\n}\n\nexport function WorkspaceIcon() {\n return <FontAwesomeIcon icon=\"fa-solid fa-gear\" />;\n}\n\nexport function SplitViewIcon() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"1.5\" y=\"2.5\" width=\"13\" height=\"11\" rx=\"1\" />\n <line x1=\"6\" y1=\"2.5\" x2=\"6\" y2=\"13.5\" />\n </svg>\n );\n}\n","/**\n * File-tree keyboard navigation — pure decision logic, unit-testable.\n *\n * Implements the key contract from the WAI-ARIA tree-view pattern against a\n * *flattened list of currently-visible rows*. Flattening first is what\n * makes the rules trivial: a collapsed folder's children simply aren't in\n * the list, so Arrow Up/Down skip them for free, and \"move to parent\" is a\n * lookup rather than a walk back up the render tree.\n *\n * The caller owns focus and expansion; these helpers only say what should\n * happen. See FileExplorer, which flattens the tree it renders and applies\n * the returned action.\n */\n\nimport type { FileSystemEntry } from '@bendyline/docblocks/filesystem';\n\nexport interface TreeRow {\n path: string;\n kind: 'file' | 'directory';\n /** 0 for a root row; mirrors the rendered indentation. */\n depth: number;\n /** Directories only — always false for a file. */\n expanded: boolean;\n /** null for a root row. */\n parentPath: string | null;\n}\n\n/** How the tree is shaped, injected so this module stays free of state. */\nexport interface TreeShape {\n roots: readonly FileSystemEntry[];\n childrenOf: (dirPath: string) => readonly FileSystemEntry[];\n isExpanded: (dirPath: string) => boolean;\n /** Mirrors the explorer's hidden-entry filter so order matches the DOM. */\n isVisible: (entry: FileSystemEntry) => boolean;\n}\n\nexport type TreeKeyAction =\n | { type: 'none' }\n | { type: 'focus'; path: string }\n | { type: 'expand'; path: string }\n | { type: 'collapse'; path: string };\n\nconst NONE: TreeKeyAction = { type: 'none' };\n\n/** Keys this module claims; the caller should preventDefault for these. */\nexport const TREE_NAV_KEYS: ReadonlySet<string> = new Set([\n 'ArrowDown',\n 'ArrowUp',\n 'ArrowRight',\n 'ArrowLeft',\n 'Home',\n 'End',\n]);\n\n/**\n * Depth-first list of the rows the tree is currently rendering, in visual\n * order. Must stay in step with FileExplorer's `renderEntries`.\n */\nexport function flattenVisibleRows(shape: TreeShape): TreeRow[] {\n const rows: TreeRow[] = [];\n const walk = (entries: readonly FileSystemEntry[], depth: number, parentPath: string | null) => {\n for (const entry of entries) {\n if (!shape.isVisible(entry)) continue;\n const expanded = entry.kind === 'directory' && shape.isExpanded(entry.path);\n rows.push({ path: entry.path, kind: entry.kind, depth, expanded, parentPath });\n if (expanded) walk(shape.childrenOf(entry.path), depth + 1, entry.path);\n }\n };\n walk(shape.roots, 0, null);\n return rows;\n}\n\n/**\n * The single tab stop for the tree (roving tabindex). Prefers the row the\n * user last focused, falls back to the selected document, then the first\n * row — so tabbing into the tree lands somewhere meaningful and never\n * leaves the tree unreachable.\n */\nexport function resolveActiveRow(\n rows: readonly TreeRow[],\n activePath: string | null,\n selectedPath: string | null,\n): string | null {\n const has = (path: string | null): path is string =>\n path !== null && rows.some((row) => row.path === path);\n if (has(activePath)) return activePath;\n if (has(selectedPath)) return selectedPath;\n return rows[0]?.path ?? null;\n}\n\n/** Decide what a navigation key does. Returns `none` for unclaimed keys. */\nexport function treeKeyAction(\n rows: readonly TreeRow[],\n activePath: string | null,\n key: string,\n): TreeKeyAction {\n if (rows.length === 0) return NONE;\n\n if (key === 'Home') return { type: 'focus', path: rows[0].path };\n if (key === 'End') return { type: 'focus', path: rows[rows.length - 1].path };\n\n const index = activePath === null ? -1 : rows.findIndex((row) => row.path === activePath);\n // Nothing (or something stale) focused: any arrow key enters at the top.\n if (index < 0) return TREE_NAV_KEYS.has(key) ? { type: 'focus', path: rows[0].path } : NONE;\n const row = rows[index];\n\n switch (key) {\n case 'ArrowDown': {\n const next = rows[index + 1];\n return next ? { type: 'focus', path: next.path } : NONE;\n }\n case 'ArrowUp': {\n const previous = rows[index - 1];\n return previous ? { type: 'focus', path: previous.path } : NONE;\n }\n case 'ArrowRight': {\n if (row.kind !== 'directory') return NONE;\n if (!row.expanded) return { type: 'expand', path: row.path };\n const child = rows[index + 1];\n // Only descend when the next row really is this folder's child: an\n // expanded-but-empty folder must not jump to its sibling.\n return child && child.parentPath === row.path ? { type: 'focus', path: child.path } : NONE;\n }\n case 'ArrowLeft': {\n // An open folder closes; anything else steps out to its parent.\n if (row.kind === 'directory' && row.expanded) return { type: 'collapse', path: row.path };\n return row.parentPath === null ? NONE : { type: 'focus', path: row.parentPath };\n }\n default:\n return NONE;\n }\n}\n","/**\n * WorkspacePicker — dropdown for switching between workspaces\n * (IndexedDB-based or native folder via File System Access API).\n */\n\nimport { Fragment, useState, useEffect, useCallback, useRef } from 'react';\nimport type { WorkspaceDescriptor } from '@bendyline/docblocks/workspace';\nimport { listWorkspaces, saveWorkspace, touchWorkspace } from '@bendyline/docblocks/workspace';\nimport { isElectronHost } from '@bendyline/docblocks/host';\nimport { FolderIcon, NewFolderIcon } from '../icons.js';\n\nfunction isNativeFileSystemSupported(): boolean {\n return (\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as { showDirectoryPicker?: unknown }).showDirectoryPicker === 'function'\n );\n}\n\nexport interface WorkspacePickerProps {\n /** Currently active workspace id. */\n activeWorkspaceId: string | null;\n /** Called when the user picks a different workspace. */\n onSelect: (descriptor: WorkspaceDescriptor) => void;\n /** Called when the user chooses \"Open Folder\" (native FS). */\n onOpenFolder: () => void;\n /**\n * Called when the user chooses \"Clone Git repository\". Only provided on\n * the desktop when git is available — omitted, the item is hidden.\n */\n onCloneRepository?: () => void;\n /** Forces a list refresh after an external workspace-registry mutation. */\n refreshKey?: number;\n /** Optional className. */\n className?: string;\n}\n\nfunction WorkspacePath({ path }: { path: string }) {\n return path.split(/([\\\\/])/).map((segment, index) => (\n <Fragment key={index}>\n {segment}\n {(segment === '\\\\' || segment === '/') && <wbr />}\n </Fragment>\n ));\n}\n\nexport function WorkspacePicker({\n activeWorkspaceId,\n onSelect,\n onOpenFolder,\n onCloneRepository,\n refreshKey,\n className,\n}: WorkspacePickerProps) {\n const [workspaces, setWorkspaces] = useState<WorkspaceDescriptor[]>([]);\n const [isOpen, setIsOpen] = useState(false);\n const pickerRef = useRef<HTMLDivElement>(null);\n\n // Close dropdown on outside click\n useEffect(() => {\n if (!isOpen) return;\n function handleOutsideClick(e: MouseEvent) {\n if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n }\n document.addEventListener('mousedown', handleOutsideClick);\n return () => document.removeEventListener('mousedown', handleOutsideClick);\n }, [isOpen]);\n\n const electron = isElectronHost();\n\n const refresh = useCallback(async () => {\n const list = await listWorkspaces();\n // Hide persisted workspaces from the other delivery surface, but retain\n // session-only documents so loose files and DBKs have a visible current\n // workspace and can be revisited until they are moved or closed.\n const filtered = electron\n ? list.filter((w) => w.type === 'electron-native' || w.type === 'transient')\n : list.filter((w) => w.type !== 'electron-native');\n setWorkspaces(filtered);\n }, [electron]);\n\n useEffect(() => {\n refresh();\n }, [refresh, activeWorkspaceId, refreshKey]);\n\n const handleSelect = useCallback(\n async (ws: WorkspaceDescriptor) => {\n await touchWorkspace(ws.id);\n onSelect(ws);\n setIsOpen(false);\n },\n [onSelect],\n );\n\n const handleCreateNew = useCallback(async () => {\n const name = `Workspace ${workspaces.length + 1}`;\n const id = `ws-${Date.now()}`;\n const descriptor: WorkspaceDescriptor = {\n id,\n name,\n type: 'indexeddb',\n lastOpened: new Date().toISOString(),\n };\n await saveWorkspace(descriptor);\n await refresh();\n onSelect(descriptor);\n setIsOpen(false);\n }, [workspaces.length, onSelect, refresh]);\n\n const activeWs = workspaces.find((w) => w.id === activeWorkspaceId);\n const activeWorkspaceName = activeWs?.name ?? 'No workspace';\n\n return (\n <div ref={pickerRef} className={`db-workspace-picker ${className ?? ''}`}>\n <button\n className=\"db-workspace-picker-btn\"\n onClick={() => setIsOpen(!isOpen)}\n title=\"Switch workspace\"\n aria-label={`Switch workspace, current: ${activeWorkspaceName}`}\n >\n <span className=\"db-workspace-picker-label\">{activeWorkspaceName}</span>\n <span className=\"db-workspace-picker-compact-icon\">\n <FolderIcon />\n </span>\n <span\n className={`db-workspace-picker-caret${isOpen ? ' db-workspace-picker-caret--open' : ''}`}\n aria-hidden=\"true\"\n />\n </button>\n\n {isOpen && (\n <div className=\"db-workspace-dropdown\">\n {workspaces.map((ws) => (\n <button\n key={ws.id}\n className={`db-workspace-dropdown-item ${\n ws.id === activeWorkspaceId ? 'db-workspace-dropdown-item--active' : ''\n }`}\n onClick={() => handleSelect(ws)}\n >\n <span className=\"db-workspace-details\">\n <span className=\"db-workspace-heading\">\n <span>{ws.name}</span>\n {(ws.type === 'native' || ws.type === 'electron-native') && (\n <span className=\"db-workspace-type\">(folder)</span>\n )}\n </span>\n {ws.rootPath && (\n <span className=\"db-workspace-path\" title={ws.rootPath}>\n <WorkspacePath path={ws.rootPath} />\n </span>\n )}\n </span>\n </button>\n ))}\n\n <div className=\"db-workspace-dropdown-divider\" />\n\n {!electron && (\n <button className=\"db-workspace-dropdown-item\" onClick={handleCreateNew}>\n <span className=\"db-workspace-dropdown-action-label\">\n <NewFolderIcon />\n <span>New Workspace</span>\n </span>\n </button>\n )}\n\n {(electron || isNativeFileSystemSupported()) && (\n <button\n className=\"db-workspace-dropdown-item\"\n onClick={() => {\n setIsOpen(false);\n onOpenFolder();\n }}\n >\n Open Folder...\n </button>\n )}\n\n {onCloneRepository && (\n <button\n className=\"db-workspace-dropdown-item\"\n onClick={() => {\n setIsOpen(false);\n onCloneRepository();\n }}\n >\n Clone Git Repository...\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * DocBlocksShell -- top-level layout component.\n *\n * Composes the left sidebar (WorkspacePicker + FileExplorer) with\n * the center editor area (squisq EditorShell).\n */\n\nimport { useState, useCallback, useEffect, useRef, useMemo, lazy, Suspense } from 'react';\nimport type {\n EditorColorScheme,\n EditorView,\n ViewPreferences,\n} from '@bendyline/squisq-editor-react';\nimport '@bendyline/squisq-editor-react/styles';\nimport { MediaContext } from '@bendyline/squisq-react';\nimport type { MediaProvider } from '@bendyline/squisq/schemas';\nimport type { VideoExportPalette } from '@bendyline/squisq-video-react';\nimport {\n DocumentVersionManager,\n type PrunePolicy,\n type SaveVersionResult,\n} from '@bendyline/squisq/versions';\nimport type {\n DbkWorkspaceSnapshot,\n ElectronFileSystemProvider,\n FileSystemProvider,\n FileSystemEntry,\n MemoryFileSystemProvider,\n} from '@bendyline/docblocks/filesystem';\nimport {\n FileSystemContentContainer,\n createFileMediaProvider,\n decodeUtf8Text,\n FsError,\n getFileSystemProviderV2,\n isQuotaExceededError,\n parseWorkspacePath,\n workspacePathContains,\n} from '@bendyline/docblocks/filesystem';\nimport {\n createFileSystemDocumentTarget,\n DocumentCommitConflictError,\n DocumentSessionConflictError,\n type DocumentCommitTarget,\n type DocumentSessionEditScope,\n} from '@bendyline/docblocks/document';\nimport type { ContentContainer } from '@bendyline/squisq/storage';\nimport { isElectronHost, getDocBlocksHost } from '@bendyline/docblocks/host';\nimport type { ElectronWorkspaceInfo, OpenRequest } from '@bendyline/docblocks/host';\nimport {\n parseSharedDocumentHash,\n type SharedDocumentMode,\n type SharedDocumentPayload,\n} from '@bendyline/docblocks/share';\nimport type { WorkspaceDescriptor } from '@bendyline/docblocks/workspace';\nimport {\n ensureDefaultWorkspace,\n getWorkspace,\n listWorkspaces,\n reconcileElectronWorkspaceDescriptors,\n removeWorkspace,\n saveWorkspace,\n touchWorkspace,\n registerTransientWorkspace,\n getTransientWorkspace,\n unregisterTransientWorkspace,\n} from '@bendyline/docblocks/workspace';\nimport { AppMenu } from '../AppMenu/AppMenu.js';\nimport { pickEmptyDocumentPrompt } from '../editor.js';\nimport {\n FileExplorer,\n type FileTreeChange,\n type FileTreeMutationHandler,\n} from '../FileExplorer/FileExplorer.js';\nimport { WorkspacePicker } from '../WorkspacePicker/WorkspacePicker.js';\nimport { WorkspaceSettingsButton } from '../WorkspacePicker/WorkspaceSettingsButton.js';\nimport { SplitViewIcon } from '../icons.js';\nimport {\n WorkspaceSettingsDialog,\n type WorkspaceVersioningOverride,\n} from '../WorkspacePicker/WorkspaceSettingsDialog.js';\nimport { useDocumentSession } from '../hooks/useDocumentSession.js';\nimport {\n ExportToolbarControls,\n type ExportDestinationAdapter,\n} from '../Export/DeferredExportToolbarControls.js';\nimport { GitContext } from '../Git/GitContext.js';\nimport { useGit } from '../Git/useGit.js';\n// The editor is only needed after a document and its media container are\n// ready. Workspace chrome stays interactive while this large feature loads.\nconst EditorShell = lazy(async () => {\n const workersReady = (globalThis as { docBlocksMonacoWorkersReady?: Promise<unknown> })\n .docBlocksMonacoWorkersReady;\n // Worker setup is an enhancement; a host that cannot install language\n // workers must not make the document editor unavailable.\n await workersReady?.catch(() => undefined);\n return import('./LazyEditorShell.js');\n});\n// The git dialogs/status bar only ever render under the Electron host, so\n// they load as a split chunk -- the site never pays for them (the entry\n// bundle budget is enforced by scripts/check-bundle-size.ts).\nconst GitUI = lazy(() => import('../Git/GitUI.js').then((m) => ({ default: m.GitUI })));\nconst GitToolbarControl = lazy(() =>\n import('../Git/GitToolbarControl.js').then((m) => ({ default: m.GitToolbarControl })),\n);\nimport {\n loadVersioningPreference,\n resolveVersioningEnabled,\n saveVersioningPreference,\n type VersioningPreference,\n} from '../preferences/versioning.js';\nimport {\n DB_CHROME_COLORS,\n loadAccentColor,\n loadThemePreference,\n saveAccentColor,\n saveThemePreference,\n type AccentColor,\n type ThemePreference,\n} from '../preferences/theme.js';\nimport {\n loadWriteCanvasPreferences,\n saveWriteCanvasPreferences,\n type WriteCanvasPreferences,\n} from '../preferences/write-canvas.js';\nimport { retainFileSystemProvider } from '../provider-lease.js';\nimport { useDocumentTitle } from './document-title.js';\nimport { decodeDbkWorkspace } from './dbk-import.js';\nimport { importDroppedFiles, summariseImport } from './import-files.js';\nimport { providerEntryExists, removeProviderEntry, writeProviderText } from './provider-io.js';\nimport { usePromptDialog } from '../components/usePromptDialog.js';\nimport { useConfirmDialog } from '../components/useConfirmDialog.js';\nimport { resolveShellTheme } from './resolve-theme.js';\nimport { buildIssueReportUrl } from './issue-report.js';\nimport { loadLastState, saveLastState } from './last-state.js';\nimport {\n isWelcomeGatewayDismissed,\n loadSidebarWidth,\n loadViewPreferences,\n markWelcomeGatewayDismissed,\n saveSidebarWidth,\n saveViewPreferences,\n SIDEBAR_COLLAPSE_THRESHOLD,\n SIDEBAR_WIDTH_MAX,\n SIDEBAR_WIDTH_MIN,\n} from './shell-preferences.js';\nimport { UpdateAvailableNotice } from './UpdateAvailableNotice.js';\nimport { useDocumentLinkProvider } from './useDocumentLinkProvider.js';\nimport { WorkspaceAuthorityBarrier } from './workspace-authority-barrier.js';\nimport { copyTransientWorkspaceContents } from './transient-workspace-move.js';\n\nconst DOCBLOCKS_VIDEO_EXPORT_PALETTE: Partial<VideoExportPalette> = Object.freeze({\n overlay: 'rgba(0, 0, 0, 0.72)',\n surface: 'var(--db-bg)',\n control: 'var(--db-bg-subtle)',\n border: 'var(--db-border-strong)',\n text: 'var(--db-text)',\n heading: 'var(--db-text)',\n label: 'var(--db-text-secondary)',\n muted: 'var(--db-text-muted)',\n secondary: 'var(--db-accent-tint-strong)',\n primary: 'var(--db-accent)',\n primaryBorder: 'var(--db-accent-hover)',\n primaryText: 'var(--db-text-on-accent)',\n success: 'var(--db-git-added)',\n danger: 'var(--db-danger)',\n});\n\nlet indexedDbFileSystemModule: Promise<\n typeof import('@bendyline/docblocks/filesystem/indexeddb')\n> | null = null;\nlet memoryFileSystemModule: Promise<\n typeof import('@bendyline/docblocks/filesystem/memory')\n> | null = null;\nlet nativeFileSystemModule: Promise<\n typeof import('@bendyline/docblocks/filesystem/native')\n> | null = null;\nlet electronFileSystemModule: Promise<\n typeof import('@bendyline/docblocks/filesystem/electron')\n> | null = null;\n\nfunction loadIndexedDbFileSystem() {\n indexedDbFileSystemModule ??= import('@bendyline/docblocks/filesystem/indexeddb').catch(\n (error: unknown) => {\n indexedDbFileSystemModule = null;\n throw error;\n },\n );\n return indexedDbFileSystemModule;\n}\n\nfunction loadMemoryFileSystem() {\n memoryFileSystemModule ??= import('@bendyline/docblocks/filesystem/memory').catch(\n (error: unknown) => {\n memoryFileSystemModule = null;\n throw error;\n },\n );\n return memoryFileSystemModule;\n}\n\nfunction loadNativeFileSystem() {\n nativeFileSystemModule ??= import('@bendyline/docblocks/filesystem/native').catch(\n (error: unknown) => {\n nativeFileSystemModule = null;\n throw error;\n },\n );\n return nativeFileSystemModule;\n}\n\nfunction loadElectronFileSystem() {\n electronFileSystemModule ??= import('@bendyline/docblocks/filesystem/electron').catch(\n (error: unknown) => {\n electronFileSystemModule = null;\n throw error;\n },\n );\n return electronFileSystemModule;\n}\n\nasync function createIndexedDbFileSystemProvider(id: string, label: string) {\n const { IndexedDBFileSystemProvider } = await loadIndexedDbFileSystem();\n return new IndexedDBFileSystemProvider(id, label);\n}\n\nasync function createElectronFileSystemProvider(\n id: string,\n label: string,\n rootPath: string,\n): Promise<ElectronFileSystemProvider> {\n const { ElectronFileSystemProvider } = await loadElectronFileSystem();\n return new ElectronFileSystemProvider(id, label, rootPath);\n}\n\nasync function createMemoryFileSystemProvider(\n id: string,\n label: string,\n): Promise<MemoryFileSystemProvider> {\n const { MemoryFileSystemProvider } = await loadMemoryFileSystem();\n return new MemoryFileSystemProvider(id, label);\n}\n\nfunction isMemoryWorkspaceProvider(\n provider: FileSystemProvider,\n): provider is MemoryFileSystemProvider {\n const candidate = provider as Partial<MemoryFileSystemProvider>;\n return (\n typeof candidate.captureContents === 'function' &&\n typeof candidate.replaceContents === 'function' &&\n typeof candidate.treeVersion === 'number'\n );\n}\n\nexport interface DocBlocksShellProps {\n /**\n * The theme to use before the user has an opinion. Omit or pass `'auto'` to\n * follow the OS. An explicit `'light'`/`'dark'` choice the user makes in\n * Settings outranks this — it is their app, not the host's.\n */\n theme?: EditorColorScheme | 'auto';\n /** Optional logo image URL for the app menu. */\n logoUrl?: string;\n /** Version and surface label included in prefilled issue reports, e.g. `1.1.2 web`. */\n issueReportVersion?: string;\n /** Stable host title used before a document opens and for the optional home document. */\n homeDocumentTitle?: string;\n /** Document path that represents the host's indexable home experience. */\n homeDocumentPath?: string;\n /**\n * Enable document version history. Snapshots are written under\n * `<basename>_files/.versions/` next to each markdown file (i.e., the\n * per-document container). Defaults to `true`.\n */\n allowVersioning?: boolean;\n /**\n * Override the document basename used in version filenames. Defaults\n * to the basename of the currently selected file.\n */\n versionBasename?: string;\n /** Prune policy applied after each successful save. Default: keep last 50. */\n versioningPrunePolicy?: PrunePolicy;\n /** Idle delay (ms) before the editor auto-saves a version. `0` disables. Default 5000. */\n versioningAutoSaveIdleMs?: number;\n /** Notified after each `saveVersion` attempt (saved=true and saved=false). */\n onSaveVersion?: (result: SaveVersionResult) => void;\n /** Optional escape hatch for hosts that want imperative access to the version manager. */\n versioningRef?: React.Ref<DocumentVersionManager | null>;\n /**\n * True when a new deploy is waiting (browser PWA hosts: a fresh service\n * worker finished installing). The shell shows an \"Update available\"\n * status-bar notice that opens a Reload/Later prompt.\n */\n updateAvailable?: boolean;\n /** Activates the waiting update and reloads onto the new version. */\n onApplyUpdate?: () => void;\n /**\n * True once the app has been fully cached for offline use (browser PWA\n * hosts). Shown to the user once as a passive notice.\n */\n offlineReady?: boolean;\n}\n\nfunction useOsTheme(): 'light' | 'dark' {\n const [dark, setDark] = useState(\n () =>\n typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches,\n );\n useEffect(() => {\n const mq = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => setDark(e.matches);\n mq.addEventListener('change', handler);\n return () => mq.removeEventListener('change', handler);\n }, []);\n return dark ? 'dark' : 'light';\n}\n\n/** Encode workspace + optional file path into a URL hash. */\nfunction buildHash(workspaceId: string, filePath?: string | null): string {\n const ws = encodeURIComponent(workspaceId);\n if (!filePath) return `#${ws}`;\n const fp = filePath.replace(/^\\//, '');\n return `#${ws}/${encodeURIComponent(fp)}`;\n}\n\n/** Decode the current URL hash into workspace id + file path. */\nfunction parseHash(): { workspaceId: string; filePath: string | null } | null {\n const raw = window.location.hash.slice(1);\n if (!raw) return null;\n try {\n const slashIdx = raw.indexOf('/');\n if (slashIdx === -1) {\n return { workspaceId: decodeURIComponent(raw), filePath: null };\n }\n return {\n workspaceId: decodeURIComponent(raw.slice(0, slashIdx)),\n filePath: '/' + decodeURIComponent(raw.slice(slashIdx + 1)),\n };\n } catch {\n return null;\n }\n}\n\nfunction dirnameOf(p: string): string {\n const clean = p.replace(/^\\/+/, '');\n const idx = clean.lastIndexOf('/');\n return idx === -1 ? '' : clean.slice(0, idx);\n}\n\nfunction basenameOf(p: string): string {\n const clean = p.replace(/^\\/+/, '');\n const idx = clean.lastIndexOf('/');\n return idx === -1 ? clean : clean.slice(idx + 1);\n}\n\n/** Strip the extension from a filename (`notes.md` -> `notes`). Matches\n * squisq's `getDocBasename` convention so version snapshot filenames\n * stay readable (`<basename>.<timestamp>.md`). */\nfunction stripExtension(name: string): string {\n return name.replace(/\\.[^.]+$/, '');\n}\n\nfunction normaliseProviderPath(p: string): string {\n const canonical = parseWorkspacePath(p);\n return canonical ? `/${canonical}` : '/';\n}\n\nfunction sameProviderPath(a: string, b: string): boolean {\n return normaliseProviderPath(a) === normaliseProviderPath(b);\n}\n\nfunction relocateProviderPath(path: string, oldPath: string, newPath: string): string {\n const current = normaliseProviderPath(path);\n const oldNormalised = normaliseProviderPath(oldPath);\n if (current !== oldNormalised && !current.startsWith(`${oldNormalised}/`)) return path;\n return `${newPath.replace(/\\/+$/, '')}${current.slice(oldNormalised.length)}`;\n}\n\nfunction pathContains(parentPath: string, candidatePath: string): boolean {\n return workspacePathContains(parseWorkspacePath(parentPath), parseWorkspacePath(candidatePath));\n}\n\nasync function readProviderDirectory(\n provider: FileSystemProvider,\n path: string,\n): Promise<FileSystemEntry[]> {\n const providerV2 = getFileSystemProviderV2(provider);\n if (!providerV2) return provider.readDirectory(path);\n const entries = await providerV2.readDirectory(parseWorkspacePath(path));\n return entries.map((entry) => ({ kind: entry.kind, name: entry.name, path: entry.path }));\n}\n\nasync function readProviderText(\n provider: FileSystemProvider,\n path: string,\n): Promise<string | null> {\n const providerV2 = getFileSystemProviderV2(provider);\n if (!providerV2) return provider.readFile(path);\n const file = await providerV2.readFile(parseWorkspacePath(path));\n return file\n ? decodeUtf8Text(file.data, { label: 'The document', path: parseWorkspacePath(path) })\n : null;\n}\n\nasync function readStableFileSnapshot(\n provider: FileSystemProvider,\n path: string,\n): Promise<{ content: string | null; version: string | null }> {\n const providerV2 = getFileSystemProviderV2(provider);\n if (providerV2) {\n const read = await providerV2.readFile(parseWorkspacePath(path));\n return {\n content: read\n ? decodeUtf8Text(read.data, {\n label: 'The document',\n path: parseWorkspacePath(path),\n })\n : null,\n version: read?.entry.version ?? null,\n };\n }\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const before = await provider.stat(path);\n const content = await provider.readFile(path);\n const after = await provider.stat(path);\n const unchanged = before?.lastModified === after?.lastModified && before?.size === after?.size;\n const existenceMatches = (content !== null) === (after !== null);\n if (unchanged && existenceMatches) {\n return {\n content,\n version: after ? `${after.lastModified}:${after.size}` : null,\n };\n }\n }\n throw new Error('The file kept changing while DocBlocks was reading it.');\n}\n\nasync function sha256Hex(data: ArrayBuffer): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', data);\n return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Ask for write access to a file handle delivered by the web File Handling\n * API. Chromium grants read on launch; readwrite needs one prompt, ideally\n * requested while the OS-launch user activation is still fresh. The\n * permission methods are Chromium-only extensions (same inline typing\n * approach as core's native-provider), so absent methods are treated as\n * writable and the write itself surfaces any failure.\n */\nasync function ensureHandleWritePermission(handle: FileSystemFileHandle): Promise<boolean> {\n const h = handle as FileSystemFileHandle & {\n queryPermission?(desc: { mode: 'read' | 'readwrite' }): Promise<PermissionState>;\n requestPermission?(desc: { mode: 'read' | 'readwrite' }): Promise<PermissionState>;\n };\n if (!h.queryPermission || !h.requestPermission) return true;\n try {\n const opts = { mode: 'readwrite' as const };\n if ((await h.queryPermission(opts)) === 'granted') return true;\n return (await h.requestPermission(opts)) === 'granted';\n } catch {\n return false;\n }\n}\n\n/** Portable relative link from one workspace file to another. Walks up\n * from the source's directory and back down to the target so the link\n * survives folder reshuffles (`../sibling.md`, `subfolder/child.md`,\n * `resume.md` for siblings at the workspace root). */\n/**\n * Walk a FileSystemProvider and copy every file into a content container.\n * Kept outside the component so document commit targets and backup actions\n * share one implementation.\n */\nasync function copyProviderToContainer(\n src: FileSystemProvider,\n container: { writeFile: (path: string, data: ArrayBuffer | Uint8Array) => Promise<void> },\n pathPrefix: string,\n): Promise<void> {\n const providerV2 = getFileSystemProviderV2(src);\n if (providerV2) {\n const snapshot = await providerV2.snapshot();\n for (const entry of snapshot.entries) {\n if (entry.kind !== 'file') continue;\n const rel = entry.path;\n const destination = pathPrefix ? `${pathPrefix}/${rel}` : rel;\n await container.writeFile(destination, entry.data);\n }\n return;\n }\n\n const stack: string[] = ['/'];\n while (stack.length > 0) {\n const dir = stack.pop()!;\n const entries = await readProviderDirectory(src, dir);\n for (const entry of entries) {\n if (entry.kind === 'directory') {\n stack.push(entry.path);\n continue;\n }\n const rel = entry.path.replace(/^\\/+/, '');\n const zipPath = pathPrefix ? pathPrefix + '/' + rel : rel;\n const binary = await src.readBinary(entry.path);\n if (binary) await container.writeFile(zipPath, binary);\n else {\n const text = await src.readFile(entry.path);\n if (text === null) throw new Error(`The workspace changed while reading ${entry.path}.`);\n await container.writeFile(zipPath, new TextEncoder().encode(text));\n }\n }\n }\n}\n\ninterface PendingDbkConflict {\n provider: MemoryFileSystemProvider;\n snapshot: DbkWorkspaceSnapshot;\n}\n\nasync function createElectronProviderFromWorkspace(\n ws: WorkspaceDescriptor,\n): Promise<ElectronFileSystemProvider | null> {\n if (!ws.rootPath) return null;\n try {\n await getDocBlocksHost().workspaces.register(ws.id);\n } catch {\n return null;\n }\n return createElectronFileSystemProvider(ws.id, ws.name, ws.rootPath);\n}\n\nfunction useIsMobile(breakpoint = 768): boolean {\n const [isMobile, setIsMobile] = useState(\n () =>\n typeof window !== 'undefined' && window.matchMedia(`(max-width: ${breakpoint}px)`).matches,\n );\n useEffect(() => {\n const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);\n const handler = (e: MediaQueryListEvent) => setIsMobile(e.matches);\n mq.addEventListener('change', handler);\n return () => mq.removeEventListener('change', handler);\n }, [breakpoint]);\n return isMobile;\n}\n\nfunction FolderGlyph() {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 7a1 1 0 0 1 1-1h5l2 2h9a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7z\" />\n </svg>\n );\n}\n\nfunction FileGlyph() {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 3h8l5 5v12a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z\" />\n <path d=\"M14 3v5h5\" />\n </svg>\n );\n}\n\nexport function DocBlocksShell({\n theme: hostTheme = 'auto',\n logoUrl,\n issueReportVersion,\n homeDocumentTitle,\n homeDocumentPath,\n allowVersioning = true,\n versionBasename,\n versioningPrunePolicy,\n versioningAutoSaveIdleMs,\n onSaveVersion,\n versioningRef,\n updateAvailable = false,\n onApplyUpdate,\n offlineReady = false,\n}: DocBlocksShellProps) {\n const osTheme = useOsTheme();\n const [themePreference, setThemePreference] = useState<ThemePreference>(loadThemePreference);\n const [accentColor, setAccentColor] = useState<AccentColor>(loadAccentColor);\n const [writeCanvasSettings, setWriteCanvasSettings] = useState<WriteCanvasPreferences>(\n loadWriteCanvasPreferences,\n );\n // Settings choice > the host's `theme` prop > the OS. See resolve-theme.ts\n // for why that order. Stamped as `data-theme` on the shell root below.\n const resolvedTheme = resolveShellTheme({ preference: themePreference, hostTheme, osTheme });\n\n const handleThemeChange = useCallback((pref: ThemePreference) => {\n setThemePreference(pref);\n saveThemePreference(pref);\n }, []);\n\n // Keep the browser's theme-color metas in sync with the resolved theme so\n // the installed web app's titlebar (Window Controls Overlay caption area,\n // Android status bar) matches the shell chrome. Both media-attributed\n // metas are overwritten on purpose: an explicit user theme choice must\n // beat the OS media query. Electron paints its own titlebar.\n useEffect(() => {\n if (isElectronHost() || typeof document === 'undefined') return;\n const metas = document.querySelectorAll<HTMLMetaElement>('meta[name=\"theme-color\"]');\n metas.forEach((meta) => {\n meta.content = DB_CHROME_COLORS[resolvedTheme];\n });\n }, [resolvedTheme]);\n\n const handleAccentColorChange = useCallback((color: AccentColor) => {\n setAccentColor(color);\n saveAccentColor(color);\n }, []);\n\n const handleWriteCanvasSettingsChange = useCallback((settings: WriteCanvasPreferences) => {\n setWriteCanvasSettings(settings);\n saveWriteCanvasPreferences(settings);\n }, []);\n\n const [viewPreferences, setViewPreferences] = useState<ViewPreferences>(loadViewPreferences);\n const handleViewPreferencesChange = useCallback((prefs: ViewPreferences) => {\n setViewPreferences(prefs);\n saveViewPreferences(prefs);\n }, []);\n const isMobile = useIsMobile();\n const [mobileShowEditor, setMobileShowEditor] = useState(false);\n // Sidebar width -- persisted across sessions, dragged via the resizer\n // between sidebar and editor area. We track the \"live\" width during a\n // drag in a ref so each mousemove doesn't trigger a state update; only\n // setState on commit so React doesn't churn through every pixel.\n const [sidebarWidth, setSidebarWidth] = useState<number>(loadSidebarWidth);\n // When the user drags the resizer below SIDEBAR_COLLAPSE_THRESHOLD,\n // we switch the layout into single-pane \"compact\" mode -- same UX as\n // the mobile narrow-viewport flow, where only the sidebar OR the\n // editor is visible at a time and a back-arrow in the toolbar pops\n // between them. A \"Restore split view\" button in either pane's header\n // exits compact mode; on real mobile that button is suppressed\n // because there's not enough viewport for side-by-side. Not\n // persisted across reloads. */\n const [compactLayout, setCompactLayout] = useState(false);\n const effectiveCompact = isMobile || compactLayout;\n const showBrowserStorageWarning = !isElectronHost();\n const issueReportUrl = buildIssueReportUrl({\n reportedAt: new Date(),\n version: isElectronHost()\n ? `${getDocBlocksHost().env.appVersion} desktop`\n : (issueReportVersion ?? 'web'),\n userAgent: typeof navigator === 'undefined' ? '' : navigator.userAgent,\n });\n const [browserStoragePersistent, setBrowserStoragePersistent] = useState(false);\n\n // --- The shell's three notification channels -------------------------\n // Declared up here because the popstate handler below is the earliest\n // consumer; everything that talks to the user goes through one of these\n // rather than through window.alert/confirm/prompt, which block the\n // renderer, ignore the theme, and wear the browser's name.\n\n // Ctrl/Cmd+S is a real acknowledgement of the session revision, not an\n // optimistic toast. A failed commit remains dirty and is surfaced.\n const [saveToast, setSaveToast] = useState<{\n kind: 'success' | 'error';\n message: string;\n } | null>(null);\n const saveToastTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n /**\n * The shell's one transient-notification channel. Everything that needs to\n * tell the user \"that worked\" / \"that didn't\" routes through here so the\n * self-dismiss timers cannot fight each other.\n */\n const showToast = useCallback((kind: 'success' | 'error', message: string) => {\n setSaveToast({ kind, message });\n if (saveToastTimerRef.current) clearTimeout(saveToastTimerRef.current);\n saveToastTimerRef.current = setTimeout(() => setSaveToast(null), 3000);\n }, []);\n\n // The shell's stand-in for `window.prompt()`, which Electron's renderer does\n // not implement -- calling it there throws and the action dies silently.\n const { prompt: promptForText, promptDialog } = usePromptDialog();\n\n // Stand-ins for `window.confirm()` (a question) and `window.alert()` (a\n // message worth stopping for). Transient outcomes use showToast instead.\n const { confirm: confirmAction, acknowledge, confirmDialog } = useConfirmDialog();\n\n // The file tree asks before deleting; give it this shell's dialog so the\n // prompt matches the product rather than falling back to its native one.\n const confirmDeleteEntry = useCallback(\n (message: string) =>\n confirmAction({\n title: 'Delete',\n message,\n confirmLabel: 'Delete',\n destructive: true,\n }),\n [confirmAction],\n );\n\n // Browser PWA install prompt (Chromium only). The event is stashed when\n // the browser deems the app installable and spent on first use.\n const [installPromptEvent, setInstallPromptEvent] = useState<BeforeInstallPromptEvent | null>(\n null,\n );\n const sidebarRef = useRef<HTMLDivElement>(null);\n const dragStateRef = useRef<{ startX: number; startWidth: number } | null>(null);\n const handleResizerPointerDown = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n dragStateRef.current = { startX: e.clientX, startWidth: sidebarWidth };\n e.preventDefault();\n // Disable text selection + flip the body cursor for the duration\n // of the drag so the col-resize cursor stays visible even when the\n // pointer slips off the 7px hit area. The custom cursor lives in\n // the CSS class so Windows' white-cursor preference doesn't make\n // the dragging cursor invisible against the light chrome.\n document.body.style.userSelect = 'none';\n document.body.classList.add('db-resizing-sidebar');\n let lastRaw = sidebarWidth;\n const onMove = (ev: PointerEvent) => {\n const drag = dragStateRef.current;\n if (!drag) return;\n lastRaw = drag.startWidth + (ev.clientX - drag.startX);\n if (lastRaw < SIDEBAR_COLLAPSE_THRESHOLD && sidebarRef.current) {\n // Below threshold -- preview the collapse by snapping to the\n // minimum width and fading the sidebar, so the user can see\n // they've crossed into \"release to collapse\" territory.\n sidebarRef.current.style.width = `${SIDEBAR_WIDTH_MIN}px`;\n sidebarRef.current.style.opacity = '0.45';\n return;\n }\n const clamped = Math.min(SIDEBAR_WIDTH_MAX, Math.max(SIDEBAR_WIDTH_MIN, lastRaw));\n if (sidebarRef.current) {\n // Update the DOM directly during the drag for jank-free\n // dragging; React state syncs on release.\n sidebarRef.current.style.width = `${clamped}px`;\n sidebarRef.current.style.opacity = '';\n }\n };\n const onUp = () => {\n document.removeEventListener('pointermove', onMove);\n document.removeEventListener('pointerup', onUp);\n document.body.style.userSelect = '';\n document.body.classList.remove('db-resizing-sidebar');\n if (sidebarRef.current) {\n sidebarRef.current.style.opacity = '';\n }\n if (lastRaw < SIDEBAR_COLLAPSE_THRESHOLD) {\n // Released below threshold -- switch to compact (single-pane)\n // layout focused on the document pane. Keep the persisted\n // sidebarWidth so exiting compact mode restores it.\n setCompactLayout(true);\n setMobileShowEditor(true);\n } else {\n const finalWidth = sidebarRef.current?.getBoundingClientRect().width;\n if (finalWidth) {\n const clamped = Math.min(\n SIDEBAR_WIDTH_MAX,\n Math.max(SIDEBAR_WIDTH_MIN, Math.round(finalWidth)),\n );\n setSidebarWidth(clamped);\n saveSidebarWidth(clamped);\n }\n }\n dragStateRef.current = null;\n };\n document.addEventListener('pointermove', onMove);\n document.addEventListener('pointerup', onUp);\n },\n [sidebarWidth],\n );\n const [provider, setProvider] = useState<FileSystemProvider | null>(null);\n const [workspaceStartupError, setWorkspaceStartupError] = useState<string | null>(null);\n const [activeWorkspaceId, setActiveWorkspaceId] = useState<string | null>(null);\n const [activeWorkspaceDescriptor, setActiveWorkspaceDescriptor] =\n useState<WorkspaceDescriptor | null>(null);\n useEffect(() => {\n if (!provider || getTransientWorkspace(provider.id)) return;\n const providerV2 = getFileSystemProviderV2(provider);\n return providerV2 ? retainFileSystemProvider(providerV2) : undefined;\n }, [provider]);\n // Re-fetch the descriptor whenever the active id (or its versioning\n // override) changes. `descriptorRefreshKey` is bumped after writes so\n // the resolver picks up the updated override without remounting.\n const [descriptorRefreshKey, setDescriptorRefreshKey] = useState(0);\n useEffect(() => {\n let cancelled = false;\n if (!activeWorkspaceId) {\n setActiveWorkspaceDescriptor(null);\n return;\n }\n void getWorkspace(activeWorkspaceId).then((ws) => {\n if (!cancelled) setActiveWorkspaceDescriptor(ws);\n });\n return () => {\n cancelled = true;\n };\n }, [activeWorkspaceId, descriptorRefreshKey]);\n const [transientMoveDestinations, setTransientMoveDestinations] = useState<WorkspaceDescriptor[]>(\n [],\n );\n useEffect(() => {\n if (activeWorkspaceDescriptor?.type !== 'transient') {\n setTransientMoveDestinations([]);\n return;\n }\n let cancelled = false;\n const electron = isElectronHost();\n void listWorkspaces()\n .then((workspaces) => {\n if (cancelled) return;\n setTransientMoveDestinations(\n workspaces.filter(\n (workspace) =>\n workspace.type !== 'transient' &&\n (electron\n ? workspace.type === 'electron-native'\n : workspace.type !== 'electron-native'),\n ),\n );\n })\n .catch(() => {\n if (!cancelled) setTransientMoveDestinations([]);\n });\n return () => {\n cancelled = true;\n };\n }, [activeWorkspaceDescriptor]);\n\n // All git UI state/actions -- null-renders on surfaces without git.\n const gitWorkspaceId =\n provider &&\n activeWorkspaceDescriptor?.id === activeWorkspaceId &&\n provider.id === activeWorkspaceId &&\n activeWorkspaceDescriptor.type === 'electron-native'\n ? activeWorkspaceDescriptor.id\n : null;\n const git = useGit(provider, gitWorkspaceId, resolvedTheme);\n const gitRef = useRef(git);\n gitRef.current = git;\n const { scheduleRefresh: gitScheduleRefresh } = git;\n\n const [workspaceSettingsOpen, setWorkspaceSettingsOpen] = useState(false);\n const [versioningPreference, setVersioningPreference] =\n useState<VersioningPreference>(loadVersioningPreference);\n const handleVersioningPreferenceChange = useCallback((pref: VersioningPreference) => {\n setVersioningPreference(pref);\n saveVersioningPreference(pref);\n }, []);\n const effectiveVersioning =\n allowVersioning && resolveVersioningEnabled(activeWorkspaceDescriptor, versioningPreference);\n\n const handleOpenWorkspaceSettings = useCallback(() => {\n if (!activeWorkspaceDescriptor) return;\n setWorkspaceSettingsOpen(true);\n }, [activeWorkspaceDescriptor]);\n\n const handleWorkspaceVersioningOverrideChange = useCallback(\n async (override: WorkspaceVersioningOverride) => {\n if (!activeWorkspaceDescriptor) return;\n await saveWorkspace({ ...activeWorkspaceDescriptor, versioningOverride: override });\n setDescriptorRefreshKey((k) => k + 1);\n setWorkspaceSettingsOpen(false);\n },\n [activeWorkspaceDescriptor],\n );\n const [selectedFile, setSelectedFile] = useState<string | null>(null);\n useDocumentTitle(selectedFile, homeDocumentTitle, homeDocumentPath);\n const exportDestinationAdapter = useMemo<ExportDestinationAdapter | undefined>(() => {\n if (!isElectronHost() || !activeWorkspaceId || !selectedFile) return undefined;\n const documentId = JSON.stringify([activeWorkspaceId, selectedFile]);\n const host = getDocBlocksHost().exports;\n return {\n resolveTarget: (filename) => host.resolveTarget(documentId, filename),\n pickTarget: (filename, currentTarget) =>\n host.pickTarget(documentId, filename, currentTarget?.grantId ?? null),\n saveBlob: async (blob, filename, target) =>\n host.save(documentId, filename, target?.grantId ?? null, await blob.arrayBuffer()),\n };\n }, [activeWorkspaceId, selectedFile]);\n const [selectedFolder, setSelectedFolder] = useState<string | null>(null);\n const [folderEntries, setFolderEntries] = useState<FileSystemEntry[]>([]);\n const { session: documentSession, snapshot: documentSnapshot } = useDocumentSession(500);\n // The session snapshot is the sole owner of document content and edit\n // identity. React retains only presentation state (path/folder/view).\n const editorContent = documentSnapshot.content;\n const editorSessionScope = useMemo<DocumentSessionEditScope | null>(\n () =>\n documentSnapshot.targetKey && !documentSnapshot.frozen\n ? {\n targetKey: documentSnapshot.targetKey,\n generation: documentSnapshot.generation,\n }\n : null,\n [documentSnapshot.frozen, documentSnapshot.generation, documentSnapshot.targetKey],\n );\n const [editorPresentationEpoch, setEditorPresentationEpoch] = useState(0);\n const editorKey = `${documentSnapshot.generation}:${editorPresentationEpoch}`;\n const editorPlaceholder = useMemo(() => {\n // Keep the selection scoped to the same generation that remounts Squisq.\n void editorKey;\n return pickEmptyDocumentPrompt();\n }, [editorKey]);\n const [explorerKey, setExplorerKey] = useState(0);\n const [documentLinkEpoch, setDocumentLinkEpoch] = useState(0);\n const [initialView, setInitialView] = useState<EditorView>('wysiwyg');\n const [initialSharedMode, setInitialSharedMode] = useState<SharedDocumentMode | null>(null);\n // First-run gateway over the welcome document's Play view.\n const [showWelcomeGateway, setShowWelcomeGateway] = useState(false);\n const navigationRequestRef = useRef(0);\n const workspaceAuthorityBarrier = useMemo(() => new WorkspaceAuthorityBarrier(), []);\n const preparedCloseRequestRef = useRef<string | null>(null);\n const pendingDbkConflictsRef = useRef(new Map<string, PendingDbkConflict>());\n\n const createDocumentTarget = useCallback(\n (\n fsProvider: FileSystemProvider,\n workspaceId: string,\n filePath: string,\n ): DocumentCommitTarget => {\n const transient = getTransientWorkspace(workspaceId);\n const baseTarget = createFileSystemDocumentTarget(fsProvider, filePath);\n\n const originKind = transient?.descriptor.origin?.kind;\n const needsElectronHost = originKind === 'loose-file' || originKind === 'dbk';\n if (!transient?.descriptor.origin || (needsElectronHost && !isElectronHost())) {\n return {\n key: baseTarget.key,\n async commit(request) {\n const result = await baseTarget.commit(request);\n gitScheduleRefresh();\n return result;\n },\n };\n }\n\n const origin = transient.descriptor.origin;\n\n if (origin.kind === 'web-file' || origin.kind === 'web-dbk') {\n // Launched-file origins (installed web app, File Handling API):\n // read and write through the FileSystemFileHandle instead of the\n // Electron host bridge, with the same optimistic external-change\n // detection as the host-backed paths below.\n const webOrigin = origin;\n const transientProvider = transient.provider;\n return {\n key: baseTarget.key,\n async commit(request) {\n if (!(await ensureHandleWritePermission(webOrigin.handle))) {\n throw new Error(\n `DocBlocks needs permission to write to \"${webOrigin.name}\". Save again to grant it.`,\n );\n }\n if (webOrigin.kind === 'web-file') {\n const current = await (await webOrigin.handle.getFile()).text();\n if (\n request.persistedContent !== null &&\n current !== request.persistedContent &&\n current !== request.content\n ) {\n pendingDbkConflictsRef.current.delete(baseTarget.key);\n await writeProviderText(fsProvider, filePath, current);\n throw new DocumentCommitConflictError(\n 'The original file changed outside DocBlocks.',\n current,\n null,\n );\n }\n const writable = await webOrigin.handle.createWritable();\n await writable.write(request.content);\n await writable.close();\n await baseTarget.commit(request);\n pendingDbkConflictsRef.current.delete(baseTarget.key);\n gitScheduleRefresh();\n return {};\n }\n // web-dbk: package the in-memory workspace into a zip and write\n // it back through the handle, guarded by a SHA-256\n // compare-and-swap that mirrors the Electron dbk path.\n const [{ MemoryContentContainer }, { containerToZip }] = await Promise.all([\n import('@bendyline/squisq/storage'),\n import('@bendyline/squisq-formats/container'),\n ]);\n const currentBytes = await (await webOrigin.handle.getFile()).arrayBuffer();\n const currentVersion = await sha256Hex(currentBytes);\n if (webOrigin.version !== null && currentVersion !== webOrigin.version) {\n if (!isMemoryWorkspaceProvider(transientProvider)) {\n throw new Error('A transient DBK workspace must use in-memory storage.');\n }\n const snapshot = await decodeDbkWorkspace(currentBytes, {\n targetDocumentPath: filePath,\n });\n // Keep both branches intact until the user chooses -- same\n // semantics as the Electron dbk conflict staging below.\n pendingDbkConflictsRef.current.set(baseTarget.key, {\n provider: transientProvider,\n snapshot,\n });\n webOrigin.version = currentVersion;\n throw new DocumentCommitConflictError(\n 'The original DocBlocks bundle changed outside DocBlocks.',\n snapshot.documentContent,\n currentVersion,\n );\n }\n const container = new MemoryContentContainer();\n await copyProviderToContainer(transientProvider, container, '');\n await container.writeFile(\n filePath.replace(/^\\/+/, ''),\n new TextEncoder().encode(request.content),\n );\n const blob = await containerToZip(container);\n const bytes = await blob.arrayBuffer();\n const writable = await webOrigin.handle.createWritable();\n await writable.write(bytes);\n await writable.close();\n webOrigin.version = await sha256Hex(bytes);\n // The transient provider intentionally retained the complete\n // local branch while external bundle B was staged for conflict\n // resolution. Once bundle C is committed to the origin, advance\n // that internal markdown baseline unconditionally; comparing its\n // old A content against request.persistedContent B would report a\n // false second conflict after the durable write already succeeded.\n await writeProviderText(fsProvider, filePath, request.content);\n pendingDbkConflictsRef.current.delete(baseTarget.key);\n gitScheduleRefresh();\n return { version: webOrigin.version };\n },\n };\n }\n\n return {\n key: baseTarget.key,\n async commit(request) {\n const host = getDocBlocksHost();\n if (origin.kind === 'loose-file') {\n const result = await host.external.commitText(\n origin.resourceId,\n request.content,\n request.persistedContent,\n );\n if (result.status === 'conflict') {\n pendingDbkConflictsRef.current.delete(baseTarget.key);\n if (result.content === null) await removeProviderEntry(fsProvider, filePath);\n else await writeProviderText(fsProvider, filePath, result.content);\n throw new DocumentCommitConflictError(\n 'The original file changed outside DocBlocks.',\n result.content,\n result.version,\n );\n }\n await baseTarget.commit(request);\n pendingDbkConflictsRef.current.delete(baseTarget.key);\n gitScheduleRefresh();\n return { version: result.version };\n } else {\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 copyProviderToContainer(transient.provider, container, '');\n await container.writeFile(\n filePath.replace(/^\\/+/, ''),\n new TextEncoder().encode(request.content),\n );\n const blob = await containerToZip(container);\n const result = await host.external.commitBinary(\n origin.resourceId,\n await blob.arrayBuffer(),\n origin.version,\n );\n if (result.status === 'conflict') {\n let externalContent: string | null = null;\n if (result.data) {\n if (!isMemoryWorkspaceProvider(transient.provider)) {\n throw new Error('A transient DBK workspace must use in-memory storage.');\n }\n const snapshot = await decodeDbkWorkspace(result.data, {\n targetDocumentPath: filePath,\n });\n externalContent = snapshot.documentContent;\n // Keep both branches intact until the user chooses. Reload\n // replaces the whole tree; Keep mine packages this untouched\n // local provider against the newly observed bundle version.\n pendingDbkConflictsRef.current.set(baseTarget.key, {\n provider: transient.provider,\n snapshot,\n });\n } else {\n pendingDbkConflictsRef.current.delete(baseTarget.key);\n }\n // Advance the optimistic origin only after the external bundle\n // has been completely staged. A parse/read failure must retry\n // against the old version rather than silently authorize an\n // overwrite of data we could not reconcile.\n origin.version = result.version;\n throw new DocumentCommitConflictError(\n 'The original DocBlocks bundle changed outside DocBlocks.',\n externalContent,\n result.version,\n );\n }\n origin.version = result.version;\n // As with web-dbk above, the in-memory provider still represents\n // the preserved local branch rather than the external conflict\n // baseline. The origin commit is the conditional authority check;\n // now make the internal document agree with that acknowledged C\n // bundle without re-comparing A against B.\n await writeProviderText(fsProvider, filePath, request.content);\n pendingDbkConflictsRef.current.delete(baseTarget.key);\n gitScheduleRefresh();\n return { version: result.version };\n }\n },\n };\n },\n [gitScheduleRefresh],\n );\n\n /**\n * Per-file media container: for `notes.md`, images live in\n * `notes_files/` next to the markdown. Created lazily on first write,\n * picked up automatically if it already exists. Set up by the effect\n * below whenever the selected file (or backing provider) changes.\n */\n const mediaContainerRef = useRef<ContentContainer | null>(null);\n const [mediaProvider, setMediaProvider] = useState<MediaProvider | null>(null);\n const [mediaEpoch, setMediaEpoch] = useState(0);\n /**\n * Per-document container scoped to `<basename>_files/`. This is what\n * the editor uses for version history (`.versions/` lives here) and\n * for audio mapping (MP3 / timing.json discovery). Distinct from\n * `mediaContainerRef` which is scoped to the parent directory so the\n * media provider can write `notes_files/image.png` paths that stay\n * portable in the markdown.\n */\n const versionsContainerRef = useRef<ContentContainer | null>(null);\n const [versionsContainer, setVersionsContainer] = useState<ContentContainer | null>(null);\n\n /** Push a new history entry with the given hash. */\n const pushHash = useCallback((wsId: string, filePath?: string | null) => {\n const hash = buildHash(wsId, filePath);\n if (window.location.hash !== hash) {\n window.history.pushState(null, '', hash);\n }\n }, []);\n\n /** Open a workspace (and optionally a file) from identifiers.\n * Returns the FileSystemProvider on success, or null on failure. */\n const openFromIds = useCallback(\n async (\n wsId: string,\n filePath: string | null,\n push: boolean,\n view?: EditorView,\n navigationRequestId?: number,\n sharedMode: SharedDocumentMode | null = null,\n ): Promise<FileSystemProvider | null> => {\n const requestId = navigationRequestId ?? ++navigationRequestRef.current;\n if (requestId !== navigationRequestRef.current) return null;\n // Transient (session-only) workspaces -- a loose file or `.dbk` opened\n // from the OS -- carry a pre-built in-memory provider in the registry.\n const transient = getTransientWorkspace(wsId);\n let ws: WorkspaceDescriptor | undefined;\n let fsProvider: FileSystemProvider | null = null;\n if (transient) {\n ws = transient.descriptor;\n fsProvider = transient.provider;\n } else {\n const workspaces = await listWorkspaces();\n ws = workspaces.find((w) => w.id === wsId);\n if (!ws) return null;\n if (ws.type === 'electron-native') {\n fsProvider = await createElectronProviderFromWorkspace(ws);\n if (!fsProvider) return null;\n } else if (ws.type === 'native') {\n const restored = await (await loadNativeFileSystem()).restoreNativeFolder(ws.id);\n if (!restored) return null;\n fsProvider = restored;\n } else {\n fsProvider = await createIndexedDbFileSystemProvider(ws.id, ws.name);\n }\n }\n if (!ws || !fsProvider) return null;\n let adopted = false;\n try {\n await touchWorkspace(ws.id);\n if (requestId !== navigationRequestRef.current) return null;\n\n let openedFile: string | null = null;\n let openedContent = '';\n const transitioned = await documentSession.transitionWithLoad(async () => {\n if (requestId !== navigationRequestRef.current) return null;\n if (filePath) {\n const content = await readProviderText(fsProvider, filePath);\n if (requestId !== navigationRequestRef.current) return null;\n if (content !== null) {\n openedFile = filePath;\n openedContent = content;\n }\n }\n\n return {\n target: openedFile ? createDocumentTarget(fsProvider, ws.id, openedFile) : null,\n content: openedContent,\n };\n });\n if (!transitioned) return null;\n\n // Once the session has accepted this target, ownership must follow it\n // even if a newer navigation request arrived in the final microtask.\n // The newer request will perform the next serialized transition.\n setProvider(fsProvider);\n adopted = true;\n setActiveWorkspaceId(ws.id);\n if (openedFile) {\n setSelectedFile(openedFile);\n setSelectedFolder(null);\n setFolderEntries([]);\n const effectiveView = view ?? 'wysiwyg';\n setInitialView(effectiveView);\n setInitialSharedMode(sharedMode);\n // Transient workspaces are session-only; don't persist them as the\n // \"last opened\" state (the id won't exist after a reload).\n if (!transient) {\n saveLastState({ workspaceId: wsId, filePath: openedFile, view: effectiveView });\n }\n } else {\n setSelectedFile(null);\n setSelectedFolder(null);\n setFolderEntries([]);\n setInitialSharedMode(null);\n }\n\n if (push) {\n pushHash(ws.id, openedFile);\n }\n return fsProvider;\n } finally {\n if (!transient && !adopted) await getFileSystemProviderV2(fsProvider)?.dispose();\n }\n },\n [createDocumentTarget, documentSession, pushHash],\n );\n\n const adoptTransientWorkspace = useCallback(\n async (options: {\n id: string;\n name: string;\n provider: MemoryFileSystemProvider;\n primaryFile: string;\n origin?: WorkspaceDescriptor['origin'];\n push: boolean;\n navigationRequestId?: number;\n view?: EditorView;\n sharedMode?: SharedDocumentMode | null;\n }): Promise<boolean> => {\n const descriptor: WorkspaceDescriptor = {\n id: options.id,\n name: options.name,\n type: 'transient',\n lastOpened: new Date().toISOString(),\n ...(options.origin ? { origin: options.origin } : {}),\n };\n let opened = false;\n registerTransientWorkspace(descriptor, options.provider);\n try {\n opened =\n (await openFromIds(\n options.id,\n `/${options.primaryFile.replace(/^\\/+/, '')}`,\n options.push,\n options.view,\n options.navigationRequestId,\n options.sharedMode ?? null,\n )) !== null;\n return opened;\n } finally {\n if (!opened && getTransientWorkspace(options.id)?.provider === options.provider) {\n await unregisterTransientWorkspace(options.id);\n }\n }\n },\n [openFromIds],\n );\n\n const openSharedDocument = useCallback(\n async (payload: SharedDocumentPayload, navigationRequestId: number): Promise<boolean> => {\n const id = `transient-shared-${navigationRequestId}`;\n const mem = await createMemoryFileSystemProvider(id, 'Shared document');\n const primaryFile = 'shared.md';\n try {\n const snapshot = await decodeDbkWorkspace(payload.archive, {\n targetDocumentPath: primaryFile,\n profile: 'shared-link',\n });\n mem.replaceContents(snapshot);\n } catch (error: unknown) {\n await getFileSystemProviderV2(mem)?.dispose();\n throw error;\n }\n\n return adoptTransientWorkspace({\n id,\n name: 'Shared document',\n provider: mem,\n primaryFile,\n push: false,\n navigationRequestId,\n view: payload.mode ? 'preview' : 'wysiwyg',\n sharedMode: payload.mode,\n });\n },\n [adoptTransientWorkspace],\n );\n\n const seedWelcomeFile = useCallback(\n async (fs: FileSystemProvider, navigationRequestId?: number) => {\n const isCurrent = () =>\n navigationRequestId === undefined || navigationRequestId === navigationRequestRef.current;\n if (!isCurrent()) return;\n const entries = await readProviderDirectory(fs, '/');\n if (!isCurrent()) return;\n\n // If the only file is the welcome doc, auto-select it.\n // Match either casing so workspaces seeded before the rename\n // (aboutDocblocks.md) keep working alongside new ones (aboutDocBlocks.md).\n if (\n entries.length === 1 &&\n entries[0].kind === 'file' &&\n entries[0].path.replace(/^\\//, '').toLowerCase() === 'aboutdocblocks.md'\n ) {\n const aboutPath = entries[0].path;\n const content = await readProviderText(fs, aboutPath);\n if (content !== null && isCurrent()) {\n await documentSession.transitionTo(createDocumentTarget(fs, fs.id, aboutPath), content);\n if (!isCurrent()) return;\n setSelectedFile(aboutPath);\n setInitialView('preview');\n setInitialSharedMode(null);\n setExplorerKey((k) => k + 1);\n pushHash(fs.id, aboutPath);\n saveLastState({ workspaceId: fs.id, filePath: aboutPath, view: 'preview' });\n if (!isWelcomeGatewayDismissed()) setShowWelcomeGateway(true);\n }\n return;\n }\n\n if (entries.length > 0) return;\n\n const welcomePath = '/aboutDocBlocks.md';\n const welcomeContent = [\n '# DocBlocks: the local-first Markdown editor',\n '',\n 'Your markdown can do anything.',\n '',\n 'DocBlocks is a free browser-based markdown document editor that lets you create, organize, and manage your documents right in the browser. What you write here can become a Word or PDF doc, a slide deck, an e-book, or a video.',\n '',\n 'Simple to write. Beautiful wherever it goes.',\n '',\n '## Features',\n '',\n '- **Rich Markdown Editing** -- Write in a visual editor or switch to raw markdown source anytime. Use section annotations to change the visualization for blocks of content.',\n '- **Workspaces** -- Organize your documents into separate workspaces in the browser or on your device.',\n '- **Useful Everywhere** -- Your content is usable across multiple formats -- Microsoft Word .docx, PowerPoint, PDF, HTML, EPUB e-books, and Markdown.',\n '- **Playback & Video** -- Preview your documents as rich visual presentations and export them as MP4 video',\n '- **No BS** -- Free, no ads, no accounts, no tracking - everything runs locally in your browser',\n '',\n '## Getting Started',\n '',\n '1. Create a new file using the **New File** button in the sidebar',\n '2. Start writing in markdown -- the editor supports headings, lists, links, images, and more',\n '3. Your work is saved automatically',\n '',\n 'Built on [Squiggly Square markdown extensions](https://github.com/bendyline/squisq) by [Bendyline](https://bendyline.com).',\n '',\n '## Explore DocBlocks',\n '',\n '- [Desktop app](https://docblocks.com/desktop/) for macOS, Windows, and Linux',\n '- [VS Code extension](https://docblocks.com/vscode/) for rich editing inside your workspace',\n '- [CLI and MCP server](https://docblocks.com/cli/) for conversion and agent workflows',\n '- [Supported formats](https://docblocks.com/formats/) and [documentation](https://docblocks.com/docs/)',\n ].join('\\n');\n\n let seededContent = welcomeContent;\n try {\n await writeProviderText(fs, welcomePath, welcomeContent, 'create');\n } catch (error: unknown) {\n if (!(error instanceof FsError && error.code === 'already-exists')) throw error;\n const existing = await readProviderText(fs, welcomePath);\n if (existing === null) throw error;\n seededContent = existing;\n }\n if (!isCurrent()) return;\n await documentSession.transitionTo(\n createDocumentTarget(fs, fs.id, welcomePath),\n seededContent,\n );\n if (!isCurrent()) return;\n setSelectedFile(welcomePath);\n setInitialView('preview');\n setInitialSharedMode(null);\n setExplorerKey((k) => k + 1);\n pushHash(fs.id, welcomePath);\n saveLastState({ workspaceId: fs.id, filePath: welcomePath, view: 'preview' });\n if (!isWelcomeGatewayDismissed()) setShowWelcomeGateway(true);\n },\n [createDocumentTarget, documentSession, pushHash],\n );\n\n // Startup is a mount lifecycle, not a reaction to callback identity. Keep\n // the latest implementations available without letting git/provider state\n // changes restart initialization and supersede an OS-open navigation.\n const startupOpenFromIdsRef = useRef(openFromIds);\n startupOpenFromIdsRef.current = openFromIds;\n const startupOpenSharedDocumentRef = useRef(openSharedDocument);\n startupOpenSharedDocumentRef.current = openSharedDocument;\n const startupSeedWelcomeFileRef = useRef(seedWelcomeFile);\n startupSeedWelcomeFileRef.current = seedWelcomeFile;\n\n /** Hide the welcome gateway and never show it again. Safe to call from\n * paths where it may not be showing -- only persists when it was. */\n const closeWelcomeGateway = useCallback(() => {\n setShowWelcomeGateway((showing) => {\n if (showing) markWelcomeGatewayDismissed();\n return false;\n });\n }, []);\n\n /** Gateway CTA -- flip the welcome doc from Play into the editor. */\n const handleStartWriting = useCallback(() => {\n closeWelcomeGateway();\n setInitialView('wysiwyg');\n setInitialSharedMode(null);\n setEditorPresentationEpoch((epoch) => epoch + 1);\n if (activeWorkspaceId && selectedFile) {\n saveLastState({ workspaceId: activeWorkspaceId, filePath: selectedFile, view: 'wysiwyg' });\n }\n }, [closeWelcomeGateway, activeWorkspaceId, selectedFile]);\n\n // Initialise workspace on mount -- restore from hash or last-used\n useEffect(() => {\n const requestId = ++navigationRequestRef.current;\n let cancelled = false;\n const isCurrent = () => !cancelled && requestId === navigationRequestRef.current;\n\n void (async () => {\n const electron = isElectronHost();\n let workspaceIdRemap: Readonly<Record<string, string>> = {};\n if (electron) {\n // Main-process persisted roots are authoritative after an upgrade or\n // collision repair. Reconcile renderer metadata before hash or\n // last-state restoration so an obsolete id cannot reopen a different\n // folder that once shared its legacy id.\n try {\n const localWorkspaces = await listWorkspaces();\n const hostWorkspaces = await getDocBlocksHost().workspaces.list();\n const reconciliation = reconcileElectronWorkspaceDescriptors(\n localWorkspaces,\n hostWorkspaces,\n getDocBlocksHost().env.platform,\n new Date().toISOString(),\n );\n for (const id of reconciliation.removeIds) await removeWorkspace(id);\n for (const workspace of reconciliation.upsert) await saveWorkspace(workspace);\n workspaceIdRemap = reconciliation.idRemap;\n } catch {\n workspaceAuthorityBarrier.markReady();\n if (isCurrent()) {\n setWorkspaceStartupError(\n 'DocBlocks could not verify access to your saved workspaces. Restart the app or open the folder again.',\n );\n }\n return;\n }\n }\n workspaceAuthorityBarrier.markReady();\n if (!isCurrent()) return;\n\n // Shared links are a distinct, bounded wire format. Never let malformed\n // shared input fall through and become a workspace id.\n const sharedHash = parseSharedDocumentHash(window.location.hash);\n if (sharedHash.kind === 'invalid') {\n setWorkspaceStartupError(sharedHash.message);\n return;\n }\n if (sharedHash.kind === 'valid') {\n try {\n const opened = await startupOpenSharedDocumentRef.current(sharedHash.payload, requestId);\n if (!isCurrent()) return;\n if (!opened) {\n setWorkspaceStartupError('This shared document link could not be opened.');\n }\n } catch (error: unknown) {\n if (isCurrent()) {\n setWorkspaceStartupError(\n error instanceof Error\n ? `This shared document link could not be opened: ${error.message}`\n : 'This shared document link could not be opened.',\n );\n }\n }\n return;\n }\n\n // Try restoring an ordinary workspace route from the URL hash first.\n const hashState = parseHash();\n if (hashState) {\n const migratedWorkspaceId = workspaceIdRemap[hashState.workspaceId];\n const restoredWorkspaceId = migratedWorkspaceId ?? hashState.workspaceId;\n if (migratedWorkspaceId) {\n window.history.replaceState(null, '', buildHash(restoredWorkspaceId, hashState.filePath));\n }\n const restoredProvider = await startupOpenFromIdsRef.current(\n restoredWorkspaceId,\n hashState.filePath,\n false,\n undefined,\n requestId,\n );\n if (!isCurrent()) return;\n if (restoredProvider) {\n // If the hash had no file, check whether we should auto-select the welcome doc\n if (!hashState.filePath) {\n await startupSeedWelcomeFileRef.current(restoredProvider, requestId);\n }\n return;\n }\n }\n\n // Try restoring last viewed document from localStorage\n const lastState = loadLastState();\n if (lastState) {\n const restoredWorkspaceId =\n workspaceIdRemap[lastState.workspaceId] ?? lastState.workspaceId;\n if (restoredWorkspaceId !== lastState.workspaceId) {\n saveLastState({ ...lastState, workspaceId: restoredWorkspaceId });\n }\n const restoredProvider = await startupOpenFromIdsRef.current(\n restoredWorkspaceId,\n lastState.filePath,\n true,\n lastState.view,\n requestId,\n );\n if (!isCurrent()) return;\n if (restoredProvider) return;\n }\n\n let fsProvider: FileSystemProvider | null = null;\n\n const workspaces = await listWorkspaces();\n if (!isCurrent()) return;\n // On desktop, hide web-only workspaces (indexeddb/native) -- only\n // folder-based workspaces are valid.\n const candidates = electron\n ? workspaces.filter((w) => w.type === 'electron-native')\n : workspaces.filter((w) => w.type !== 'electron-native');\n // Pick the most recently opened workspace\n const sorted = [...candidates].sort((a, b) =>\n (b.lastOpened ?? '').localeCompare(a.lastOpened ?? ''),\n );\n for (const ws of sorted) {\n if (ws.type === 'electron-native') {\n const p = await createElectronProviderFromWorkspace(ws);\n if (!p) continue;\n if (!isCurrent()) {\n await getFileSystemProviderV2(p)?.dispose();\n return;\n }\n await touchWorkspace(ws.id);\n if (!isCurrent()) {\n await getFileSystemProviderV2(p)?.dispose();\n return;\n }\n fsProvider = p;\n break;\n } else if (ws.type === 'native') {\n const restored = await (await loadNativeFileSystem()).restoreNativeFolder(ws.id);\n if (restored) {\n if (!isCurrent()) {\n await getFileSystemProviderV2(restored)?.dispose();\n return;\n }\n await touchWorkspace(ws.id);\n if (!isCurrent()) {\n await getFileSystemProviderV2(restored)?.dispose();\n return;\n }\n fsProvider = restored;\n break;\n }\n } else {\n const p = await createIndexedDbFileSystemProvider(ws.id, ws.name);\n if (!isCurrent()) {\n await getFileSystemProviderV2(p)?.dispose();\n return;\n }\n await touchWorkspace(ws.id);\n if (!isCurrent()) {\n await getFileSystemProviderV2(p)?.dispose();\n return;\n }\n fsProvider = p;\n break;\n }\n }\n\n if (!fsProvider) {\n if (electron) {\n // Desktop: ask the host for the default folder workspace\n // (creates DocBlocks in the OS-resolved Documents folder on first launch).\n const info = await getDocBlocksHost().workspaces.getDefault();\n if (!isCurrent()) return;\n const descriptor: WorkspaceDescriptor = {\n id: info.id,\n name: info.name,\n type: 'electron-native',\n rootPath: info.rootPath,\n lastOpened: new Date().toISOString(),\n };\n await saveWorkspace(descriptor);\n if (!isCurrent()) return;\n const p = await createElectronFileSystemProvider(info.id, info.name, info.rootPath);\n if (!isCurrent()) {\n await getFileSystemProviderV2(p)?.dispose();\n return;\n }\n fsProvider = p;\n } else {\n // Web: create the IndexedDB default workspace\n const defaultWs = await ensureDefaultWorkspace();\n if (!isCurrent()) return;\n const p = await createIndexedDbFileSystemProvider(defaultWs.id, defaultWs.name);\n if (!isCurrent()) {\n await getFileSystemProviderV2(p)?.dispose();\n return;\n }\n fsProvider = p;\n }\n }\n\n let adopted = false;\n try {\n if (!isCurrent()) return;\n // Set the root hash before seeding; seedWelcomeFile replaces it with\n // the welcome path when it opens that document.\n pushHash(fsProvider.id, null);\n await startupSeedWelcomeFileRef.current(fsProvider, requestId);\n if (!isCurrent()) return;\n setProvider(fsProvider);\n setActiveWorkspaceId(fsProvider.id);\n adopted = true;\n } finally {\n if (!adopted) await getFileSystemProviderV2(fsProvider)?.dispose();\n }\n })().catch(() => {\n if (isCurrent()) {\n setWorkspaceStartupError(\n 'DocBlocks could not initialize your workspace. Restart the app or open the folder again.',\n );\n }\n });\n\n return () => {\n cancelled = true;\n if (navigationRequestRef.current === requestId) navigationRequestRef.current += 1;\n };\n }, [pushHash, workspaceAuthorityBarrier]);\n\n // Handle browser back/forward\n useEffect(() => {\n const onPopState = () => {\n const requestedHash = window.location.hash;\n const restoreCurrentHash = () => {\n if (!activeWorkspaceId || window.location.hash !== requestedHash) return;\n window.history.replaceState(null, '', buildHash(activeWorkspaceId, selectedFile));\n };\n const sharedHash = parseSharedDocumentHash(requestedHash);\n if (sharedHash.kind === 'invalid') {\n restoreCurrentHash();\n showToast('error', sharedHash.message);\n return;\n }\n if (sharedHash.kind === 'valid') {\n const requestId = ++navigationRequestRef.current;\n void openSharedDocument(sharedHash.payload, requestId)\n .then((opened) => {\n if (!opened) restoreCurrentHash();\n })\n .catch((error: unknown) => {\n restoreCurrentHash();\n showToast(\n 'error',\n error instanceof Error\n ? 'DocBlocks could not open the shared document: ' + error.message\n : 'DocBlocks could not open the shared document.',\n );\n });\n return;\n }\n\n const hashState = parseHash();\n if (hashState) {\n void openFromIds(hashState.workspaceId, hashState.filePath, false)\n .then((opened) => {\n if (!opened) restoreCurrentHash();\n })\n .catch((error: unknown) => {\n restoreCurrentHash();\n showToast(\n 'error',\n error instanceof Error\n ? 'DocBlocks could not switch documents: ' + error.message\n : 'DocBlocks could not switch documents.',\n );\n });\n }\n };\n window.addEventListener('popstate', onPopState);\n return () => window.removeEventListener('popstate', onPopState);\n }, [activeWorkspaceId, openFromIds, openSharedDocument, selectedFile, showToast]);\n\n useEffect(() => {\n if (!showBrowserStorageWarning || typeof navigator === 'undefined') return;\n const storage = navigator.storage;\n if (!storage || typeof storage.persisted !== 'function') return;\n\n let cancelled = false;\n void storage\n .persisted()\n .then((persistent) => {\n if (!cancelled) setBrowserStoragePersistent(persistent);\n })\n .catch(() => {\n // Ignore unsupported/denied checks; the menu action can still try persist().\n });\n\n return () => {\n cancelled = true;\n };\n }, [showBrowserStorageWarning]);\n\n // Browser PWA install plumbing. Chromium fires `beforeinstallprompt` when\n // the app is installable; stashing it (after preventDefault) lets the app\n // menu offer \"Install DocBlocks…\" on our terms. `appinstalled` fires for\n // any install path (menu item or the browser's own omnibox affordance).\n useEffect(() => {\n if (isElectronHost() || typeof window === 'undefined') return;\n const onBeforeInstallPrompt = (e: BeforeInstallPromptEvent) => {\n e.preventDefault();\n setInstallPromptEvent(e);\n };\n const onAppInstalled = () => {\n setInstallPromptEvent(null);\n // Chromium auto-grants persistent storage to installed apps -- re-probe\n // so the \"Keep data in browser for longer\" nag retires itself.\n const storage = navigator.storage;\n if (storage && typeof storage.persisted === 'function') {\n storage\n .persisted()\n .then((persistent) => {\n if (persistent) setBrowserStoragePersistent(true);\n })\n .catch(() => {\n // Probe is best-effort; the manual menu action still works.\n });\n }\n };\n window.addEventListener('beforeinstallprompt', onBeforeInstallPrompt);\n window.addEventListener('appinstalled', onAppInstalled);\n return () => {\n window.removeEventListener('beforeinstallprompt', onBeforeInstallPrompt);\n window.removeEventListener('appinstalled', onAppInstalled);\n };\n }, []);\n\n const handleInstallApp = useCallback(async () => {\n const promptEvent = installPromptEvent;\n // prompt() is single-use: clear the stash up front and rely on the\n // browser re-firing beforeinstallprompt if the user dismisses.\n setInstallPromptEvent(null);\n if (!promptEvent) return;\n try {\n await promptEvent.prompt();\n await promptEvent.userChoice;\n } catch {\n // The prompt was already consumed or is not allowed right now.\n }\n }, [installPromptEvent]);\n\n // Track view mode changes (Editor/Raw/Play tabs) and persist to localStorage\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n const target = (e.target as HTMLElement).closest?.('[data-view]');\n if (target) {\n const view = target.getAttribute('data-view') as EditorView;\n if (view) {\n // The user found the view tabs on their own -- the gateway's job is done.\n closeWelcomeGateway();\n }\n if (view && activeWorkspaceId && selectedFile) {\n saveLastState({ workspaceId: activeWorkspaceId, filePath: selectedFile, view });\n }\n }\n };\n window.addEventListener('click', handler, true);\n return () => window.removeEventListener('click', handler, true);\n }, [activeWorkspaceId, selectedFile, closeWelcomeGateway]);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const sKey = e.key === 's' || e.key === 'S';\n const accel = e.ctrlKey || e.metaKey;\n if (!sKey || !accel || e.altKey) return;\n e.preventDefault();\n e.stopPropagation();\n void (async () => {\n try {\n await documentSession.flush('manual');\n showToast('success', 'Saved. You’re all set.');\n } catch (error: unknown) {\n showToast(\n 'error',\n isQuotaExceededError(error)\n ? 'Could not save -- browser storage is full. Free up space or back up your work.'\n : error instanceof Error\n ? error.message\n : 'Could not save this document.',\n );\n }\n })();\n };\n window.addEventListener('keydown', onKey, true);\n return () => window.removeEventListener('keydown', onKey, true);\n }, [documentSession, showToast]);\n useEffect(() => {\n return () => {\n if (saveToastTimerRef.current) clearTimeout(saveToastTimerRef.current);\n };\n }, []);\n\n // One-time passive notice when the host reports the app is fully cached\n // for offline use. Mirrors the save toast's look and self-dismissal.\n const [offlineReadyToast, setOfflineReadyToast] = useState(false);\n const offlineReadyAnnouncedRef = useRef(false);\n useEffect(() => {\n if (!offlineReady || offlineReadyAnnouncedRef.current) return;\n offlineReadyAnnouncedRef.current = true;\n setOfflineReadyToast(true);\n const timer = setTimeout(() => setOfflineReadyToast(false), 3000);\n return () => clearTimeout(timer);\n }, [offlineReady]);\n\n // Quota-exhaustion banner. The session clears `error` on every keystroke\n // and at each retry, so the raw snapshot flickers during a failing\n // type/retry loop -- latch it, and release only when a commit succeeds.\n // Known gap: version-snapshot writes (squisq's DocumentVersionManager)\n // swallow their own failures upstream (`SaveVersionResult` has no error\n // variant), but they hit the same provider, so the primary autosave\n // latches this banner within one edit cycle anyway.\n const [storageFull, setStorageFull] = useState(false);\n useEffect(() => {\n if (documentSnapshot.error && isQuotaExceededError(documentSnapshot.error)) {\n setStorageFull(true);\n } else if (documentSnapshot.status === 'saved') {\n setStorageFull(false);\n }\n }, [documentSnapshot.error, documentSnapshot.status]);\n\n // Ask the browser to make origin storage durable the first time real work\n // is saved (browser surface only, once per session). Chromium decides\n // silently -- installed apps are auto-granted; Firefox may show one prompt\n // at this meaningful moment rather than at page load.\n const autoPersistRequestedRef = useRef(false);\n useEffect(() => {\n if (!showBrowserStorageWarning || browserStoragePersistent) return;\n if (autoPersistRequestedRef.current) return;\n if (documentSnapshot.status !== 'saved') return;\n const storage = typeof navigator !== 'undefined' ? navigator.storage : undefined;\n if (!storage || typeof storage.persist !== 'function') return;\n autoPersistRequestedRef.current = true;\n storage\n .persist()\n .then((granted) => {\n if (granted) setBrowserStoragePersistent(true);\n })\n .catch(() => {\n // Best-effort; the manual menu action remains available.\n });\n }, [showBrowserStorageWarning, browserStoragePersistent, documentSnapshot.status]);\n\n // Per-file media: for `notes.md` images live in `notes_files/` beside it.\n // Rebuilds whenever the provider or selected file changes.\n useEffect(() => {\n if (!provider || !selectedFile) {\n mediaContainerRef.current = null;\n versionsContainerRef.current = null;\n setMediaProvider(null);\n setVersionsContainer(null);\n return;\n }\n const parentDir = dirnameOf(selectedFile);\n const base = basenameOf(selectedFile);\n const baseNoExt = base.replace(/\\.[^.]+$/, '');\n const container = new FileSystemContentContainer(provider, parentDir);\n const vPrefix = parentDir ? `${parentDir}/${baseNoExt}_files` : `${baseNoExt}_files`;\n const vContainer = new FileSystemContentContainer(provider, vPrefix);\n const mp = createFileMediaProvider(container, base);\n mediaContainerRef.current = container;\n versionsContainerRef.current = vContainer;\n setMediaProvider(mp);\n setVersionsContainer(vContainer);\n return () => {\n mp.dispose();\n };\n }, [provider, selectedFile, mediaEpoch]);\n\n const documentLinkProvider = useDocumentLinkProvider(provider, selectedFile, documentLinkEpoch);\n\n // Expose a DocumentVersionManager via versioningRef when requested.\n useEffect(() => {\n const ref = versioningRef;\n if (!ref) return;\n const assign = (mgr: DocumentVersionManager | null) => {\n if (typeof ref === 'function') ref(mgr);\n else (ref as React.MutableRefObject<DocumentVersionManager | null>).current = mgr;\n };\n if (!effectiveVersioning || !versionsContainer || !selectedFile) {\n assign(null);\n return;\n }\n const base = stripExtension(basenameOf(selectedFile));\n const mgr = new DocumentVersionManager(versionsContainer, {\n basename: versionBasename ?? base,\n });\n assign(mgr);\n return () => assign(null);\n }, [versioningRef, effectiveVersioning, versionBasename, selectedFile, versionsContainer]);\n\n // React to external file changes watched by the Electron host (chokidar).\n useEffect(() => {\n if (!provider) return;\n const providerV2 = getFileSystemProviderV2(provider);\n if (!providerV2?.capabilities.watch) return;\n if (!selectedFile || !documentSnapshot.targetKey) return;\n const watchedFile = selectedFile;\n const targetKey = documentSnapshot.targetKey;\n let disposed = false;\n let reading = false;\n let rerun = false;\n let observationSequence = 0;\n\n const drainWatcherReads = async () => {\n if (reading) {\n rerun = true;\n return;\n }\n reading = true;\n try {\n do {\n rerun = false;\n const sequence = ++observationSequence;\n const external = await readStableFileSnapshot(provider, watchedFile);\n if (disposed) return;\n const result = documentSession.observeExternal({\n targetKey,\n sequence,\n content: external.content,\n version: external.version,\n });\n if (result === 'applied') {\n // observeExternal increments the session generation. The editor\n // remount key and content both derive from that snapshot.\n }\n } while (rerun && !disposed);\n } catch {\n // The next watcher event will retry a file that was changing too\n // quickly to obtain a stable content/metadata pair.\n } finally {\n reading = false;\n if (rerun && !disposed) void drainWatcherReads();\n }\n };\n\n const subscription = providerV2.watch(\n (event) => {\n if (event.type === 'overflow') {\n void drainWatcherReads();\n return;\n }\n const changedCurrent = sameProviderPath(event.path, watchedFile);\n const changedDestination =\n event.destinationPath !== null && sameProviderPath(event.destinationPath, watchedFile);\n if (changedCurrent || changedDestination) void drainWatcherReads();\n },\n {\n onError: () => {\n // Re-read the active file on watcher failure. The session decides\n // whether the result is a clean update or an external conflict.\n void drainWatcherReads();\n },\n },\n );\n void subscription.ready.catch(() => undefined);\n return () => {\n disposed = true;\n void subscription.dispose();\n };\n }, [provider, selectedFile, documentSession, documentSnapshot.targetKey]);\n\n const transitionAwayFromDocument = useCallback(\n async (requestId: number): Promise<boolean> => {\n if (requestId !== navigationRequestRef.current) return false;\n try {\n const transitioned = await documentSession.transitionWithLoad(async () =>\n requestId === navigationRequestRef.current ? { target: null, content: '' } : null,\n );\n if (!transitioned || requestId !== navigationRequestRef.current) return false;\n return true;\n } catch (error: unknown) {\n showToast(\n 'error',\n error instanceof Error\n ? 'DocBlocks could not save this document: ' + error.message\n : 'DocBlocks could not save this document.',\n );\n return false;\n }\n },\n [documentSession, showToast],\n );\n\n const handleUseExternalDocument = useCallback(async () => {\n const conflictKey = documentSession.getSnapshot().conflict?.targetKey;\n const pendingDbk = conflictKey ? pendingDbkConflictsRef.current.get(conflictKey) : undefined;\n try {\n if (pendingDbk) {\n pendingDbk.provider.replaceContents(pendingDbk.snapshot);\n pendingDbkConflictsRef.current.delete(conflictKey!);\n setDocumentLinkEpoch((epoch) => epoch + 1);\n setMediaEpoch((epoch) => epoch + 1);\n setExplorerKey((key) => key + 1);\n }\n const snapshot = await documentSession.resolveConflict('use-external');\n if (!snapshot.targetKey) {\n setSelectedFile(null);\n if (activeWorkspaceId) pushHash(activeWorkspaceId, null);\n }\n } catch (error: unknown) {\n setSaveToast({\n kind: 'error',\n message: error instanceof Error ? error.message : 'Could not reload the external document.',\n });\n }\n }, [activeWorkspaceId, documentSession, pushHash]);\n\n const handleKeepLocalDocument = useCallback(async () => {\n const conflictKey = documentSession.getSnapshot().conflict?.targetKey;\n try {\n await documentSession.resolveConflict('use-local');\n if (conflictKey) pendingDbkConflictsRef.current.delete(conflictKey);\n setSaveToast({ kind: 'success', message: 'Your version was saved.' });\n } catch (error: unknown) {\n setSaveToast({\n kind: 'error',\n message: error instanceof Error ? error.message : 'Could not save your version.',\n });\n }\n }, [documentSession]);\n\n useEffect(() => {\n const needsWarning = ['dirty', 'saving', 'error', 'conflict'].includes(documentSnapshot.status);\n if (!documentSnapshot.targetKey) return;\n const flushBestEffort = () => {\n void documentSession.flush('close').catch(() => {\n // A browser cannot await asynchronous storage during teardown. The\n // beforeunload warning remains active when persistence is unresolved.\n });\n };\n const onBeforeUnload = (event: BeforeUnloadEvent) => {\n flushBestEffort();\n if (!needsWarning) return;\n event.preventDefault();\n event.returnValue = '';\n };\n const onPageHide = () => flushBestEffort();\n const onVisibilityChange = () => {\n if (document.visibilityState === 'hidden') flushBestEffort();\n };\n window.addEventListener('beforeunload', onBeforeUnload);\n window.addEventListener('pagehide', onPageHide);\n document.addEventListener('visibilitychange', onVisibilityChange);\n return () => {\n window.removeEventListener('beforeunload', onBeforeUnload);\n window.removeEventListener('pagehide', onPageHide);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n };\n }, [documentSession, documentSnapshot.status, documentSnapshot.targetKey]);\n\n // Electron can defer window destruction and await this acknowledgement.\n // Browser unload remains best-effort, which is why continuous autosave is\n // still the primary durability mechanism.\n useEffect(() => {\n if (!isElectronHost()) return;\n const lifecycle = getDocBlocksHost().lifecycle;\n const stopPrepare = lifecycle.onPrepareClose(async (request) => {\n preparedCloseRequestRef.current = request.requestId;\n try {\n const snapshot = await documentSession.prepareClose();\n return { status: 'ready' as const, persistedRevision: snapshot.persistedRevision };\n } catch (error: unknown) {\n preparedCloseRequestRef.current = null;\n return {\n status: 'blocked' as const,\n code:\n error instanceof DocumentSessionConflictError\n ? ('external-conflict' as const)\n : ('save-failed' as const),\n message: error instanceof Error ? error.message : 'Could not save the document.',\n };\n }\n });\n const stopCancel = lifecycle.onCancelClose((requestId) => {\n if (preparedCloseRequestRef.current !== requestId) return;\n preparedCloseRequestRef.current = null;\n documentSession.cancelClose();\n });\n return () => {\n stopPrepare();\n stopCancel();\n };\n }, [documentSession]);\n\n const handleWorkspaceSelect = useCallback(\n async (ws: WorkspaceDescriptor) => {\n const requestId = ++navigationRequestRef.current;\n await touchWorkspace(ws.id);\n if (requestId !== navigationRequestRef.current) return;\n let nextProvider: FileSystemProvider | null = null;\n const transient = getTransientWorkspace(ws.id);\n if (transient) {\n nextProvider = transient.provider;\n } else if (ws.type === 'electron-native') {\n nextProvider = await createElectronProviderFromWorkspace(ws);\n if (!nextProvider) return;\n } else if (ws.type === 'native') {\n const restored = await (await loadNativeFileSystem()).restoreNativeFolder(ws.id);\n if (!restored) {\n // Permission denied or handle lost -- fall through without changing provider\n return;\n }\n nextProvider = restored;\n } else {\n nextProvider = await createIndexedDbFileSystemProvider(ws.id, ws.name);\n }\n if (requestId !== navigationRequestRef.current) return;\n if (!(await transitionAwayFromDocument(requestId))) return;\n setProvider(nextProvider);\n setActiveWorkspaceId(ws.id);\n setSelectedFile(null);\n setSelectedFolder(null);\n setFolderEntries([]);\n pushHash(ws.id, null);\n },\n [pushHash, transitionAwayFromDocument],\n );\n\n const handleMoveTransientWorkspace = useCallback(\n async (destinationWorkspaceId: string) => {\n if (!activeWorkspaceId || !provider || !selectedFile) {\n throw new Error('Select the temporary document before moving it.');\n }\n const transient = getTransientWorkspace(activeWorkspaceId);\n if (!transient || transient.provider !== provider) {\n throw new Error('This workspace is no longer temporary.');\n }\n const destination = transientMoveDestinations.find(\n (workspace) => workspace.id === destinationWorkspaceId,\n );\n if (!destination) {\n throw new Error('That destination workspace is no longer available.');\n }\n\n const requestId = ++navigationRequestRef.current;\n let destinationProvider: FileSystemProvider | null = null;\n let adoptedDestination = false;\n const sourceTargetKey = documentSnapshot.targetKey;\n\n try {\n if (destination.type === 'electron-native') {\n destinationProvider = await createElectronProviderFromWorkspace(destination);\n } else if (destination.type === 'native') {\n destinationProvider = await (\n await loadNativeFileSystem()\n ).restoreNativeFolder(destination.id);\n } else {\n destinationProvider = await createIndexedDbFileSystemProvider(\n destination.id,\n destination.name,\n );\n }\n if (!destinationProvider) {\n throw new Error(\n `DocBlocks could not open “${destination.name}”. Open that workspace and grant access, then try again.`,\n );\n }\n const openedDestination = destinationProvider;\n\n const moved = await documentSession.transitionWithLoad(async () => {\n if (requestId !== navigationRequestRef.current) return null;\n const content = await readProviderText(provider, selectedFile);\n if (content === null) {\n throw new Error('The temporary document is no longer available.');\n }\n await copyTransientWorkspaceContents(provider, openedDestination);\n return {\n target: createDocumentTarget(openedDestination, destination.id, selectedFile),\n content,\n };\n });\n if (!moved) {\n throw new Error('The move was interrupted by another navigation request.');\n }\n\n adoptedDestination = true;\n setProvider(openedDestination);\n setActiveWorkspaceId(destination.id);\n setActiveWorkspaceDescriptor(destination);\n setSelectedFile(selectedFile);\n setSelectedFolder(null);\n setFolderEntries([]);\n setInitialView('wysiwyg');\n setInitialSharedMode(null);\n setExplorerKey((key) => key + 1);\n closeWelcomeGateway();\n pushHash(destination.id, selectedFile);\n saveLastState({\n workspaceId: destination.id,\n filePath: selectedFile,\n view: 'wysiwyg',\n });\n if (effectiveCompact) setMobileShowEditor(true);\n void touchWorkspace(destination.id).catch(() => undefined);\n if (sourceTargetKey) pendingDbkConflictsRef.current.delete(sourceTargetKey);\n\n const origin = transient.descriptor.origin;\n if (isElectronHost() && origin && (origin.kind === 'loose-file' || origin.kind === 'dbk')) {\n try {\n await getDocBlocksHost().external.revoke(origin.resourceId);\n } catch {\n // Navigation and renderer teardown also revoke external grants.\n }\n }\n try {\n await removeWorkspace(activeWorkspaceId);\n } catch {\n // The transient registry forgets the entry before provider disposal;\n // a disposal failure must not make a successful move look undone.\n }\n setDescriptorRefreshKey((key) => key + 1);\n } catch (error: unknown) {\n if (destinationProvider && !adoptedDestination) {\n try {\n await getFileSystemProviderV2(destinationProvider)?.dispose();\n } catch {\n // Preserve the move failure as the actionable error.\n }\n }\n throw error;\n }\n },\n [\n activeWorkspaceId,\n closeWelcomeGateway,\n createDocumentTarget,\n documentSession,\n documentSnapshot.targetKey,\n effectiveCompact,\n provider,\n pushHash,\n selectedFile,\n transientMoveDestinations,\n ],\n );\n\n const handleOpenFolder = useCallback(async () => {\n const requestId = ++navigationRequestRef.current;\n try {\n if (isElectronHost()) {\n const info = await getDocBlocksHost().workspaces.pickFolder();\n if (!info) return; // user cancelled\n if (requestId !== navigationRequestRef.current) return;\n const descriptor: WorkspaceDescriptor = {\n id: info.id,\n name: info.name,\n type: 'electron-native',\n rootPath: info.rootPath,\n lastOpened: new Date().toISOString(),\n };\n await saveWorkspace(descriptor);\n if (requestId !== navigationRequestRef.current) return;\n const provider = await createElectronFileSystemProvider(info.id, info.name, info.rootPath);\n if (!(await transitionAwayFromDocument(requestId))) return;\n setProvider(provider);\n setActiveWorkspaceId(descriptor.id);\n setSelectedFile(null);\n setSelectedFolder(null);\n setFolderEntries([]);\n pushHash(descriptor.id, null);\n return;\n }\n\n const nativeProvider = await (await loadNativeFileSystem()).openNativeFolder();\n if (requestId !== navigationRequestRef.current) return;\n const descriptor: WorkspaceDescriptor = {\n id: nativeProvider.id,\n name: nativeProvider.label,\n type: 'native',\n lastOpened: new Date().toISOString(),\n };\n await saveWorkspace(descriptor);\n if (requestId !== navigationRequestRef.current) return;\n if (!(await transitionAwayFromDocument(requestId))) return;\n setProvider(nativeProvider);\n setActiveWorkspaceId(descriptor.id);\n setSelectedFile(null);\n setSelectedFolder(null);\n setFolderEntries([]);\n pushHash(descriptor.id, null);\n } catch {\n // User cancelled or API not supported\n }\n }, [pushHash, transitionAwayFromDocument]);\n\n // A clone finished: the host already registered + persisted the folder,\n // so opening it mirrors the pickFolder success path exactly.\n const handleWorkspaceCloned = useCallback(\n (info: ElectronWorkspaceInfo) => {\n const requestId = ++navigationRequestRef.current;\n void (async () => {\n const descriptor: WorkspaceDescriptor = {\n id: info.id,\n name: info.name,\n type: 'electron-native',\n rootPath: info.rootPath,\n lastOpened: new Date().toISOString(),\n };\n await saveWorkspace(descriptor);\n if (requestId !== navigationRequestRef.current) return;\n const cloneProvider = await createElectronFileSystemProvider(\n info.id,\n info.name,\n info.rootPath,\n );\n if (!(await transitionAwayFromDocument(requestId))) return;\n setProvider(cloneProvider);\n setActiveWorkspaceId(descriptor.id);\n setSelectedFile(null);\n setSelectedFolder(null);\n setFolderEntries([]);\n pushHash(descriptor.id, null);\n })();\n },\n [pushHash, transitionAwayFromDocument],\n );\n\n const handleNewFile = useCallback(async () => {\n if (!provider) return;\n const name = await promptForText({\n title: 'New document',\n label: 'Document name',\n initialValue: 'Untitled.md',\n confirmLabel: 'Create',\n });\n if (!name) return;\n const filename = /\\.[a-zA-Z0-9]+$/.test(name) ? name : `${name}.md`;\n const path = '/' + filename;\n const content = '# ' + filename.replace(/\\.[^.]+$/, '') + '\\n';\n const requestId = ++navigationRequestRef.current;\n try {\n const transitioned = await documentSession.transitionWithLoad(async () => {\n if (requestId !== navigationRequestRef.current) return null;\n const providerV2 = getFileSystemProviderV2(provider);\n if (providerV2) {\n try {\n await writeProviderText(provider, path, content, 'create');\n } catch (error: unknown) {\n if (error instanceof FsError && error.code === 'already-exists') {\n throw new Error('A document with that name already exists.');\n }\n throw error;\n }\n } else if (provider.commitFile) {\n const result = await provider.commitFile(path, content, null);\n if (result.status === 'conflict') {\n throw new Error('A document with that name already exists.');\n }\n } else {\n if (await providerEntryExists(provider, path)) {\n throw new Error('A document with that name already exists.');\n }\n await writeProviderText(provider, path, content);\n }\n if (requestId !== navigationRequestRef.current) return null;\n return {\n target: createDocumentTarget(provider, activeWorkspaceId ?? provider.id, path),\n content,\n };\n });\n if (!transitioned) return;\n } catch (error: unknown) {\n showToast('error', error instanceof Error ? error.message : 'Could not create the document.');\n return;\n }\n setSelectedFile(path);\n setInitialView('wysiwyg');\n setInitialSharedMode(null);\n setExplorerKey((k) => k + 1);\n closeWelcomeGateway();\n if (activeWorkspaceId) {\n pushHash(activeWorkspaceId, '/' + filename);\n }\n }, [\n provider,\n activeWorkspaceId,\n pushHash,\n closeWelcomeGateway,\n createDocumentTarget,\n documentSession,\n promptForText,\n showToast,\n ]);\n\n // Manifest shortcut \"New document\" launches `/?action=new` (installed\n // PWA jump list). Handled once the first workspace/provider is ready,\n // then stripped from the URL so a reload doesn't re-trigger it.\n const actionNewHandledRef = useRef(false);\n useEffect(() => {\n if (!provider || actionNewHandledRef.current) return;\n if (typeof window === 'undefined') return;\n const params = new URLSearchParams(window.location.search);\n if (params.get('action') !== 'new') return;\n actionNewHandledRef.current = true;\n params.delete('action');\n const query = params.toString();\n window.history.replaceState(\n null,\n '',\n window.location.pathname + (query ? `?${query}` : '') + window.location.hash,\n );\n void handleNewFile();\n }, [provider, handleNewFile]);\n\n const handleRevealWorkspace = useCallback(async () => {\n if (!isElectronHost() || !activeWorkspaceId) return;\n const ws = await getWorkspace(activeWorkspaceId);\n if (ws?.type === 'electron-native' && ws.rootPath) {\n await getDocBlocksHost().shell.revealInFolder(ws.id);\n }\n }, [activeWorkspaceId]);\n\n // Subscribe to native menu commands (Electron host).\n useEffect(() => {\n if (!isElectronHost()) return;\n const host = getDocBlocksHost();\n return host.onMenuCommand((cmd) => {\n switch (cmd) {\n case 'file:new':\n handleNewFile();\n break;\n case 'file:openFolder':\n handleOpenFolder();\n break;\n case 'file:revealWorkspace':\n handleRevealWorkspace();\n break;\n case 'git:commit':\n if (gitRef.current.repo) gitRef.current.openDialog({ kind: 'commit' });\n break;\n case 'git:push':\n if (gitRef.current.repo) void gitRef.current.push();\n break;\n case 'git:pull':\n if (gitRef.current.repo) void gitRef.current.pull();\n break;\n case 'git:fetch':\n if (gitRef.current.repo) void gitRef.current.fetchRemote();\n break;\n case 'git:newBranch':\n if (gitRef.current.repo) {\n gitRef.current.openDialog({ kind: 'branches', createFocus: true });\n }\n break;\n case 'git:switchBranch':\n if (gitRef.current.repo) gitRef.current.openDialog({ kind: 'branches' });\n break;\n case 'git:history':\n if (gitRef.current.repo) gitRef.current.openDialog({ kind: 'history' });\n break;\n case 'git:clone':\n if (gitRef.current.available) gitRef.current.openDialog({ kind: 'clone' });\n break;\n case 'git:openOnRemote':\n gitRef.current.openOnRemote();\n break;\n case 'git:createPullRequest':\n if (gitRef.current.repo) void gitRef.current.createPullRequest();\n break;\n case 'help:viewOnGitHub':\n host.shell.openExternal('https://github.com/bendyline/docblocks');\n break;\n case 'help:checkForUpdates':\n host.updater.checkForUpdates().catch(() => {\n // errors surface via updater.onStatus\n });\n break;\n case 'help:about':\n void (async () => {\n const version = await host.updater.getVersion();\n // Deliberately a dialog, not a toast: the user asked to see this\n // and a version string they cannot read twice is useless.\n await acknowledge({ title: 'About DocBlocks', message: `DocBlocks ${version}` });\n })();\n break;\n default:\n break;\n }\n });\n }, [handleNewFile, handleOpenFolder, handleRevealWorkspace, acknowledge]);\n\n // OS open-file / deep-link handling lives after the container helpers it\n // depends on -- see the `openTransient` + onOpenRequest effect below.\n\n const handleSelect = useCallback(\n async (path: string, kind: 'file' | 'directory') => {\n if (!provider || !activeWorkspaceId) return;\n const requestId = ++navigationRequestRef.current;\n\n if (kind === 'directory') {\n if (!(await transitionAwayFromDocument(requestId))) return;\n if (requestId !== navigationRequestRef.current) return;\n setSelectedFile(null);\n setSelectedFolder(path);\n const entries = await readProviderDirectory(provider, path);\n if (requestId !== navigationRequestRef.current) return;\n setFolderEntries(entries);\n pushHash(activeWorkspaceId, null);\n } else {\n let content: string | null = null;\n try {\n const transitioned = await documentSession.transitionWithLoad(async () => {\n if (requestId !== navigationRequestRef.current) return null;\n content = await readProviderText(provider, path);\n if (requestId !== navigationRequestRef.current || content === null) return null;\n return {\n target: createDocumentTarget(provider, activeWorkspaceId, path),\n content,\n };\n });\n if (!transitioned) return;\n } catch (error: unknown) {\n showToast(\n 'error',\n error instanceof Error ? error.message : 'Could not switch documents.',\n );\n return;\n }\n if (requestId !== navigationRequestRef.current) return;\n setSelectedFile(path);\n setSelectedFolder(null);\n setFolderEntries([]);\n setInitialView('wysiwyg');\n setInitialSharedMode(null);\n closeWelcomeGateway();\n pushHash(activeWorkspaceId, path);\n saveLastState({ workspaceId: activeWorkspaceId, filePath: path, view: 'wysiwyg' });\n if (effectiveCompact) setMobileShowEditor(true);\n }\n },\n [\n provider,\n activeWorkspaceId,\n pushHash,\n effectiveCompact,\n closeWelcomeGateway,\n createDocumentTarget,\n documentSession,\n transitionAwayFromDocument,\n showToast,\n ],\n );\n\n const handleTreeMutation = useCallback<FileTreeMutationHandler>(\n async (change, mutate) => {\n if (!provider || !activeWorkspaceId || !selectedFile) {\n await mutate();\n return;\n }\n\n if (change.type === 'move') {\n const nextFile = relocateProviderPath(selectedFile, change.oldPath, change.newPath);\n if (nextFile !== selectedFile) {\n await documentSession.retarget(\n createDocumentTarget(provider, activeWorkspaceId, nextFile),\n mutate,\n );\n return;\n }\n }\n\n if (change.type === 'delete' && pathContains(change.path, selectedFile)) {\n await documentSession.delete(mutate);\n return;\n }\n\n await mutate();\n },\n [provider, activeWorkspaceId, selectedFile, documentSession, createDocumentTarget],\n );\n\n const handleTreeChange = useCallback(\n async (change?: FileTreeChange) => {\n if (!provider) return;\n setDocumentLinkEpoch((epoch) => epoch + 1);\n if (change?.type === 'move' && change.oldPath && change.newPath) {\n const nextFile = selectedFile\n ? relocateProviderPath(selectedFile, change.oldPath, change.newPath)\n : null;\n const nextFolder = selectedFolder\n ? relocateProviderPath(selectedFolder, change.oldPath, change.newPath)\n : null;\n\n if (nextFile !== selectedFile) {\n setSelectedFile(nextFile);\n if (activeWorkspaceId) {\n pushHash(activeWorkspaceId, nextFile);\n if (nextFile) {\n saveLastState({\n workspaceId: activeWorkspaceId,\n filePath: nextFile,\n view: 'wysiwyg',\n });\n }\n }\n }\n if (nextFolder !== selectedFolder) setSelectedFolder(nextFolder);\n if (nextFolder) setFolderEntries(await readProviderDirectory(provider, nextFolder));\n return;\n }\n\n // If the open file was deleted, clear the editor\n if (selectedFile) {\n const exists = await providerEntryExists(provider, selectedFile);\n if (!exists) {\n setSelectedFile(null);\n if (activeWorkspaceId) pushHash(activeWorkspaceId, null);\n }\n }\n if (selectedFolder) {\n const entries = await readProviderDirectory(provider, selectedFolder);\n setFolderEntries(entries);\n }\n },\n [provider, selectedFile, selectedFolder, activeWorkspaceId, pushHash],\n );\n\n /**\n * Copy non-markdown files from an imported container into the target\n * markdown file's `_files/` sibling folder, preserving the source's\n * relative structure.\n */\n const persistImportedMedia = useCallback(\n async (\n source: {\n listFiles(): Promise<Array<{ path: string; mimeType: string }>>;\n readFile(path: string): Promise<ArrayBuffer | null>;\n },\n target: FileSystemProvider,\n importedMarkdownPath: string,\n ) => {\n const parentDir = dirnameOf(importedMarkdownPath);\n const folder = basenameOf(importedMarkdownPath).replace(/\\.[^.]+$/, '') + '_files';\n const mediaRoot = parentDir ? `${parentDir}/${folder}` : folder;\n const entries = await source.listFiles();\n const targetV2 = getFileSystemProviderV2(target);\n for (const entry of entries) {\n if (entry.path.endsWith('.md')) continue;\n const data = await source.readFile(entry.path);\n if (!data) continue;\n const cleanPath = entry.path.replace(/^\\/+/, '');\n const destination = `${mediaRoot}/${cleanPath}`;\n if (targetV2) {\n await targetV2.writeFile(parseWorkspacePath(destination), data, {\n mode: 'upsert',\n createParents: true,\n });\n } else {\n await target.writeBinary(destination, data);\n }\n }\n },\n [],\n );\n\n const handleImportFiles = useCallback(\n async (files: File[]) => {\n if (!provider) return;\n const result = await importDroppedFiles(files, provider, {\n persistMedia: (source, path) => persistImportedMedia(source, provider, path),\n });\n // Refresh file tree so the new markdown files + _files folders show up.\n setExplorerKey((k) => k + 1);\n // A drop that failed used to be indistinguishable from no drop at all.\n const summary = summariseImport(result);\n if (summary) showToast(summary.kind, summary.message);\n },\n [provider, persistImportedMedia, showToast],\n );\n\n const handleEditorChange = useCallback(\n (source: string) => {\n if (!editorSessionScope) return;\n try {\n documentSession.edit(source, editorSessionScope);\n } catch {\n // A close/transition has frozen the session. Do not let a late editor\n // callback create view state that cannot be persisted.\n }\n },\n [documentSession, editorSessionScope],\n );\n\n const handleRenameWorkspace = useCallback(async () => {\n if (!activeWorkspaceId) return;\n const ws = await getWorkspace(activeWorkspaceId);\n if (!ws) return;\n const newName = await promptForText({\n title: 'Rename workspace',\n label: 'Workspace name',\n initialValue: ws.name,\n confirmLabel: 'Rename',\n });\n if (!newName || newName === ws.name) return;\n await saveWorkspace({ ...ws, name: newName });\n setDescriptorRefreshKey((key) => key + 1);\n }, [activeWorkspaceId, promptForText]);\n\n /**\n * Open a loose file or `.dbk` bundle delivered by the OS into a session-only\n * *transient* workspace backed by an in-memory provider. Loose files save\n * straight back to disk; bundles are re-zipped by the session commit target.\n */\n const openTransient = useCallback(\n async (\n req: Extract<OpenRequest, { kind: 'external-file' | 'external-bundle' }>,\n navigationRequestId: number,\n ) => {\n const isCurrent = () => navigationRequestId === navigationRequestRef.current;\n const host = getDocBlocksHost();\n const revokeAbandonedResource = () =>\n host.external.revoke(req.resourceId).catch(() => undefined);\n if (!isCurrent()) {\n await revokeAbandonedResource();\n return;\n }\n const id = `transient-${req.kind}-${req.resourceId}`;\n let mem: MemoryFileSystemProvider;\n try {\n mem = await createMemoryFileSystemProvider(id, req.name);\n } catch (error: unknown) {\n await revokeAbandonedResource();\n throw error;\n }\n if (!isCurrent()) {\n await getFileSystemProviderV2(mem)?.dispose();\n await revokeAbandonedResource();\n return;\n }\n let primaryFile: string;\n let origin: WorkspaceDescriptor['origin'];\n let adoptionStarted = false;\n let opened = false;\n\n try {\n if (req.kind === 'external-file') {\n const content = await host.external.readText(req.resourceId);\n if (content === null) {\n throw new Error('The external file is no longer available.');\n }\n if (!isCurrent()) return;\n primaryFile = req.name; // e.g. \"notes.md\"\n mem.seedText(primaryFile, content);\n origin = { kind: 'loose-file', resourceId: req.resourceId };\n } else {\n const bytes = await host.external.readBinary(req.resourceId);\n if (!bytes) {\n throw new Error('The external bundle is no longer available.');\n }\n if (!isCurrent()) return;\n const version = await sha256Hex(bytes);\n if (!isCurrent()) return;\n const base = req.name.replace(/\\.[^.]+$/, '');\n primaryFile = `${base}.md`;\n const snapshot = await decodeDbkWorkspace(bytes, {\n targetDocumentPath: primaryFile,\n });\n if (!isCurrent()) return;\n mem.replaceContents(snapshot);\n origin = { kind: 'dbk', resourceId: req.resourceId, version };\n }\n\n adoptionStarted = true;\n opened = await adoptTransientWorkspace({\n id,\n name: req.name,\n provider: mem,\n primaryFile,\n origin,\n push: true,\n navigationRequestId,\n });\n } finally {\n try {\n if (!adoptionStarted) {\n await getFileSystemProviderV2(mem)?.dispose();\n }\n } finally {\n if (!opened) await revokeAbandonedResource();\n }\n }\n },\n [adoptTransientWorkspace],\n );\n\n // Subscribe to OS open-file / deep-link requests.\n useEffect(() => {\n if (!isElectronHost()) return;\n const host = getDocBlocksHost();\n return host.onOpenRequest((req) => {\n // Claim the navigation when the OS request arrives, before any external\n // file read or bundle decoding. A slower older request can no longer\n // finish after and replace a newer document.\n const requestId = ++navigationRequestRef.current;\n void (\n req.kind === 'workspace-file'\n ? workspaceAuthorityBarrier.wait().then(() => {\n if (requestId !== navigationRequestRef.current) return null;\n return openFromIds(req.workspaceId, req.path, true, undefined, requestId).then(\n (opened) => {\n if (!opened && requestId === navigationRequestRef.current) {\n throw new Error('The requested workspace file is no longer available.');\n }\n return opened;\n },\n );\n })\n : openTransient(req, requestId)\n ).catch((error: unknown) => {\n if (requestId !== navigationRequestRef.current) return;\n showToast(\n 'error',\n error instanceof Error\n ? 'DocBlocks could not open the requested file: ' + error.message\n : 'DocBlocks could not open the requested file.',\n );\n });\n });\n }, [openFromIds, openTransient, workspaceAuthorityBarrier, showToast]);\n\n /**\n * Web counterpart of `openTransient`: a `.md` or `.dbk` launched into the\n * installed PWA (File Handling API) arrives as a FileSystemFileHandle.\n * Contents are seeded into the same session-only in-memory workspace;\n * saves write back through the handle (see `createDocumentTarget`).\n */\n const openTransientFromHandle = useCallback(\n async (handle: FileSystemFileHandle) => {\n const name = handle.name;\n const isBundle = /\\.(dbk|zip)$/i.test(name);\n // Keyed by file name: relaunching the same file replaces the registry\n // entry instead of piling up session workspaces. Two different files\n // that share a name would collide -- acceptable for session-only state.\n const id = `transient-web-${isBundle ? 'bundle' : 'file'}-${name}`;\n // Ask for write access while the OS-launch user activation is fresh so\n // autosave doesn't have to prompt mid-typing. Best-effort: a denial\n // surfaces on save, not on open.\n await ensureHandleWritePermission(handle);\n const mem = await createMemoryFileSystemProvider(id, name);\n const file = await handle.getFile();\n let primaryFile: string;\n let origin: WorkspaceDescriptor['origin'];\n let adoptionStarted = false;\n\n try {\n if (!isBundle) {\n primaryFile = name;\n mem.seedText(primaryFile, await file.text());\n origin = { kind: 'web-file', handle, name };\n } else {\n const bytes = await file.arrayBuffer();\n const version = await sha256Hex(bytes);\n const base = name.replace(/\\.[^.]+$/, '');\n primaryFile = `${base}.md`;\n const snapshot = await decodeDbkWorkspace(bytes, {\n targetDocumentPath: primaryFile,\n });\n mem.replaceContents(snapshot);\n origin = { kind: 'web-dbk', handle, name, version };\n }\n\n adoptionStarted = true;\n await adoptTransientWorkspace({\n id,\n name,\n provider: mem,\n primaryFile,\n origin,\n push: true,\n });\n } finally {\n if (!adoptionStarted) await getFileSystemProviderV2(mem)?.dispose();\n }\n },\n [adoptTransientWorkspace],\n );\n\n // Consume files the OS delivers to the installed PWA (Chromium desktop).\n // launchQueue buffers launch params until a consumer is set, so a\n // post-mount effect is early enough to catch the launching file.\n useEffect(() => {\n if (isElectronHost() || typeof window === 'undefined') return;\n const launchQueue = window.launchQueue;\n if (!launchQueue) return;\n launchQueue.setConsumer((params) => {\n if (params.files.length === 0) return;\n const handle = params.files[0];\n void openTransientFromHandle(handle).catch((error: unknown) => {\n showToast(\n 'error',\n error instanceof Error\n ? 'DocBlocks could not open the launched file: ' + error.message\n : 'DocBlocks could not open the launched file.',\n );\n });\n });\n }, [openTransientFromHandle, showToast]);\n\n const updateStatusBarVisible =\n viewPreferences.showStatusBar === true && selectedFile !== null && mediaProvider !== null;\n\n const handleDownloadWorkspace = useCallback(async () => {\n if (!provider) return;\n try {\n await documentSession.flush('backup');\n const [{ MemoryContentContainer }, { containerToZip }] = await Promise.all([\n import('@bendyline/squisq/storage'),\n import('@bendyline/squisq-formats/container'),\n ]);\n\n const container = new MemoryContentContainer();\n await copyProviderToContainer(provider, container, '');\n\n const blob = await containerToZip(container);\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n const safeName =\n (provider.label || 'workspace').replace(/[^a-z0-9_\\- ]/gi, '_').trim() || 'workspace';\n a.download = `${safeName}.zip`;\n a.click();\n URL.revokeObjectURL(url);\n } catch (err) {\n console.error('Failed to download workspace', err);\n showToast('error', 'Failed to download workspace. See console for details.');\n }\n }, [provider, documentSession, showToast]);\n\n /**\n * Bundle every workspace the host can open without further prompting\n * into a single zip, with each workspace nested under its own folder.\n * Native (browser-picked) workspaces whose handle hasn't been re-granted\n * for this session are skipped -- restoring them would require a user\n * gesture per workspace.\n */\n const handleDownloadAllWorkspaces = useCallback(async () => {\n try {\n await documentSession.flush('backup');\n const [{ MemoryContentContainer }, { containerToZip }] = await Promise.all([\n import('@bendyline/squisq/storage'),\n import('@bendyline/squisq-formats/container'),\n ]);\n\n const electron = isElectronHost();\n const all = await listWorkspaces();\n const candidates = all.filter((w) =>\n electron\n ? w.type === 'electron-native' || w.type === 'transient'\n : w.type !== 'electron-native',\n );\n if (candidates.length === 0) {\n showToast('error', 'No workspaces to download.');\n return;\n }\n\n const container = new MemoryContentContainer();\n const usedFolders = new Set<string>();\n const skipped: string[] = [];\n\n for (const ws of candidates) {\n let p: FileSystemProvider | null = null;\n let ownsProvider = false;\n try {\n const transient = getTransientWorkspace(ws.id);\n if (transient) {\n p = transient.provider;\n } else if (ws.type === 'electron-native') {\n p = await createElectronProviderFromWorkspace(ws);\n ownsProvider = p !== null;\n } else if (ws.type === 'native') {\n // Restore without prompting -- only succeeds when the browser\n // still remembers the granted handle for this origin/session.\n p = await (await loadNativeFileSystem()).restoreNativeFolder(ws.id);\n ownsProvider = p !== null;\n } else {\n p = await createIndexedDbFileSystemProvider(ws.id, ws.name);\n ownsProvider = true;\n }\n } catch (err) {\n console.warn(`Skipping workspace ${ws.name}:`, err);\n }\n\n if (!p) {\n skipped.push(ws.name);\n continue;\n }\n\n // Pick a unique, filesystem-safe folder name per workspace.\n const base = (ws.name || 'workspace').replace(/[^a-z0-9_\\- ]/gi, '_').trim() || 'workspace';\n let folder = base;\n let suffix = 2;\n while (usedFolders.has(folder)) {\n folder = `${base} (${suffix++})`;\n }\n usedFolders.add(folder);\n\n try {\n await copyProviderToContainer(p, container, folder);\n } finally {\n if (ownsProvider) await getFileSystemProviderV2(p)?.dispose();\n }\n }\n\n if (usedFolders.size === 0) {\n showToast('error', 'No workspaces could be opened for download.');\n return;\n }\n\n const blob = await containerToZip(container);\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n const stamp = new Date().toISOString().slice(0, 10);\n a.download = `docblocks-workspaces-${stamp}.zip`;\n a.click();\n URL.revokeObjectURL(url);\n\n if (skipped.length > 0) {\n // A dialog, not a toast: this names workspaces the user now has to go\n // re-grant one by one. A list you must act on cannot expire in 3s.\n await acknowledge({\n title: 'Some workspaces were skipped',\n message: `Downloaded ${usedFolders.size} workspace(s). Skipped ${skipped.length} that require re-granting access: ${skipped.join(', ')}.`,\n });\n }\n } catch (err) {\n console.error('Failed to download all workspaces', err);\n showToast('error', 'Failed to download all workspaces. See console for details.');\n }\n }, [documentSession, acknowledge, showToast]);\n\n const handleKeepBrowserData = useCallback(async () => {\n if (typeof navigator === 'undefined') return;\n\n // Every outcome here that ends in \"back up your documents\" is a dialog:\n // it is standing advice about the durability of the user's work, and a\n // toast that evaporates in 3s is the wrong channel for it. The one\n // outcome that asks nothing of the user -- storage is already persistent\n // -- is a plain success toast.\n const storage = navigator.storage;\n if (!storage || typeof storage.persist !== 'function') {\n await acknowledge({\n title: 'Persistent storage unavailable',\n message:\n 'This browser does not support persistent storage requests. Please back up browser docs frequently.',\n });\n return;\n }\n\n try {\n const alreadyPersistent =\n typeof storage.persisted === 'function' ? await storage.persisted() : false;\n if (alreadyPersistent) {\n setBrowserStoragePersistent(true);\n showToast('success', 'DocBlocks browser data is already marked as persistent.');\n return;\n }\n\n const granted = await storage.persist();\n if (granted) {\n setBrowserStoragePersistent(true);\n await acknowledge({\n title: 'Storage will be kept for longer',\n message:\n 'This browser will try to keep DocBlocks data for longer. Please still back up browser docs frequently.',\n });\n } else {\n await acknowledge({\n title: 'Storage request declined',\n message:\n 'The browser did not grant permanent storage for DocBlocks. Please try again in a day or two. Meanwhile, please back up browser documents frequently.',\n });\n }\n } catch {\n await acknowledge({\n title: 'Storage request failed',\n message:\n 'DocBlocks could not request persistent browser storage. Please back up browser docs frequently.',\n });\n }\n }, [acknowledge, showToast]);\n\n // Settings dialog \"Storage\" row (browser surface): usage/quota estimate.\n const getBrowserStorageEstimate = useCallback(async () => {\n if (typeof navigator === 'undefined') return null;\n const storage = navigator.storage;\n if (!storage || typeof storage.estimate !== 'function') return null;\n try {\n const { usage, quota } = await storage.estimate();\n if (typeof usage !== 'number' || typeof quota !== 'number') return null;\n return { usage, quota };\n } catch {\n return null;\n }\n }, []);\n\n const handleRemoveWorkspace = useCallback(async () => {\n if (!activeWorkspaceId) return;\n const ws = await getWorkspace(activeWorkspaceId);\n // Only a browser-local workspace's documents are DocBlocks' to destroy.\n // Folder-backed workspaces (Electron or File System Access) keep their\n // files on the user's disk, so promising the removal is irreversible there\n // would be a lie in the more alarming direction.\n const destroysDocuments = ws?.type === 'indexeddb';\n const confirmed = await confirmAction({\n title: 'Remove workspace',\n message: destroysDocuments\n ? 'Remove this workspace? Its documents will be permanently deleted.'\n : 'Remove this workspace from DocBlocks? The files on disk will not be deleted.',\n confirmLabel: 'Remove',\n // Only the browser-local case actually destroys the user's documents.\n destructive: destroysDocuments,\n });\n if (!confirmed) return;\n // No request-id re-check is needed across this await: unlike the native\n // confirm() it replaces, nothing above claimed a navigation. The id is\n // still taken *after* the user answers, so a navigation that happened\n // while the dialog was open is the one this request supersedes -- exactly\n // the ordering the synchronous version had.\n const requestId = ++navigationRequestRef.current;\n if (!(await transitionAwayFromDocument(requestId))) return;\n\n if (ws?.type === 'electron-native') {\n try {\n await getDocBlocksHost().workspaces.unregister(activeWorkspaceId);\n } catch {\n // ignore -- host cleanup is best-effort\n }\n } else if (ws?.type === 'transient') {\n const origin = ws.origin;\n if (isElectronHost() && origin && (origin.kind === 'loose-file' || origin.kind === 'dbk')) {\n try {\n await getDocBlocksHost().external.revoke(origin.resourceId);\n } catch {\n // Navigation/destruction also revokes the capability; removal is best effort.\n }\n }\n } else if (ws?.type === 'native') {\n await (await loadNativeFileSystem()).removeDirectoryHandle(activeWorkspaceId);\n } else if (ws?.type === 'indexeddb') {\n // A browser-local workspace's documents live in a DocBlocks-owned\n // IndexedDB database. Dropping only the descriptor would strand them:\n // invisible to the user, still charged against the origin quota, and\n // ready to reappear the moment a workspace reuses this id -- which\n // `ensureDefaultWorkspace` does on the very next launch for 'default'.\n await (await loadIndexedDbFileSystem()).deleteIndexedDBWorkspaceData(activeWorkspaceId);\n }\n await removeWorkspace(activeWorkspaceId);\n if (requestId !== navigationRequestRef.current) return;\n\n const electron = isElectronHost();\n // Switch to most recent remaining workspace or create default\n const remaining = (await listWorkspaces()).filter((w) =>\n electron ? w.type === 'electron-native' : w.type !== 'electron-native',\n );\n if (remaining.length > 0) {\n const next = remaining[0];\n await handleWorkspaceSelect(next);\n } else if (electron) {\n const info = await getDocBlocksHost().workspaces.getDefault();\n const descriptor: WorkspaceDescriptor = {\n id: info.id,\n name: info.name,\n type: 'electron-native',\n rootPath: info.rootPath,\n lastOpened: new Date().toISOString(),\n };\n await saveWorkspace(descriptor);\n const p = await createElectronFileSystemProvider(info.id, info.name, info.rootPath);\n setProvider(p);\n setActiveWorkspaceId(info.id);\n setSelectedFile(null);\n setSelectedFolder(null);\n setFolderEntries([]);\n } else {\n const defaultWs = await ensureDefaultWorkspace();\n const fsProvider = await createIndexedDbFileSystemProvider(defaultWs.id, defaultWs.name);\n setProvider(fsProvider);\n setActiveWorkspaceId(defaultWs.id);\n setSelectedFile(null);\n setSelectedFolder(null);\n setFolderEntries([]);\n }\n }, [activeWorkspaceId, handleWorkspaceSelect, transitionAwayFromDocument, confirmAction]);\n\n return (\n <div\n className={`db-shell${effectiveCompact ? ' db-shell--mobile' : ''}`}\n data-theme={resolvedTheme}\n data-accent={accentColor}\n data-document-status={documentSnapshot.status}\n >\n <GitContext.Provider value={git}>\n {promptDialog}\n {confirmDialog}\n {workspaceStartupError && (\n <div className=\"db-save-toast db-save-toast--error\" role=\"alert\" aria-live=\"assertive\">\n {workspaceStartupError}\n </div>\n )}\n {saveToast && (\n <div\n className={'db-save-toast db-save-toast--' + saveToast.kind}\n role={saveToast.kind === 'error' ? 'alert' : 'status'}\n aria-live={saveToast.kind === 'error' ? 'assertive' : 'polite'}\n >\n {saveToast.message}\n </div>\n )}\n {offlineReadyToast && !saveToast && (\n <div className=\"db-save-toast db-save-toast--success\" role=\"status\" aria-live=\"polite\">\n DocBlocks is ready to work offline.\n </div>\n )}\n {documentSnapshot.conflict && (\n <div className=\"db-document-conflict\" role=\"alert\">\n <span>\n This document changed outside DocBlocks. Your unsaved version is still intact.\n </span>\n <div className=\"db-document-conflict-actions\">\n <button type=\"button\" onClick={() => void handleKeepLocalDocument()}>\n Keep mine\n </button>\n <button type=\"button\" onClick={() => void handleUseExternalDocument()}>\n Reload external\n </button>\n </div>\n </div>\n )}\n {storageFull && !documentSnapshot.conflict && (\n <div className=\"db-storage-full-banner\" role=\"alert\">\n <span>\n Browser storage is full -- changes can&rsquo;t be saved. Free up space or back up your\n work now.\n </span>\n <div className=\"db-storage-full-banner-actions\">\n <button type=\"button\" onClick={() => void handleDownloadAllWorkspaces()}>\n Download all workspaces\n </button>\n <button type=\"button\" onClick={() => setStorageFull(false)}>\n Dismiss\n </button>\n </div>\n </div>\n )}\n {workspaceSettingsOpen && activeWorkspaceDescriptor && (\n <WorkspaceSettingsDialog\n workspace={activeWorkspaceDescriptor}\n globalVersioningPreference={versioningPreference}\n onChange={handleWorkspaceVersioningOverrideChange}\n onClose={() => setWorkspaceSettingsOpen(false)}\n />\n )}\n {/* Main area */}\n <div style={{ display: 'flex', flex: 1, overflow: 'hidden' }}>\n {/* Left sidebar -- hidden in compact layout when the editor is\n showing (compact = real mobile narrow viewport OR the user\n dragged the resizer below SIDEBAR_COLLAPSE_THRESHOLD). */}\n {(!effectiveCompact || !mobileShowEditor) && (\n <div\n ref={sidebarRef}\n className=\"db-shell-sidebar\"\n style={effectiveCompact ? undefined : { width: `${sidebarWidth}px` }}\n >\n <div className=\"db-shell-sidebar-header\">\n <AppMenu\n logoUrl={logoUrl}\n themePreference={themePreference}\n onThemeChange={handleThemeChange}\n accentColor={accentColor}\n onAccentColorChange={handleAccentColorChange}\n writeCanvasSettings={writeCanvasSettings}\n onWriteCanvasSettingsChange={handleWriteCanvasSettingsChange}\n versioningPreference={versioningPreference}\n onVersioningPreferenceChange={handleVersioningPreferenceChange}\n onDownloadAllWorkspaces={handleDownloadAllWorkspaces}\n onKeepBrowserData={\n showBrowserStorageWarning && !browserStoragePersistent\n ? handleKeepBrowserData\n : undefined\n }\n onInstallApp={installPromptEvent ? handleInstallApp : undefined}\n getStorageEstimate={\n showBrowserStorageWarning ? getBrowserStorageEstimate : undefined\n }\n storagePersistent={\n showBrowserStorageWarning ? browserStoragePersistent : undefined\n }\n />\n <WorkspacePicker\n activeWorkspaceId={activeWorkspaceId}\n refreshKey={descriptorRefreshKey}\n onSelect={handleWorkspaceSelect}\n onOpenFolder={handleOpenFolder}\n onCloneRepository={\n git.available ? () => git.openDialog({ kind: 'clone' }) : undefined\n }\n />\n <WorkspaceSettingsButton\n onSettings={handleOpenWorkspaceSettings}\n onRename={handleRenameWorkspace}\n onDownload={handleDownloadWorkspace}\n onRemove={handleRemoveWorkspace}\n />\n {compactLayout && !isMobile && (\n <button\n className=\"db-restore-split\"\n onClick={() => setCompactLayout(false)}\n aria-label=\"Restore split view\"\n title=\"Restore split view\"\n >\n <SplitViewIcon />\n </button>\n )}\n </div>\n {git.available && (\n <Suspense fallback={null}>\n <GitUI\n onOpenFile={(path) => void handleSelect(path, 'file')}\n onWorkspaceCloned={handleWorkspaceCloned}\n />\n </Suspense>\n )}\n <FileExplorer\n key={explorerKey}\n provider={provider}\n activeFilePath={selectedFile}\n onSelect={handleSelect}\n onTreeMutation={handleTreeMutation}\n onTreeChange={handleTreeChange}\n onImportFiles={handleImportFiles}\n confirmDelete={confirmDeleteEntry}\n moveDestinations={\n activeWorkspaceDescriptor?.type === 'transient'\n ? transientMoveDestinations\n : undefined\n }\n onMoveToWorkspace={\n activeWorkspaceDescriptor?.type === 'transient'\n ? handleMoveTransientWorkspace\n : undefined\n }\n />\n <div className=\"db-shell-sidebar-footer\">\n <a href=\"https://docblocks.com/docs/\" target=\"_blank\" rel=\"noopener noreferrer\">\n Docs\n </a>\n <span className=\"db-shell-sidebar-footer-separator\" aria-hidden=\"true\">\n &bull;\n </span>\n <a href=\"https://docblocks.com/terms/\" target=\"_blank\" rel=\"noopener noreferrer\">\n Terms\n </a>\n <span className=\"db-shell-sidebar-footer-separator\" aria-hidden=\"true\">\n &bull;\n </span>\n <a href={issueReportUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n Issues\n </a>\n {showBrowserStorageWarning && (\n <>\n <span className=\"db-shell-sidebar-footer-separator\" aria-hidden=\"true\">\n &bull;\n </span>\n <button\n type=\"button\"\n className=\"db-shell-sidebar-footer-action\"\n onClick={() => void handleDownloadAllWorkspaces()}\n title=\"Browser docs can get auto-removed. Download all workspaces.\"\n >\n Backup browser docs frequently\n </button>\n </>\n )}\n </div>\n </div>\n )}\n\n {/* Resize handle between sidebar and editor -- hidden whenever\n the layout is compact (no sidebar to resize). */}\n {!effectiveCompact && (\n <div\n className=\"db-shell-sidebar-resizer\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize sidebar\"\n onPointerDown={handleResizerPointerDown}\n />\n )}\n\n {/* Editor area -- hidden in compact layout when the sidebar is showing. */}\n {(!effectiveCompact || mobileShowEditor) && (\n <main\n className={\n updateAvailable && onApplyUpdate && updateStatusBarVisible\n ? 'db-shell-editor-area db-shell-editor-area--has-update'\n : 'db-shell-editor-area'\n }\n style={{\n flex: 1,\n overflow: 'hidden',\n display: 'flex',\n flexDirection: 'column',\n position: 'relative',\n }}\n >\n {selectedFile && mediaProvider ? (\n <MediaContext.Provider value={mediaProvider}>\n <Suspense\n fallback={\n <div className=\"db-shell-empty\" role=\"status\">\n Loading editor&hellip;\n </div>\n }\n >\n <EditorShell\n key={`${selectedFile}-${editorKey}`}\n initialMarkdown={editorContent}\n initialView={initialView}\n articleId={selectedFile}\n fileName={selectedFile}\n onChange={handleEditorChange}\n colorScheme={resolvedTheme}\n writeCanvasSettings={writeCanvasSettings}\n height=\"100%\"\n placeholder={editorPlaceholder}\n outlineWidth={280}\n mediaProvider={mediaProvider}\n documentLinkProvider={documentLinkProvider}\n workspaceContainer={versionsContainer ?? undefined}\n allowVersioning={effectiveVersioning}\n viewPreferences={viewPreferences}\n onViewPreferencesChange={handleViewPreferencesChange}\n versionBasename={versionBasename ?? stripExtension(basenameOf(selectedFile))}\n versioningPrunePolicy={versioningPrunePolicy}\n versioningAutoSaveIdleMs={versioningAutoSaveIdleMs}\n onSaveVersion={onSaveVersion}\n toolbarSlotLeft={\n effectiveCompact ? (\n <button\n className=\"db-mobile-back\"\n onClick={() => setMobileShowEditor(false)}\n aria-label=\"Show file list\"\n >\n <span className=\"db-mobile-files-icon\">\n <FolderGlyph />\n </span>\n </button>\n ) : undefined\n }\n toolbarSlotRight={\n <>\n {/* Restore split view -- only relevant when compact\n layout was manually triggered on a wide viewport.\n On real mobile, side-by-side doesn't fit so the\n button is suppressed. */}\n {compactLayout && !isMobile && (\n <button\n className=\"db-restore-split\"\n onClick={() => setCompactLayout(false)}\n aria-label=\"Restore split view\"\n title=\"Restore split view\"\n >\n <SplitViewIcon />\n </button>\n )}\n {git.repo && (\n <Suspense fallback={null}>\n <GitToolbarControl selectedFile={selectedFile} />\n </Suspense>\n )}\n <ExportToolbarControls\n selectedFile={selectedFile}\n mediaContainer={mediaContainerRef.current}\n destinationAdapter={exportDestinationAdapter}\n colorScheme={resolvedTheme}\n videoExportPalette={DOCBLOCKS_VIDEO_EXPORT_PALETTE}\n initialSharedMode={initialSharedMode}\n />\n </>\n }\n />\n </Suspense>\n {showWelcomeGateway && (\n <div className=\"db-welcome-gateway\" role=\"note\" aria-label=\"Welcome tip\">\n <span className=\"db-welcome-gateway-text\">\n You&rsquo;re watching this welcome doc in <strong>Slideshow</strong> view --\n it&rsquo;s a regular markdown file, and so is everything you&rsquo;ll write.\n </span>\n <button className=\"db-welcome-gateway-cta\" onClick={handleStartWriting}>\n Start writing\n </button>\n <button\n className=\"db-welcome-gateway-dismiss\"\n onClick={closeWelcomeGateway}\n aria-label=\"Dismiss welcome tip\"\n title=\"Dismiss\"\n >\n &times;\n </button>\n </div>\n )}\n </MediaContext.Provider>\n ) : selectedFolder ? (\n <div className=\"db-folder-view\">\n {effectiveCompact && (\n <button className=\"db-mobile-back\" onClick={() => setMobileShowEditor(false)}>\n <span className=\"db-mobile-files-icon\">\n <FolderGlyph />\n </span>\n Back to files\n </button>\n )}\n <div className=\"db-folder-view-header\">\n <span className=\"db-folder-view-icon\">\n <FolderGlyph />\n </span>\n <span className=\"db-folder-view-path\">{selectedFolder}</span>\n </div>\n {folderEntries.length === 0 ? (\n <p className=\"db-folder-view-empty\">This folder is empty.</p>\n ) : (\n <ul className=\"db-folder-view-list\">\n {folderEntries.map((entry) => (\n <li\n key={entry.path}\n className=\"db-folder-view-item\"\n onClick={() => handleSelect(entry.path, entry.kind)}\n >\n <span className=\"db-folder-view-item-icon\">\n {entry.kind === 'directory' ? <FolderGlyph /> : <FileGlyph />}\n </span>\n {entry.name}\n </li>\n ))}\n </ul>\n )}\n </div>\n ) : (\n <div className=\"db-shell-empty\">\n {effectiveCompact && (\n <button className=\"db-mobile-back\" onClick={() => setMobileShowEditor(false)}>\n <span className=\"db-mobile-files-icon\">\n <FolderGlyph />\n </span>\n Back to files\n </button>\n )}\n <p>Select a file to start editing, or create a new one.</p>\n </div>\n )}\n <UpdateAvailableNotice\n available={updateAvailable}\n onApplyUpdate={onApplyUpdate}\n blocked={documentSnapshot.conflict !== null || storageFull}\n statusBarVisible={updateStatusBarVisible}\n />\n </main>\n )}\n </div>\n </GitContext.Provider>\n </div>\n );\n}\n","/**\n * AppMenu — top-left dropdown with workspace actions and app links.\n */\n\nimport { useState, useCallback, useRef, useEffect } from 'react';\nimport type { VersioningPreference } from '../preferences/versioning.js';\nimport type { AccentColor, ThemePreference } from '../preferences/theme.js';\nimport {\n DEFAULT_WRITE_CANVAS_PREFERENCES,\n type WriteCanvasPreferences,\n} from '../preferences/write-canvas.js';\nimport {\n AccentColorSettings,\n SettingsDialog,\n ThemeSettings,\n WriteCanvasSettingsControls,\n} from '../Settings/Settings.js';\nimport { Dialog } from '../components/Dialog.js';\n\nexport type { AccentColor, ThemePreference } from '../preferences/theme.js';\n\nexport interface AppMenuProps {\n /** Optional logo image URL to display instead of the text label. */\n logoUrl?: string;\n /** Current theme preference. */\n themePreference?: ThemePreference;\n /** Called when the user changes the theme preference. */\n onThemeChange?: (theme: ThemePreference) => void;\n /** Current accent color. */\n accentColor?: AccentColor;\n /** Called when the user changes the accent color. */\n onAccentColorChange?: (color: AccentColor) => void;\n /** Current typography preferences for the editor's Write canvas. */\n writeCanvasSettings?: WriteCanvasPreferences;\n /** Called when the user changes the Write canvas typography. */\n onWriteCanvasSettingsChange?: (settings: WriteCanvasPreferences) => void;\n /** Current global versioning preference. */\n versioningPreference?: VersioningPreference;\n /** Called when the user changes the global versioning preference. */\n onVersioningPreferenceChange?: (pref: VersioningPreference) => void;\n /**\n * Called when the user clicks \"Download all workspaces\". When omitted,\n * the menu item is hidden.\n */\n onDownloadAllWorkspaces?: () => void | Promise<void>;\n /**\n * Called when the user asks the browser to keep origin storage persistent.\n * When omitted, the menu item is hidden.\n */\n onKeepBrowserData?: () => void | Promise<void>;\n /**\n * Called when the user clicks \"Install DocBlocks…\" (browser PWA install).\n * When omitted — Electron, unsupported browsers, or already installed —\n * the menu item is hidden.\n */\n onInstallApp?: () => void | Promise<void>;\n /**\n * Async origin storage usage/quota for the Settings \"Storage\" section\n * (fetched when the dialog opens). When omitted — Electron, or browsers\n * without `navigator.storage.estimate` — the section is hidden.\n */\n getStorageEstimate?: () => Promise<{ usage: number; quota: number } | null>;\n /** Whether the browser has marked origin storage persistent (Settings display). */\n storagePersistent?: boolean;\n}\n\nfunction formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return '—';\n let value = bytes;\n let unit = 'B';\n for (const next of ['KB', 'MB', 'GB', 'TB']) {\n if (value < 1024) break;\n value /= 1024;\n unit = next;\n }\n return `${value >= 100 || unit === 'B' ? Math.round(value) : value.toFixed(1)} ${unit}`;\n}\n\nexport function AppMenu({\n logoUrl,\n themePreference = 'auto',\n onThemeChange,\n accentColor = 'brown',\n onAccentColorChange,\n writeCanvasSettings = DEFAULT_WRITE_CANVAS_PREFERENCES,\n onWriteCanvasSettingsChange,\n versioningPreference = 'browser-only',\n onVersioningPreferenceChange,\n onDownloadAllWorkspaces,\n onKeepBrowserData,\n onInstallApp,\n getStorageEstimate,\n storagePersistent,\n}: AppMenuProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [showAbout, setShowAbout] = useState(false);\n const [showSettings, setShowSettings] = useState(false);\n const [requestingPersistentStorage, setRequestingPersistentStorage] = useState(false);\n const menuRef = useRef<HTMLDivElement>(null);\n const [storageEstimate, setStorageEstimate] = useState<{\n usage: number;\n quota: number;\n } | null>(null);\n\n // Refresh the Settings \"Storage\" figures each time the dialog opens.\n useEffect(() => {\n if (!showSettings || !getStorageEstimate) return;\n let cancelled = false;\n getStorageEstimate()\n .then((estimate) => {\n if (!cancelled) setStorageEstimate(estimate);\n })\n .catch(() => {\n if (!cancelled) setStorageEstimate(null);\n });\n return () => {\n cancelled = true;\n };\n }, [showSettings, getStorageEstimate]);\n\n useEffect(() => {\n if (!isOpen) return;\n function handleOutsideClick(e: MouseEvent) {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n }\n document.addEventListener('mousedown', handleOutsideClick);\n return () => document.removeEventListener('mousedown', handleOutsideClick);\n }, [isOpen]);\n\n const handleAction = useCallback((action: () => void) => {\n setIsOpen(false);\n action();\n }, []);\n\n const handleKeepBrowserDataFromSettings = useCallback(async () => {\n if (!onKeepBrowserData || requestingPersistentStorage) return;\n setRequestingPersistentStorage(true);\n try {\n await onKeepBrowserData();\n } finally {\n setRequestingPersistentStorage(false);\n }\n }, [onKeepBrowserData, requestingPersistentStorage]);\n\n return (\n <>\n <div ref={menuRef} className=\"db-app-menu\">\n <button\n className=\"db-app-menu-btn\"\n onClick={() => setIsOpen(!isOpen)}\n aria-expanded={isOpen}\n aria-haspopup=\"true\"\n >\n {logoUrl ? (\n <img\n src={logoUrl}\n alt=\"DocBlocks\"\n className=\"db-app-menu-logo\"\n width={1266}\n height={544}\n />\n ) : (\n <span className=\"db-app-menu-label\">docblocks</span>\n )}\n <span\n className={`db-app-menu-caret${isOpen ? ' db-app-menu-caret--open' : ''}`}\n aria-hidden=\"true\"\n />\n </button>\n\n {isOpen && (\n <div className=\"db-app-menu-dropdown\" role=\"menu\">\n <button\n className=\"db-app-menu-item\"\n role=\"menuitem\"\n onClick={() => handleAction(() => setShowSettings(true))}\n >\n Settings\n </button>\n {onInstallApp && (\n <button\n className=\"db-app-menu-item\"\n role=\"menuitem\"\n onClick={() => handleAction(() => void onInstallApp())}\n >\n Install DocBlocks&hellip;\n </button>\n )}\n {onKeepBrowserData && (\n <button\n className=\"db-app-menu-item\"\n role=\"menuitem\"\n onClick={() => handleAction(() => void onKeepBrowserData())}\n >\n Keep data in browser for longer\n </button>\n )}\n {onDownloadAllWorkspaces && (\n <button\n className=\"db-app-menu-item\"\n role=\"menuitem\"\n onClick={() => handleAction(() => void onDownloadAllWorkspaces())}\n >\n Download all workspaces\n </button>\n )}\n <div className=\"db-app-menu-divider\" />\n <button\n className=\"db-app-menu-item\"\n role=\"menuitem\"\n onClick={() => handleAction(() => setShowAbout(true))}\n >\n About\n </button>\n </div>\n )}\n </div>\n\n {showSettings && (\n <SettingsDialog onClose={() => setShowSettings(false)}>\n <ThemeSettings\n value={themePreference}\n onChange={(preference) => onThemeChange?.(preference)}\n />\n <AccentColorSettings\n value={accentColor}\n onChange={(color) => onAccentColorChange?.(color)}\n />\n <WriteCanvasSettingsControls\n value={writeCanvasSettings}\n onChange={(settings) => onWriteCanvasSettingsChange?.(settings)}\n />\n\n {getStorageEstimate && (\n <fieldset className=\"db-settings-fieldset\">\n <legend className=\"db-settings-legend\">Storage</legend>\n <p className=\"db-settings-hint\">\n {storageEstimate\n ? `DocBlocks documents and app data are using ${formatBytes(\n storageEstimate.usage,\n )} of the ${formatBytes(\n storageEstimate.quota,\n )} this browser allows for the site.`\n : 'Storage usage is not available in this browser.'}\n </p>\n {storagePersistent !== undefined && (\n <p className=\"db-settings-hint\">\n {storagePersistent\n ? 'Data is marked persistent, so the browser will avoid evicting it.'\n : 'Data is not yet marked persistent.'}\n </p>\n )}\n {onKeepBrowserData && (\n <button\n type=\"button\"\n className=\"db-settings-action\"\n disabled={requestingPersistentStorage}\n onClick={() => void handleKeepBrowserDataFromSettings()}\n >\n {requestingPersistentStorage\n ? 'Requesting persistent storage…'\n : 'Keep data in browser for longer'}\n </button>\n )}\n </fieldset>\n )}\n\n {onVersioningPreferenceChange && (\n <fieldset className=\"db-settings-fieldset\">\n <legend className=\"db-settings-legend\">Version history</legend>\n <p className=\"db-settings-hint\">\n When on, DocBlocks keeps prior revisions of each document inside a sibling{' '}\n <code>&lt;name&gt;_files/.versions/</code> folder. Individual workspaces can\n override this default in their own settings.\n </p>\n <label className=\"db-settings-radio\">\n <input\n type=\"radio\"\n name=\"versioning\"\n value=\"on\"\n checked={versioningPreference === 'on'}\n onChange={() => onVersioningPreferenceChange('on')}\n />\n On for all workspaces\n </label>\n <label className=\"db-settings-radio\">\n <input\n type=\"radio\"\n name=\"versioning\"\n value=\"browser-only\"\n checked={versioningPreference === 'browser-only'}\n onChange={() => onVersioningPreferenceChange('browser-only')}\n />\n On in browser workspaces, off for local folders\n </label>\n <label className=\"db-settings-radio\">\n <input\n type=\"radio\"\n name=\"versioning\"\n value=\"off\"\n checked={versioningPreference === 'off'}\n onChange={() => onVersioningPreferenceChange('off')}\n />\n Off for all workspaces\n </label>\n </fieldset>\n )}\n </SettingsDialog>\n )}\n\n {showAbout && (\n <Dialog title=\"About DocBlocks\" onClose={() => setShowAbout(false)}>\n <p>\n <strong>DocBlocks</strong> is a markdown document editor that runs entirely in your\n browser. Your files stay on your device.\n </p>\n <p>\n Built with{' '}\n <a href=\"https://github.com/bendyline/squisq\" target=\"_blank\" rel=\"noopener noreferrer\">\n squisq\n </a>{' '}\n by{' '}\n <a href=\"https://bendyline.com\" target=\"_blank\" rel=\"noopener noreferrer\">\n Bendyline\n </a>\n .\n </p>\n <p className=\"db-dialog-links\">\n <a\n href=\"https://github.com/bendyline/docblocks\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n GitHub\n </a>\n <span className=\"db-dialog-sep\">&middot;</span>\n <a\n href=\"https://github.com/bendyline/docblocks/blob/main/LICENSE\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n License (MIT)\n </a>\n <span className=\"db-dialog-sep\">&middot;</span>\n <a\n href=\"https://github.com/bendyline/docblocks/blob/main/NOTICE.md\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n &hearts; built on open source\n </a>\n </p>\n </Dialog>\n )}\n </>\n );\n}\n","/**\n * WorkspaceSettingsButton — gear icon dropdown for workspace actions.\n */\n\nimport { useState, useCallback, useRef, useEffect } from 'react';\nimport { WorkspaceIcon } from '../icons.js';\n\nexport interface WorkspaceSettingsButtonProps {\n onSettings: () => void;\n onRename: () => void;\n onDownload: () => void;\n onRemove: () => void;\n}\n\nexport function WorkspaceSettingsButton({\n onSettings,\n onRename,\n onDownload,\n onRemove,\n}: WorkspaceSettingsButtonProps) {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!isOpen) return;\n function handleOutsideClick(e: MouseEvent) {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n }\n document.addEventListener('mousedown', handleOutsideClick);\n return () => document.removeEventListener('mousedown', handleOutsideClick);\n }, [isOpen]);\n\n const handleAction = useCallback((action: () => void) => {\n setIsOpen(false);\n action();\n }, []);\n\n return (\n <div ref={ref} className=\"db-ws-settings\">\n <button\n className=\"db-ws-settings-btn\"\n onClick={() => setIsOpen(!isOpen)}\n aria-expanded={isOpen}\n aria-haspopup=\"true\"\n aria-label=\"Workspace settings\"\n title=\"Workspace settings\"\n >\n <WorkspaceIcon />\n </button>\n\n {isOpen && (\n <div className=\"db-ws-settings-dropdown\" role=\"menu\">\n <button\n className=\"db-ws-settings-item\"\n role=\"menuitem\"\n onClick={() => handleAction(onSettings)}\n >\n Workspace settings…\n </button>\n <button\n className=\"db-ws-settings-item\"\n role=\"menuitem\"\n onClick={() => handleAction(onRename)}\n >\n Rename workspace\n </button>\n <button\n className=\"db-ws-settings-item\"\n role=\"menuitem\"\n onClick={() => handleAction(onDownload)}\n >\n Download workspace\n </button>\n <div className=\"db-ws-settings-divider\" />\n <button\n className=\"db-ws-settings-item db-ws-settings-item--danger\"\n role=\"menuitem\"\n onClick={() => handleAction(onRemove)}\n >\n Remove workspace\n </button>\n </div>\n )}\n </div>\n );\n}\n","/**\n * Versioning preferences — global default + per-workspace resolution.\n *\n * The global preference controls whether DocBlocks writes version\n * snapshots (under `<basename>_files/.versions/`) when editing. The\n * default is `'browser-only'` so local-folder workspaces stay clean by\n * default and only IndexedDB workspaces accumulate version history.\n *\n * Each workspace can override the global default with its own setting\n * stored on the WorkspaceDescriptor. `'inherit'` (or absent) defers to\n * the global preference; `'on'` / `'off'` force the behavior regardless.\n */\n\nimport type { WorkspaceDescriptor } from '@bendyline/docblocks/workspace';\n\nexport type VersioningPreference = 'on' | 'browser-only' | 'off';\n\nconst STORAGE_KEY = 'docblocks:versioningPreference';\nconst DEFAULT_PREFERENCE: VersioningPreference = 'browser-only';\n\nexport function loadVersioningPreference(): VersioningPreference {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (raw === 'on' || raw === 'browser-only' || raw === 'off') return raw;\n } catch {\n // ignore\n }\n return DEFAULT_PREFERENCE;\n}\n\nexport function saveVersioningPreference(value: VersioningPreference): void {\n try {\n localStorage.setItem(STORAGE_KEY, value);\n } catch {\n // ignore quota errors\n }\n}\n\n/** Whether a workspace type is \"local\" (writes to a real folder on disk). */\nexport function isLocalWorkspaceType(type: WorkspaceDescriptor['type']): boolean {\n return type === 'native' || type === 'electron-native';\n}\n\n/**\n * Compute the effective versioning state for a workspace, honoring the\n * per-workspace override first and falling back to the global preference.\n *\n * Returns `false` whenever no workspace is provided so callers can use\n * this directly during initial render before a workspace loads.\n */\nexport function resolveVersioningEnabled(\n workspace: WorkspaceDescriptor | null,\n globalPref: VersioningPreference,\n): boolean {\n if (!workspace) return false;\n\n const override = workspace.versioningOverride;\n if (override === 'on') return true;\n if (override === 'off') return false;\n\n switch (globalPref) {\n case 'on':\n return true;\n case 'off':\n return false;\n case 'browser-only':\n return !isLocalWorkspaceType(workspace.type);\n }\n}\n","/**\n * WorkspaceSettingsDialog — per-workspace settings modal.\n *\n * Lets the user override the global versioning preference for a single\n * workspace (or fall back to inheriting it). The override is stored on\n * the WorkspaceDescriptor and persisted via `saveWorkspace`.\n */\n\nimport type { WorkspaceDescriptor } from '@bendyline/docblocks/workspace';\nimport {\n isLocalWorkspaceType,\n resolveVersioningEnabled,\n type VersioningPreference,\n} from '../preferences/versioning.js';\nimport { Dialog } from '../components/Dialog.js';\n\nexport type WorkspaceVersioningOverride = NonNullable<WorkspaceDescriptor['versioningOverride']>;\n\nexport interface WorkspaceSettingsDialogProps {\n workspace: WorkspaceDescriptor;\n /** Current global versioning preference — used to label \"Inherit\". */\n globalVersioningPreference: VersioningPreference;\n /** Apply a new override and close the dialog. */\n onChange: (override: WorkspaceVersioningOverride) => void;\n onClose: () => void;\n}\n\nconst VERSIONING_LABELS: Record<VersioningPreference, string> = {\n on: 'on',\n 'browser-only': 'on for browser workspaces, off for local folders',\n off: 'off',\n};\n\nexport function WorkspaceSettingsDialog({\n workspace,\n globalVersioningPreference,\n onChange,\n onClose,\n}: WorkspaceSettingsDialogProps) {\n // Treat absent/undefined as 'inherit' for the radio state.\n const current: WorkspaceVersioningOverride = workspace.versioningOverride ?? 'inherit';\n\n const isLocal = isLocalWorkspaceType(workspace.type);\n const inheritedEnabled = resolveVersioningEnabled(\n { ...workspace, versioningOverride: 'inherit' },\n globalVersioningPreference,\n );\n const inheritLabel = `Inherit default — currently ${VERSIONING_LABELS[globalVersioningPreference]} (${inheritedEnabled ? 'on' : 'off'} for this workspace)`;\n\n return (\n <Dialog title=\"Workspace settings\" onClose={onClose}>\n <p className=\"db-settings-hint\">\n <strong>{workspace.name}</strong> &middot;{' '}\n {isLocal ? 'Local folder workspace' : 'Browser workspace'}\n </p>\n\n <fieldset className=\"db-settings-fieldset\">\n <legend className=\"db-settings-legend\">Version history</legend>\n <p className=\"db-settings-hint\">\n Controls whether DocBlocks keeps prior revisions in{' '}\n <code>&lt;name&gt;_files/.versions/</code> for documents in this workspace.\n </p>\n <label className=\"db-settings-radio\">\n <input\n type=\"radio\"\n name=\"ws-versioning\"\n value=\"inherit\"\n checked={current === 'inherit'}\n onChange={() => onChange('inherit')}\n />\n {inheritLabel}\n </label>\n <label className=\"db-settings-radio\">\n <input\n type=\"radio\"\n name=\"ws-versioning\"\n value=\"on\"\n checked={current === 'on'}\n onChange={() => onChange('on')}\n />\n On for this workspace\n </label>\n <label className=\"db-settings-radio\">\n <input\n type=\"radio\"\n name=\"ws-versioning\"\n value=\"off\"\n checked={current === 'off'}\n onChange={() => onChange('off')}\n />\n Off for this workspace\n </label>\n </fieldset>\n </Dialog>\n );\n}\n","import { useState, useSyncExternalStore } from 'react';\nimport {\n DocumentRecoveryJournal,\n DocumentSession,\n getDefaultDocumentRecoveryStorage,\n type DocumentSessionSnapshot,\n} from '@bendyline/docblocks/document';\n\nexport interface UseDocumentSessionResult {\n /** Stable controller for the lifetime of the mounted shell/panel. */\n session: DocumentSession;\n /** React snapshot of dirty/saving/saved/error/conflict state. */\n snapshot: DocumentSessionSnapshot;\n}\n\n/**\n * React binding for the framework-neutral DocumentSession engine.\n *\n * The hook deliberately does not infer target transitions from props.\n * Callers must use transitionTo(), retarget(), or delete() before changing\n * their view state so persistence ordering remains explicit.\n */\nexport function useDocumentSession(autoSaveDelayMs = 500): UseDocumentSessionResult {\n const [session] = useState(\n () =>\n new DocumentSession({\n autoSaveDelayMs,\n recoveryJournal: new DocumentRecoveryJournal(getDefaultDocumentRecoveryStorage()),\n }),\n );\n const snapshot = useSyncExternalStore(\n session.subscribe,\n session.getSnapshot,\n session.getSnapshot,\n );\n return { session, snapshot };\n}\n","import { lazy, Suspense } from 'react';\nimport type {\n ExportDestinationAdapter,\n ExportDestinationTarget,\n ExportToolbarControlsProps,\n} from './ExportToolbarControls.js';\n\nconst ExportToolbarControlsImplementation = lazy(() =>\n import('./ExportToolbarControls.js').then((module) => ({\n default: module.ExportToolbarControls,\n })),\n);\n\n/** Public toolbar control with its editor-coupled implementation deferred. */\nexport function ExportToolbarControls(props: ExportToolbarControlsProps) {\n return (\n <Suspense fallback={null}>\n <ExportToolbarControlsImplementation {...props} />\n </Suspense>\n );\n}\n\nexport type { ExportDestinationAdapter, ExportDestinationTarget, ExportToolbarControlsProps };\n","/**\n * useGit — the single hook DocBlocksShell calls to power all git UI.\n *\n * Tier 1 (`available`): running under the Electron host with a working git —\n * gates only the clone entry. Tier 2 (`repo`): the active workspace is an\n * electron-native folder that is a git repository — gates everything else.\n * On the site / VS Code webview / store builds every surface null-renders.\n *\n * Actions never throw: typed GitErrors are routed to the auth-guidance or\n * conflicts dialogs when actionable, otherwise to the aria-live result line.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n DocBlocksHostGitAPI,\n GitCapabilities,\n GitError,\n GitRepoDetection,\n GitRemoteInfo,\n} from '@bendyline/docblocks/host';\nimport { maybeGetDocBlocksHost } from '@bendyline/docblocks/host';\nimport type { FileSystemProvider } from '@bendyline/docblocks/filesystem';\nimport { buildBadgeMap, conflictedPaths } from './git-status.js';\nimport { useGitStatus } from './useGitStatus.js';\nimport type { GitBusyKind, GitDialogState, GitInlineResult, GitValue } from './GitContext.js';\n\n/**\n * Capabilities can't change within a session — probe once per page load.\n *\n * Only a *fulfilled* probe is cached. Caching the rejected promise meant a\n * single transient IPC failure pinned `available` to false for the life of\n * the page, hiding every git surface with no way back short of a reload.\n */\nlet capabilitiesPromise: Promise<GitCapabilities> | null = null;\nfunction capabilitiesOnce(gitApi: DocBlocksHostGitAPI): Promise<GitCapabilities> {\n capabilitiesPromise ??= gitApi.capabilities().catch((error: unknown) => {\n capabilitiesPromise = null;\n throw error;\n });\n return capabilitiesPromise;\n}\n\n/** Test seam — drops the memoised probe so each test starts clean. */\nexport function resetGitCapabilitiesCache(): void {\n capabilitiesPromise = null;\n}\n\n/** Bounded retry for the capabilities probe — a transient IPC failure\n must not permanently hide the git UI. */\nconst CAPABILITIES_RETRIES = 2;\nconst CAPABILITIES_RETRY_MS = 1000;\n\nfunction describeError(error: GitError): string {\n return error.message || 'Git operation failed';\n}\n\nexport function useGit(\n provider: FileSystemProvider | null,\n requestedWorkspaceId: string | null,\n theme: 'light' | 'dark',\n): GitValue {\n const host = maybeGetDocBlocksHost();\n const gitApi = host?.git ?? null;\n const workspaceId = gitApi ? requestedWorkspaceId : null;\n\n const [capabilities, setCapabilities] = useState<GitCapabilities | null>(null);\n useEffect(() => {\n if (!gitApi) return;\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n // `available` gates every git surface, so a probe that fails must be\n // retried rather than silently leaving the UI switched off.\n const attempt = (remaining: number) => {\n void capabilitiesOnce(gitApi).then(\n (caps) => {\n if (!cancelled) setCapabilities(caps);\n },\n (error: unknown) => {\n if (cancelled) return;\n if (remaining > 0) {\n timer = setTimeout(() => attempt(remaining - 1), CAPABILITIES_RETRY_MS);\n return;\n }\n console.warn('DocBlocks: git capabilities probe failed; git UI stays hidden', error);\n },\n );\n };\n attempt(CAPABILITIES_RETRIES);\n\n return () => {\n cancelled = true;\n if (timer) clearTimeout(timer);\n };\n }, [gitApi]);\n\n const available = gitApi !== null && capabilities?.gitAvailable === true;\n\n const [repo, setRepo] = useState<GitRepoDetection | null>(null);\n const [remoteWeb, setRemoteWeb] = useState<GitValue['remoteWeb']>(null);\n useEffect(() => {\n setRepo(null);\n setRemoteWeb(null);\n if (!gitApi || !workspaceId || !available) return;\n let cancelled = false;\n void gitApi.detectRepo(workspaceId).then(\n (result) => {\n if (cancelled || !result.ok || !result.value.isRepo || !result.value.repositoryId) {\n return;\n }\n setRepo(result.value);\n void gitApi.listRemotes(result.value.repositoryId).then(\n (remotes) => {\n if (cancelled || !remotes.ok) return;\n const first: GitRemoteInfo | undefined = remotes.value[0];\n setRemoteWeb(first?.web ?? null);\n },\n // No remote is a supported state; a failed probe degrades to it\n // rather than surfacing an unhandled rejection.\n () => undefined,\n );\n },\n /* detection failure → not a repo, which is the default state */ () => undefined,\n );\n return () => {\n cancelled = true;\n };\n }, [gitApi, workspaceId, available]);\n\n const repositoryId = repo?.repositoryId ?? null;\n const isRepo = repositoryId !== null;\n const { status, refresh, scheduleRefresh } = useGitStatus(gitApi, repositoryId, isRepo);\n const badges = useMemo(() => buildBadgeMap(status?.changes ?? []), [status]);\n\n const [busy, setBusy] = useState<GitBusyKind>(null);\n const [lastResult, setLastResult] = useState<GitInlineResult | null>(null);\n const [dialog, setDialog] = useState<GitDialogState>({ kind: 'none' });\n\n const openDialog = useCallback((next: GitDialogState) => {\n // `lastResult` is a single shared slot rendered as a role=\"alert\" by\n // whichever dialog is open. Without this, yesterday's failed pull\n // greets the user inside today's commit dialog. Operations that open a\n // dialog *to report* an outcome (routeError, the conflicts dialog) set\n // the dialog directly and are unaffected.\n setLastResult(null);\n setDialog(next);\n }, []);\n const closeDialog = useCallback(() => setDialog({ kind: 'none' }), []);\n\n // Route a failed operation somewhere useful.\n const routeError = useCallback(\n (operation: 'push' | 'pull' | 'fetch' | 'commit' | 'branch' | 'pr', error: GitError) => {\n if (error.code === 'auth-failed') {\n setDialog({\n kind: 'auth-guidance',\n operation: operation === 'commit' || operation === 'branch' ? 'push' : operation,\n detail: error.message,\n });\n return;\n }\n setLastResult({ tone: 'error', message: describeError(error) });\n },\n [],\n );\n\n // Mirrored in an effect, not during render: a render-phase ref write is\n // impure and can be torn by a discarded concurrent render. Only the\n // action callbacks read it, and they run after commit.\n const statusRef = useRef(status);\n useEffect(() => {\n statusRef.current = status;\n }, [status]);\n\n const runAction = useCallback(\n async <T>(\n kind: Exclude<GitBusyKind, null>,\n operation: 'push' | 'pull' | 'fetch' | 'commit' | 'branch' | 'pr',\n action: (\n api: DocBlocksHostGitAPI,\n repository: string,\n ) => Promise<{ ok: true; value: T } | { ok: false; error: GitError }>,\n successMessage?: string,\n ): Promise<boolean> => {\n if (!gitApi || !repositoryId) return false;\n setBusy(kind);\n setLastResult(null);\n try {\n const result = await action(gitApi, repositoryId);\n if (result.ok) {\n if (successMessage) setLastResult({ tone: 'info', message: successMessage });\n refresh();\n return true;\n }\n if (operation === 'pull' && result.error.code === 'merge-conflict') {\n // Surface the conflicted files; the fresh status carries them.\n const fresh = await gitApi.status(repositoryId);\n const paths = fresh.ok ? conflictedPaths(fresh.value) : [];\n refresh();\n setDialog({ kind: 'conflicts', paths });\n setLastResult({ tone: 'error', message: 'Pull hit merge conflicts' });\n return false;\n }\n routeError(operation, result.error);\n refresh();\n return false;\n } finally {\n setBusy(null);\n }\n },\n [gitApi, repositoryId, refresh, routeError],\n );\n\n const commit = useCallback(\n (message: string, paths: string[]) =>\n runAction(\n 'commit',\n 'commit',\n (api, repository) => api.commit(repository, message, paths),\n 'Committed',\n ),\n [runAction],\n );\n\n const push = useCallback(async () => {\n const setUpstream = statusRef.current?.upstream === null;\n await runAction(\n 'push',\n 'push',\n (api, repository) => api.push(repository, setUpstream ? { setUpstream: true } : undefined),\n setUpstream ? 'Branch published' : 'Pushed',\n );\n }, [runAction]);\n\n const pull = useCallback(async () => {\n await runAction('pull', 'pull', (api, repository) => api.pull(repository), 'Pulled');\n }, [runAction]);\n\n const fetchRemote = useCallback(async () => {\n await runAction('fetch', 'fetch', (api, repository) => api.fetch(repository), 'Fetched');\n }, [runAction]);\n\n const createBranch = useCallback(\n (name: string) =>\n runAction(\n 'branch',\n 'branch',\n (api, repository) => api.createBranch(repository, name, { checkout: true }),\n `Switched to new branch ${name}`,\n ),\n [runAction],\n );\n\n const switchBranch = useCallback(\n (name: string) =>\n runAction(\n 'branch',\n 'branch',\n (api, repository) => api.checkoutBranch(repository, name),\n `Switched to ${name}`,\n ),\n [runAction],\n );\n\n const openOnRemote = useCallback(\n (filePath?: string) => {\n if (!remoteWeb || !host) return;\n let url = remoteWeb.webUrl;\n // Only GitHub's blob-path shape is a safe bet; other hosts get the repo.\n if (filePath && remoteWeb.host === 'github.com' && statusRef.current?.branch) {\n const rel = filePath.replace(/^\\/+/, '');\n url = `${remoteWeb.webUrl}/blob/${encodeURIComponent(statusRef.current.branch)}/${rel\n .split('/')\n .map(encodeURIComponent)\n .join('/')}`;\n }\n void host.shell.openExternal(url);\n },\n [remoteWeb, host],\n );\n\n const createPullRequest = useCallback(async () => {\n if (!gitApi || !repositoryId) return;\n setBusy('pr');\n setLastResult(null);\n try {\n const result = await gitApi.createPullRequest(repositoryId);\n if (result.ok) {\n setLastResult({ tone: 'info', message: 'Opening pull request in browser' });\n return;\n }\n if (result.error.code === 'no-upstream') {\n setLastResult({\n tone: 'error',\n message: 'Push the branch first, then create the pull request',\n });\n return;\n }\n if (result.error.code === 'gh-not-available') {\n setLastResult({\n tone: 'error',\n message: 'Install the GitHub CLI (gh) to create pull requests',\n });\n return;\n }\n routeError('pr', result.error);\n } finally {\n setBusy(null);\n }\n }, [gitApi, repositoryId, routeError]);\n\n // This object *is* the GitContext.Provider value (DocBlocksShell passes it\n // straight through). Rebuilding it every render re-rendered the status\n // bar, toolbar, tree badges and any open dialog on every shell render,\n // which also negated useGitStatus's payload dedupe.\n return useMemo(\n () => ({\n available,\n capabilities,\n repo,\n repositoryId,\n remoteWeb,\n gitApi,\n provider,\n theme,\n status,\n badges,\n busy,\n lastResult,\n refresh,\n scheduleRefresh,\n commit,\n push,\n pull,\n fetchRemote,\n createBranch,\n switchBranch,\n openOnRemote,\n createPullRequest,\n dialog,\n openDialog,\n closeDialog,\n }),\n [\n available,\n capabilities,\n repo,\n repositoryId,\n remoteWeb,\n gitApi,\n provider,\n theme,\n status,\n badges,\n busy,\n lastResult,\n refresh,\n scheduleRefresh,\n commit,\n push,\n pull,\n fetchRemote,\n createBranch,\n switchBranch,\n openOnRemote,\n createPullRequest,\n dialog,\n openDialog,\n closeDialog,\n ],\n );\n}\n","/**\n * useGitStatus — subscribes to the host's owner-scoped repository stream.\n *\n * Dedupes identical payloads so a permanently-dirty working tree (normal\n * under the manual-commit model) doesn't repaint the tree on every push\n * from the main process.\n *\n * Every asynchronous path is generation-guarded. Switching workspaces\n * while a `scheduleRefresh` debounce is pending, or while a `refresh()`\n * request is in flight, must not paint the previous repository's branch,\n * badges, and dirty count onto the new one.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DocBlocksHostGitAPI, GitStatus } from '@bendyline/docblocks/host';\n\nconst SCHEDULE_REFRESH_MS = 1500;\n\nfunction statusKey(status: GitStatus): string {\n return JSON.stringify(status);\n}\n\nexport interface UseGitStatusResult {\n status: GitStatus | null;\n /** Fetch a fresh status immediately (after a renderer-initiated git op). */\n refresh: () => void;\n /** Trailing-debounced refresh (after autosave writes). */\n scheduleRefresh: () => void;\n}\n\nexport function useGitStatus(\n gitApi: DocBlocksHostGitAPI | null,\n repositoryId: string | null,\n enabled: boolean,\n): UseGitStatusResult {\n const [status, setStatus] = useState<GitStatus | null>(null);\n const lastKeyRef = useRef<string | null>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n /**\n * Bumped every time the subscribed repository changes. An in-flight\n * `status()` that resolves after the switch belongs to the old repo and\n * is dropped instead of being painted onto the new workspace.\n */\n const generationRef = useRef(0);\n\n const apply = useCallback((next: GitStatus) => {\n const key = statusKey(next);\n if (key === lastKeyRef.current) return;\n lastKeyRef.current = key;\n setStatus(next);\n }, []);\n\n useEffect(() => {\n generationRef.current += 1;\n // A refresh debounced against the previous repository must not land on\n // the new one: the timer outlives the effect that scheduled it.\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n lastKeyRef.current = null;\n setStatus(null);\n if (!gitApi || !repositoryId || !enabled) return;\n let cancelled = false;\n const unsubscribe = gitApi.onStatusChanged(repositoryId, (next) => {\n if (!cancelled) apply(next);\n });\n return () => {\n cancelled = true;\n unsubscribe();\n };\n }, [gitApi, repositoryId, enabled, apply]);\n\n const refresh = useCallback(() => {\n if (!gitApi || !repositoryId || !enabled) return;\n const generation = generationRef.current;\n void gitApi.status(repositoryId).then(\n (result) => {\n if (generation !== generationRef.current) return;\n if (result.ok) apply(result.value);\n },\n // A rejected status (IPC torn down mid-switch) is not actionable\n // here — the subscription stays the source of truth. Swallow it\n // rather than leave an unhandled rejection.\n () => undefined,\n );\n }, [gitApi, repositoryId, enabled, apply]);\n\n const scheduleRefresh = useCallback(() => {\n if (timerRef.current) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n refresh();\n }, SCHEDULE_REFRESH_MS);\n }, [refresh]);\n\n useEffect(() => {\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n };\n }, []);\n\n return { status, refresh, scheduleRefresh };\n}\n","import type { FileSystemProviderV2 } from '@bendyline/docblocks/filesystem';\n\ninterface ProviderLeaseRecord {\n holders: number;\n generation: number;\n disposePromise: Promise<void> | null;\n}\n\nconst leases = new WeakMap<FileSystemProviderV2, ProviderLeaseRecord>();\n\n/**\n * Retain one UI ownership lease for a provider.\n *\n * Final release is deferred by one microtask. React Strict Mode intentionally\n * performs setup → cleanup → setup, so an immediate cleanup disposer would\n * permanently close the provider that the second setup still owns.\n */\nexport function retainFileSystemProvider(provider: FileSystemProviderV2): () => void {\n let record = leases.get(provider);\n if (!record) {\n record = { holders: 0, generation: 0, disposePromise: null };\n leases.set(provider, record);\n }\n if (record.disposePromise) {\n throw new Error('Cannot retain a filesystem provider after disposal has started.');\n }\n\n record.holders += 1;\n record.generation += 1;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n record!.holders -= 1;\n record!.generation += 1;\n const releaseGeneration = record!.generation;\n queueMicrotask(() => {\n if (\n record!.holders !== 0 ||\n record!.generation !== releaseGeneration ||\n record!.disposePromise\n ) {\n return;\n }\n record!.disposePromise = provider.dispose();\n // React cleanup cannot await or render a disposal failure. Joiners still\n // receive the original promise from the provider; this observer prevents\n // an unhandled rejection during unmount.\n void record!.disposePromise.catch(() => undefined);\n });\n };\n}\n","import { useEffect } from 'react';\n\nconst APP_TITLE = 'DocBlocks';\n\nexport function titleForSelectedFile(\n selectedFile: string | null,\n homeDocumentTitle = APP_TITLE,\n homeDocumentPath?: string,\n): string {\n if (!selectedFile || selectedFile === homeDocumentPath) return homeDocumentTitle;\n\n const filename = selectedFile.replace(/^\\/+/, '').split('/').pop();\n const name = filename?.replace(/\\.[^.]+$/, '');\n return name ? `${name} - ${APP_TITLE}` : APP_TITLE;\n}\n\nexport function useDocumentTitle(\n selectedFile: string | null,\n homeDocumentTitle?: string,\n homeDocumentPath?: string,\n): void {\n useEffect(() => {\n if (typeof document !== 'undefined') {\n document.title = titleForSelectedFile(selectedFile, homeDocumentTitle, homeDocumentPath);\n }\n }, [homeDocumentPath, homeDocumentTitle, selectedFile]);\n}\n","import {\n createDbkWorkspaceSnapshot,\n type DbkWorkspaceSnapshot,\n} from '@bendyline/docblocks/filesystem';\nimport { SHARED_DOCUMENT_LIMITS } from '@bendyline/docblocks/share';\nimport type { ZipToContainerOptions } from '@bendyline/squisq-formats/container';\n\nconst WORKSPACE_DBK_LIMITS = Object.freeze({\n maxEntries: 256,\n maxUncompressedBytes: 16 * 1024 * 1024,\n maxEntryUncompressedBytes: 8 * 1024 * 1024,\n maxCompressionRatio: 200,\n}) satisfies ZipToContainerOptions;\n\nconst SHARED_DBK_LIMITS = Object.freeze({\n maxEntries: 4,\n maxUncompressedBytes: SHARED_DOCUMENT_LIMITS.markdownBytes,\n maxEntryUncompressedBytes: SHARED_DOCUMENT_LIMITS.markdownBytes,\n // The independent 20 KiB uncompressed cap is authoritative here. Highly\n // repetitive legitimate Markdown can exceed 200:1 while remaining tiny.\n maxCompressionRatio: 1_000,\n}) satisfies ZipToContainerOptions;\n\nexport interface DecodeDbkWorkspaceOptions {\n targetDocumentPath: string;\n profile?: 'workspace' | 'shared-link';\n}\n\n/**\n * Decode an untrusted DBK through Squisq's bounded ZIP reader, then apply the\n * independent DocBlocks Markdown-only/UTF-8 workspace validation pass.\n */\nexport async function decodeDbkWorkspace(\n bytes: ArrayBuffer | Uint8Array | Blob,\n options: DecodeDbkWorkspaceOptions,\n): Promise<DbkWorkspaceSnapshot> {\n const { zipToContainer } = await import('@bendyline/squisq-formats/container');\n const shared = options.profile === 'shared-link';\n const container = await zipToContainer(bytes, shared ? SHARED_DBK_LIMITS : WORKSPACE_DBK_LIMITS);\n const snapshot = await createDbkWorkspaceSnapshot(container, {\n targetDocumentPath: options.targetDocumentPath,\n });\n if (shared && snapshot.files.length !== 1) {\n throw new Error('A shared document link must contain exactly one Markdown file.');\n }\n return snapshot;\n}\n","/**\n * import-files — the drag-and-drop import pipeline.\n *\n * Extracted from `DocBlocksShell` so the collision and failure behaviour is\n * testable without standing up the whole shell.\n *\n * Two rules this module exists to enforce:\n *\n * 1. **An import never destroys an existing document.** Dropping `report.docx`\n * into a workspace that already holds `report.md` used to overwrite it\n * outright -- no prompt, no undo. Every write here goes through\n * `mode: 'create'`, and a collision moves the import aside to\n * `report (2).md` instead of asking. A drop is a bulk, low-ceremony\n * gesture: N modal confirmations would be worse than the disease, and the\n * OS file managers and every browser's download flow already train users\n * to expect the numbered-suffix behaviour. Nothing is lost either way, and\n * an unwanted extra file is one delete away -- an overwritten document is\n * gone for good.\n * 2. **A failed import is reported.** Failures used to be `console.error`-only,\n * so a bad drop looked identical to no drop at all. Each file is isolated:\n * one failure never aborts the rest of the batch, and the caller receives\n * everything it needs to tell the user what happened.\n */\n\nimport type { DbkWorkspaceSnapshot, FileSystemProvider } from '@bendyline/docblocks/filesystem';\nimport { FsError } from '@bendyline/docblocks/filesystem';\nimport { decodeDbkWorkspace } from './dbk-import.js';\nimport { removeProviderEntry, writeProviderText } from './provider-io.js';\n\n/** The shape `docxToContainer` / `pdfToContainer` results expose to the shell. */\nexport interface ImportedMediaSource {\n listFiles(): Promise<Array<{ path: string; mimeType: string }>>;\n readFile(path: string): Promise<ArrayBuffer | null>;\n}\n\nexport interface ImportFilesDeps {\n /** Copy a converted container's media into `<path minus ext>_files/`. */\n persistMedia: (source: ImportedMediaSource, path: string) => Promise<void>;\n}\n\nexport interface ImportedDocument {\n /** The dropped file's original name, e.g. `report.docx`. */\n source: string;\n /** The path actually written, e.g. `report (2).md`. */\n path: string;\n /** True when a name collision moved this import aside. */\n renamed: boolean;\n}\n\nexport interface ImportFailure {\n source: string;\n message: string;\n}\n\nexport interface ImportFilesResult {\n imported: ImportedDocument[];\n failed: ImportFailure[];\n /** Dropped files with an extension the importer does not handle. */\n unsupported: string[];\n}\n\n/** Bounded so a pathological workspace cannot spin here forever. */\nconst MAX_NAME_ATTEMPTS = 100;\n\nfunction withCopySuffix(path: string, n: number): string {\n const dot = path.lastIndexOf('.');\n const slash = path.lastIndexOf('/');\n if (dot <= slash + 1) return `${path} (${n})`;\n return `${path.slice(0, dot)} (${n})${path.slice(dot)}`;\n}\n\nfunction isAlreadyExists(error: unknown): boolean {\n return error instanceof FsError && error.code === 'already-exists';\n}\n\n/**\n * Reserve a free path by *writing* an empty file with `mode: 'create'`, walking\n * `name.md` -> `name (2).md` -> ... until one sticks.\n *\n * Claiming rather than probing with `stat` is deliberate: the name has to be\n * final before the converters run (a `.dbk` snapshot and the `_files/` media\n * folder are both keyed off the document path), and `create` is the only check\n * that cannot lose a race with a concurrent import of the same filename.\n */\nasync function claimAvailablePath(\n provider: FileSystemProvider,\n desiredPath: string,\n): Promise<{ path: string; renamed: boolean }> {\n for (let attempt = 1; attempt <= MAX_NAME_ATTEMPTS; attempt++) {\n const candidate = attempt === 1 ? desiredPath : withCopySuffix(desiredPath, attempt);\n try {\n await writeProviderText(provider, candidate, '', 'create');\n return { path: candidate, renamed: attempt > 1 };\n } catch (error: unknown) {\n if (!isAlreadyExists(error)) throw error;\n }\n }\n throw new Error(`Too many documents are already named like “${desiredPath}”.`);\n}\n\nasync function readImportedMarkdown(\n file: File,\n ext: string,\n destPath: string,\n provider: FileSystemProvider,\n deps: ImportFilesDeps,\n): Promise<string> {\n if (ext === '.md' || ext === '.txt') {\n return file.text();\n }\n if (ext === '.docx') {\n const { docxToContainer } = await import('@bendyline/squisq-formats/docx');\n const container = await docxToContainer(await file.arrayBuffer());\n const markdown = (await container.readDocument()) ?? '';\n await deps.persistMedia(container, destPath);\n return markdown;\n }\n if (ext === '.pdf') {\n const { pdfToContainer } = await import('@bendyline/squisq-formats/pdf');\n const container = await pdfToContainer(await file.arrayBuffer());\n const markdown = (await container.readDocument()) ?? '';\n await deps.persistMedia(container, destPath);\n return markdown;\n }\n const snapshot = await decodeDbkWorkspace(await file.arrayBuffer(), {\n targetDocumentPath: destPath,\n });\n await writeDbkCompanions(snapshot, provider);\n return snapshot.documentContent;\n}\n\n/**\n * Write a decoded DBK's *secondary* Markdown alongside the primary document.\n *\n * A `.dbk` is a workspace bundle, not a lone document: it can carry up to 255\n * further Markdown files. `decodeDbkWorkspace` has already rebased them beneath\n * `<document>_files/` -- the default `auto` layout resolves to `companion` here,\n * because a bundle's own primary path never matches the freshly claimed target\n * -- so the snapshot arrives ready to write. Returning only `documentContent`,\n * as this path used to, silently dropped every one of them while reporting the\n * drop as a complete success. (The OS-open path never had this bug: it hands\n * the whole snapshot to `replaceContents`.)\n *\n * `create` mode, like every other write here: a companion landing on a file the\n * user already has is a real conflict, and failing the import loudly beats\n * overwriting it.\n */\nasync function writeDbkCompanions(\n snapshot: DbkWorkspaceSnapshot,\n provider: FileSystemProvider,\n): Promise<void> {\n for (const entry of snapshot.files) {\n // The caller writes the primary itself, onto the path it claimed.\n if (entry.path === snapshot.targetDocumentPath) continue;\n // Workspace DBKs are Markdown-only by contract: createDbkWorkspaceSnapshot\n // fails the whole snapshot on a binary member, so this never skips data.\n if (entry.kind !== 'text') continue;\n await writeProviderText(provider, entry.path, entry.content, 'create');\n }\n}\n\nconst SUPPORTED_EXTENSIONS = new Set(['.md', '.txt', '.docx', '.pdf', '.dbk', '.zip']);\n\n/**\n * Import each dropped file as a markdown document, never clobbering an\n * existing one. Always resolves: per-file failures are collected, not thrown.\n */\nexport async function importDroppedFiles(\n files: readonly File[],\n provider: FileSystemProvider,\n deps: ImportFilesDeps,\n): Promise<ImportFilesResult> {\n const result: ImportFilesResult = { imported: [], failed: [], unsupported: [] };\n\n for (const file of files) {\n // Matches the historical extension sniff, including its treatment of a\n // name with no dot at all (which lands on an unsupported extension).\n const ext = file.name.slice(file.name.lastIndexOf('.')).toLowerCase();\n if (!SUPPORTED_EXTENSIONS.has(ext)) {\n result.unsupported.push(file.name);\n continue;\n }\n\n const baseName = file.name.replace(/\\.[^.]+$/, '');\n let claimed: string | null = null;\n try {\n const claim = await claimAvailablePath(provider, `${baseName}.md`);\n claimed = claim.path;\n const markdown = await readImportedMarkdown(file, ext, claim.path, provider, deps);\n await writeProviderText(provider, claim.path, markdown);\n result.imported.push({ source: file.name, path: claim.path, renamed: claim.renamed });\n } catch (error: unknown) {\n // The placeholder only ever exists to hold the name; a conversion that\n // fails afterwards must not leave an empty document behind.\n if (claimed) {\n await removeProviderEntry(provider, claimed).catch(() => undefined);\n }\n result.failed.push({\n source: file.name,\n message: error instanceof Error ? error.message : 'The file could not be imported.',\n });\n }\n }\n\n return result;\n}\n\n/** Human-readable summary of an import, or `null` when there is nothing to say. */\nexport function summariseImport(\n result: ImportFilesResult,\n): { kind: 'success' | 'error'; message: string } | null {\n const { imported, failed, unsupported } = result;\n\n if (failed.length > 0) {\n const detail =\n failed.length === 1\n ? `Could not import ${failed[0].source} — ${failed[0].message}`\n : `Could not import ${failed.length} of ${failed.length + imported.length} files.`;\n return { kind: 'error', message: detail };\n }\n\n if (imported.length === 0) {\n if (unsupported.length === 0) return null;\n return {\n kind: 'error',\n message:\n unsupported.length === 1\n ? `${unsupported[0]} is not a file type DocBlocks can import.`\n : `${unsupported.length} dropped files are not file types DocBlocks can import.`,\n };\n }\n\n // Renames are the one success worth narrating: the user dropped `report.docx`\n // and got `report (2).md`, and silence there looks like the import went\n // somewhere unexpected.\n const renamed = imported.filter((entry) => entry.renamed);\n if (renamed.length === 1) {\n return {\n kind: 'success',\n message: `Imported as ${renamed[0].path} — a document named ${renamed[0].source.replace(/\\.[^.]+$/, '')}.md already exists.`,\n };\n }\n if (renamed.length > 1) {\n return {\n kind: 'success',\n message: `Imported ${imported.length} files. ${renamed.length} were renamed to avoid replacing existing documents.`,\n };\n }\n return null;\n}\n","/**\n * provider-io — small read/write helpers over a `FileSystemProvider` that\n * paper over the v1/v2 provider split.\n *\n * These used to be module-private to `DocBlocksShell.tsx`; they moved here so\n * `import-files.ts` can share them rather than growing a second copy of the\n * \"does this provider speak v2?\" branch.\n */\n\nimport {\n FsError,\n getFileSystemProviderV2,\n parseWorkspacePath,\n type FileSystemProvider,\n} from '@bendyline/docblocks/filesystem';\n\nexport async function providerEntryExists(\n provider: FileSystemProvider,\n path: string,\n): Promise<boolean> {\n const providerV2 = getFileSystemProviderV2(provider);\n return providerV2\n ? (await providerV2.stat(parseWorkspacePath(path))) !== null\n : provider.exists(path);\n}\n\n/**\n * Write text to `path`. `mode: 'create'` refuses to clobber an existing entry,\n * raising an `already-exists` `FsError` -- the same contract on both provider\n * generations, so callers can rely on it to protect a user's document.\n */\nexport async function writeProviderText(\n provider: FileSystemProvider,\n path: string,\n content: string,\n mode: 'upsert' | 'create' = 'upsert',\n): Promise<void> {\n const providerV2 = getFileSystemProviderV2(provider);\n if (providerV2) {\n await providerV2.writeFile(parseWorkspacePath(path), new TextEncoder().encode(content), {\n mode,\n createParents: true,\n expectedVersion: mode === 'create' ? null : undefined,\n });\n return;\n }\n if (mode === 'create' && (await provider.exists(path))) {\n throw new FsError('already-exists', 'File already exists.', { operation: 'write', path });\n }\n await provider.writeFile(path, content);\n}\n\nexport async function removeProviderEntry(\n provider: FileSystemProvider,\n path: string,\n): Promise<void> {\n const providerV2 = getFileSystemProviderV2(provider);\n if (providerV2) {\n await providerV2.remove(parseWorkspacePath(path), { recursive: true, missing: 'ignore' });\n return;\n }\n await provider.delete(path);\n}\n","/**\n * usePromptDialog — an `await`-able, in-product replacement for the native\n * `window.prompt()`.\n *\n * Electron's renderer does not implement `window.prompt()` (it throws\n * \"prompt() is and will not be supported\"), so any shell action that asked for\n * a single line of text that way was dead on the desktop app. This hook gives\n * those call sites the same shape on top of the focus-trapped `Dialog`.\n *\n * The contract callers depend on:\n * • resolves to the entered string, or `null` when the user cancels\n * • it *always* resolves — superseding a prompt or unmounting the host\n * settles the outstanding promise as a cancel rather than stranding a\n * caller in an `await` that nobody will ever answer\n */\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { PromptDialog, type PromptRequest } from './PromptDialog.js';\n\ninterface PendingPrompt {\n id: number;\n request: PromptRequest;\n settle: (value: string | null) => void;\n}\n\nexport interface PromptDialogController {\n /** Ask the user for a line of text. Resolves `null` if they cancel. */\n prompt: (request: PromptRequest) => Promise<string | null>;\n /** Render this somewhere in the host's tree. */\n promptDialog: React.ReactNode;\n}\n\nexport function usePromptDialog(): PromptDialogController {\n const [pending, setPending] = useState<PendingPrompt | null>(null);\n const pendingRef = useRef<PendingPrompt | null>(null);\n const nextIdRef = useRef(0);\n\n /**\n * The single exit for an open prompt. Submit, cancel, supersede and unmount\n * all funnel through here, which is what guarantees no caller is left\n * awaiting a promise nobody settles. Settling twice is a no-op.\n */\n const settlePending = useCallback((value: string | null) => {\n const current = pendingRef.current;\n if (!current) return;\n pendingRef.current = null;\n setPending((open) => (open?.id === current.id ? null : open));\n current.settle(value);\n }, []);\n\n const prompt = useCallback(\n (request: PromptRequest) =>\n new Promise<string | null>((resolve) => {\n // A newer prompt replaces the older one; the superseded caller sees a\n // cancel rather than a promise that outlives its dialog.\n settlePending(null);\n const next: PendingPrompt = { id: ++nextIdRef.current, request, settle: resolve };\n pendingRef.current = next;\n setPending(next);\n }),\n [settlePending],\n );\n\n useEffect(() => {\n // Unmounting the shell must not strand a caller mid-await.\n return () => settlePending(null);\n }, [settlePending]);\n\n const promptDialog = pending\n ? React.createElement(PromptDialog, {\n // Remount on a superseding request so the field re-seeds from it.\n key: pending.id,\n request: pending.request,\n onSettle: settlePending,\n })\n : null;\n\n return { prompt, promptDialog };\n}\n","/**\n * PromptDialog — a single-line text prompt on the shared `Dialog` primitive.\n *\n * The product's replacement for `window.prompt()`, which Electron's renderer\n * does not implement. Callers drive it through `usePromptDialog()`, which owns\n * the open/settle lifecycle; this component is only the view.\n */\n\nimport React, { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { Dialog } from './Dialog.js';\n\nexport interface PromptRequest {\n /** Dialog heading, e.g. \"New document\". */\n title: string;\n /** Visible label for the text field, e.g. \"Document name\". */\n label: string;\n /** Pre-filled (and pre-selected) value. */\n initialValue?: string;\n /** Confirm button text; defaults to \"OK\". */\n confirmLabel?: string;\n}\n\nexport interface PromptDialogProps {\n request: PromptRequest;\n /** Called exactly once with the entered value, or `null` on cancel. */\n onSettle: (value: string | null) => void;\n}\n\nexport function PromptDialog({ request, onSettle }: PromptDialogProps) {\n const [value, setValue] = useState(request.initialValue ?? '');\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = useId();\n const cancel = useCallback(() => onSettle(null), [onSettle]);\n const submit = useCallback(() => {\n // An empty name is never a meaningful answer, and every caller treats it\n // as a cancel anyway. Refuse it here so the button state matches.\n if (value.trim() === '') return;\n onSettle(value);\n }, [onSettle, value]);\n\n // Pre-select the seeded value so typing replaces it -- the behaviour the\n // native prompt() had, and what a rename dialog needs to feel usable.\n useEffect(() => {\n inputRef.current?.select();\n }, []);\n\n return (\n <Dialog\n title={request.title}\n onClose={cancel}\n initialFocusRef={inputRef}\n // A stray backdrop click must not discard something the user typed.\n closeOnBackdrop={false}\n footer={\n <>\n <button type=\"button\" className=\"db-git-secondary-btn\" onClick={cancel}>\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"db-git-primary-btn\"\n disabled={value.trim() === ''}\n onClick={submit}\n >\n {request.confirmLabel ?? 'OK'}\n </button>\n </>\n }\n >\n <div className=\"db-git-form-row\">\n <label className=\"db-git-form-label\" htmlFor={inputId}>\n {request.label}\n </label>\n <input\n id={inputId}\n ref={inputRef}\n className=\"db-git-form-input\"\n type=\"text\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key !== 'Enter') return;\n // Own Enter explicitly: implicit form submission is not something\n // a bare input in a dialog gets for free.\n e.preventDefault();\n submit();\n }}\n />\n </div>\n </Dialog>\n );\n}\n","/**\n * useConfirmDialog — `await`-able, in-product replacements for the native\n * `window.confirm()` and `window.alert()`.\n *\n * Both natives block the renderer, look nothing like the product, and title\n * themselves with the browser's or Electron's name. This hook gives those call\n * sites the same shape on top of the focus-trapped `Dialog`.\n *\n * The contract callers depend on (identical to `usePromptDialog`'s):\n * • `confirm` resolves `true` when accepted, `false` when cancelled\n * • `acknowledge` resolves once the user dismisses the message\n * • it *always* resolves — superseding a dialog or unmounting the host\n * settles the outstanding promise as a cancel rather than stranding a\n * caller in an `await` that nobody will ever answer\n *\n * Callers that convert a synchronous `confirm()` into an `await` gain a\n * suspension point the original did not have: re-check any request-id fence\n * *after* awaiting, not before.\n */\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n ConfirmDialog,\n type AcknowledgeRequest,\n type ConfirmDialogRequest,\n type ConfirmRequest,\n} from './ConfirmDialog.js';\n\ninterface PendingConfirm {\n id: number;\n request: ConfirmDialogRequest;\n settle: (value: boolean) => void;\n}\n\nexport interface ConfirmDialogController {\n /** Ask the user a yes/no question. Resolves `false` if they cancel. */\n confirm: (request: ConfirmRequest) => Promise<boolean>;\n /** Show a message the user must dismiss. Resolves once it is dismissed. */\n acknowledge: (request: AcknowledgeRequest) => Promise<void>;\n /** Render this somewhere in the host's tree. */\n confirmDialog: React.ReactNode;\n}\n\nexport function useConfirmDialog(): ConfirmDialogController {\n const [pending, setPending] = useState<PendingConfirm | null>(null);\n const pendingRef = useRef<PendingConfirm | null>(null);\n const nextIdRef = useRef(0);\n\n /**\n * The single exit for an open dialog. Accept, cancel, supersede and unmount\n * all funnel through here, which is what guarantees no caller is left\n * awaiting a promise nobody settles. Settling twice is a no-op.\n */\n const settlePending = useCallback((value: boolean) => {\n const current = pendingRef.current;\n if (!current) return;\n pendingRef.current = null;\n setPending((open) => (open?.id === current.id ? null : open));\n current.settle(value);\n }, []);\n\n const open = useCallback(\n (request: ConfirmDialogRequest) =>\n new Promise<boolean>((resolve) => {\n // A newer dialog replaces the older one; the superseded caller sees a\n // cancel rather than a promise that outlives its dialog.\n settlePending(false);\n const next: PendingConfirm = { id: ++nextIdRef.current, request, settle: resolve };\n pendingRef.current = next;\n setPending(next);\n }),\n [settlePending],\n );\n\n const confirm = useCallback(\n (request: ConfirmRequest) => open({ kind: 'confirm', ...request }),\n [open],\n );\n\n const acknowledge = useCallback(\n async (request: AcknowledgeRequest) => {\n // The resolved value carries no information for an acknowledgement --\n // dismissed and unmounted are the same outcome to every caller.\n await open({ kind: 'acknowledge', ...request });\n },\n [open],\n );\n\n useEffect(() => {\n // Unmounting the shell must not strand a caller mid-await.\n return () => settlePending(false);\n }, [settlePending]);\n\n const confirmDialog = pending\n ? React.createElement(ConfirmDialog, {\n // Remount on a superseding request so focus re-seeds from it.\n key: pending.id,\n request: pending.request,\n onSettle: settlePending,\n })\n : null;\n\n return { confirm, acknowledge, confirmDialog };\n}\n","/**\n * ConfirmDialog — a yes/no question, or a message the user must acknowledge,\n * on the shared `Dialog` primitive.\n *\n * The product's replacement for `window.confirm()` and `window.alert()`. Both\n * natives block the renderer's event loop, ignore the app's theme and accent,\n * and stamp the browser/Electron chrome's name on a DocBlocks question — in a\n * shell that already ships a focus-trapped `Dialog` and a toast channel.\n *\n * Confirm and acknowledge share one component because an acknowledgement is a\n * confirm with the cancel path removed: same focus trap, same settle contract,\n * same footer. Callers drive it through `useConfirmDialog()`, which owns the\n * open/settle lifecycle; this component is only the view.\n */\n\nimport React, { useCallback, useRef } from 'react';\nimport { Dialog } from './Dialog.js';\n\nexport interface ConfirmRequest {\n /** Dialog heading, e.g. \"Remove workspace\". */\n title: string;\n /** The question. Rendered as plain text — no markup. */\n message: string;\n /** Confirm button text; defaults to \"OK\". */\n confirmLabel?: string;\n /** Cancel button text; defaults to \"Cancel\". */\n cancelLabel?: string;\n /**\n * Styles the confirm button as destructive and moves initial focus to\n * Cancel, so a reflexive Enter does not delete anything.\n */\n destructive?: boolean;\n}\n\nexport interface AcknowledgeRequest {\n /** Dialog heading, e.g. \"About DocBlocks\". */\n title: string;\n /** The message. Rendered as plain text — no markup. */\n message: string;\n /** Dismiss button text; defaults to \"OK\". */\n confirmLabel?: string;\n}\n\n/**\n * `acknowledge` has no cancel path, so it carries neither a cancel label nor a\n * destructive treatment. The discriminant keeps those props off the shape that\n * cannot use them rather than documenting \"ignored when …\".\n */\nexport type ConfirmDialogRequest =\n | ({ kind: 'confirm' } & ConfirmRequest)\n | ({ kind: 'acknowledge' } & AcknowledgeRequest);\n\nexport interface ConfirmDialogProps {\n request: ConfirmDialogRequest;\n /**\n * Called exactly once. `true` when confirmed (or acknowledged), `false`\n * when the user cancels a confirm.\n */\n onSettle: (value: boolean) => void;\n}\n\nexport function ConfirmDialog({ request, onSettle }: ConfirmDialogProps) {\n const acknowledge = request.kind === 'acknowledge';\n const destructive = request.kind === 'confirm' && request.destructive === true;\n\n const cancelRef = useRef<HTMLButtonElement>(null);\n const confirmRef = useRef<HTMLButtonElement>(null);\n\n const accept = useCallback(() => onSettle(true), [onSettle]);\n const reject = useCallback(() => onSettle(false), [onSettle]);\n\n // Escape, the close button and a backdrop click are a dismissal. For a\n // question that means \"no\"; for an acknowledgement, dismissing *is* the\n // acknowledgement, so it settles the same way the OK button does.\n const close = acknowledge ? accept : reject;\n\n return (\n <Dialog\n title={request.title}\n onClose={close}\n // Focus the safe button. On a destructive confirm that is Cancel, so\n // muscle-memory Enter cannot destroy a workspace; everywhere else the\n // confirm button is both safe and the likely answer.\n initialFocusRef={destructive ? cancelRef : confirmRef}\n footer={\n <>\n {!acknowledge && (\n <button ref={cancelRef} type=\"button\" className=\"db-git-secondary-btn\" onClick={reject}>\n {request.cancelLabel ?? 'Cancel'}\n </button>\n )}\n <button\n ref={confirmRef}\n type=\"button\"\n className={\n destructive ? 'db-git-primary-btn db-git-primary-btn--danger' : 'db-git-primary-btn'\n }\n onClick={accept}\n >\n {request.confirmLabel ?? 'OK'}\n </button>\n </>\n }\n >\n <p className=\"db-dialog-message\">{request.message}</p>\n </Dialog>\n );\n}\n","/**\n * Theme resolution for the shell.\n *\n * Three inputs decide what `data-theme` the shell stamps, and they are not\n * equal partners:\n *\n * 1. `preference` — what the user picked in Settings. It is *their* app;\n * an explicit choice here outranks whatever the host asked for.\n * 2. `hostTheme` — the `theme` prop a host passes to `<DocBlocksShell>`.\n * A default, not a command: it decides the look before the user has an\n * opinion, and whenever the user's opinion is \"System default\".\n * 3. `osTheme` — the OS/browser `prefers-color-scheme`, the last resort.\n *\n * Both `preference` and `hostTheme` use `'auto'` to mean \"I have no opinion,\n * ask the next one down\", which is what makes the chain collapse cleanly to\n * the OS when nobody has an opinion.\n *\n * This exists as a pure function because the shell itself is not\n * unit-renderable (lazy editor chunk, workspace bootstrap, IndexedDB), and\n * the precedence order is the part worth pinning.\n */\n\nimport type { ThemePreference } from '../preferences/theme.js';\n\nexport interface ResolveThemeInput {\n /** The user's Settings choice. Wins unless it is 'auto'. */\n preference: ThemePreference;\n /** The host's `theme` prop. Consulted when the preference is 'auto'. */\n hostTheme?: ThemePreference;\n /** `prefers-color-scheme`, used when nobody else has an opinion. */\n osTheme: 'light' | 'dark';\n}\n\nexport function resolveShellTheme({\n preference,\n hostTheme,\n osTheme,\n}: ResolveThemeInput): 'light' | 'dark' {\n if (preference === 'light' || preference === 'dark') return preference;\n if (hostTheme === 'light' || hostTheme === 'dark') return hostTheme;\n return osTheme;\n}\n","const NEW_ISSUE_URL = 'https://github.com/bendyline/docblocks/issues/new';\nconst VERSION_VALUE_LIMIT = 128;\nconst USER_AGENT_VALUE_LIMIT = 512;\n\nexport interface IssueReportEnvironment {\n reportedAt: Date;\n version: string;\n userAgent: string;\n}\n\nfunction normalizeEnvironmentValue(value: string, fallback: string, limit: number): string {\n const normalized = value\n .replace(/[\\r\\n]+/g, ' ')\n .trim()\n .slice(0, limit);\n return normalized || fallback;\n}\n\n/** Build an editable GitHub issue with bounded diagnostics from the current surface. */\nexport function buildIssueReportUrl(environment: IssueReportEnvironment): string {\n const body = [\n '## Description',\n '',\n '<!-- What happened, and what did you expect? -->',\n '',\n '## Environment',\n '',\n `- Date: ${environment.reportedAt.toISOString().slice(0, 10)}`,\n `- DocBlocks: ${normalizeEnvironmentValue(environment.version, 'unknown', VERSION_VALUE_LIMIT)}`,\n `- User agent: ${normalizeEnvironmentValue(\n environment.userAgent,\n 'unavailable',\n USER_AGENT_VALUE_LIMIT,\n )}`,\n ].join('\\n');\n\n const url = new URL(NEW_ISSUE_URL);\n url.searchParams.set('body', body);\n return url.href;\n}\n","import type { EditorView } from '@bendyline/squisq-editor-react';\nimport { tryParseWorkspacePath } from '@bendyline/docblocks/filesystem';\n\nexport const LAST_STATE_KEY = 'docblocks:lastState';\n\nconst MAX_WORKSPACE_ID_CHARACTERS = 256;\nconst MAX_WORKSPACE_PATH_CHARACTERS = 4_096;\nconst EDITOR_VIEWS = new Set<EditorView>(['raw', 'wysiwyg', 'preview']);\n\nexport interface LastState {\n workspaceId: string;\n filePath: string;\n view: EditorView;\n}\n\ntype LastStateStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>;\n\nfunction hasExactKeys(record: Record<string, unknown>, keys: readonly string[]): boolean {\n const actual = Object.keys(record);\n return (\n actual.length === keys.length &&\n keys.every((key) => Object.prototype.hasOwnProperty.call(record, key))\n );\n}\n\nfunction isBoundedText(value: unknown, maximum: number): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length <= maximum &&\n ![...value].some((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 0x1f || codePoint === 0x7f;\n })\n );\n}\n\nexport function parseLastState(value: unknown): LastState | null {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return null;\n const record = value as Record<string, unknown>;\n if (!hasExactKeys(record, ['workspaceId', 'filePath', 'view'])) return null;\n if (!isBoundedText(record.workspaceId, MAX_WORKSPACE_ID_CHARACTERS)) return null;\n if (!isBoundedText(record.filePath, MAX_WORKSPACE_PATH_CHARACTERS)) return null;\n const parsedPath = tryParseWorkspacePath(record.filePath);\n if (!parsedPath) return null;\n if (typeof record.view !== 'string' || !EDITOR_VIEWS.has(record.view as EditorView)) return null;\n return {\n workspaceId: record.workspaceId,\n filePath: record.filePath,\n view: record.view as EditorView,\n };\n}\n\nexport function saveLastState(state: LastState, storage: LastStateStorage = localStorage): void {\n try {\n storage.setItem(LAST_STATE_KEY, JSON.stringify(state));\n } catch {\n // Navigation persistence is best-effort; quota or disabled storage must\n // not make an otherwise-open document unusable.\n }\n}\n\nexport function loadLastState(storage: LastStateStorage = localStorage): LastState | null {\n try {\n const raw = storage.getItem(LAST_STATE_KEY);\n if (!raw) return null;\n const state = parseLastState(JSON.parse(raw) as unknown);\n if (state) return state;\n try {\n storage.removeItem(LAST_STATE_KEY);\n } catch {\n // The invalid record is ignored even when storage is read-only.\n }\n return null;\n } catch {\n return null;\n }\n}\n","import type { ViewPreferences } from '@bendyline/squisq-editor-react';\n\nconst WELCOME_GATEWAY_KEY = 'docblocks:welcomeGatewayDismissed';\nconst SIDEBAR_WIDTH_KEY = 'docblocks:sidebarWidth';\nconst VIEW_PREFERENCES_KEY = 'docblocks:viewPreferences';\n\nexport const SIDEBAR_WIDTH_DEFAULT = 320;\nexport const SIDEBAR_WIDTH_MIN = 320;\nexport const SIDEBAR_WIDTH_MAX = 600;\nexport const SIDEBAR_COLLAPSE_THRESHOLD = SIDEBAR_WIDTH_MIN;\n\nconst DEFAULT_VIEW_PREFERENCES: ViewPreferences = Object.freeze({\n outline: false,\n inlinePreview: true,\n showStatusBar: true,\n});\n\nexport function isWelcomeGatewayDismissed(): boolean {\n try {\n return localStorage.getItem(WELCOME_GATEWAY_KEY) === '1';\n } catch {\n return false;\n }\n}\n\nexport function markWelcomeGatewayDismissed(): void {\n try {\n localStorage.setItem(WELCOME_GATEWAY_KEY, '1');\n } catch {\n // First-run presentation state is best-effort.\n }\n}\n\nexport function loadSidebarWidth(): number {\n try {\n const raw = localStorage.getItem(SIDEBAR_WIDTH_KEY);\n if (raw === null) return SIDEBAR_WIDTH_DEFAULT;\n const value = Number(raw);\n if (!Number.isFinite(value)) return SIDEBAR_WIDTH_DEFAULT;\n return Math.min(SIDEBAR_WIDTH_MAX, Math.max(SIDEBAR_WIDTH_MIN, value));\n } catch {\n return SIDEBAR_WIDTH_DEFAULT;\n }\n}\n\nexport function saveSidebarWidth(px: number): void {\n try {\n localStorage.setItem(SIDEBAR_WIDTH_KEY, String(Math.round(px)));\n } catch {\n // Layout persistence is best-effort.\n }\n}\n\nexport function loadViewPreferences(): ViewPreferences {\n try {\n const raw = localStorage.getItem(VIEW_PREFERENCES_KEY);\n if (!raw) return DEFAULT_VIEW_PREFERENCES;\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return DEFAULT_VIEW_PREFERENCES;\n }\n const record = parsed as Record<string, unknown>;\n return {\n outline:\n typeof record.outline === 'boolean' ? record.outline : DEFAULT_VIEW_PREFERENCES.outline,\n inlinePreview:\n typeof record.inlinePreview === 'boolean'\n ? record.inlinePreview\n : DEFAULT_VIEW_PREFERENCES.inlinePreview,\n showStatusBar:\n typeof record.showStatusBar === 'boolean'\n ? record.showStatusBar\n : DEFAULT_VIEW_PREFERENCES.showStatusBar,\n };\n } catch {\n return DEFAULT_VIEW_PREFERENCES;\n }\n}\n\nexport function saveViewPreferences(preferences: ViewPreferences): void {\n try {\n localStorage.setItem(VIEW_PREFERENCES_KEY, JSON.stringify(preferences));\n } catch {\n // View preference persistence is best-effort.\n }\n}\n","import { useState } from 'react';\n\nconst UPDATE_PROMPT_ID = 'db-update-available-prompt';\n\nexport interface UpdateAvailableNoticeProps {\n available: boolean;\n onApplyUpdate?: () => void;\n blocked?: boolean;\n statusBarVisible: boolean;\n}\n\n/**\n * Keeps PWA updates unobtrusive until the user asks to review one. The\n * notice is positioned over the editor status bar by DocBlocksShell CSS;\n * the existing Reload/Later prompt remains a fixed shell-level card.\n */\nexport function UpdateAvailableNotice({\n available,\n onApplyUpdate,\n blocked = false,\n statusBarVisible,\n}: UpdateAvailableNoticeProps) {\n const [promptOpen, setPromptOpen] = useState(false);\n\n if (!available || !onApplyUpdate) return null;\n\n const promptVisible = promptOpen && !blocked;\n\n return (\n <>\n <button\n type=\"button\"\n className={`db-update-status-notice${\n statusBarVisible ? '' : ' db-update-status-notice--floating'\n }`}\n onClick={() => setPromptOpen(true)}\n disabled={blocked}\n aria-controls={UPDATE_PROMPT_ID}\n aria-expanded={promptVisible}\n aria-label=\"A new version of DocBlocks is available. Show update options.\"\n title=\"A new version of DocBlocks is available\"\n >\n Update available\n </button>\n {promptVisible && (\n <div id={UPDATE_PROMPT_ID} className=\"db-update-banner\" role=\"alert\">\n <span>A new version of DocBlocks is available.</span>\n <div className=\"db-update-banner-actions\">\n <button type=\"button\" onClick={onApplyUpdate}>\n Reload\n </button>\n <button type=\"button\" onClick={() => setPromptOpen(false)}>\n Later\n </button>\n </div>\n </div>\n )}\n </>\n );\n}\n","import { useCallback, useEffect, useRef } from 'react';\nimport type { DocumentLinkProvider } from '@bendyline/squisq-editor-react';\nimport type { FileSystemEntry, FileSystemProvider } from '@bendyline/docblocks/filesystem';\nimport { collectMarkdownFiles, createDocumentLinkCandidates } from './document-links.js';\n\ninterface DocumentLinkCache {\n readonly provider: FileSystemProvider;\n readonly epoch: number;\n readonly controller: AbortController;\n readonly entries: Promise<FileSystemEntry[]>;\n}\n\nexport function useDocumentLinkProvider(\n provider: FileSystemProvider | null,\n selectedFile: string | null,\n epoch = 0,\n): DocumentLinkProvider {\n const cacheRef = useRef<DocumentLinkCache | null>(null);\n\n useEffect(\n () => () => {\n if (cacheRef.current?.provider !== provider || cacheRef.current.epoch !== epoch) return;\n cacheRef.current.controller.abort();\n cacheRef.current = null;\n },\n [provider, epoch],\n );\n\n return useCallback<DocumentLinkProvider>(\n async (query) => {\n if (!provider || !selectedFile) return [];\n let cache = cacheRef.current;\n if (!cache || cache.provider !== provider || cache.epoch !== epoch) {\n cache?.controller.abort();\n const controller = new AbortController();\n cache = {\n provider,\n epoch,\n controller,\n entries: collectMarkdownFiles(provider, '', { signal: controller.signal }),\n };\n cacheRef.current = cache;\n }\n try {\n return createDocumentLinkCandidates(await cache.entries, selectedFile, query);\n } catch (error: unknown) {\n if (cacheRef.current === cache) cacheRef.current = null;\n throw error;\n }\n },\n [provider, selectedFile, epoch],\n );\n}\n","import type { DocumentLinkCandidate } from '@bendyline/squisq-editor-react';\nimport type { FileSystemEntry, FileSystemProvider } from '@bendyline/docblocks/filesystem';\nimport {\n FsError,\n getFileSystemProviderV2,\n parseWorkspacePath,\n} from '@bendyline/docblocks/filesystem';\n\nexport const DEFAULT_DOCUMENT_DISCOVERY_LIMITS = Object.freeze({\n entries: 10_000,\n directories: 2_000,\n depth: 64,\n milliseconds: 5_000,\n});\n\nexport interface DocumentDiscoveryOptions {\n readonly maxEntries?: number;\n readonly maxDirectories?: number;\n readonly maxDepth?: number;\n readonly timeoutMs?: number;\n readonly signal?: AbortSignal;\n}\n\nexport class DocumentDiscoveryError extends Error {\n readonly code: 'cancelled' | 'limit' | 'timeout';\n\n constructor(code: DocumentDiscoveryError['code'], message: string) {\n super(message);\n this.name = 'DocumentDiscoveryError';\n this.code = code;\n }\n}\n\nfunction positiveLimit(value: number | undefined, fallback: number, label: string): number {\n const selected = value ?? fallback;\n if (!Number.isSafeInteger(selected) || selected < 1) {\n throw new Error(`Invalid document discovery ${label} limit.`);\n }\n return selected;\n}\n\nasync function readDirectory(\n provider: FileSystemProvider,\n path: string,\n): Promise<FileSystemEntry[]> {\n const providerV2 = getFileSystemProviderV2(provider);\n if (!providerV2) return provider.readDirectory(path);\n const entries = await providerV2.readDirectory(parseWorkspacePath(path));\n return entries.map((entry) => ({ kind: entry.kind, name: entry.name, path: entry.path }));\n}\n\nfunction cancellationError(signal: AbortSignal): unknown {\n if (signal.reason !== undefined) return signal.reason;\n return new DocumentDiscoveryError('cancelled', 'Document discovery was cancelled.');\n}\n\nasync function readWithBudget(\n provider: FileSystemProvider,\n directory: string,\n deadline: number,\n signal: AbortSignal | undefined,\n): Promise<FileSystemEntry[]> {\n if (signal?.aborted) throw cancellationError(signal);\n const remaining = deadline - Date.now();\n if (remaining <= 0) {\n throw new DocumentDiscoveryError('timeout', 'Document discovery exceeded its time limit.');\n }\n\n return new Promise<FileSystemEntry[]>((resolve, reject) => {\n let settled = false;\n const finish = (operation: () => void): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n operation();\n };\n const onAbort = (): void => finish(() => reject(cancellationError(signal!)));\n const timer = setTimeout(\n () =>\n finish(() =>\n reject(\n new DocumentDiscoveryError('timeout', 'Document discovery exceeded its time limit.'),\n ),\n ),\n remaining,\n );\n signal?.addEventListener('abort', onAbort, { once: true });\n void readDirectory(provider, directory).then(\n (entries) => finish(() => resolve(entries)),\n (error: unknown) => finish(() => reject(error)),\n );\n });\n}\n\n/**\n * Collect workspace Markdown without allowing one link-dialog request to walk\n * an unbounded tree or hang forever on a stalled provider.\n */\nexport async function collectMarkdownFiles(\n provider: FileSystemProvider,\n root: string,\n options: DocumentDiscoveryOptions = {},\n): Promise<FileSystemEntry[]> {\n const maxEntries = positiveLimit(\n options.maxEntries,\n DEFAULT_DOCUMENT_DISCOVERY_LIMITS.entries,\n 'entry',\n );\n const maxDirectories = positiveLimit(\n options.maxDirectories,\n DEFAULT_DOCUMENT_DISCOVERY_LIMITS.directories,\n 'directory',\n );\n const maxDepth = positiveLimit(\n options.maxDepth,\n DEFAULT_DOCUMENT_DISCOVERY_LIMITS.depth,\n 'depth',\n );\n const timeoutMs = positiveLimit(\n options.timeoutMs,\n DEFAULT_DOCUMENT_DISCOVERY_LIMITS.milliseconds,\n 'time',\n );\n const deadline = Date.now() + timeoutMs;\n const markdown: FileSystemEntry[] = [];\n const visited = new Set<string>();\n const pending: Array<{ path: string; depth: number }> = [{ path: root, depth: 0 }];\n let entryCount = 0;\n\n while (pending.length > 0) {\n if (options.signal?.aborted) throw cancellationError(options.signal);\n const current = pending.pop()!;\n const canonical = parseWorkspacePath(current.path);\n if (visited.has(canonical)) continue;\n visited.add(canonical);\n if (visited.size > maxDirectories) {\n throw new DocumentDiscoveryError(\n 'limit',\n `Document discovery exceeded ${maxDirectories} directories.`,\n );\n }\n\n let entries: FileSystemEntry[];\n try {\n entries = await readWithBudget(provider, canonical, deadline, options.signal);\n } catch (error: unknown) {\n if (error instanceof FsError && error.code === 'not-found') continue;\n throw error;\n }\n entryCount += entries.length;\n if (entryCount > maxEntries) {\n throw new DocumentDiscoveryError(\n 'limit',\n `Document discovery exceeded ${maxEntries} entries.`,\n );\n }\n\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n const entry = entries[index];\n if (entry.kind === 'directory') {\n const lower = entry.name.toLowerCase();\n if (lower.startsWith('.') || lower === 'node_modules' || lower.endsWith('_files')) continue;\n if (current.depth >= maxDepth) {\n throw new DocumentDiscoveryError(\n 'limit',\n `Document discovery exceeded a depth of ${maxDepth}.`,\n );\n }\n pending.push({ path: entry.path, depth: current.depth + 1 });\n } else if (entry.kind === 'file' && entry.name.toLowerCase().endsWith('.md')) {\n markdown.push(entry);\n }\n }\n }\n\n return markdown;\n}\n\nfunction dirname(path: string): string {\n const clean = path.replace(/^\\/+/, '');\n const index = clean.lastIndexOf('/');\n return index < 0 ? '' : clean.slice(0, index);\n}\n\nexport function relativeMarkdownLink(fromFile: string, toFile: string): string {\n const fromParts = fromFile.replace(/^\\/+/, '').split('/').filter(Boolean);\n const toParts = toFile.replace(/^\\/+/, '').split('/').filter(Boolean);\n const fromDirectory = fromParts.slice(0, -1);\n const toDirectory = toParts.slice(0, -1);\n const toBase = toParts[toParts.length - 1] ?? '';\n let common = 0;\n while (\n common < fromDirectory.length &&\n common < toDirectory.length &&\n fromDirectory[common] === toDirectory[common]\n ) {\n common += 1;\n }\n const parts = [\n ...Array(fromDirectory.length - common).fill('..'),\n ...toDirectory.slice(common),\n toBase,\n ];\n return parts.length === 0 ? toBase : parts.join('/');\n}\n\nexport function createDocumentLinkCandidates(\n entries: readonly FileSystemEntry[],\n selectedFile: string,\n query: string,\n): DocumentLinkCandidate[] {\n const normalizedQuery = query.trim().toLowerCase();\n const selected = parseWorkspacePath(selectedFile);\n const candidates: DocumentLinkCandidate[] = [];\n for (const entry of entries) {\n if (entry.kind !== 'file' || parseWorkspacePath(entry.path) === selected) continue;\n const label = entry.name.replace(/\\.md$/iu, '');\n const path = relativeMarkdownLink(selectedFile, entry.path);\n if (\n normalizedQuery &&\n !label.toLowerCase().includes(normalizedQuery) &&\n !path.toLowerCase().includes(normalizedQuery)\n ) {\n continue;\n }\n const description = dirname(entry.path);\n candidates.push(description ? { path, label, description } : { path, label });\n }\n candidates.sort((left, right) => left.label.localeCompare(right.label));\n return candidates;\n}\n","/**\n * Renderer-side barrier for main-authoritative Electron workspace identity.\n * OS requests may arrive before IndexedDB descriptors have been reconciled;\n * they must retain navigation priority while waiting for that reconciliation.\n */\nexport class WorkspaceAuthorityBarrier {\n private ready = false;\n private readonly readyPromise: Promise<void>;\n private resolveReady!: () => void;\n\n public constructor() {\n this.readyPromise = new Promise<void>((resolve) => {\n this.resolveReady = resolve;\n });\n }\n\n public markReady(): void {\n if (this.ready) return;\n this.ready = true;\n this.resolveReady();\n }\n\n public wait(): Promise<void> {\n return this.readyPromise;\n }\n}\n","import {\n getFileSystemProviderV2,\n type FileSystemFileSnapshot,\n type FileSystemProvider,\n type FileSystemSnapshotFile,\n type WorkspacePath,\n} from '@bendyline/docblocks/filesystem';\n\nfunction pathDepth(path: WorkspacePath): number {\n return path ? path.split('/').length : 0;\n}\n\n/**\n * Copy a complete transient workspace tree into an existing workspace root.\n *\n * Every destination entry is created with no-replace semantics. If a write\n * fails after creation begins, files are removed only while their versions\n * still match the versions created here, followed by now-empty directories.\n * The caller owns closing the transient workspace after its document session\n * has transitioned to the returned destination tree.\n */\nexport async function copyTransientWorkspaceContents(\n source: FileSystemProvider,\n destination: FileSystemProvider,\n): Promise<void> {\n const sourceV2 = getFileSystemProviderV2(source);\n const destinationV2 = getFileSystemProviderV2(destination);\n if (!sourceV2 || !destinationV2) {\n throw new Error('Moving a temporary document requires a current workspace provider.');\n }\n\n const snapshot = await sourceV2.snapshot();\n const entries = snapshot.entries.filter((entry) => entry.path !== '');\n if (entries.length === 0) {\n throw new Error('The temporary workspace does not contain anything to move.');\n }\n\n // Preflight the complete snapshot before making the first mutation. A DBK\n // can contain a Markdown file plus several companion directories; none of\n // those entries may merge with or replace destination content implicitly.\n for (const entry of entries) {\n if ((await destinationV2.stat(entry.path)) !== null) {\n throw new Error(\n `“${entry.path}” already exists in ${destination.label}. Rename or move it, then try again.`,\n );\n }\n }\n\n const directories = entries\n .filter((entry) => entry.kind === 'directory')\n .sort((left, right) => pathDepth(left.path) - pathDepth(right.path));\n const files = entries\n .filter((entry): entry is FileSystemSnapshotFile => entry.kind === 'file')\n .sort((left, right) => left.path.localeCompare(right.path));\n const createdDirectories: WorkspacePath[] = [];\n const createdFiles: FileSystemFileSnapshot[] = [];\n\n try {\n for (const directory of directories) {\n await destinationV2.createDirectory(directory.path, {\n mode: 'create',\n createParents: false,\n });\n createdDirectories.push(directory.path);\n }\n for (const file of files) {\n const created = await destinationV2.writeFile(file.path, file.data, {\n mode: 'create',\n createParents: false,\n expectedVersion: null,\n });\n createdFiles.push(created);\n }\n } catch (error: unknown) {\n // A changed file is no longer ours to remove. Empty-directory removal is\n // deliberately non-recursive so a concurrent addition is preserved.\n for (const file of [...createdFiles].reverse()) {\n try {\n await destinationV2.remove(file.path, {\n missing: 'ignore',\n expectedVersion: file.version,\n });\n } catch {\n // Best-effort rollback cannot overwrite the original failure.\n }\n }\n for (const path of [...createdDirectories].reverse()) {\n try {\n const current = await destinationV2.stat(path);\n if (current?.kind !== 'directory') continue;\n await destinationV2.remove(path, {\n recursive: false,\n missing: 'ignore',\n expectedVersion: current.version,\n });\n } catch {\n // Preserve a non-empty or concurrently changed directory.\n }\n }\n throw error;\n }\n}\n","/** Keep a user-edited target name while switching the selected export format. */\nexport function updateExportTargetExtension(targetPath: string, suggestedFilename: string): string {\n const nextExtension = extensionOf(suggestedFilename);\n if (!nextExtension) return targetPath;\n if (!targetPath.trim()) return suggestedFilename;\n\n const suffixIndex = firstSuffixIndex(targetPath);\n const pathPart = suffixIndex === -1 ? targetPath : targetPath.slice(0, suffixIndex);\n const suffix = suffixIndex === -1 ? '' : targetPath.slice(suffixIndex);\n const separatorIndex = Math.max(pathPart.lastIndexOf('/'), pathPart.lastIndexOf('\\\\'));\n const dotIndex = pathPart.lastIndexOf('.');\n const stem = dotIndex > separatorIndex ? pathPart.slice(0, dotIndex) : pathPart;\n return `${stem}${nextExtension}${suffix}`;\n}\n\nfunction extensionOf(value: string): string {\n const suffixIndex = firstSuffixIndex(value);\n const pathPart = suffixIndex === -1 ? value : value.slice(0, suffixIndex);\n const separatorIndex = Math.max(pathPart.lastIndexOf('/'), pathPart.lastIndexOf('\\\\'));\n const dotIndex = pathPart.lastIndexOf('.');\n return dotIndex > separatorIndex ? pathPart.slice(dotIndex) : '';\n}\n\nfunction firstSuffixIndex(value: string): number {\n const query = value.indexOf('?');\n const fragment = value.indexOf('#');\n if (query === -1) return fragment;\n if (fragment === -1) return query;\n return Math.min(query, fragment);\n}\n"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","parseWorkspacePath","useCallback","useState","useRef","useEffect","jsx","jsxs","useState","useRef","useCallback","parentPath","useEffect","parentPath","row","jsx","jsxs","normalisePath","parseWorkspacePath","hasEquivalentPath","useState","useRef","useEffect","useCallback","Fragment","useState","useEffect","useCallback","useRef","jsx","jsxs","Fragment","useState","useRef","useEffect","useCallback","useState","useCallback","useEffect","useRef","useMemo","lazy","Suspense","FsError","getFileSystemProviderV2","parseWorkspacePath","isElectronHost","listWorkspaces","saveWorkspace","touchWorkspace","useState","useCallback","useRef","useEffect","Fragment","jsx","jsxs","useState","useRef","useEffect","useCallback","useState","useCallback","useRef","useEffect","jsx","jsxs","useState","useRef","useEffect","useCallback","jsx","jsxs","useState","jsx","useCallback","useEffect","useMemo","useRef","useState","useCallback","useEffect","useRef","useState","useState","useEffect","useMemo","useCallback","useRef","useEffect","FsError","FsError","getFileSystemProviderV2","parseWorkspacePath","FsError","SUPPORTED_EXTENSIONS","React","useCallback","useEffect","useRef","useState","useCallback","useEffect","useRef","useState","Fragment","jsx","jsxs","useState","useRef","useCallback","useEffect","useState","useRef","useCallback","useEffect","React","React","useCallback","useEffect","useRef","useState","useCallback","useRef","Fragment","jsx","jsxs","useRef","useCallback","useState","useRef","useCallback","open","useEffect","React","useState","Fragment","jsx","jsxs","useCallback","useEffect","useRef","FsError","getFileSystemProviderV2","parseWorkspacePath","useRef","useEffect","useCallback","getFileSystemProviderV2","Fragment","jsx","jsxs","lazy","useState","useEffect","parseWorkspacePath","parentPath","readProviderDirectory","getFileSystemProviderV2","useCallback","isElectronHost","useRef","listWorkspaces","saveWorkspace","useMemo","writable","touchWorkspace","FsError","mgr","descriptor","provider","Suspense"]}