@tangle-network/sandbox-ui 0.14.0 → 0.15.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.
Files changed (104) hide show
  1. package/dist/auth.d.ts +1 -74
  2. package/dist/auth.js +1 -4
  3. package/dist/chat.d.ts +1 -136
  4. package/dist/chat.js +2 -15
  5. package/dist/chunk-2BUPSB7O.js +0 -0
  6. package/dist/chunk-3J6FG3FJ.js +18 -0
  7. package/dist/chunk-76IQLPW2.js +206 -0
  8. package/dist/chunk-7ZA5SEK3.js +239 -0
  9. package/dist/chunk-AHBZCBDO.js +2960 -0
  10. package/dist/chunk-AZ3AWMTM.js +8 -0
  11. package/dist/chunk-CMY7W45U.js +380 -0
  12. package/dist/{chunk-QMU2PWOU.js → chunk-DNZ4DTNA.js} +71 -17
  13. package/dist/chunk-EI44GEQ5.js +6 -0
  14. package/dist/{chunk-5OQ27N57.js → chunk-GPT7VKK6.js} +34 -38
  15. package/dist/chunk-JBGKGLD7.js +16 -0
  16. package/dist/chunk-NJNME4J4.js +14 -0
  17. package/dist/chunk-QPAJR74X.js +20 -0
  18. package/dist/chunk-TK46XFLM.js +28 -0
  19. package/dist/chunk-WID73FPH.js +89 -0
  20. package/dist/chunk-YVXK4XRO.js +30 -0
  21. package/dist/dashboard.d.ts +538 -4
  22. package/dist/dashboard.js +15 -886
  23. package/dist/editor.d.ts +1 -120
  24. package/dist/editor.js +1 -5
  25. package/dist/files.d.ts +1 -129
  26. package/dist/files.js +2 -7
  27. package/dist/globals.css +2 -1265
  28. package/dist/hooks.d.ts +114 -11
  29. package/dist/hooks.js +17 -88
  30. package/dist/index.d.ts +24 -99
  31. package/dist/index.js +247 -252
  32. package/dist/markdown.d.ts +1 -29
  33. package/dist/markdown.js +2 -2
  34. package/dist/openui.d.ts +8 -115
  35. package/dist/openui.js +1 -6
  36. package/dist/pages.d.ts +1 -2
  37. package/dist/pages.js +68 -66
  38. package/dist/primitives.d.ts +14 -49
  39. package/dist/primitives.js +69 -77
  40. package/dist/run.d.ts +1 -14
  41. package/dist/run.js +2 -22
  42. package/dist/sdk-hooks.d.ts +3 -283
  43. package/dist/sdk-hooks.js +10 -14
  44. package/dist/stores.d.ts +2 -14
  45. package/dist/stores.js +11 -39
  46. package/dist/styles.css +2 -1265
  47. package/dist/{usage-chart-CPTcNlGs.d.ts → template-card-UhV3pmRC.d.ts} +16 -1
  48. package/dist/types.d.ts +11 -8
  49. package/dist/types.js +1 -0
  50. package/dist/utils.d.ts +1 -44
  51. package/dist/utils.js +6 -12
  52. package/dist/workspace.d.ts +5 -10
  53. package/dist/workspace.js +3 -19
  54. package/package.json +19 -54
  55. package/dist/active-sessions-store-CeOmXgv5.d.ts +0 -85
  56. package/dist/artifact-pane-Bh45Ssco.d.ts +0 -24
  57. package/dist/branding-DCi5VEik.d.ts +0 -13
  58. package/dist/button-CMQuQEW_.d.ts +0 -17
  59. package/dist/chat-container-f4yEs6KN.d.ts +0 -106
  60. package/dist/chunk-34A66VBG.js +0 -214
  61. package/dist/chunk-34I7UFSX.js +0 -92
  62. package/dist/chunk-36QY2W5G.js +0 -802
  63. package/dist/chunk-4CLN43XT.js +0 -45
  64. package/dist/chunk-54SQQMMM.js +0 -156
  65. package/dist/chunk-66EZOYZR.js +0 -102
  66. package/dist/chunk-BX6AQMUS.js +0 -183
  67. package/dist/chunk-DI3NZ5ZX.js +0 -192
  68. package/dist/chunk-DPGIXDAI.js +0 -220
  69. package/dist/chunk-DXMIEK4K.js +0 -1426
  70. package/dist/chunk-GSZA3TSY.js +0 -79
  71. package/dist/chunk-HB5Y37YU.js +0 -54
  72. package/dist/chunk-LQNEZDRM.js +0 -109
  73. package/dist/chunk-MA7YKRUP.js +0 -131
  74. package/dist/chunk-MKTSMWVD.js +0 -109
  75. package/dist/chunk-MQXABZTB.js +0 -1348
  76. package/dist/chunk-MT5FJ3ZT.js +0 -186
  77. package/dist/chunk-NKUPJC34.js +0 -2070
  78. package/dist/chunk-OEX7NZE3.js +0 -321
  79. package/dist/chunk-OKLQVY3Y.js +0 -139
  80. package/dist/chunk-Q56BYXQF.js +0 -61
  81. package/dist/chunk-QD4QE5P5.js +0 -40
  82. package/dist/chunk-QDH5GEGY.js +0 -630
  83. package/dist/chunk-QID2OOMG.js +0 -133
  84. package/dist/chunk-RQHJBTEU.js +0 -10
  85. package/dist/chunk-T7HMZEVO.js +0 -216
  86. package/dist/chunk-U6QTHMY6.js +0 -1290
  87. package/dist/chunk-US6JKJKH.js +0 -124
  88. package/dist/chunk-VX3XOUEB.js +0 -63
  89. package/dist/chunk-XLG757B6.js +0 -933
  90. package/dist/chunk-ZMNSRDMH.js +0 -127
  91. package/dist/chunk-ZNCEM5CD.js +0 -316
  92. package/dist/document-editor-pane-A70-EhdQ.d.ts +0 -124
  93. package/dist/document-editor-pane-TLPVRBBU.js +0 -11
  94. package/dist/expanded-tool-detail-Dh99mcbY.d.ts +0 -63
  95. package/dist/file-tabs-BLfxfmAH.d.ts +0 -51
  96. package/dist/parts-CyGkM6Fp.d.ts +0 -50
  97. package/dist/run-CtFZ6s-D.d.ts +0 -41
  98. package/dist/sidebar-drop-zone-tDBsuOH5.d.ts +0 -301
  99. package/dist/sidecar-CFU2W9j1.d.ts +0 -8
  100. package/dist/template-card-BAtvcAkU.d.ts +0 -18
  101. package/dist/tool-call-feed-Bs3MyQMT.d.ts +0 -68
  102. package/dist/tool-display-Ct9nFAzJ.d.ts +0 -32
  103. package/dist/use-sandbox-metrics-DWc0k9Xm.d.ts +0 -153
  104. package/dist/variant-list-BrHYcBCk.d.ts +0 -540
