@shapesos/clay 0.17.0 → 0.18.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 (80) hide show
  1. package/dist/ai-elements.cjs +3 -1
  2. package/dist/ai-elements.cjs.map +1 -1
  3. package/dist/ai-elements.js +4 -4
  4. package/dist/artifacts.cjs +963 -34
  5. package/dist/artifacts.cjs.map +1 -1
  6. package/dist/artifacts.d.cts +20 -3
  7. package/dist/artifacts.d.ts +20 -3
  8. package/dist/artifacts.js +13 -5
  9. package/dist/blocks.cjs +677 -50
  10. package/dist/blocks.cjs.map +1 -1
  11. package/dist/blocks.css +1 -1
  12. package/dist/blocks.d.cts +3 -3
  13. package/dist/blocks.d.ts +3 -3
  14. package/dist/blocks.js +5 -5
  15. package/dist/button.cjs +3 -1
  16. package/dist/button.cjs.map +1 -1
  17. package/dist/button.js +2 -2
  18. package/dist/capture.cjs +3 -1
  19. package/dist/capture.cjs.map +1 -1
  20. package/dist/capture.js +2 -2
  21. package/dist/chart.cjs +3 -1
  22. package/dist/chart.cjs.map +1 -1
  23. package/dist/chart.js +2 -2
  24. package/dist/chat.cjs +701 -74
  25. package/dist/chat.cjs.map +1 -1
  26. package/dist/chat.d.cts +2 -2
  27. package/dist/chat.d.ts +2 -2
  28. package/dist/chat.js +6 -6
  29. package/dist/{chunk-46ZYTBX5.js → chunk-7MY4X4YL.js} +3 -3
  30. package/dist/chunk-BHHJOG5X.js +1 -0
  31. package/dist/{chunk-B6GAPZ2R.js → chunk-CATIRDZP.js} +5 -5
  32. package/dist/{chunk-B4U37WIH.js → chunk-CFCLVJIO.js} +2 -2
  33. package/dist/{chunk-PYDVANWI.js → chunk-E36VI2HA.js} +2 -2
  34. package/dist/{chunk-PUVZ2S3F.js → chunk-G4NXVFXU.js} +2 -2
  35. package/dist/{chunk-JAGNXEWK.js → chunk-GK4XW4BC.js} +2 -2
  36. package/dist/{chunk-4VE6ZXXW.js → chunk-MQP57DOP.js} +3 -3
  37. package/dist/{chunk-6YZ65KPW.js → chunk-QR4VBGK4.js} +673 -42
  38. package/dist/chunk-QR4VBGK4.js.map +1 -0
  39. package/dist/{chunk-JF3P66JF.js → chunk-SN3ORQSJ.js} +4 -2
  40. package/dist/{chunk-JF3P66JF.js.map → chunk-SN3ORQSJ.js.map} +1 -1
  41. package/dist/{chunk-PGR2MDDU.js → chunk-W66OJM55.js} +2 -2
  42. package/dist/{chunk-7OYIDM42.js → chunk-XKURJ72I.js} +2 -2
  43. package/dist/{dom-to-image-NATF3446.js → dom-to-image-QB7KMTAE.js} +3 -3
  44. package/dist/icon.cjs +3 -1
  45. package/dist/icon.cjs.map +1 -1
  46. package/dist/icon.js +2 -2
  47. package/dist/index.cjs +767 -132
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.cts +3 -3
  50. package/dist/index.d.ts +3 -3
  51. package/dist/index.js +19 -11
  52. package/dist/keyboard-shortcut.cjs +3 -1
  53. package/dist/keyboard-shortcut.cjs.map +1 -1
  54. package/dist/keyboard-shortcut.js +2 -2
  55. package/dist/text-area.cjs +3 -1
  56. package/dist/text-area.cjs.map +1 -1
  57. package/dist/text-area.js +2 -2
  58. package/dist/tokens.cjs +3 -1
  59. package/dist/tokens.cjs.map +1 -1
  60. package/dist/tokens.d.cts +1 -0
  61. package/dist/tokens.d.ts +1 -0
  62. package/dist/tokens.js +1 -1
  63. package/dist/{types-CW45GBXl.d.cts → types-BDYPVP2N.d.cts} +1 -1
  64. package/dist/{types-D1b8v7EY.d.ts → types-BMwa4bPW.d.ts} +1 -1
  65. package/dist/{types-GCkXbyFm.d.ts → types-C8JtnwNY.d.ts} +200 -4
  66. package/dist/{types-BzXPBy6s.d.cts → types-DTdDFU3O.d.cts} +200 -4
  67. package/package.json +1 -1
  68. package/dist/chunk-6YZ65KPW.js.map +0 -1
  69. package/dist/chunk-RSRNSWJN.js +0 -1
  70. /package/dist/{chunk-46ZYTBX5.js.map → chunk-7MY4X4YL.js.map} +0 -0
  71. /package/dist/{chunk-RSRNSWJN.js.map → chunk-BHHJOG5X.js.map} +0 -0
  72. /package/dist/{chunk-B6GAPZ2R.js.map → chunk-CATIRDZP.js.map} +0 -0
  73. /package/dist/{chunk-B4U37WIH.js.map → chunk-CFCLVJIO.js.map} +0 -0
  74. /package/dist/{chunk-PYDVANWI.js.map → chunk-E36VI2HA.js.map} +0 -0
  75. /package/dist/{chunk-PUVZ2S3F.js.map → chunk-G4NXVFXU.js.map} +0 -0
  76. /package/dist/{chunk-JAGNXEWK.js.map → chunk-GK4XW4BC.js.map} +0 -0
  77. /package/dist/{chunk-4VE6ZXXW.js.map → chunk-MQP57DOP.js.map} +0 -0
  78. /package/dist/{chunk-PGR2MDDU.js.map → chunk-W66OJM55.js.map} +0 -0
  79. /package/dist/{chunk-7OYIDM42.js.map → chunk-XKURJ72I.js.map} +0 -0
  80. /package/dist/{dom-to-image-NATF3446.js.map → dom-to-image-QB7KMTAE.js.map} +0 -0
package/dist/chat.cjs CHANGED
@@ -128,7 +128,9 @@ var init_colors = __esm({
128
128
  "red-200": "#FECACA",
129
129
  "red-400": "#F7776C",
130
130
  "red-500": "#EF4444",
131
- "red-600": "#DC2626"
131
+ "red-600": "#DC2626",
132
+ // Deck
133
+ "deck-canvas": "#faf8f5"
132
134
  };
133
135
  }
134
136
  });
