@tangle-network/ui 11.7.0 → 11.9.0

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 (41) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/chat.js +10 -9
  3. package/dist/{chunk-3M7BPSSW.js → chunk-3TI5DEHV.js} +1 -1
  4. package/dist/chunk-4CLN43XT.js +45 -0
  5. package/dist/{chunk-UYTRNR7Z.js → chunk-565EATZZ.js} +1 -1
  6. package/dist/{chunk-VDCZHOOO.js → chunk-7YOCS6IF.js} +6 -6
  7. package/dist/{chunk-P5F43A65.js → chunk-EOAX2ENE.js} +2 -1
  8. package/dist/{chunk-XT4JMYVB.js → chunk-KNYSKNZX.js} +5 -3
  9. package/dist/{chunk-EIUE5GV2.js → chunk-ND3ZFXQK.js} +1 -44
  10. package/dist/{chunk-AAUNOHVL.js → chunk-NWECTSOH.js} +1 -1
  11. package/dist/{chunk-CVX53NCC.js → chunk-TN4FUEWY.js} +7 -7
  12. package/dist/{chunk-4ENFLPWQ.js → chunk-VPWY4I5O.js} +1 -1
  13. package/dist/{chunk-ZRVH3WCA.js → chunk-XU3HB5QL.js} +21 -1
  14. package/dist/{chunk-6RIX7M27.js → chunk-XYAIX4SU.js} +2 -2
  15. package/dist/{chunk-PLWRAS5Z.js → chunk-YJ6RE5WV.js} +272 -108
  16. package/dist/{chunk-LFVF2HFB.js → chunk-YTO5V6QS.js} +1 -1
  17. package/dist/{chunk-QGTIBEPX.js → chunk-ZKCEAIIZ.js} +1 -1
  18. package/dist/{document-editor-pane-A3JURPW5.js → document-editor-pane-EX25CEYW.js} +2 -2
  19. package/dist/editor.js +2 -2
  20. package/dist/files.d.ts +41 -12
  21. package/dist/files.js +14 -6
  22. package/dist/hooks.js +9 -8
  23. package/dist/index.d.ts +2 -1
  24. package/dist/index.js +32 -24
  25. package/dist/markdown.d.ts +4 -1
  26. package/dist/markdown.js +1 -1
  27. package/dist/openui.js +2 -2
  28. package/dist/run.js +10 -9
  29. package/dist/sdk-hooks.js +9 -8
  30. package/dist/tool-previews.js +2 -2
  31. package/dist/utils.js +6 -4
  32. package/package.json +3 -3
  33. package/src/files/file-artifact-pane.stories.tsx +149 -0
  34. package/src/files/file-artifact-pane.test.tsx +192 -0
  35. package/src/files/file-artifact-pane.tsx +6 -1
  36. package/src/files/file-format.ts +42 -4
  37. package/src/files/file-preview-kind.test.ts +109 -0
  38. package/src/files/file-preview.tsx +315 -132
  39. package/src/files/index.ts +8 -1
  40. package/src/markdown/markdown.test.tsx +26 -2
  41. package/src/markdown/markdown.tsx +5 -2
package/dist/files.js CHANGED
@@ -1,23 +1,29 @@
1
1
  import {
2
+ CSV_PREVIEW_ROW_LIMIT,
2
3
  FileArtifactPane,
3
4
  FilePreview,
4
5
  FileTabs,
5
6
  FileTree,
6
7
  RichFileTree,
7
- filterFileTree
8
- } from "./chunk-PLWRAS5Z.js";
8
+ filterFileTree,
9
+ parseCsv
10
+ } from "./chunk-YJ6RE5WV.js";
11
+ import "./chunk-4CLN43XT.js";
9
12
  import {
10
13
  detectFileFormat,
11
14
  fileExtension,
12
15
  getCodeLanguage,
13
16
  getFormatLabel,
14
- getSyntaxLanguage
15
- } from "./chunk-ZRVH3WCA.js";
17
+ getSyntaxLanguage,
18
+ resolveFilePreviewKind
19
+ } from "./chunk-XU3HB5QL.js";
20
+ import "./chunk-MKTSMWVD.js";
16
21
  import "./chunk-LTEKI7YJ.js";
