@tangle-network/agent-app 0.31.0 → 0.33.1
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-BQ2MZIMM.js +7 -0
- package/dist/VaultPane-BQ2MZIMM.js.map +1 -0
- package/dist/VaultPane-By2l5lol.d.ts +141 -0
- package/dist/chunk-FNUEUOOZ.js +597 -0
- package/dist/chunk-FNUEUOOZ.js.map +1 -0
- package/dist/vault/index.d.ts +22 -0
- package/dist/vault/index.js +9 -0
- package/dist/vault/index.js.map +1 -0
- package/dist/vault/lazy.d.ts +7 -0
- package/dist/vault/lazy.js +9 -0
- package/dist/vault/lazy.js.map +1 -0
- package/package.json +11 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Seams between the shared VaultPane and the host product. Everything here is
|
|
6
|
+
* interface-only: the pane never imports a file tree, an artifact viewer, a
|
|
7
|
+
* dialog library, or a product's data client. The product supplies the data
|
|
8
|
+
* (`VaultDataPort`) and the renderers (`renderTree`/`renderArtifact`/`renderDock`),
|
|
9
|
+
* so the same 3-pane vault mounts in any Tangle agent product.
|
|
10
|
+
*
|
|
11
|
+
* `VaultTreeNode` BYTE-MATCHES sandbox-ui's `FileNode` so a product's tree
|
|
12
|
+
* passes straight through both the data port and `renderTree` with zero mapping.
|
|
13
|
+
*
|
|
14
|
+
* The only import is React's `ReactNode` type — pure type, no runtime, so this
|
|
15
|
+
* file stays server-safe and the contracts are usable without React mounted.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* One node in the vault tree. Field-for-field identical to sandbox-ui's
|
|
20
|
+
* `FileNode`, so a `VaultTreeNode[]` IS a `FileNode[]` — the product hands
|
|
21
|
+
* sandbox-ui's `RichFileTree` the `root` from `renderTree` with no conversion.
|
|
22
|
+
*/
|
|
23
|
+
interface VaultTreeNode {
|
|
24
|
+
name: string;
|
|
25
|
+
path: string;
|
|
26
|
+
type: 'file' | 'directory';
|
|
27
|
+
children?: VaultTreeNode[];
|
|
28
|
+
size?: number;
|
|
29
|
+
mimeType?: string;
|
|
30
|
+
}
|
|
31
|
+
/** A loaded vault file: its text content plus optional preview hints. */
|
|
32
|
+
interface VaultFile {
|
|
33
|
+
path: string;
|
|
34
|
+
content: string;
|
|
35
|
+
mimeType?: string;
|
|
36
|
+
/** Object URL for binary/media previews the artifact renderer streams. */
|
|
37
|
+
blobUrl?: string;
|
|
38
|
+
/** Product-domain passthrough (media metadata, review state, …) the artifact
|
|
39
|
+
* renderer reads. The pane never inspects it. */
|
|
40
|
+
extras?: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The data seam the product owns. Every method is async and product-backed —
|
|
44
|
+
* over fetch, a sandbox session, a worker RPC, whatever the product uses. The
|
|
45
|
+
* pane calls these; it never knows the transport.
|
|
46
|
+
*/
|
|
47
|
+
interface VaultDataPort {
|
|
48
|
+
/** List the full vault tree. The returned nodes feed `renderTree` directly. */
|
|
49
|
+
listTree(): Promise<VaultTreeNode[]>;
|
|
50
|
+
/** Read a single file by path. */
|
|
51
|
+
readFile(path: string): Promise<VaultFile>;
|
|
52
|
+
/** Persist `content` to `path`. */
|
|
53
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
54
|
+
/** Create a new file at `path`; returns the CANONICAL path actually created
|
|
55
|
+
* (the port may normalize, e.g. append an extension) so the pane opens it. */
|
|
56
|
+
createFile(path: string): Promise<string>;
|
|
57
|
+
/** Delete the file at `path`. */
|
|
58
|
+
deleteFile(path: string): Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The parsed form of a file's rich content. The pane stays agnostic about the
|
|
62
|
+
* shape — it round-trips `serialize(parse(raw))` through the codec to compute
|
|
63
|
+
* dirtiness, so any structure (frontmatter + body, AST, etc.) works as long as
|
|
64
|
+
* `parse` and `serialize` are inverses for unchanged content.
|
|
65
|
+
*/
|
|
66
|
+
type VaultRichParts = unknown;
|
|
67
|
+
/**
|
|
68
|
+
* Optional rich/source codec. When supplied, the pane's rich mode edits
|
|
69
|
+
* `parse(raw)` and the source mode edits `raw`; switching modes recomputes
|
|
70
|
+
* dirtiness against the saved content via `serialize`. Default: identity
|
|
71
|
+
* passthrough (the rich draft IS the raw string) so source mode works without a
|
|
72
|
+
* codec and there's no markdown dependency in the shell.
|
|
73
|
+
*
|
|
74
|
+
* CONTRACT: `parse`/`serialize` MUST be exact inverses — `serialize(parse(raw))
|
|
75
|
+
* === raw` for ALL content, INCLUDING the empty / no-metadata case. The pane
|
|
76
|
+
* uses that round-trip to detect edits, so a non-inverse opens files false-dirty
|
|
77
|
+
* and a save corrupts them.
|
|
78
|
+
*/
|
|
79
|
+
interface VaultMarkdownCodec {
|
|
80
|
+
parse(raw: string): VaultRichParts;
|
|
81
|
+
serialize(parts: VaultRichParts): string;
|
|
82
|
+
}
|
|
83
|
+
/** Props the pane passes to the product's tree renderer (e.g. RichFileTree). */
|
|
84
|
+
interface VaultTreeRenderProps {
|
|
85
|
+
root: VaultTreeNode;
|
|
86
|
+
selectedPath?: string;
|
|
87
|
+
onSelect: (path: string) => void;
|
|
88
|
+
}
|
|
89
|
+
/** Props the pane passes to the product's artifact renderer (e.g. FileArtifactPane). */
|
|
90
|
+
interface VaultArtifactRenderProps {
|
|
91
|
+
file: VaultFile | null;
|
|
92
|
+
loading: boolean;
|
|
93
|
+
/** Current editor mode. In 'rich' mode the product MAY host a WYSIWYG editor
|
|
94
|
+
* wired to `richDraft` + `onRichChange` + `onSave`; else render a read preview. */
|
|
95
|
+
mode: VaultEditorMode;
|
|
96
|
+
/** Whether editing is allowed (mirrors VaultPaneProps.canWrite). */
|
|
97
|
+
canWrite: boolean;
|
|
98
|
+
/** The live rich draft (the codec's parsed form). The product's rich editor
|
|
99
|
+
* edits this; reverting to the saved content clears dirtiness. */
|
|
100
|
+
richDraft: VaultRichParts;
|
|
101
|
+
/** Whether the draft has unsaved edits. */
|
|
102
|
+
dirty: boolean;
|
|
103
|
+
/** The product's rich editor reports edits here (updates draft + dirtiness). */
|
|
104
|
+
onRichChange: (parts: VaultRichParts) => void;
|
|
105
|
+
/** Persist the current draft through the data port. */
|
|
106
|
+
onSave: () => void;
|
|
107
|
+
}
|
|
108
|
+
/** Props the pane passes to the product's optional dock renderer (e.g. an agent dock). */
|
|
109
|
+
interface VaultDockRenderProps {
|
|
110
|
+
file: VaultFile | null;
|
|
111
|
+
open: boolean;
|
|
112
|
+
onClose: () => void;
|
|
113
|
+
}
|
|
114
|
+
/** The two editor surfaces the pane switches between for editable text files. */
|
|
115
|
+
type VaultEditorMode = 'rich' | 'source';
|
|
116
|
+
interface VaultPaneProps {
|
|
117
|
+
/** Product-owned data access. */
|
|
118
|
+
port: VaultDataPort;
|
|
119
|
+
/** Renders the left tree pane. The product passes sandbox-ui's RichFileTree. */
|
|
120
|
+
renderTree: (props: VaultTreeRenderProps) => ReactNode;
|
|
121
|
+
/** Renders the center artifact pane. The product passes sandbox-ui's FileArtifactPane. */
|
|
122
|
+
renderArtifact: (props: VaultArtifactRenderProps) => ReactNode;
|
|
123
|
+
/** Renders an optional right dock (agent chat, metadata, …). Omit to hide. */
|
|
124
|
+
renderDock?: (props: VaultDockRenderProps) => ReactNode;
|
|
125
|
+
/**
|
|
126
|
+
* When false, all write affordances (create / delete / save / source editor)
|
|
127
|
+
* are hidden and the pane is read-only. Defaults to true.
|
|
128
|
+
*/
|
|
129
|
+
canWrite?: boolean;
|
|
130
|
+
/** Controlled selection. Pair with `onSelectedPathChange`. */
|
|
131
|
+
selectedPath?: string | null;
|
|
132
|
+
/** Notified whenever the selected path changes (including clear → null). */
|
|
133
|
+
onSelectedPathChange?: (path: string | null) => void;
|
|
134
|
+
/** Optional rich/source codec. Defaults to identity passthrough. */
|
|
135
|
+
codec?: VaultMarkdownCodec;
|
|
136
|
+
className?: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
declare function VaultPane(props: VaultPaneProps): react.JSX.Element;
|
|
140
|
+
|
|
141
|
+
export { type VaultArtifactRenderProps as V, type VaultDataPort as a, type VaultDockRenderProps as b, type VaultEditorMode as c, type VaultFile as d, type VaultMarkdownCodec as e, VaultPane as f, type VaultPaneProps as g, type VaultRichParts as h, type VaultTreeNode as i, type VaultTreeRenderProps as j };
|
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
// src/vault/VaultPane.tsx
|
|
2
|
+
import {
|
|
3
|
+
Component,
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect as useEffect2,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef as useRef2,
|
|
8
|
+
useState
|
|
9
|
+
} from "react";
|
|
10
|
+
|
|
11
|
+
// src/vault/ConfirmDialog.tsx
|
|
12
|
+
import { useEffect, useRef } from "react";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
function ConfirmDialog({
|
|
15
|
+
open,
|
|
16
|
+
title,
|
|
17
|
+
description,
|
|
18
|
+
confirmLabel = "Confirm",
|
|
19
|
+
cancelLabel = "Cancel",
|
|
20
|
+
destructive = false,
|
|
21
|
+
confirmDisabled = false,
|
|
22
|
+
onConfirm,
|
|
23
|
+
onCancel,
|
|
24
|
+
children
|
|
25
|
+
}) {
|
|
26
|
+
const panelRef = useRef(null);
|
|
27
|
+
const confirmRef = useRef(null);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!open) return;
|
|
30
|
+
confirmRef.current?.focus();
|
|
31
|
+
}, [open]);
|
|
32
|
+
if (!open) return null;
|
|
33
|
+
function onKeyDown(event) {
|
|
34
|
+
if (event.key === "Escape") {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
onCancel();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (event.key === "Enter" && !confirmDisabled) {
|
|
40
|
+
event.preventDefault();
|
|
41
|
+
onConfirm();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (event.key !== "Tab") return;
|
|
45
|
+
const focusable = panelRef.current?.querySelectorAll(
|
|
46
|
+
'button:not([disabled]), input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
47
|
+
);
|
|
48
|
+
if (!focusable || focusable.length === 0) return;
|
|
49
|
+
const first = focusable[0];
|
|
50
|
+
const last = focusable[focusable.length - 1];
|
|
51
|
+
const active = document.activeElement;
|
|
52
|
+
if (event.shiftKey && active === first) {
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
last?.focus();
|
|
55
|
+
} else if (!event.shiftKey && active === last) {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
first?.focus();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return /* @__PURE__ */ jsx(
|
|
61
|
+
"div",
|
|
62
|
+
{
|
|
63
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4",
|
|
64
|
+
onMouseDown: (e) => {
|
|
65
|
+
if (e.target === e.currentTarget) onCancel();
|
|
66
|
+
},
|
|
67
|
+
children: /* @__PURE__ */ jsxs(
|
|
68
|
+
"div",
|
|
69
|
+
{
|
|
70
|
+
ref: panelRef,
|
|
71
|
+
role: "dialog",
|
|
72
|
+
"aria-modal": "true",
|
|
73
|
+
"aria-label": title,
|
|
74
|
+
onKeyDown,
|
|
75
|
+
className: "w-full max-w-md rounded-lg border border-border bg-card p-5 shadow-lg",
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-foreground", children: title }),
|
|
78
|
+
description && /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-xs text-muted-foreground", children: description }),
|
|
79
|
+
children && /* @__PURE__ */ jsx("div", { className: "mt-3", children }),
|
|
80
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-5 flex justify-end gap-2", children: [
|
|
81
|
+
/* @__PURE__ */ jsx(
|
|
82
|
+
"button",
|
|
83
|
+
{
|
|
84
|
+
type: "button",
|
|
85
|
+
onClick: onCancel,
|
|
86
|
+
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 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60",
|
|
87
|
+
children: cancelLabel
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
/* @__PURE__ */ jsx(
|
|
91
|
+
"button",
|
|
92
|
+
{
|
|
93
|
+
ref: confirmRef,
|
|
94
|
+
type: "button",
|
|
95
|
+
onClick: onConfirm,
|
|
96
|
+
disabled: confirmDisabled,
|
|
97
|
+
className: `inline-flex h-8 items-center rounded-md px-3 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60 disabled:pointer-events-none disabled:opacity-50 ${destructive ? "bg-destructive text-destructive-foreground hover:bg-destructive/90" : "bg-primary text-primary-foreground hover:bg-primary/90"}`,
|
|
98
|
+
children: confirmLabel
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
] })
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/vault/VaultPane.tsx
|
|
110
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
111
|
+
var IDENTITY_CODEC = {
|
|
112
|
+
parse: (raw) => raw,
|
|
113
|
+
serialize: (parts) => typeof parts === "string" ? parts : String(parts ?? "")
|
|
114
|
+
};
|
|
115
|
+
function collectFilePaths(nodes, into) {
|
|
116
|
+
for (const node of nodes) {
|
|
117
|
+
if (node.type === "file") into.add(node.path);
|
|
118
|
+
if (node.children) collectFilePaths(node.children, into);
|
|
119
|
+
}
|
|
120
|
+
return into;
|
|
121
|
+
}
|
|
122
|
+
function countFiles(nodes) {
|
|
123
|
+
return nodes.reduce(
|
|
124
|
+
(sum, node) => node.type === "file" ? sum + 1 : sum + countFiles(node.children ?? []),
|
|
125
|
+
0
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
var EditorErrorBoundary = class extends Component {
|
|
129
|
+
state = { error: null };
|
|
130
|
+
static getDerivedStateFromError(error) {
|
|
131
|
+
return { error };
|
|
132
|
+
}
|
|
133
|
+
componentDidCatch(error, info) {
|
|
134
|
+
console.error("Vault crashed:", error, info);
|
|
135
|
+
}
|
|
136
|
+
render() {
|
|
137
|
+
if (this.state.error) {
|
|
138
|
+
const msg = this.state.error instanceof Error ? this.state.error.message : typeof this.state.error === "string" ? this.state.error : "Something went wrong loading the vault";
|
|
139
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex h-full flex-1 flex-col items-center justify-center p-8 text-center", children: [
|
|
140
|
+
/* @__PURE__ */ jsx2("h3", { className: "mb-1 text-sm font-medium text-foreground", children: "Vault failed to load" }),
|
|
141
|
+
/* @__PURE__ */ jsx2("p", { className: "mb-4 max-w-xs text-xs text-muted-foreground", children: String(msg) }),
|
|
142
|
+
/* @__PURE__ */ jsx2(
|
|
143
|
+
"button",
|
|
144
|
+
{
|
|
145
|
+
type: "button",
|
|
146
|
+
onClick: () => {
|
|
147
|
+
this.setState({ error: null });
|
|
148
|
+
this.props.onReset?.();
|
|
149
|
+
},
|
|
150
|
+
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 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60",
|
|
151
|
+
children: "Try again"
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
] });
|
|
155
|
+
}
|
|
156
|
+
return this.props.children;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
function TreeSkeleton() {
|
|
160
|
+
return /* @__PURE__ */ jsx2("div", { className: "space-y-2 p-4", "aria-hidden": "true", children: [32, 48, 40, 52].map((w, i) => /* @__PURE__ */ jsx2("div", { className: "h-4 animate-pulse rounded bg-muted", style: { width: `${w * 4}px` } }, i)) });
|
|
161
|
+
}
|
|
162
|
+
function EditorSkeleton() {
|
|
163
|
+
return /* @__PURE__ */ jsxs2("div", { className: "space-y-3 p-8", "aria-hidden": "true", children: [
|
|
164
|
+
/* @__PURE__ */ jsx2("div", { className: "h-5 w-1/2 animate-pulse rounded bg-muted" }),
|
|
165
|
+
/* @__PURE__ */ jsx2("div", { className: "h-4 w-full animate-pulse rounded bg-muted" }),
|
|
166
|
+
/* @__PURE__ */ jsx2("div", { className: "h-4 w-3/4 animate-pulse rounded bg-muted" }),
|
|
167
|
+
/* @__PURE__ */ jsx2("div", { className: "h-4 w-2/3 animate-pulse rounded bg-muted" })
|
|
168
|
+
] });
|
|
169
|
+
}
|
|
170
|
+
function EmptyState() {
|
|
171
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex h-full flex-col items-center justify-center p-8 text-center", children: [
|
|
172
|
+
/* @__PURE__ */ jsx2("h3", { className: "text-sm font-medium text-foreground", children: "Open a vault document" }),
|
|
173
|
+
/* @__PURE__ */ jsx2("p", { className: "mt-1 max-w-xs text-xs text-muted-foreground", children: "Select a file from the directory, or create a new one." })
|
|
174
|
+
] });
|
|
175
|
+
}
|
|
176
|
+
function VaultPane(props) {
|
|
177
|
+
const {
|
|
178
|
+
port,
|
|
179
|
+
renderTree,
|
|
180
|
+
renderArtifact,
|
|
181
|
+
renderDock,
|
|
182
|
+
canWrite = true,
|
|
183
|
+
selectedPath: controlledPath,
|
|
184
|
+
onSelectedPathChange,
|
|
185
|
+
codec,
|
|
186
|
+
className
|
|
187
|
+
} = props;
|
|
188
|
+
const activeCodec = codec ?? IDENTITY_CODEC;
|
|
189
|
+
const controlled = controlledPath !== void 0;
|
|
190
|
+
const isMarkdownCapable = codec !== void 0;
|
|
191
|
+
const [tree, setTree] = useState([]);
|
|
192
|
+
const [treeLoading, setTreeLoading] = useState(true);
|
|
193
|
+
const [internalPath, setInternalPath] = useState(null);
|
|
194
|
+
const selectedPath = controlled ? controlledPath ?? null : internalPath;
|
|
195
|
+
const [selectedFile, setSelectedFile] = useState(null);
|
|
196
|
+
const [fileLoading, setFileLoading] = useState(false);
|
|
197
|
+
const [saving, setSaving] = useState(false);
|
|
198
|
+
const [editorMode, setEditorMode] = useState("rich");
|
|
199
|
+
const [richDraft, setRichDraft] = useState("");
|
|
200
|
+
const [sourceDraft, setSourceDraft] = useState("");
|
|
201
|
+
const [isDirty, setIsDirty] = useState(false);
|
|
202
|
+
const [createOpen, setCreateOpen] = useState(false);
|
|
203
|
+
const [newPath, setNewPath] = useState("");
|
|
204
|
+
const [creating, setCreating] = useState(false);
|
|
205
|
+
const [deleteOpen, setDeleteOpen] = useState(false);
|
|
206
|
+
const [deleting, setDeleting] = useState(false);
|
|
207
|
+
const [dockOpen, setDockOpen] = useState(false);
|
|
208
|
+
const [pendingNav, setPendingNav] = useState(null);
|
|
209
|
+
const savedContentRef = useRef2("");
|
|
210
|
+
const loadedPathRef = useRef2(null);
|
|
211
|
+
const filePaths = useMemo(() => collectFilePaths(tree, /* @__PURE__ */ new Set()), [tree]);
|
|
212
|
+
const treeRoot = useMemo(
|
|
213
|
+
() => ({ name: "Vault", path: "", type: "directory", children: tree }),
|
|
214
|
+
[tree]
|
|
215
|
+
);
|
|
216
|
+
const fileCount = useMemo(() => countFiles(tree), [tree]);
|
|
217
|
+
const commitPath = useCallback(
|
|
218
|
+
(next) => {
|
|
219
|
+
if (!controlled) setInternalPath(next);
|
|
220
|
+
onSelectedPathChange?.(next);
|
|
221
|
+
},
|
|
222
|
+
[controlled, onSelectedPathChange]
|
|
223
|
+
);
|
|
224
|
+
const refresh = useCallback(async () => {
|
|
225
|
+
setTreeLoading(true);
|
|
226
|
+
try {
|
|
227
|
+
setTree(await port.listTree());
|
|
228
|
+
} finally {
|
|
229
|
+
setTreeLoading(false);
|
|
230
|
+
}
|
|
231
|
+
}, [port]);
|
|
232
|
+
useEffect2(() => {
|
|
233
|
+
void refresh();
|
|
234
|
+
}, [refresh]);
|
|
235
|
+
useEffect2(() => {
|
|
236
|
+
if (!selectedPath) {
|
|
237
|
+
setSelectedFile(null);
|
|
238
|
+
setFileLoading(false);
|
|
239
|
+
loadedPathRef.current = null;
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
let cancelled = false;
|
|
243
|
+
const path = selectedPath;
|
|
244
|
+
setFileLoading(true);
|
|
245
|
+
void (async () => {
|
|
246
|
+
try {
|
|
247
|
+
const file = await port.readFile(path);
|
|
248
|
+
if (!cancelled) setSelectedFile(file);
|
|
249
|
+
} catch {
|
|
250
|
+
if (!cancelled) setSelectedFile(null);
|
|
251
|
+
} finally {
|
|
252
|
+
if (!cancelled) setFileLoading(false);
|
|
253
|
+
}
|
|
254
|
+
})();
|
|
255
|
+
return () => {
|
|
256
|
+
cancelled = true;
|
|
257
|
+
};
|
|
258
|
+
}, [port, selectedPath]);
|
|
259
|
+
useEffect2(() => {
|
|
260
|
+
if (!selectedFile) {
|
|
261
|
+
loadedPathRef.current = null;
|
|
262
|
+
savedContentRef.current = "";
|
|
263
|
+
setRichDraft("");
|
|
264
|
+
setSourceDraft("");
|
|
265
|
+
setEditorMode("rich");
|
|
266
|
+
setIsDirty(false);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const pathChanged = loadedPathRef.current !== selectedFile.path;
|
|
270
|
+
loadedPathRef.current = selectedFile.path;
|
|
271
|
+
savedContentRef.current = selectedFile.content;
|
|
272
|
+
setRichDraft(activeCodec.parse(selectedFile.content));
|
|
273
|
+
setSourceDraft(selectedFile.content);
|
|
274
|
+
if (pathChanged) setEditorMode("rich");
|
|
275
|
+
setIsDirty(false);
|
|
276
|
+
setDockOpen(false);
|
|
277
|
+
}, [selectedFile, activeCodec]);
|
|
278
|
+
const guardedOpen = useCallback(
|
|
279
|
+
(path) => {
|
|
280
|
+
if (path === selectedPath) return;
|
|
281
|
+
if (isDirty) {
|
|
282
|
+
setPendingNav({ type: "open", path });
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
commitPath(path);
|
|
286
|
+
},
|
|
287
|
+
[isDirty, selectedPath, commitPath]
|
|
288
|
+
);
|
|
289
|
+
const guardedClose = useCallback(() => {
|
|
290
|
+
if (isDirty) {
|
|
291
|
+
setPendingNav({ type: "close" });
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
commitPath(null);
|
|
295
|
+
setSelectedFile(null);
|
|
296
|
+
}, [isDirty, commitPath]);
|
|
297
|
+
const confirmDiscard = useCallback(() => {
|
|
298
|
+
const nav = pendingNav;
|
|
299
|
+
setPendingNav(null);
|
|
300
|
+
setIsDirty(false);
|
|
301
|
+
if (!nav) return;
|
|
302
|
+
if (nav.type === "open") {
|
|
303
|
+
commitPath(nav.path);
|
|
304
|
+
} else {
|
|
305
|
+
commitPath(null);
|
|
306
|
+
setSelectedFile(null);
|
|
307
|
+
}
|
|
308
|
+
}, [pendingNav, commitPath]);
|
|
309
|
+
const showRichMode = useCallback(() => {
|
|
310
|
+
setEditorMode((mode) => {
|
|
311
|
+
if (mode === "rich") return mode;
|
|
312
|
+
setRichDraft(activeCodec.parse(sourceDraft));
|
|
313
|
+
setIsDirty(sourceDraft !== savedContentRef.current);
|
|
314
|
+
return "rich";
|
|
315
|
+
});
|
|
316
|
+
}, [activeCodec, sourceDraft]);
|
|
317
|
+
const showSourceMode = useCallback(() => {
|
|
318
|
+
setEditorMode((mode) => {
|
|
319
|
+
if (mode === "source") return mode;
|
|
320
|
+
const content = isDirty ? activeCodec.serialize(richDraft) : savedContentRef.current;
|
|
321
|
+
setSourceDraft(content);
|
|
322
|
+
setIsDirty(content !== savedContentRef.current);
|
|
323
|
+
return "source";
|
|
324
|
+
});
|
|
325
|
+
}, [activeCodec, isDirty, richDraft]);
|
|
326
|
+
const onSourceChange = useCallback((next) => {
|
|
327
|
+
setSourceDraft(next);
|
|
328
|
+
setIsDirty(next !== savedContentRef.current);
|
|
329
|
+
}, []);
|
|
330
|
+
const onRichChange = useCallback((next) => {
|
|
331
|
+
setRichDraft(next);
|
|
332
|
+
setIsDirty(activeCodec.serialize(next) !== savedContentRef.current);
|
|
333
|
+
}, [activeCodec]);
|
|
334
|
+
const saveCurrent = useCallback(async () => {
|
|
335
|
+
if (!selectedFile) return;
|
|
336
|
+
const content = editorMode === "source" ? sourceDraft : activeCodec.serialize(richDraft);
|
|
337
|
+
setSaving(true);
|
|
338
|
+
try {
|
|
339
|
+
await port.writeFile(selectedFile.path, content);
|
|
340
|
+
savedContentRef.current = content;
|
|
341
|
+
setSelectedFile({ ...selectedFile, content });
|
|
342
|
+
setSourceDraft(content);
|
|
343
|
+
setRichDraft(activeCodec.parse(content));
|
|
344
|
+
setIsDirty(false);
|
|
345
|
+
} finally {
|
|
346
|
+
setSaving(false);
|
|
347
|
+
}
|
|
348
|
+
}, [selectedFile, editorMode, sourceDraft, richDraft, activeCodec, port]);
|
|
349
|
+
const handleCreate = useCallback(async () => {
|
|
350
|
+
const trimmed = newPath.trim();
|
|
351
|
+
if (!trimmed) return;
|
|
352
|
+
setCreating(true);
|
|
353
|
+
try {
|
|
354
|
+
const created = await port.createFile(trimmed);
|
|
355
|
+
setCreateOpen(false);
|
|
356
|
+
setNewPath("");
|
|
357
|
+
await refresh();
|
|
358
|
+
commitPath(created);
|
|
359
|
+
} finally {
|
|
360
|
+
setCreating(false);
|
|
361
|
+
}
|
|
362
|
+
}, [newPath, port, refresh, commitPath]);
|
|
363
|
+
const handleDelete = useCallback(async () => {
|
|
364
|
+
if (!selectedFile) return;
|
|
365
|
+
setDeleting(true);
|
|
366
|
+
try {
|
|
367
|
+
await port.deleteFile(selectedFile.path);
|
|
368
|
+
setDeleteOpen(false);
|
|
369
|
+
setIsDirty(false);
|
|
370
|
+
commitPath(null);
|
|
371
|
+
setSelectedFile(null);
|
|
372
|
+
await refresh();
|
|
373
|
+
} finally {
|
|
374
|
+
setDeleting(false);
|
|
375
|
+
}
|
|
376
|
+
}, [selectedFile, port, refresh, commitPath]);
|
|
377
|
+
return /* @__PURE__ */ jsx2(EditorErrorBoundary, { onReset: () => {
|
|
378
|
+
commitPath(null);
|
|
379
|
+
setSelectedFile(null);
|
|
380
|
+
}, children: /* @__PURE__ */ jsxs2("div", { className: `flex min-h-0 flex-1 overflow-hidden ${className ?? ""}`, children: [
|
|
381
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex w-[23rem] min-w-[23rem] flex-col border-r border-border bg-background", children: [
|
|
382
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between gap-3 border-b border-border px-4 py-3", children: [
|
|
383
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
384
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm font-semibold text-foreground", children: "Vault" }),
|
|
385
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-xs text-muted-foreground", children: [
|
|
386
|
+
fileCount,
|
|
387
|
+
" file",
|
|
388
|
+
fileCount === 1 ? "" : "s"
|
|
389
|
+
] })
|
|
390
|
+
] }),
|
|
391
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
392
|
+
/* @__PURE__ */ jsx2(
|
|
393
|
+
"button",
|
|
394
|
+
{
|
|
395
|
+
type: "button",
|
|
396
|
+
"aria-label": "Refresh vault",
|
|
397
|
+
onClick: () => void refresh(),
|
|
398
|
+
className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60",
|
|
399
|
+
children: "\u21BB"
|
|
400
|
+
}
|
|
401
|
+
),
|
|
402
|
+
canWrite && /* @__PURE__ */ jsx2(
|
|
403
|
+
"button",
|
|
404
|
+
{
|
|
405
|
+
type: "button",
|
|
406
|
+
"aria-label": "New vault file",
|
|
407
|
+
onClick: () => setCreateOpen(true),
|
|
408
|
+
className: "inline-flex h-8 w-8 items-center justify-center rounded-md bg-primary text-primary-foreground transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60",
|
|
409
|
+
children: "+"
|
|
410
|
+
}
|
|
411
|
+
)
|
|
412
|
+
] })
|
|
413
|
+
] }),
|
|
414
|
+
/* @__PURE__ */ jsx2("div", { className: "flex-1 overflow-y-auto", children: treeLoading ? /* @__PURE__ */ jsx2(TreeSkeleton, {}) : renderTree({
|
|
415
|
+
root: treeRoot,
|
|
416
|
+
selectedPath: selectedPath ?? void 0,
|
|
417
|
+
onSelect: (path) => {
|
|
418
|
+
if (filePaths.has(path)) guardedOpen(path);
|
|
419
|
+
}
|
|
420
|
+
}) })
|
|
421
|
+
] }),
|
|
422
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden", children: [
|
|
423
|
+
selectedFile && /* @__PURE__ */ jsxs2("div", { className: "flex shrink-0 items-center justify-between border-b border-border bg-card px-4 py-1.5", children: [
|
|
424
|
+
/* @__PURE__ */ jsx2("span", { "data-vault-path": true, className: "truncate text-xs text-muted-foreground", children: selectedFile.path }),
|
|
425
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1", children: [
|
|
426
|
+
canWrite && isMarkdownCapable && /* @__PURE__ */ jsxs2("div", { className: "mr-1 flex items-center gap-1", children: [
|
|
427
|
+
/* @__PURE__ */ jsx2(
|
|
428
|
+
"button",
|
|
429
|
+
{
|
|
430
|
+
type: "button",
|
|
431
|
+
"aria-label": "Edit as rich text",
|
|
432
|
+
"aria-pressed": editorMode === "rich",
|
|
433
|
+
onClick: showRichMode,
|
|
434
|
+
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"}`,
|
|
435
|
+
children: "Rich"
|
|
436
|
+
}
|
|
437
|
+
),
|
|
438
|
+
/* @__PURE__ */ jsx2(
|
|
439
|
+
"button",
|
|
440
|
+
{
|
|
441
|
+
type: "button",
|
|
442
|
+
"aria-label": "Edit as source",
|
|
443
|
+
"aria-pressed": editorMode === "source",
|
|
444
|
+
onClick: showSourceMode,
|
|
445
|
+
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"}`,
|
|
446
|
+
children: "Source"
|
|
447
|
+
}
|
|
448
|
+
)
|
|
449
|
+
] }),
|
|
450
|
+
renderDock && /* @__PURE__ */ jsx2(
|
|
451
|
+
"button",
|
|
452
|
+
{
|
|
453
|
+
type: "button",
|
|
454
|
+
"aria-label": "Discuss with agent",
|
|
455
|
+
"aria-pressed": dockOpen,
|
|
456
|
+
disabled: isDirty,
|
|
457
|
+
title: isDirty ? "Save before discussing with agent" : "Discuss with agent",
|
|
458
|
+
onClick: () => setDockOpen((v) => !v),
|
|
459
|
+
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"}`,
|
|
460
|
+
children: "Discuss"
|
|
461
|
+
}
|
|
462
|
+
),
|
|
463
|
+
canWrite && /* @__PURE__ */ jsx2(
|
|
464
|
+
"button",
|
|
465
|
+
{
|
|
466
|
+
type: "button",
|
|
467
|
+
"aria-label": "Delete this file",
|
|
468
|
+
title: "Delete file",
|
|
469
|
+
onClick: () => setDeleteOpen(true),
|
|
470
|
+
className: "p-1 text-muted-foreground transition-colors hover:text-destructive",
|
|
471
|
+
children: "\u2715"
|
|
472
|
+
}
|
|
473
|
+
)
|
|
474
|
+
] })
|
|
475
|
+
] }),
|
|
476
|
+
/* @__PURE__ */ jsx2("div", { className: "flex-1 overflow-hidden", children: fileLoading ? /* @__PURE__ */ jsx2(EditorSkeleton, {}) : selectedFile && canWrite && isMarkdownCapable && editorMode === "source" ? /* @__PURE__ */ jsx2(
|
|
477
|
+
SourceEditor,
|
|
478
|
+
{
|
|
479
|
+
path: selectedFile.path,
|
|
480
|
+
content: sourceDraft,
|
|
481
|
+
saving,
|
|
482
|
+
dirty: isDirty,
|
|
483
|
+
onChange: onSourceChange,
|
|
484
|
+
onSave: () => void saveCurrent()
|
|
485
|
+
}
|
|
486
|
+
) : selectedFile ? renderArtifact({
|
|
487
|
+
file: selectedFile,
|
|
488
|
+
loading: false,
|
|
489
|
+
mode: editorMode,
|
|
490
|
+
canWrite,
|
|
491
|
+
richDraft,
|
|
492
|
+
dirty: isDirty,
|
|
493
|
+
onRichChange,
|
|
494
|
+
onSave: () => void saveCurrent()
|
|
495
|
+
}) : /* @__PURE__ */ jsx2(EmptyState, {}) })
|
|
496
|
+
] }),
|
|
497
|
+
renderDock && selectedFile && renderDock({
|
|
498
|
+
file: selectedFile,
|
|
499
|
+
open: dockOpen,
|
|
500
|
+
onClose: () => setDockOpen(false)
|
|
501
|
+
}),
|
|
502
|
+
/* @__PURE__ */ jsx2(
|
|
503
|
+
ConfirmDialog,
|
|
504
|
+
{
|
|
505
|
+
open: createOpen,
|
|
506
|
+
title: "Create vault file",
|
|
507
|
+
description: "Add a new document to this vault.",
|
|
508
|
+
confirmLabel: creating ? "Creating\u2026" : "Create",
|
|
509
|
+
confirmDisabled: creating || !newPath.trim(),
|
|
510
|
+
onConfirm: () => void handleCreate(),
|
|
511
|
+
onCancel: () => {
|
|
512
|
+
setCreateOpen(false);
|
|
513
|
+
setNewPath("");
|
|
514
|
+
},
|
|
515
|
+
children: /* @__PURE__ */ jsx2(
|
|
516
|
+
"input",
|
|
517
|
+
{
|
|
518
|
+
value: newPath,
|
|
519
|
+
autoFocus: true,
|
|
520
|
+
onChange: (e) => setNewPath(e.target.value),
|
|
521
|
+
placeholder: "e.g. playbooks/new-strategy.md",
|
|
522
|
+
"aria-label": "New file path",
|
|
523
|
+
className: "h-9 w-full rounded-md border border-border bg-background px-3 text-sm text-foreground outline-none placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-primary/60"
|
|
524
|
+
}
|
|
525
|
+
)
|
|
526
|
+
}
|
|
527
|
+
),
|
|
528
|
+
/* @__PURE__ */ jsx2(
|
|
529
|
+
ConfirmDialog,
|
|
530
|
+
{
|
|
531
|
+
open: deleteOpen,
|
|
532
|
+
title: "Delete file?",
|
|
533
|
+
description: `This permanently removes ${selectedFile?.path ?? "this file"} from the vault.`,
|
|
534
|
+
confirmLabel: deleting ? "Deleting\u2026" : "Delete file",
|
|
535
|
+
confirmDisabled: deleting,
|
|
536
|
+
destructive: true,
|
|
537
|
+
onConfirm: () => void handleDelete(),
|
|
538
|
+
onCancel: () => setDeleteOpen(false)
|
|
539
|
+
}
|
|
540
|
+
),
|
|
541
|
+
/* @__PURE__ */ jsx2(
|
|
542
|
+
ConfirmDialog,
|
|
543
|
+
{
|
|
544
|
+
open: pendingNav !== null,
|
|
545
|
+
title: "Discard unsaved changes?",
|
|
546
|
+
description: "Your edits to this document haven't been saved. Continue and lose them?",
|
|
547
|
+
confirmLabel: "Discard changes",
|
|
548
|
+
destructive: true,
|
|
549
|
+
onConfirm: confirmDiscard,
|
|
550
|
+
onCancel: () => setPendingNav(null)
|
|
551
|
+
}
|
|
552
|
+
)
|
|
553
|
+
] }) });
|
|
554
|
+
}
|
|
555
|
+
function SourceEditor({
|
|
556
|
+
path,
|
|
557
|
+
content,
|
|
558
|
+
saving,
|
|
559
|
+
dirty,
|
|
560
|
+
onChange,
|
|
561
|
+
onSave
|
|
562
|
+
}) {
|
|
563
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex h-full min-h-0 flex-col bg-background", children: [
|
|
564
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between gap-2 border-b border-border px-4 py-2", children: [
|
|
565
|
+
/* @__PURE__ */ jsx2("p", { className: "truncate font-mono text-[11px] text-muted-foreground", children: path }),
|
|
566
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
567
|
+
/* @__PURE__ */ jsx2("span", { className: "rounded-full border border-border bg-background px-2.5 py-1 text-xs text-muted-foreground", children: dirty ? "Unsaved changes" : "Saved" }),
|
|
568
|
+
/* @__PURE__ */ jsx2(
|
|
569
|
+
"button",
|
|
570
|
+
{
|
|
571
|
+
type: "button",
|
|
572
|
+
onClick: onSave,
|
|
573
|
+
disabled: saving || !dirty,
|
|
574
|
+
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",
|
|
575
|
+
children: saving ? "Saving\u2026" : "Save"
|
|
576
|
+
}
|
|
577
|
+
)
|
|
578
|
+
] })
|
|
579
|
+
] }),
|
|
580
|
+
/* @__PURE__ */ jsx2(
|
|
581
|
+
"textarea",
|
|
582
|
+
{
|
|
583
|
+
value: content,
|
|
584
|
+
onChange: (event) => onChange(event.target.value),
|
|
585
|
+
spellCheck: false,
|
|
586
|
+
"aria-label": "Source editor",
|
|
587
|
+
className: "min-h-0 flex-1 resize-none border-0 bg-background p-4 font-mono text-sm leading-6 text-foreground outline-none"
|
|
588
|
+
}
|
|
589
|
+
)
|
|
590
|
+
] });
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
export {
|
|
594
|
+
ConfirmDialog,
|
|
595
|
+
VaultPane
|
|
596
|
+
};
|
|
597
|
+
//# sourceMappingURL=chunk-FNUEUOOZ.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, an error boundary,\n * and an empty state. 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 ReactNode,\n} from 'react'\nimport { ConfirmDialog } from './ConfirmDialog'\nimport type {\n VaultEditorMode,\n VaultFile,\n VaultMarkdownCodec,\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\nfunction collectFilePaths(nodes: VaultTreeNode[], into: Set<string>): Set<string> {\n for (const node of nodes) {\n if (node.type === 'file') into.add(node.path)\n if (node.children) collectFilePaths(node.children, into)\n }\n return into\n}\n\nfunction countFiles(nodes: VaultTreeNode[]): number {\n return nodes.reduce(\n (sum, node) => (node.type === 'file' ? sum + 1 : sum + countFiles(node.children ?? [])),\n 0,\n )\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 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60\"\n >\n Try again\n </button>\n </div>\n )\n }\n return this.props.children\n }\n}\n\nfunction TreeSkeleton() {\n return (\n <div className=\"space-y-2 p-4\" aria-hidden=\"true\">\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 </div>\n )\n}\n\nfunction EditorSkeleton() {\n return (\n <div className=\"space-y-3 p-8\" aria-hidden=\"true\">\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 </div>\n )\n}\n\nfunction EmptyState() {\n return (\n <div className=\"flex h-full flex-col items-center justify-center p-8 text-center\">\n <h3 className=\"text-sm font-medium text-foreground\">Open a vault document</h3>\n <p className=\"mt-1 max-w-xs text-xs text-muted-foreground\">\n Select a file from the directory, or create a new one.\n </p>\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 codec,\n className,\n } = props\n\n const activeCodec = codec ?? IDENTITY_CODEC\n const controlled = controlledPath !== undefined\n const isMarkdownCapable = codec !== undefined\n\n const [tree, setTree] = useState<VaultTreeNode[]>([])\n const [treeLoading, setTreeLoading] = useState(true)\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 [saving, setSaving] = useState(false)\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 [deleteOpen, setDeleteOpen] = useState(false)\n const [deleting, setDeleting] = useState(false)\n const [dockOpen, setDockOpen] = useState(false)\n const [pendingNav, setPendingNav] = useState<PendingNav>(null)\n\n const savedContentRef = useRef('')\n const loadedPathRef = useRef<string | null>(null)\n\n const filePaths = useMemo(() => collectFilePaths(tree, new Set<string>()), [tree])\n const treeRoot = useMemo<VaultTreeNode>(\n () => ({ name: 'Vault', path: '', type: 'directory', children: tree }),\n [tree],\n )\n const fileCount = useMemo(() => countFiles(tree), [tree])\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 refresh = useCallback(async () => {\n setTreeLoading(true)\n try {\n setTree(await port.listTree())\n } finally {\n setTreeLoading(false)\n }\n }, [port])\n\n useEffect(() => {\n void refresh()\n }, [refresh])\n\n useEffect(() => {\n if (!selectedPath) {\n setSelectedFile(null)\n setFileLoading(false)\n loadedPathRef.current = null\n return\n }\n let cancelled = false\n const path = selectedPath\n setFileLoading(true)\n void (async () => {\n try {\n const file = await port.readFile(path)\n if (!cancelled) setSelectedFile(file)\n } catch {\n if (!cancelled) setSelectedFile(null)\n } finally {\n if (!cancelled) setFileLoading(false)\n }\n })()\n return () => {\n cancelled = true\n }\n }, [port, selectedPath])\n\n useEffect(() => {\n if (!selectedFile) {\n loadedPathRef.current = null\n savedContentRef.current = ''\n setRichDraft('')\n setSourceDraft('')\n setEditorMode('rich')\n setIsDirty(false)\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 setDockOpen(false)\n }, [selectedFile, 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 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 setSourceDraft(next)\n setIsDirty(next !== savedContentRef.current)\n }, [])\n\n const onRichChange = useCallback((next: VaultRichParts) => {\n setRichDraft(next)\n setIsDirty(activeCodec.serialize(next) !== savedContentRef.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 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 } finally {\n setSaving(false)\n }\n }, [selectedFile, editorMode, sourceDraft, richDraft, activeCodec, port])\n\n const handleCreate = useCallback(async () => {\n const trimmed = newPath.trim()\n if (!trimmed) return\n setCreating(true)\n try {\n const created = await port.createFile(trimmed)\n setCreateOpen(false)\n setNewPath('')\n await refresh()\n commitPath(created)\n } finally {\n setCreating(false)\n }\n }, [newPath, port, refresh, commitPath])\n\n const handleDelete = useCallback(async () => {\n if (!selectedFile) return\n setDeleting(true)\n try {\n await port.deleteFile(selectedFile.path)\n setDeleteOpen(false)\n setIsDirty(false)\n commitPath(null)\n setSelectedFile(null)\n await refresh()\n } finally {\n setDeleting(false)\n }\n }, [selectedFile, port, refresh, commitPath])\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 justify-between gap-3 border-b border-border px-4 py-3\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">Vault</span>\n <span className=\"text-xs text-muted-foreground\">\n {fileCount} file{fileCount === 1 ? '' : 's'}\n </span>\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\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 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60\"\n >\n ↻\n </button>\n {canWrite && (\n <button\n type=\"button\"\n aria-label=\"New vault file\"\n onClick={() => 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 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60\"\n >\n +\n </button>\n )}\n </div>\n </div>\n <div className=\"flex-1 overflow-y-auto\">\n {treeLoading ? (\n <TreeSkeleton />\n ) : (\n renderTree({\n root: treeRoot,\n selectedPath: selectedPath ?? undefined,\n onSelect: (path) => { if (filePaths.has(path)) guardedOpen(path) },\n })\n )}\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 bg-card px-4 py-1.5\">\n <span data-vault-path className=\"truncate text-xs text-muted-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 && (\n <button\n type=\"button\"\n aria-label=\"Discuss with agent\"\n aria-pressed={dockOpen}\n disabled={isDirty}\n title={isDirty ? 'Save before discussing with agent' : 'Discuss with agent'}\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 Discuss\n </button>\n )}\n {canWrite && (\n <button\n type=\"button\"\n aria-label=\"Delete this file\"\n title=\"Delete file\"\n onClick={() => setDeleteOpen(true)}\n className=\"p-1 text-muted-foreground transition-colors hover:text-destructive\"\n >\n ✕\n </button>\n )}\n </div>\n </div>\n )}\n <div className=\"flex-1 overflow-hidden\">\n {fileLoading ? (\n <EditorSkeleton />\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 ) : (\n <EmptyState />\n )}\n </div>\n </div>\n\n {renderDock && selectedFile && renderDock({\n file: selectedFile,\n open: dockOpen,\n onClose: () => setDockOpen(false),\n })}\n\n <ConfirmDialog\n open={createOpen}\n title=\"Create vault file\"\n description=\"Add a new document to this vault.\"\n confirmLabel={creating ? 'Creating…' : 'Create'}\n confirmDisabled={creating || !newPath.trim()}\n onConfirm={() => void handleCreate()}\n onCancel={() => { setCreateOpen(false); setNewPath('') }}\n >\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 outline-none placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-primary/60\"\n />\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)}\n />\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-[11px] 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 className=\"min-h-0 flex-1 resize-none border-0 bg-background p-4 font-mono text-sm leading-6 text-foreground outline-none\"\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 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60\"\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 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/60 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","useRef","useEffect"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { V as VaultArtifactRenderProps, a as VaultDataPort, b as VaultDockRenderProps, c as VaultEditorMode, d as VaultFile, e as VaultMarkdownCodec, f as VaultPane, g as VaultPaneProps, h as VaultRichParts, i as VaultTreeNode, j as VaultTreeRenderProps } from '../VaultPane-By2l5lol.js';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface ConfirmDialogProps {
|
|
6
|
+
open: boolean;
|
|
7
|
+
title: string;
|
|
8
|
+
description?: ReactNode;
|
|
9
|
+
confirmLabel?: string;
|
|
10
|
+
cancelLabel?: string;
|
|
11
|
+
/** Styles the confirm button as a destructive action. */
|
|
12
|
+
destructive?: boolean;
|
|
13
|
+
/** Disables the confirm button (e.g. while the action is in flight). */
|
|
14
|
+
confirmDisabled?: boolean;
|
|
15
|
+
onConfirm: () => void;
|
|
16
|
+
onCancel: () => void;
|
|
17
|
+
/** Optional body (e.g. an input field for the create flow). */
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
declare function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, destructive, confirmDisabled, onConfirm, onCancel, children, }: ConfirmDialogProps): react.JSX.Element | null;
|
|
21
|
+
|
|
22
|
+
export { ConfirmDialog, type ConfirmDialogProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/vault/lazy.tsx"],"sourcesContent":["/**\n * Code-split entry for the vault surface. Products that don't need the vault on\n * initial load import `VaultPaneLazy` (a `React.lazy` handle) instead of the\n * component directly, so the pane chunk loads on first render. Mount inside a\n * `<Suspense>` boundary; the product provides the fallback.\n */\n\nimport { lazy } from 'react'\nimport type { VaultPaneProps } from './contracts'\n\nexport type { VaultPaneProps }\n\nexport const VaultPaneLazy = lazy(\n () => import('./VaultPane').then((m) => ({ default: m.VaultPane })),\n)\n"],"mappings":";AAOA,SAAS,YAAY;AAKd,IAAM,gBAAgB;AAAA,EAC3B,MAAM,OAAO,0BAAa,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE;AACpE;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"packageManager": "pnpm@10.33.4",
|
|
5
5
|
"description": "Application-shell framework for Tangle agent products: a bounded tool loop, the structured agent→app tool side channel, integration-hub client, per-workspace billing, and crypto — composed over the Tangle agent substrate through typed seams.",
|
|
6
6
|
"keywords": [
|
|
@@ -278,6 +278,16 @@
|
|
|
278
278
|
"import": "./dist/intakes-react/lazy.js",
|
|
279
279
|
"default": "./dist/intakes-react/lazy.js"
|
|
280
280
|
},
|
|
281
|
+
"./vault": {
|
|
282
|
+
"types": "./dist/vault/index.d.ts",
|
|
283
|
+
"import": "./dist/vault/index.js",
|
|
284
|
+
"default": "./dist/vault/index.js"
|
|
285
|
+
},
|
|
286
|
+
"./vault/lazy": {
|
|
287
|
+
"types": "./dist/vault/lazy.d.ts",
|
|
288
|
+
"import": "./dist/vault/lazy.js",
|
|
289
|
+
"default": "./dist/vault/lazy.js"
|
|
290
|
+
},
|
|
281
291
|
"./theme": {
|
|
282
292
|
"types": "./dist/theme/index.d.ts",
|
|
283
293
|
"import": "./dist/theme/index.js",
|