@@ -276,7 +278,7 @@ __export(chat_exports, {
276
278
  module.exports = __toCommonJS(chat_exports);
277
279
 
278
280
  // src/components/chat/chat-message/chat-message.tsx
279
- var import_react19 = require("react");
281
+ var import_react22 = require("react");
280
282
 
281
283
  // src/components/blocks/types.ts
282
284
  var blockTypes = {
@@ -287,7 +289,8 @@ var blockTypes = {
287
289
  // src/components/artifacts/artifact-base.ts
288
290
  var artifactTypes = {
289
291
  TABLE: "TABLE",
290
- CHART: "CHART"
292
+ CHART: "CHART",
293
+ DECK: "DECK"
291
294
  };
292
295
 
293
296
  // src/components/artifacts/chart-artifact/types.ts
@@ -312,6 +315,34 @@ var DEFAULT_TABLE_ARTIFACT_LABELS = {
312
315
  empty: "No rows to display."
313
316
  };
314
317
 
318
+ // src/components/artifacts/deck-artifact/types.ts
319
+ var deckBlockTypes = {
320
+ TEXT: "TEXT",
321
+ CHART: "CHART",
322
+ TABLE: "TABLE"
323
+ };
324
+ var deckSlideKinds = {
325
+ TITLE: "TITLE",
326
+ AGENDA: "AGENDA",
327
+ SECTION: "SECTION",
328
+ CONTENT: "CONTENT",
329
+ CLOSING: "CLOSING"
330
+ };
331
+ var DEFAULT_DECK_ARTIFACT_LABELS = {
332
+ previous: "Previous slide",
333
+ next: "Next slide",
334
+ position: "Slide {current} of {total}",
335
+ download: "Download",
336
+ unavailable: "Deck content is unavailable.",
337
+ enterFullscreen: "Fullscreen",
338
+ exitFullscreen: "Exit fullscreen",
339
+ thankYou: "Thank you",
340
+ questions: "Questions?",
341
+ agenda: "Agenda",
342
+ chart: DEFAULT_CHART_ARTIFACT_LABELS,
343
+ table: DEFAULT_TABLE_ARTIFACT_LABELS
344
+ };
345
+
315
346
  // src/components/artifacts/chart-artifact/chart-artifact.tsx
316
347
  var import_react13 = require("react");
317
348
 
@@ -404,37 +435,53 @@ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
404
435
  var __iconNode = [["path", { "d": "M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0", "key": "svg-0" }], ["path", { "d": "M12 8v4", "key": "svg-1" }], ["path", { "d": "M12 16h.01", "key": "svg-2" }]];
405
436
  var IconAlertCircle = createReactComponent("outline", "alert-circle", "AlertCircle", __iconNode);
406
437
 
438
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconArrowsMaximize.mjs
439
+ var __iconNode2 = [["path", { "d": "M16 4l4 0l0 4", "key": "svg-0" }], ["path", { "d": "M14 10l6 -6", "key": "svg-1" }], ["path", { "d": "M8 20l-4 0l0 -4", "key": "svg-2" }], ["path", { "d": "M4 20l6 -6", "key": "svg-3" }], ["path", { "d": "M16 20l4 0l0 -4", "key": "svg-4" }], ["path", { "d": "M14 14l6 6", "key": "svg-5" }], ["path", { "d": "M8 4l-4 0l0 4", "key": "svg-6" }], ["path", { "d": "M4 4l6 6", "key": "svg-7" }]];
440
+ var IconArrowsMaximize = createReactComponent("outline", "arrows-maximize", "ArrowsMaximize", __iconNode2);
441
+
442
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconArrowsMinimize.mjs
443
+ var __iconNode3 = [["path", { "d": "M5 9l4 0l0 -4", "key": "svg-0" }], ["path", { "d": "M3 3l6 6", "key": "svg-1" }], ["path", { "d": "M5 15l4 0l0 4", "key": "svg-2" }], ["path", { "d": "M3 21l6 -6", "key": "svg-3" }], ["path", { "d": "M19 9l-4 0l0 -4", "key": "svg-4" }], ["path", { "d": "M15 9l6 -6", "key": "svg-5" }], ["path", { "d": "M19 15l-4 0l0 4", "key": "svg-6" }], ["path", { "d": "M15 15l6 6", "key": "svg-7" }]];
444
+ var IconArrowsMinimize = createReactComponent("outline", "arrows-minimize", "ArrowsMinimize", __iconNode3);
445
+
407
446
  // node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
408
- var __iconNode2 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
409
- var IconCheck = createReactComponent("outline", "check", "Check", __iconNode2);
447
+ var __iconNode4 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
448
+ var IconCheck = createReactComponent("outline", "check", "Check", __iconNode4);
449
+
450
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconChevronLeft.mjs
451
+ var __iconNode5 = [["path", { "d": "M15 6l-6 6l6 6", "key": "svg-0" }]];
452
+ var IconChevronLeft = createReactComponent("outline", "chevron-left", "ChevronLeft", __iconNode5);
453
+
454
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconChevronRight.mjs
455
+ var __iconNode6 = [["path", { "d": "M9 6l6 6l-6 6", "key": "svg-0" }]];
456
+ var IconChevronRight = createReactComponent("outline", "chevron-right", "ChevronRight", __iconNode6);
410
457
 
411
458
  // node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
412
- var __iconNode3 = [["path", { "d": "M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666", "key": "svg-0" }], ["path", { "d": "M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1", "key": "svg-1" }]];
413
- var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode3);
459
+ var __iconNode7 = [["path", { "d": "M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666", "key": "svg-0" }], ["path", { "d": "M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1", "key": "svg-1" }]];
460
+ var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode7);
414
461
 
415
462
  // node_modules/@tabler/icons-react/dist/esm/icons/IconDownload.mjs
416
- var __iconNode4 = [["path", { "d": "M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2", "key": "svg-0" }], ["path", { "d": "M7 11l5 5l5 -5", "key": "svg-1" }], ["path", { "d": "M12 4l0 12", "key": "svg-2" }]];
417
- var IconDownload = createReactComponent("outline", "download", "Download", __iconNode4);
463
+ var __iconNode8 = [["path", { "d": "M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2", "key": "svg-0" }], ["path", { "d": "M7 11l5 5l5 -5", "key": "svg-1" }], ["path", { "d": "M12 4l0 12", "key": "svg-2" }]];
464
+ var IconDownload = createReactComponent("outline", "download", "Download", __iconNode8);
418
465
 
419
466
  // node_modules/@tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs
420
- var __iconNode5 = [["path", { "d": "M14 3v4a1 1 0 0 0 1 1h4", "key": "svg-0" }], ["path", { "d": "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2", "key": "svg-1" }], ["path", { "d": "M8 11h8v7h-8l0 -7", "key": "svg-2" }], ["path", { "d": "M8 15h8", "key": "svg-3" }], ["path", { "d": "M11 11v7", "key": "svg-4" }]];
421
- var IconFileSpreadsheet = createReactComponent("outline", "file-spreadsheet", "FileSpreadsheet", __iconNode5);
467
+ var __iconNode9 = [["path", { "d": "M14 3v4a1 1 0 0 0 1 1h4", "key": "svg-0" }], ["path", { "d": "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2", "key": "svg-1" }], ["path", { "d": "M8 11h8v7h-8l0 -7", "key": "svg-2" }], ["path", { "d": "M8 15h8", "key": "svg-3" }], ["path", { "d": "M11 11v7", "key": "svg-4" }]];
468
+ var IconFileSpreadsheet = createReactComponent("outline", "file-spreadsheet", "FileSpreadsheet", __iconNode9);
422
469
 
423
470
  // node_modules/@tabler/icons-react/dist/esm/icons/IconLoader2.mjs
424
- var __iconNode6 = [["path", { "d": "M12 3a9 9 0 1 0 9 9", "key": "svg-0" }]];
425
- var IconLoader2 = createReactComponent("outline", "loader-2", "Loader2", __iconNode6);
471
+ var __iconNode10 = [["path", { "d": "M12 3a9 9 0 1 0 9 9", "key": "svg-0" }]];
472
+ var IconLoader2 = createReactComponent("outline", "loader-2", "Loader2", __iconNode10);
426
473
 
427
474
  // node_modules/@tabler/icons-react/dist/esm/icons/IconPhoto.mjs
428
- var __iconNode7 = [["path", { "d": "M15 8h.01", "key": "svg-0" }], ["path", { "d": "M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12", "key": "svg-1" }], ["path", { "d": "M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5", "key": "svg-2" }], ["path", { "d": "M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3", "key": "svg-3" }]];
429
- var IconPhoto = createReactComponent("outline", "photo", "Photo", __iconNode7);
475
+ var __iconNode11 = [["path", { "d": "M15 8h.01", "key": "svg-0" }], ["path", { "d": "M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12", "key": "svg-1" }], ["path", { "d": "M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5", "key": "svg-2" }], ["path", { "d": "M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3", "key": "svg-3" }]];
476
+ var IconPhoto = createReactComponent("outline", "photo", "Photo", __iconNode11);
430
477
 
431
478
  // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
432
- var __iconNode8 = [["path", { "d": "M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3", "key": "svg-0" }]];
433
- var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode8);
479
+ var __iconNode12 = [["path", { "d": "M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3", "key": "svg-0" }]];
480
+ var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode12);
434
481
 