17
- import "./chunk-P5F43A65.js";
22
+ import "./chunk-EOAX2ENE.js";
18
23
  import "./chunk-WUQDUBJG.js";
19
24
  import "./chunk-RQHJBTEU.js";
20
25
  export {
26
+ CSV_PREVIEW_ROW_LIMIT,
21
27
  FileArtifactPane,
22
28
  FilePreview,
23
29
  FileTabs,
@@ -28,5 +34,7 @@ export {
28
34
  filterFileTree,
29
35
  getCodeLanguage,
30
36
  getFormatLabel,
31
- getSyntaxLanguage
37
+ getSyntaxLanguage,
38
+ parseCsv,
39
+ resolveFilePreviewKind
32
40
  };
package/dist/hooks.js CHANGED
@@ -11,20 +11,21 @@ import {
11
11
  useSSEStream,
12
12
  useSdkSession,
13
13
  useToolCallStream
14
- } from "./chunk-4ENFLPWQ.js";
14
+ } from "./chunk-VPWY4I5O.js";
15
15
  import "./chunk-OEX7NZE3.js";
16
16
  import {
17
17
  useAutoScroll,
18
18
  useRunCollapseState,
19
19
  useRunGroups
20
- } from "./chunk-UYTRNR7Z.js";
21
- import "./chunk-6RIX7M27.js";
22
- import "./chunk-XT4JMYVB.js";
23
- import "./chunk-EIUE5GV2.js";
24
- import "./chunk-AAUNOHVL.js";
20
+ } from "./chunk-565EATZZ.js";
21
+ import "./chunk-XYAIX4SU.js";
22
+ import "./chunk-KNYSKNZX.js";
23
+ import "./chunk-ND3ZFXQK.js";
24
+ import "./chunk-NWECTSOH.js";
25
25
  import "./chunk-L57WRIND.js";
26
- import "./chunk-ZRVH3WCA.js";
27
- import "./chunk-P5F43A65.js";
26
+ import "./chunk-4CLN43XT.js";
27
+ import "./chunk-XU3HB5QL.js";
28
+ import "./chunk-EOAX2ENE.js";
28
29
  import "./chunk-WUQDUBJG.js";
29
30
  import "./chunk-RQHJBTEU.js";
30
31
  export {
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, Agen
6
6
  export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps, RunRowShell, RunRowShellProps, RunRowStatus, RunRowStatusDot } from './run.js';
7
7
  export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallStatus, d as ToolCallType, p as parseToolEvent } from './tool-call-feed-D9iofJgW.js';
8
8
  export { OpenUIAction, OpenUIActionsNode, OpenUIArtifactRenderer, OpenUIArtifactRendererProps, OpenUIBadgeNode, OpenUICardNode, OpenUICodeNode, OpenUIComponentNode, OpenUIGridNode, OpenUIHeadingNode, OpenUIKeyValueNode, OpenUIMarkdownNode, OpenUIPrimitive, OpenUISeparatorNode, OpenUIStackNode, OpenUIStatNode, OpenUITableNode, OpenUITextNode } from './openui.js';
9
- export { FileArtifactPane, FileArtifactPaneProps, FileFormat, FileNode, FilePreview, FilePreviewProps, FileTabData, FileTabs, FileTabsProps, FileTree, FileTreeProps, FileTreeVisibilityOptions, RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage } from './files.js';
9
+ export { CSV_PREVIEW_ROW_LIMIT, FileArtifactPane, FileArtifactPaneProps, FileFormat, FileNode, FilePreview, FilePreviewKind, FilePreviewProps, FileTabData, FileTabs, FileTabsProps, FileTree, FileTreeProps, FileTreeVisibilityOptions, RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage, parseCsv, resolveFilePreviewKind } from './files.js';
10
10
  export { Markdown, MarkdownProps } from './markdown.js';
11
11
  export { C as CodeBlock, a as CodeBlockProps, b as CopyButton } from './code-block-0kSpWMnf.js';
12
12
  export { AuthHeader, AuthHeaderProps, GitHubLoginButton, GitHubLoginButtonProps, LoginLayout, LoginLayoutProps, SessionUser, UserMenu, UserMenuProps } from './auth.js';
@@ -38,5 +38,6 @@ import '@pierre/trees';
38
38
  import './document-editor-pane-IAEQn_Dl.js';
39
39
  import '@hocuspocus/provider';
