@tangle-network/ui 11.12.0 → 11.13.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/CHANGELOG.md +24 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/auth/auth.d.ts +53 -0
- package/dist/{auth-DOETfnd9.js → auth/auth.js} +7 -37
- package/dist/auth/login-layout.d.ts +20 -0
- package/dist/auth/login-layout.js +36 -0
- package/dist/auth.d.ts +2 -1
- package/dist/auth.js +2 -1
- package/dist/chat/agent-timeline.d.ts +83 -0
- package/dist/chat/agent-timeline.js +236 -0
- package/dist/chat/chat-container.d.ts +51 -0
- package/dist/chat/chat-container.js +309 -0
- package/dist/chat/chat-message.d.ts +22 -0
- package/dist/chat/chat-message.js +38 -0
- package/dist/chat/message-list.d.ts +32 -0
- package/dist/chat/message-list.js +37 -0
- package/dist/chat/thinking-indicator.d.ts +6 -0
- package/dist/chat/thinking-indicator.js +38 -0
- package/dist/chat/user-message.d.ts +21 -0
- package/dist/chat/user-message.js +42 -0
- package/dist/chat.d.ts +6 -1
- package/dist/chat.js +6 -1
- package/dist/editor/document-editor-pane.d.ts +37 -0
- package/dist/editor/document-editor-pane.js +199 -0
- package/dist/editor/editor-lazy.js +37 -0
- package/dist/editor/editor-loading.js +21 -0
- package/dist/editor/editor-peers.d.ts +6 -0
- package/dist/editor/editor-peers.js +155 -0
- package/dist/editor/editor-provider.d.ts +97 -0
- package/dist/editor/editor-provider.js +253 -0
- package/dist/editor/editor-toolbar.d.ts +11 -0
- package/dist/editor/editor-toolbar.js +106 -0
- package/dist/editor/markdown-conversion.js +23 -0
- package/dist/editor/markdown-document-editor.js +103 -0
- package/dist/editor/tiptap-editor.d.ts +45 -0
- package/dist/editor/tiptap-editor.js +271 -0
- package/dist/editor/use-editor.d.ts +67 -0
- package/dist/editor/use-editor.js +158 -0
- package/dist/editor.d.ts +6 -119
- package/dist/editor.js +5 -1
- package/dist/files/file-artifact-pane.d.ts +47 -0
- package/dist/files/file-artifact-pane.js +114 -0
- package/dist/files/file-format.d.ts +51 -0
- package/dist/{file-format-BgXbr-Ib.js → files/file-format.js} +1 -1
- package/dist/files/file-preview.d.ts +27 -0
- package/dist/files/file-preview.js +359 -0
- package/dist/files/file-tabs.d.ts +19 -0
- package/dist/files/file-tabs.js +48 -0
- package/dist/files/file-tree.d.ts +31 -0
- package/dist/files/file-tree.js +135 -0
- package/dist/files/rich-file-tree.d.ts +62 -0
- package/dist/files/rich-file-tree.js +122 -0
- package/dist/files.d.ts +6 -1
- package/dist/files.js +6 -2
- package/dist/hooks/use-auth.d.ts +40 -0
- package/dist/hooks/use-auth.js +91 -0
- package/dist/hooks/use-auto-scroll.d.ts +11 -0
- package/dist/hooks/use-auto-scroll.js +48 -0
- package/dist/hooks/use-dropdown-menu.d.ts +12 -0
- package/dist/hooks/use-dropdown-menu.js +31 -0
- package/dist/hooks/use-live-time.d.ts +7 -0
- package/dist/hooks/use-live-time.js +22 -0
- package/dist/hooks/use-realtime-session.d.ts +32 -0
- package/dist/hooks/use-realtime-session.js +235 -0
- package/dist/hooks/use-run-collapse-state.d.ts +13 -0
- package/dist/hooks/use-run-collapse-state.js +24 -0
- package/dist/hooks/use-run-groups.d.ts +11 -0
- package/dist/hooks/use-run-groups.js +85 -0
- package/dist/hooks/use-sdk-session.d.ts +59 -0
- package/dist/hooks/use-sdk-session.js +322 -0
- package/dist/hooks/use-sse-stream.d.ts +124 -0
- package/dist/hooks/use-sse-stream.js +229 -0
- package/dist/hooks/use-tool-call-stream.d.ts +23 -0
- package/dist/hooks/use-tool-call-stream.js +75 -0
- package/dist/hooks.d.ts +11 -49
- package/dist/hooks.js +10 -110
- package/dist/index.d.ts +99 -25
- package/dist/index.js +86 -36
- package/dist/lib/focus.d.ts +55 -0
- package/dist/{focus-BcE_SHqz.js → lib/focus.js} +1 -1
- package/dist/lib/utils.d.ts +4 -0
- package/dist/{utils-C_uf36nf.js → lib/utils.js} +1 -1
- package/dist/{code-block-B9miUPht.d.ts → markdown/code-block.d.ts} +5 -6
- package/dist/{code-block-B36KVUSN.js → markdown/code-block.js} +60 -55
- package/dist/{markdown-C0atSabr.d.ts → markdown/markdown.d.ts} +4 -5
- package/dist/{markdown-Db08KAYF.js → markdown/markdown.js} +3 -3
- package/dist/markdown.d.ts +2 -2
- package/dist/markdown.js +2 -2
- package/dist/{openui-artifact-renderer-fkBQaoLO.d.ts → openui/openui-artifact-renderer.d.ts} +20 -21
- package/dist/{openui-artifact-renderer-DG_i2lOR.js → openui/openui-artifact-renderer.js} +9 -7
- package/dist/{schema-BpW9rSSG.js → openui/schema-compiled.js} +2 -354
- package/dist/{schema-DAstk-J4.d.ts → openui/schema-data.d.ts} +3 -24
- package/dist/openui/schema-data.js +206 -0
- package/dist/openui-schema.d.ts +22 -3
- package/dist/openui-schema.js +138 -1
- package/dist/openui.d.ts +3 -2
- package/dist/openui.js +3 -2
- package/dist/{artifact-pane-BL_DFWNl.d.ts → primitives/artifact-pane.d.ts} +3 -4
- package/dist/{artifact-pane-DMXT9a8U.js → primitives/artifact-pane.js} +2 -2
- package/dist/primitives/avatar.d.ts +8 -0
- package/dist/primitives/avatar.js +25 -0
- package/dist/primitives/badge.d.ts +22 -0
- package/dist/primitives/badge.js +47 -0
- package/dist/{button-yoIv77e2.d.ts → primitives/button.d.ts} +2 -2
- package/dist/primitives/button.js +113 -0
- package/dist/primitives/card.d.ts +18 -0
- package/dist/primitives/card.js +52 -0
- package/dist/primitives/code-block.d.ts +6 -0
- package/dist/primitives/code-block.js +13 -0
- package/dist/primitives/dialog.d.ts +23 -0
- package/dist/primitives/dialog.js +59 -0
- package/dist/primitives/drop-zone.d.ts +23 -0
- package/dist/primitives/drop-zone.js +104 -0
- package/dist/primitives/dropdown-menu.d.ts +29 -0
- package/dist/{dropdown-menu-BpcLa5vF.js → primitives/dropdown-menu.js} +2 -23
- package/dist/primitives/empty-state.d.ts +11 -0
- package/dist/primitives/empty-state.js +32 -0
- package/dist/primitives/heading.d.ts +23 -0
- package/dist/primitives/heading.js +38 -0
- package/dist/primitives/input.d.ts +23 -0
- package/dist/primitives/input.js +110 -0
- package/dist/primitives/label.d.ts +6 -0
- package/dist/primitives/label.js +16 -0
- package/dist/primitives/metric-strip.d.ts +48 -0
- package/dist/primitives/metric-strip.js +52 -0
- package/dist/primitives/page-header.d.ts +25 -0
- package/dist/primitives/page-header.js +47 -0
- package/dist/primitives/page-shell.d.ts +14 -0
- package/dist/primitives/page-shell.js +17 -0
- package/dist/primitives/progress.d.ts +9 -0
- package/dist/primitives/progress.js +29 -0
- package/dist/primitives/segmented-control.d.ts +40 -0
- package/dist/primitives/segmented-control.js +57 -0
- package/dist/primitives/select.d.ts +15 -0
- package/dist/primitives/select.js +74 -0
- package/dist/primitives/sidebar-drop-zone.d.ts +21 -0
- package/dist/primitives/sidebar-drop-zone.js +88 -0
- package/dist/primitives/skeleton.d.ts +10 -0
- package/dist/primitives/skeleton.js +50 -0
- package/dist/primitives/stat-card.d.ts +16 -0
- package/dist/primitives/stat-card.js +60 -0
- package/dist/primitives/status-pill.d.ts +44 -0
- package/dist/primitives/status-pill.js +119 -0
- package/dist/primitives/switch.d.ts +6 -0
- package/dist/primitives/switch.js +16 -0
- package/dist/primitives/table.d.ts +22 -0
- package/dist/primitives/table.js +63 -0
- package/dist/primitives/tabs.d.ts +13 -0
- package/dist/{tabs-BVHR6NkO.js → primitives/tabs.js} +3 -3
- package/dist/primitives/terminal-display.d.ts +25 -0
- package/dist/primitives/terminal-display.js +109 -0
- package/dist/primitives/text-shimmer.d.ts +16 -0
- package/dist/{text-shimmer-BUUo6I-g.js → primitives/text-shimmer.js} +2 -2
- package/dist/primitives/theme-toggle.d.ts +11 -0
- package/dist/primitives/theme-toggle.js +154 -0
- package/dist/primitives/toast.d.ts +29 -0
- package/dist/primitives/toast.js +142 -0
- package/dist/primitives/toolbar.d.ts +55 -0
- package/dist/primitives/toolbar.js +37 -0
- package/dist/primitives/upload-progress.d.ts +23 -0
- package/dist/primitives/upload-progress.js +72 -0
- package/dist/primitives.d.ts +35 -5
- package/dist/primitives.js +35 -9
- package/dist/{index-COgqsFAQ.d.ts → redaction/redacted-document.d.ts} +6 -7
- package/dist/{redaction-CGGB2ENG.js → redaction/redacted-document.js} +2 -2
- package/dist/redaction.d.ts +1 -1
- package/dist/redaction.js +1 -1
- package/dist/run/expandable-content.js +41 -0
- package/dist/run/expanded-tool-detail.d.ts +12 -0
- package/dist/run/expanded-tool-detail.js +163 -0
- package/dist/run/inline-thinking-item.d.ts +11 -0
- package/dist/run/inline-thinking-item.js +60 -0
- package/dist/run/inline-tool-item.d.ts +25 -0
- package/dist/run/inline-tool-item.js +63 -0
- package/dist/run/run-group.d.ts +26 -0
- package/dist/{run-group-BWGeesgs.js → run/run-group.js} +9 -60
- package/dist/run/run-item-primitives.d.ts +5 -0
- package/dist/{run-ZsIKPA6J.js → run/run-item-primitives.js} +2 -2
- package/dist/run/run-row-shell.d.ts +53 -0
- package/dist/run/run-row-shell.js +114 -0
- package/dist/{tool-call-feed-BeB1_4pX.d.ts → run/tool-call-feed.d.ts} +7 -12
- package/dist/{tool-call-feed-BpmMLpPX.js → run/tool-call-feed.js} +4 -4
- package/dist/run/tool-call-step.d.ts +5 -0
- package/dist/run/tool-call-step.js +82 -0
- package/dist/run.d.ts +8 -2
- package/dist/run.js +7 -4
- package/dist/sdk-hooks.d.ts +8 -1
- package/dist/sdk-hooks.js +8 -2
- package/dist/stores/active-sessions-store.d.ts +83 -0
- package/dist/{active-sessions-store-Gt1R0rFG.js → stores/active-sessions-store.js} +1 -1
- package/dist/stores/chat-store.d.ts +14 -0
- package/dist/stores/chat-store.js +33 -0
- package/dist/stores.d.ts +3 -16
- package/dist/stores.js +2 -33
- package/dist/tool-previews/command-preview.d.ts +11 -0
- package/dist/tool-previews/command-preview.js +91 -0
- package/dist/tool-previews/diff-preview.d.ts +7 -0
- package/dist/tool-previews/diff-preview.js +76 -0
- package/dist/tool-previews/glob-results-preview.d.ts +7 -0
- package/dist/tool-previews/glob-results-preview.js +53 -0
- package/dist/tool-previews/grep-results-preview.d.ts +7 -0
- package/dist/tool-previews/grep-results-preview.js +99 -0
- package/dist/tool-previews/preview-primitives.js +58 -0
- package/dist/tool-previews/question-preview.d.ts +7 -0
- package/dist/tool-previews/question-preview.js +63 -0
- package/dist/tool-previews/web-search-preview.d.ts +7 -0
- package/dist/tool-previews/web-search-preview.js +78 -0
- package/dist/tool-previews/write-file-preview.d.ts +11 -0
- package/dist/tool-previews/write-file-preview.js +52 -0
- package/dist/tool-previews.d.ts +7 -1
- package/dist/tool-previews.js +7 -1
- package/dist/{branding-26d5ARIr.d.ts → types/branding.d.ts} +2 -3
- package/dist/{message-vhUI0c5G.d.ts → types/message.d.ts} +2 -3
- package/dist/{parts-5mhy9yJ3.d.ts → types/parts.d.ts} +8 -9
- package/dist/{run-OyWmIDqu.d.ts → types/run.d.ts} +9 -10
- package/dist/{tool-display-DgmL5rIU.d.ts → types/tool-display.d.ts} +5 -6
- package/dist/types.d.ts +5 -5
- package/dist/utils/copy-text.d.ts +7 -0
- package/dist/{utils-Bl_CZ0Qp.js → utils/copy-text.js} +1 -11
- package/dist/utils/format.d.ts +22 -0
- package/dist/{format-DfcLWqMa.js → utils/format.js} +1 -1
- package/dist/utils/time-ago.d.ts +3 -0
- package/dist/utils/time-ago.js +11 -0
- package/dist/utils/tool-display.d.ts +16 -0
- package/dist/{tool-display-BAuAVa43.js → utils/tool-display.js} +1 -1
- package/dist/utils.d.ts +6 -1
- package/dist/utils.js +6 -5
- package/package.json +2 -2
- package/src/files/rich-file-tree.stories.tsx +1 -1
- package/src/files/rich-file-tree.tsx +12 -9
- package/src/markdown/code-block.test.tsx +80 -2
- package/src/markdown/code-block.tsx +76 -80
- package/src/primitives/button.stories.tsx +37 -1
- package/src/primitives/button.test.tsx +230 -0
- package/src/primitives/button.tsx +62 -14
- package/src/primitives/card-anatomy.stories.tsx +51 -0
- package/src/primitives/card.test.tsx +71 -0
- package/src/primitives/card.tsx +25 -13
- package/src/primitives/heading.stories.tsx +35 -0
- package/src/primitives/heading.test.tsx +56 -0
- package/src/primitives/heading.tsx +76 -0
- package/src/primitives/index.ts +8 -0
- package/src/primitives/input.stories.tsx +28 -0
- package/src/primitives/input.test.tsx +161 -0
- package/src/primitives/input.tsx +34 -28
- package/src/primitives/page-header.stories.tsx +51 -0
- package/src/primitives/page-header.test.tsx +48 -0
- package/src/primitives/page-header.tsx +35 -35
- package/src/primitives/page-shell.stories.tsx +89 -0
- package/src/primitives/page-shell.test.tsx +24 -0
- package/src/primitives/page-shell.tsx +26 -0
- package/src/primitives/table-wrapper.stories.tsx +54 -0
- package/src/primitives/table.test.tsx +72 -0
- package/src/primitives/table.tsx +33 -12
- package/src/primitives/theme-toggle.test.tsx +167 -0
- package/src/primitives/theme-toggle.tsx +111 -39
- package/dist/active-sessions-store-nl70ZnMC.d.ts +0 -84
- package/dist/button-C87nEe2R.js +0 -78
- package/dist/chat-DDvF2oGQ.js +0 -672
- package/dist/diff-preview-BcK3nRXb.js +0 -533
- package/dist/document-editor-pane-BilJfiCo.d.ts +0 -136
- package/dist/document-editor-pane-POsq5Q0o.js +0 -1279
- package/dist/files-hywocVZz.js +0 -753
- package/dist/index-2UntyjBb.d.ts +0 -52
- package/dist/index-BgUHilZm.d.ts +0 -108
- package/dist/index-CJ8wRfiC.d.ts +0 -236
- package/dist/index-CPDET_s1.d.ts +0 -549
- package/dist/index-Cg6gYAqh.d.ts +0 -73
- package/dist/index-Cs7j8V7l.d.ts +0 -203
- package/dist/index-DjKxO357.d.ts +0 -128
- package/dist/primitives-Bx59fT-U.js +0 -1239
- package/dist/table-Bss73DhB.js +0 -146
- package/dist/tool-call-step-DNebqhmX.js +0 -434
- package/dist/use-auto-scroll-C5Pjeqon.js +0 -153
- package/dist/use-sse-stream-DjqRuDft.js +0 -884
- package/dist/use-sse-stream-Dm6R5YWz.d.ts +0 -282
package/dist/files-hywocVZz.js
DELETED
|
@@ -1,753 +0,0 @@
|
|
|
1
|
-
import { a as focusRingInset, i as focusRing } from "./focus-BcE_SHqz.js";
|
|
2
|
-
import { t as cn } from "./utils-C_uf36nf.js";
|
|
3
|
-
import { t as Button } from "./button-C87nEe2R.js";
|
|
4
|
-
import { t as ArtifactPane } from "./artifact-pane-DMXT9a8U.js";
|
|
5
|
-
import { n as CopyButton, t as CodeBlock } from "./code-block-B36KVUSN.js";
|
|
6
|
-
import { t as formatBytes } from "./format-DfcLWqMa.js";
|
|
7
|
-
import { i as getFormatLabel, n as fileExtension, o as resolveFilePreviewKind, r as getCodeLanguage, t as detectFileFormat } from "./file-format-BgXbr-Ib.js";
|
|
8
|
-
import { t as Markdown } from "./markdown-Db08KAYF.js";
|
|
9
|
-
import { Suspense, lazy, useEffect, useMemo, useState } from "react";
|
|
10
|
-
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
import { ChevronRight, Download, File, FileCode, FileImage, FileJson, FileSpreadsheet, FileText, Folder, FolderOpen, Music, X } from "lucide-react";
|
|
12
|
-
import { FileTree, useFileTree } from "@pierre/trees/react";
|
|
13
|
-
//#region src/files/file-tree.tsx
|
|
14
|
-
/**
|
|
15
|
-
* FileTree — directory browser with file type icons.
|
|
16
|
-
*
|
|
17
|
-
* Renders a hierarchical file system view. Clicking a file
|
|
18
|
-
* triggers onSelect with the full path.
|
|
19
|
-
*/
|
|
20
|
-
function isNodeVisible(node, visibility) {
|
|
21
|
-
if (!visibility) return true;
|
|
22
|
-
if (visibility.hiddenPaths?.includes(node.path)) return false;
|
|
23
|
-
if (visibility.hiddenPathPrefixes?.some((prefix) => node.path === prefix || node.path.startsWith(`${prefix}/`))) return false;
|
|
24
|
-
return visibility.isVisible ? visibility.isVisible(node) : true;
|
|
25
|
-
}
|
|
26
|
-
function filterFileTree(root, visibility) {
|
|
27
|
-
if (!isNodeVisible(root, visibility)) return null;
|
|
28
|
-
if (root.type === "file") return root;
|
|
29
|
-
const children = (root.children ?? []).map((child) => filterFileTree(child, visibility)).filter((child) => child !== null);
|
|
30
|
-
if (root.children && root.children.length > 0 && children.length === 0) return null;
|
|
31
|
-
return {
|
|
32
|
-
...root,
|
|
33
|
-
children
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
const FILE_ICONS = {
|
|
37
|
-
pdf: FileText,
|
|
38
|
-
csv: FileSpreadsheet,
|
|
39
|
-
xlsx: FileSpreadsheet,
|
|
40
|
-
xls: FileSpreadsheet,
|
|
41
|
-
py: FileCode,
|
|
42
|
-
ts: FileCode,
|
|
43
|
-
js: FileCode,
|
|
44
|
-
json: FileJson,
|
|
45
|
-
yaml: FileCode,
|
|
46
|
-
yml: FileCode,
|
|
47
|
-
md: FileText,
|
|
48
|
-
txt: FileText,
|
|
49
|
-
png: FileImage,
|
|
50
|
-
jpg: FileImage,
|
|
51
|
-
jpeg: FileImage,
|
|
52
|
-
gif: FileImage,
|
|
53
|
-
svg: FileImage
|
|
54
|
-
};
|
|
55
|
-
function getFileIcon(name) {
|
|
56
|
-
const ext = name.split(".").pop()?.toLowerCase() || "";
|
|
57
|
-
return FILE_ICONS[ext] || File;
|
|
58
|
-
}
|
|
59
|
-
function getFileColor(name) {
|
|
60
|
-
switch (name.split(".").pop()?.toLowerCase() || "") {
|
|
61
|
-
case "pdf": return "text-red-400";
|
|
62
|
-
case "py": return "text-yellow-400";
|
|
63
|
-
case "ts":
|
|
64
|
-
case "js": return "text-blue-400";
|
|
65
|
-
case "json": return "text-green-400";
|
|
66
|
-
case "yaml":
|
|
67
|
-
case "yml": return "text-[var(--accent-text)]";
|
|
68
|
-
case "csv":
|
|
69
|
-
case "xlsx": return "text-emerald-400";
|
|
70
|
-
case "md": return "text-foreground";
|
|
71
|
-
default: return "text-muted-foreground";
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
function TreeNode({ node, depth, selectedPath, onSelect, defaultExpanded }) {
|
|
75
|
-
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
76
|
-
const isSelected = node.path === selectedPath;
|
|
77
|
-
const isDir = node.type === "directory";
|
|
78
|
-
const handleClick = () => {
|
|
79
|
-
if (isDir) setExpanded(!expanded);
|
|
80
|
-
onSelect?.(node.path, node);
|
|
81
|
-
};
|
|
82
|
-
const Icon = isDir ? expanded ? FolderOpen : Folder : getFileIcon(node.name);
|
|
83
|
-
const iconColor = isDir ? "text-primary" : getFileColor(node.name);
|
|
84
|
-
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("button", {
|
|
85
|
-
type: "button",
|
|
86
|
-
className: cn("flex items-center gap-1.5 w-full text-left px-2 py-[2px] cursor-pointer text-[13px] transition-colors", "appearance-none bg-transparent border-none", "hover:bg-accent", isSelected ? "bg-primary/15 text-foreground" : "text-foreground"),
|
|
87
|
-
style: { paddingLeft: `${depth * 16 + 8}px` },
|
|
88
|
-
onClick: handleClick,
|
|
89
|
-
"aria-expanded": isDir ? expanded : void 0,
|
|
90
|
-
children: [
|
|
91
|
-
isDir && /* @__PURE__ */ jsx(ChevronRight, { className: cn("h-3 w-3 shrink-0 text-muted-foreground transition-transform", expanded && "rotate-90") }),
|
|
92
|
-
!isDir && /* @__PURE__ */ jsx("span", { className: "w-3" }),
|
|
93
|
-
/* @__PURE__ */ jsx(Icon, { className: cn("h-4 w-4 shrink-0", iconColor) }),
|
|
94
|
-
/* @__PURE__ */ jsx("span", {
|
|
95
|
-
className: "truncate",
|
|
96
|
-
children: node.name
|
|
97
|
-
}),
|
|
98
|
-
node.size !== void 0 && !isDir && /* @__PURE__ */ jsx("span", {
|
|
99
|
-
className: "text-muted-foreground text-xs ml-auto tabular-nums",
|
|
100
|
-
children: formatSize(node.size)
|
|
101
|
-
})
|
|
102
|
-
]
|
|
103
|
-
}), isDir && expanded && node.children && /* @__PURE__ */ jsx("div", { children: node.children.sort((a, b) => {
|
|
104
|
-
if (a.type !== b.type) return a.type === "directory" ? -1 : 1;
|
|
105
|
-
return a.name.localeCompare(b.name);
|
|
106
|
-
}).map((child) => /* @__PURE__ */ jsx(TreeNode, {
|
|
107
|
-
node: child,
|
|
108
|
-
depth: depth + 1,
|
|
109
|
-
selectedPath,
|
|
110
|
-
onSelect,
|
|
111
|
-
defaultExpanded
|
|
112
|
-
}, child.path)) })] });
|
|
113
|
-
}
|
|
114
|
-
function formatSize(bytes) {
|
|
115
|
-
if (bytes < 1024) return `${bytes}B`;
|
|
116
|
-
if (bytes < 1048576) return `${(bytes / 1024).toFixed(0)}K`;
|
|
117
|
-
return `${(bytes / 1048576).toFixed(1)}M`;
|
|
118
|
-
}
|
|
119
|
-
function FileTree$1({ root, selectedPath, onSelect, className, defaultExpanded = true, visibility }) {
|
|
120
|
-
const visibleRoot = filterFileTree(root, visibility);
|
|
121
|
-
if (!visibleRoot) return null;
|
|
122
|
-
return /* @__PURE__ */ jsx("div", {
|
|
123
|
-
className: cn("text-sm font-sans", className),
|
|
124
|
-
children: visibleRoot.children ? visibleRoot.children.sort((a, b) => {
|
|
125
|
-
if (a.type !== b.type) return a.type === "directory" ? -1 : 1;
|
|
126
|
-
return a.name.localeCompare(b.name);
|
|
127
|
-
}).map((child) => /* @__PURE__ */ jsx(TreeNode, {
|
|
128
|
-
node: child,
|
|
129
|
-
depth: 0,
|
|
130
|
-
selectedPath,
|
|
131
|
-
onSelect,
|
|
132
|
-
defaultExpanded
|
|
133
|
-
}, child.path)) : /* @__PURE__ */ jsx(TreeNode, {
|
|
134
|
-
node: visibleRoot,
|
|
135
|
-
depth: 0,
|
|
136
|
-
selectedPath,
|
|
137
|
-
onSelect,
|
|
138
|
-
defaultExpanded
|
|
139
|
-
})
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
//#endregion
|
|
143
|
-
//#region src/files/rich-file-tree.tsx
|
|
144
|
-
/**
|
|
145
|
-
* RichFileTree — feature-rich file browser built on @pierre/trees.
|
|
146
|
-
*
|
|
147
|
-
* Why this exists alongside the existing FileTree:
|
|
148
|
-
* - Built-in search (cmd-K-style fuzzy filter)
|
|
149
|
-
* - Virtualized rendering for vaults with thousands of files
|
|
150
|
-
* - Git-status overlays per row (modified / added / staged)
|
|
151
|
-
* - Right-click + button-lane context menus with custom item rendering
|
|
152
|
-
* - VS Code-style icons via @pierre/vscode-icons (optional)
|
|
153
|
-
*
|
|
154
|
-
* The existing FileTree stays as-is for simple cases. RichFileTree is the
|
|
155
|
-
* upgrade path when a consumer's vault grows past a few hundred files or
|
|
156
|
-
* needs richer affordances.
|
|
157
|
-
*
|
|
158
|
-
* Pierre renders inside a shadow DOM to keep its CSS isolated. We bridge
|
|
159
|
-
* the host theme via CSS variables on the host element below — the tree
|
|
160
|
-
* picks them up through `--trees-*-override` overrides.
|
|
161
|
-
*/
|
|
162
|
-
/**
|
|
163
|
-
* Map a sandbox-ui design token (e.g. `--accent-surface-soft`) to a CSS
|
|
164
|
-
* `var(--token)` reference. Pierre's CSS-variable surface accepts any
|
|
165
|
-
* valid CSS color expression, so passing `var(--token)` lets the host
|
|
166
|
-
* theme propagate through without us having to read computed styles.
|
|
167
|
-
*/
|
|
168
|
-
function cssVarFromToken(name) {
|
|
169
|
-
return `var(${name})`;
|
|
170
|
-
}
|
|
171
|
-
const DEFAULT_THEME = {
|
|
172
|
-
selectedBg: cssVarFromToken("--accent-surface-soft"),
|
|
173
|
-
selectedFg: cssVarFromToken("--accent-text"),
|
|
174
|
-
fg: cssVarFromToken("--foreground"),
|
|
175
|
-
hoverBg: cssVarFromToken("--muted"),
|
|
176
|
-
border: cssVarFromToken("--border"),
|
|
177
|
-
mutedFg: cssVarFromToken("--muted-foreground")
|
|
178
|
-
};
|
|
179
|
-
/**
|
|
180
|
-
* Walk a recursive FileNode and return a flat list of canonical paths.
|
|
181
|
-
*
|
|
182
|
-
* Pierre infers directory structure from path segments — passing both
|
|
183
|
-
* `dir` and `dir/file.md` collides because `dir` looks like a file.
|
|
184
|
-
* We emit only files; pure-directory leaves get a trailing slash so
|
|
185
|
-
* Pierre keeps them as folders even when they have no children.
|
|
186
|
-
*/
|
|
187
|
-
function flattenFileNode(node, out = []) {
|
|
188
|
-
if (node.type === "file" && node.path) {
|
|
189
|
-
out.push(node.path);
|
|
190
|
-
return out;
|
|
191
|
-
}
|
|
192
|
-
if (node.type === "directory") {
|
|
193
|
-
if (node.children?.length) {
|
|
194
|
-
for (const child of node.children) flattenFileNode(child, out);
|
|
195
|
-
return out;
|
|
196
|
-
}
|
|
197
|
-
if (node.path) out.push(`${node.path}/`);
|
|
198
|
-
}
|
|
199
|
-
return out;
|
|
200
|
-
}
|
|
201
|
-
function RichFileTree({ root, paths, selectedPath, onSelect, search = true, initialExpansion = "open", gitStatus, renderContextMenu, header, themeOverrides, className, style, height }) {
|
|
202
|
-
if (root && paths) throw new Error("RichFileTree: pass `root` or `paths`, not both");
|
|
203
|
-
const flatPaths = useMemo(() => {
|
|
204
|
-
if (paths) return Array.from(paths);
|
|
205
|
-
if (root) return flattenFileNode(root);
|
|
206
|
-
return [];
|
|
207
|
-
}, [paths, root]);
|
|
208
|
-
const { model } = useFileTree({
|
|
209
|
-
paths: flatPaths,
|
|
210
|
-
search,
|
|
211
|
-
initialExpansion,
|
|
212
|
-
onSelectionChange: (selected) => {
|
|
213
|
-
const next = selected[0];
|
|
214
|
-
if (next && next !== selectedPath) onSelect?.(next);
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
useEffect(() => {
|
|
218
|
-
if (!gitStatus) return;
|
|
219
|
-
model.setGitStatus(gitStatus);
|
|
220
|
-
}, [model, gitStatus]);
|
|
221
|
-
useEffect(() => {
|
|
222
|
-
model.resetPaths(flatPaths);
|
|
223
|
-
}, [model, flatPaths]);
|
|
224
|
-
useEffect(() => {
|
|
225
|
-
if (!selectedPath) return;
|
|
226
|
-
const current = model.getSelectedPaths();
|
|
227
|
-
if (current.length === 1 && current[0] === selectedPath) return;
|
|
228
|
-
model.setSelectedPaths?.([selectedPath]);
|
|
229
|
-
}, [model, selectedPath]);
|
|
230
|
-
const theme = {
|
|
231
|
-
...DEFAULT_THEME,
|
|
232
|
-
...themeOverrides
|
|
233
|
-
};
|
|
234
|
-
const themeStyle = useMemo(() => ({
|
|
235
|
-
["--trees-selected-bg-override"]: theme.selectedBg,
|
|
236
|
-
["--trees-selected-fg-override"]: theme.selectedFg,
|
|
237
|
-
["--trees-fg-override"]: theme.fg,
|
|
238
|
-
["--trees-hover-bg-override"]: theme.hoverBg,
|
|
239
|
-
["--trees-border-color-override"]: theme.border,
|
|
240
|
-
["--trees-muted-fg-override"]: theme.mutedFg,
|
|
241
|
-
height: height ?? "100%",
|
|
242
|
-
...style
|
|
243
|
-
}), [
|
|
244
|
-
theme,
|
|
245
|
-
height,
|
|
246
|
-
style
|
|
247
|
-
]);
|
|
248
|
-
return /* @__PURE__ */ jsx(FileTree, {
|
|
249
|
-
model,
|
|
250
|
-
header,
|
|
251
|
-
renderContextMenu,
|
|
252
|
-
className,
|
|
253
|
-
style: themeStyle
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
//#endregion
|
|
257
|
-
//#region src/files/file-preview.tsx
|
|
258
|
-
/**
|
|
259
|
-
* FilePreview — universal file renderer.
|
|
260
|
-
*
|
|
261
|
-
* Renders any file type:
|
|
262
|
-
* - PDF: embedded viewer at full pane height
|
|
263
|
-
* - Images: fit to the pane on a checker ground; click toggles natural size
|
|
264
|
-
* - Video / audio: native players
|
|
265
|
-
* - CSV: sticky-header table, capped at CSV_PREVIEW_ROW_LIMIT rows
|
|
266
|
-
* - XLSX / XLS: download card
|
|
267
|
-
* - Code (py/json/yaml/ts/js): syntax-highlighted, line-numbered viewer
|
|
268
|
-
* - Markdown: rendered prose
|
|
269
|
-
* - Text: monospace preview
|
|
270
|
-
* - Anything else: text when content is a string, otherwise a download card
|
|
271
|
-
*/
|
|
272
|
-
/** Rows rendered by the CSV preview; the count line reports the total. */
|
|
273
|
-
const CSV_PREVIEW_ROW_LIMIT = 500;
|
|
274
|
-
const NEEDS_DOWNLOAD_LINK = "This file needs a download link to preview.";
|
|
275
|
-
const NO_INLINE_PREVIEW = "This file type has no inline preview.";
|
|
276
|
-
const NO_INLINE_CONTENT = "This file has no inline content to preview yet.";
|
|
277
|
-
function CodePreview({ content, filename, kind }) {
|
|
278
|
-
const lineCount = content.split("\n").length;
|
|
279
|
-
const language = getCodeLanguage(filename, kind);
|
|
280
|
-
const labelToken = fileExtension(filename) || language || "txt";
|
|
281
|
-
return /* @__PURE__ */ jsx(CodeBlock, {
|
|
282
|
-
code: content,
|
|
283
|
-
language,
|
|
284
|
-
label: `${labelToken} · ${lineCount} lines`,
|
|
285
|
-
showLineNumbers: true,
|
|
286
|
-
className: "max-h-[70vh] overflow-auto",
|
|
287
|
-
children: /* @__PURE__ */ jsx(CopyButton, { text: content })
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* Split CSV text into rows of cells (RFC 4180): a quoted cell may hold commas,
|
|
292
|
-
* line breaks, and doubled quotes. Unquoted cells are trimmed; blank lines and
|
|
293
|
-
* a trailing line break add no row.
|
|
294
|
-
*/
|
|
295
|
-
function parseCsv(content) {
|
|
296
|
-
const rows = [];
|
|
297
|
-
let row = [];
|
|
298
|
-
let cell = "";
|
|
299
|
-
let quoted = false;
|
|
300
|
-
let inQuotes = false;
|
|
301
|
-
const endCell = () => {
|
|
302
|
-
row.push(quoted ? cell : cell.trim());
|
|
303
|
-
cell = "";
|
|
304
|
-
quoted = false;
|
|
305
|
-
};
|
|
306
|
-
const endRow = () => {
|
|
307
|
-
endCell();
|
|
308
|
-
if (row.length > 1 || row[0] !== "") rows.push(row);
|
|
309
|
-
row = [];
|
|
310
|
-
};
|
|
311
|
-
for (let index = 0; index < content.length; index += 1) {
|
|
312
|
-
const char = content[index];
|
|
313
|
-
if (inQuotes) {
|
|
314
|
-
if (char === "\"") {
|
|
315
|
-
if (content[index + 1] === "\"") {
|
|
316
|
-
cell += "\"";
|
|
317
|
-
index += 1;
|
|
318
|
-
} else inQuotes = false;
|
|
319
|
-
} else cell += char;
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
if (char === "\"") {
|
|
323
|
-
inQuotes = true;
|
|
324
|
-
quoted = true;
|
|
325
|
-
continue;
|
|
326
|
-
}
|
|
327
|
-
if (char === ",") {
|
|
328
|
-
endCell();
|
|
329
|
-
continue;
|
|
330
|
-
}
|
|
331
|
-
if (char === "\r" || char === "\n") {
|
|
332
|
-
if (char === "\r" && content[index + 1] === "\n") index += 1;
|
|
333
|
-
endRow();
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
cell += char;
|
|
337
|
-
}
|
|
338
|
-
if (cell.length > 0 || quoted || row.length > 0) endRow();
|
|
339
|
-
return rows;
|
|
340
|
-
}
|
|
341
|
-
function CsvPreview({ content }) {
|
|
342
|
-
const [headers = [], ...body] = parseCsv(content);
|
|
343
|
-
if (headers.length === 0) return null;
|
|
344
|
-
const visible = body.slice(0, 500);
|
|
345
|
-
const columnCount = Math.max(headers.length, ...visible.map((cells) => cells.length));
|
|
346
|
-
const capped = body.length > visible.length;
|
|
347
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
348
|
-
className: "flex min-h-0 flex-1 flex-col gap-2",
|
|
349
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
350
|
-
className: "min-h-0 overflow-auto rounded-[var(--radius-md)] border border-border",
|
|
351
|
-
children: /* @__PURE__ */ jsxs("table", {
|
|
352
|
-
className: "w-full text-sm",
|
|
353
|
-
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: Array.from({ length: columnCount }, (_, column) => /* @__PURE__ */ jsx("th", {
|
|
354
|
-
className: "sticky top-0 whitespace-nowrap border-b border-border bg-card px-3 py-2 text-left text-xs font-semibold text-foreground",
|
|
355
|
-
children: headers[column] ?? ""
|
|
356
|
-
}, column)) }) }), /* @__PURE__ */ jsx("tbody", { children: visible.map((cells, rowIndex) => /* @__PURE__ */ jsx("tr", {
|
|
357
|
-
className: "border-b border-border hover:bg-accent",
|
|
358
|
-
children: Array.from({ length: columnCount }, (_, column) => /* @__PURE__ */ jsx("td", {
|
|
359
|
-
className: "whitespace-nowrap px-3 py-1.5 font-mono text-xs text-foreground",
|
|
360
|
-
children: cells[column] ?? ""
|
|
361
|
-
}, column))
|
|
362
|
-
}, rowIndex)) })]
|
|
363
|
-
})
|
|
364
|
-
}), /* @__PURE__ */ jsxs("p", {
|
|
365
|
-
className: "shrink-0 text-xs text-muted-foreground",
|
|
366
|
-
children: [capped ? `Showing ${visible.length} of ${body.length} rows` : `${body.length} ${body.length === 1 ? "row" : "rows"}`, ` · ${columnCount} ${columnCount === 1 ? "column" : "columns"}`]
|
|
367
|
-
})]
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
const CHECKER_STYLE = {
|
|
371
|
-
backgroundColor: "var(--color-background)",
|
|
372
|
-
backgroundImage: "repeating-conic-gradient(var(--color-muted) 0% 25%, transparent 0% 50%)",
|
|
373
|
-
backgroundSize: "16px 16px"
|
|
374
|
-
};
|
|
375
|
-
function ImagePreview({ src, filename }) {
|
|
376
|
-
const [naturalSize, setNaturalSize] = useState(false);
|
|
377
|
-
return /* @__PURE__ */ jsx("div", {
|
|
378
|
-
className: "flex min-h-[12rem] flex-1 overflow-auto rounded-[var(--radius-md)] border border-border",
|
|
379
|
-
style: CHECKER_STYLE,
|
|
380
|
-
children: /* @__PURE__ */ jsx("button", {
|
|
381
|
-
type: "button",
|
|
382
|
-
onClick: () => setNaturalSize((value) => !value),
|
|
383
|
-
"aria-pressed": naturalSize,
|
|
384
|
-
"aria-label": naturalSize ? "Fit image to pane" : "Show image at natural size",
|
|
385
|
-
className: cn("flex items-center justify-center", focusRingInset, naturalSize ? "m-auto cursor-zoom-out" : "h-full w-full cursor-zoom-in p-4"),
|
|
386
|
-
children: /* @__PURE__ */ jsx("img", {
|
|
387
|
-
src,
|
|
388
|
-
alt: filename,
|
|
389
|
-
draggable: false,
|
|
390
|
-
className: naturalSize ? "max-w-none" : "max-h-full max-w-full object-contain"
|
|
391
|
-
})
|
|
392
|
-
})
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
function PdfPreview({ blobUrl, filename, size, onDownload }) {
|
|
396
|
-
return /* @__PURE__ */ jsx("object", {
|
|
397
|
-
data: blobUrl,
|
|
398
|
-
type: "application/pdf",
|
|
399
|
-
title: filename,
|
|
400
|
-
className: "min-h-[24rem] w-full flex-1 rounded-[var(--radius-md)]",
|
|
401
|
-
children: /* @__PURE__ */ jsx(DownloadCard, {
|
|
402
|
-
filename,
|
|
403
|
-
size,
|
|
404
|
-
sentence: "This browser does not show PDFs inline.",
|
|
405
|
-
onDownload,
|
|
406
|
-
className: "h-full"
|
|
407
|
-
})
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
function VideoPreview({ src, filename }) {
|
|
411
|
-
return /* @__PURE__ */ jsx("div", {
|
|
412
|
-
className: "flex min-h-[12rem] flex-1 items-center justify-center overflow-hidden rounded-[var(--radius-md)] border border-border bg-background",
|
|
413
|
-
children: /* @__PURE__ */ jsx("video", {
|
|
414
|
-
controls: true,
|
|
415
|
-
preload: "metadata",
|
|
416
|
-
src,
|
|
417
|
-
"aria-label": filename,
|
|
418
|
-
className: "max-h-full max-w-full"
|
|
419
|
-
})
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
function AudioPreview({ src, filename }) {
|
|
423
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
424
|
-
className: "flex flex-col items-center gap-4 rounded-[var(--radius-md)] border border-border bg-background px-6 py-10",
|
|
425
|
-
children: [
|
|
426
|
-
/* @__PURE__ */ jsx(Music, { className: "h-10 w-10 text-muted-foreground opacity-60" }),
|
|
427
|
-
/* @__PURE__ */ jsx("p", {
|
|
428
|
-
className: "max-w-full truncate text-sm font-medium text-foreground",
|
|
429
|
-
children: filename
|
|
430
|
-
}),
|
|
431
|
-
/* @__PURE__ */ jsx("audio", {
|
|
432
|
-
controls: true,
|
|
433
|
-
preload: "metadata",
|
|
434
|
-
src,
|
|
435
|
-
"aria-label": filename,
|
|
436
|
-
className: "w-full max-w-md"
|
|
437
|
-
})
|
|
438
|
-
]
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
function TextPreview({ content }) {
|
|
442
|
-
return /* @__PURE__ */ jsx("pre", {
|
|
443
|
-
className: "bg-card rounded-[var(--radius-md)] border border-border p-4 overflow-auto max-h-[70vh] text-sm text-foreground font-mono leading-[1.55]",
|
|
444
|
-
children: content
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
function MarkdownPreview({ content, urlTransform }) {
|
|
448
|
-
return /* @__PURE__ */ jsx("div", {
|
|
449
|
-
className: "rounded-[var(--radius-md)] border border-border bg-background p-5",
|
|
450
|
-
children: /* @__PURE__ */ jsx(Markdown, {
|
|
451
|
-
urlTransform,
|
|
452
|
-
children: content
|
|
453
|
-
})
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* One muted sentence plus the filename, its size when known, and a Download
|
|
458
|
-
* button when the host wires `onDownload`. Serves spreadsheets, binaries, and
|
|
459
|
-
* every kind whose source (blob or text) is missing.
|
|
460
|
-
*/
|
|
461
|
-
function DownloadCard({ filename, size, sentence, icon: Icon = FileText, onDownload, className }) {
|
|
462
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
463
|
-
className: cn("flex flex-col items-center justify-center rounded-[var(--radius-md)] border border-dashed border-border bg-background px-6 py-16 text-center", className),
|
|
464
|
-
children: [
|
|
465
|
-
/* @__PURE__ */ jsx(Icon, { className: "mb-3 h-12 w-12 text-muted-foreground opacity-40" }),
|
|
466
|
-
/* @__PURE__ */ jsx("p", {
|
|
467
|
-
className: "max-w-full truncate text-sm font-medium text-foreground",
|
|
468
|
-
children: filename
|
|
469
|
-
}),
|
|
470
|
-
size !== void 0 && /* @__PURE__ */ jsx("p", {
|
|
471
|
-
className: "mt-1 text-xs text-muted-foreground",
|
|
472
|
-
children: formatBytes(size)
|
|
473
|
-
}),
|
|
474
|
-
/* @__PURE__ */ jsx("p", {
|
|
475
|
-
className: "mt-3 max-w-md text-sm text-muted-foreground",
|
|
476
|
-
children: sentence
|
|
477
|
-
}),
|
|
478
|
-
onDownload && /* @__PURE__ */ jsxs(Button, {
|
|
479
|
-
type: "button",
|
|
480
|
-
variant: "outline",
|
|
481
|
-
size: "sm",
|
|
482
|
-
className: "mt-5",
|
|
483
|
-
onClick: onDownload,
|
|
484
|
-
children: [/* @__PURE__ */ jsx(Download, {}), "Download"]
|
|
485
|
-
})
|
|
486
|
-
]
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
function PreviewBody({ kind, filename, content, blobUrl, size, urlTransform, onDownload }) {
|
|
490
|
-
const hasText = typeof content === "string";
|
|
491
|
-
const card = (sentence, icon) => /* @__PURE__ */ jsx(DownloadCard, {
|
|
492
|
-
filename,
|
|
493
|
-
size,
|
|
494
|
-
sentence,
|
|
495
|
-
icon,
|
|
496
|
-
onDownload
|
|
497
|
-
});
|
|
498
|
-
switch (kind) {
|
|
499
|
-
case "pdf":
|
|
500
|
-
if (blobUrl) return /* @__PURE__ */ jsx(PdfPreview, {
|
|
501
|
-
blobUrl,
|
|
502
|
-
filename,
|
|
503
|
-
size,
|
|
504
|
-
onDownload
|
|
505
|
-
});
|
|
506
|
-
return card(NEEDS_DOWNLOAD_LINK);
|
|
507
|
-
case "image":
|
|
508
|
-
if (blobUrl) return /* @__PURE__ */ jsx(ImagePreview, {
|
|
509
|
-
src: blobUrl,
|
|
510
|
-
filename
|
|
511
|
-
});
|
|
512
|
-
if (hasText) return /* @__PURE__ */ jsx(CodePreview, {
|
|
513
|
-
content,
|
|
514
|
-
filename,
|
|
515
|
-
kind: "code"
|
|
516
|
-
});
|
|
517
|
-
return card(NEEDS_DOWNLOAD_LINK);
|
|
518
|
-
case "video":
|
|
519
|
-
if (blobUrl) return /* @__PURE__ */ jsx(VideoPreview, {
|
|
520
|
-
src: blobUrl,
|
|
521
|
-
filename
|
|
522
|
-
});
|
|
523
|
-
return card(NEEDS_DOWNLOAD_LINK);
|
|
524
|
-
case "audio":
|
|
525
|
-
if (blobUrl) return /* @__PURE__ */ jsx(AudioPreview, {
|
|
526
|
-
src: blobUrl,
|
|
527
|
-
filename
|
|
528
|
-
});
|
|
529
|
-
return card(NEEDS_DOWNLOAD_LINK, Music);
|
|
530
|
-
case "csv":
|
|
531
|
-
if (hasText) return /* @__PURE__ */ jsx(CsvPreview, { content });
|
|
532
|
-
return card(NO_INLINE_CONTENT, FileSpreadsheet);
|
|
533
|
-
case "code":
|
|
534
|
-
case "json":
|
|
535
|
-
case "yaml":
|
|
536
|
-
if (hasText) return /* @__PURE__ */ jsx(CodePreview, {
|
|
537
|
-
content,
|
|
538
|
-
filename,
|
|
539
|
-
kind
|
|
540
|
-
});
|
|
541
|
-
return card(NO_INLINE_CONTENT);
|
|
542
|
-
case "markdown":
|
|
543
|
-
if (hasText) return /* @__PURE__ */ jsx(MarkdownPreview, {
|
|
544
|
-
content,
|
|
545
|
-
urlTransform
|
|
546
|
-
});
|
|
547
|
-
return card(NO_INLINE_CONTENT);
|
|
548
|
-
case "text":
|
|
549
|
-
if (hasText) return /* @__PURE__ */ jsx(TextPreview, { content });
|
|
550
|
-
return card(NO_INLINE_CONTENT);
|
|
551
|
-
case "spreadsheet": return card("Download to open this workbook in a spreadsheet app.", FileSpreadsheet);
|
|
552
|
-
case "binary":
|
|
553
|
-
if (hasText) return /* @__PURE__ */ jsx(TextPreview, { content });
|
|
554
|
-
return card(blobUrl ? NO_INLINE_PREVIEW : NEEDS_DOWNLOAD_LINK);
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
function FilePreview({ filename, content, blobUrl, mimeType, size, urlTransform, onClose, onDownload, hideHeader = false, className }) {
|
|
558
|
-
const kind = resolveFilePreviewKind(filename, mimeType);
|
|
559
|
-
const previewLabel = getFormatLabel(kind);
|
|
560
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
561
|
-
className: cn("flex flex-col h-full", className),
|
|
562
|
-
children: [!hideHeader && /* @__PURE__ */ jsxs("div", {
|
|
563
|
-
className: "flex items-center gap-2 px-3 py-2 border-b border-border shrink-0",
|
|
564
|
-
children: [
|
|
565
|
-
/* @__PURE__ */ jsxs("div", {
|
|
566
|
-
className: "min-w-0 flex-1",
|
|
567
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
568
|
-
className: "truncate text-sm font-medium text-foreground",
|
|
569
|
-
children: filename
|
|
570
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
571
|
-
className: "mt-0.5 text-[11px] uppercase tracking-[0.12em] text-muted-foreground",
|
|
572
|
-
children: previewLabel
|
|
573
|
-
})]
|
|
574
|
-
}),
|
|
575
|
-
onDownload && /* @__PURE__ */ jsx("button", {
|
|
576
|
-
type: "button",
|
|
577
|
-
onClick: onDownload,
|
|
578
|
-
"aria-label": `Download ${filename}`,
|
|
579
|
-
className: "p-1.5 rounded-[var(--radius-sm)] hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
580
|
-
children: /* @__PURE__ */ jsx(Download, { className: "h-4 w-4" })
|
|
581
|
-
}),
|
|
582
|
-
onClose && /* @__PURE__ */ jsx("button", {
|
|
583
|
-
type: "button",
|
|
584
|
-
onClick: onClose,
|
|
585
|
-
"aria-label": `Close ${filename}`,
|
|
586
|
-
className: "p-1.5 rounded-[var(--radius-sm)] hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
587
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
588
|
-
})
|
|
589
|
-
]
|
|
590
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
591
|
-
className: "flex min-h-0 flex-1 flex-col overflow-auto p-3",
|
|
592
|
-
children: /* @__PURE__ */ jsx(PreviewBody, {
|
|
593
|
-
kind,
|
|
594
|
-
filename,
|
|
595
|
-
content,
|
|
596
|
-
blobUrl,
|
|
597
|
-
size,
|
|
598
|
-
urlTransform,
|
|
599
|
-
onDownload
|
|
600
|
-
})
|
|
601
|
-
})]
|
|
602
|
-
});
|
|
603
|
-
}
|
|
604
|
-
//#endregion
|
|
605
|
-
//#region src/files/file-tabs.tsx
|
|
606
|
-
/**
|
|
607
|
-
* FileTabs — tab bar for open files in the preview panel.
|
|
608
|
-
*/
|
|
609
|
-
function getTabIcon(name) {
|
|
610
|
-
const ext = name.split(".").pop()?.toLowerCase() || "";
|
|
611
|
-
if (["pdf"].includes(ext)) return FileText;
|
|
612
|
-
if (["csv", "xlsx"].includes(ext)) return FileSpreadsheet;
|
|
613
|
-
return FileCode;
|
|
614
|
-
}
|
|
615
|
-
function FileTabs({ tabs, activeId, onSelect, onClose, className }) {
|
|
616
|
-
if (tabs.length === 0) return null;
|
|
617
|
-
return /* @__PURE__ */ jsx("div", {
|
|
618
|
-
className: cn("flex items-center border-b border-border bg-background overflow-x-auto", className),
|
|
619
|
-
children: tabs.map((tab) => {
|
|
620
|
-
const isActive = tab.id === activeId;
|
|
621
|
-
const Icon = getTabIcon(tab.name);
|
|
622
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
623
|
-
className: cn("group flex items-center border-r border-border shrink-0", isActive ? "bg-card text-foreground border-b-2 border-b-primary" : "text-muted-foreground hover:bg-muted/50"),
|
|
624
|
-
children: [/* @__PURE__ */ jsxs("button", {
|
|
625
|
-
type: "button",
|
|
626
|
-
onClick: () => onSelect(tab.id),
|
|
627
|
-
className: cn("flex min-w-0 items-center gap-1.5 px-3 py-1.5 text-xs transition-colors hover:text-foreground", focusRingInset),
|
|
628
|
-
children: [
|
|
629
|
-
/* @__PURE__ */ jsx(Icon, { className: "h-3 w-3 shrink-0" }),
|
|
630
|
-
/* @__PURE__ */ jsx("span", {
|
|
631
|
-
className: "max-w-[120px] truncate",
|
|
632
|
-
children: tab.name
|
|
633
|
-
}),
|
|
634
|
-
tab.dirty && /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-primary" })
|
|
635
|
-
]
|
|
636
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
637
|
-
type: "button",
|
|
638
|
-
"aria-label": `Close ${tab.name}`,
|
|
639
|
-
onClick: () => onClose(tab.id),
|
|
640
|
-
className: cn("mr-1 rounded p-0.5 opacity-0 transition-opacity hover:bg-accent focus-visible:opacity-100 group-hover:opacity-100", focusRing),
|
|
641
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-2.5 w-2.5" })
|
|
642
|
-
})]
|
|
643
|
-
}, tab.id);
|
|
644
|
-
})
|
|
645
|
-
});
|
|
646
|
-
}
|
|
647
|
-
//#endregion
|
|
648
|
-
//#region src/files/file-artifact-pane.tsx
|
|
649
|
-
const LazyDocumentEditorPane = lazy(async () => {
|
|
650
|
-
return { default: (await import("./document-editor-pane-POsq5Q0o.js").then((n) => n.n)).DocumentEditorPane };
|
|
651
|
-
});
|
|
652
|
-
/**
|
|
653
|
-
* FileArtifactPane — opinionated artifact frame for file previews with tabs and
|
|
654
|
-
* header actions. The body is `FilePreview`, so every kind it renders (image,
|
|
655
|
-
* PDF, video, audio, CSV, spreadsheet, markdown, code, text) renders here too;
|
|
656
|
-
* `onDownload` drives both the header button and the body's download cards.
|
|
657
|
-
*/
|
|
658
|
-
function FileArtifactPane({ filename, content, blobUrl, mimeType, size, onClose, onDownload, urlTransform, path, tabs = [], activeTabId, onTabSelect, onTabClose, eyebrow = "Artifact", meta, toolbar, footer, className, headerClassName, hideTitleBlock, editor }) {
|
|
659
|
-
const paneTabs = tabs.length > 0 && onTabSelect && onTabClose ? /* @__PURE__ */ jsx(FileTabs, {
|
|
660
|
-
tabs,
|
|
661
|
-
activeId: activeTabId,
|
|
662
|
-
onSelect: onTabSelect,
|
|
663
|
-
onClose: onTabClose
|
|
664
|
-
}) : void 0;
|
|
665
|
-
const isEditableMarkdown = (detectFileFormat(filename, mimeType) === "markdown" || (path ? detectFileFormat(path, mimeType) === "markdown" : false)) && editor?.enabled;
|
|
666
|
-
const headerActions = onDownload || onClose ? /* @__PURE__ */ jsxs(Fragment$1, { children: [onDownload && /* @__PURE__ */ jsx("button", {
|
|
667
|
-
type: "button",
|
|
668
|
-
"aria-label": `Download ${filename}`,
|
|
669
|
-
onClick: onDownload,
|
|
670
|
-
className: `rounded-[var(--radius-sm)] p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing}`,
|
|
671
|
-
children: /* @__PURE__ */ jsx(Download, { className: "h-4 w-4" })
|
|
672
|
-
}), onClose && /* @__PURE__ */ jsx("button", {
|
|
673
|
-
type: "button",
|
|
674
|
-
"aria-label": `Close ${filename}`,
|
|
675
|
-
onClick: onClose,
|
|
676
|
-
className: `rounded-[var(--radius-sm)] p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground ${focusRing}`,
|
|
677
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
678
|
-
})] }) : void 0;
|
|
679
|
-
if (isEditableMarkdown) return /* @__PURE__ */ jsx(Suspense, {
|
|
680
|
-
fallback: /* @__PURE__ */ jsx(ArtifactPane, {
|
|
681
|
-
eyebrow,
|
|
682
|
-
title: filename,
|
|
683
|
-
subtitle: path,
|
|
684
|
-
meta,
|
|
685
|
-
toolbar,
|
|
686
|
-
footer,
|
|
687
|
-
className,
|
|
688
|
-
tabs: paneTabs,
|
|
689
|
-
headerActions,
|
|
690
|
-
headerClassName,
|
|
691
|
-
hideTitleBlock,
|
|
692
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
693
|
-
className: "flex min-h-[12rem] items-center justify-center rounded-[var(--radius-lg)] border border-dashed border-border bg-muted text-sm text-muted-foreground",
|
|
694
|
-
children: "Loading editor…"
|
|
695
|
-
})
|
|
696
|
-
}),
|
|
697
|
-
children: /* @__PURE__ */ jsx(LazyDocumentEditorPane, {
|
|
698
|
-
eyebrow,
|
|
699
|
-
title: filename,
|
|
700
|
-
subtitle: path,
|
|
701
|
-
meta,
|
|
702
|
-
toolbar,
|
|
703
|
-
footer,
|
|
704
|
-
className,
|
|
705
|
-
tabs: paneTabs,
|
|
706
|
-
headerActions,
|
|
707
|
-
headerClassName,
|
|
708
|
-
hideTitleBlock,
|
|
709
|
-
markdown: content ?? "",
|
|
710
|
-
savedMarkdown: editor.savedContent,
|
|
711
|
-
urlTransform,
|
|
712
|
-
mode: editor.mode,
|
|
713
|
-
defaultMode: editor.defaultMode,
|
|
714
|
-
onModeChange: editor.onModeChange,
|
|
715
|
-
backend: editor.backend,
|
|
716
|
-
collaboration: editor.collaboration,
|
|
717
|
-
placeholder: editor.placeholder,
|
|
718
|
-
autoFocus: editor.autoFocus,
|
|
719
|
-
readOnly: editor.readOnly,
|
|
720
|
-
saving: editor.saving,
|
|
721
|
-
saveLabel: editor.saveLabel,
|
|
722
|
-
onChange: editor.onChange,
|
|
723
|
-
onSave: editor.onSave,
|
|
724
|
-
previewClassName: editor.previewClassName,
|
|
725
|
-
editorClassName: editor.editorClassName
|
|
726
|
-
})
|
|
727
|
-
});
|
|
728
|
-
return /* @__PURE__ */ jsx(ArtifactPane, {
|
|
729
|
-
eyebrow,
|
|
730
|
-
title: filename,
|
|
731
|
-
subtitle: path,
|
|
732
|
-
meta,
|
|
733
|
-
toolbar,
|
|
734
|
-
footer,
|
|
735
|
-
className,
|
|
736
|
-
tabs: paneTabs,
|
|
737
|
-
headerActions,
|
|
738
|
-
headerClassName,
|
|
739
|
-
hideTitleBlock,
|
|
740
|
-
children: /* @__PURE__ */ jsx(FilePreview, {
|
|
741
|
-
filename,
|
|
742
|
-
content,
|
|
743
|
-
blobUrl,
|
|
744
|
-
mimeType,
|
|
745
|
-
size,
|
|
746
|
-
urlTransform,
|
|
747
|
-
onDownload,
|
|
748
|
-
hideHeader: true
|
|
749
|
-
})
|
|
750
|
-
});
|
|
751
|
-
}
|
|
752
|
-
//#endregion
|
|
753
|
-
export { parseCsv as a, filterFileTree as c, FilePreview as i, FileTabs as n, RichFileTree as o, CSV_PREVIEW_ROW_LIMIT as r, FileTree$1 as s, FileArtifactPane as t };
|