435
482
  // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
436
- var __iconNode9 = [["path", { "d": "M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3", "key": "svg-0" }]];
437
- var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode9);
483
+ var __iconNode13 = [["path", { "d": "M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3", "key": "svg-0" }]];
484
+ var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode13);
438
485
 
439
486
  // src/components/artifacts/artifact-copy-as-image-button/artifact-copy-as-image-button.tsx
440
487
  var import_react6 = require("react");
@@ -2007,8 +2054,13 @@ var ChartArtifactService = {
2007
2054
  toClipboardText: chartArtifactToClipboardText
2008
2055
  };
2009
2056
 
2010
- // src/components/artifacts/table-artifact/table-artifact.tsx
2011
- var import_react15 = require("react");
2057
+ // src/components/artifacts/deck-artifact/deck-artifact.tsx
2058
+ var import_react17 = require("react");
2059
+ var import_react_dom = require("react-dom");
2060
+ init_capture_exclude_attribute();
2061
+
2062
+ // src/components/artifacts/deck-artifact/deck-artifact-content.tsx
2063
+ var import_react16 = require("react");
2012
2064
 
2013
2065
  // src/components/ui/table.tsx
2014
2066
  var React3 = __toESM(require("react"), 1);
@@ -2155,9 +2207,333 @@ function renderEmptyRow(colSpan, emptyMessage) {
2155
2207
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableCell, { colSpan, className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) });
2156
2208
  }
2157
2209
 