40
40
  import 'yjs';
41
+ import 'react-markdown';
41
42
  import 'nanostores';
42
43
  import 'clsx';
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  useSSEStream,
21
21
  useSdkSession,
22
22
  useToolCallStream
23
- } from "./chunk-4ENFLPWQ.js";
23
+ } from "./chunk-VPWY4I5O.js";
24
24
  import {
25
25
  addMessage,
26
26
  addParts,
@@ -146,39 +146,35 @@ import {
146
146
  MessageList,
147
147
  ThinkingIndicator,
148
148
  UserMessage
149
- } from "./chunk-VDCZHOOO.js";
149
+ } from "./chunk-7YOCS6IF.js";
150
150
  import {
151
151
  useAutoScroll,
152
152
  useRunCollapseState,
153
153
  useRunGroups
154
- } from "./chunk-UYTRNR7Z.js";
154
+ } from "./chunk-565EATZZ.js";
155
155
  import {
156
156
  LiveDuration
157
- } from "./chunk-LFVF2HFB.js";
157
+ } from "./chunk-YTO5V6QS.js";
158
158
  import {
159
159
  ToolCallFeed,
160
160
  parseToolEvent
161
- } from "./chunk-6RIX7M27.js";
161
+ } from "./chunk-XYAIX4SU.js";
162
162
  import {
163
163
  InlineThinkingItem,
164
164
  RunGroup
165
- } from "./chunk-CVX53NCC.js";
165
+ } from "./chunk-TN4FUEWY.js";
166
166
  import {
167
167
  ExpandedToolDetail,
168
168
  InlineToolItem,
169
169
  RunRowShell,
170
170
  RunRowStatusDot
171
- } from "./chunk-XT4JMYVB.js";
171
+ } from "./chunk-KNYSKNZX.js";
172
172
  import {
173
173
  TOOL_CATEGORY_ICONS,
174
- formatBytes,
175
- formatDuration,
176
- formatUptime,
177
174
  getToolCategory,
178
175
  getToolDisplayMetadata,
179
- getToolErrorText,
180
- truncateText
181
- } from "./chunk-EIUE5GV2.js";
176
+ getToolErrorText
177
+ } from "./chunk-ND3ZFXQK.js";
182
178
  import {
183
179
  CommandPreview,
184
180
  DiffPreview,
@@ -187,14 +183,14 @@ import {
187
183
  QuestionPreview,
188
184
  WebSearchPreview,
189
185
  WriteFilePreview
190
- } from "./chunk-AAUNOHVL.js";
186
+ } from "./chunk-NWECTSOH.js";
191
187
  import {
192
188
  TextShimmer
193
189
  } from "./chunk-L57WRIND.js";
194
190
  import "./chunk-RQGKSCEZ.js";