@@ -1,630 +0,0 @@
1
- import {
2
- ArtifactPane
3
- } from "./chunk-HB5Y37YU.js";
4
- import {
5
- Markdown
6
- } from "./chunk-T7HMZEVO.js";
7
- import {
8
- cn
9
- } from "./chunk-RQHJBTEU.js";
10
-
11
- // src/files/file-tree.tsx
12
- import { useState } from "react";
13
- import {
14
- File,
15
- FileText,
16
- FileCode,
17
- FileSpreadsheet,
18
- FileImage,
19
- Folder,
20
- FolderOpen,
21
- ChevronRight,
22
- FileJson
23
- } from "lucide-react";
24
- import { jsx, jsxs } from "react/jsx-runtime";
25
- function isNodeVisible(node, visibility) {
26
- if (!visibility) return true;
27
- if (visibility.hiddenPaths?.includes(node.path)) {
28
- return false;
29
- }
30
- if (visibility.hiddenPathPrefixes?.some(
31
- (prefix) => node.path === prefix || node.path.startsWith(`${prefix}/`)
32
- )) {
33
- return false;
34
- }
35
- return visibility.isVisible ? visibility.isVisible(node) : true;
36
- }
37
- function filterFileTree(root, visibility) {
38
- if (!isNodeVisible(root, visibility)) {
39
- return null;
40
- }
41
- if (root.type === "file") {
42
- return root;
43
- }
44
- const children = (root.children ?? []).map((child) => filterFileTree(child, visibility)).filter((child) => child !== null);
45
- if (root.children && root.children.length > 0 && children.length === 0) {
46
- return null;
47
- }
48
- return {
49
- ...root,
50
- children
51
- };
52
- }
53
- var FILE_ICONS = {
54
- pdf: FileText,
55
- csv: FileSpreadsheet,
56
- xlsx: FileSpreadsheet,
57
- xls: FileSpreadsheet,
58
- py: FileCode,
59
- ts: FileCode,
60
- js: FileCode,
61
- json: FileJson,
62
- yaml: FileCode,
63
- yml: FileCode,
64
- md: FileText,
65
- txt: FileText,
66
- png: FileImage,
67
- jpg: FileImage,
68
- jpeg: FileImage,
69
- gif: FileImage,
70
- svg: FileImage
71
- };
72
- function getFileIcon(name) {
73
- const ext = name.split(".").pop()?.toLowerCase() || "";
74
- return FILE_ICONS[ext] || File;
75
- }
76
- function getFileColor(name) {
77
- const ext = name.split(".").pop()?.toLowerCase() || "";
78
- switch (ext) {
79
- case "pdf":
80
- return "text-red-400";
81
- case "py":
82
- return "text-yellow-400";
83
- case "ts":
84
- case "js":
85
- return "text-blue-400";
86
- case "json":
87
- return "text-green-400";
88
- case "yaml":
89
- case "yml":
90
- return "text-[var(--accent-text)]";
91
- case "csv":
92
- case "xlsx":
93
- return "text-emerald-400";
94
- case "md":
95
- return "text-foreground";
96
- default:
97
- return "text-muted-foreground";
98
- }
99
- }
100
- function TreeNode({ node, depth, selectedPath, onSelect, defaultExpanded }) {
101
- const [expanded, setExpanded] = useState(defaultExpanded);
102
- const isSelected = node.path === selectedPath;
103
- const isDir = node.type === "directory";
104
- const handleClick = () => {
105
- if (isDir) {
106
- setExpanded(!expanded);
107
- }
108
- onSelect?.(node.path, node);
109
- };
110
- const Icon = isDir ? expanded ? FolderOpen : Folder : getFileIcon(node.name);
111
- const iconColor = isDir ? "text-primary" : getFileColor(node.name);
112
- return /* @__PURE__ */ jsxs("div", { children: [
113
- /* @__PURE__ */ jsxs(
114
- "button",
115
- {
116
- type: "button",
117
- className: cn(
118
- "flex items-center gap-1.5 w-full text-left px-2 py-[2px] cursor-pointer text-[13px] transition-colors",
119
- "appearance-none bg-transparent border-none",
120
- "hover:bg-accent",
121
- isSelected ? "bg-primary/15 text-foreground" : "text-foreground"
122
- ),
123
- style: { paddingLeft: `${depth * 16 + 8}px` },
124
- onClick: handleClick,
125
- "aria-expanded": isDir ? expanded : void 0,
126
- children: [
127
- isDir && /* @__PURE__ */ jsx(
128
- ChevronRight,
129
- {
130
- className: cn(
131
- "h-3 w-3 shrink-0 text-muted-foreground transition-transform",
132
- expanded && "rotate-90"
133
- )
134
- }
135
- ),
136
- !isDir && /* @__PURE__ */ jsx("span", { className: "w-3" }),
137
- /* @__PURE__ */ jsx(Icon, { className: cn("h-4 w-4 shrink-0", iconColor) }),
138
- /* @__PURE__ */ jsx("span", { className: "truncate", children: node.name }),
139
- node.size !== void 0 && !isDir && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs ml-auto tabular-nums", children: formatSize(node.size) })
140
- ]
141
- }
142
- ),
143
- isDir && expanded && node.children && /* @__PURE__ */ jsx("div", { children: node.children.sort((a, b) => {
144
- if (a.type !== b.type) return a.type === "directory" ? -1 : 1;
145
- return a.name.localeCompare(b.name);
146
- }).map((child) => /* @__PURE__ */ jsx(
147
- TreeNode,
148
- {
149
- node: child,
150
- depth: depth + 1,
151
- selectedPath,
152
- onSelect,
153
- defaultExpanded
154
- },
155
- child.path
156
- )) })
157
- ] });
158
- }
159
- function formatSize(bytes) {
160
- if (bytes < 1024) return `${bytes}B`;
161
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)}K`;
162
- return `${(bytes / (1024 * 1024)).toFixed(1)}M`;
163
- }
164
- function FileTree({
165
- root,
166
- selectedPath,
167
- onSelect,
168
- className,
169
- defaultExpanded = true,
170
- visibility
171
- }) {
172
- const visibleRoot = filterFileTree(root, visibility);
173
- if (!visibleRoot) {
174
- return null;
175
- }
176
- return /* @__PURE__ */ jsx("div", { className: cn("text-sm font-sans", className), children: visibleRoot.children ? visibleRoot.children.sort((a, b) => {
177
- if (a.type !== b.type) return a.type === "directory" ? -1 : 1;
178
- return a.name.localeCompare(b.name);
179
- }).map((child) => /* @__PURE__ */ jsx(
180
- TreeNode,
181
- {
182
- node: child,
183
- depth: 0,
184
- selectedPath,
185
- onSelect,
186
- defaultExpanded
187
- },
188
- child.path
189
- )) : /* @__PURE__ */ jsx(
190
- TreeNode,
191
- {
192
- node: visibleRoot,
193
- depth: 0,
194
- selectedPath,
195
- onSelect,
196
- defaultExpanded
197
- }
198
- ) });
199
- }
200
-
201
- // src/files/file-preview.tsx
202
- import {
203
- Download,
204
- X,
205
- FileText as FileText2
206
- } from "lucide-react";
207
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
208
- function getPreviewType(filename, mimeType) {
209
- const ext = filename.split(".").pop()?.toLowerCase() || "";
210
- if (mimeType?.startsWith("application/pdf") || ext === "pdf") return "pdf";
211
- if (mimeType?.startsWith("image/") || ["png", "jpg", "jpeg", "gif", "svg", "webp"].includes(ext)) return "image";
212
- if (["csv"].includes(ext)) return "csv";
213
- if (["xlsx", "xls"].includes(ext)) return "spreadsheet";
214
- if (["py", "ts", "js", "tsx", "jsx", "sh", "bash"].includes(ext) || ["profile", "bashrc", "bash_logout", "env", "gitignore"].includes(ext)) return "code";
215
- if (["json"].includes(ext)) return "json";
216
- if (["yaml", "yml"].includes(ext)) return "yaml";
217
- if (["md", "markdown"].includes(ext)) return "markdown";
218
- if (["txt", "log", "text"].includes(ext)) return "text";
219
- if (mimeType?.startsWith("text/plain")) return "text";
220
- return "unknown";
221
- }
222
- function getPreviewLabel(previewType) {
223
- switch (previewType) {
224
- case "pdf":
225
- return "PDF";
226
- case "image":
227
- return "Image";
228
- case "csv":
229
- return "CSV";
230
- case "spreadsheet":
231
- return "Spreadsheet";
232
- case "code":
233
- return "Code";
234
- case "json":
235
- return "JSON";
236
- case "yaml":
237
- return "YAML";
238
- case "markdown":
239
- return "Markdown";
240
- case "text":
241
- return "Text";
242
- default:
243
- return "File";
244
- }
245
- }
246
- function CodePreview({ content, filename }) {
247
- const lines = content.split("\n");
248
- const language = filename.split(".").pop()?.toUpperCase() || "TXT";
249
- return /* @__PURE__ */ jsxs2("div", { className: "relative bg-background rounded-[var(--radius-md)] border border-border overflow-hidden", children: [
250
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between gap-3 border-b border-border px-4 py-2.5", children: [
251
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-1.5", children: [
252
- /* @__PURE__ */ jsx2("div", { className: "w-3 h-3 rounded-full bg-[#FF5F57]" }),
253
- /* @__PURE__ */ jsx2("div", { className: "w-3 h-3 rounded-full bg-[#FEBC2E]" }),
254
- /* @__PURE__ */ jsx2("div", { className: "w-3 h-3 rounded-full bg-[#8E59FF]" })
255
- ] }),
256
- /* @__PURE__ */ jsx2("div", { className: "ml-2 min-w-0 flex-1 truncate text-xs font-mono text-muted-foreground", children: filename }),
257
- /* @__PURE__ */ jsxs2("div", { className: "inline-flex items-center gap-2 rounded-[var(--radius-full)] border border-border bg-card px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: [
258
- /* @__PURE__ */ jsx2("span", { children: language }),
259
- /* @__PURE__ */ jsx2("span", { className: "h-1 w-1 rounded-full bg-[var(--border-hover)]" }),
260
- /* @__PURE__ */ jsxs2("span", { children: [
261
- lines.length,
262
- " lines"
263
- ] })
264
- ] })
265
- ] }),
266
- /* @__PURE__ */ jsx2("div", { className: "overflow-auto max-h-[70vh]", children: /* @__PURE__ */ jsx2("table", { className: "w-full", children: /* @__PURE__ */ jsx2("tbody", { children: lines.map((line, i) => /* @__PURE__ */ jsxs2("tr", { className: "hover:bg-accent", children: [
267
- /* @__PURE__ */ jsx2("td", { className: "text-right pr-4 pl-4 py-0 select-none text-muted-foreground text-xs font-mono w-10 align-top leading-[1.55]", children: i + 1 }),
268
- /* @__PURE__ */ jsx2("td", { className: "pr-4 py-0 font-mono text-[13px] text-foreground leading-[1.55] whitespace-pre", children: line || " " })
269
- ] }, i)) }) }) })
270
- ] });
271
- }
272
- function parseCsvRow(line) {
273
- const cells = [];
274
- let current = "";
275
- let inQuotes = false;
276
- for (let index = 0; index < line.length; index += 1) {
277
- const char = line[index];
278
- const next = line[index + 1];
279
- if (char === '"') {
280
- if (inQuotes && next === '"') {
281
- current += '"';
282
- index += 1;
283
- continue;
284
- }
285
- inQuotes = !inQuotes;
286
- continue;
287
- }
288
- if (char === "," && !inQuotes) {
289
- cells.push(current.trim());
290
- current = "";
291
- continue;
292
- }
293
- current += char;
294
- }
295
- cells.push(current.trim());
296
- return cells;
297
- }
298
- function CsvPreview({ content }) {
299
- const lines = content.trim().split(/\r?\n/).filter(Boolean);
300
- if (lines.length === 0) return null;
301
- const headers = parseCsvRow(lines[0]).map((header) => header.replace(/^"|"$/g, ""));
302
- const rows = lines.slice(1).map(
303
- (line) => parseCsvRow(line).map((cell) => cell.replace(/^"|"$/g, ""))
304
- );
305
- return /* @__PURE__ */ jsx2("div", { className: "overflow-auto max-h-[70vh] rounded-[var(--radius-md)] border border-border", children: /* @__PURE__ */ jsxs2("table", { className: "w-full text-sm", children: [
306
- /* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsx2("tr", { className: "bg-muted/50 sticky top-0", children: headers.map((h, i) => /* @__PURE__ */ jsx2(
307
- "th",
308
- {
309
- className: "px-3 py-2 text-left text-xs font-semibold text-foreground border-b border-border whitespace-nowrap",
310
- children: h
311
- },
312
- i
313
- )) }) }),
314
- /* @__PURE__ */ jsx2("tbody", { children: rows.map((row, i) => /* @__PURE__ */ jsx2("tr", { className: "border-b border-border hover:bg-accent", children: row.map((cell, j) => /* @__PURE__ */ jsx2(
315
- "td",
316
- {
317
- className: "px-3 py-1.5 text-foreground font-mono text-xs whitespace-nowrap",
318
- children: cell
319
- },
320
- j
321
- )) }, i)) })
322
- ] }) });
323
- }
324
- function ImagePreview({ src, filename }) {
325
- return /* @__PURE__ */ jsx2("div", { className: "flex items-center justify-center p-4 bg-background rounded-[var(--radius-md)] border border-border", children: /* @__PURE__ */ jsx2("img", { src, alt: filename, className: "max-w-full max-h-[70vh] object-contain rounded" }) });
326
- }
327
- function PdfPreview({ blobUrl, filename }) {
328
- return /* @__PURE__ */ jsx2("div", { className: "rounded-[var(--radius-md)] border border-border overflow-hidden bg-background", children: /* @__PURE__ */ jsx2(
329
- "iframe",
330
- {
331
- src: blobUrl,
332
- title: filename,
333
- className: "w-full h-[70vh] border-0"
334
- }
335
- ) });
336
- }
337
- function TextPreview({ content }) {
338
- return /* @__PURE__ */ jsx2("pre", { className: "bg-background rounded-[var(--radius-md)] border border-border p-4 overflow-auto max-h-[70vh] text-sm text-foreground font-mono leading-[1.55]", children: content });
339
- }
340
- function UnsupportedPreview({
341
- filename,
342
- title,
343
- description
344
- }) {
345
- return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center justify-center rounded-[var(--radius-md)] border border-dashed border-border bg-background px-6 py-16 text-center text-muted-foreground", children: [
346
- /* @__PURE__ */ jsx2(FileText2, { className: "mb-3 h-12 w-12 opacity-30" }),
347
- /* @__PURE__ */ jsx2("p", { className: "text-sm text-foreground", children: title }),
348
- /* @__PURE__ */ jsx2("p", { className: "mt-1 max-w-md text-xs", children: description }),
349
- /* @__PURE__ */ jsx2("p", { className: "mt-4 text-[11px] uppercase tracking-[0.12em]", children: filename })
350
- ] });
351
- }
352
- function MarkdownPreview({ content }) {
353
- return /* @__PURE__ */ jsx2("div", { className: "rounded-[var(--radius-md)] border border-border bg-background p-5", children: /* @__PURE__ */ jsx2(Markdown, { className: "prose-sm max-w-none", children: content }) });
354
- }
355
- function EmptyPreview({ filename }) {
356
- return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center justify-center py-16 text-muted-foreground", children: [
357
- /* @__PURE__ */ jsx2(FileText2, { className: "h-12 w-12 mb-3 opacity-30" }),
358
- /* @__PURE__ */ jsxs2("p", { className: "text-sm", children: [
359
- "Cannot preview ",
360
- filename
361
- ] }),
362
- /* @__PURE__ */ jsx2("p", { className: "text-xs mt-1", children: "Download to view this file" })
363
- ] });
364
- }
365
- function FilePreview({
366
- filename,
367
- content,
368
- blobUrl,
369
- mimeType,
370
- onClose,
371
- onDownload,
372
- hideHeader = false,
373
- className
374
- }) {
375
- const previewType = getPreviewType(filename, mimeType);
376
- const previewLabel = getPreviewLabel(previewType);
377
- const hasRenderableSource = Boolean(content) || Boolean(blobUrl) || previewType === "unknown" || previewType === "spreadsheet";
378
- return /* @__PURE__ */ jsxs2("div", { className: cn("flex flex-col h-full", className), children: [
379
- !hideHeader && /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border shrink-0", children: [
380
- /* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
381
- /* @__PURE__ */ jsx2("div", { className: "truncate text-sm font-medium text-foreground", children: filename }),
382
- /* @__PURE__ */ jsx2("div", { className: "mt-0.5 text-[11px] uppercase tracking-[0.12em] text-muted-foreground", children: previewLabel })
383
- ] }),
384
- onDownload && /* @__PURE__ */ jsx2(
385
- "button",
386
- {
387
- type: "button",
388
- onClick: onDownload,
389
- "aria-label": `Download ${filename}`,
390
- className: "p-1.5 rounded-[var(--radius-sm)] hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
391
- children: /* @__PURE__ */ jsx2(Download, { className: "h-4 w-4" })
392
- }
393
- ),
394
- onClose && /* @__PURE__ */ jsx2(
395
- "button",
396
- {
397
- type: "button",
398
- onClick: onClose,
399
- "aria-label": `Close ${filename}`,
400
- className: "p-1.5 rounded-[var(--radius-sm)] hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
401
- children: /* @__PURE__ */ jsx2(X, { className: "h-4 w-4" })
402
- }
403
- )
404
- ] }),
405
- /* @__PURE__ */ jsxs2("div", { className: "flex-1 overflow-auto p-3", children: [
406
- previewType === "pdf" && blobUrl && /* @__PURE__ */ jsx2(PdfPreview, { blobUrl, filename }),
407
- previewType === "image" && blobUrl && /* @__PURE__ */ jsx2(ImagePreview, { src: blobUrl, filename }),
408
- previewType === "csv" && typeof content === "string" && /* @__PURE__ */ jsx2(CsvPreview, { content }),
409
- (previewType === "code" || previewType === "json" || previewType === "yaml") && typeof content === "string" && /* @__PURE__ */ jsx2(CodePreview, { content, filename }),
410
- previewType === "text" && typeof content === "string" && /* @__PURE__ */ jsx2(TextPreview, { content }),
411
- previewType === "markdown" && typeof content === "string" && /* @__PURE__ */ jsx2(MarkdownPreview, { content }),
412
- previewType === "spreadsheet" && /* @__PURE__ */ jsx2(
413
- UnsupportedPreview,
414
- {
415
- filename,
416
- title: "Spreadsheet preview is not available in this surface",
417
- description: "Download the workbook or convert it to CSV when you need an inline preview."
418
- }
419
- ),
420
- previewType === "unknown" && typeof content !== "string" && /* @__PURE__ */ jsx2(EmptyPreview, { filename }),
421
- previewType === "unknown" && typeof content === "string" && /* @__PURE__ */ jsx2(TextPreview, { content }),
422
- !hasRenderableSource && typeof content !== "string" && /* @__PURE__ */ jsx2(
423
- UnsupportedPreview,
424
- {
425
- filename,
426
- title: "Preview data is not available yet",
427
- description: "This artifact can be shown once the app provides inline content or a downloadable blob."
428
- }
429
- )
430
- ] })
431
- ] });
432
- }
433
-
434
- // src/files/file-tabs.tsx
435
- import { X as X2, FileText as FileText3, FileCode as FileCode2, FileSpreadsheet as FileSpreadsheet2 } from "lucide-react";
436
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
437
- function getTabIcon(name) {
438
- const ext = name.split(".").pop()?.toLowerCase() || "";
439
- if (["pdf"].includes(ext)) return FileText3;
440
- if (["csv", "xlsx"].includes(ext)) return FileSpreadsheet2;
441
- return FileCode2;
442
- }
443
- function FileTabs({ tabs, activeId, onSelect, onClose, className }) {
444
- if (tabs.length === 0) return null;
445
- return /* @__PURE__ */ jsx3("div", { className: cn("flex items-center border-b border-border bg-background overflow-x-auto", className), children: tabs.map((tab) => {
446
- const isActive = tab.id === activeId;
447
- const Icon = getTabIcon(tab.name);
448
- return /* @__PURE__ */ jsxs3(
449
- "div",
450
- {
451
- className: cn(
452
- "group flex items-center border-r border-border shrink-0",
453
- isActive ? "bg-card text-foreground border-b-2 border-b-primary" : "text-muted-foreground hover:bg-muted/50"
454
- ),
455
- children: [
456
- /* @__PURE__ */ jsxs3(
457
- "button",
458
- {
459
- type: "button",
460
- onClick: () => onSelect(tab.id),
461
- className: "flex min-w-0 items-center gap-1.5 px-3 py-1.5 text-xs transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary/60",
462
- children: [
463
- /* @__PURE__ */ jsx3(Icon, { className: "h-3 w-3 shrink-0" }),
464
- /* @__PURE__ */ jsx3("span", { className: "max-w-[120px] truncate", children: tab.name }),
465
- tab.dirty && /* @__PURE__ */ jsx3("span", { className: "h-1.5 w-1.5 rounded-full bg-primary" })
466
- ]
467
- }
468
- ),
469
- /* @__PURE__ */ jsx3(
470
- "button",
471
- {
472
- type: "button",
473
- "aria-label": `Close ${tab.name}`,
474
- onClick: () => onClose(tab.id),
475
- className: "mr-1 rounded p-0.5 opacity-0 transition-opacity hover:bg-accent focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60 group-hover:opacity-100",
476
- children: /* @__PURE__ */ jsx3(X2, { className: "h-2.5 w-2.5" })
477
- }
478
- )
479
- ]
480
- },
481
- tab.id
482
- );
483
- }) });
484
- }
485
-
486
- // src/files/file-artifact-pane.tsx
487
- import { lazy, Suspense } from "react";
488
- import { Download as Download2, X as X3 } from "lucide-react";
489
- import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
490
- var LazyDocumentEditorPane = lazy(async () => {
491
- const module = await import("./document-editor-pane-TLPVRBBU.js");
492
- return { default: module.DocumentEditorPane };
493
- });
494
- function FileArtifactPane({
495
- filename,
496
- content,
497
- blobUrl,
498
- mimeType,
499
- onClose,
500
- onDownload,
501
- path,
502
- tabs = [],
503
- activeTabId,
504
- onTabSelect,
505
- onTabClose,
506
- eyebrow = "Artifact",
507
- meta,
508
- toolbar,
509
- footer,
510
- className,
511
- editor
512
- }) {
513
- const showTabs = tabs.length > 0 && onTabSelect && onTabClose;
514
- const paneTabs = showTabs ? /* @__PURE__ */ jsx4(
515
- FileTabs,
516
- {
517
- tabs,
518
- activeId: activeTabId,
519
- onSelect: onTabSelect,
520
- onClose: onTabClose
521
- }
522
- ) : void 0;
523
- const isMarkdown = mimeType === "text/markdown" || filename.toLowerCase().endsWith(".md") || path?.toLowerCase().endsWith(".md");
524
- const isEditableMarkdown = isMarkdown && editor?.enabled;
525
- const headerActions = /* @__PURE__ */ jsxs4(Fragment, { children: [
526
- onDownload && /* @__PURE__ */ jsx4(
527
- "button",
528
- {
529
- type: "button",
530
- "aria-label": `Download ${filename}`,
531
- onClick: onDownload,
532
- className: "rounded-[var(--radius-sm)] p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
533
- children: /* @__PURE__ */ jsx4(Download2, { className: "h-4 w-4" })
534
- }
535
- ),
536
- onClose && /* @__PURE__ */ jsx4(
537
- "button",
538
- {
539
- type: "button",
540
- "aria-label": `Close ${filename}`,
541
- onClick: onClose,
542
- className: "rounded-[var(--radius-sm)] p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/60",
543
- children: /* @__PURE__ */ jsx4(X3, { className: "h-4 w-4" })
544
- }
545
- )
546
- ] });
547
- if (isEditableMarkdown) {
548
- return /* @__PURE__ */ jsx4(
549
- Suspense,
550
- {
551
- fallback: /* @__PURE__ */ jsx4(
552
- ArtifactPane,
553
- {
554
- eyebrow,
555
- title: filename,
556
- subtitle: path,
557
- meta,
558
- toolbar,
559
- footer,
560
- className,
561
- tabs: paneTabs,
562
- headerActions,
563
- children: /* @__PURE__ */ jsx4("div", { 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", children: "Loading editor\u2026" })
564
- }
565
- ),
566
- children: /* @__PURE__ */ jsx4(
567
- LazyDocumentEditorPane,
568
- {
569
- eyebrow,
570
- title: filename,
571
- subtitle: path,
572
- meta,
573
- toolbar,
574
- footer,
575
- className,
576
- tabs: paneTabs,
577
- headerActions,
578
- markdown: content ?? "",
579
- mode: editor.mode,
580
- defaultMode: editor.defaultMode,
581
- onModeChange: editor.onModeChange,
582
- backend: editor.backend,
583
- collaboration: editor.collaboration,
584
- placeholder: editor.placeholder,
585
- autoFocus: editor.autoFocus,
586
- readOnly: editor.readOnly,
587
- saving: editor.saving,
588
- saveLabel: editor.saveLabel,
589
- onChange: editor.onChange,
590
- onSave: editor.onSave,
591
- previewClassName: editor.previewClassName,
592
- editorClassName: editor.editorClassName
593
- }
594
- )
595
- }
596
- );
597
- }
598
- return /* @__PURE__ */ jsx4(
599
- ArtifactPane,
600
- {
601
- eyebrow,
602
- title: filename,
603
- subtitle: path,
604
- meta,
605
- toolbar,
606
- footer,
607
- className,
608
- tabs: paneTabs,
609
- headerActions,
610
- children: /* @__PURE__ */ jsx4(
611
- FilePreview,
612
- {
613
- filename,
614
- content,
615
- blobUrl,
616
- mimeType,
617
- hideHeader: true
618
- }
619
- )
620
- }
621
- );
622
- }
623
-
624
- export {
625
- filterFileTree,
626
- FileTree,
627
- FilePreview,
628
- FileTabs,
629
- FileArtifactPane
630
- };