2158
- // src/components/artifacts/table-artifact/use-table-artifact-data.ts
2159
- function useTableArtifactData(presignedUrl, columns) {
2160
- return useRowsArtifactData(presignedUrl, columns, parseCsv);
2210
+ // src/components/artifacts/deck-artifact/deck-markdown.tsx
2211
+ var import_react_markdown = __toESM(require("react-markdown"), 1);
2212
+ var import_remark_breaks = __toESM(require("remark-breaks"), 1);
2213
+ var import_remark_gfm = __toESM(require("remark-gfm"), 1);
2214
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2215
+ function sanitize(text) {
2216
+ return text.split("\n").filter((line) => {
2217
+ const t = line.trim();
2218
+ return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
2219
+ }).join("\n");
2220
+ }
2221
+ var MARKDOWN_COMPONENTS = {
2222
+ h1: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h1", { className: "text-[30px] font-semibold leading-tight text-foreground mb-3", ...props }),
2223
+ h2: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h2", { className: "text-[26px] font-semibold leading-tight text-foreground mb-2", ...props }),
2224
+ h3: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2225
+ h4: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h4", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2226
+ h5: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h5", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2227
+ h6: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h6", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2228
+ p: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-[22px] leading-relaxed text-foreground my-2", ...props }),
2229
+ ul: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ul", { className: "list-disc pl-7 text-[22px] leading-relaxed text-foreground my-2", ...props }),
2230
+ ol: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ol", { className: "list-decimal pl-7 text-[22px] leading-relaxed text-foreground my-2", ...props }),
2231
+ // react-markdown injects list metadata (`ordered` / `index` / `checked`) that must not leak to the DOM.
2232
+ li: ({ node: _node, ordered: _ordered, index: _index, checked: _checked, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("li", { className: "my-1", ...props }),
2233
+ strong: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("strong", { className: "font-semibold", ...props }),
2234
+ em: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("em", { className: "italic", ...props }),
2235
+ // Gate `<img src>` against an http(s) allowlist. react-markdown v8 percent-encodes the URL but
2236
+ // does NOT protocol-filter image src (unlike link href), so an LLM-authored
2237
+ // `![](javascript:…)` / `![](data:…)` or a tracking-pixel `![](http://…)` would otherwise render
2238
+ // with the raw URL. Unsafe src → render nothing.
2239
+ img: ({ node: _node, src, ...props }) => typeof src === "string" && isSafeDownloadUrl(src) ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src, className: "max-w-full", ...props }) : null,
2240
+ a: ({ node: _node, ...props }) => (
2241
+ // `rel` is forced AFTER `{...props}` so it can't be overridden — if a consumer ever adds
2242
+ // `linkTarget="_blank"`, LLM-authored links still can't reach `window.opener`.
2243
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("a", { className: "underline underline-offset-2", ...props, rel: "noopener noreferrer" })
2244
+ ),
2245
+ // react-markdown passes `inline` to distinguish inline code from fenced blocks — strip it from the DOM.
2246
+ code: ({ node: _node, inline: _inline, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("code", { className: "rounded bg-muted px-1.5 py-0.5 font-mono text-[18px]", ...props }),
2247
+ blockquote: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("blockquote", { className: "border-l-2 border-brown-alpha-12 pl-4 text-[22px] text-muted-foreground", ...props }),
2248
+ hr: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("hr", { className: "my-4 border-brown-alpha-12", ...props }),
2249
+ table: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("table", { className: "w-full border-collapse text-[20px]", ...props }) }),
2250
+ // react-markdown passes `isHeader` to cell renderers — strip it so it never reaches the DOM.
2251
+ th: ({ node: _node, isHeader: _isHeader, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("th", { className: "border-b border-brown-alpha-12 px-3 py-1.5 text-left font-medium", ...props }),
2252
+ td: ({ node: _node, isHeader: _isHeader, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("td", { className: "border-b border-brown-alpha-12 px-3 py-1.5", ...props })
2253
+ };
2254
+ function DeckMarkdown({ markdown }) {
2255
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: MARKDOWN_COMPONENTS, children: sanitize(markdown) });
2256
+ }
2257
+
2258
+ // src/components/artifacts/deck-artifact/slide-renderers.tsx
2259
+ var import_react15 = require("react");
2260
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2261
+ function safeLogoUrl(meta) {
2262
+ return meta?.logoUrl && isSafeDownloadUrl(meta.logoUrl) ? meta.logoUrl : null;
2263
+ }
2264
+ var DESIGN_W = 1280;
2265
+ var DESIGN_H = 720;
2266
+ var EYEBROW_H = 84;
2267
+ var CANVAS_LOGO_MAX_H = 48;
2268
+ var ACCENT_FONT = { fontFamily: `"${fontFamilies.CRIMSON_PRO}", serif`, fontStyle: "italic" };
2269
+ function SlideFrame({ meta, children, accent = false, bare = false }) {
2270
+ const frameRef = (0, import_react15.useRef)(null);
2271
+ const [scale, setScale] = (0, import_react15.useState)(null);
2272
+ (0, import_react15.useLayoutEffect)(() => {
2273
+ const el = frameRef.current;
2274
+ if (!el) return;
2275
+ const apply = (width) => {
2276
+ if (width > 0) setScale(width / DESIGN_W);
2277
+ };
2278
+ apply(el.clientWidth);
2279
+ const ro = new ResizeObserver((entries) => apply(entries[0]?.contentRect.width ?? 0));
2280
+ ro.observe(el);
2281
+ return () => ro.disconnect();
2282
+ }, []);
2283
+ const bg = accent ? "bg-indigo-600" : "bg-deck-canvas";
2284
+ const eyebrowColor = accent ? "text-white/70" : "text-brown-60";
2285
+ const borderColor = accent ? "border-white/20" : "border-brown-alpha-12";
2286
+ const logoSrc = safeLogoUrl(meta);
2287
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: frameRef, className: `relative aspect-[16/9] w-full overflow-hidden rounded-lg ${bg}`, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2288
+ "div",
2289
+ {
2290
+ className: "absolute left-0 top-0 origin-top-left",
2291
+ style: {
2292
+ width: DESIGN_W,
2293
+ height: DESIGN_H,
2294
+ transform: `scale(${scale ?? 0})`,
2295
+ visibility: scale === null ? "hidden" : "visible"
2296
+ },
2297
+ children: [
2298
+ !bare ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2299
+ "div",
2300
+ {
2301
+ className: `absolute inset-x-0 top-0 flex items-center justify-between border-b px-16 ${borderColor}`,
2302
+ style: { height: EYEBROW_H },
2303
+ children: [
2304
+ meta?.eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: eyebrowColor, style: { ...ACCENT_FONT, fontSize: 22 }, children: meta.eyebrow }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", {}),
2305
+ logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: logoSrc, alt: "", className: "object-contain", style: { maxHeight: CANVAS_LOGO_MAX_H } }) : null
2306
+ ]
2307
+ }
2308
+ ) : null,
2309
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute inset-x-0 bottom-0 overflow-hidden", style: { top: bare ? 0 : EYEBROW_H }, children })
2310
+ ]
2311
+ }
2312
+ ) });
2313
+ }
2314
+ function TitleSlide({ slide, meta }) {
2315
+ const logoSrc = safeLogoUrl(meta);
2316
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SlideFrame, { meta, bare: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex h-full flex-col justify-center px-24 py-16", children: [
2317
+ logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2318
+ "img",
2319
+ {
2320
+ src: logoSrc,
2321
+ alt: "",
2322
+ className: "mb-16 object-contain object-left",
2323
+ style: { maxHeight: 56, maxWidth: 380 }
2324
+ }
2325
+ ) : null,
2326
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2327
+ "h1",
2328
+ {
2329
+ className: "font-bold tracking-tight text-brown-100",
2330
+ style: { fontSize: 92, lineHeight: 1.04, maxWidth: 1060 },
2331
+ children: slide.title
2332
+ }
2333
+ ),
2334
+ slide.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "mt-7 text-brown-70", style: { ...ACCENT_FONT, fontSize: 34 }, children: slide.subtitle }) : null,
2335
+ slide.description ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "mt-4 leading-relaxed text-brown-70", style: { fontSize: 24, maxWidth: 880 }, children: slide.description }) : null,
2336
+ meta?.date ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "mt-10 text-brown-70", style: { ...ACCENT_FONT, fontSize: 30 }, children: meta.date }) : null
2337
+ ] }) });
2338
+ }
2339
+ function AgendaSlide({ slide, meta, labels }) {
2340
+ const items = slide.items ?? [];
2341
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "h-full px-24 py-14", children: [
2342
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "mb-10 font-bold text-brown-90", style: { fontSize: 40 }, children: slide.title || labels.agenda }),
2343
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-col", children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-baseline gap-6 border-b border-brown-alpha-12 py-5", children: [
2344
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "shrink-0 text-indigo-600", style: { ...ACCENT_FONT, fontSize: 28, width: 64 }, children: String(i + 1).padStart(2, "0") }),
2345
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-brown-90", style: { fontSize: 28 }, children: item })
2346
+ ] }, i)) })
2347
+ ] }) });
2348
+ }
2349
+ function SectionSlide({ slide, meta }) {
2350
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SlideFrame, { meta, accent: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex h-full flex-col justify-center gap-6 px-24", children: [
2351
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "font-bold text-white", style: { fontSize: 72, lineHeight: 1.05, maxWidth: 940 }, children: slide.title }),
2352
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "mt-2 bg-white/50", style: { width: 96, height: 5 } })
2353
+ ] }) });
2354
+ }
2355
+ function ClosingSlide({ meta, labels }) {
2356
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex h-full flex-col items-center justify-center gap-6 px-24 text-center", children: [
2357
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: "font-bold text-brown-100", style: { fontSize: 72 }, children: labels.thankYou }),
2358
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-indigo-600", style: { ...ACCENT_FONT, fontSize: 36 }, children: labels.questions })
2359
+ ] }) });
2360
+ }
2361
+
2362
+ // src/components/artifacts/deck-artifact/deck-artifact-content.tsx
2363
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2364
+ var TABLE_BLOCK_MAX_SHIMMER_ROWS = 10;
2365
+ var TABLE_CHROME_RESERVE = 56;
2366
+ var VISUAL_FALLBACK_HEIGHT = 360;
2367
+ function DeckArtifactContent({
2368
+ slides,
2369
+ labels,
2370
+ onNavigate,
2371
+ meta,
2372
+ onDark = false,
2373
+ currentSlide,
2374
+ onSlideChange
2375
+ }) {
2376
+ const navBtnClass = onDark ? "[&_svg]:!text-white hover:!bg-white/20 disabled:opacity-40" : void 0;
2377
+ const navBtnSize = onDark ? "medium" : "small";
2378
+ const isControlled = currentSlide !== void 0;
2379
+ const [internalIndex, setInternalIndex] = (0, import_react16.useState)(0);
2380
+ const index = isControlled ? currentSlide : internalIndex;
2381
+ const current = Math.min(index, slides.length - 1);
2382
+ const slide = slides[current];
2383
+ const goTo = (0, import_react16.useCallback)(
2384
+ (next) => {
2385
+ const clamped = Math.max(0, Math.min(next, slides.length - 1));
2386
+ if (isControlled) onSlideChange?.(clamped);
2387
+ else setInternalIndex(clamped);
2388
+ onNavigate?.(clamped);
2389
+ },
2390
+ [slides.length, onNavigate, isControlled, onSlideChange]
2391
+ );
2392
+ const position = labels.position.replace("{current}", String(current + 1)).replace("{total}", String(slides.length));
2393
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
2394
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideDispatch, { slide, labels, meta }),
2395
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2396
+ "div",
2397
+ {
2398
+ className: `flex items-center justify-between border-t pt-2 ${onDark ? "border-white/20" : "border-brown-alpha-12"}`,
2399
+ children: [
2400
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2401
+ IconButton,
2402
+ {
2403
+ icon: IconChevronLeft,
2404
+ size: navBtnSize,
2405
+ className: navBtnClass,
2406
+ "aria-label": labels.previous,
2407
+ disabled: current === 0,
2408
+ onClick: () => goTo(current - 1)
2409
+ }
2410
+ ),
2411
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: `text-xs font-medium ${onDark ? "text-white/70" : "text-brown-70"}`, children: position }),
2412
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2413
+ IconButton,
2414
+ {
2415
+ icon: IconChevronRight,
2416
+ size: navBtnSize,
2417
+ className: navBtnClass,
2418
+ "aria-label": labels.next,
2419
+ disabled: current === slides.length - 1,
2420
+ onClick: () => goTo(current + 1)
2421
+ }
2422
+ )
2423
+ ]
2424
+ }
2425
+ )
2426
+ ] });
2427
+ }
2428
+ function SlideDispatch({ slide, labels, meta }) {
2429
+ const kind = slide.kind ?? deckSlideKinds.CONTENT;
2430
+ switch (kind) {
2431
+ case deckSlideKinds.TITLE:
2432
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TitleSlide, { slide, meta });
2433
+ case deckSlideKinds.AGENDA:
2434
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AgendaSlide, { slide, meta, labels });
2435
+ case deckSlideKinds.SECTION:
2436
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SectionSlide, { slide, meta });
2437
+ case deckSlideKinds.CLOSING:
2438
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ClosingSlide, { meta, labels });
2439
+ case deckSlideKinds.CONTENT:
2440
+ default:
2441
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ContentSlide, { slide, meta, labels });
2442
+ }
2443
+ }
2444
+ function isVisualBlock(block) {
2445
+ return block.type === deckBlockTypes.CHART || block.type === deckBlockTypes.TABLE;
2446
+ }
2447
+ function ContentSlide({ slide, meta, labels }) {
2448
+ const content = slide.content ?? [];
2449
+ const visuals = content.filter(isVisualBlock);
2450
+ const texts = content.filter(
2451
+ (b) => b.type === deckBlockTypes.TEXT
2452
+ );
2453
+ if (visuals.length === 1 && texts.length > 0) {
2454
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full items-stretch gap-12 px-16 py-12", children: [
2455
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex w-[42%] shrink-0 flex-col overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AutoFit, { children: [
2456
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "mb-5 font-bold leading-tight text-foreground", style: { fontSize: 34 }, children: slide.title }),
2457
+ texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
2458
+ ] }) }),
2459
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "min-h-0 min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(FillVisual, { block: visuals[0], labels }) })
2460
+ ] }) });
2461
+ }
2462
+ if (visuals.length > 0) {
2463
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full flex-col gap-5 px-16 py-10", children: [
2464
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "shrink-0 font-bold leading-tight text-foreground", style: { fontSize: 32 }, children: slide.title }),
2465
+ content.map(
2466
+ (block, i) => isVisualBlock(block) ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "min-h-0 min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(FillVisual, { block, labels }) }, i) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "shrink-0 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DeckMarkdown, { markdown: block.markdown }) }, i)
2467
+ )
2468
+ ] }) });
2469
+ }
2470
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "h-full px-24 py-12", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AutoFit, { children: [
2471
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "mb-6 font-bold leading-tight text-foreground", style: { fontSize: 38 }, children: slide.title }),
2472
+ texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
2473
+ ] }) }) });
2474
+ }
2475
+ function AutoFit({ children }) {
2476
+ const boxRef = (0, import_react16.useRef)(null);
2477
+ const contentRef = (0, import_react16.useRef)(null);
2478
+ const [fit, setFit] = (0, import_react16.useState)({ scale: 1, height: 0 });
2479
+ (0, import_react16.useLayoutEffect)(() => {
2480
+ const boxEl = boxRef.current;
2481
+ const contentEl = contentRef.current;
2482
+ if (!boxEl || !contentEl) return;
2483
+ const measure = () => {
2484
+ const avail = boxEl.clientHeight;
2485
+ const natural = contentEl.offsetHeight;
2486
+ const scale = avail > 0 && natural > avail ? avail / natural : 1;
2487
+ setFit({ scale, height: natural * scale });
2488
+ };
2489
+ measure();
2490
+ const ro = new ResizeObserver(measure);
2491
+ ro.observe(boxEl);
2492
+ ro.observe(contentEl);
2493
+ return () => ro.disconnect();
2494
+ }, []);
2495
+ const scaled = fit.scale < 1;
2496
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: boxRef, className: "flex h-full min-h-0 w-full flex-col justify-center overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: scaled ? { height: fit.height } : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2497
+ "div",
2498
+ {
2499
+ ref: contentRef,
2500
+ className: "w-full origin-top-left",
2501
+ style: scaled ? { transform: `scale(${fit.scale})` } : void 0,
2502
+ children
2503
+ }
2504
+ ) }) });
2505
+ }
2506
+ function FillVisual({ block, labels }) {
2507
+ const ref = (0, import_react16.useRef)(null);
2508
+ const [height, setHeight] = (0, import_react16.useState)(VISUAL_FALLBACK_HEIGHT);
2509
+ (0, import_react16.useLayoutEffect)(() => {
2510
+ const el = ref.current;
2511
+ if (!el) return;
2512
+ const apply = (h) => {
2513
+ if (h > 0) setHeight(h);
2514
+ };
2515
+ apply(el.clientHeight);
2516
+ const ro = new ResizeObserver((entries) => apply(entries[0]?.contentRect.height ?? 0));
2517
+ ro.observe(el);
2518
+ return () => ro.disconnect();
2519
+ }, []);
2520
+ const chartLabels = labels.chart ?? DEFAULT_CHART_ARTIFACT_LABELS;
2521
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref, className: "h-full min-h-0 w-full overflow-hidden", children: block.type === deckBlockTypes.CHART ? (
2522
+ // ChartArtifactContent assumes a non-empty rowset (the standalone ChartArtifact guards
2523
+ // `rows.length > 0` upstream); mirror that guard here so an empty inline chart shows the
2524
+ // localized empty status instead of a blank chart area.
2525
+ block.rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(StatusMessage, { $tone: "info", children: chartLabels.empty }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { height }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChartArtifactContent, { config: block.config, rows: block.rows, labels: chartLabels }) })
2526
+ ) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2527
+ TableArtifactContent,
2528
+ {
2529
+ columns: block.config.columns,
2530
+ data: { status: "ready", rows: block.rows, error: null },
2531
+ knownRowCount: block.config.stats?.rowCount ?? block.rows.length,
2532
+ maxShimmerRows: TABLE_BLOCK_MAX_SHIMMER_ROWS,
2533
+ maxBodyHeight: Math.max(0, height - TABLE_CHROME_RESERVE),
2534
+ labels: labels.table ?? DEFAULT_TABLE_ARTIFACT_LABELS
2535
+ }
2536
+ ) });
2161
2537
  }