195
191
  import {
196
192
  OpenUIArtifactRenderer
197
- } from "./chunk-3M7BPSSW.js";
193
+ } from "./chunk-3TI5DEHV.js";
198
194
  import {
199
195
  Badge,
200
196
  Card,
@@ -215,24 +211,33 @@ import {
215
211
  badgeVariants
216
212
  } from "./chunk-GYPQXTJU.js";
217
213
  import {
218
- Button,
219
- buttonVariants
220
- } from "./chunk-MKTSMWVD.js";
221
- import {
214
+ CSV_PREVIEW_ROW_LIMIT,
222
215
  FileArtifactPane,
223
216
  FilePreview,
224
217
  FileTabs,
225
218
  FileTree,
226
219
  RichFileTree,
227
- filterFileTree
228
- } from "./chunk-PLWRAS5Z.js";
220
+ filterFileTree,
221
+ parseCsv
222
+ } from "./chunk-YJ6RE5WV.js";
223
+ import {
224
+ formatBytes,
225
+ formatDuration,
226
+ formatUptime,
227
+ truncateText
228
+ } from "./chunk-4CLN43XT.js";
229
229
  import {
230
230
  detectFileFormat,
231
231
  fileExtension,
232
232
  getCodeLanguage,
233
233
  getFormatLabel,
234
- getSyntaxLanguage
235
- } from "./chunk-ZRVH3WCA.js";
234
+ getSyntaxLanguage,
235
+ resolveFilePreviewKind
236
+ } from "./chunk-XU3HB5QL.js";
237
+ import {
238
+ Button,
239
+ buttonVariants
240
+ } from "./chunk-MKTSMWVD.js";
236
241
  import {
237
242
  Tabs,
238
243
  TabsContent,
@@ -245,7 +250,7 @@ import {
245
250
  import "./chunk-5Z5ZYMOJ.js";
246
251
  import {
247
252
  Markdown
248
- } from "./chunk-P5F43A65.js";
253
+ } from "./chunk-EOAX2ENE.js";
249
254
  import {
250
255
  CodeBlock,
251
256
  CopyButton
@@ -262,6 +267,7 @@ export {
262
267
  AvatarImage,
263
268
  Badge,
264
269
  Button,
270
+ CSV_PREVIEW_ROW_LIMIT,
265
271
  Card,
266
272
  CardContent,
267
273
  CardDescription,
@@ -413,10 +419,12 @@ export {
413
419
  hasBackgroundRunningSessions,
414
420
  isStreamingAtom,
415
421
  messagesAtom,
422
+ parseCsv,
416
423
  parseToolEvent,
417
424
  partMapAtom,
418
425
  registerActiveSession,
419
426
  resetActiveSessions,
427
+ resolveFilePreviewKind,
420
428
  setActiveSessionAttention,
421
429
  setActiveSessionConnection,
422
430
  setActiveSessionError,
@@ -1,15 +1,18 @@
1
1
  import * as React from 'react';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
+ import { UrlTransform } from 'react-markdown';
3
4
  export { C as CodeBlock, a as CodeBlockProps, b as CopyButton } from './code-block-0kSpWMnf.js';
4
5
 
5
6
  interface MarkdownProps {
6
7
  children: string;
7
8
  className?: string;
9
+ /** Transform parsed link and image URLs before sanitisation. */
10
+ urlTransform?: UrlTransform;
8
11
  }
9
12
  /**
10
13
  * Renders Markdown content with GFM support, XSS sanitisation, and
11
14
  * custom code block rendering via our CodeBlock component.
12
15
  */
13
- declare const Markdown: React.MemoExoticComponent<({ children, className }: MarkdownProps) => react_jsx_runtime.JSX.Element>;
16
+ declare const Markdown: React.MemoExoticComponent<({ children, className, urlTransform }: MarkdownProps) => react_jsx_runtime.JSX.Element>;
14
17
 
15
18
  export { Markdown, type MarkdownProps };
package/dist/markdown.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import "./chunk-5Z5ZYMOJ.js";
2
2
  import {
3
3
  Markdown
4
- } from "./chunk-P5F43A65.js";
4
+ } from "./chunk-EOAX2ENE.js";
5
5
  import {
6
6
  CodeBlock,
7
7
  CopyButton
package/dist/openui.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import "./chunk-RQGKSCEZ.js";
2
2
  import {
3
3
  OpenUIArtifactRenderer
4
- } from "./chunk-3M7BPSSW.js";
4
+ } from "./chunk-3TI5DEHV.js";
5
5
  import "./chunk-GYPQXTJU.js";
6
6
  import "./chunk-MKTSMWVD.js";
7
- import "./chunk-P5F43A65.js";
7
+ import "./chunk-EOAX2ENE.js";
8
8
  import "./chunk-WUQDUBJG.js";
9
9
  import "./chunk-RQHJBTEU.js";
10
10
  export {
package/dist/run.js CHANGED
@@ -1,28 +1,29 @@
1
1
  import {
2
2
  LiveDuration
3
- } from "./chunk-LFVF2HFB.js";
3
+ } from "./chunk-YTO5V6QS.js";
4
4
  import {
5
5
  ToolCallFeed,
6
6
  parseToolEvent
7
- } from "./chunk-6RIX7M27.js";
7
+ } from "./chunk-XYAIX4SU.js";
8
8
  import {
9
9
  InlineThinkingItem,
10
10
  RunGroup
11
- } from "./chunk-CVX53NCC.js";
11
+ } from "./chunk-TN4FUEWY.js";
12
12
  import {
13
13
  ExpandedToolDetail,
14
14
  InlineToolItem,
15
15
  RunRowShell,
16
16
  RunRowStatusDot
17
- } from "./chunk-XT4JMYVB.js";
18
- import "./chunk-EIUE5GV2.js";
19
- import "./chunk-AAUNOHVL.js";
17
+ } from "./chunk-KNYSKNZX.js";
18
+ import "./chunk-ND3ZFXQK.js";
19
+ import "./chunk-NWECTSOH.js";
20
20
  import "./chunk-L57WRIND.js";
