@tangle-network/agent-app 0.60.161 → 0.60.163
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/VaultPane-QEG35UAZ.js +7 -0
- package/dist/assistant/index.js +1 -1
- package/dist/{chunk-N5VO46Z6.js → chunk-IDQU36M5.js} +99 -24
- package/dist/chunk-IDQU36M5.js.map +1 -0
- package/dist/{chunk-UMWASXC2.js → chunk-J3D3HQPY.js} +5 -1
- package/dist/{chunk-UMWASXC2.js.map → chunk-J3D3HQPY.js.map} +1 -1
- package/dist/vault/contracts.d.ts +4 -0
- package/dist/vault/index.js +1 -1
- package/dist/vault/lazy.js +1 -1
- package/dist/web-react/composer-profile-pill.d.ts +5 -2
- package/dist/web-react/index.js +1 -1
- package/package.json +3 -3
- package/dist/VaultPane-IJTK3BDM.js +0 -7
- package/dist/chunk-N5VO46Z6.js.map +0 -1
- /package/dist/{VaultPane-IJTK3BDM.js.map → VaultPane-QEG35UAZ.js.map} +0 -0
|
@@ -151,6 +151,10 @@ export interface VaultArtifactRenderProps {
|
|
|
151
151
|
/** The live rich draft (the codec's parsed form). The product's rich editor
|
|
152
152
|
* edits this; reverting to the saved content clears dirtiness. */
|
|
153
153
|
richDraft: VaultRichParts;
|
|
154
|
+
/** Codec-parsed persisted baseline, independent of `richDraft`. Pass its body
|
|
155
|
+
* to an editor's saved-content prop when the live draft drives its content.
|
|
156
|
+
* Optional for structural compatibility with existing custom renderers. */
|
|
157
|
+
savedRichDraft?: VaultRichParts;
|
|
154
158
|
/** Whether the draft has unsaved edits. */
|
|
155
159
|
dirty: boolean;
|
|
156
160
|
/** The product's rich editor reports edits here (updates draft + dirtiness). */
|
package/dist/vault/index.js
CHANGED
package/dist/vault/lazy.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/vault/lazy.tsx
|
|
2
2
|
import { lazy } from "react";
|
|
3
3
|
var VaultPaneLazy = lazy(
|
|
4
|
-
() => import("../VaultPane-
|
|
4
|
+
() => import("../VaultPane-QEG35UAZ.js").then((m) => ({ default: m.VaultPane }))
|
|
5
5
|
);
|
|
6
6
|
export {
|
|
7
7
|
VaultPaneLazy
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AgentProfilePickerProps } from '@tangle-network/sandbox-ui/chat';
|
|
2
2
|
/** The selection half of a thread's profile: the picker's own field names, so a rename upstream cannot drift past this. */
|
|
3
3
|
export type ComposerProfileSelection = Pick<AgentProfilePickerProps, 'value' | 'onChange' | 'profiles' | 'disabled'>;
|
|
4
|
-
export interface ComposerProfilePillProps extends Pick<AgentProfilePickerProps, 'locked' | 'lockReason' | 'onNewChat' | 'side' | 'capabilities' | 'onCreate' | 'onUpdate' | 'onDelete'> {
|
|
4
|
+
export interface ComposerProfilePillProps extends Pick<AgentProfilePickerProps, 'locked' | 'lockReason' | 'onNewChat' | 'side' | 'capabilities' | 'onCreate' | 'onUpdate' | 'onDelete' | 'onEdit' | 'onNew'> {
|
|
5
5
|
/** The catalog and the current choice; products pass their server-resolvable profiles only. */
|
|
6
6
|
selection: ComposerProfileSelection;
|
|
7
7
|
/**
|
|
@@ -22,5 +22,8 @@ export interface ComposerProfilePillProps extends Pick<AgentProfilePickerProps,
|
|
|
22
22
|
* writes and selection; pass its callbacks to enable authoring and switching
|
|
23
23
|
* within the current conversation. `locked` is reserved for a product-specific
|
|
24
24
|
* admission constraint, not a conversation that already has messages.
|
|
25
|
+
* Use `onEdit` and `onNew` to open the product's shared AgentProfileEditor.
|
|
26
|
+
* Inline `onCreate`/`onUpdate` callbacks resolve only after the write is
|
|
27
|
+
* confirmed and reject refused writes, so the picker can preserve the draft.
|
|
25
28
|
*/
|
|
26
|
-
export declare function ComposerProfilePill({ selection, locked, lockReason, onNewChat, capabilities, onCreate, onUpdate, onDelete, side, placement, className, }: ComposerProfilePillProps): import("react").JSX.Element;
|
|
29
|
+
export declare function ComposerProfilePill({ selection, locked, lockReason, onNewChat, capabilities, onCreate, onUpdate, onDelete, onEdit, onNew, side, placement, className, }: ComposerProfilePillProps): import("react").JSX.Element;
|
package/dist/web-react/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-app",
|
|
3
|
-
"version": "0.60.
|
|
3
|
+
"version": "0.60.163",
|
|
4
4
|
"packageManager": "pnpm@11.24.0",
|
|
5
5
|
"description": "Build agent applications with typed chat, tools, sandboxes, integrations, billing, and evaluation.",
|
|
6
6
|
"keywords": [
|
|
@@ -700,7 +700,7 @@
|
|
|
700
700
|
"@tangle-network/brand": "1.24.2",
|
|
701
701
|
"@tangle-network/hub-sdk": "0.28.0",
|
|
702
702
|
"@tangle-network/sandbox": "0.60.22",
|
|
703
|
-
"@tangle-network/sandbox-ui": "0.134.
|
|
703
|
+
"@tangle-network/sandbox-ui": "0.134.6",
|
|
704
704
|
"@tangle-network/ui": "11.33.0",
|
|
705
705
|
"@testing-library/dom": "^10.4.1",
|
|
706
706
|
"@testing-library/react": "^16.3.3",
|
|
@@ -772,7 +772,7 @@
|
|
|
772
772
|
"@tangle-network/brand": ">=1.21.1",
|
|
773
773
|
"@tangle-network/hub-sdk": ">=0.19.3 <0.21.0 || >=0.21.0 <0.22.0 || >=0.22.1 <0.25.0 || >=0.27.0 <0.28.0 || >=0.28.0 <0.29.0",
|
|
774
774
|
"@tangle-network/sandbox": ">=0.45.0 <0.48.0 || ^0.49.0 || ^0.50.0 || ^0.51.0 || ^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || >=0.58.1 <0.60.0 || >=0.60.3 <0.61.0",
|
|
775
|
-
"@tangle-network/sandbox-ui": ">=0.134.
|
|
775
|
+
"@tangle-network/sandbox-ui": ">=0.134.6 <0.135.0",
|
|
776
776
|
"@tangle-network/ui": ">=11.32.0 <12.0.0",
|
|
777
777
|
"@tiptap/core": ">=3.28.0 <4.0.0",
|
|
778
778
|
"@tiptap/extension-mention": ">=3.28.0 <4.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vault/VaultPane.tsx","../src/vault/ConfirmDialog.tsx","../src/vault/recent-files.ts","../src/vault/VaultContentResults.tsx","../src/vault/VaultHistoryPanel.tsx"],"sourcesContent":["/**\n * The shared 3-pane vault: tree | artifact viewer | optional agent dock. This is\n * shell mechanism — selection, the dirty-guard + pending-nav state machine,\n * rich/source editor modes, create/delete/refresh, skeletons, and an error\n * boundary — plus the vault's tree (sandbox-ui's `VaultTree`) in a contained surface. It\n * renders no artifact viewer of its own: that arrives through the\n * `renderArtifact` / `renderDock` seams, and `renderTree` can replace the tree.\n *\n * Data flows exclusively through `port` (a `VaultDataPort`). The pane never\n * imports a fetch client, a router, a toast system, or a markdown library — the\n * optional `codec` seam supplies rich/source parsing (identity passthrough by\n * default). Chrome uses the shared theme tokens (bg-card, border-border, …).\n */\n\nimport {\n Component,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ErrorInfo,\n type ReactNode,\n} from 'react'\nimport { Download, FileText, Folder, History, Plus, RefreshCw, Trash2 } from 'lucide-react'\nimport { ConfirmDialog } from './ConfirmDialog'\nimport { readRecentFiles, recordRecentFile } from './recent-files'\nimport { VaultContentResults, type ContentSearchState } from './VaultContentResults'\nimport { VaultHistoryPanel } from './VaultHistoryPanel'\nimport { filterFileNodes, VaultTree } from '@tangle-network/sandbox-ui/vault-tree'\nimport type {\n VaultEditorMode,\n VaultFile,\n VaultMarkdownCodec,\n VaultOperation,\n VaultOperationFailure,\n VaultOperationPhase,\n VaultPaneHandle,\n VaultPaneProps,\n VaultRichParts,\n VaultTreeNode,\n} from './contracts'\nimport { ShellHeader } from '@tangle-network/sandbox-ui/workspace'\n\n/** Narrowest pane that places a dock beside the document rather than in it. */\nconst DOCK_SIDE_MIN_PX = 960\n\n/** Characters a content search needs before it asks the port. */\nconst CONTENT_SEARCH_MIN = 2\n/** Pause after the last keystroke before a content search is sent. */\nconst CONTENT_SEARCH_DEBOUNCE_MS = 250\n\n/** Square header action on the control scale's small step, a touch target on coarse pointers. */\nconst TREE_ICON_BUTTON = 'inline-flex size-8 shrink-0 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [@media(pointer:coarse)]:size-10'\n\nconst IDENTITY_CODEC: VaultMarkdownCodec = {\n parse: (raw) => raw,\n serialize: (parts) => (typeof parts === 'string' ? parts : String(parts ?? '')),\n}\n\ntype PendingNav = { path: string; request?: PendingOpen } | null\ntype PendingOpen = {\n path: string\n fromPath: string | null\n resolve: (opened: boolean) => void\n loaded: boolean\n selected: boolean\n}\n\ninterface TreeRefreshContext {\n operation: Extract<VaultOperation, 'list' | 'create' | 'delete'>\n phase: VaultOperationPhase\n path?: string\n selectAfterRecovery?: string\n}\n\ninterface TreeFailureState {\n failure: VaultOperationFailure\n context: TreeRefreshContext\n}\n\nconst LIST_CONTEXT: TreeRefreshContext = { operation: 'list', phase: 'operation' }\n\nfunction operationMessage(error: unknown, fallback: string): string {\n return error instanceof Error && error.message ? error.message : fallback\n}\n\nfunction treeFailureMessage(failure: VaultOperationFailure, label: string): string {\n if (failure.phase !== 'post-mutation-refresh') return failure.message\n const completed = failure.operation === 'create' ? 'created' : 'deleted'\n return `The file was ${completed}, but ${label} couldn't refresh. ${failure.message}`\n}\n\ninterface TreePaths {\n files: Set<string>\n directories: Set<string>\n}\n\n// Directories are collected alongside files because a click on one has to be\n// RECOGNIZED to be answered — dropping them here is what made a folder row a\n// dead target: the path resolved to nothing and every downstream branch was\n// keyed on a file.\nfunction collectTreePaths(nodes: VaultTreeNode[], into: TreePaths): TreePaths {\n for (const node of nodes) {\n if (node.type === 'file') into.files.add(node.path)\n else into.directories.add(node.path)\n if (node.children) collectTreePaths(node.children, into)\n }\n return into\n}\n\nfunction resolveFilePath(rawPath: string, filePaths: Set<string>): string | null {\n if (filePaths.has(rawPath)) return rawPath\n const path = rawPath.replace(/^\\/+|\\/+$/g, '')\n return filePaths.has(path) ? path : null\n}\n\nfunction resolveTreePath(rawPath: string, paths: TreePaths): { path: string; type: 'file' | 'directory' } | null {\n const file = resolveFilePath(rawPath, paths.files)\n if (file) return { path: file, type: 'file' }\n if (paths.directories.has(rawPath)) return { path: rawPath, type: 'directory' }\n const trimmed = rawPath.replace(/^\\/+|\\/+$/g, '')\n return paths.directories.has(trimmed) ? { path: trimmed, type: 'directory' } : null\n}\n\nfunction findDirectory(nodes: VaultTreeNode[], path: string): VaultTreeNode | null {\n for (const node of nodes) {\n if (node.type === 'directory' && node.path === path) return node\n const found = node.children ? findDirectory(node.children, path) : null\n if (found) return found\n }\n return null\n}\n\nclass EditorErrorBoundary extends Component<{ children: ReactNode; label: string; onReset?: () => void }, { error: unknown }> {\n state: { error: unknown } = { error: null }\n static getDerivedStateFromError(error: unknown) {\n return { error }\n }\n componentDidCatch(error: unknown, info: ErrorInfo) {\n console.error('Vault crashed:', error, info)\n }\n render() {\n if (this.state.error) {\n const msg = this.state.error instanceof Error\n ? this.state.error.message\n : typeof this.state.error === 'string'\n ? this.state.error\n : `${this.props.label} did not load. Reload the page to try again.`\n return (\n <div className=\"flex h-full flex-1 flex-col items-center justify-center p-8 text-center\">\n <h3 className=\"mb-1 text-sm font-medium text-foreground\">{this.props.label} failed to load</h3>\n <p className=\"mb-4 max-w-xs text-xs text-muted-foreground\">{String(msg)}</p>\n <button\n type=\"button\"\n onClick={() => { this.setState({ error: null }); this.props.onReset?.() }}\n className=\"inline-flex h-8 items-center rounded-md border border-border px-3 text-xs font-medium text-foreground transition-colors hover:bg-muted\"\n >\n Try again\n </button>\n </div>\n )\n }\n return this.props.children\n }\n}\n\n/**\n * A skeleton is a picture of a wait, and a picture is exactly what a screen\n * reader cannot see. `aria-hidden` on the shimmer bars is right — they carry no\n * information — but hiding them without saying anything else is what left the\n * whole load silent. The container announces the wait instead: `aria-busy` for\n * the state, a `status` live region so arrival is reported, and a real text\n * label, since a live region with only decorative children announces nothing.\n */\nfunction SkeletonRegion({ label, className, children }: { label: string; className: string; children: ReactNode }) {\n // The live region is a SIBLING of the shimmer, not a wrapper around it: the\n // shimmer container keeps its exact classes and its exact position in the\n // parent's layout, so adding the announcement cannot move a pixel. Wrapping\n // it would put a new box between `space-y-*` and the bars it spaces.\n return (\n <>\n <span role=\"status\" aria-live=\"polite\" aria-busy={true} className=\"sr-only\">\n {label}\n </span>\n <div className={className} aria-hidden=\"true\">\n {children}\n </div>\n </>\n )\n}\n\nfunction TreeSkeleton() {\n return (\n <SkeletonRegion label=\"Loading files…\" className=\"space-y-2 p-4\">\n {[32, 48, 40, 52].map((w, i) => (\n <div key={i} className=\"h-4 animate-pulse rounded bg-muted\" style={{ width: `${w * 4}px` }} />\n ))}\n </SkeletonRegion>\n )\n}\n\nfunction EditorSkeleton() {\n return (\n <SkeletonRegion label=\"Loading file…\" className=\"space-y-3 p-8\">\n <div className=\"h-5 w-1/2 animate-pulse rounded bg-muted\" />\n <div className=\"h-4 w-full animate-pulse rounded bg-muted\" />\n <div className=\"h-4 w-3/4 animate-pulse rounded bg-muted\" />\n <div className=\"h-4 w-2/3 animate-pulse rounded bg-muted\" />\n </SkeletonRegion>\n )\n}\n\nfunction ReadErrorState({ message, onRetry }: { message: string; onRetry: () => void }) {\n return (\n <div className=\"flex h-full flex-col items-center justify-center gap-3 p-8 text-center\">\n <div>\n <h3 className=\"text-sm font-medium text-foreground\">Couldn't open this file</h3>\n <p className=\"mt-1 max-w-md text-xs text-muted-foreground\">{message}</p>\n </div>\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"inline-flex h-8 items-center rounded-md border border-border px-3 text-xs font-medium text-foreground transition-colors hover:bg-muted\"\n >\n Retry\n </button>\n </div>\n )\n}\n\nfunction TreeErrorState({ label, message, onRetry }: { label: string; message: string; onRetry: () => void }) {\n return (\n <div role=\"alert\" className=\"flex h-full flex-col items-center justify-center gap-3 p-6 text-center\">\n <div>\n <h3 className=\"text-sm font-medium text-foreground\">Couldn't load {label}</h3>\n <p className=\"mt-1 max-w-xs text-xs text-muted-foreground\">{message}</p>\n </div>\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"inline-flex h-8 items-center rounded-md border border-border px-3 text-xs font-medium text-foreground transition-colors hover:bg-muted\"\n >\n Retry\n </button>\n </div>\n )\n}\n\n/**\n * The tree pane when the vault holds nothing at all. It sits under the header\n * whose controls add files, so it names the state and offers the same action\n * instead of leaving a blank column under a search box with nothing to search.\n */\nfunction TreeEmptyState({ canCreate, onCreate }: { canCreate: boolean; onCreate: () => void }) {\n return (\n <div className=\"flex h-full flex-col items-center justify-center gap-3 p-6 text-center\">\n <div>\n <h3 className=\"text-sm font-medium text-foreground\">No files yet</h3>\n <p className=\"mt-1 max-w-xs text-xs text-muted-foreground\">\n {canCreate ? 'Create a file to start.' : 'Files appear here once they are added.'}\n </p>\n </div>\n {canCreate && (\n <button\n type=\"button\"\n onClick={onCreate}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90\"\n >\n <Plus className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n New file\n </button>\n )}\n </div>\n )\n}\n\nfunction TreeNoMatchState({ query, onClear }: { query: string; onClear: () => void }) {\n return (\n <div className=\"flex flex-col items-center gap-3 p-6 text-center\">\n <p className=\"max-w-xs break-words text-xs text-muted-foreground\">No files match “{query}”.</p>\n <button\n type=\"button\"\n onClick={onClear}\n className=\"inline-flex h-8 items-center rounded-md border border-border px-3 text-xs font-medium text-foreground transition-colors hover:bg-muted\"\n >\n Clear search\n </button>\n </div>\n )\n}\n\nfunction OperationErrorAlert({\n message,\n retryLabel,\n onRetry,\n onDismiss,\n}: {\n message: string\n retryLabel: string\n onRetry: () => void\n onDismiss: () => void\n}) {\n return (\n <div\n role=\"alert\"\n className=\"flex shrink-0 items-center justify-between gap-3 border-b border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-[var(--surface-danger-text)]\"\n >\n <span className=\"min-w-0 flex-1\">{message}</span>\n <div className=\"flex shrink-0 items-center gap-3\">\n <button type=\"button\" aria-label={retryLabel} onClick={onRetry} className=\"font-medium underline-offset-2 hover:underline\">\n Retry\n </button>\n <button type=\"button\" onClick={onDismiss} className=\"underline-offset-2 hover:underline\">\n Dismiss\n </button>\n </div>\n </div>\n )\n}\n\n/** How many recent files the empty document pane offers. */\nconst RECENT_SHOWN = 5\n\n/**\n * The document pane with nothing open: says what to do, and offers the files\n * this reader opened last in this vault so returning work is one click away.\n */\nfunction DocumentEmptyState({ label, recent, onOpen }: { label: string; recent: string[]; onOpen: (path: string) => void }) {\n const recentHeadingId = useId()\n return (\n <div data-vault-document-empty className=\"flex h-full items-center justify-center overflow-y-auto p-8\">\n <div className=\"w-full max-w-sm text-center\">\n <span className=\"mx-auto flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground\">\n <FileText className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <h3 className=\"mt-4 text-base font-semibold text-foreground\">Select a file</h3>\n <p className=\"mt-1 text-sm text-muted-foreground\">Choose a file in {label} to open it here.</p>\n {recent.length > 0 && (\n <section aria-labelledby={recentHeadingId} className=\"mt-8 text-left\">\n <h4 id={recentHeadingId} className=\"text-xs font-medium text-muted-foreground\">Recently opened</h4>\n <ul className=\"mt-2 overflow-hidden rounded-xl border border-border bg-card shadow-raised\">\n {recent.map((path) => {\n const slash = path.lastIndexOf('/')\n return (\n <li key={path} className=\"border-b border-border last:border-b-0\">\n <button\n type=\"button\"\n onClick={() => onOpen(path)}\n title={path}\n className=\"flex min-h-10 w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring\"\n >\n <FileText className=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <span className=\"min-w-0 truncate font-medium\">{path.slice(slash + 1)}</span>\n {slash > 0 && <span className=\"ml-auto min-w-0 shrink truncate text-xs text-muted-foreground\">{path.slice(0, slash)}</span>}\n </button>\n </li>\n )\n })}\n </ul>\n </section>\n )}\n </div>\n </div>\n )\n}\n\n/**\n * Browse and edit files in the available pane width.\n * Below 60rem, Files and the selected document share one pane, so an open\n * document gets the whole width: beside a 23rem tree, a narrower pane left a\n * GTM call sheet's table about 385px and hid its third column.\n * Switching panes keeps the editor mounted and preserves unsaved changes.\n */\nexport const VaultPane = forwardRef<VaultPaneHandle, VaultPaneProps>(function VaultPane(props, ref) {\n const {\n port,\n renderTree,\n treeStateKey,\n renderArtifact,\n renderDock,\n canWrite = true,\n selectedPath: controlledPath,\n onSelectedPathChange,\n onOperationError,\n codec,\n className,\n dockToggle,\n refreshKey,\n headerActions,\n onDownloadFile,\n pathBarClassName,\n label = 'Vault',\n emptyState,\n treeEmptyState,\n dockLabel = 'Details',\n fileActions,\n } = props\n const noun = label.toLowerCase()\n const canCreate = canWrite && (props.canCreate ?? true)\n const canDelete = canWrite && (props.canDelete ?? true)\n\n const activeCodec = codec ?? IDENTITY_CODEC\n const controlled = controlledPath !== undefined\n const isMarkdownCapable = codec !== undefined\n // `false` → a persistent dock (no toggle, always open with the selected file).\n const persistentDock = dockToggle === false\n const dockToggleCfg = dockToggle ? dockToggle : { label: 'Discuss', disabledWhenDirty: true }\n\n const [tree, setTree] = useState<VaultTreeNode[]>([])\n const [treeLoading, setTreeLoading] = useState(true)\n const [treeLoaded, setTreeLoaded] = useState(false)\n const [treeError, setTreeError] = useState<TreeFailureState | null>(null)\n const [internalPath, setInternalPath] = useState<string | null>(null)\n const selectedPath = controlled ? (controlledPath ?? null) : internalPath\n const [filesOpen, setFilesOpen] = useState(false)\n const showFiles = filesOpen || !selectedPath\n const searchRef = useRef<HTMLInputElement>(null)\n const documentRef = useRef<HTMLDivElement>(null)\n const treeHeadingId = useId()\n const [recentFiles, setRecentFiles] = useState(() => ({ key: treeStateKey, paths: readRecentFiles(treeStateKey) }))\n if (recentFiles.key !== treeStateKey) setRecentFiles({ key: treeStateKey, paths: readRecentFiles(treeStateKey) })\n\n useEffect(() => {\n setFilesOpen(false)\n }, [selectedPath])\n\n const showDocument = useCallback(() => {\n const focused = document.activeElement\n setFilesOpen(false)\n requestAnimationFrame(() => {\n if (document.activeElement === focused || document.activeElement === document.body) {\n documentRef.current?.focus({ preventScroll: true })\n }\n })\n }, [])\n\n const [selectedFile, setSelectedFile] = useState<VaultFile | null>(null)\n const [displayReadyPath, setDisplayReadyPath] = useState<string | null>(null)\n const [fileLoading, setFileLoading] = useState(false)\n const [readError, setReadError] = useState<string | null>(null)\n const [reloadNonce, setReloadNonce] = useState(0)\n const [saving, setSaving] = useState(false)\n const [saveError, setSaveError] = useState<VaultOperationFailure | null>(null)\n\n const [editorMode, setEditorMode] = useState<VaultEditorMode>('rich')\n const [richDraft, setRichDraft] = useState<VaultRichParts>('')\n const [sourceDraft, setSourceDraft] = useState('')\n const [isDirty, setIsDirty] = useState(false)\n\n const [createOpen, setCreateOpen] = useState(false)\n const [newPath, setNewPath] = useState('')\n const [creating, setCreating] = useState(false)\n const [createError, setCreateError] = useState<VaultOperationFailure | null>(null)\n const [deleteOpen, setDeleteOpen] = useState(false)\n const [deleting, setDeleting] = useState(false)\n const [deleteError, setDeleteError] = useState<VaultOperationFailure | null>(null)\n const [dockOpen, setDockOpen] = useState(false)\n // Below DOCK_SIDE_MIN_PX of pane width a side dock squeezes the document to\n // nothing (measured on Legal at 390px: the review panel took the whole width\n // and the document and its Files switcher were unreachable). There the dock\n // opens IN the document pane instead, behind a path-bar toggle. Measured, not\n // a media query: the pane is often a drawer or a split inside a wide window.\n const rootRef = useRef<HTMLDivElement>(null)\n const [dockInline, setDockInline] = useState(false)\n useLayoutEffect(() => {\n const root = rootRef.current\n if (!root || !renderDock || typeof ResizeObserver === 'undefined') return\n const apply = (width: number) => { if (width > 0) setDockInline(width < DOCK_SIDE_MIN_PX) }\n apply(root.getBoundingClientRect().width)\n const observer = new ResizeObserver((entries) => apply(entries[0]?.contentRect.width ?? 0))\n observer.observe(root)\n return () => observer.disconnect()\n }, [renderDock])\n const [pendingNav, setPendingNav] = useState<PendingNav>(null)\n const [query, setQuery] = useState('')\n const [folderPath, setFolderPath] = useState<string | null>(null)\n const [contentSearch, setContentSearch] = useState<ContentSearchState>({ status: 'idle' })\n const [contentSearchNonce, setContentSearchNonce] = useState(0)\n const [historyOpen, setHistoryOpen] = useState(false)\n\n const dirtyRef = useRef(isDirty)\n dirtyRef.current = isDirty\n const treeRequestRef = useRef(0)\n const savedContentRef = useRef('')\n const loadedPathRef = useRef<string | null>(null)\n const onOperationErrorRef = useRef(onOperationError)\n onOperationErrorRef.current = onOperationError\n const pendingOpenRef = useRef<PendingOpen | null>(null)\n const previousPortRef = useRef(port)\n\n const finishPendingOpen = useCallback((opened: boolean, clearNavigation = true) => {\n const pending = pendingOpenRef.current\n if (!pending) return\n pendingOpenRef.current = null\n if (!opened && clearNavigation) {\n setPendingNav((current) => current?.request === pending ? null : current)\n }\n pending.resolve(opened)\n }, [])\n\n useEffect(() => () => finishPendingOpen(false, false), [finishPendingOpen])\n\n useEffect(() => {\n if (previousPortRef.current !== port) finishPendingOpen(false)\n previousPortRef.current = port\n }, [port, finishPendingOpen])\n\n useEffect(() => {\n const pending = pendingOpenRef.current\n if (!pending) return\n if (selectedPath === pending.path) pending.selected = true\n else if (pending.selected || selectedPath !== pending.fromPath) finishPendingOpen(false)\n }, [selectedPath, finishPendingOpen])\n\n const treePaths = useMemo(\n () => collectTreePaths(tree, { files: new Set<string>(), directories: new Set<string>() }),\n [tree],\n )\n const resolvedSelectedPath = useMemo(() => {\n if (!selectedPath) return null\n const listed = resolveTreePath(selectedPath, treePaths)\n if (listed?.type === 'directory') return null\n // A committed file can be readable before an older tree snapshot lists it.\n // The data port owns validation and missing-file errors for explicit paths.\n return listed?.path ?? selectedPath\n }, [selectedPath, treePaths])\n // The clicked folder, resolved against the CURRENT tree — a folder that a\n // refresh removed stops being the active one on its own, so neither the\n // search scope nor the create target can point at a directory that is gone.\n const activeFolderNode = useMemo(\n () => (folderPath ? findDirectory(tree, folderPath) : null),\n [tree, folderPath],\n )\n const activeFolder = activeFolderNode?.path ?? null\n const treeRoot = useMemo<VaultTreeNode>(\n () => ({ name: label, path: '', type: 'directory', children: tree }),\n [tree, label],\n )\n // Search always covers the whole vault. Expanding a folder makes it the\n // active folder, and a search silently narrowed to it hid files the reader\n // was looking for; the active folder only decides where a new file goes.\n const visibleRoot = useMemo<VaultTreeNode>(() => {\n const q = query.trim().toLowerCase()\n if (!q) return treeRoot\n return { ...treeRoot, children: filterFileNodes(treeRoot.children ?? [], q) }\n }, [treeRoot, query])\n\n // Words inside files, from the port, a moment after the reader stops typing.\n const searchQuery = query.trim()\n const canSearchContent = typeof port.searchContent === 'function'\n useEffect(() => {\n if (!canSearchContent || searchQuery.length < CONTENT_SEARCH_MIN) {\n setContentSearch({ status: 'idle' })\n return\n }\n const controller = new AbortController()\n setContentSearch((current) => ({\n status: 'loading',\n query: searchQuery,\n matches: current.status !== 'idle' && current.status !== 'error' && current.query === searchQuery ? current.matches : [],\n }))\n const timer = setTimeout(() => {\n port.searchContent!(searchQuery, { signal: controller.signal }).then(\n (matches) => {\n if (!controller.signal.aborted) setContentSearch({ status: 'done', query: searchQuery, matches })\n },\n (error) => {\n if (!controller.signal.aborted) {\n setContentSearch({ status: 'error', query: searchQuery, message: operationMessage(error, 'The search did not answer.') })\n }\n },\n )\n }, CONTENT_SEARCH_DEBOUNCE_MS)\n return () => {\n clearTimeout(timer)\n controller.abort()\n }\n }, [port, canSearchContent, searchQuery, contentSearchNonce])\n // Until the effect catches up with a new query, its results are pending, not empty.\n const contentResults: ContentSearchState = !canSearchContent || searchQuery.length < CONTENT_SEARCH_MIN\n ? { status: 'idle' }\n : contentSearch.status !== 'idle' && contentSearch.query === searchQuery\n ? contentSearch\n : { status: 'loading', query: searchQuery, matches: [] }\n\n const commitPath = useCallback(\n (next: string | null) => {\n if (controlled) {\n const decision: unknown = onSelectedPathChange?.(next)\n return decision !== false\n }\n setInternalPath(next)\n onSelectedPathChange?.(next)\n return true\n },\n [controlled, onSelectedPathChange],\n )\n\n const reportFailure = useCallback((\n operation: VaultOperation,\n phase: VaultOperationPhase,\n error: unknown,\n fallback: string,\n path?: string,\n ): VaultOperationFailure => {\n const failure: VaultOperationFailure = {\n operation,\n phase,\n path,\n message: operationMessage(error, fallback),\n cause: error,\n }\n try {\n onOperationErrorRef.current?.(failure)\n } catch (callbackError) {\n console.error('Vault onOperationError callback failed:', callbackError)\n }\n return failure\n }, [])\n\n const refresh = useCallback(async (context: TreeRefreshContext = LIST_CONTEXT): Promise<boolean> => {\n const request = ++treeRequestRef.current\n setTreeLoading(true)\n setTreeError(null)\n try {\n const nextTree = await port.listTree()\n if (request !== treeRequestRef.current) return false\n setTree(nextTree)\n setTreeLoaded(true)\n return true\n } catch (error) {\n if (request !== treeRequestRef.current) return false\n const failure = reportFailure(\n context.operation,\n context.phase,\n error,\n `Failed to load ${label}`,\n context.path,\n )\n setTreeError({ failure, context })\n return false\n } finally {\n if (request === treeRequestRef.current) setTreeLoading(false)\n }\n }, [port, reportFailure, label])\n\n useEffect(() => {\n setTree([])\n setTreeLoaded(false)\n setTreeError(null)\n setSelectedFile(null)\n }, [port])\n\n useEffect(() => {\n void refresh()\n return () => { treeRequestRef.current += 1 }\n }, [refresh, refreshKey])\n\n const retryTree = useCallback(async () => {\n if (!treeError) return\n const { context } = treeError\n const recovered = await refresh(context)\n if (recovered && context.selectAfterRecovery) commitPath(context.selectAfterRecovery)\n }, [treeError, refresh, commitPath])\n\n useEffect(() => {\n if (!selectedPath) {\n setSelectedFile(null)\n setFileLoading(false)\n setReadError(null)\n loadedPathRef.current = null\n return\n }\n // An external path can be read after listing fails; the data port still validates access.\n const explicitOpenAfterTreeError = !!treeError && pendingOpenRef.current?.path === selectedPath\n if (treeLoading || (!treeLoaded && !explicitOpenAfterTreeError) || isDirty || saving) return\n if (!resolvedSelectedPath) {\n finishPendingOpen(false)\n commitPath(null)\n setSelectedFile(null)\n setFileLoading(false)\n setReadError(null)\n loadedPathRef.current = null\n return\n }\n let cancelled = false\n const path = resolvedSelectedPath\n if (path !== selectedPath) commitPath(path)\n setFileLoading(true)\n setReadError(null)\n void (async () => {\n try {\n const file = await port.readFile(path)\n if (file.path !== path) throw new Error(`Vault returned ${file.path} for ${path}`)\n if (!cancelled && !dirtyRef.current) {\n const pending = pendingOpenRef.current\n if (pending?.path === path) pending.loaded = true\n setSelectedFile(file)\n } else if (!cancelled && pendingOpenRef.current?.path === path) {\n finishPendingOpen(false)\n }\n } catch (err) {\n // Surface read failures instead of making them indistinguishable from\n // the intentionally empty \"no file selected\" state.\n if (!cancelled) {\n if (pendingOpenRef.current?.path === path) finishPendingOpen(false)\n const failure = reportFailure('read', 'operation', err, 'Failed to read file', path)\n setSelectedFile((current) => current?.path === path ? current : null)\n setReadError(failure.message)\n }\n } finally {\n if (!cancelled) setFileLoading(false)\n }\n })()\n return () => {\n cancelled = true\n }\n }, [port, selectedPath, resolvedSelectedPath, treeLoading, treeLoaded, treeError, isDirty, saving, reloadNonce, commitPath, reportFailure, finishPendingOpen])\n\n useEffect(() => {\n if (!selectedFile) {\n loadedPathRef.current = null\n setDisplayReadyPath(null)\n savedContentRef.current = ''\n setRichDraft('')\n setSourceDraft('')\n setEditorMode('rich')\n setIsDirty(false)\n setSaveError(null)\n return\n }\n const pathChanged = loadedPathRef.current !== selectedFile.path\n loadedPathRef.current = selectedFile.path\n setDisplayReadyPath(selectedFile.path)\n savedContentRef.current = selectedFile.content\n setRichDraft(activeCodec.parse(selectedFile.content))\n setSourceDraft(selectedFile.content)\n if (pathChanged) setEditorMode('rich')\n setIsDirty(false)\n setSaveError(null)\n setDockOpen(false)\n }, [selectedFile?.path, selectedFile?.content, activeCodec])\n\n useEffect(() => {\n const pending = pendingOpenRef.current\n if (\n pending?.loaded &&\n pending.path === selectedPath &&\n selectedFile?.path === pending.path &&\n displayReadyPath === pending.path &&\n sourceDraft === selectedFile.content &&\n !fileLoading\n ) {\n finishPendingOpen(true)\n }\n }, [selectedPath, selectedFile, displayReadyPath, sourceDraft, fileLoading, finishPendingOpen])\n\n const guardedOpen = useCallback((rawPath: string, resolve?: (opened: boolean) => void) => {\n const target = resolveTreePath(rawPath, treePaths)\n if (!rawPath.trim() || target?.type === 'directory') {\n resolve?.(false)\n return\n }\n const path = target?.path ?? rawPath\n finishPendingOpen(false)\n setPendingNav(null)\n if (path === selectedPath && selectedFile?.path === path && displayReadyPath === path) {\n showDocument()\n resolve?.(true)\n return\n }\n if (resolve) {\n const pending: PendingOpen = {\n path,\n fromPath: selectedPath,\n resolve,\n loaded: false,\n selected: path === selectedPath,\n }\n pendingOpenRef.current = pending\n }\n if (path === selectedPath) {\n showDocument()\n if (!fileLoading && (readError || (treeError && !treeLoaded))) setReloadNonce((nonce) => nonce + 1)\n return\n }\n if (isDirty) {\n setPendingNav({ path, request: resolve ? pendingOpenRef.current ?? undefined : undefined })\n return\n }\n showDocument()\n if (commitPath(path) === false) finishPendingOpen(false)\n }, [finishPendingOpen, treePaths, selectedPath, selectedFile, displayReadyPath, fileLoading, showDocument, readError, treeError, treeLoaded, isDirty, commitPath])\n\n useImperativeHandle(ref, () => ({\n openFile: (path) => new Promise<boolean>((resolve) => guardedOpen(path, resolve)),\n }), [guardedOpen])\n\n // Clicking a folder makes it the vault's active folder: the search narrows to\n // it and a new file lands inside it. Clicking it again clears that — the same\n // row is the way back out, so the gesture is reversible where it was made.\n const toggleFolder = useCallback((path: string) => {\n setFolderPath((current) => (current === path ? null : path))\n }, [])\n // The built-in tree reports the folder's new state: expanding a folder makes\n // it active, and collapsing the active folder or one around it clears it.\n const handleFolderToggle = useCallback((path: string, expanded: boolean) => {\n setFolderPath((current) => {\n if (expanded) return path\n return current && (current === path || current.startsWith(`${path}/`)) ? null : current\n })\n }, [])\n\n // Some tree models keep their original selection callback while resetting\n // paths internally. Keep the callable stable, but have it execute the latest\n // path validation and dirty-guard logic.\n const selectFileRef = useRef<(path: string) => void>(() => {})\n selectFileRef.current = (rawPath: string) => {\n const target = resolveTreePath(rawPath, treePaths)\n if (!target) return\n if (target.type === 'file') {\n guardedOpen(target.path)\n return\n }\n toggleFolder(target.path)\n }\n const handleTreeSelect = useCallback((path: string) => selectFileRef.current(path), [])\n\n const confirmDiscard = useCallback(() => {\n const nav = pendingNav\n setPendingNav(null)\n if (!nav) return\n if (nav.request && pendingOpenRef.current !== nav.request) return\n if (!commitPath(nav.path)) {\n finishPendingOpen(false)\n return\n }\n setIsDirty(false)\n showDocument()\n }, [pendingNav, commitPath, showDocument, finishPendingOpen])\n\n const showRichMode = useCallback(() => {\n setEditorMode((mode) => {\n if (mode === 'rich') return mode\n setRichDraft(activeCodec.parse(sourceDraft))\n setIsDirty(sourceDraft !== savedContentRef.current)\n return 'rich'\n })\n }, [activeCodec, sourceDraft])\n\n const showSourceMode = useCallback(() => {\n setEditorMode((mode) => {\n if (mode === 'source') return mode\n const content = isDirty ? activeCodec.serialize(richDraft) : savedContentRef.current\n setSourceDraft(content)\n setIsDirty(content !== savedContentRef.current)\n return 'source'\n })\n }, [activeCodec, isDirty, richDraft])\n\n const onSourceChange = useCallback((next: string) => {\n dirtyRef.current = next !== savedContentRef.current\n setSourceDraft(next)\n setIsDirty(dirtyRef.current)\n }, [])\n\n const onRichChange = useCallback((next: VaultRichParts) => {\n dirtyRef.current = activeCodec.serialize(next) !== savedContentRef.current\n setRichDraft(next)\n setIsDirty(dirtyRef.current)\n }, [activeCodec])\n\n const saveCurrent = useCallback(async () => {\n if (!selectedFile) return\n const content = editorMode === 'source' ? sourceDraft : activeCodec.serialize(richDraft)\n setSaving(true)\n setSaveError(null)\n try {\n await port.writeFile(selectedFile.path, content)\n savedContentRef.current = content\n setSelectedFile({ ...selectedFile, content })\n setSourceDraft(content)\n setRichDraft(activeCodec.parse(content))\n setIsDirty(false)\n } catch (error) {\n setSaveError(reportFailure('save', 'operation', error, 'Failed to save file', selectedFile.path))\n } finally {\n setSaving(false)\n }\n }, [selectedFile, editorMode, sourceDraft, richDraft, activeCodec, port, reportFailure])\n\n const handleCreate = useCallback(async () => {\n const trimmed = newPath.trim()\n // Same rule as the confirm button, enforced here too: the dialog can also be\n // confirmed by keyboard, and a directory path is not a file to create.\n if (!trimmed || !(trimmed.split('/').pop()?.trim())) return\n setCreating(true)\n setCreateError(null)\n try {\n const created = await port.createFile(trimmed)\n setCreateOpen(false)\n setNewPath('')\n const refreshed = await refresh({\n operation: 'create',\n phase: 'post-mutation-refresh',\n path: created,\n selectAfterRecovery: created,\n })\n if (refreshed) commitPath(created)\n } catch (error) {\n setCreateError(reportFailure('create', 'operation', error, 'Failed to create file', trimmed))\n } finally {\n setCreating(false)\n }\n }, [newPath, port, refresh, commitPath, reportFailure])\n\n const handleDelete = useCallback(async () => {\n if (!selectedFile) return\n const path = selectedFile.path\n setDeleting(true)\n setDeleteError(null)\n try {\n await port.deleteFile(path)\n setDeleteOpen(false)\n setIsDirty(false)\n commitPath(null)\n setSelectedFile(null)\n await refresh({ operation: 'delete', phase: 'post-mutation-refresh', path })\n } catch (error) {\n setDeleteError(reportFailure('delete', 'operation', error, 'Failed to delete file', path))\n } finally {\n setDeleting(false)\n }\n }, [selectedFile, port, refresh, commitPath, reportFailure])\n\n // History belongs to the open file; another file starts with the document.\n const historyPath = selectedFile?.path ?? null\n useEffect(() => { setHistoryOpen(false) }, [historyPath])\n const canShowHistory = typeof port.listRevisions === 'function' && typeof port.readRevision === 'function'\n const listRevisions = useCallback((path: string) => port.listRevisions!(path), [port])\n const readRevision = useCallback((path: string, id: string) => port.readRevision!(path, id), [port])\n const restoreRevision = useCallback(async (content: string) => {\n if (!selectedFile) return\n await port.writeFile(selectedFile.path, content)\n setHistoryOpen(false)\n // Re-read, so the pane holds the server's copy and its new revision.\n setReloadNonce((n) => n + 1)\n }, [port, selectedFile])\n\n // A file counts as opened once it is on screen, not when it is requested.\n // It is recorded in the commit that first shows it: `displayReadyPath` trails\n // that commit by one render, so a pane closed right after showing a file\n // (or a reader who navigates away at once) lost the record.\n const shownPath = selectedFile?.path ?? null\n useEffect(() => {\n if (!shownPath || !treeStateKey) return\n setRecentFiles({ key: treeStateKey, paths: recordRecentFile(treeStateKey, shownPath) })\n }, [shownPath, treeStateKey])\n const recentToOffer = recentFiles.paths\n .filter((path) => path !== selectedPath && treePaths.files.has(path))\n .slice(0, RECENT_SHOWN)\n\n const createFileName = newPath.trim().split('/').pop()?.trim() ?? ''\n const dockButtonLabel = persistentDock ? dockLabel : dockToggleCfg.label\n const dockBlockedByDraft = !persistentDock && (dockToggleCfg.disabledWhenDirty ?? true) && isDirty\n const openCreate = () => { setCreateError(null); setNewPath(activeFolder ? `${activeFolder}/` : ''); setCreateOpen(true) }\n // Loading, empty and filled vaults share one geometry (tree column, search,\n // document pane), so the pane never jumps when the first listing answers: an\n // empty-vault layout measured CLS 0.38 on Hospitality's Files page.\n const vaultEmpty = treeLoaded && treePaths.files.size === 0 && treePaths.directories.size === 0\n const trimmedQuery = query.trim()\n const nameMatches = (visibleRoot.children?.length ?? 0) > 0\n\n let treeContent: ReactNode\n if (!treeLoaded && (treeLoading || !treeError)) {\n treeContent = <TreeSkeleton />\n } else if (!treeLoaded && treeError) {\n treeContent = <TreeErrorState label={label} message={treeFailureMessage(treeError.failure, label)} onRetry={() => void retryTree()} />\n } else {\n treeContent = (\n <>\n {treeError && (\n <OperationErrorAlert\n message={treeFailureMessage(treeError.failure, label)}\n retryLabel={`Retry ${noun} refresh`}\n onRetry={() => void retryTree()}\n onDismiss={() => setTreeError(null)}\n />\n )}\n {vaultEmpty && !trimmedQuery\n ? (treeEmptyState !== undefined ? treeEmptyState : <TreeEmptyState canCreate={canCreate} onCreate={openCreate} />)\n : trimmedQuery && !nameMatches && (contentResults.status === 'idle' || (contentResults.status === 'done' && contentResults.matches.length === 0))\n ? <TreeNoMatchState query={trimmedQuery} onClear={() => setQuery('')} />\n : trimmedQuery && !nameMatches\n ? null\n : renderTree\n ? renderTree({\n root: visibleRoot,\n selectedPath: resolvedSelectedPath ?? undefined,\n onSelect: handleTreeSelect,\n })\n : (\n <VaultTree\n root={visibleRoot}\n selectedPath={resolvedSelectedPath ?? undefined}\n activeFolder={activeFolder}\n onSelect={handleTreeSelect}\n onFolderToggle={handleFolderToggle}\n storageKey={treeStateKey}\n expandAll={!!trimmedQuery}\n label={label}\n />\n )}\n {trimmedQuery && contentResults.status !== 'idle' && (\n <VaultContentResults\n state={contentResults}\n selectedPath={resolvedSelectedPath}\n onOpen={(path) => guardedOpen(path)}\n onRetry={() => setContentSearchNonce((n) => n + 1)}\n />\n )}\n </>\n )\n }\n\n return (\n <EditorErrorBoundary label={label} onReset={() => { commitPath(null); setSelectedFile(null) }}>\n <div ref={rootRef} className={`flex min-h-0 min-w-0 flex-1 overflow-hidden ${className ?? ''}`}>\n <div className=\"@container/vault flex min-w-0 flex-1 flex-col\">\n {/* The pane switcher exists only while there is a document to switch\n to; with nothing selected the Files pane is already all there is,\n and a lone Files chip would be a control that does nothing. */}\n {selectedPath && (\n <nav aria-label={`${label} navigation`} className=\"flex shrink-0 items-center gap-1 border-b border-border p-2 @[60rem]/vault:hidden\">\n <button\n type=\"button\"\n aria-pressed={showFiles}\n onClick={() => {\n const focused = document.activeElement\n setFilesOpen(true)\n requestAnimationFrame(() => {\n if (document.activeElement === focused || document.activeElement === document.body) {\n searchRef.current?.focus()\n }\n })\n }}\n className={`shrink-0 rounded-md px-3 py-2 text-sm ${showFiles ? 'bg-muted font-medium text-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n Files\n </button>\n {selectedPath && (\n <button\n type=\"button\"\n aria-pressed={!showFiles}\n onClick={showDocument}\n title={selectedPath}\n className={`min-w-0 truncate rounded-md px-3 py-2 text-sm ${!showFiles ? 'bg-muted font-medium text-foreground' : 'text-muted-foreground hover:bg-muted'}`}\n >\n {selectedPath.split('/').pop()}\n </button>\n )}\n </nav>\n )}\n <div className=\"flex min-h-0 min-w-0 flex-1\">\n <div data-vault-tree className={`${showFiles ? 'flex' : 'hidden'} min-w-0 flex-1 flex-col p-2 @[60rem]/vault:flex @[60rem]/vault:p-3 @[60rem]/vault:w-[23rem] @[60rem]/vault:min-w-[23rem] @[60rem]/vault:flex-none`}>\n {/* The tree is its own surface: a card on the page background,\n so the file list reads as a finished panel rather than\n text floating on the canvas. */}\n <section\n aria-labelledby={treeHeadingId}\n data-vault-tree-surface\n data-slot=\"card\"\n className=\"flex min-h-0 flex-1 flex-col overflow-hidden rounded-xl border border-border bg-card text-card-foreground shadow-raised\"\n >\n <div className=\"flex shrink-0 items-center gap-2 px-3 pb-2 pt-3\">\n <h2 id={treeHeadingId} className=\"min-w-0 flex-1 truncate text-sm font-semibold text-foreground\">\n {label}\n </h2>\n <div className=\"flex shrink-0 items-center gap-1\">\n {headerActions}\n <button\n type=\"button\"\n aria-label={`Refresh ${noun}`}\n title=\"Refresh\"\n onClick={() => void refresh()}\n className={`${TREE_ICON_BUTTON} text-muted-foreground hover:bg-muted hover:text-foreground`}\n >\n <RefreshCw className=\"size-4\" aria-hidden=\"true\" />\n </button>\n {canCreate && (\n <button\n type=\"button\"\n title=\"New file\"\n aria-label={activeFolder ? `New file in ${activeFolder}` : 'New file'}\n onClick={openCreate}\n className={`${TREE_ICON_BUTTON} bg-primary text-primary-foreground hover:bg-primary/90`}\n >\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n </button>\n )}\n </div>\n </div>\n <div className=\"shrink-0 px-3 pb-2\">\n <input\n ref={searchRef}\n type=\"search\"\n disabled={vaultEmpty}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={canSearchContent ? `Search ${noun} names and text…` : `Search ${noun}…`}\n aria-label={`Search ${noun}`}\n className=\"h-8 w-full rounded-md border border-[var(--field-border,var(--color-border))] bg-[var(--well,var(--color-input))] px-3 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring [@media(pointer:coarse)]:h-10 [@media(pointer:coarse)]:text-base\"\n />\n </div>\n {activeFolder && canCreate && (\n <div className=\"mx-3 mb-2 flex shrink-0 items-center gap-1.5 rounded-md bg-muted px-2 py-1 text-sm\">\n <Folder className=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <span className=\"shrink-0 text-muted-foreground\">New files go in</span>\n <span data-vault-folder className=\"min-w-0 flex-1 truncate font-medium text-foreground\" title={activeFolder}>\n {activeFolder}\n </span>\n <button\n type=\"button\"\n aria-label=\"Clear the active folder\"\n onClick={() => setFolderPath(null)}\n className=\"shrink-0 rounded px-1 text-muted-foreground underline-offset-2 transition-colors hover:text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n Clear\n </button>\n </div>\n )}\n <div className=\"min-h-0 flex-1 overflow-y-auto border-t border-border px-1.5 py-1.5\">\n {treeContent}\n </div>\n </section>\n </div>\n\n <div\n ref={documentRef}\n role=\"region\"\n aria-label={`${label} document`}\n tabIndex={-1}\n className={`${showFiles ? 'hidden' : 'flex'} min-w-0 flex-1 flex-col overflow-hidden @[60rem]/vault:flex`}\n >\n {selectedFile && (\n <ShellHeader className={`justify-between gap-2 px-4 ${pathBarClassName ?? 'bg-card'}`}>\n <span data-vault-path className=\"min-w-0 flex-1 truncate text-sm font-medium text-foreground\">{selectedFile.path}</span>\n <div className=\"flex shrink-0 items-center gap-1\">\n {canWrite && isMarkdownCapable && (\n <div className=\"mr-1 flex items-center gap-1\">\n <button\n type=\"button\"\n aria-label=\"Edit as rich text\"\n aria-pressed={editorMode === 'rich'}\n onClick={showRichMode}\n className={`inline-flex h-8 items-center rounded px-2.5 text-sm transition-colors ${\n editorMode === 'rich'\n ? 'bg-primary text-primary-foreground'\n : 'text-muted-foreground hover:bg-muted hover:text-foreground'\n }`}\n >\n Rich\n </button>\n <button\n type=\"button\"\n aria-label=\"Edit as source\"\n aria-pressed={editorMode === 'source'}\n onClick={showSourceMode}\n className={`inline-flex h-8 items-center rounded px-2.5 text-sm transition-colors ${\n editorMode === 'source'\n ? 'bg-primary text-primary-foreground'\n : 'text-muted-foreground hover:bg-muted hover:text-foreground'\n }`}\n >\n Source\n </button>\n </div>\n )}\n {canShowHistory && (\n <button\n type=\"button\"\n aria-pressed={historyOpen}\n disabled={isDirty && !historyOpen}\n title={isDirty && !historyOpen ? 'Save or discard your edits first' : 'Saved versions of this file'}\n onClick={() => setHistoryOpen((open) => !open)}\n className={`inline-flex h-8 items-center gap-1.5 rounded px-2.5 text-sm transition-colors disabled:pointer-events-none disabled:opacity-40 ${\n historyOpen\n ? 'bg-primary text-primary-foreground'\n : 'text-muted-foreground hover:bg-muted hover:text-foreground'\n }`}\n >\n <History className=\"size-4\" aria-hidden=\"true\" />\n History\n </button>\n )}\n {renderDock && (!persistentDock || dockInline) && (\n <button\n type=\"button\"\n aria-label={dockButtonLabel}\n aria-pressed={dockOpen}\n disabled={dockBlockedByDraft}\n title={dockBlockedByDraft ? 'Save your changes first' : (persistentDock ? dockLabel : (dockToggleCfg.title ?? dockToggleCfg.label))}\n onClick={() => setDockOpen((v) => !v)}\n className={`inline-flex h-8 items-center gap-1 rounded px-2.5 text-sm transition-colors disabled:pointer-events-none disabled:opacity-40 ${\n dockOpen\n ? 'bg-primary text-primary-foreground'\n : 'text-muted-foreground hover:bg-muted hover:text-foreground'\n }`}\n >\n {dockButtonLabel}\n </button>\n )}\n {fileActions?.(selectedFile)}\n {onDownloadFile && (\n <button\n type=\"button\"\n aria-label=\"Download this file\"\n title=\"Download file\"\n onClick={() => onDownloadFile(selectedFile)}\n className=\"inline-flex h-7 w-7 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <Download className=\"h-4 w-4\" />\n </button>\n )}\n {canDelete && (\n <button\n type=\"button\"\n aria-label=\"Delete this file\"\n title=\"Delete file\"\n onClick={() => { setDeleteError(null); setDeleteOpen(true) }}\n className=\"inline-flex h-7 w-7 items-center justify-center rounded text-[var(--surface-danger-text)] transition-colors hover:bg-destructive/10\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </ShellHeader>\n )}\n {selectedFile && saveError && (\n <OperationErrorAlert\n message={saveError.message}\n retryLabel=\"Retry save\"\n onRetry={() => void saveCurrent()}\n onDismiss={() => setSaveError(null)}\n />\n )}\n {readError && selectedFile?.path === resolvedSelectedPath && (\n <OperationErrorAlert\n message={readError}\n retryLabel=\"Retry file refresh\"\n onRetry={() => setReloadNonce((n) => n + 1)}\n onDismiss={() => setReadError(null)}\n />\n )}\n <div className=\"flex-1 overflow-hidden\">\n {fileLoading && selectedFile?.path !== resolvedSelectedPath ? (\n <EditorSkeleton />\n ) : readError && selectedFile?.path !== resolvedSelectedPath ? (\n <ReadErrorState message={readError} onRetry={() => setReloadNonce((n) => n + 1)} />\n ) : selectedFile && historyOpen && canShowHistory ? (\n <VaultHistoryPanel\n path={selectedFile.path}\n listRevisions={listRevisions}\n readRevision={readRevision}\n canRestore={canWrite}\n renderPreview={(content, revision) => renderArtifact({\n file: { ...selectedFile, content },\n loading: false,\n mode: 'rich',\n canWrite: false,\n richDraft: activeCodec.parse(content),\n dirty: false,\n onRichChange: () => {},\n onSave: () => {},\n saving: false,\n revision,\n })}\n onRestore={restoreRevision}\n onClose={() => setHistoryOpen(false)}\n />\n ) : selectedFile && renderDock && dockInline && dockOpen ? (\n <div data-vault-dock=\"inline\" className=\"flex h-full min-h-0 flex-col overflow-y-auto\">\n {renderDock({ file: selectedFile, open: true, onClose: () => setDockOpen(false), placement: 'inline' })}\n </div>\n ) : selectedFile && canWrite && isMarkdownCapable && editorMode === 'source' ? (\n <SourceEditor\n path={selectedFile.path}\n content={sourceDraft}\n saving={saving}\n dirty={isDirty}\n onChange={onSourceChange}\n onSave={() => void saveCurrent()}\n />\n ) : selectedFile ? (\n renderArtifact({\n file: selectedFile,\n loading: false,\n mode: editorMode,\n canWrite,\n richDraft,\n dirty: isDirty,\n onRichChange,\n onSave: () => void saveCurrent(),\n saving,\n })\n ) : emptyState !== undefined ? emptyState : (\n <DocumentEmptyState label={label} recent={recentToOffer} onOpen={(path) => guardedOpen(path)} />\n )}\n </div>\n </div>\n </div>\n </div>\n\n {renderDock && selectedFile && !dockInline && renderDock({\n file: selectedFile,\n open: persistentDock ? true : dockOpen,\n onClose: persistentDock ? () => {} : () => setDockOpen(false),\n placement: 'side',\n })}\n\n <ConfirmDialog\n open={createOpen}\n title=\"Create file\"\n description={activeFolder ? `Add a new document to ${activeFolder}.` : `Add a new document to ${label}.`}\n confirmLabel={creating ? 'Creating…' : 'Create'}\n // A prefilled folder is a path with no file name yet, so emptiness is\n // not the test — `folder/` would otherwise be sent to the port as a\n // file to create.\n confirmDisabled={creating || !createFileName}\n onConfirm={() => void handleCreate()}\n onCancel={() => { setCreateOpen(false); setNewPath(''); setCreateError(null) }}\n >\n <div className=\"space-y-2\">\n <input\n value={newPath}\n autoFocus\n onChange={(e) => setNewPath(e.target.value)}\n placeholder=\"e.g. playbooks/new-strategy.md\"\n aria-label=\"New file path\"\n className=\"h-9 w-full rounded-md border border-border bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground\"\n />\n {createError && <p role=\"alert\" className=\"text-xs text-[var(--surface-danger-text)]\">{createError.message}</p>}\n </div>\n </ConfirmDialog>\n\n <ConfirmDialog\n open={deleteOpen}\n title=\"Delete file?\"\n description={`This permanently removes ${selectedFile?.path ?? 'this file'} from ${label}.`}\n confirmLabel={deleting ? 'Deleting…' : 'Delete file'}\n confirmDisabled={deleting}\n destructive\n onConfirm={() => void handleDelete()}\n onCancel={() => { setDeleteOpen(false); setDeleteError(null) }}\n >\n {deleteError && <p role=\"alert\" className=\"text-xs text-[var(--surface-danger-text)]\">{deleteError.message}</p>}\n </ConfirmDialog>\n\n <ConfirmDialog\n open={pendingNav !== null}\n title=\"Discard unsaved changes?\"\n description=\"Your edits to this document haven't been saved. Continue and lose them?\"\n confirmLabel=\"Discard changes\"\n destructive\n onConfirm={confirmDiscard}\n onCancel={() => { finishPendingOpen(false); setPendingNav(null) }}\n />\n </div>\n </EditorErrorBoundary>\n )\n})\n\nfunction SourceEditor({\n path,\n content,\n saving,\n dirty,\n onChange,\n onSave,\n}: {\n path: string\n content: string\n saving: boolean\n dirty: boolean\n onChange: (content: string) => void\n onSave: () => void\n}) {\n return (\n <div className=\"flex h-full min-h-0 flex-col bg-background\">\n <div className=\"flex items-center justify-between gap-2 border-b border-border px-4 py-2\">\n <p className=\"truncate font-mono text-sm text-muted-foreground\">{path}</p>\n {/* One save state, as in the rich editor: Save exists only while there is something to save. */}\n <div className=\"flex shrink-0 items-center gap-2\">\n <span\n role=\"status\"\n aria-live=\"polite\"\n className={`rounded-full border px-2.5 py-1 text-sm ${\n dirty\n ? 'border-[var(--surface-warning-border)] bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)]'\n : 'border-border bg-background text-muted-foreground'\n }`}\n >\n {saving ? 'Saving…' : dirty ? 'Unsaved changes' : 'Saved'}\n </span>\n {(dirty || saving) && (\n <button\n type=\"button\"\n onClick={onSave}\n disabled={saving}\n title=\"Save (Ctrl+S)\"\n className=\"inline-flex h-8 items-center rounded-md bg-primary px-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50\"\n >\n Save\n </button>\n )}\n </div>\n </div>\n <textarea\n value={content}\n onChange={(event) => onChange(event.target.value)}\n onKeyDown={(event) => {\n if ((event.metaKey || event.ctrlKey) && !event.altKey && !event.shiftKey && event.key.toLowerCase() === 's') {\n event.preventDefault()\n if (dirty && !saving) onSave()\n }\n }}\n spellCheck={false}\n aria-label=\"Source editor\"\n // Full-bleed editor: keep the floor's ring but draw it inside the border\n // box, since an outward ring on a `flex-1` pane child is clipped.\n className=\"min-h-0 flex-1 resize-none border-0 bg-background p-4 font-mono text-sm leading-6 text-foreground focus-visible:[outline-offset:-2px]\"\n />\n </div>\n )\n}\n","/**\n * Self-contained confirm dialog — no dialog library. A focus-trapped modal with\n * Escape-to-cancel and Enter from text inputs, used for create / delete / discard-unsaved\n * flows so the pane carries zero UI-kit dependency.\n */\n\nimport { useEffect, useRef, type ReactNode } from 'react'\n\nexport interface ConfirmDialogProps {\n open: boolean\n title: string\n description?: ReactNode\n confirmLabel?: string\n cancelLabel?: string\n /** Styles the confirm button as a destructive action. */\n destructive?: boolean\n /** Disables the confirm button (e.g. while the action is in flight). */\n confirmDisabled?: boolean\n onConfirm: () => void\n onCancel: () => void\n /** Optional body (e.g. an input field for the create flow). */\n children?: ReactNode\n}\n\nexport function ConfirmDialog({\n open,\n title,\n description,\n confirmLabel = 'Confirm',\n cancelLabel = 'Cancel',\n destructive = false,\n confirmDisabled = false,\n onConfirm,\n onCancel,\n children,\n}: ConfirmDialogProps) {\n const panelRef = useRef<HTMLDivElement>(null)\n const confirmRef = useRef<HTMLButtonElement>(null)\n\n useEffect(() => {\n if (!open) return\n confirmRef.current?.focus()\n }, [open])\n\n if (!open) return null\n\n function onKeyDown(event: React.KeyboardEvent) {\n if (event.key === 'Escape') {\n event.preventDefault()\n onCancel()\n return\n }\n const target = event.target\n if (\n event.key === 'Enter'\n && !event.defaultPrevented\n && !event.nativeEvent.isComposing\n && !confirmDisabled\n && target instanceof HTMLInputElement\n && ['text', 'search', 'email', 'url', 'tel', 'password', 'number'].includes(target.type)\n ) {\n event.preventDefault()\n onConfirm()\n return\n }\n if (event.key !== 'Tab') return\n const focusable = panelRef.current?.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n )\n if (!focusable || focusable.length === 0) return\n const first = focusable[0]\n const last = focusable[focusable.length - 1]\n const active = document.activeElement as HTMLElement | null\n if (event.shiftKey && active === first) {\n event.preventDefault()\n last?.focus()\n } else if (!event.shiftKey && active === last) {\n event.preventDefault()\n first?.focus()\n }\n }\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\"\n onMouseDown={(e) => { if (e.target === e.currentTarget) onCancel() }}\n >\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n onKeyDown={onKeyDown}\n className=\"w-full max-w-md rounded-lg border border-border bg-card p-5 shadow-lg\"\n >\n <h2 className=\"text-sm font-semibold text-foreground\">{title}</h2>\n {description && <p className=\"mt-1.5 text-xs text-muted-foreground\">{description}</p>}\n {children && <div className=\"mt-3\">{children}</div>}\n <div className=\"mt-5 flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"inline-flex h-8 items-center rounded-md px-3 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n {cancelLabel}\n </button>\n <button\n ref={confirmRef}\n type=\"button\"\n onClick={onConfirm}\n disabled={confirmDisabled}\n className={`inline-flex h-8 items-center rounded-md px-3 text-xs font-medium transition-colors disabled:pointer-events-none disabled:opacity-50 ${\n destructive\n ? 'bg-destructive text-destructive-foreground hover:bg-destructive/90'\n : 'bg-primary text-primary-foreground hover:bg-primary/90'\n }`}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>\n )\n}\n","/**\n * The files a reader opened most recently in this browser, per vault scope\n * (`treeStateKey`). Storage can be blocked or full; every access degrades to\n * an empty list rather than failing the pane.\n */\n\nconst PREFIX = 'tangle:vault-recent:'\n/** How many paths are kept; the empty state shows a few of them. */\nconst RECENT_FILE_LIMIT = 8\n\nfunction storage(key: string | undefined): Storage | null {\n if (!key || typeof window === 'undefined') return null\n try {\n return window.localStorage\n } catch {\n return null\n }\n}\n\nexport function readRecentFiles(key: string | undefined): string[] {\n const store = storage(key)\n if (!store) return []\n try {\n const parsed: unknown = JSON.parse(store.getItem(PREFIX + key) ?? '[]')\n return Array.isArray(parsed) ? parsed.filter((item): item is string => typeof item === 'string') : []\n } catch {\n return []\n }\n}\n\n/** Moves `path` to the front and returns the new list. */\nexport function recordRecentFile(key: string | undefined, path: string): string[] {\n const next = [path, ...readRecentFiles(key).filter((item) => item !== path)].slice(0, RECENT_FILE_LIMIT)\n const store = storage(key)\n if (store) {\n try {\n store.setItem(PREFIX + key, JSON.stringify(next))\n } catch {\n // Full or blocked storage: the list lives for this render only.\n }\n }\n return next\n}\n","/**\n * Words found inside files, listed under the vault's name matches. Each row\n * names the file, its folder, and an excerpt with the query marked, and opens\n * the file through the pane's dirty-guarded navigation.\n */\n\nimport { useId, type ReactNode } from 'react'\nimport { FileText } from 'lucide-react'\nimport type { VaultContentMatch } from './contracts'\n\nexport type ContentSearchState =\n | { status: 'idle' }\n | { status: 'loading'; query: string; matches: VaultContentMatch[] }\n | { status: 'done'; query: string; matches: VaultContentMatch[] }\n | { status: 'error'; query: string; message: string }\n\n/** Splits `text` so every case-insensitive occurrence of `query` is marked. */\nfunction highlight(text: string, query: string): ReactNode[] {\n const needle = query.toLowerCase()\n const haystack = text.toLowerCase()\n const parts: ReactNode[] = []\n let from = 0\n for (let at = haystack.indexOf(needle); needle && at >= 0; at = haystack.indexOf(needle, from)) {\n if (at > from) parts.push(text.slice(from, at))\n parts.push(\n <mark key={at} className=\"rounded-sm bg-[var(--surface-warning-bg)] px-0.5 text-[var(--surface-warning-text)]\">\n {text.slice(at, at + needle.length)}\n </mark>,\n )\n from = at + needle.length\n }\n if (from < text.length) parts.push(text.slice(from))\n return parts\n}\n\nexport function VaultContentResults({\n state,\n selectedPath,\n onOpen,\n onRetry,\n}: {\n state: Exclude<ContentSearchState, { status: 'idle' }>\n selectedPath: string | null\n onOpen: (path: string) => void\n onRetry: () => void\n}) {\n const headingId = useId()\n return (\n <section aria-labelledby={headingId} data-vault-content-results className=\"mt-2 border-t border-border px-1.5 pt-3\">\n <h3 id={headingId} className=\"px-1.5 text-sm font-medium text-foreground\">\n In file contents\n </h3>\n {state.status === 'error' ? (\n <div role=\"alert\" className=\"mt-2 space-y-2 px-1.5 text-sm text-[var(--surface-danger-text)]\">\n <p>Couldn't search file contents. {state.message}</p>\n <button type=\"button\" onClick={onRetry} className=\"font-medium underline-offset-2 hover:underline\">\n Try again\n </button>\n </div>\n ) : state.matches.length === 0 ? (\n <p role=\"status\" className=\"mt-2 px-1.5 text-sm text-muted-foreground\">\n {state.status === 'loading' ? 'Searching file contents…' : `No file contains “${state.query}”.`}\n </p>\n ) : (\n <ul className=\"mt-1.5 space-y-0.5\" aria-busy={state.status === 'loading'}>\n {state.matches.map((match) => {\n const slash = match.path.lastIndexOf('/')\n const selected = match.path === selectedPath\n return (\n <li key={match.path}>\n <button\n type=\"button\"\n onClick={() => onOpen(match.path)}\n title={match.path}\n aria-current={selected ? 'true' : undefined}\n className={`w-full rounded-md px-2 py-2 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring ${\n selected ? 'bg-muted' : 'hover:bg-muted'\n }`}\n >\n <span className=\"flex min-w-0 items-center gap-2\">\n <FileText className=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <span className=\"min-w-0 truncate text-sm font-medium text-foreground\">{match.path.slice(slash + 1)}</span>\n {slash > 0 && (\n <span className=\"ml-auto min-w-0 shrink truncate text-sm text-muted-foreground\">{match.path.slice(0, slash)}</span>\n )}\n </span>\n <span className=\"mt-1 line-clamp-2 block text-sm text-muted-foreground\">\n {highlight(match.snippet, state.query)}\n </span>\n </button>\n </li>\n )\n })}\n </ul>\n )}\n </section>\n )\n}\n","/**\n * A file's saved versions, newest first, with a read-only preview of the one\n * selected and a confirmed Restore. Restoring writes the old text as a new\n * version, so the version it replaces stays in the list.\n */\n\nimport { useCallback, useEffect, useId, useState, type ReactNode } from 'react'\nimport { History, X } from 'lucide-react'\nimport { ConfirmDialog } from './ConfirmDialog'\nimport type { VaultRevision } from './contracts'\n\ntype Load<T> = { status: 'loading' } | { status: 'ready'; value: T } | { status: 'error'; message: string }\n\nfunction message(error: unknown, fallback: string) {\n return error instanceof Error && error.message ? error.message : fallback\n}\n\nfunction savedAtLabel(savedAt: string) {\n const date = new Date(savedAt)\n if (Number.isNaN(date.getTime())) return savedAt\n return new Intl.DateTimeFormat(undefined, { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }).format(date)\n}\n\nexport interface VaultHistoryPanelProps {\n path: string\n listRevisions: (path: string) => Promise<VaultRevision[]>\n readRevision: (path: string, revisionId: string) => Promise<string>\n /** False hides Restore, for a reader who cannot write. */\n canRestore: boolean\n /** Renders a version's text read-only, the way the pane renders the file. */\n renderPreview: (content: string, revision: VaultRevision) => ReactNode\n /** Writes `content` as the file's newest version. */\n onRestore: (content: string) => Promise<void>\n onClose: () => void\n}\n\nexport function VaultHistoryPanel({\n path,\n listRevisions,\n readRevision,\n canRestore,\n renderPreview,\n onRestore,\n onClose,\n}: VaultHistoryPanelProps) {\n const listId = useId()\n const [revisions, setRevisions] = useState<Load<VaultRevision[]>>({ status: 'loading' })\n const [listNonce, setListNonce] = useState(0)\n const [selectedId, setSelectedId] = useState<string | null>(null)\n const [contents, setContents] = useState<Record<string, Load<string>>>({})\n const [confirming, setConfirming] = useState(false)\n const [restoring, setRestoring] = useState(false)\n const [restoreError, setRestoreError] = useState<string | null>(null)\n\n useEffect(() => {\n let cancelled = false\n setRevisions({ status: 'loading' })\n listRevisions(path).then(\n (value) => {\n if (cancelled) return\n setRevisions({ status: 'ready', value })\n setSelectedId((current) => current ?? value[0]?.id ?? null)\n },\n (error) => {\n if (!cancelled) setRevisions({ status: 'error', message: message(error, 'Could not list the saved versions.') })\n },\n )\n return () => { cancelled = true }\n }, [path, listRevisions, listNonce])\n\n const loadContent = useCallback((id: string) => {\n setContents((current) => ({ ...current, [id]: { status: 'loading' } }))\n readRevision(path, id).then(\n (value) => setContents((current) => ({ ...current, [id]: { status: 'ready', value } })),\n (error) => setContents((current) => ({\n ...current,\n [id]: { status: 'error', message: message(error, 'Could not read this version.') },\n })),\n )\n }, [path, readRevision])\n\n useEffect(() => {\n if (selectedId && !contents[selectedId]) loadContent(selectedId)\n }, [selectedId, contents, loadContent])\n\n const list = revisions.status === 'ready' ? revisions.value : []\n const selected = list.find((revision) => revision.id === selectedId) ?? null\n const content = selectedId ? contents[selectedId] : undefined\n const restorable = canRestore && selected !== null && !selected.current && content?.status === 'ready'\n\n const restore = async () => {\n if (content?.status !== 'ready') return\n setRestoring(true)\n setRestoreError(null)\n try {\n await onRestore(content.value)\n setConfirming(false)\n } catch (error) {\n setRestoreError(message(error, 'Could not restore this version.'))\n setConfirming(false)\n } finally {\n setRestoring(false)\n }\n }\n\n return (\n <div data-vault-history className=\"flex h-full min-h-0 flex-col @[60rem]/vault:flex-row\">\n <nav\n aria-labelledby={listId}\n className=\"flex max-h-56 shrink-0 flex-col border-b border-border @[60rem]/vault:max-h-none @[60rem]/vault:w-64 @[60rem]/vault:border-b-0 @[60rem]/vault:border-r\"\n >\n <h3 id={listId} className=\"flex items-center gap-2 px-4 pb-2 pt-3 text-sm font-semibold text-foreground\">\n <History className=\"size-4 text-muted-foreground\" aria-hidden=\"true\" />\n Saved versions\n </h3>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-2 pb-2\">\n {revisions.status === 'loading' && <p role=\"status\" className=\"px-2 py-1 text-sm text-muted-foreground\">Loading versions…</p>}\n {revisions.status === 'error' && (\n <div role=\"alert\" className=\"space-y-2 px-2 py-1 text-sm text-[var(--surface-danger-text)]\">\n <p>{revisions.message}</p>\n <button type=\"button\" onClick={() => setListNonce((n) => n + 1)} className=\"font-medium underline-offset-2 hover:underline\">\n Try again\n </button>\n </div>\n )}\n {revisions.status === 'ready' && list.length === 0 && (\n <p className=\"px-2 py-1 text-sm text-muted-foreground\">No earlier versions are saved for this file.</p>\n )}\n <ul className=\"space-y-0.5\">\n {list.map((revision) => (\n <li key={revision.id}>\n <button\n type=\"button\"\n onClick={() => setSelectedId(revision.id)}\n aria-pressed={revision.id === selectedId}\n className={`w-full rounded-md px-2 py-2 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring ${\n revision.id === selectedId ? 'bg-muted' : 'hover:bg-muted'\n }`}\n >\n <span className=\"flex items-center gap-2 text-sm font-medium text-foreground\">\n {savedAtLabel(revision.savedAt)}\n {revision.current && (\n <span className=\"rounded-full border border-border px-2 text-sm font-normal text-muted-foreground\">Current</span>\n )}\n </span>\n {revision.author && <span className=\"mt-0.5 block text-sm text-muted-foreground\">{revision.author}</span>}\n </button>\n </li>\n ))}\n </ul>\n </div>\n </nav>\n\n <div className=\"flex min-h-0 min-w-0 flex-1 flex-col\">\n <div className=\"flex flex-wrap items-center justify-between gap-2 border-b border-border px-4 py-2\">\n <p className=\"min-w-0 text-sm text-muted-foreground\">\n {selected\n ? selected.current\n ? 'This is the version the file holds now.'\n : `Saved ${savedAtLabel(selected.savedAt)}${selected.author ? ` by ${selected.author}` : ''}. Read only.`\n : 'Choose a version to see it.'}\n </p>\n <div className=\"flex shrink-0 items-center gap-2\">\n {restorable && (\n <button\n type=\"button\"\n onClick={() => { setRestoreError(null); setConfirming(true) }}\n className=\"inline-flex h-8 items-center rounded-md bg-primary px-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90\"\n >\n Restore this version\n </button>\n )}\n <button\n type=\"button\"\n onClick={onClose}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-md border border-border px-3 text-sm text-foreground transition-colors hover:bg-muted\"\n >\n <X className=\"size-4\" aria-hidden=\"true\" />\n Close history\n </button>\n </div>\n </div>\n {restoreError && (\n <p role=\"alert\" className=\"border-b border-destructive/30 bg-destructive/10 px-4 py-2 text-sm text-[var(--surface-danger-text)]\">\n {restoreError}\n </p>\n )}\n <div className=\"min-h-0 flex-1 overflow-hidden\">\n {content?.status === 'ready' && selected ? (\n renderPreview(content.value, selected)\n ) : content?.status === 'error' ? (\n <div role=\"alert\" className=\"space-y-2 p-6 text-sm text-[var(--surface-danger-text)]\">\n <p>{content.message}</p>\n <button type=\"button\" onClick={() => selectedId && loadContent(selectedId)} className=\"font-medium underline-offset-2 hover:underline\">\n Try again\n </button>\n </div>\n ) : selectedId ? (\n <p role=\"status\" className=\"p-6 text-sm text-muted-foreground\">Loading this version…</p>\n ) : null}\n </div>\n </div>\n\n <ConfirmDialog\n open={confirming}\n title=\"Restore this version?\"\n description={`${path} goes back to the version saved ${selected ? savedAtLabel(selected.savedAt) : ''}. The version it holds now stays in this list.`}\n confirmLabel={restoring ? 'Restoring…' : 'Restore version'}\n confirmDisabled={restoring}\n onConfirm={() => void restore()}\n onCancel={() => setConfirming(false)}\n />\n </div>\n )\n}\n"],"mappings":"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","names":["useCallback","useEffect","useId","useRef","useState","FileText","History","jsx","jsxs","useEffect","useId","jsx","jsxs","useId","useEffect","jsx","jsxs","message","useId","FileText","VaultPane","useState","useRef","useEffect","useCallback","History"]}
|
|
File without changes
|