2162
2538
 
2163
2539
  // src/components/artifacts/table-artifact/validate.ts
@@ -2176,19 +2552,265 @@ function isValidTableColumn(column) {
2176
2552
  return true;
2177
2553
  }
2178
2554
 
2179
- // src/components/artifacts/table-artifact/table-artifact.tsx
2180
- var import_jsx_runtime22 = require("react/jsx-runtime");
2555
+ // src/components/artifacts/deck-artifact/validate.ts
2556
+ function isValidDeckConfig(config) {
2557
+ if (!config || typeof config !== "object") return false;
2558
+ const candidate = config;
2559
+ if (!Array.isArray(candidate.slides)) return false;
2560
+ if (candidate.slides.length === 0) return false;
2561
+ return candidate.slides.every(isValidDeckSlide);
2562
+ }
2563
+ function isValidDeckSlide(slide) {
2564
+ if (!slide || typeof slide !== "object") return false;
2565
+ const candidate = slide;
2566
+ if (typeof candidate.title !== "string") return false;
2567
+ const kind = typeof candidate.kind === "string" ? candidate.kind : deckSlideKinds.CONTENT;
2568
+ if (kind === deckSlideKinds.CONTENT && !Array.isArray(candidate.content)) return false;
2569
+ const content = Array.isArray(candidate.content) ? candidate.content : [];
2570
+ if (candidate.items != null) {
2571
+ if (!Array.isArray(candidate.items)) return false;
2572
+ if (!candidate.items.every((item) => typeof item === "string")) return false;
2573
+ }
2574
+ return content.every(isValidDeckBlock);
2575
+ }
2576
+ function isValidDeckBlock(block) {
2577
+ if (!block || typeof block !== "object") return false;
2578
+ const candidate = block;
2579
+ switch (candidate.type) {
2580
+ case deckBlockTypes.TEXT:
2581
+ return typeof candidate.markdown === "string";
2582
+ case deckBlockTypes.CHART:
2583
+ return isValidChartConfig(candidate.config) && Array.isArray(candidate.rows);
2584
+ case deckBlockTypes.TABLE:
2585
+ return isValidTableConfig(candidate.config) && Array.isArray(candidate.rows);
2586
+ default:
2587
+ return false;
2588
+ }
2589
+ }
2590
+
2591
+ // src/components/artifacts/deck-artifact/deck-artifact.tsx
2592
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2181
2593
  var TITLE_CLASSES2 = "text-sm font-semibold text-foreground";