21
- import "./chunk-3M7BPSSW.js";
21
+ import "./chunk-3TI5DEHV.js";
22
22
  import "./chunk-GYPQXTJU.js";
23
+ import "./chunk-4CLN43XT.js";
24
+ import "./chunk-XU3HB5QL.js";
23
25
  import "./chunk-MKTSMWVD.js";
24
- import "./chunk-ZRVH3WCA.js";
25
- import "./chunk-P5F43A65.js";
26
+ import "./chunk-EOAX2ENE.js";
26
27
  import "./chunk-WUQDUBJG.js";
27
28
  import "./chunk-RQHJBTEU.js";
28
29
  export {
package/dist/sdk-hooks.js CHANGED
@@ -5,20 +5,21 @@ import {
5
5
  useSSEStream,
6
6
  useSdkSession,
7
7
  useToolCallStream
8
- } from "./chunk-4ENFLPWQ.js";
8
+ } from "./chunk-VPWY4I5O.js";
9
9
  import "./chunk-OEX7NZE3.js";
10
10
  import {
11
11
  useAutoScroll,
12
12
  useRunCollapseState,
13
13
  useRunGroups
14
- } from "./chunk-UYTRNR7Z.js";
15
- import "./chunk-6RIX7M27.js";
16
- import "./chunk-XT4JMYVB.js";
17
- import "./chunk-EIUE5GV2.js";
18
- import "./chunk-AAUNOHVL.js";
14
+ } from "./chunk-565EATZZ.js";
15
+ import "./chunk-XYAIX4SU.js";
16
+ import "./chunk-KNYSKNZX.js";
17
+ import "./chunk-ND3ZFXQK.js";
18
+ import "./chunk-NWECTSOH.js";
19
19
  import "./chunk-L57WRIND.js";
20
- import "./chunk-ZRVH3WCA.js";
21
- import "./chunk-P5F43A65.js";
20
+ import "./chunk-4CLN43XT.js";
21
+ import "./chunk-XU3HB5QL.js";
22
+ import "./chunk-EOAX2ENE.js";
22
23
  import "./chunk-WUQDUBJG.js";
23
24
  import "./chunk-RQHJBTEU.js";
24
25
  export {
@@ -7,8 +7,8 @@ import {
7
7
  QuestionPreview,
8
8
  WebSearchPreview,
9
9
  WriteFilePreview
10
- } from "./chunk-AAUNOHVL.js";
11
- import "./chunk-ZRVH3WCA.js";
10
+ } from "./chunk-NWECTSOH.js";
11
+ import "./chunk-XU3HB5QL.js";
12
12
  import "./chunk-WUQDUBJG.js";
13
13
  import "./chunk-RQHJBTEU.js";
14
14
  export {
package/dist/utils.js CHANGED
@@ -4,14 +4,16 @@ import {
4
4
  } from "./chunk-XGKULLYE.js";
5
5
  import {
6
6
  TOOL_CATEGORY_ICONS,
7
+ getToolCategory,
8
+ getToolDisplayMetadata,
9
+ getToolErrorText
10
+ } from "./chunk-ND3ZFXQK.js";
11
+ import {
7
12
  formatBytes,
8
13
  formatDuration,
9
14
  formatUptime,
10
- getToolCategory,
11
- getToolDisplayMetadata,
12
- getToolErrorText,
13
15
  truncateText
14
- } from "./chunk-EIUE5GV2.js";
16
+ } from "./chunk-4CLN43XT.js";
15
17
  import {
16
18
  cn
17
19
  } from "./chunk-RQHJBTEU.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "11.7.0",
3
+ "version": "11.9.0",
4
4
  "description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -134,6 +134,7 @@
134
134
  "turndown": "^7.2.2"
135
135
  },
