@tangle-network/sandbox-ui 2.0.19 → 2.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/VirtualList-DLh2JE0F.js +205 -0
- package/dist/event-stream-DNEbvx4s.d.ts +2 -0
- package/dist/globals.css +19 -0
- package/dist/hooks.d.ts +2 -2
- package/dist/hooks.js +2 -2
- package/dist/{index-DRLVHl-o.d.ts → index-1qlc9-S2.d.ts} +16 -2
- package/dist/{index-BnaVprN6.d.ts → index-DxMX-DlX.d.ts} +62 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +7 -6
- package/dist/{record-Bqt1kE_Q.js → record-CnxPRyxC.js} +89 -234
- package/dist/run/live.d.ts +1 -1
- package/dist/run/live.js +26 -28
- package/dist/run/record.d.ts +2 -2
- package/dist/run/record.js +3 -1
- package/dist/run.d.ts +4 -4
- package/dist/run.js +4 -3
- package/dist/styles.css +19 -0
- package/dist/{trace-workspace-C8dHRBDV.js → trace-workspace-DkakKRLV.js} +64 -78
- package/dist/{tree-data-C8CNt4WE.js → tree-data-B_IXAIgg.js} +171 -121
- package/dist/use-follow-tail-Ckx5ZSV2.js +1 -0
- package/dist/vault-tree.js +1 -1
- package/dist/{workspace-CzikYt_y.js → workspace--GvnZNpH.js} +1 -1
- package/dist/{workspace-files-pane-DB9Nvwh4.js → workspace-files-pane-C0PeY6rY.js} +12 -12
- package/dist/workspace-viewer.js +9277 -8990
- package/dist/workspace.js +2 -2
- package/package.json +6 -6
- package/dist/agent-stream-CBZ2fXJ2.d.ts +0 -66
|
@@ -2,14 +2,16 @@ import { t as cn } from "./utils-BER_bdgE.js";
|
|
|
2
2
|
import { i as modelBrandFor, t as ModelBrandStack } from "./model-brand-BQlarCIo.js";
|
|
3
3
|
import { t as ProviderIcon } from "./provider-logo-CPKRPHcS.js";
|
|
4
4
|
import { t as AgentGraph$1 } from "./AgentGraph-BGWx9hhS.js";
|
|
5
|
+
import { t as useFollowTail } from "./use-follow-tail-Ckx5ZSV2.js";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import {
|
|
7
|
+
import { useMemo, useReducer, useRef, useState } from "react";
|
|
7
8
|
import { X } from "lucide-react";
|
|
8
9
|
import { activityTiming, ambientStyle, syncAmbient } from "@tangle-network/charts/react/agent-graph/presentation";
|
|
9
10
|
import { AgentTimeline } from "@tangle-network/ui/chat";
|
|
10
11
|
import { InlineThinkingItem, runStatus } from "@tangle-network/ui/run";
|
|
11
12
|
import { FlowWaterfall, toolGlyph } from "@tangle-network/charts/react";
|
|
12
13
|
import { LatestEvents } from "@tangle-network/charts/react/agent-graph";
|
|
14
|
+
import { useEventStream } from "@tangle-network/ui/hooks";
|
|
13
15
|
// src/run/trace-waterfall.tsx
|
|
14
16
|
/** Agent and model spans show their lab/host mark; tool spans show their provider's mark. Unknown keeps the kind glyph. */
|
|
15
17
|
function traceSpanMark(span) {
|
|
@@ -205,59 +207,61 @@ function useAgentStream(url, openEventSource) {
|
|
|
205
207
|
lastSeq: 0,
|
|
206
208
|
alive: false
|
|
207
209
|
});
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
210
|
+
const cursor = useRef({ lastSeq: 0 });
|
|
211
|
+
useEventStream(url, {
|
|
212
|
+
opener: openEventSource,
|
|
213
|
+
after: () => cursor.current.lastSeq,
|
|
214
|
+
onStart: () => {
|
|
215
|
+
cursor.current = { lastSeq: 0 };
|
|
216
|
+
dispatch({ type: "reset" });
|
|
217
|
+
},
|
|
218
|
+
onLiveChange: (live) => {
|
|
219
|
+
if (!live) dispatch({ type: "unreachable" });
|
|
220
|
+
},
|
|
221
|
+
events: {
|
|
222
|
+
rows: (message) => {
|
|
223
|
+
try {
|
|
224
|
+
const data = JSON.parse(message.data);
|
|
225
|
+
if (!Array.isArray(data.events)) throw new Error("Invalid agent rows stream");
|
|
226
|
+
if (data.generation !== void 0 && data.generation !== cursor.current.generation) cursor.current = {
|
|
227
|
+
lastSeq: 0,
|
|
228
|
+
generation: data.generation
|
|
229
|
+
};
|
|
230
|
+
cursor.current.lastSeq = Math.max(cursor.current.lastSeq, data.lastSeq ?? 0, ...data.events.map((row) => row.seq));
|
|
231
|
+
dispatch({
|
|
232
|
+
type: "rows",
|
|
233
|
+
generation: data.generation,
|
|
234
|
+
rows: data.events,
|
|
235
|
+
alive: data.alive
|
|
236
|
+
});
|
|
237
|
+
} catch (cause) {
|
|
238
|
+
dispatch({
|
|
239
|
+
type: "error",
|
|
240
|
+
message: String(cause)
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
reset: (message) => {
|
|
245
|
+
try {
|
|
246
|
+
const { generation } = JSON.parse(message.data);
|
|
247
|
+
cursor.current = {
|
|
248
|
+
lastSeq: 0,
|
|
249
|
+
generation
|
|
250
|
+
};
|
|
251
|
+
dispatch({
|
|
252
|
+
type: "reset",
|
|
253
|
+
generation
|
|
254
|
+
});
|
|
255
|
+
} catch (cause) {
|
|
256
|
+
dispatch({
|
|
257
|
+
type: "error",
|
|
258
|
+
message: String(cause)
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
end: () => dispatch({ type: "end" })
|
|
263
|
+
}
|
|
264
|
+
});
|
|
261
265
|
return state;
|
|
262
266
|
}
|
|
263
267
|
// src/run/trace-workspace.tsx
|
|
@@ -438,18 +442,10 @@ function TraceWorkspace({ trace, streamUrl, openEventSource, events, onTimeChang
|
|
|
438
442
|
const live = stream.alive && !stream.error && cursor === null;
|
|
439
443
|
const items = useMemo(() => timelineItems(shown, live), [shown, live]);
|
|
440
444
|
const scroller = useRef(null);
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
if (!element) return;
|
|
446
|
-
if (pinned.current) element.scrollTop = element.scrollHeight;
|
|
447
|
-
else setUnseen(true);
|
|
448
|
-
}, [items.length, items[items.length - 1]]);
|
|
449
|
-
useEffect(() => {
|
|
450
|
-
pinned.current = true;
|
|
451
|
-
setUnseen(false);
|
|
452
|
-
}, [selected]);
|
|
445
|
+
const { unseen, jump } = useFollowTail(scroller, {
|
|
446
|
+
identity: showConversation ? selected : void 0,
|
|
447
|
+
content: items
|
|
448
|
+
});
|
|
453
449
|
return /* @__PURE__ */ jsxs("div", {
|
|
454
450
|
className: cn("sandbox-trace-workspace flex min-h-0 flex-col gap-3", className),
|
|
455
451
|
children: [
|
|
@@ -580,11 +576,6 @@ function TraceWorkspace({ trace, streamUrl, openEventSource, events, onTimeChang
|
|
|
580
576
|
}),
|
|
581
577
|
/* @__PURE__ */ jsx("div", {
|
|
582
578
|
ref: scroller,
|
|
583
|
-
onScroll: (event) => {
|
|
584
|
-
const element = event.currentTarget;
|
|
585
|
-
pinned.current = element.scrollHeight - element.scrollTop - element.clientHeight < 48;
|
|
586
|
-
if (pinned.current) setUnseen(false);
|
|
587
|
-
},
|
|
588
579
|
"data-primary-content": "",
|
|
589
580
|
className: "min-h-0 flex-1 overflow-y-auto px-3 py-2",
|
|
590
581
|
children: streamUrl && (cursor === null || origin !== void 0) ? /* @__PURE__ */ jsx(AgentTimeline, {
|
|
@@ -598,12 +589,7 @@ function TraceWorkspace({ trace, streamUrl, openEventSource, events, onTimeChang
|
|
|
598
589
|
}),
|
|
599
590
|
unseen && /* @__PURE__ */ jsx("button", {
|
|
600
591
|
type: "button",
|
|
601
|
-
onClick: () =>
|
|
602
|
-
const element = scroller.current;
|
|
603
|
-
if (element) element.scrollTop = element.scrollHeight;
|
|
604
|
-
pinned.current = true;
|
|
605
|
-
setUnseen(false);
|
|
606
|
-
},
|
|
592
|
+
onClick: () => jump(),
|
|
607
593
|
className: "absolute bottom-3 left-1/2 -translate-x-1/2 rounded-full border border-border bg-background px-3 py-1 text-xs shadow-sm",
|
|
608
594
|
children: "New output"
|
|
609
595
|
})
|
|
@@ -612,4 +598,4 @@ function TraceWorkspace({ trace, streamUrl, openEventSource, events, onTimeChang
|
|
|
612
598
|
]
|
|
613
599
|
});
|
|
614
600
|
}
|
|
615
|
-
export {
|
|
601
|
+
export { useEventStream as a, useAgentStream as i, LatestEvents as n, TraceWaterfall as o, foldAgentRows as r, traceSpanMark as s, TraceWorkspace as t };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as revealInScroller } from "./reveal-in-scroller-CzKwuqCG.js";
|
|
2
|
+
import { t as VirtualList } from "./VirtualList-DLh2JE0F.js";
|
|
2
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
4
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
5
|
import { BookOpen, Braces, ChevronRight, File, FileCode, FileCog, FileImage, FileLock, FileSpreadsheet, FileTerminal, FileText, Folder, FolderOpen, GitBranch, Package, Scale } from "lucide-react";
|
|
@@ -10,8 +11,8 @@ import { BookOpen, Braces, ChevronRight, File, FileCode, FileCog, FileImage, Fil
|
|
|
10
11
|
* trees given the same key share one remembered expansion.
|
|
11
12
|
*
|
|
12
13
|
* Rendering is lazy: only the children of expanded folders are walked or
|
|
13
|
-
* mounted
|
|
14
|
-
*
|
|
14
|
+
* mounted; folders retain their child paging, and collections over 100 visible
|
|
15
|
+
* rows use the shared viewport list. Keyboard navigation reveals offscreen rows.
|
|
15
16
|
*
|
|
16
17
|
* The tree follows the WAI-ARIA tree pattern with a single tab stop: arrow keys
|
|
17
18
|
* move between rows, Right/Left expand, collapse or move to a child or parent,
|
|
@@ -294,7 +295,10 @@ function VaultTree({ root, selectedPath, activeFolder, onSelect, onFolderToggle,
|
|
|
294
295
|
const [focusedPath, setFocusedPath] = useState(null);
|
|
295
296
|
const rowRefs = useRef(/* @__PURE__ */ new Map());
|
|
296
297
|
const pendingFocusRef = useRef(null);
|
|
297
|
-
const
|
|
298
|
+
const treeRef = useRef(null), scroller = useRef(null);
|
|
299
|
+
const [target, setTarget] = useState();
|
|
300
|
+
const previousPaths = useRef(null);
|
|
301
|
+
const revealed = useRef(void 0);
|
|
298
302
|
const index = useMemo(() => {
|
|
299
303
|
const nodes = /* @__PURE__ */ new Map();
|
|
300
304
|
const parents = /* @__PURE__ */ new Map();
|
|
@@ -376,35 +380,48 @@ function VaultTree({ root, selectedPath, activeFolder, onSelect, onFolderToggle,
|
|
|
376
380
|
onFolderToggle
|
|
377
381
|
]);
|
|
378
382
|
useEffect(() => {
|
|
379
|
-
if (!selectedPath || !index.nodes.has(selectedPath))
|
|
383
|
+
if (!selectedPath || !index.nodes.has(selectedPath)) {
|
|
384
|
+
revealed.current = void 0;
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (revealed.current?.path === selectedPath && revealed.current.scope === storageKey) return;
|
|
388
|
+
revealed.current = {
|
|
389
|
+
scope: storageKey,
|
|
390
|
+
path: selectedPath
|
|
391
|
+
};
|
|
380
392
|
const ancestors = [];
|
|
381
393
|
for (let parent = index.parents.get(selectedPath) ?? null; parent; parent = index.parents.get(parent) ?? null) ancestors.push(parent);
|
|
382
|
-
|
|
394
|
+
setTarget(selectedPath);
|
|
395
|
+
setPageLimits((current) => {
|
|
396
|
+
const next = new Map(current);
|
|
397
|
+
for (const path of [selectedPath, ...ancestors]) {
|
|
398
|
+
const parent = index.parents.get(path) ?? null;
|
|
399
|
+
if (parent) next.set(parent, Math.max(next.get(parent) ?? 200, (index.children.get(parent)?.findIndex((n) => n.path === path) ?? -1) + 1));
|
|
400
|
+
}
|
|
401
|
+
return next;
|
|
402
|
+
});
|
|
383
403
|
if (ancestors.some((path) => !expandedPaths.has(path))) updateExpanded((next) => {
|
|
384
404
|
for (const path of ancestors) next.add(path);
|
|
385
405
|
});
|
|
386
|
-
}, [
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
const row = rowRefs.current.get(reveal);
|
|
392
|
-
if (row) revealInScroller(row);
|
|
393
|
-
}
|
|
394
|
-
const focus = pendingFocusRef.current;
|
|
395
|
-
if (focus && rowRefs.current.has(focus)) {
|
|
396
|
-
pendingFocusRef.current = null;
|
|
397
|
-
rowRefs.current.get(focus)?.focus();
|
|
398
|
-
}
|
|
399
|
-
}, [rows]);
|
|
406
|
+
}, [
|
|
407
|
+
selectedPath,
|
|
408
|
+
index,
|
|
409
|
+
storageKey
|
|
410
|
+
]);
|
|
400
411
|
const visiblePaths = useMemo(() => new Set(nodeRows.map((row) => row.node.path)), [nodeRows]);
|
|
401
412
|
const tabStop = focusedPath && visiblePaths.has(focusedPath) && focusedPath || selectedPath && visiblePaths.has(selectedPath) && selectedPath || nodeRows[0]?.node.path || null;
|
|
402
413
|
const focusRow = useCallback((path) => {
|
|
403
414
|
if (!path) return;
|
|
404
415
|
setFocusedPath(path);
|
|
405
416
|
const element = rowRefs.current.get(path);
|
|
406
|
-
if (element)
|
|
407
|
-
|
|
417
|
+
if (element) {
|
|
418
|
+
setTarget(void 0);
|
|
419
|
+
element.focus({ preventScroll: true });
|
|
420
|
+
revealInScroller(element);
|
|
421
|
+
} else {
|
|
422
|
+
pendingFocusRef.current = path;
|
|
423
|
+
setTarget(path);
|
|
424
|
+
}
|
|
408
425
|
}, []);
|
|
409
426
|
const activate = useCallback((node) => {
|
|
410
427
|
setFocusedPath(node.path);
|
|
@@ -424,19 +441,14 @@ function VaultTree({ root, selectedPath, activeFolder, onSelect, onFolderToggle,
|
|
|
424
441
|
const dir = node.type === "directory";
|
|
425
442
|
const open = dir && isOpen(node.path);
|
|
426
443
|
let handled = true;
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
focusRow(nodeRows[0]?.node.path);
|
|
436
|
-
break;
|
|
437
|
-
case "End":
|
|
438
|
-
focusRow(nodeRows[nodeRows.length - 1]?.node.path);
|
|
439
|
-
break;
|
|
444
|
+
const moves = {
|
|
445
|
+
ArrowDown: nodeRows[at + 1]?.node.path,
|
|
446
|
+
ArrowUp: nodeRows[at - 1]?.node.path,
|
|
447
|
+
Home: nodeRows[0]?.node.path,
|
|
448
|
+
End: nodeRows[nodeRows.length - 1]?.node.path
|
|
449
|
+
};
|
|
450
|
+
if (event.key in moves) focusRow(moves[event.key]);
|
|
451
|
+
else switch (event.key) {
|
|
440
452
|
case "ArrowRight":
|
|
441
453
|
if (dir && !open) setFolderOpen(node.path, true);
|
|
442
454
|
else if (open) {
|
|
@@ -480,97 +492,135 @@ function VaultTree({ root, selectedPath, activeFolder, onSelect, onFolderToggle,
|
|
|
480
492
|
return out;
|
|
481
493
|
}, [status]);
|
|
482
494
|
const openParent = selectedPath ? index.parents.get(selectedPath) ?? null : null;
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
495
|
+
useEffect(() => {
|
|
496
|
+
previousPaths.current = new Set(index.nodes.keys());
|
|
497
|
+
}, [index]);
|
|
498
|
+
const keyOf = (row) => row.kind === "node" ? row.node.path : `more:${row.parent}`;
|
|
499
|
+
const render = (row) => {
|
|
500
|
+
if (row.kind === "more") return /* @__PURE__ */ jsxs("button", {
|
|
501
|
+
type: "button",
|
|
502
|
+
onClick: () => {
|
|
503
|
+
focusRow(index.children.get(row.parent)?.[(index.children.get(row.parent)?.length ?? 0) - row.hidden]?.path);
|
|
504
|
+
setPageLimits((current) => {
|
|
492
505
|
const next = new Map(current);
|
|
493
506
|
next.set(row.parent, Math.max(200, current.get(row.parent) ?? 0) + 200);
|
|
494
507
|
return next;
|
|
508
|
+
});
|
|
509
|
+
},
|
|
510
|
+
style: { paddingInlineStart: row.depth * INDENT + 28 },
|
|
511
|
+
className: "flex min-h-8 w-full items-center rounded-md pr-2 text-left text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
512
|
+
children: [
|
|
513
|
+
"Show ",
|
|
514
|
+
Math.min(row.hidden, 200),
|
|
515
|
+
" more of ",
|
|
516
|
+
row.hidden
|
|
517
|
+
]
|
|
518
|
+
}, `more:${row.parent}`);
|
|
519
|
+
const { node, depth } = row;
|
|
520
|
+
const dir = node.type === "directory";
|
|
521
|
+
const open = dir && isOpen(node.path);
|
|
522
|
+
const selected = !dir && node.path === selectedPath;
|
|
523
|
+
const active = dir && node.path === activeFolder;
|
|
524
|
+
const kind = dir ? {
|
|
525
|
+
Icon: open ? FolderOpen : Folder,
|
|
526
|
+
ink: "text-muted-foreground"
|
|
527
|
+
} : fileKind(node.name);
|
|
528
|
+
const Icon = kind.Icon;
|
|
529
|
+
const change = dir ? open ? void 0 : changedFolders.get(node.path) : status?.[node.path];
|
|
530
|
+
const ancestors = [];
|
|
531
|
+
for (let at = row.parent; at; at = index.parents.get(at) ?? null) ancestors.unshift(at);
|
|
532
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
533
|
+
ref: (element) => {
|
|
534
|
+
if (element) {
|
|
535
|
+
rowRefs.current.set(node.path, element);
|
|
536
|
+
if (previousPaths.current && !previousPaths.current.has(node.path) && !window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
537
|
+
previousPaths.current.add(node.path);
|
|
538
|
+
element.classList.add("agent-arrive");
|
|
539
|
+
Promise.allSettled(element.getAnimations().map((animation) => animation.finished)).then(() => element.classList.remove("agent-arrive"));
|
|
540
|
+
}
|
|
541
|
+
if (pendingFocusRef.current === node.path) {
|
|
542
|
+
pendingFocusRef.current = null;
|
|
543
|
+
element.focus({ preventScroll: true });
|
|
544
|
+
}
|
|
545
|
+
if (target === node.path && rows.length <= 100) revealInScroller(element);
|
|
546
|
+
} else rowRefs.current.delete(node.path);
|
|
547
|
+
},
|
|
548
|
+
role: "treeitem",
|
|
549
|
+
"aria-level": depth + 1,
|
|
550
|
+
"aria-posinset": row.posInSet,
|
|
551
|
+
"aria-setsize": row.setSize,
|
|
552
|
+
"aria-expanded": dir ? open : void 0,
|
|
553
|
+
"aria-selected": dir ? void 0 : selected,
|
|
554
|
+
"aria-current": active ? "true" : void 0,
|
|
555
|
+
tabIndex: node.path === tabStop ? 0 : -1,
|
|
556
|
+
title: node.path,
|
|
557
|
+
"data-vault-tree-item": node.type,
|
|
558
|
+
"data-path": node.path,
|
|
559
|
+
"data-selected": selected ? "true" : void 0,
|
|
560
|
+
onClick: () => activate(node),
|
|
561
|
+
onFocus: () => setFocusedPath(node.path),
|
|
562
|
+
onKeyDown: (event) => onKeyDown(event, node),
|
|
563
|
+
style: { paddingInlineStart: depth * INDENT + 4 },
|
|
564
|
+
className: [
|
|
565
|
+
"group relative flex min-h-8 w-full cursor-pointer select-none items-center gap-1.5 rounded-md pr-2 text-sm transition-colors [@media(pointer:coarse)]:min-h-10",
|
|
566
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
567
|
+
selected ? "bg-[var(--ix-sel-bg)] font-medium text-[var(--accent-text)]" : active ? "bg-muted font-medium text-foreground" : "text-foreground hover:bg-[var(--ix-hover-bg)]"
|
|
568
|
+
].join(" "),
|
|
569
|
+
children: [
|
|
570
|
+
ancestors.map((folder, level) => /* @__PURE__ */ jsx("span", {
|
|
571
|
+
"aria-hidden": "true",
|
|
572
|
+
className: `pointer-events-none absolute inset-y-0 w-px ${folder === openParent ? "bg-[var(--border-strong)]" : "bg-border"}`,
|
|
573
|
+
style: { left: level * INDENT + 12 }
|
|
574
|
+
}, folder)),
|
|
575
|
+
/* @__PURE__ */ jsx("span", {
|
|
576
|
+
"aria-hidden": "true",
|
|
577
|
+
className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground",
|
|
578
|
+
children: dir && /* @__PURE__ */ jsx(ChevronRight, { className: `size-3.5 transition-transform duration-fast ${open ? "rotate-90" : ""}` })
|
|
579
|
+
}),
|
|
580
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
581
|
+
"aria-hidden": "true",
|
|
582
|
+
className: `size-4 shrink-0 ${kind.ink}`
|
|
495
583
|
}),
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
"
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
onFocus: () => setFocusedPath(node.path),
|
|
537
|
-
onKeyDown: (event) => onKeyDown(event, node),
|
|
538
|
-
style: { paddingInlineStart: depth * INDENT + 4 },
|
|
539
|
-
className: [
|
|
540
|
-
"group relative flex min-h-8 w-full cursor-pointer select-none items-center gap-1.5 rounded-md pr-2 text-sm transition-colors [@media(pointer:coarse)]:min-h-10",
|
|
541
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
542
|
-
selected ? "bg-[var(--ix-sel-bg)] font-medium text-[var(--accent-text)]" : active ? "bg-muted font-medium text-foreground" : "text-foreground hover:bg-[var(--ix-hover-bg)]"
|
|
543
|
-
].join(" "),
|
|
544
|
-
children: [
|
|
545
|
-
ancestors.map((folder, level) => /* @__PURE__ */ jsx("span", {
|
|
546
|
-
"aria-hidden": "true",
|
|
547
|
-
className: `pointer-events-none absolute inset-y-0 w-px ${folder === openParent ? "bg-[var(--border-strong)]" : "bg-border"}`,
|
|
548
|
-
style: { left: level * INDENT + 12 }
|
|
549
|
-
}, folder)),
|
|
550
|
-
/* @__PURE__ */ jsx("span", {
|
|
551
|
-
"aria-hidden": "true",
|
|
552
|
-
className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground",
|
|
553
|
-
children: dir && /* @__PURE__ */ jsx(ChevronRight, { className: `size-3.5 transition-transform duration-fast ${open ? "rotate-90" : ""}` })
|
|
554
|
-
}),
|
|
555
|
-
/* @__PURE__ */ jsx(Icon, {
|
|
556
|
-
"aria-hidden": "true",
|
|
557
|
-
className: `size-4 shrink-0 ${kind.ink}`
|
|
558
|
-
}),
|
|
559
|
-
/* @__PURE__ */ jsx("span", {
|
|
560
|
-
className: "min-w-0 flex-1 truncate",
|
|
561
|
-
children: node.name
|
|
562
|
-
}),
|
|
563
|
-
change && (dir ? /* @__PURE__ */ jsx("span", {
|
|
564
|
-
"aria-label": `holds ${change === "added" ? "added" : "changed"} files`,
|
|
565
|
-
className: `size-1.5 shrink-0 rounded-full ${change === "added" ? "bg-[var(--surface-success-text)]" : "bg-[var(--surface-warning-text)]"}`
|
|
566
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
567
|
-
"aria-label": change,
|
|
568
|
-
className: `w-3.5 shrink-0 text-center font-mono text-xs font-semibold ${CHANGE[change].ink}`,
|
|
569
|
-
children: CHANGE[change].letter
|
|
570
|
-
}))
|
|
571
|
-
]
|
|
572
|
-
}, node.path);
|
|
573
|
-
})
|
|
584
|
+
/* @__PURE__ */ jsx("span", {
|
|
585
|
+
className: "min-w-0 flex-1 truncate",
|
|
586
|
+
children: node.name
|
|
587
|
+
}),
|
|
588
|
+
change && (dir ? /* @__PURE__ */ jsx("span", {
|
|
589
|
+
"aria-label": `holds ${change === "added" ? "added" : "changed"} files`,
|
|
590
|
+
className: `size-1.5 shrink-0 rounded-full ${change === "added" ? "bg-[var(--surface-success-text)]" : "bg-[var(--surface-warning-text)]"}`
|
|
591
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
592
|
+
"aria-label": change,
|
|
593
|
+
className: `w-3.5 shrink-0 text-center font-mono text-sm font-semibold ${CHANGE[change].ink}`,
|
|
594
|
+
children: CHANGE[change].letter
|
|
595
|
+
}))
|
|
596
|
+
]
|
|
597
|
+
}, node.path);
|
|
598
|
+
};
|
|
599
|
+
return /* @__PURE__ */ jsx("div", {
|
|
600
|
+
ref: (element) => {
|
|
601
|
+
treeRef.current = element;
|
|
602
|
+
if (!element) return;
|
|
603
|
+
let parent = element?.parentElement ?? null;
|
|
604
|
+
while (parent && !/auto|scroll/.test(getComputedStyle(parent).overflowY)) parent = parent.parentElement;
|
|
605
|
+
scroller.current = parent ?? document.scrollingElement;
|
|
606
|
+
},
|
|
607
|
+
role: "tree",
|
|
608
|
+
"aria-label": label,
|
|
609
|
+
"data-vault-tree-rows": true,
|
|
610
|
+
className,
|
|
611
|
+
children: /* @__PURE__ */ jsx(VirtualList, {
|
|
612
|
+
items: rows,
|
|
613
|
+
keyOf,
|
|
614
|
+
render,
|
|
615
|
+
scroller,
|
|
616
|
+
origin: treeRef,
|
|
617
|
+
estimate: 33,
|
|
618
|
+
overscan: 320,
|
|
619
|
+
target,
|
|
620
|
+
targetAlign: "nearest",
|
|
621
|
+
virtualize: rows.length > 100,
|
|
622
|
+
keepMounted: tabStop ?? void 0
|
|
623
|
+
}, storageKey)
|
|
574
624
|
});
|
|
575
625
|
}
|
|
576
626
|
// src/vault-tree/tree-data.ts
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useFollowTail as t } from "@tangle-network/ui/hooks";
|
package/dist/vault-tree.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { r as VAULT_TREE_CHILD_PAGE, i as VaultTree, t as fileTreeFromPaths, n as filterFileNodes } from "./tree-data-
|
|
1
|
+
export { r as VAULT_TREE_CHILD_PAGE, i as VaultTree, t as fileTreeFromPaths, n as filterFileNodes } from "./tree-data-B_IXAIgg.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as cn$1 } from "./utils-BER_bdgE.js";
|
|
2
2
|
import { r as ShellHeader } from "./shell-header-CwqDzC4I.js";
|
|
3
3
|
import { t as MOTION_CONTROL } from "./motion-2Ine0j_s.js";
|
|
4
|
-
import "./workspace-files-pane-
|
|
4
|
+
import "./workspace-files-pane-C0PeY6rY.js";
|
|
5
5
|
import { ArtifactPane, ArtifactPane as ArtifactPane$1, EmptyState, Input, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@tangle-network/ui/primitives";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { Markdown } from "@tangle-network/ui/markdown";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as cn } from "./utils-BER_bdgE.js";
|
|
2
|
-
import { i as VaultTree, n as filterFileNodes, t as fileTreeFromPaths } from "./tree-data-
|
|
2
|
+
import { i as VaultTree, n as filterFileNodes, t as fileTreeFromPaths } from "./tree-data-B_IXAIgg.js";
|
|
3
3
|
import { Button, EmptyState, Input, SegmentedControl } from "@tangle-network/ui/primitives";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
@@ -263,7 +263,7 @@ function WorkspaceFilesPane({ root, paths, selectedPath, onSelect, preview, onBa
|
|
|
263
263
|
preview,
|
|
264
264
|
split,
|
|
265
265
|
tabs: split && tabs,
|
|
266
|
-
|
|
266
|
+
files: index,
|
|
267
267
|
backRef,
|
|
268
268
|
onBack,
|
|
269
269
|
onOpen: (path) => onSelect?.(path, index.get(path)),
|
|
@@ -277,7 +277,7 @@ function WorkspaceFilesPane({ root, paths, selectedPath, onSelect, preview, onBa
|
|
|
277
277
|
}
|
|
278
278
|
const baseName = (path) => path.replace(/\/+$/, "").split("/").pop() || path;
|
|
279
279
|
/** The editor side of the pane: open-file tabs, a File | Diff toggle, the full-screen control, and the open file. */
|
|
280
|
-
function FilesViewer({ preview, split, tabs,
|
|
280
|
+
function FilesViewer({ preview, split, tabs, files, backRef, onBack, onOpen, expand }) {
|
|
281
281
|
const path = preview?.path;
|
|
282
282
|
const [open, setOpen] = useState(() => path ? [path] : []);
|
|
283
283
|
useEffect(() => {
|
|
@@ -285,12 +285,12 @@ function FilesViewer({ preview, split, tabs, empty, backRef, onBack, onOpen, exp
|
|
|
285
285
|
}, [path]);
|
|
286
286
|
const [mode, setMode] = useState("file");
|
|
287
287
|
useEffect(() => setMode("file"), [path]);
|
|
288
|
+
const shown = open.filter((entry) => entry === path || files.get(entry)?.type === "file");
|
|
288
289
|
const close = (target) => {
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
setOpen(rest);
|
|
290
|
+
const rest = shown.filter((entry) => entry !== target);
|
|
291
|
+
setOpen((paths) => paths.filter((entry) => entry !== target));
|
|
292
292
|
if (target !== path) return;
|
|
293
|
-
const neighbour = rest[Math.min(
|
|
293
|
+
const neighbour = rest[Math.min(shown.indexOf(target), rest.length - 1)];
|
|
294
294
|
if (neighbour) onOpen(neighbour);
|
|
295
295
|
else onBack?.();
|
|
296
296
|
};
|
|
@@ -299,7 +299,7 @@ function FilesViewer({ preview, split, tabs, empty, backRef, onBack, onOpen, exp
|
|
|
299
299
|
return /* @__PURE__ */ jsxs("div", {
|
|
300
300
|
className: "flex min-h-0 min-w-0 flex-1 flex-col",
|
|
301
301
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
302
|
-
className: cn(HEADER_ROW, "sticky top-0 z-10 gap-2 pr-[var(--files-inset)]", !(tabs &&
|
|
302
|
+
className: cn(HEADER_ROW, "sticky top-0 z-10 gap-2 pr-[var(--files-inset)]", !(tabs && shown.length > 0) && "pl-[var(--files-inset)]", !split && "h-auto min-h-11 flex-wrap py-1.5 pointer-coarse:h-auto"),
|
|
303
303
|
children: [
|
|
304
304
|
onBack && !split && preview && /* @__PURE__ */ jsxs(Button, {
|
|
305
305
|
ref: backRef,
|
|
@@ -310,8 +310,8 @@ function FilesViewer({ preview, split, tabs, empty, backRef, onBack, onOpen, exp
|
|
|
310
310
|
className: "-ml-2 shrink-0 gap-1 px-2 text-muted-foreground",
|
|
311
311
|
children: [/* @__PURE__ */ jsx(ArrowLeft, { "aria-hidden": "true" }), "Back to files"]
|
|
312
312
|
}),
|
|
313
|
-
tabs &&
|
|
314
|
-
tabs:
|
|
313
|
+
tabs && shown.length > 0 ? /* @__PURE__ */ jsx(FileTabs, {
|
|
314
|
+
tabs: shown.map((entry) => ({
|
|
315
315
|
id: entry,
|
|
316
316
|
name: baseName(entry),
|
|
317
317
|
path: entry
|
|
@@ -339,7 +339,7 @@ function FilesViewer({ preview, split, tabs, empty, backRef, onBack, onOpen, exp
|
|
|
339
339
|
className: cn("shrink-0 p-0.5 [&>button]:py-1", !split && "order-last")
|
|
340
340
|
}),
|
|
341
341
|
preview?.actions && /* @__PURE__ */ jsx("div", {
|
|
342
|
-
className: "flex
|
|
342
|
+
className: cn("flex min-w-0 max-w-full flex-wrap items-center gap-2", !split && "order-last"),
|
|
343
343
|
children: preview.actions
|
|
344
344
|
}),
|
|
345
345
|
expand && /* @__PURE__ */ jsx(Button, {
|
|
@@ -360,7 +360,7 @@ function FilesViewer({ preview, split, tabs, empty, backRef, onBack, onOpen, exp
|
|
|
360
360
|
children: mode === "diff" && compare ? compare.content : preview.content
|
|
361
361
|
}) : /* @__PURE__ */ jsx("div", {
|
|
362
362
|
className: "flex min-h-0 min-w-0 flex-1 items-center justify-center p-6 text-sm text-muted-foreground",
|
|
363
|
-
children:
|
|
363
|
+
children: files.size === 0 ? null : "Select a file to open it here."
|
|
364
364
|
})]
|
|
365
365
|
});
|
|
366
366
|
}
|