2594
+ function DeckArtifact({ artifact, labels, callbacks }) {
2595
+ const validConfig = isValidDeckConfig(artifact.config);
2596
+ const [isFullscreen, setIsFullscreen] = (0, import_react17.useState)(false);
2597
+ const [currentSlide, setCurrentSlide] = (0, import_react17.useState)(0);
2598
+ (0, import_react17.useEffect)(() => {
2599
+ if (validConfig) return;
2600
+ console.warn("[clay] DeckArtifact: malformed `config` \u2014 skipping render.");
2601
+ }, [validConfig]);
2602
+ (0, import_react17.useEffect)(() => {
2603
+ if (!isFullscreen) return;
2604
+ const handleKey = (e) => {
2605
+ if (e.key === "Escape") setIsFullscreen(false);
2606
+ };
2607
+ document.addEventListener("keydown", handleKey);
2608
+ const previousOverflow = document.documentElement.style.overflow;
2609
+ document.documentElement.style.overflow = "hidden";
2610
+ return () => {
2611
+ document.removeEventListener("keydown", handleKey);
2612
+ document.documentElement.style.overflow = previousOverflow;
2613
+ };
2614
+ }, [isFullscreen]);
2615
+ const resolvedLabels = (0, import_react17.useMemo)(
2616
+ () => ({
2617
+ ...DEFAULT_DECK_ARTIFACT_LABELS,
2618
+ ...labels ?? {},
2619
+ chart: { ...DEFAULT_CHART_ARTIFACT_LABELS, ...labels?.chart ?? {} },
2620
+ table: { ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels?.table ?? {} }
2621
+ }),
2622
+ [labels]
2623
+ );
2624
+ const onNavigate = callbacks?.onNavigate;
2625
+ const handleNavigate = onNavigate ? (slideIndex) => onNavigate(artifact, slideIndex) : void 0;
2626
+ const onDownload = callbacks?.onDownload;
2627
+ const handleDownload = onDownload ? () => onDownload(artifact) : void 0;
2628
+ const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
2629
+ const showDownload = presignedUrl !== null && isSafeDownloadUrl(presignedUrl);
2630
+ const meta = artifact.config?.meta;
2631
+ const handleOpenFullscreen = () => setIsFullscreen(true);
2632
+ const handleCloseFullscreen = () => setIsFullscreen(false);
2633
+ const actions = /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(ArtifactActions, { ...{ [CAPTURE_EXCLUDE_ATTRIBUTE]: "" }, children: [
2634
+ showDownload ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactDownloadButton, { href: presignedUrl ?? "", label: resolvedLabels.download, onClick: handleDownload }) : null,
2635
+ validConfig ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2636
+ IconButton,
2637
+ {
2638
+ icon: IconArrowsMaximize,
2639
+ size: "small",
2640
+ "aria-label": resolvedLabels.enterFullscreen,
2641
+ onClick: handleOpenFullscreen
2642
+ }
2643
+ ) : null
2644
+ ] });
2645
+ if (!validConfig) {
2646
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2647
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2648
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", {}),
2649
+ actions
2650
+ ] }),
2651
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
2652
+ ] });
2653
+ }
2654
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
2655
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2656
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2657
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", {}),
2658
+ actions
2659
+ ] }),
2660
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2661
+ DeckArtifactContent,
2662
+ {
2663
+ slides: artifact.config.slides,
2664
+ labels: resolvedLabels,
2665
+ onNavigate: handleNavigate,
2666
+ meta,
2667
+ currentSlide,
2668
+ onSlideChange: setCurrentSlide
2669
+ }
2670
+ ) })
2671
+ ] }),
2672
+ isFullscreen && (0, import_react_dom.createPortal)(
2673
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2674
+ FullscreenOverlay,
2675
+ {
2676
+ artifact,
2677
+ resolvedLabels,
2678
+ onNavigate: handleNavigate,
2679
+ currentSlide,
2680
+ onSlideChange: setCurrentSlide,
2681
+ onClose: handleCloseFullscreen
2682
+ }
2683
+ ),
2684
+ document.body
2685
+ )
2686
+ ] });
2687
+ }
2688
+ function FullscreenOverlay({
2689
+ artifact,
2690
+ resolvedLabels,
2691
+ onNavigate,
2692
+ currentSlide,
2693
+ onSlideChange,
2694
+ onClose
2695
+ }) {
2696
+ const meta = artifact.config?.meta;
2697
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2698
+ "div",
2699
+ {
2700
+ className: "fixed inset-0 z-[2147483647] flex items-center justify-center bg-black/80",
2701
+ role: "dialog",
2702
+ "aria-modal": "true",
2703
+ "aria-label": resolvedLabels.exitFullscreen,
2704
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "relative", style: { width: "min(94vw, calc(82vh * 16 / 9))" }, children: [
2705
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2706
+ DeckArtifactContent,
2707
+ {
2708
+ slides: artifact.config.slides,
2709
+ labels: resolvedLabels,
2710
+ onNavigate,
2711
+ meta,
2712
+ currentSlide,
2713
+ onSlideChange,
2714
+ onDark: true
2715
+ }
2716
+ ),
2717
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
2718
+ "button",
2719
+ {
2720
+ className: "absolute -top-10 right-6 flex items-center gap-1.5 text-sm text-white/80 hover:text-white",
2721
+ "aria-label": resolvedLabels.exitFullscreen,
2722
+ onClick: onClose,
2723
+ children: [
2724
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(IconArrowsMinimize, { size: 16 }),
2725
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: resolvedLabels.exitFullscreen })
2726
+ ]
2727
+ }
2728
+ )
2729
+ ] })
2730
+ }
2731
+ );
2732
+ }
2733
+
2734
+ // src/components/artifacts/deck-artifact/to-clipboard-text.ts
2735
+ function deckArtifactToClipboardText(artifact) {
2736
+ const header = artifact.title?.trim() || "Deck";
2737
+ const slides = artifact.config?.slides ?? [];
2738
+ const body = slides.map((slide, i) => slideToText(slide, i)).join("\n\n");
2739
+ return body ? `${header}
2740
+
2741
+ ${body}` : header;
2742
+ }
2743
+ function slideToText(slide, index) {
2744
+ const kind = slide.kind ?? deckSlideKinds.CONTENT;
2745
+ const prefix = `Slide ${index + 1}: `;
2746
+ switch (kind) {
2747
+ case deckSlideKinds.TITLE: {
2748
+ const parts = [slide.title];
2749
+ if (slide.subtitle) parts.push(slide.subtitle);
2750
+ if (slide.description) parts.push(slide.description);
2751
+ return `${prefix}${parts.join(" \u2014 ")}`.trim();
2752
+ }
2753
+ case deckSlideKinds.AGENDA: {
2754
+ const items = (slide.items ?? []).map((item, i) => ` ${String(i + 1).padStart(2, "0")}. ${item}`).join("\n");
2755
+ return `${prefix}${slide.title || "Agenda"}${items ? `
2756
+ ${items}` : ""}`.trim();
2757
+ }
2758
+ case deckSlideKinds.SECTION:
2759
+ return `${prefix}${slide.title}`.trim();
2760
+ case deckSlideKinds.CLOSING:
2761
+ return `${prefix}Thank you`.trim();
2762
+ case deckSlideKinds.CONTENT:
2763
+ default: {
2764
+ const blocks = (slide.content ?? []).map(blockToText).filter(Boolean).join("\n\n");
2765
+ return `${prefix}${slide.title}${blocks ? `
2766
+ ${blocks}` : ""}`.trim();
2767
+ }
2768
+ }
2769
+ }
2770
+ function blockToText(block) {
2771
+ switch (block.type) {
2772
+ case deckBlockTypes.TEXT:
2773
+ return block.markdown.trim();
2774
+ case deckBlockTypes.CHART:
2775
+ return `[Chart: ${block.config.variant}]`;
2776
+ case deckBlockTypes.TABLE: {
2777
+ const columnCount = block.config.columns.length;
2778
+ const rowCount = block.rows.length;
2779
+ return `[Table: ${columnCount} column${columnCount === 1 ? "" : "s"} \xD7 ${rowCount} row${rowCount === 1 ? "" : "s"}]`;
2780
+ }
2781
+ default:
2782
+ return "";
2783
+ }
2784
+ }
2785
+
2786
+ // src/components/artifacts/artifact-services/deck-artifact-service.ts
2787
+ var DeckArtifactService = {
2788
+ type: artifactTypes.DECK,
2789
+ Component: DeckArtifact,
2790
+ toClipboardText: deckArtifactToClipboardText
2791
+ };
2792
+
2793
+ // src/components/artifacts/table-artifact/table-artifact.tsx
2794
+ var import_react18 = require("react");
2795
+
2796
+ // src/components/artifacts/table-artifact/use-table-artifact-data.ts
2797
+ function useTableArtifactData(presignedUrl, columns) {
2798
+ return useRowsArtifactData(presignedUrl, columns, parseCsv);
2799
+ }
2800
+
2801
+ // src/components/artifacts/table-artifact/table-artifact.tsx
2802
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2803
+ var TITLE_CLASSES3 = "text-sm font-semibold text-foreground";
2182
2804
  var TABLE_MAX_BODY_HEIGHT = 480;