136
136
  "peerDependencies": {
137
+ "@tangle-network/brand": "^1.5.0",
137
138
  "@hocuspocus/provider": ">=2.15.0 <5.0.0",
138
139
  "@nanostores/react": ">=0.8.4 <2.0.0",
139
140
  "@tiptap/core": ">=3.20.4 <4.0.0",
@@ -145,8 +146,7 @@
145
146
  "react": "^18 || ^19",
146
147
  "react-dom": "^18 || ^19",
147
148
  "react-router": "^7 || ^8",
148
- "yjs": "^13.6.0",
149
- "@tangle-network/brand": "^1.5.0"
149
+ "yjs": "^13.6.0"
150
150
  },
151
151
  "peerDependenciesMeta": {
152
152
  "@nanostores/react": {
@@ -0,0 +1,149 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { FileArtifactPane } from "./file-artifact-pane";
3
+
4
+ const TS_SOURCE = `interface SandboxConfig {
5
+ model: string
6
+ timeout: number
7
+ env: Record<string, string>
8
+ }
9
+
10
+ // Create a new sandbox and stream its output.
11
+ export async function run(config: SandboxConfig) {
12
+ const sandbox = await Sandbox.create(config)
13
+ for await (const chunk of sandbox.stream()) {
14
+ process.stdout.write(chunk)
15
+ }
16
+ }`;
17
+
18
+ const MARKDOWN_SOURCE = `# Run report
19
+
20
+ The agent finished **3 of 3** tasks.
21
+
22
+ | Task | Result |
23
+ | --- | --- |
24
+ | Build | pass |
25
+ | Test | 315 / 315 |
26
+ | Deploy | staging |
27
+
28
+ \`\`\`ts
29
+ export const ready = true
30
+ \`\`\`
31
+ `;
32
+
33
+ // A transparent SVG, larger than the pane, so the checker ground shows through
34
+ // and the fit-to-pane / natural-size toggle has a visible effect.
35
+ const IMAGE_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 640 360">
36
+ <defs>
37
+ <linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
38
+ <stop offset="0" stop-color="#8263FF"/>
39
+ <stop offset="1" stop-color="#10b981"/>
40
+ </linearGradient>
41
+ </defs>
42
+ <circle cx="220" cy="180" r="120" fill="url(#g)"/>
43
+ <rect x="360" y="80" width="200" height="200" rx="28" fill="#FFB347" opacity="0.9"/>
44
+ <text x="320" y="330" text-anchor="middle" font-family="sans-serif" font-size="22" fill="#E8E6F6">chart.svg · 1600 × 900</text>
45
+ </svg>`;
46
+ const IMAGE_URL = `data:image/svg+xml;utf8,${encodeURIComponent(IMAGE_SVG)}`;
47
+
48
+ // One-page PDF (Helvetica text and a rule) so the viewer has real content.
49
+ const PDF_URL =
50
+ "data:application/pdf;base64,JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMiAwIFIgPj4KZW5kb2JqCjIgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFszIDAgUl0gL0NvdW50IDEgPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCAyIDAgUiAvTWVkaWFCb3ggWzAgMCA2MTIgNzkyXSAvQ29udGVudHMgNCAwIFIgL1Jlc291cmNlcyA8PCAvRm9udCA8PCAvRjEgNSAwIFIgPj4gPj4gPj4KZW5kb2JqCjQgMCBvYmoKPDwgL0xlbmd0aCAyODkgPj4Kc3RyZWFtCkJUIC9GMSAyMiBUZiA1NiA3MDAgVGQgKEZpbGVBcnRpZmFjdFBhbmUpIFRqIEVUCkJUIC9GMSAxMiBUZiA1NiA2NzIgVGQgKFBERiBwcmV2aWV3IHJlbmRlcnMgdGhlIGJsb2JVcmwgYXQgZnVsbCBwYW5lIGhlaWdodC4pIFRqIEVUCkJUIC9GMSAxMiBUZiA1NiA2NTIgVGQgKEV2ZXJ5IGNvbnN1bWVyIG9mIEB0YW5nbGUtbmV0d29yay91aS9maWxlcyBnZXRzIHRoaXMgZm9yIGZyZWUuKSBUaiBFVAo1NiA2MjAgbSA1NTYgNjIwIGwgUwpCVCAvRjEgMTAgVGYgNTYgNTk2IFRkIChQYWdlIDEgb2YgMSkgVGogRVQKZW5kc3RyZWFtCmVuZG9iago1IDAgb2JqCjw8IC9UeXBlIC9Gb250IC9TdWJ0eXBlIC9UeXBlMSAvQmFzZUZvbnQgL0hlbHZldGljYSA+PgplbmRvYmoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDA5IDAwMDAwIG4gCjAwMDAwMDAwNTggMDAwMDAgbiAKMDAwMDAwMDExNSAwMDAwMCBuIAowMDAwMDAwMjQxIDAwMDAwIG4gCjAwMDAwMDA1ODEgMDAwMDAgbiAKdHJhaWxlcgo8PCAvU2l6ZSA2IC9Sb290IDEgMCBSID4+CnN0YXJ0eHJlZgo2NTEKJSVFT0YK";
51
+
52
+ const CSV_SOURCE = [
53
+ "id,name,role,note,active",
54
+ ...Array.from({ length: 520 }, (_, i) =>
55
+ [
56
+ i + 1,
57
+ `"Lovelace, Ada ${i + 1}"`,
58
+ ["engineer", "maintainer", "architect"][i % 3],
59
+ `"Handles ""quoted"" values, and commas"`,
60
+ i % 4 === 0 ? "false" : "true",
61
+ ].join(","),
62
+ ),
63
+ ].join("\n");
64
+
65
+ // CC0 sample media hosted by MDN; the story only needs a playable src.
66
+ const VIDEO_URL = "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4";
67
+ const AUDIO_URL = "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3";
68
+
69
+ const meta: Meta<typeof FileArtifactPane> = {
70
+ title: "Files/FileArtifactPane",
71
+ component: FileArtifactPane,
72
+ parameters: { layout: "fullscreen" },
73
+ argTypes: {
74
+ onDownload: { action: "download" },
75
+ onClose: { action: "close" },
76
+ },
77
+ decorators: [
78
+ (Story) => (
79
+ <div className="h-[560px] w-[760px] overflow-hidden rounded-xl border border-border bg-card text-foreground">
80
+ <Story />
81
+ </div>
82
+ ),
83
+ ],
84
+ };
85
+
86
+ export default meta;
87
+ type Story = StoryObj<typeof FileArtifactPane>;
88
+
89
+ export const Code: Story = {
90
+ args: { filename: "run.ts", path: "src/run.ts", content: TS_SOURCE },
91
+ };
92
+
93
+ export const Image: Story = {
94
+ args: {
95
+ filename: "chart.svg",
96
+ path: "out/chart.svg",
97
+ blobUrl: IMAGE_URL,
98
+ mimeType: "image/svg+xml",
99
+ size: 1_204,
100
+ },
101
+ };
102
+
103
+ export const Pdf: Story = {
104
+ name: "PDF",
105
+ args: {
106
+ filename: "report.pdf",
107
+ path: "out/report.pdf",
108
+ blobUrl: PDF_URL,
109
+ mimeType: "application/pdf",
110
+ size: 834,
111
+ },
112
+ };
113
+
114
+ export const Csv: Story = {
115
+ name: "CSV (520 rows, capped at 500)",
116
+ args: { filename: "people.csv", path: "data/people.csv", content: CSV_SOURCE },
117
+ };
118
+
119
+ export const Video: Story = {
120
+ args: {
121
+ filename: "flower.mp4",
122
+ path: "media/flower.mp4",
123
+ blobUrl: VIDEO_URL,
124
+ mimeType: "video/mp4",
125
+ },
126
+ };
127
+
128
+ export const Audio: Story = {
129
+ args: {
130
+ filename: "t-rex-roar.mp3",
131
+ path: "media/t-rex-roar.mp3",
132
+ blobUrl: AUDIO_URL,
133
+ mimeType: "audio/mpeg",
134
+ },
135
+ };
136
+
137
+ export const Spreadsheet: Story = {
138
+ args: { filename: "ledger.xlsx", path: "finance/ledger.xlsx", size: 48_213 },
139
+ };
140
+
141
+ export const MarkdownProse: Story = {
142
+ name: "Markdown",
143
+ args: { filename: "REPORT.md", path: "out/REPORT.md", content: MARKDOWN_SOURCE },
144
+ };
145
+
146
+ export const BinaryWithoutLink: Story = {
147
+ name: "Binary without a download link",
148
+ args: { filename: "weights.bin", path: "model/weights.bin", size: 402_653_184 },
149
+ };