@tangle-network/agent-app 0.49.28 → 0.49.30
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-32HVWZ6A.js +7 -0
- package/dist/{chunk-ZNLASEO3.js → chunk-FCUWRMAF.js} +224 -157
- package/dist/chunk-FCUWRMAF.js.map +1 -0
- package/dist/vault/VaultPane.d.ts +5 -0
- package/dist/vault/index.js +1 -1
- package/dist/vault/lazy.js +1 -1
- package/package.json +1 -1
- package/dist/VaultPane-QZC3YKQG.js +0 -7
- package/dist/chunk-ZNLASEO3.js.map +0 -1
- /package/dist/{VaultPane-QZC3YKQG.js.map → VaultPane-32HVWZ6A.js.map} +0 -0
|
@@ -310,6 +310,22 @@ function VaultPane(props) {
|
|
|
310
310
|
const [treeError, setTreeError] = useState(null);
|
|
311
311
|
const [internalPath, setInternalPath] = useState(null);
|
|
312
312
|
const selectedPath = controlled ? controlledPath ?? null : internalPath;
|
|
313
|
+
const [filesOpen, setFilesOpen] = useState(false);
|
|
314
|
+
const showFiles = filesOpen || !selectedPath;
|
|
315
|
+
const searchRef = useRef2(null);
|
|
316
|
+
const documentRef = useRef2(null);
|
|
317
|
+
useEffect2(() => {
|
|
318
|
+
setFilesOpen(false);
|
|
319
|
+
}, [selectedPath]);
|
|
320
|
+
const showDocument = useCallback(() => {
|
|
321
|
+
const focused = document.activeElement;
|
|
322
|
+
setFilesOpen(false);
|
|
323
|
+
requestAnimationFrame(() => {
|
|
324
|
+
if (document.activeElement === focused || document.activeElement === document.body) {
|
|
325
|
+
documentRef.current?.focus({ preventScroll: true });
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}, []);
|
|
313
329
|
const [selectedFile, setSelectedFile] = useState(null);
|
|
314
330
|
const [fileLoading, setFileLoading] = useState(false);
|
|
315
331
|
const [readError, setReadError] = useState(null);
|
|
@@ -490,14 +506,18 @@ function VaultPane(props) {
|
|
|
490
506
|
}, [selectedFile?.path, selectedFile?.content, activeCodec]);
|
|
491
507
|
const guardedOpen = useCallback(
|
|
492
508
|
(path) => {
|
|
493
|
-
if (path === selectedPath)
|
|
509
|
+
if (path === selectedPath) {
|
|
510
|
+
showDocument();
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
494
513
|
if (isDirty) {
|
|
495
514
|
setPendingNav({ type: "open", path });
|
|
496
515
|
return;
|
|
497
516
|
}
|
|
517
|
+
showDocument();
|
|
498
518
|
commitPath(path);
|
|
499
519
|
},
|
|
500
|
-
[isDirty, selectedPath, commitPath]
|
|
520
|
+
[isDirty, selectedPath, commitPath, showDocument]
|
|
501
521
|
);
|
|
502
522
|
const toggleFolder = useCallback((path) => {
|
|
503
523
|
setFolderPath((current) => current === path ? null : path);
|
|
@@ -528,12 +548,13 @@ function VaultPane(props) {
|
|
|
528
548
|
setIsDirty(false);
|
|
529
549
|
if (!nav) return;
|
|
530
550
|
if (nav.type === "open") {
|
|
551
|
+
showDocument();
|
|
531
552
|
commitPath(nav.path);
|
|
532
553
|
} else {
|
|
533
554
|
commitPath(null);
|
|
534
555
|
setSelectedFile(null);
|
|
535
556
|
}
|
|
536
|
-
}, [pendingNav, commitPath]);
|
|
557
|
+
}, [pendingNav, commitPath, showDocument]);
|
|
537
558
|
const showRichMode = useCallback(() => {
|
|
538
559
|
setEditorMode((mode) => {
|
|
539
560
|
if (mode === "rich") return mode;
|
|
@@ -646,180 +667,226 @@ function VaultPane(props) {
|
|
|
646
667
|
return /* @__PURE__ */ jsx2(EditorErrorBoundary, { onReset: () => {
|
|
647
668
|
commitPath(null);
|
|
648
669
|
setSelectedFile(null);
|
|
649
|
-
}, children: /* @__PURE__ */ jsxs2("div", { className: `flex min-h-0 flex-1 overflow-hidden ${className ?? ""}`, children: [
|
|
650
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex
|
|
651
|
-
/* @__PURE__ */ jsxs2("
|
|
652
|
-
/* @__PURE__ */ jsx2(
|
|
653
|
-
"
|
|
670
|
+
}, children: /* @__PURE__ */ jsxs2("div", { className: `flex min-h-0 min-w-0 flex-1 overflow-hidden ${className ?? ""}`, children: [
|
|
671
|
+
/* @__PURE__ */ jsxs2("div", { className: "@container/vault flex min-w-0 flex-1 flex-col", children: [
|
|
672
|
+
/* @__PURE__ */ jsxs2("nav", { "aria-label": "Vault navigation", className: "flex shrink-0 items-center gap-1 border-b border-border p-2 @[45rem]/vault:hidden", children: [
|
|
673
|
+
/* @__PURE__ */ jsx2(
|
|
674
|
+
"button",
|
|
654
675
|
{
|
|
655
|
-
type: "
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
676
|
+
type: "button",
|
|
677
|
+
"aria-pressed": showFiles,
|
|
678
|
+
onClick: () => {
|
|
679
|
+
const focused = document.activeElement;
|
|
680
|
+
setFilesOpen(true);
|
|
681
|
+
requestAnimationFrame(() => {
|
|
682
|
+
if (document.activeElement === focused || document.activeElement === document.body) {
|
|
683
|
+
searchRef.current?.focus();
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
},
|
|
687
|
+
className: `shrink-0 rounded-md px-3 py-2 text-sm ${showFiles ? "bg-muted font-medium text-foreground" : "text-muted-foreground hover:bg-muted"}`,
|
|
688
|
+
children: "Files"
|
|
661
689
|
}
|
|
662
|
-
)
|
|
663
|
-
/* @__PURE__ */
|
|
664
|
-
headerActions,
|
|
665
|
-
/* @__PURE__ */ jsx2(
|
|
666
|
-
"button",
|
|
667
|
-
{
|
|
668
|
-
type: "button",
|
|
669
|
-
"aria-label": "Refresh vault",
|
|
670
|
-
onClick: () => void refresh(),
|
|
671
|
-
className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
672
|
-
children: "\u21BB"
|
|
673
|
-
}
|
|
674
|
-
),
|
|
675
|
-
canWrite && /* @__PURE__ */ jsx2(
|
|
676
|
-
"button",
|
|
677
|
-
{
|
|
678
|
-
type: "button",
|
|
679
|
-
"aria-label": activeFolder ? `New vault file in ${activeFolder}` : "New vault file",
|
|
680
|
-
onClick: () => {
|
|
681
|
-
setCreateError(null);
|
|
682
|
-
setNewPath(activeFolder ? `${activeFolder}/` : "");
|
|
683
|
-
setCreateOpen(true);
|
|
684
|
-
},
|
|
685
|
-
className: "inline-flex h-8 w-8 items-center justify-center rounded-md bg-primary text-primary-foreground transition-colors hover:bg-primary/90",
|
|
686
|
-
children: "+"
|
|
687
|
-
}
|
|
688
|
-
)
|
|
689
|
-
] })
|
|
690
|
-
] }),
|
|
691
|
-
activeFolder && /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1.5 border-b border-border bg-muted/40 px-4 py-1.5 text-xs", children: [
|
|
692
|
-
/* @__PURE__ */ jsx2(Folder, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
|
|
693
|
-
/* @__PURE__ */ jsx2("span", { "data-vault-folder": true, className: "min-w-0 flex-1 truncate font-medium text-foreground", title: activeFolder, children: activeFolder }),
|
|
694
|
-
/* @__PURE__ */ jsx2(
|
|
690
|
+
),
|
|
691
|
+
selectedPath && /* @__PURE__ */ jsx2(
|
|
695
692
|
"button",
|
|
696
693
|
{
|
|
697
694
|
type: "button",
|
|
698
|
-
"aria-
|
|
699
|
-
onClick:
|
|
700
|
-
|
|
701
|
-
|
|
695
|
+
"aria-pressed": !showFiles,
|
|
696
|
+
onClick: showDocument,
|
|
697
|
+
title: selectedPath,
|
|
698
|
+
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"}`,
|
|
699
|
+
children: selectedPath.split("/").pop()
|
|
702
700
|
}
|
|
703
701
|
)
|
|
704
702
|
] }),
|
|
705
|
-
/* @__PURE__ */
|
|
706
|
-
"div",
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
const target = treeClickTarget(event);
|
|
711
|
-
if (target) handleTreeSelect(target.path);
|
|
712
|
-
},
|
|
713
|
-
children: treeContent
|
|
714
|
-
}
|
|
715
|
-
)
|
|
716
|
-
] }),
|
|
717
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden", children: [
|
|
718
|
-
selectedFile && /* @__PURE__ */ jsxs2("div", { className: `flex shrink-0 items-center justify-between border-b border-border px-4 py-1.5 ${pathBarClassName ?? "bg-card"}`, children: [
|
|
719
|
-
/* @__PURE__ */ jsx2("span", { "data-vault-path": true, className: "truncate text-xs font-medium text-foreground", children: selectedFile.path }),
|
|
720
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1", children: [
|
|
721
|
-
canWrite && isMarkdownCapable && /* @__PURE__ */ jsxs2("div", { className: "mr-1 flex items-center gap-1", children: [
|
|
722
|
-
/* @__PURE__ */ jsx2(
|
|
723
|
-
"button",
|
|
703
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex min-h-0 min-w-0 flex-1", children: [
|
|
704
|
+
/* @__PURE__ */ jsxs2("div", { "data-vault-tree": true, className: `${showFiles ? "flex" : "hidden"} min-w-0 flex-1 flex-col border-r border-border bg-background @[45rem]/vault:flex @[45rem]/vault:w-[23rem] @[45rem]/vault:min-w-[23rem] @[45rem]/vault:flex-none`, children: [
|
|
705
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
|
|
706
|
+
/* @__PURE__ */ jsx2("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx2(
|
|
707
|
+
"input",
|
|
724
708
|
{
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
709
|
+
ref: searchRef,
|
|
710
|
+
type: "text",
|
|
711
|
+
value: query,
|
|
712
|
+
onChange: (e) => setQuery(e.target.value),
|
|
713
|
+
placeholder: activeFolder ? `Search ${activeFolder}\u2026` : "Search\u2026",
|
|
714
|
+
"aria-label": "Search vault",
|
|
715
|
+
className: "h-8 w-full rounded-md border border-border bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground"
|
|
731
716
|
}
|
|
732
|
-
),
|
|
717
|
+
) }),
|
|
718
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
719
|
+
headerActions,
|
|
720
|
+
/* @__PURE__ */ jsx2(
|
|
721
|
+
"button",
|
|
722
|
+
{
|
|
723
|
+
type: "button",
|
|
724
|
+
"aria-label": "Refresh vault",
|
|
725
|
+
onClick: () => void refresh(),
|
|
726
|
+
className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
727
|
+
children: "\u21BB"
|
|
728
|
+
}
|
|
729
|
+
),
|
|
730
|
+
canWrite && /* @__PURE__ */ jsx2(
|
|
731
|
+
"button",
|
|
732
|
+
{
|
|
733
|
+
type: "button",
|
|
734
|
+
"aria-label": activeFolder ? `New vault file in ${activeFolder}` : "New vault file",
|
|
735
|
+
onClick: () => {
|
|
736
|
+
setCreateError(null);
|
|
737
|
+
setNewPath(activeFolder ? `${activeFolder}/` : "");
|
|
738
|
+
setCreateOpen(true);
|
|
739
|
+
},
|
|
740
|
+
className: "inline-flex h-8 w-8 items-center justify-center rounded-md bg-primary text-primary-foreground transition-colors hover:bg-primary/90",
|
|
741
|
+
children: "+"
|
|
742
|
+
}
|
|
743
|
+
)
|
|
744
|
+
] })
|
|
745
|
+
] }),
|
|
746
|
+
activeFolder && /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1.5 border-b border-border bg-muted/40 px-4 py-1.5 text-xs", children: [
|
|
747
|
+
/* @__PURE__ */ jsx2(Folder, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
|
|
748
|
+
/* @__PURE__ */ jsx2("span", { "data-vault-folder": true, className: "min-w-0 flex-1 truncate font-medium text-foreground", title: activeFolder, children: activeFolder }),
|
|
733
749
|
/* @__PURE__ */ jsx2(
|
|
734
750
|
"button",
|
|
735
751
|
{
|
|
736
752
|
type: "button",
|
|
737
|
-
"aria-label": "
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
children: "Source"
|
|
753
|
+
"aria-label": "Clear the active folder",
|
|
754
|
+
onClick: () => setFolderPath(null),
|
|
755
|
+
className: "shrink-0 rounded px-1 text-muted-foreground underline-offset-2 transition-colors hover:text-foreground hover:underline",
|
|
756
|
+
children: "Clear"
|
|
742
757
|
}
|
|
743
758
|
)
|
|
744
759
|
] }),
|
|
745
|
-
|
|
746
|
-
"
|
|
747
|
-
{
|
|
748
|
-
type: "button",
|
|
749
|
-
"aria-label": dockToggleCfg.label,
|
|
750
|
-
"aria-pressed": dockOpen,
|
|
751
|
-
disabled: (dockToggleCfg.disabledWhenDirty ?? true) && isDirty,
|
|
752
|
-
title: (dockToggleCfg.disabledWhenDirty ?? true) && isDirty ? "Save your changes first" : dockToggleCfg.title ?? dockToggleCfg.label,
|
|
753
|
-
onClick: () => setDockOpen((v) => !v),
|
|
754
|
-
className: `inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs transition-colors disabled:pointer-events-none disabled:opacity-40 ${dockOpen ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"}`,
|
|
755
|
-
children: dockToggleCfg.label
|
|
756
|
-
}
|
|
757
|
-
),
|
|
758
|
-
onDownloadFile && /* @__PURE__ */ jsx2(
|
|
759
|
-
"button",
|
|
760
|
-
{
|
|
761
|
-
type: "button",
|
|
762
|
-
"aria-label": "Download this file",
|
|
763
|
-
title: "Download file",
|
|
764
|
-
onClick: () => onDownloadFile(selectedFile),
|
|
765
|
-
className: "inline-flex h-7 w-7 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
766
|
-
children: /* @__PURE__ */ jsx2(Download, { className: "h-4 w-4" })
|
|
767
|
-
}
|
|
768
|
-
),
|
|
769
|
-
canWrite && /* @__PURE__ */ jsx2(
|
|
770
|
-
"button",
|
|
760
|
+
/* @__PURE__ */ jsx2(
|
|
761
|
+
"div",
|
|
771
762
|
{
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
setDeleteError(null);
|
|
777
|
-
setDeleteOpen(true);
|
|
763
|
+
className: "flex-1 overflow-y-auto",
|
|
764
|
+
onClickCapture: (event) => {
|
|
765
|
+
const target = treeClickTarget(event);
|
|
766
|
+
if (target) handleTreeSelect(target.path);
|
|
778
767
|
},
|
|
779
|
-
|
|
780
|
-
children: /* @__PURE__ */ jsx2(Trash2, { className: "h-4 w-4" })
|
|
768
|
+
children: treeContent
|
|
781
769
|
}
|
|
782
770
|
)
|
|
783
|
-
] })
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
771
|
+
] }),
|
|
772
|
+
/* @__PURE__ */ jsxs2(
|
|
773
|
+
"div",
|
|
774
|
+
{
|
|
775
|
+
ref: documentRef,
|
|
776
|
+
role: "region",
|
|
777
|
+
"aria-label": "Vault document",
|
|
778
|
+
tabIndex: -1,
|
|
779
|
+
className: `${showFiles ? "hidden" : "flex"} min-w-0 flex-1 flex-col overflow-hidden @[45rem]/vault:flex`,
|
|
780
|
+
children: [
|
|
781
|
+
selectedFile && /* @__PURE__ */ jsxs2("div", { className: `flex shrink-0 items-center justify-between gap-2 border-b border-border px-4 py-1.5 ${pathBarClassName ?? "bg-card"}`, children: [
|
|
782
|
+
/* @__PURE__ */ jsx2("span", { "data-vault-path": true, className: "min-w-0 flex-1 truncate text-xs font-medium text-foreground", children: selectedFile.path }),
|
|
783
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
784
|
+
canWrite && isMarkdownCapable && /* @__PURE__ */ jsxs2("div", { className: "mr-1 flex items-center gap-1", children: [
|
|
785
|
+
/* @__PURE__ */ jsx2(
|
|
786
|
+
"button",
|
|
787
|
+
{
|
|
788
|
+
type: "button",
|
|
789
|
+
"aria-label": "Edit as rich text",
|
|
790
|
+
"aria-pressed": editorMode === "rich",
|
|
791
|
+
onClick: showRichMode,
|
|
792
|
+
className: `inline-flex h-7 items-center rounded px-2 text-xs transition-colors ${editorMode === "rich" ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"}`,
|
|
793
|
+
children: "Rich"
|
|
794
|
+
}
|
|
795
|
+
),
|
|
796
|
+
/* @__PURE__ */ jsx2(
|
|
797
|
+
"button",
|
|
798
|
+
{
|
|
799
|
+
type: "button",
|
|
800
|
+
"aria-label": "Edit as source",
|
|
801
|
+
"aria-pressed": editorMode === "source",
|
|
802
|
+
onClick: showSourceMode,
|
|
803
|
+
className: `inline-flex h-7 items-center rounded px-2 text-xs transition-colors ${editorMode === "source" ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"}`,
|
|
804
|
+
children: "Source"
|
|
805
|
+
}
|
|
806
|
+
)
|
|
807
|
+
] }),
|
|
808
|
+
renderDock && !persistentDock && /* @__PURE__ */ jsx2(
|
|
809
|
+
"button",
|
|
810
|
+
{
|
|
811
|
+
type: "button",
|
|
812
|
+
"aria-label": dockToggleCfg.label,
|
|
813
|
+
"aria-pressed": dockOpen,
|
|
814
|
+
disabled: (dockToggleCfg.disabledWhenDirty ?? true) && isDirty,
|
|
815
|
+
title: (dockToggleCfg.disabledWhenDirty ?? true) && isDirty ? "Save your changes first" : dockToggleCfg.title ?? dockToggleCfg.label,
|
|
816
|
+
onClick: () => setDockOpen((v) => !v),
|
|
817
|
+
className: `inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs transition-colors disabled:pointer-events-none disabled:opacity-40 ${dockOpen ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"}`,
|
|
818
|
+
children: dockToggleCfg.label
|
|
819
|
+
}
|
|
820
|
+
),
|
|
821
|
+
onDownloadFile && /* @__PURE__ */ jsx2(
|
|
822
|
+
"button",
|
|
823
|
+
{
|
|
824
|
+
type: "button",
|
|
825
|
+
"aria-label": "Download this file",
|
|
826
|
+
title: "Download file",
|
|
827
|
+
onClick: () => onDownloadFile(selectedFile),
|
|
828
|
+
className: "inline-flex h-7 w-7 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
829
|
+
children: /* @__PURE__ */ jsx2(Download, { className: "h-4 w-4" })
|
|
830
|
+
}
|
|
831
|
+
),
|
|
832
|
+
canWrite && /* @__PURE__ */ jsx2(
|
|
833
|
+
"button",
|
|
834
|
+
{
|
|
835
|
+
type: "button",
|
|
836
|
+
"aria-label": "Delete this file",
|
|
837
|
+
title: "Delete file",
|
|
838
|
+
onClick: () => {
|
|
839
|
+
setDeleteError(null);
|
|
840
|
+
setDeleteOpen(true);
|
|
841
|
+
},
|
|
842
|
+
className: "inline-flex h-7 w-7 items-center justify-center rounded text-destructive/70 transition-colors hover:bg-destructive/10 hover:text-destructive",
|
|
843
|
+
children: /* @__PURE__ */ jsx2(Trash2, { className: "h-4 w-4" })
|
|
844
|
+
}
|
|
845
|
+
)
|
|
846
|
+
] })
|
|
847
|
+
] }),
|
|
848
|
+
selectedFile && saveError && /* @__PURE__ */ jsx2(
|
|
849
|
+
OperationErrorAlert,
|
|
850
|
+
{
|
|
851
|
+
message: saveError.message,
|
|
852
|
+
retryLabel: "Retry save",
|
|
853
|
+
onRetry: () => void saveCurrent(),
|
|
854
|
+
onDismiss: () => setSaveError(null)
|
|
855
|
+
}
|
|
856
|
+
),
|
|
857
|
+
readError && selectedFile?.path === resolvedSelectedPath && /* @__PURE__ */ jsx2(
|
|
858
|
+
OperationErrorAlert,
|
|
859
|
+
{
|
|
860
|
+
message: readError,
|
|
861
|
+
retryLabel: "Retry file refresh",
|
|
862
|
+
onRetry: () => setReloadNonce((n) => n + 1),
|
|
863
|
+
onDismiss: () => setReadError(null)
|
|
864
|
+
}
|
|
865
|
+
),
|
|
866
|
+
/* @__PURE__ */ jsx2("div", { className: "flex-1 overflow-hidden", children: fileLoading && selectedFile?.path !== resolvedSelectedPath ? /* @__PURE__ */ jsx2(EditorSkeleton, {}) : readError && selectedFile?.path !== resolvedSelectedPath ? /* @__PURE__ */ jsx2(ReadErrorState, { message: readError, onRetry: () => setReloadNonce((n) => n + 1) }) : selectedFile && canWrite && isMarkdownCapable && editorMode === "source" ? /* @__PURE__ */ jsx2(
|
|
867
|
+
SourceEditor,
|
|
868
|
+
{
|
|
869
|
+
path: selectedFile.path,
|
|
870
|
+
content: sourceDraft,
|
|
871
|
+
saving,
|
|
872
|
+
dirty: isDirty,
|
|
873
|
+
onChange: onSourceChange,
|
|
874
|
+
onSave: () => void saveCurrent()
|
|
875
|
+
}
|
|
876
|
+
) : selectedFile ? renderArtifact({
|
|
877
|
+
file: selectedFile,
|
|
878
|
+
loading: false,
|
|
879
|
+
mode: editorMode,
|
|
880
|
+
canWrite,
|
|
881
|
+
richDraft,
|
|
882
|
+
dirty: isDirty,
|
|
883
|
+
onRichChange,
|
|
884
|
+
onSave: () => void saveCurrent()
|
|
885
|
+
}) : null })
|
|
886
|
+
]
|
|
887
|
+
}
|
|
888
|
+
)
|
|
889
|
+
] })
|
|
823
890
|
] }),
|
|
824
891
|
renderDock && selectedFile && renderDock({
|
|
825
892
|
file: selectedFile,
|
|
@@ -930,4 +997,4 @@ export {
|
|
|
930
997
|
ConfirmDialog,
|
|
931
998
|
VaultPane
|
|
932
999
|
};
|
|
933
|
-
//# sourceMappingURL=chunk-
|
|
1000
|
+
//# sourceMappingURL=chunk-FCUWRMAF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vault/VaultPane.tsx","../src/vault/ConfirmDialog.tsx"],"sourcesContent":["/**\n * The shared 3-pane vault: tree | artifact viewer | optional agent dock. This is\n * pure shell MECHANISM — selection, the dirty-guard + pending-nav state machine,\n * rich/source editor modes, create/delete/refresh, skeletons, and an error\n * boundary. It renders NO file tree and NO artifact viewer of its own:\n * those arrive through the `renderTree` / `renderArtifact` / `renderDock` seams,\n * so a product wires sandbox-ui's RichFileTree + FileArtifactPane in ~10 lines.\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 useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ErrorInfo,\n type MouseEvent,\n type ReactNode,\n} from 'react'\nimport { Download, Folder, Trash2 } from 'lucide-react'\nimport { ConfirmDialog } from './ConfirmDialog'\nimport type {\n VaultEditorMode,\n VaultFile,\n VaultMarkdownCodec,\n VaultOperation,\n VaultOperationFailure,\n VaultOperationPhase,\n VaultPaneProps,\n VaultRichParts,\n VaultTreeNode,\n} from './contracts'\n\nconst IDENTITY_CODEC: VaultMarkdownCodec = {\n parse: (raw) => raw,\n serialize: (parts) => (typeof parts === 'string' ? parts : String(parts ?? '')),\n}\n\ntype PendingNav = { type: 'open'; path: string } | { type: 'close' } | null\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): 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 the Vault 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\n/** The clicked tree row, files and directories alike. The type travels with the\n * path so the caller routes on it instead of discarding everything that is not\n * a file. */\nfunction treeClickTarget(event: MouseEvent<HTMLElement>): { path: string; type: string } | null {\n const read = (el: HTMLElement) => {\n const path = el.dataset.itemPath\n return path ? { path, type: el.dataset.itemType ?? '' } : null\n }\n\n const path = event.nativeEvent.composedPath?.() ?? []\n for (const item of path) {\n if (!(item instanceof HTMLElement)) continue\n if (item.dataset.type !== 'item') continue\n return read(item)\n }\n\n const target = event.target instanceof HTMLElement\n ? event.target.closest('[data-type=\"item\"]')\n : null\n return target instanceof HTMLElement ? read(target) : null\n}\n\n// Case-insensitive name filter over the tree: files survive when their name\n// matches; a directory survives whole (with all its children) when its own name\n// matches, otherwise only when some descendant survives.\nfunction filterNodes(nodes: VaultTreeNode[], q: string): VaultTreeNode[] {\n const out: VaultTreeNode[] = []\n for (const node of nodes) {\n if (node.type === 'file') {\n if (node.name.toLowerCase().includes(q)) out.push(node)\n } else if (node.name.toLowerCase().includes(q)) {\n out.push(node)\n } else {\n const children = filterNodes(node.children ?? [], q)\n if (children.length > 0) out.push({ ...node, children })\n }\n }\n return out\n}\n\nclass EditorErrorBoundary extends Component<{ children: ReactNode; 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 : 'Something went wrong loading the vault'\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\">Vault 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({ message, onRetry }: { 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 the Vault</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\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-destructive\"\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/**\n * Browse and edit files in the available pane width.\n * Below 45rem, Files and the selected document share one pane.\n * Switching panes keeps the editor mounted and preserves unsaved changes.\n */\nexport function VaultPane(props: VaultPaneProps) {\n const {\n port,\n renderTree,\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 } = props\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\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 [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 const [pendingNav, setPendingNav] = useState<PendingNav>(null)\n const [query, setQuery] = useState('')\n const [folderPath, setFolderPath] = useState<string | null>(null)\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\n const treePaths = useMemo(\n () => collectTreePaths(tree, { files: new Set<string>(), directories: new Set<string>() }),\n [tree],\n )\n const filePaths = treePaths.files\n const resolvedSelectedPath = useMemo(\n () => selectedPath ? resolveFilePath(selectedPath, filePaths) : null,\n [selectedPath, filePaths],\n )\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: 'Vault', path: '', type: 'directory', children: tree }),\n [tree],\n )\n // With no query the whole vault stays on screen: the tree renderer owns\n // expansion (both sandbox-ui trees keep it internal), so re-rooting on a\n // plain folder click would fight the expand the click already performs. The\n // folder scopes the SEARCH, which is where a narrowed list is what the reader\n // asked for.\n const visibleRoot = useMemo<VaultTreeNode>(() => {\n const q = query.trim().toLowerCase()\n if (!q) return treeRoot\n const base = activeFolderNode ?? treeRoot\n return { ...base, children: filterNodes(base.children ?? [], q) }\n }, [treeRoot, activeFolderNode, query])\n\n const commitPath = useCallback(\n (next: string | null) => {\n if (!controlled) setInternalPath(next)\n onSelectedPathChange?.(next)\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 the Vault',\n context.path,\n )\n setTreeError({ failure, context })\n return false\n } finally {\n if (request === treeRequestRef.current) setTreeLoading(false)\n }\n }, [port, reportFailure])\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 if (treeLoading || !treeLoaded || isDirty || saving) return\n if (!resolvedSelectedPath) {\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 (!cancelled && !dirtyRef.current) setSelectedFile(file)\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 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, isDirty, saving, reloadNonce, commitPath, reportFailure])\n\n useEffect(() => {\n if (!selectedFile) {\n loadedPathRef.current = 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 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 const guardedOpen = useCallback(\n (path: string) => {\n if (path === selectedPath) {\n showDocument()\n return\n }\n if (isDirty) {\n setPendingNav({ type: 'open', path })\n return\n }\n showDocument()\n commitPath(path)\n },\n [isDirty, selectedPath, commitPath, showDocument],\n )\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\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 guardedClose = useCallback(() => {\n if (isDirty) {\n setPendingNav({ type: 'close' })\n return\n }\n commitPath(null)\n setSelectedFile(null)\n }, [isDirty, commitPath])\n\n const confirmDiscard = useCallback(() => {\n const nav = pendingNav\n setPendingNav(null)\n setIsDirty(false)\n if (!nav) return\n if (nav.type === 'open') {\n showDocument()\n commitPath(nav.path)\n } else {\n commitPath(null)\n setSelectedFile(null)\n }\n }, [pendingNav, commitPath, showDocument])\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 const createFileName = newPath.trim().split('/').pop()?.trim() ?? ''\n\n let treeContent: ReactNode\n if (!treeLoaded && (treeLoading || !treeError)) {\n treeContent = <TreeSkeleton />\n } else if (!treeLoaded && treeError) {\n treeContent = <TreeErrorState message={treeFailureMessage(treeError.failure)} onRetry={() => void retryTree()} />\n } else {\n treeContent = (\n <>\n {treeError && (\n <OperationErrorAlert\n message={treeFailureMessage(treeError.failure)}\n retryLabel=\"Retry vault refresh\"\n onRetry={() => void retryTree()}\n onDismiss={() => setTreeError(null)}\n />\n )}\n {renderTree({\n root: visibleRoot,\n selectedPath: resolvedSelectedPath ?? undefined,\n onSelect: handleTreeSelect,\n })}\n </>\n )\n }\n\n return (\n <EditorErrorBoundary onReset={() => { commitPath(null); setSelectedFile(null) }}>\n <div 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 <nav aria-label=\"Vault navigation\" className=\"flex shrink-0 items-center gap-1 border-b border-border p-2 @[45rem]/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 <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 border-r border-border bg-background @[45rem]/vault:flex @[45rem]/vault:w-[23rem] @[45rem]/vault:min-w-[23rem] @[45rem]/vault:flex-none`}>\n <div className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <div className=\"min-w-0 flex-1\">\n <input\n ref={searchRef}\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={activeFolder ? `Search ${activeFolder}…` : 'Search…'}\n aria-label=\"Search vault\"\n className=\"h-8 w-full rounded-md border border-border bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground\"\n />\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {headerActions}\n <button\n type=\"button\"\n aria-label=\"Refresh vault\"\n onClick={() => void refresh()}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n ↻\n </button>\n {canWrite && (\n <button\n type=\"button\"\n aria-label={activeFolder ? `New vault file in ${activeFolder}` : 'New vault file'}\n onClick={() => { setCreateError(null); setNewPath(activeFolder ? `${activeFolder}/` : ''); setCreateOpen(true) }}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded-md bg-primary text-primary-foreground transition-colors hover:bg-primary/90\"\n >\n +\n </button>\n )}\n </div>\n </div>\n {activeFolder && (\n <div className=\"flex items-center gap-1.5 border-b border-border bg-muted/40 px-4 py-1.5 text-xs\">\n <Folder className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\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\"\n >\n Clear\n </button>\n </div>\n )}\n <div\n className=\"flex-1 overflow-y-auto\"\n onClickCapture={(event) => {\n const target = treeClickTarget(event)\n if (target) handleTreeSelect(target.path)\n }}\n >\n {treeContent}\n </div>\n </div>\n\n <div\n ref={documentRef}\n role=\"region\"\n aria-label=\"Vault document\"\n tabIndex={-1}\n className={`${showFiles ? 'hidden' : 'flex'} min-w-0 flex-1 flex-col overflow-hidden @[45rem]/vault:flex`}\n >\n {selectedFile && (\n <div className={`flex shrink-0 items-center justify-between gap-2 border-b border-border px-4 py-1.5 ${pathBarClassName ?? 'bg-card'}`}>\n <span data-vault-path className=\"min-w-0 flex-1 truncate text-xs 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-7 items-center rounded px-2 text-xs 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-7 items-center rounded px-2 text-xs 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 {renderDock && !persistentDock && (\n <button\n type=\"button\"\n aria-label={dockToggleCfg.label}\n aria-pressed={dockOpen}\n disabled={(dockToggleCfg.disabledWhenDirty ?? true) && isDirty}\n title={(dockToggleCfg.disabledWhenDirty ?? true) && isDirty ? 'Save your changes first' : (dockToggleCfg.title ?? dockToggleCfg.label)}\n onClick={() => setDockOpen((v) => !v)}\n className={`inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs 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 {dockToggleCfg.label}\n </button>\n )}\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 {canWrite && (\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-destructive/70 transition-colors hover:bg-destructive/10 hover:text-destructive\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </div>\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 && 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 })\n ) : null}\n </div>\n </div>\n </div>\n </div>\n\n {renderDock && selectedFile && renderDock({\n file: selectedFile,\n open: persistentDock ? true : dockOpen,\n onClose: persistentDock ? () => {} : () => setDockOpen(false),\n })}\n\n <ConfirmDialog\n open={createOpen}\n title=\"Create vault file\"\n description={activeFolder ? `Add a new document to ${activeFolder}.` : 'Add a new document to this vault.'}\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-destructive\">{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 the vault.`}\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-destructive\">{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={() => 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-xs text-muted-foreground\">{path}</p>\n <div className=\"flex shrink-0 items-center gap-2\">\n <span className=\"rounded-full border border-border bg-background px-2.5 py-1 text-xs text-muted-foreground\">\n {dirty ? 'Unsaved changes' : 'Saved'}\n </span>\n <button\n type=\"button\"\n onClick={onSave}\n disabled={saving || !dirty}\n className=\"inline-flex h-7 items-center rounded-md bg-primary px-2 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50\"\n >\n {saving ? 'Saving…' : 'Save'}\n </button>\n </div>\n </div>\n <textarea\n value={content}\n onChange={(event) => onChange(event.target.value)}\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 * Esc-to-cancel and Enter-to-confirm, 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 if (event.key === 'Enter' && !confirmDisabled) {\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"],"mappings":"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","names":["useEffect","useRef","jsx","jsxs","path","useRef","useEffect"]}
|
|
@@ -12,4 +12,9 @@
|
|
|
12
12
|
* default). Chrome uses the shared theme tokens (bg-card, border-border, …).
|
|
13
13
|
*/
|
|
14
14
|
import type { VaultPaneProps } from './contracts';
|
|
15
|
+
/**
|
|
16
|
+
* Browse and edit files in the available pane width.
|
|
17
|
+
* Below 45rem, Files and the selected document share one pane.
|
|
18
|
+
* Switching panes keeps the editor mounted and preserves unsaved changes.
|
|
19
|
+
*/
|
|
15
20
|
export declare function VaultPane(props: VaultPaneProps): import("react").JSX.Element;
|
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-32HVWZ6A.js").then((m) => ({ default: m.VaultPane }))
|
|
5
5
|
);
|
|
6
6
|
export {
|
|
7
7
|
VaultPaneLazy
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vault/VaultPane.tsx","../src/vault/ConfirmDialog.tsx"],"sourcesContent":["/**\n * The shared 3-pane vault: tree | artifact viewer | optional agent dock. This is\n * pure shell MECHANISM — selection, the dirty-guard + pending-nav state machine,\n * rich/source editor modes, create/delete/refresh, skeletons, and an error\n * boundary. It renders NO file tree and NO artifact viewer of its own:\n * those arrive through the `renderTree` / `renderArtifact` / `renderDock` seams,\n * so a product wires sandbox-ui's RichFileTree + FileArtifactPane in ~10 lines.\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 useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ErrorInfo,\n type MouseEvent,\n type ReactNode,\n} from 'react'\nimport { Download, Folder, Trash2 } from 'lucide-react'\nimport { ConfirmDialog } from './ConfirmDialog'\nimport type {\n VaultEditorMode,\n VaultFile,\n VaultMarkdownCodec,\n VaultOperation,\n VaultOperationFailure,\n VaultOperationPhase,\n VaultPaneProps,\n VaultRichParts,\n VaultTreeNode,\n} from './contracts'\n\nconst IDENTITY_CODEC: VaultMarkdownCodec = {\n parse: (raw) => raw,\n serialize: (parts) => (typeof parts === 'string' ? parts : String(parts ?? '')),\n}\n\ntype PendingNav = { type: 'open'; path: string } | { type: 'close' } | null\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): 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 the Vault 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\n/** The clicked tree row, files and directories alike. The type travels with the\n * path so the caller routes on it instead of discarding everything that is not\n * a file. */\nfunction treeClickTarget(event: MouseEvent<HTMLElement>): { path: string; type: string } | null {\n const read = (el: HTMLElement) => {\n const path = el.dataset.itemPath\n return path ? { path, type: el.dataset.itemType ?? '' } : null\n }\n\n const path = event.nativeEvent.composedPath?.() ?? []\n for (const item of path) {\n if (!(item instanceof HTMLElement)) continue\n if (item.dataset.type !== 'item') continue\n return read(item)\n }\n\n const target = event.target instanceof HTMLElement\n ? event.target.closest('[data-type=\"item\"]')\n : null\n return target instanceof HTMLElement ? read(target) : null\n}\n\n// Case-insensitive name filter over the tree: files survive when their name\n// matches; a directory survives whole (with all its children) when its own name\n// matches, otherwise only when some descendant survives.\nfunction filterNodes(nodes: VaultTreeNode[], q: string): VaultTreeNode[] {\n const out: VaultTreeNode[] = []\n for (const node of nodes) {\n if (node.type === 'file') {\n if (node.name.toLowerCase().includes(q)) out.push(node)\n } else if (node.name.toLowerCase().includes(q)) {\n out.push(node)\n } else {\n const children = filterNodes(node.children ?? [], q)\n if (children.length > 0) out.push({ ...node, children })\n }\n }\n return out\n}\n\nclass EditorErrorBoundary extends Component<{ children: ReactNode; 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 : 'Something went wrong loading the vault'\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\">Vault 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({ message, onRetry }: { 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 the Vault</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\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-destructive\"\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\nexport function VaultPane(props: VaultPaneProps) {\n const {\n port,\n renderTree,\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 } = props\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\n const [selectedFile, setSelectedFile] = useState<VaultFile | 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 const [pendingNav, setPendingNav] = useState<PendingNav>(null)\n const [query, setQuery] = useState('')\n const [folderPath, setFolderPath] = useState<string | null>(null)\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\n const treePaths = useMemo(\n () => collectTreePaths(tree, { files: new Set<string>(), directories: new Set<string>() }),\n [tree],\n )\n const filePaths = treePaths.files\n const resolvedSelectedPath = useMemo(\n () => selectedPath ? resolveFilePath(selectedPath, filePaths) : null,\n [selectedPath, filePaths],\n )\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: 'Vault', path: '', type: 'directory', children: tree }),\n [tree],\n )\n // With no query the whole vault stays on screen: the tree renderer owns\n // expansion (both sandbox-ui trees keep it internal), so re-rooting on a\n // plain folder click would fight the expand the click already performs. The\n // folder scopes the SEARCH, which is where a narrowed list is what the reader\n // asked for.\n const visibleRoot = useMemo<VaultTreeNode>(() => {\n const q = query.trim().toLowerCase()\n if (!q) return treeRoot\n const base = activeFolderNode ?? treeRoot\n return { ...base, children: filterNodes(base.children ?? [], q) }\n }, [treeRoot, activeFolderNode, query])\n\n const commitPath = useCallback(\n (next: string | null) => {\n if (!controlled) setInternalPath(next)\n onSelectedPathChange?.(next)\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 the Vault',\n context.path,\n )\n setTreeError({ failure, context })\n return false\n } finally {\n if (request === treeRequestRef.current) setTreeLoading(false)\n }\n }, [port, reportFailure])\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 if (treeLoading || !treeLoaded || isDirty || saving) return\n if (!resolvedSelectedPath) {\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 (!cancelled && !dirtyRef.current) setSelectedFile(file)\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 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, isDirty, saving, reloadNonce, commitPath, reportFailure])\n\n useEffect(() => {\n if (!selectedFile) {\n loadedPathRef.current = 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 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 const guardedOpen = useCallback(\n (path: string) => {\n if (path === selectedPath) return\n if (isDirty) {\n setPendingNav({ type: 'open', path })\n return\n }\n commitPath(path)\n },\n [isDirty, selectedPath, commitPath],\n )\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\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 guardedClose = useCallback(() => {\n if (isDirty) {\n setPendingNav({ type: 'close' })\n return\n }\n commitPath(null)\n setSelectedFile(null)\n }, [isDirty, commitPath])\n\n const confirmDiscard = useCallback(() => {\n const nav = pendingNav\n setPendingNav(null)\n setIsDirty(false)\n if (!nav) return\n if (nav.type === 'open') {\n commitPath(nav.path)\n } else {\n commitPath(null)\n setSelectedFile(null)\n }\n }, [pendingNav, commitPath])\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 const createFileName = newPath.trim().split('/').pop()?.trim() ?? ''\n\n let treeContent: ReactNode\n if (!treeLoaded && (treeLoading || !treeError)) {\n treeContent = <TreeSkeleton />\n } else if (!treeLoaded && treeError) {\n treeContent = <TreeErrorState message={treeFailureMessage(treeError.failure)} onRetry={() => void retryTree()} />\n } else {\n treeContent = (\n <>\n {treeError && (\n <OperationErrorAlert\n message={treeFailureMessage(treeError.failure)}\n retryLabel=\"Retry vault refresh\"\n onRetry={() => void retryTree()}\n onDismiss={() => setTreeError(null)}\n />\n )}\n {renderTree({\n root: visibleRoot,\n selectedPath: resolvedSelectedPath ?? undefined,\n onSelect: handleTreeSelect,\n })}\n </>\n )\n }\n\n return (\n <EditorErrorBoundary onReset={() => { commitPath(null); setSelectedFile(null) }}>\n <div className={`flex min-h-0 flex-1 overflow-hidden ${className ?? ''}`}>\n <div className=\"flex w-[23rem] min-w-[23rem] flex-col border-r border-border bg-background\">\n <div className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <div className=\"min-w-0 flex-1\">\n <input\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={activeFolder ? `Search ${activeFolder}…` : 'Search…'}\n aria-label=\"Search vault\"\n className=\"h-8 w-full rounded-md border border-border bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground\"\n />\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {headerActions}\n <button\n type=\"button\"\n aria-label=\"Refresh vault\"\n onClick={() => void refresh()}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n ↻\n </button>\n {canWrite && (\n <button\n type=\"button\"\n aria-label={activeFolder ? `New vault file in ${activeFolder}` : 'New vault file'}\n onClick={() => { setCreateError(null); setNewPath(activeFolder ? `${activeFolder}/` : ''); setCreateOpen(true) }}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded-md bg-primary text-primary-foreground transition-colors hover:bg-primary/90\"\n >\n +\n </button>\n )}\n </div>\n </div>\n {activeFolder && (\n <div className=\"flex items-center gap-1.5 border-b border-border bg-muted/40 px-4 py-1.5 text-xs\">\n <Folder className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\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\"\n >\n Clear\n </button>\n </div>\n )}\n <div\n className=\"flex-1 overflow-y-auto\"\n onClickCapture={(event) => {\n const target = treeClickTarget(event)\n if (target) handleTreeSelect(target.path)\n }}\n >\n {treeContent}\n </div>\n </div>\n\n <div className=\"flex min-w-0 flex-1 flex-col overflow-hidden\">\n {selectedFile && (\n <div className={`flex shrink-0 items-center justify-between border-b border-border px-4 py-1.5 ${pathBarClassName ?? 'bg-card'}`}>\n <span data-vault-path className=\"truncate text-xs font-medium text-foreground\">{selectedFile.path}</span>\n <div className=\"flex 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-7 items-center rounded px-2 text-xs 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-7 items-center rounded px-2 text-xs 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 {renderDock && !persistentDock && (\n <button\n type=\"button\"\n aria-label={dockToggleCfg.label}\n aria-pressed={dockOpen}\n disabled={(dockToggleCfg.disabledWhenDirty ?? true) && isDirty}\n title={(dockToggleCfg.disabledWhenDirty ?? true) && isDirty ? 'Save your changes first' : (dockToggleCfg.title ?? dockToggleCfg.label)}\n onClick={() => setDockOpen((v) => !v)}\n className={`inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs 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 {dockToggleCfg.label}\n </button>\n )}\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 {canWrite && (\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-destructive/70 transition-colors hover:bg-destructive/10 hover:text-destructive\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </div>\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 && 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 })\n ) : null}\n </div>\n </div>\n\n {renderDock && selectedFile && renderDock({\n file: selectedFile,\n open: persistentDock ? true : dockOpen,\n onClose: persistentDock ? () => {} : () => setDockOpen(false),\n })}\n\n <ConfirmDialog\n open={createOpen}\n title=\"Create vault file\"\n description={activeFolder ? `Add a new document to ${activeFolder}.` : 'Add a new document to this vault.'}\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-destructive\">{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 the vault.`}\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-destructive\">{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={() => 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-xs text-muted-foreground\">{path}</p>\n <div className=\"flex shrink-0 items-center gap-2\">\n <span className=\"rounded-full border border-border bg-background px-2.5 py-1 text-xs text-muted-foreground\">\n {dirty ? 'Unsaved changes' : 'Saved'}\n </span>\n <button\n type=\"button\"\n onClick={onSave}\n disabled={saving || !dirty}\n className=\"inline-flex h-7 items-center rounded-md bg-primary px-2 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50\"\n >\n {saving ? 'Saving…' : 'Save'}\n </button>\n </div>\n </div>\n <textarea\n value={content}\n onChange={(event) => onChange(event.target.value)}\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 * Esc-to-cancel and Enter-to-confirm, 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 if (event.key === 'Enter' && !confirmDisabled) {\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"],"mappings":"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","names":["useEffect","useRef","jsx","jsxs","path","useRef","useEffect"]}
|
|
File without changes
|