2183
2805
  var MAX_SHIMMER_ROWS = 10;
2184
2806
  function TableArtifact({ artifact, labels, callbacks }) {
2185
2807
  const validConfig = isValidTableConfig(artifact.config);
2186
2808
  const validColumns = validConfig ? artifact.config.columns : null;
2187
- (0, import_react15.useEffect)(() => {
2809
+ (0, import_react18.useEffect)(() => {
2188
2810
  if (validConfig) return;
2189
2811
  console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
2190
2812
  }, [validConfig]);
2191
- const resolvedLabels = (0, import_react15.useMemo)(
2813
+ const resolvedLabels = (0, import_react18.useMemo)(
2192
2814
  () => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels ?? {} }),
2193
2815
  [labels]
2194
2816
  );
@@ -2200,10 +2822,10 @@ function TableArtifact({ artifact, labels, callbacks }) {
2200
2822
  const onDownload = callbacks?.onDownload;
2201
2823
  const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
2202
2824
  if (!validConfig || !validColumns) {
2203
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2204
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2205
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", {}),
2206
- presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2825
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2826
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2827
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
2828
+ presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2207
2829
  ArtifactDownloadButton,
2208
2830
  {
2209
2831
  href: presignedUrl,
@@ -2212,17 +2834,17 @@ function TableArtifact({ artifact, labels, callbacks }) {
2212
2834
  }
2213
2835
  ) }) : null
2214
2836
  ] }),
2215
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
2837
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
2216
2838
  ] });
2217
2839
  }
2218
2840
  return (
2219
2841
  // The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
2220
2842
  // Disable the outer overflow container so only one scroll context exists — this prevents
2221
2843
  // double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
2222
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2223
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2224
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", {}),
2225
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2844
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2845
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2846
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
2847
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2226
2848
  ArtifactDownloadButton,
2227
2849
  {
2228
2850
  href: presignedUrl ?? "",
@@ -2231,7 +2853,7 @@ function TableArtifact({ artifact, labels, callbacks }) {
2231
2853
  }
2232
2854
  ) })
2233
2855
  ] }),
2234
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2856
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2235
2857
  TableArtifactContent,
2236
2858
  {
2237
2859
  columns: validColumns,
@@ -2262,7 +2884,8 @@ var TableArtifactService = {
2262
2884
  // src/components/artifacts/artifact-services/index.ts
2263
2885
  var ArtifactServices = {
2264
2886
  [artifactTypes.TABLE]: TableArtifactService,
2265
- [artifactTypes.CHART]: ChartArtifactService
2887
+ [artifactTypes.CHART]: ChartArtifactService,
2888
+ [artifactTypes.DECK]: DeckArtifactService
2266
2889
  };
2267
2890
  function artifactToClipboardText(artifact) {
2268
2891
  const entry = ArtifactServices[artifact.type];
@@ -2273,13 +2896,13 @@ function artifactToClipboardText(artifact) {
2273
2896
  }
2274
2897
 
2275
2898
  // src/components/blocks/artifact-ref-block/artifact-ref-block.tsx
2276
- var import_jsx_runtime23 = require("react/jsx-runtime");
2899
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2277
2900
  function ArtifactRefBlock({ block }) {
2278
2901
  const { artifact, labels, callbacks } = block.payload;
2279
2902
  const entry = ArtifactServices[artifact.type];
2280
2903
  if (!entry) return null;
2281
2904
  const Component = entry.Component;
2282
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Component, { artifact, labels, callbacks });
2905
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Component, { artifact, labels, callbacks });
2283
2906
  }
2284
2907
 
2285
2908
  // src/components/blocks/block-services/artifact-ref-block-service.ts
@@ -2314,9 +2937,9 @@ function markdownToPlainText(markdown) {
2314
2937
  }
2315
2938
 
2316
2939
  // src/components/blocks/text-block/text-block.tsx
2317
- var import_react_markdown = __toESM(require("react-markdown"), 1);
2318
- var import_remark_breaks = __toESM(require("remark-breaks"), 1);
2319
- var import_remark_gfm = __toESM(require("remark-gfm"), 1);
2940
+ var import_react_markdown2 = __toESM(require("react-markdown"), 1);
2941
+ var import_remark_breaks2 = __toESM(require("remark-breaks"), 1);
2942
+ var import_remark_gfm2 = __toESM(require("remark-gfm"), 1);
2320
2943
 
2321
2944
  // src/components/blocks/scrollable-table/scrollable-table-styles.ts
2322
2945
  var import_styled_components3 = __toESM(require("styled-components"), 1);
@@ -2331,13 +2954,13 @@ var TableScroll = import_styled_components3.default.div`
2331
2954
  `;
2332
2955
 
2333
2956
  // src/components/blocks/scrollable-table/scrollable-table.tsx
2334
- var import_jsx_runtime24 = require("react/jsx-runtime");
2957
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2335
2958
  function ScrollableTable({ node: _node, ...props }) {
2336
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TableContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("table", { ...props }) }) });
2959
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TableContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("table", { ...props }) }) });
2337
2960
  }
2338
2961
 
2339
2962
  // src/components/blocks/text-block/sanitize.ts
2340
- function sanitize(text) {
2963
+ function sanitize2(text) {
2341
2964
  return text.split("\n").filter((line) => {
2342
2965
  const t = line.trim();
2343
2966
  return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
@@ -2477,12 +3100,12 @@ var TextBlockWrapper = import_styled_components4.default.div`
2477
3100
  `;
2478
3101
 
2479
3102
  // src/components/blocks/text-block/text-block.tsx
2480
- var import_jsx_runtime25 = require("react/jsx-runtime");
3103
+ var import_jsx_runtime29 = require("react/jsx-runtime");
2481
3104
  var markdownComponents = {
2482
- table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ScrollableTable, { ...tableProps }))
3105
+ table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ScrollableTable, { ...tableProps }))
2483
3106
  };
2484
3107
  function TextBlock({ block }) {
2485
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TextBlockWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: markdownComponents, children: sanitize(block.payload.text) }) });
3108
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TextBlockWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_markdown2.default, { remarkPlugins: [import_remark_gfm2.default, import_remark_breaks2.default], components: markdownComponents, children: sanitize2(block.payload.text) }) });
2486
3109
  }
2487
3110
 
2488
3111
  // src/components/blocks/block-services/text-block-service.ts
@@ -2504,12 +3127,12 @@ var BlockServices = {
2504
3127
  };
2505
3128
 
2506
3129
  // src/components/blocks/block/block.tsx
2507
- var import_jsx_runtime26 = require("react/jsx-runtime");
3130
+ var import_jsx_runtime30 = require("react/jsx-runtime");
2508
3131
  function Block({ block }) {
2509
3132
  const service = BlockServices[block.type];
2510
3133
  if (!service) return null;
2511
3134
  const { Component } = service;
2512
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Component, { block });
3135
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Component, { block });
2513
3136
  }
2514
3137
 
2515
3138
  // src/components/chat/hooks/copy-message-text.ts
@@ -2527,13 +3150,13 @@ function copyMessageText(message) {
2527
3150
  }
2528
3151
 
2529
3152
  // src/components/chat/chat-message-actions/chat-message-actions.tsx
2530
- var import_react18 = require("react");
3153
+ var import_react21 = require("react");
2531
3154
 
2532
3155
  // src/components/chat/chat-context/chat-context.ts
2533
- var import_react16 = require("react");
2534
- var ChatContext = (0, import_react16.createContext)(null);
3156
+ var import_react19 = require("react");
3157
+ var ChatContext = (0, import_react19.createContext)(null);
2535
3158
  function useChatContext() {
2536
- const context = (0, import_react16.useContext)(ChatContext);
3159
+ const context = (0, import_react19.useContext)(ChatContext);
2537
3160
  if (!context) {
2538
3161
  throw new Error("useChatContext must be used within a Chat.Root component");
2539
3162
  }
@@ -2541,7 +3164,7 @@ function useChatContext() {
2541
3164
  }
2542
3165
 
2543
3166
  // src/components/chat/hooks/use-copy-to-clipboard.ts
2544
- var import_react17 = require("react");
3167
+ var import_react20 = require("react");
2545
3168
 
2546
3169
  // src/utils/clipboard.ts
2547
3170
  function copyToClipboard(text, options) {
@@ -2554,14 +3177,14 @@ function copyToClipboard(text, options) {
2554
3177
  // src/components/chat/hooks/use-copy-to-clipboard.ts
2555
3178
  var RESET_DELAY_MS = 2e3;
2556
3179
  function useCopyToClipboard() {
2557
- const [isCopied, setIsCopied] = (0, import_react17.useState)(false);
2558
- const timeoutRef = (0, import_react17.useRef)(null);
2559
- (0, import_react17.useEffect)(() => {
3180
+ const [isCopied, setIsCopied] = (0, import_react20.useState)(false);
3181
+ const timeoutRef = (0, import_react20.useRef)(null);
3182
+ (0, import_react20.useEffect)(() => {
2560
3183
  return () => {
2561
3184
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
2562
3185
  };
2563
3186
  }, []);
2564
- const copy = (0, import_react17.useCallback)((text) => {
3187
+ const copy = (0, import_react20.useCallback)((text) => {
2565
3188
  copyToClipboard(text, {
2566
3189
  onSuccess: () => {
2567
3190
  setIsCopied(true);
@@ -2601,24 +3224,24 @@ var AnimatedAction = import_styled_components5.default.div`
2601
3224
  `;
2602
3225
 
2603
3226
  // src/components/chat/chat-message-actions/chat-message-actions.tsx
2604
- var import_jsx_runtime27 = require("react/jsx-runtime");
3227
+ var import_jsx_runtime31 = require("react/jsx-runtime");
2605
3228
  function ChatMessageActions({ className, messageId, content, role, isHelpful }) {
2606
3229
  const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
2607
3230
  const { isCopied, copy } = useCopyToClipboard();
2608
- const handleCopy = (0, import_react18.useCallback)(() => {
3231
+ const handleCopy = (0, import_react21.useCallback)(() => {
2609
3232
  copy(content);
2610
3233
  onCopyMessage?.(messageId);
2611
3234
  }, [content, messageId, copy, onCopyMessage]);
2612
- const handleThumbUp = (0, import_react18.useCallback)(() => {
3235
+ const handleThumbUp = (0, import_react21.useCallback)(() => {
2613
3236
  onThumbUpClick?.(messageId, isHelpful === true ? null : true);
2614
3237
  }, [messageId, isHelpful, onThumbUpClick]);
2615
- const handleThumbDown = (0, import_react18.useCallback)(() => {
3238
+ const handleThumbDown = (0, import_react21.useCallback)(() => {
2616
3239
  onThumbDownClick?.(messageId, isHelpful === false ? null : false);
2617
3240
  }, [messageId, isHelpful, onThumbDownClick]);
2618
3241
  const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
2619
3242
  const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
2620
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(ActionsContainer, { $role: role, className, children: [
2621
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3243
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(ActionsContainer, { $role: role, className, children: [
3244
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2622
3245
  IconButton,
2623
3246
  {
2624
3247
  icon: isCopied ? IconCheck : IconCopy,
@@ -2626,7 +3249,7 @@ function ChatMessageActions({ className, messageId, content, role, isHelpful })
2626
3249
  "aria-label": isCopied ? "Copied" : "Copy message"
2627
3250
  }
2628
3251
  ),
2629
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3252
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2630
3253
  IconButton,
2631
3254
  {
2632
3255
  icon: IconThumbUp,
@@ -2635,7 +3258,7 @@ function ChatMessageActions({ className, messageId, content, role, isHelpful })
2635
3258
  "aria-label": "Good response"
2636
3259
  }
2637
3260
  ) }),
2638
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3261
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2639
3262
  IconButton,
2640
3263
  {
2641
3264
  icon: IconThumbDown,
@@ -2686,12 +3309,12 @@ var MessageBubble = import_styled_components6.default.div`
2686
3309
  `;
2687
3310
 
2688
3311
  // src/components/chat/chat-message/chat-message.tsx
2689
- var import_jsx_runtime28 = require("react/jsx-runtime");
3312
+ var import_jsx_runtime32 = require("react/jsx-runtime");
2690
3313
  function ChatMessage({ message }) {
2691
- const clipboardText = (0, import_react19.useMemo)(() => copyMessageText(message), [message]);
2692
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(MessageContainer, { $role: message.role, children: [
2693
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MessageBubble, { $role: message.role, "data-testid": "message-bubble", children: message.blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Block, { block }, index)) }),
2694
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3314
+ const clipboardText = (0, import_react22.useMemo)(() => copyMessageText(message), [message]);
3315
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(MessageContainer, { $role: message.role, children: [
3316
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MessageBubble, { $role: message.role, "data-testid": "message-bubble", children: message.blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Block, { block }, index)) }),
3317
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
2695
3318
  ChatMessageActions,
2696
3319
  {
2697
3320
  messageId: message.id,
@@ -2716,7 +3339,11 @@ function ChatMessage({ message }) {
2716
3339
  @tabler/icons-react/dist/esm/defaultAttributes.mjs:
2717
3340
  @tabler/icons-react/dist/esm/createReactComponent.mjs:
2718
3341
  @tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs:
3342
+ @tabler/icons-react/dist/esm/icons/IconArrowsMaximize.mjs:
3343
+ @tabler/icons-react/dist/esm/icons/IconArrowsMinimize.mjs:
2719
3344
  @tabler/icons-react/dist/esm/icons/IconCheck.mjs:
3345
+ @tabler/icons-react/dist/esm/icons/IconChevronLeft.mjs:
3346
+ @tabler/icons-react/dist/esm/icons/IconChevronRight.mjs:
2720
3347
  @tabler/icons-react/dist/esm/icons/IconCopy.mjs:
2721
3348
  @tabler/icons-react/dist/esm/icons/IconDownload.mjs:
2722
3349
  @tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs: