@shapesos/clay 0.17.0 → 0.19.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 (111) 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 +1010 -60
  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 +15 -6
  9. package/dist/badge.cjs +70 -0
  10. package/dist/badge.cjs.map +1 -0
  11. package/dist/badge.d.cts +28 -0
  12. package/dist/badge.d.ts +28 -0
  13. package/dist/badge.js +9 -0
  14. package/dist/blocks.cjs +981 -96
  15. package/dist/blocks.cjs.map +1 -1
  16. package/dist/blocks.css +1 -1
  17. package/dist/blocks.d.cts +15 -4
  18. package/dist/blocks.d.ts +15 -4
  19. package/dist/blocks.js +20 -8
  20. package/dist/button.cjs +3 -1
  21. package/dist/button.cjs.map +1 -1
  22. package/dist/button.js +2 -2
  23. package/dist/capture.cjs +3 -1
  24. package/dist/capture.cjs.map +1 -1
  25. package/dist/capture.js +2 -2
  26. package/dist/chart.cjs +3 -1
  27. package/dist/chart.cjs.map +1 -1
  28. package/dist/chart.js +2 -2
  29. package/dist/chat.cjs +986 -151
  30. package/dist/chat.cjs.map +1 -1
  31. package/dist/chat.d.cts +2 -2
  32. package/dist/chat.d.ts +2 -2
  33. package/dist/chat.js +13 -8
  34. package/dist/{chunk-JGMN6W72.js → chunk-2X4KUXYP.js} +1 -1
  35. package/dist/chunk-BHHJOG5X.js +1 -0
  36. package/dist/{chunk-B4U37WIH.js → chunk-CFCLVJIO.js} +2 -2
  37. package/dist/chunk-CSTCTO3B.js +161 -0
  38. package/dist/chunk-CSTCTO3B.js.map +1 -0
  39. package/dist/{chunk-6YZ65KPW.js → chunk-DC5KYT2G.js} +669 -171
  40. package/dist/chunk-DC5KYT2G.js.map +1 -0
  41. package/dist/{chunk-PYDVANWI.js → chunk-E36VI2HA.js} +2 -2
  42. package/dist/chunk-EIAWZXE4.js +69 -0
  43. package/dist/chunk-EIAWZXE4.js.map +1 -0
  44. package/dist/chunk-EXRNGIQ2.js +41 -0
  45. package/dist/chunk-EXRNGIQ2.js.map +1 -0
  46. package/dist/{chunk-B6GAPZ2R.js → chunk-FCSYVF4Z.js} +12 -46
  47. package/dist/chunk-FCSYVF4Z.js.map +1 -0
  48. package/dist/{chunk-PUVZ2S3F.js → chunk-G4NXVFXU.js} +2 -2
  49. package/dist/{chunk-JAGNXEWK.js → chunk-GK4XW4BC.js} +2 -2
  50. package/dist/{chunk-4MZZH3WX.js → chunk-HU5W7CGE.js} +37 -2
  51. package/dist/chunk-HU5W7CGE.js.map +1 -0
  52. package/dist/chunk-JMHE3Q5K.js +406 -0
  53. package/dist/chunk-JMHE3Q5K.js.map +1 -0
  54. package/dist/{chunk-4VE6ZXXW.js → chunk-MQP57DOP.js} +3 -3
  55. package/dist/{chunk-JF3P66JF.js → chunk-SN3ORQSJ.js} +4 -2
  56. package/dist/{chunk-JF3P66JF.js.map → chunk-SN3ORQSJ.js.map} +1 -1
  57. package/dist/{chunk-PGR2MDDU.js → chunk-W66OJM55.js} +2 -2
  58. package/dist/{chunk-7OYIDM42.js → chunk-XKURJ72I.js} +2 -2
  59. package/dist/copy-button.cjs +439 -0
  60. package/dist/copy-button.cjs.map +1 -0
  61. package/dist/copy-button.d.cts +20 -0
  62. package/dist/copy-button.d.ts +20 -0
  63. package/dist/copy-button.js +12 -0
  64. package/dist/copy-button.js.map +1 -0
  65. package/dist/{dom-to-image-NATF3446.js → dom-to-image-QB7KMTAE.js} +3 -3
  66. package/dist/dom-to-image-QB7KMTAE.js.map +1 -0
  67. package/dist/icon.cjs +3 -1
  68. package/dist/icon.cjs.map +1 -1
  69. package/dist/icon.js +2 -2
  70. package/dist/index.cjs +1070 -209
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.d.cts +6 -4
  73. package/dist/index.d.ts +6 -4
  74. package/dist/index.js +42 -17
  75. package/dist/keyboard-shortcut.cjs +3 -1
  76. package/dist/keyboard-shortcut.cjs.map +1 -1
  77. package/dist/keyboard-shortcut.js +2 -2
  78. package/dist/table.cjs +40 -0
  79. package/dist/table.cjs.map +1 -1
  80. package/dist/table.d.cts +37 -2
  81. package/dist/table.d.ts +37 -2
  82. package/dist/table.js +11 -1
  83. package/dist/text-area.cjs +3 -1
  84. package/dist/text-area.cjs.map +1 -1
  85. package/dist/text-area.js +2 -2
  86. package/dist/tokens.cjs +3 -1
  87. package/dist/tokens.cjs.map +1 -1
  88. package/dist/tokens.d.cts +1 -0
  89. package/dist/tokens.d.ts +1 -0
  90. package/dist/tokens.js +1 -1
  91. package/dist/{types-CW45GBXl.d.cts → types-Bhg0_ES8.d.cts} +75 -3
  92. package/dist/{types-GCkXbyFm.d.ts → types-C8JtnwNY.d.ts} +200 -4
  93. package/dist/{types-BzXPBy6s.d.cts → types-DTdDFU3O.d.cts} +200 -4
  94. package/dist/{types-D1b8v7EY.d.ts → types-orOQcI2z.d.ts} +75 -3
  95. package/package.json +11 -1
  96. package/dist/chunk-46ZYTBX5.js +0 -250
  97. package/dist/chunk-46ZYTBX5.js.map +0 -1
  98. package/dist/chunk-4MZZH3WX.js.map +0 -1
  99. package/dist/chunk-6YZ65KPW.js.map +0 -1
  100. package/dist/chunk-B6GAPZ2R.js.map +0 -1
  101. package/dist/chunk-RSRNSWJN.js +0 -1
  102. /package/dist/{chunk-RSRNSWJN.js.map → badge.js.map} +0 -0
  103. /package/dist/{chunk-JGMN6W72.js.map → chunk-2X4KUXYP.js.map} +0 -0
  104. /package/dist/{dom-to-image-NATF3446.js.map → chunk-BHHJOG5X.js.map} +0 -0
  105. /package/dist/{chunk-B4U37WIH.js.map → chunk-CFCLVJIO.js.map} +0 -0
  106. /package/dist/{chunk-PYDVANWI.js.map → chunk-E36VI2HA.js.map} +0 -0
  107. /package/dist/{chunk-PUVZ2S3F.js.map → chunk-G4NXVFXU.js.map} +0 -0
  108. /package/dist/{chunk-JAGNXEWK.js.map → chunk-GK4XW4BC.js.map} +0 -0
  109. /package/dist/{chunk-4VE6ZXXW.js.map → chunk-MQP57DOP.js.map} +0 -0
  110. /package/dist/{chunk-PGR2MDDU.js.map → chunk-W66OJM55.js.map} +0 -0
  111. /package/dist/{chunk-7OYIDM42.js.map → chunk-XKURJ72I.js.map} +0 -0
@@ -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
  });
@@ -272,10 +274,14 @@ __export(artifacts_exports, {
272
274
  ArtifactServices: () => ArtifactServices,
273
275
  ChartArtifact: () => ChartArtifact,
274
276
  DEFAULT_CHART_ARTIFACT_LABELS: () => DEFAULT_CHART_ARTIFACT_LABELS,
277
+ DEFAULT_DECK_ARTIFACT_LABELS: () => DEFAULT_DECK_ARTIFACT_LABELS,
275
278
  DEFAULT_TABLE_ARTIFACT_LABELS: () => DEFAULT_TABLE_ARTIFACT_LABELS,
279
+ DeckArtifact: () => DeckArtifact,
276
280
  TableArtifact: () => TableArtifact,
277
281
  artifactToClipboardText: () => artifactToClipboardText,
278
282
  artifactTypes: () => artifactTypes,
283
+ deckBlockTypes: () => deckBlockTypes,
284
+ deckSlideKinds: () => deckSlideKinds,
279
285
  isSafeDownloadUrl: () => isSafeDownloadUrl
280
286
  });
281
287
  module.exports = __toCommonJS(artifacts_exports);
@@ -283,7 +289,8 @@ module.exports = __toCommonJS(artifacts_exports);
283
289
  // src/components/artifacts/artifact-base.ts
284
290
  var artifactTypes = {
285
291
  TABLE: "TABLE",
286
- CHART: "CHART"
292
+ CHART: "CHART",
293
+ DECK: "DECK"
287
294
  };
288
295
 
289
296
  // src/components/artifacts/chart-artifact/types.ts
@@ -308,6 +315,34 @@ var DEFAULT_TABLE_ARTIFACT_LABELS = {
308
315
  empty: "No rows to display."
309
316
  };
310
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
+
311
346
  // src/components/artifacts/chart-artifact/chart-artifact.tsx
312
347
  var import_react13 = require("react");
313
348
 
@@ -400,29 +435,45 @@ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
400
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" }]];
401
436
  var IconAlertCircle = createReactComponent("outline", "alert-circle", "AlertCircle", __iconNode);
402
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
+
403
446
  // node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
404
- var __iconNode2 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
405
- 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);
406
457
 
407
458
  // node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
408
- 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" }]];
409
- 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);
410
461
 
411
462
  // node_modules/@tabler/icons-react/dist/esm/icons/IconDownload.mjs
412
- 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" }]];
413
- 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);
414
465
 
415
466
  // node_modules/@tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs
416
- 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" }]];
417
- 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);
418
469
 
419
470
  // node_modules/@tabler/icons-react/dist/esm/icons/IconLoader2.mjs
420
- var __iconNode6 = [["path", { "d": "M12 3a9 9 0 1 0 9 9", "key": "svg-0" }]];
421
- 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);
422
473
 
423
474
  // node_modules/@tabler/icons-react/dist/esm/icons/IconPhoto.mjs
424
- 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" }]];
425
- 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);
426
477
 
427
478
  // src/components/artifacts/artifact-copy-as-image-button/artifact-copy-as-image-button.tsx
428
479
  var import_react6 = require("react");
@@ -958,6 +1009,300 @@ function ChartTooltipContent({
958
1009
  // src/tokens/index.ts
959
1010
  init_colors();
960
1011
 
1012
+ // src/tokens/typography.ts
1013
+ var fontFamilies = {
1014
+ /** Geist — primary UI font for body text, labels, headings, and display. */
1015
+ GEIST: "Geist",
1016
+ /** Crimson Pro — editorial/serif font, mostly italic. Used for decorative headings and pull quotes. */
1017
+ CRIMSON_PRO: "Crimson Pro"
1018
+ };
1019
+ var typographyTypes = {
1020
+ // Geist Label Caption (12px)
1021
+ GEIST_LABEL_CAPTION_REGULAR: "GEIST_LABEL_CAPTION_REGULAR",
1022
+ GEIST_LABEL_CAPTION_MEDIUM: "GEIST_LABEL_CAPTION_MEDIUM",
1023
+ GEIST_LABEL_CAPTION_SEMI_BOLD: "GEIST_LABEL_CAPTION_SEMI_BOLD",
1024
+ // Geist Body Extra Small (14px)
1025
+ GEIST_BODY_XS_REGULAR: "GEIST_BODY_XS_REGULAR",
1026
+ GEIST_BODY_XS_MEDIUM: "GEIST_BODY_XS_MEDIUM",
1027
+ GEIST_BODY_XS_BOLD: "GEIST_BODY_XS_BOLD",
1028
+ // Geist Body Small (16px)
1029
+ GEIST_BODY_S_REGULAR: "GEIST_BODY_S_REGULAR",
1030
+ GEIST_BODY_S_MEDIUM: "GEIST_BODY_S_MEDIUM",
1031
+ GEIST_BODY_S_SEMI_BOLD: "GEIST_BODY_S_SEMI_BOLD",
1032
+ GEIST_BODY_S_BOLD: "GEIST_BODY_S_BOLD",
1033
+ // Geist Body Medium (18px)
1034
+ GEIST_BODY_M_LIGHT: "GEIST_BODY_M_LIGHT",
1035
+ GEIST_BODY_M_REGULAR: "GEIST_BODY_M_REGULAR",
1036
+ GEIST_BODY_M_MEDIUM: "GEIST_BODY_M_MEDIUM",
1037
+ GEIST_BODY_M_SEMI_BOLD: "GEIST_BODY_M_SEMI_BOLD",
1038
+ // Geist Body Large (20px)
1039
+ GEIST_BODY_L_REGULAR: "GEIST_BODY_L_REGULAR",
1040
+ GEIST_BODY_L_MEDIUM: "GEIST_BODY_L_MEDIUM",
1041
+ GEIST_BODY_L_SEMI_BOLD: "GEIST_BODY_L_SEMI_BOLD",
1042
+ GEIST_BODY_L_BOLD: "GEIST_BODY_L_BOLD",
1043
+ // Geist Heading Small (24px)
1044
+ GEIST_HEADING_S_REGULAR: "GEIST_HEADING_S_REGULAR",
1045
+ GEIST_HEADING_S_MEDIUM: "GEIST_HEADING_S_MEDIUM",
1046
+ GEIST_HEADING_S_BOLD: "GEIST_HEADING_S_BOLD",
1047
+ // Geist Heading Medium (28px)
1048
+ GEIST_HEADING_M_BOLD: "GEIST_HEADING_M_BOLD",
1049
+ // Geist Heading Large (32px)
1050
+ GEIST_HEADING_L_REGULAR: "GEIST_HEADING_L_REGULAR",
1051
+ GEIST_HEADING_L_MEDIUM: "GEIST_HEADING_L_MEDIUM",
1052
+ GEIST_HEADING_L_SEMI_BOLD: "GEIST_HEADING_L_SEMI_BOLD",
1053
+ GEIST_HEADING_L_BOLD: "GEIST_HEADING_L_BOLD",
1054
+ // Geist Display Large (36px)
1055
+ GEIST_DISPLAY_L_MEDIUM: "GEIST_DISPLAY_L_MEDIUM",
1056
+ // Crimson Pro Body Small (16px, italic)
1057
+ CRIMSON_PRO_BODY_S_LIGHT_ITALIC: "CRIMSON_PRO_BODY_S_LIGHT_ITALIC",
1058
+ // Crimson Pro Body Medium (18px, italic)
1059
+ CRIMSON_PRO_BODY_M_LIGHT_ITALIC: "CRIMSON_PRO_BODY_M_LIGHT_ITALIC",
1060
+ // Crimson Pro Heading Medium (24px, italic)
1061
+ CRIMSON_PRO_HEADING_M_MEDIUM_ITALIC: "CRIMSON_PRO_HEADING_M_MEDIUM_ITALIC",
1062
+ // Crimson Pro Display Large (40px, upright)
1063
+ CRIMSON_PRO_DISPLAY_L_REGULAR: "CRIMSON_PRO_DISPLAY_L_REGULAR",
1064
+ // Crimson Pro Display Extra Large (46px, italic)
1065
+ CRIMSON_PRO_DISPLAY_XL_REGULAR_ITALIC: "CRIMSON_PRO_DISPLAY_XL_REGULAR_ITALIC"
1066
+ };
1067
+ var typographyStyles = {
1068
+ // Geist Label Caption (12px)
1069
+ [typographyTypes.GEIST_LABEL_CAPTION_REGULAR]: {
1070
+ fontFamily: fontFamilies.GEIST,
1071
+ fontSize: 12,
1072
+ fontWeight: 400,
1073
+ lineHeight: 16
1074
+ },
1075
+ [typographyTypes.GEIST_LABEL_CAPTION_MEDIUM]: {
1076
+ fontFamily: fontFamilies.GEIST,
1077
+ fontSize: 12,
1078
+ fontWeight: 500,
1079
+ lineHeight: 16
1080
+ },
1081
+ [typographyTypes.GEIST_LABEL_CAPTION_SEMI_BOLD]: {
1082
+ fontFamily: fontFamilies.GEIST,
1083
+ fontSize: 12,
1084
+ fontWeight: 600,
1085
+ lineHeight: 16
1086
+ },
1087
+ // Geist Body Extra Small (14px)
1088
+ [typographyTypes.GEIST_BODY_XS_REGULAR]: {
1089
+ fontFamily: fontFamilies.GEIST,
1090
+ fontSize: 14,
1091
+ fontWeight: 400,
1092
+ lineHeight: 20
1093
+ },
1094
+ [typographyTypes.GEIST_BODY_XS_MEDIUM]: {
1095
+ fontFamily: fontFamilies.GEIST,
1096
+ fontSize: 14,
1097
+ fontWeight: 500,
1098
+ lineHeight: 20
1099
+ },
1100
+ [typographyTypes.GEIST_BODY_XS_BOLD]: {
1101
+ fontFamily: fontFamilies.GEIST,
1102
+ fontSize: 14,
1103
+ fontWeight: 600,
1104
+ lineHeight: 20
1105
+ },
1106
+ // Geist Body Small (16px)
1107
+ [typographyTypes.GEIST_BODY_S_REGULAR]: {
1108
+ fontFamily: fontFamilies.GEIST,
1109
+ fontSize: 16,
1110
+ fontWeight: 400,
1111
+ lineHeight: 24,
1112
+ letterSpacing: -0.08
1113
+ },
1114
+ [typographyTypes.GEIST_BODY_S_MEDIUM]: {
1115
+ fontFamily: fontFamilies.GEIST,
1116
+ fontSize: 16,
1117
+ fontWeight: 500,
1118
+ lineHeight: 24,
1119
+ letterSpacing: -0.08
1120
+ },
1121
+ [typographyTypes.GEIST_BODY_S_SEMI_BOLD]: {
1122
+ fontFamily: fontFamilies.GEIST,
1123
+ fontSize: 16,
1124
+ fontWeight: 600,
1125
+ lineHeight: 24,
1126
+ letterSpacing: -0.08
1127
+ },
1128
+ [typographyTypes.GEIST_BODY_S_BOLD]: {
1129
+ fontFamily: fontFamilies.GEIST,
1130
+ fontSize: 16,
1131
+ fontWeight: 700,
1132
+ lineHeight: 24,
1133
+ letterSpacing: -0.08
1134
+ },
1135
+ // Geist Body Medium (18px)
1136
+ [typographyTypes.GEIST_BODY_M_LIGHT]: {
1137
+ fontFamily: fontFamilies.GEIST,
1138
+ fontSize: 18,
1139
+ fontWeight: 300,
1140
+ lineHeight: 28,
1141
+ letterSpacing: -0.09
1142
+ },
1143
+ [typographyTypes.GEIST_BODY_M_REGULAR]: {
1144
+ fontFamily: fontFamilies.GEIST,
1145
+ fontSize: 18,
1146
+ fontWeight: 400,
1147
+ lineHeight: 28,
1148
+ letterSpacing: -0.09
1149
+ },
1150
+ [typographyTypes.GEIST_BODY_M_MEDIUM]: {
1151
+ fontFamily: fontFamilies.GEIST,
1152
+ fontSize: 18,
1153
+ fontWeight: 500,
1154
+ lineHeight: 28,
1155
+ letterSpacing: -0.09
1156
+ },
1157
+ [typographyTypes.GEIST_BODY_M_SEMI_BOLD]: {
1158
+ fontFamily: fontFamilies.GEIST,
1159
+ fontSize: 18,
1160
+ fontWeight: 600,
1161
+ lineHeight: 28,
1162
+ letterSpacing: -0.09
1163
+ },
1164
+ // Geist Body Large (20px)
1165
+ [typographyTypes.GEIST_BODY_L_REGULAR]: {
1166
+ fontFamily: fontFamilies.GEIST,
1167
+ fontSize: 20,
1168
+ fontWeight: 400,
1169
+ lineHeight: 30,
1170
+ letterSpacing: -0.2
1171
+ },
1172
+ [typographyTypes.GEIST_BODY_L_MEDIUM]: {
1173
+ fontFamily: fontFamilies.GEIST,
1174
+ fontSize: 20,
1175
+ fontWeight: 500,
1176
+ lineHeight: 30,
1177
+ letterSpacing: -0.2
1178
+ },
1179
+ [typographyTypes.GEIST_BODY_L_SEMI_BOLD]: {
1180
+ fontFamily: fontFamilies.GEIST,
1181
+ fontSize: 20,
1182
+ fontWeight: 600,
1183
+ lineHeight: 30,
1184
+ letterSpacing: -0.2
1185
+ },
1186
+ [typographyTypes.GEIST_BODY_L_BOLD]: {
1187
+ fontFamily: fontFamilies.GEIST,
1188
+ fontSize: 20,
1189
+ fontWeight: 700,
1190
+ lineHeight: 30,
1191
+ letterSpacing: -0.2
1192
+ },
1193
+ // Geist Heading Small (24px)
1194
+ [typographyTypes.GEIST_HEADING_S_REGULAR]: {
1195
+ fontFamily: fontFamilies.GEIST,
1196
+ fontSize: 24,
1197
+ fontWeight: 400,
1198
+ lineHeight: 32,
1199
+ letterSpacing: -0.48
1200
+ },
1201
+ [typographyTypes.GEIST_HEADING_S_MEDIUM]: {
1202
+ fontFamily: fontFamilies.GEIST,
1203
+ fontSize: 24,
1204
+ fontWeight: 500,
1205
+ lineHeight: 32,
1206
+ letterSpacing: -0.48
1207
+ },
1208
+ [typographyTypes.GEIST_HEADING_S_BOLD]: {
1209
+ fontFamily: fontFamilies.GEIST,
1210
+ fontSize: 24,
1211
+ fontWeight: 700,
1212
+ lineHeight: 32,
1213
+ letterSpacing: -0.48
1214
+ },
1215
+ // Geist Heading Medium (28px)
1216
+ [typographyTypes.GEIST_HEADING_M_BOLD]: {
1217
+ fontFamily: fontFamilies.GEIST,
1218
+ fontSize: 28,
1219
+ fontWeight: 700,
1220
+ lineHeight: 36,
1221
+ letterSpacing: -0.6
1222
+ },
1223
+ // Geist Heading Large (32px)
1224
+ [typographyTypes.GEIST_HEADING_L_REGULAR]: {
1225
+ fontFamily: fontFamilies.GEIST,
1226
+ fontSize: 32,
1227
+ fontWeight: 400,
1228
+ lineHeight: 40,
1229
+ letterSpacing: -0.64
1230
+ },
1231
+ [typographyTypes.GEIST_HEADING_L_MEDIUM]: {
1232
+ fontFamily: fontFamilies.GEIST,
1233
+ fontSize: 32,
1234
+ fontWeight: 500,
1235
+ lineHeight: 40,
1236
+ letterSpacing: -0.64
1237
+ },
1238
+ [typographyTypes.GEIST_HEADING_L_SEMI_BOLD]: {
1239
+ fontFamily: fontFamilies.GEIST,
1240
+ fontSize: 32,
1241
+ fontWeight: 600,
1242
+ lineHeight: 40,
1243
+ letterSpacing: -0.64
1244
+ },
1245
+ [typographyTypes.GEIST_HEADING_L_BOLD]: {
1246
+ fontFamily: fontFamilies.GEIST,
1247
+ fontSize: 32,
1248
+ fontWeight: 700,
1249
+ lineHeight: 40,
1250
+ letterSpacing: -0.64
1251
+ },
1252
+ // Geist Display Large (36px)
1253
+ [typographyTypes.GEIST_DISPLAY_L_MEDIUM]: {
1254
+ fontFamily: fontFamilies.GEIST,
1255
+ fontSize: 36,
1256
+ fontWeight: 500,
1257
+ lineHeight: 44,
1258
+ letterSpacing: -0.72
1259
+ },
1260
+ // Crimson Pro Body Small (16px, italic)
1261
+ [typographyTypes.CRIMSON_PRO_BODY_S_LIGHT_ITALIC]: {
1262
+ fontFamily: fontFamilies.CRIMSON_PRO,
1263
+ fontSize: 16,
1264
+ fontWeight: 300,
1265
+ lineHeight: 20,
1266
+ letterSpacing: -0.32,
1267
+ fontStyle: "italic"
1268
+ },
1269
+ // Crimson Pro Body Medium (18px, italic)
1270
+ [typographyTypes.CRIMSON_PRO_BODY_M_LIGHT_ITALIC]: {
1271
+ fontFamily: fontFamilies.CRIMSON_PRO,
1272
+ fontSize: 18,
1273
+ fontWeight: 300,
1274
+ lineHeight: 28,
1275
+ letterSpacing: 0,
1276
+ fontStyle: "italic"
1277
+ },
1278
+ // Crimson Pro Heading Medium (24px, italic)
1279
+ [typographyTypes.CRIMSON_PRO_HEADING_M_MEDIUM_ITALIC]: {
1280
+ fontFamily: fontFamilies.CRIMSON_PRO,
1281
+ fontSize: 24,
1282
+ fontWeight: 400,
1283
+ lineHeight: 32,
1284
+ letterSpacing: -0.48,
1285
+ fontStyle: "italic"
1286
+ },
1287
+ // Crimson Pro Display Large (40px, upright)
1288
+ [typographyTypes.CRIMSON_PRO_DISPLAY_L_REGULAR]: {
1289
+ fontFamily: fontFamilies.CRIMSON_PRO,
1290
+ fontSize: 40,
1291
+ fontWeight: 300,
1292
+ lineHeight: 48,
1293
+ letterSpacing: -1.6
1294
+ },
1295
+ // Crimson Pro Display Extra Large (46px, italic)
1296
+ [typographyTypes.CRIMSON_PRO_DISPLAY_XL_REGULAR_ITALIC]: {
1297
+ fontFamily: fontFamilies.CRIMSON_PRO,
1298
+ fontSize: 46,
1299
+ fontWeight: 400,
1300
+ lineHeight: 54,
1301
+ letterSpacing: -1.38,
1302
+ fontStyle: "italic"
1303
+ }
1304
+ };
1305
+
961
1306
  // src/components/chart/chart-palette.ts
962
1307
  var CHART_PALETTE = [
963
1308
  colors["blue-600"],
@@ -1690,8 +2035,13 @@ var ChartArtifactService = {
1690
2035
  toClipboardText: chartArtifactToClipboardText
1691
2036
  };
1692
2037
 
1693
- // src/components/artifacts/table-artifact/table-artifact.tsx
1694
- var import_react15 = require("react");
2038
+ // src/components/artifacts/deck-artifact/deck-artifact.tsx
2039
+ var import_react17 = require("react");
2040
+ var import_react_dom = require("react-dom");
2041
+ init_capture_exclude_attribute();
2042
+
2043
+ // src/components/artifacts/deck-artifact/deck-artifact-content.tsx
2044
+ var import_react16 = require("react");
1695
2045
 
1696
2046
  // src/components/ui/table.tsx
1697
2047
  var React3 = __toESM(require("react"), 1);
@@ -1770,6 +2120,36 @@ function useScrollShadow() {
1770
2120
  return { targetRef, isScrolled };
1771
2121
  }
1772
2122
 
2123
+ // src/components/table/data-table.tsx
2124
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2125
+ var DATA_TABLE_HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
2126
+ var DATA_TABLE_CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
2127
+ var DATA_TABLE_ROW_CLASS = "border-b-brown-30 bg-background/70 hover:bg-secondary";
2128
+ var DATA_TABLE_SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
2129
+ function DataTable({ header, children, maxBodyHeight, className }) {
2130
+ const { targetRef, isScrolled } = useScrollShadow();
2131
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2132
+ "div",
2133
+ {
2134
+ ref: targetRef,
2135
+ className: cn("overscroll-none", className),
2136
+ style: maxBodyHeight !== void 0 ? { maxHeight: maxBodyHeight, overflowY: "auto" } : void 0,
2137
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Table, { containerClassName: "overflow-visible", children: [
2138
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2139
+ TableHeader,
2140
+ {
2141
+ "data-scrolled": isScrolled ? "true" : void 0,
2142
+ className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
2143
+ style: isScrolled ? { boxShadow: DATA_TABLE_SCROLL_SHADOW } : void 0,
2144
+ children: header
2145
+ }
2146
+ ),
2147
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableBody, { children })
2148
+ ] })
2149
+ }
2150
+ );
2151
+ }
2152
+
1773
2153
  // src/components/artifacts/table-artifact/table-artifact-content.constants.ts
1774
2154
  var TABLE_STATUS = {
1775
2155
  LOADING: "loading",
@@ -1782,14 +2162,10 @@ var TABLE_STATUS = {
1782
2162
  function formatCell(row, column) {
1783
2163
  return row[column.key] ?? "";
1784
2164
  }
1785
- var HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
1786
- var CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
1787
- var ROW_CLASSES = "border-b-brown-30 bg-background/70 hover:bg-secondary";
1788
- var DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;
1789
- var SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
2165
+ var DATA_ROW_CLASSES = `${DATA_TABLE_ROW_CLASS} animate-in fade-in duration-300`;
1790
2166
 
1791
2167
  // src/components/artifacts/table-artifact/table-artifact-content.tsx
1792
- var import_jsx_runtime21 = require("react/jsx-runtime");
2168
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1793
2169
  function TableArtifactContent({
1794
2170
  columns,
1795
2171
  data,
@@ -1799,48 +2175,367 @@ function TableArtifactContent({
1799
2175
  labels
1800
2176
  }) {
1801
2177
  if (data.status === TABLE_STATUS.ERROR) {
1802
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusMessage, { $tone: "error", children: labels.loadError });
2178
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "error", children: labels.loadError });
1803
2179
  }
1804
2180
  if (data.status === TABLE_STATUS.UNAVAILABLE) {
1805
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
2181
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
1806
2182
  }
1807
2183
  if (data.status === TABLE_STATUS.LOADING) {
1808
2184
  if (typeof knownRowCount === "number" && knownRowCount > 0) {
1809
2185
  const shimmerCount = Math.min(knownRowCount, maxShimmerRows);
1810
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
2186
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
1811
2187
  }
1812
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusMessage, { $tone: "info", children: labels.loading });
2188
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "info", children: labels.loading });
1813
2189
  }
1814
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ArtifactTable, { columns, maxBodyHeight, children: data.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data.rows) });
2190
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTable, { columns, maxBodyHeight, children: data.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data.rows) });
1815
2191
  }
1816
2192
  function ArtifactTable({ columns, maxBodyHeight, children }) {
1817
- const { targetRef, isScrolled } = useScrollShadow();
1818
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { ref: targetRef, className: "overscroll-none", style: { maxHeight: maxBodyHeight, overflowY: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Table, { containerClassName: "overflow-visible", children: [
1819
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1820
- TableHeader,
2193
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2194
+ DataTable,
2195
+ {
2196
+ maxBodyHeight,
2197
+ header: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: "hover:bg-transparent", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: column.label }, column.key)) }),
2198
+ children
2199
+ }
2200
+ );
2201
+ }
2202
+ function renderShimmerRows(columns, count) {
2203
+ return Array.from({ length: count }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: DATA_TABLE_ROW_CLASS, "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20" }) }, column.key)) }, `shimmer-${index}`));
2204
+ }
2205
+ function renderDataRows(columns, rows) {
2206
+ return rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: DATA_ROW_CLASSES, children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: formatCell(row, column) }, column.key)) }, index));
2207
+ }
2208
+ function renderEmptyRow(colSpan, emptyMessage) {
2209
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableCell, { colSpan, className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) });
2210
+ }
2211
+
2212
+ // src/components/artifacts/deck-artifact/deck-markdown.tsx
2213
+ var import_react_markdown = __toESM(require("react-markdown"), 1);
2214
+ var import_remark_breaks = __toESM(require("remark-breaks"), 1);
2215
+ var import_remark_gfm = __toESM(require("remark-gfm"), 1);
2216
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2217
+ function sanitize(text) {
2218
+ return text.split("\n").filter((line) => {
2219
+ const t = line.trim();
2220
+ return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
2221
+ }).join("\n");
2222
+ }
2223
+ var MARKDOWN_COMPONENTS = {
2224
+ h1: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: "text-[30px] font-semibold leading-tight text-foreground mb-3", ...props }),
2225
+ h2: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "text-[26px] font-semibold leading-tight text-foreground mb-2", ...props }),
2226
+ h3: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2227
+ h4: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h4", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2228
+ h5: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h5", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2229
+ h6: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h6", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2230
+ p: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[22px] leading-relaxed text-foreground my-2", ...props }),
2231
+ ul: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("ul", { className: "list-disc pl-7 text-[22px] leading-relaxed text-foreground my-2", ...props }),
2232
+ ol: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("ol", { className: "list-decimal pl-7 text-[22px] leading-relaxed text-foreground my-2", ...props }),
2233
+ // react-markdown injects list metadata (`ordered` / `index` / `checked`) that must not leak to the DOM.
2234
+ li: ({ node: _node, ordered: _ordered, index: _index, checked: _checked, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("li", { className: "my-1", ...props }),
2235
+ strong: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("strong", { className: "font-semibold", ...props }),
2236
+ em: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("em", { className: "italic", ...props }),
2237
+ // Gate `<img src>` against an http(s) allowlist. react-markdown v8 percent-encodes the URL but
2238
+ // does NOT protocol-filter image src (unlike link href), so an LLM-authored
2239
+ // `![](javascript:…)` / `![](data:…)` or a tracking-pixel `![](http://…)` would otherwise render
2240
+ // with the raw URL. Unsafe src → render nothing.
2241
+ img: ({ node: _node, src, ...props }) => typeof src === "string" && isSafeDownloadUrl(src) ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src, className: "max-w-full", ...props }) : null,
2242
+ a: ({ node: _node, ...props }) => (
2243
+ // `rel` is forced AFTER `{...props}` so it can't be overridden — if a consumer ever adds
2244
+ // `linkTarget="_blank"`, LLM-authored links still can't reach `window.opener`.
2245
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("a", { className: "underline underline-offset-2", ...props, rel: "noopener noreferrer" })
2246
+ ),
2247
+ // react-markdown passes `inline` to distinguish inline code from fenced blocks — strip it from the DOM.
2248
+ code: ({ node: _node, inline: _inline, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("code", { className: "rounded bg-muted px-1.5 py-0.5 font-mono text-[18px]", ...props }),
2249
+ blockquote: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("blockquote", { className: "border-l-2 border-brown-alpha-12 pl-4 text-[22px] text-muted-foreground", ...props }),
2250
+ hr: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("hr", { className: "my-4 border-brown-alpha-12", ...props }),
2251
+ table: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("table", { className: "w-full border-collapse text-[20px]", ...props }) }),
2252
+ // react-markdown passes `isHeader` to cell renderers — strip it so it never reaches the DOM.
2253
+ th: ({ node: _node, isHeader: _isHeader, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "border-b border-brown-alpha-12 px-3 py-1.5 text-left font-medium", ...props }),
2254
+ td: ({ node: _node, isHeader: _isHeader, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "border-b border-brown-alpha-12 px-3 py-1.5", ...props })
2255
+ };
2256
+ function DeckMarkdown({ markdown }) {
2257
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: MARKDOWN_COMPONENTS, children: sanitize(markdown) });
2258
+ }
2259
+
2260
+ // src/components/artifacts/deck-artifact/slide-renderers.tsx
2261
+ var import_react15 = require("react");
2262
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2263
+ function safeLogoUrl(meta) {
2264
+ return meta?.logoUrl && isSafeDownloadUrl(meta.logoUrl) ? meta.logoUrl : null;
2265
+ }
2266
+ var DESIGN_W = 1280;
2267
+ var DESIGN_H = 720;
2268
+ var EYEBROW_H = 84;
2269
+ var CANVAS_LOGO_MAX_H = 48;
2270
+ var ACCENT_FONT = { fontFamily: `"${fontFamilies.CRIMSON_PRO}", serif`, fontStyle: "italic" };
2271
+ function SlideFrame({ meta, children, accent = false, bare = false }) {
2272
+ const frameRef = (0, import_react15.useRef)(null);
2273
+ const [scale, setScale] = (0, import_react15.useState)(null);
2274
+ (0, import_react15.useLayoutEffect)(() => {
2275
+ const el = frameRef.current;
2276
+ if (!el) return;
2277
+ const apply = (width) => {
2278
+ if (width > 0) setScale(width / DESIGN_W);
2279
+ };
2280
+ apply(el.clientWidth);
2281
+ const ro = new ResizeObserver((entries) => apply(entries[0]?.contentRect.width ?? 0));
2282
+ ro.observe(el);
2283
+ return () => ro.disconnect();
2284
+ }, []);
2285
+ const bg = accent ? "bg-indigo-600" : "bg-deck-canvas";
2286
+ const eyebrowColor = accent ? "text-white/70" : "text-brown-60";
2287
+ const borderColor = accent ? "border-white/20" : "border-brown-alpha-12";
2288
+ const logoSrc = safeLogoUrl(meta);
2289
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: frameRef, className: `relative aspect-[16/9] w-full overflow-hidden rounded-lg ${bg}`, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2290
+ "div",
2291
+ {
2292
+ className: "absolute left-0 top-0 origin-top-left",
2293
+ style: {
2294
+ width: DESIGN_W,
2295
+ height: DESIGN_H,
2296
+ transform: `scale(${scale ?? 0})`,
2297
+ visibility: scale === null ? "hidden" : "visible"
2298
+ },
2299
+ children: [
2300
+ !bare ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2301
+ "div",
2302
+ {
2303
+ className: `absolute inset-x-0 top-0 flex items-center justify-between border-b px-16 ${borderColor}`,
2304
+ style: { height: EYEBROW_H },
2305
+ children: [
2306
+ meta?.eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: eyebrowColor, style: { ...ACCENT_FONT, fontSize: 22 }, children: meta.eyebrow }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", {}),
2307
+ logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: logoSrc, alt: "", className: "object-contain", style: { maxHeight: CANVAS_LOGO_MAX_H } }) : null
2308
+ ]
2309
+ }
2310
+ ) : null,
2311
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute inset-x-0 bottom-0 overflow-hidden", style: { top: bare ? 0 : EYEBROW_H }, children })
2312
+ ]
2313
+ }
2314
+ ) });
2315
+ }
2316
+ function TitleSlide({ slide, meta }) {
2317
+ const logoSrc = safeLogoUrl(meta);
2318
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, bare: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full flex-col justify-center px-24 py-16", children: [
2319
+ logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2320
+ "img",
2321
+ {
2322
+ src: logoSrc,
2323
+ alt: "",
2324
+ className: "mb-16 object-contain object-left",
2325
+ style: { maxHeight: 56, maxWidth: 380 }
2326
+ }
2327
+ ) : null,
2328
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2329
+ "h1",
1821
2330
  {
1822
- "data-scrolled": isScrolled ? "true" : void 0,
1823
- className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
1824
- style: isScrolled ? { boxShadow: SCROLL_SHADOW } : void 0,
1825
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableRow, { className: "hover:bg-transparent", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableHead, { scope: "col", className: HEAD_CLASS, children: column.label }, column.key)) })
2331
+ className: "font-bold tracking-tight text-brown-100",
2332
+ style: { fontSize: 92, lineHeight: 1.04, maxWidth: 1060 },
2333
+ children: slide.title
1826
2334
  }
1827
2335
  ),
1828
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableBody, { children })
2336
+ slide.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-7 text-brown-70", style: { ...ACCENT_FONT, fontSize: 34 }, children: slide.subtitle }) : null,
2337
+ slide.description ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-4 leading-relaxed text-brown-70", style: { fontSize: 24, maxWidth: 880 }, children: slide.description }) : null,
2338
+ meta?.date ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-10 text-brown-70", style: { ...ACCENT_FONT, fontSize: 30 }, children: meta.date }) : null
1829
2339
  ] }) });
1830
2340
  }
1831
- function renderShimmerRows(columns, count) {
1832
- return Array.from({ length: count }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableRow, { className: ROW_CLASSES, "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableCell, { className: CELL_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20" }) }, column.key)) }, `shimmer-${index}`));
2341
+ function AgendaSlide({ slide, meta, labels }) {
2342
+ const items = slide.items ?? [];
2343
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "h-full px-24 py-14", children: [
2344
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "mb-10 font-bold text-brown-90", style: { fontSize: 40 }, children: slide.title || labels.agenda }),
2345
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex flex-col", children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-baseline gap-6 border-b border-brown-alpha-12 py-5", children: [
2346
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "shrink-0 text-indigo-600", style: { ...ACCENT_FONT, fontSize: 28, width: 64 }, children: String(i + 1).padStart(2, "0") }),
2347
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-brown-90", style: { fontSize: 28 }, children: item })
2348
+ ] }, i)) })
2349
+ ] }) });
1833
2350
  }
1834
- function renderDataRows(columns, rows) {
1835
- return rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableRow, { className: DATA_ROW_CLASSES, children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableCell, { className: CELL_CLASS, children: formatCell(row, column) }, column.key)) }, index));
2351
+ function SectionSlide({ slide, meta }) {
2352
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, accent: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full flex-col justify-center gap-6 px-24", children: [
2353
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "font-bold text-white", style: { fontSize: 72, lineHeight: 1.05, maxWidth: 940 }, children: slide.title }),
2354
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-2 bg-white/50", style: { width: 96, height: 5 } })
2355
+ ] }) });
1836
2356
  }
1837
- function renderEmptyRow(colSpan, emptyMessage) {
1838
- 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 }) });
2357
+ function ClosingSlide({ meta, labels }) {
2358
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full flex-col items-center justify-center gap-6 px-24 text-center", children: [
2359
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h1", { className: "font-bold text-brown-100", style: { fontSize: 72 }, children: labels.thankYou }),
2360
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-indigo-600", style: { ...ACCENT_FONT, fontSize: 36 }, children: labels.questions })
2361
+ ] }) });
1839
2362
  }
1840
2363
 
1841
- // src/components/artifacts/table-artifact/use-table-artifact-data.ts
1842
- function useTableArtifactData(presignedUrl, columns) {
1843
- return useRowsArtifactData(presignedUrl, columns, parseCsv);
2364
+ // src/components/artifacts/deck-artifact/deck-artifact-content.tsx
2365
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2366
+ var TABLE_BLOCK_MAX_SHIMMER_ROWS = 10;
2367
+ var TABLE_CHROME_RESERVE = 56;
2368
+ var VISUAL_FALLBACK_HEIGHT = 360;
2369
+ function DeckArtifactContent({
2370
+ slides,
2371
+ labels,
2372
+ onNavigate,
2373
+ meta,
2374
+ onDark = false,
2375
+ currentSlide,
2376
+ onSlideChange
2377
+ }) {
2378
+ const navBtnClass = onDark ? "[&_svg]:!text-white hover:!bg-white/20 disabled:opacity-40" : void 0;
2379
+ const navBtnSize = onDark ? "medium" : "small";
2380
+ const isControlled = currentSlide !== void 0;
2381
+ const [internalIndex, setInternalIndex] = (0, import_react16.useState)(0);
2382
+ const index = isControlled ? currentSlide : internalIndex;
2383
+ const current = Math.min(index, slides.length - 1);
2384
+ const slide = slides[current];
2385
+ const goTo = (0, import_react16.useCallback)(
2386
+ (next) => {
2387
+ const clamped = Math.max(0, Math.min(next, slides.length - 1));
2388
+ if (isControlled) onSlideChange?.(clamped);
2389
+ else setInternalIndex(clamped);
2390
+ onNavigate?.(clamped);
2391
+ },
2392
+ [slides.length, onNavigate, isControlled, onSlideChange]
2393
+ );
2394
+ const position = labels.position.replace("{current}", String(current + 1)).replace("{total}", String(slides.length));
2395
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
2396
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideDispatch, { slide, labels, meta }),
2397
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
2398
+ "div",
2399
+ {
2400
+ className: `flex items-center justify-between border-t pt-2 ${onDark ? "border-white/20" : "border-brown-alpha-12"}`,
2401
+ children: [
2402
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2403
+ IconButton,
2404
+ {
2405
+ icon: IconChevronLeft,
2406
+ size: navBtnSize,
2407
+ className: navBtnClass,
2408
+ "aria-label": labels.previous,
2409
+ disabled: current === 0,
2410
+ onClick: () => goTo(current - 1)
2411
+ }
2412
+ ),
2413
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: `text-xs font-medium ${onDark ? "text-white/70" : "text-brown-70"}`, children: position }),
2414
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2415
+ IconButton,
2416
+ {
2417
+ icon: IconChevronRight,
2418
+ size: navBtnSize,
2419
+ className: navBtnClass,
2420
+ "aria-label": labels.next,
2421
+ disabled: current === slides.length - 1,
2422
+ onClick: () => goTo(current + 1)
2423
+ }
2424
+ )
2425
+ ]
2426
+ }
2427
+ )
2428
+ ] });
2429
+ }
2430
+ function SlideDispatch({ slide, labels, meta }) {
2431
+ const kind = slide.kind ?? deckSlideKinds.CONTENT;
2432
+ switch (kind) {
2433
+ case deckSlideKinds.TITLE:
2434
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TitleSlide, { slide, meta });
2435
+ case deckSlideKinds.AGENDA:
2436
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AgendaSlide, { slide, meta, labels });
2437
+ case deckSlideKinds.SECTION:
2438
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SectionSlide, { slide, meta });
2439
+ case deckSlideKinds.CLOSING:
2440
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ClosingSlide, { meta, labels });
2441
+ case deckSlideKinds.CONTENT:
2442
+ default:
2443
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ContentSlide, { slide, meta, labels });
2444
+ }
2445
+ }
2446
+ function isVisualBlock(block) {
2447
+ return block.type === deckBlockTypes.CHART || block.type === deckBlockTypes.TABLE;
2448
+ }
2449
+ function ContentSlide({ slide, meta, labels }) {
2450
+ const content = slide.content ?? [];
2451
+ const visuals = content.filter(isVisualBlock);
2452
+ const texts = content.filter(
2453
+ (b) => b.type === deckBlockTypes.TEXT
2454
+ );
2455
+ if (visuals.length === 1 && texts.length > 0) {
2456
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex h-full items-stretch gap-12 px-16 py-12", children: [
2457
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex w-[42%] shrink-0 flex-col overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(AutoFit, { children: [
2458
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "mb-5 font-bold leading-tight text-foreground", style: { fontSize: 34 }, children: slide.title }),
2459
+ texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
2460
+ ] }) }),
2461
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "min-h-0 min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FillVisual, { block: visuals[0], labels }) })
2462
+ ] }) });
2463
+ }
2464
+ if (visuals.length > 0) {
2465
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex h-full flex-col gap-5 px-16 py-10", children: [
2466
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "shrink-0 font-bold leading-tight text-foreground", style: { fontSize: 32 }, children: slide.title }),
2467
+ content.map(
2468
+ (block, i) => isVisualBlock(block) ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "min-h-0 min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FillVisual, { block, labels }) }, i) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "shrink-0 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }) }, i)
2469
+ )
2470
+ ] }) });
2471
+ }
2472
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-full px-24 py-12", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(AutoFit, { children: [
2473
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "mb-6 font-bold leading-tight text-foreground", style: { fontSize: 38 }, children: slide.title }),
2474
+ texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
2475
+ ] }) }) });
2476
+ }
2477
+ function AutoFit({ children }) {
2478
+ const boxRef = (0, import_react16.useRef)(null);
2479
+ const contentRef = (0, import_react16.useRef)(null);
2480
+ const [fit, setFit] = (0, import_react16.useState)({ scale: 1, height: 0 });
2481
+ (0, import_react16.useLayoutEffect)(() => {
2482
+ const boxEl = boxRef.current;
2483
+ const contentEl = contentRef.current;
2484
+ if (!boxEl || !contentEl) return;
2485
+ const measure = () => {
2486
+ const avail = boxEl.clientHeight;
2487
+ const natural = contentEl.offsetHeight;
2488
+ const scale = avail > 0 && natural > avail ? avail / natural : 1;
2489
+ setFit({ scale, height: natural * scale });
2490
+ };
2491
+ measure();
2492
+ const ro = new ResizeObserver(measure);
2493
+ ro.observe(boxEl);
2494
+ ro.observe(contentEl);
2495
+ return () => ro.disconnect();
2496
+ }, []);
2497
+ const scaled = fit.scale < 1;
2498
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: boxRef, className: "flex h-full min-h-0 w-full flex-col justify-center overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: scaled ? { height: fit.height } : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2499
+ "div",
2500
+ {
2501
+ ref: contentRef,
2502
+ className: "w-full origin-top-left",
2503
+ style: scaled ? { transform: `scale(${fit.scale})` } : void 0,
2504
+ children
2505
+ }
2506
+ ) }) });
2507
+ }
2508
+ function FillVisual({ block, labels }) {
2509
+ const ref = (0, import_react16.useRef)(null);
2510
+ const [height, setHeight] = (0, import_react16.useState)(VISUAL_FALLBACK_HEIGHT);
2511
+ (0, import_react16.useLayoutEffect)(() => {
2512
+ const el = ref.current;
2513
+ if (!el) return;
2514
+ const apply = (h) => {
2515
+ if (h > 0) setHeight(h);
2516
+ };
2517
+ apply(el.clientHeight);
2518
+ const ro = new ResizeObserver((entries) => apply(entries[0]?.contentRect.height ?? 0));
2519
+ ro.observe(el);
2520
+ return () => ro.disconnect();
2521
+ }, []);
2522
+ const chartLabels = labels.chart ?? DEFAULT_CHART_ARTIFACT_LABELS;
2523
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref, className: "h-full min-h-0 w-full overflow-hidden", children: block.type === deckBlockTypes.CHART ? (
2524
+ // ChartArtifactContent assumes a non-empty rowset (the standalone ChartArtifact guards
2525
+ // `rows.length > 0` upstream); mirror that guard here so an empty inline chart shows the
2526
+ // localized empty status instead of a blank chart area.
2527
+ block.rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusMessage, { $tone: "info", children: chartLabels.empty }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { height }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChartArtifactContent, { config: block.config, rows: block.rows, labels: chartLabels }) })
2528
+ ) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2529
+ TableArtifactContent,
2530
+ {
2531
+ columns: block.config.columns,
2532
+ data: { status: "ready", rows: block.rows, error: null },
2533
+ knownRowCount: block.config.stats?.rowCount ?? block.rows.length,
2534
+ maxShimmerRows: TABLE_BLOCK_MAX_SHIMMER_ROWS,
2535
+ maxBodyHeight: Math.max(0, height - TABLE_CHROME_RESERVE),
2536
+ labels: labels.table ?? DEFAULT_TABLE_ARTIFACT_LABELS
2537
+ }
2538
+ ) });
1844
2539
  }
1845
2540
 
1846
2541
  // src/components/artifacts/table-artifact/validate.ts
@@ -1859,19 +2554,265 @@ function isValidTableColumn(column) {
1859
2554
  return true;
1860
2555
  }
1861
2556
 
1862
- // src/components/artifacts/table-artifact/table-artifact.tsx
1863
- var import_jsx_runtime22 = require("react/jsx-runtime");
2557
+ // src/components/artifacts/deck-artifact/validate.ts
2558
+ function isValidDeckConfig(config) {
2559
+ if (!config || typeof config !== "object") return false;
2560
+ const candidate = config;
2561
+ if (!Array.isArray(candidate.slides)) return false;
2562
+ if (candidate.slides.length === 0) return false;
2563
+ return candidate.slides.every(isValidDeckSlide);
2564
+ }
2565
+ function isValidDeckSlide(slide) {
2566
+ if (!slide || typeof slide !== "object") return false;
2567
+ const candidate = slide;
2568
+ if (typeof candidate.title !== "string") return false;
2569
+ const kind = typeof candidate.kind === "string" ? candidate.kind : deckSlideKinds.CONTENT;
2570
+ if (kind === deckSlideKinds.CONTENT && !Array.isArray(candidate.content)) return false;
2571
+ const content = Array.isArray(candidate.content) ? candidate.content : [];
2572
+ if (candidate.items != null) {
2573
+ if (!Array.isArray(candidate.items)) return false;
2574
+ if (!candidate.items.every((item) => typeof item === "string")) return false;
2575
+ }
2576
+ return content.every(isValidDeckBlock);
2577
+ }
2578
+ function isValidDeckBlock(block) {
2579
+ if (!block || typeof block !== "object") return false;
2580
+ const candidate = block;
2581
+ switch (candidate.type) {
2582
+ case deckBlockTypes.TEXT:
2583
+ return typeof candidate.markdown === "string";
2584
+ case deckBlockTypes.CHART:
2585
+ return isValidChartConfig(candidate.config) && Array.isArray(candidate.rows);
2586
+ case deckBlockTypes.TABLE:
2587
+ return isValidTableConfig(candidate.config) && Array.isArray(candidate.rows);
2588
+ default:
2589
+ return false;
2590
+ }
2591
+ }
2592
+
2593
+ // src/components/artifacts/deck-artifact/deck-artifact.tsx
2594
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1864
2595
  var TITLE_CLASSES2 = "text-sm font-semibold text-foreground";
2596
+ function DeckArtifact({ artifact, labels, callbacks }) {
2597
+ const validConfig = isValidDeckConfig(artifact.config);
2598
+ const [isFullscreen, setIsFullscreen] = (0, import_react17.useState)(false);
2599
+ const [currentSlide, setCurrentSlide] = (0, import_react17.useState)(0);
2600
+ (0, import_react17.useEffect)(() => {
2601
+ if (validConfig) return;
2602
+ console.warn("[clay] DeckArtifact: malformed `config` \u2014 skipping render.");
2603
+ }, [validConfig]);
2604
+ (0, import_react17.useEffect)(() => {
2605
+ if (!isFullscreen) return;
2606
+ const handleKey = (e) => {
2607
+ if (e.key === "Escape") setIsFullscreen(false);
2608
+ };
2609
+ document.addEventListener("keydown", handleKey);
2610
+ const previousOverflow = document.documentElement.style.overflow;
2611
+ document.documentElement.style.overflow = "hidden";
2612
+ return () => {
2613
+ document.removeEventListener("keydown", handleKey);
2614
+ document.documentElement.style.overflow = previousOverflow;
2615
+ };
2616
+ }, [isFullscreen]);
2617
+ const resolvedLabels = (0, import_react17.useMemo)(
2618
+ () => ({
2619
+ ...DEFAULT_DECK_ARTIFACT_LABELS,
2620
+ ...labels ?? {},
2621
+ chart: { ...DEFAULT_CHART_ARTIFACT_LABELS, ...labels?.chart ?? {} },
2622
+ table: { ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels?.table ?? {} }
2623
+ }),
2624
+ [labels]
2625
+ );
2626
+ const onNavigate = callbacks?.onNavigate;
2627
+ const handleNavigate = onNavigate ? (slideIndex) => onNavigate(artifact, slideIndex) : void 0;
2628
+ const onDownload = callbacks?.onDownload;
2629
+ const handleDownload = onDownload ? () => onDownload(artifact) : void 0;
2630
+ const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
2631
+ const showDownload = presignedUrl !== null && isSafeDownloadUrl(presignedUrl);
2632
+ const meta = artifact.config?.meta;
2633
+ const handleOpenFullscreen = () => setIsFullscreen(true);
2634
+ const handleCloseFullscreen = () => setIsFullscreen(false);
2635
+ const actions = /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactActions, { ...{ [CAPTURE_EXCLUDE_ATTRIBUTE]: "" }, children: [
2636
+ showDownload ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactDownloadButton, { href: presignedUrl ?? "", label: resolvedLabels.download, onClick: handleDownload }) : null,
2637
+ validConfig ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2638
+ IconButton,
2639
+ {
2640
+ icon: IconArrowsMaximize,
2641
+ size: "small",
2642
+ "aria-label": resolvedLabels.enterFullscreen,
2643
+ onClick: handleOpenFullscreen
2644
+ }
2645
+ ) : null
2646
+ ] });
2647
+ if (!validConfig) {
2648
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2649
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2650
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
2651
+ actions
2652
+ ] }),
2653
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
2654
+ ] });
2655
+ }
2656
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
2657
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2658
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2659
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
2660
+ actions
2661
+ ] }),
2662
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2663
+ DeckArtifactContent,
2664
+ {
2665
+ slides: artifact.config.slides,
2666
+ labels: resolvedLabels,
2667
+ onNavigate: handleNavigate,
2668
+ meta,
2669
+ currentSlide,
2670
+ onSlideChange: setCurrentSlide
2671
+ }
2672
+ ) })
2673
+ ] }),
2674
+ isFullscreen && (0, import_react_dom.createPortal)(
2675
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2676
+ FullscreenOverlay,
2677
+ {
2678
+ artifact,
2679
+ resolvedLabels,
2680
+ onNavigate: handleNavigate,
2681
+ currentSlide,
2682
+ onSlideChange: setCurrentSlide,
2683
+ onClose: handleCloseFullscreen
2684
+ }
2685
+ ),
2686
+ document.body
2687
+ )
2688
+ ] });
2689
+ }
2690
+ function FullscreenOverlay({
2691
+ artifact,
2692
+ resolvedLabels,
2693
+ onNavigate,
2694
+ currentSlide,
2695
+ onSlideChange,
2696
+ onClose
2697
+ }) {
2698
+ const meta = artifact.config?.meta;
2699
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2700
+ "div",
2701
+ {
2702
+ className: "fixed inset-0 z-[2147483647] flex items-center justify-center bg-black/80",
2703
+ role: "dialog",
2704
+ "aria-modal": "true",
2705
+ "aria-label": resolvedLabels.exitFullscreen,
2706
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "relative", style: { width: "min(94vw, calc(82vh * 16 / 9))" }, children: [
2707
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2708
+ DeckArtifactContent,
2709
+ {
2710
+ slides: artifact.config.slides,
2711
+ labels: resolvedLabels,
2712
+ onNavigate,
2713
+ meta,
2714
+ currentSlide,
2715
+ onSlideChange,
2716
+ onDark: true
2717
+ }
2718
+ ),
2719
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
2720
+ "button",
2721
+ {
2722
+ className: "absolute -top-10 right-6 flex items-center gap-1.5 text-sm text-white/80 hover:text-white",
2723
+ "aria-label": resolvedLabels.exitFullscreen,
2724
+ onClick: onClose,
2725
+ children: [
2726
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IconArrowsMinimize, { size: 16 }),
2727
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: resolvedLabels.exitFullscreen })
2728
+ ]
2729
+ }
2730
+ )
2731
+ ] })
2732
+ }
2733
+ );
2734
+ }
2735
+
2736
+ // src/components/artifacts/deck-artifact/to-clipboard-text.ts
2737
+ function deckArtifactToClipboardText(artifact) {
2738
+ const header = artifact.title?.trim() || "Deck";
2739
+ const slides = artifact.config?.slides ?? [];
2740
+ const body = slides.map((slide, i) => slideToText(slide, i)).join("\n\n");
2741
+ return body ? `${header}
2742
+
2743
+ ${body}` : header;
2744
+ }
2745
+ function slideToText(slide, index) {
2746
+ const kind = slide.kind ?? deckSlideKinds.CONTENT;
2747
+ const prefix = `Slide ${index + 1}: `;
2748
+ switch (kind) {
2749
+ case deckSlideKinds.TITLE: {
2750
+ const parts = [slide.title];
2751
+ if (slide.subtitle) parts.push(slide.subtitle);
2752
+ if (slide.description) parts.push(slide.description);
2753
+ return `${prefix}${parts.join(" \u2014 ")}`.trim();
2754
+ }
2755
+ case deckSlideKinds.AGENDA: {
2756
+ const items = (slide.items ?? []).map((item, i) => ` ${String(i + 1).padStart(2, "0")}. ${item}`).join("\n");
2757
+ return `${prefix}${slide.title || "Agenda"}${items ? `
2758
+ ${items}` : ""}`.trim();
2759
+ }
2760
+ case deckSlideKinds.SECTION:
2761
+ return `${prefix}${slide.title}`.trim();
2762
+ case deckSlideKinds.CLOSING:
2763
+ return `${prefix}Thank you`.trim();
2764
+ case deckSlideKinds.CONTENT:
2765
+ default: {
2766
+ const blocks = (slide.content ?? []).map(blockToText).filter(Boolean).join("\n\n");
2767
+ return `${prefix}${slide.title}${blocks ? `
2768
+ ${blocks}` : ""}`.trim();
2769
+ }
2770
+ }
2771
+ }
2772
+ function blockToText(block) {
2773
+ switch (block.type) {
2774
+ case deckBlockTypes.TEXT:
2775
+ return block.markdown.trim();
2776
+ case deckBlockTypes.CHART:
2777
+ return `[Chart: ${block.config.variant}]`;
2778
+ case deckBlockTypes.TABLE: {
2779
+ const columnCount = block.config.columns.length;
2780
+ const rowCount = block.rows.length;
2781
+ return `[Table: ${columnCount} column${columnCount === 1 ? "" : "s"} \xD7 ${rowCount} row${rowCount === 1 ? "" : "s"}]`;
2782
+ }
2783
+ default:
2784
+ return "";
2785
+ }
2786
+ }
2787
+
2788
+ // src/components/artifacts/artifact-services/deck-artifact-service.ts
2789
+ var DeckArtifactService = {
2790
+ type: artifactTypes.DECK,
2791
+ Component: DeckArtifact,
2792
+ toClipboardText: deckArtifactToClipboardText
2793
+ };
2794
+
2795
+ // src/components/artifacts/table-artifact/table-artifact.tsx
2796
+ var import_react18 = require("react");
2797
+
2798
+ // src/components/artifacts/table-artifact/use-table-artifact-data.ts
2799
+ function useTableArtifactData(presignedUrl, columns) {
2800
+ return useRowsArtifactData(presignedUrl, columns, parseCsv);
2801
+ }
2802
+
2803
+ // src/components/artifacts/table-artifact/table-artifact.tsx
2804
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2805
+ var TITLE_CLASSES3 = "text-sm font-semibold text-foreground";
1865
2806
  var TABLE_MAX_BODY_HEIGHT = 480;
1866
2807
  var MAX_SHIMMER_ROWS = 10;
1867
2808
  function TableArtifact({ artifact, labels, callbacks }) {
1868
2809
  const validConfig = isValidTableConfig(artifact.config);
1869
2810
  const validColumns = validConfig ? artifact.config.columns : null;
1870
- (0, import_react15.useEffect)(() => {
2811
+ (0, import_react18.useEffect)(() => {
1871
2812
  if (validConfig) return;
1872
2813
  console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
1873
2814
  }, [validConfig]);
1874
- const resolvedLabels = (0, import_react15.useMemo)(
2815
+ const resolvedLabels = (0, import_react18.useMemo)(
1875
2816
  () => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels ?? {} }),
1876
2817
  [labels]
1877
2818
  );
@@ -1883,10 +2824,10 @@ function TableArtifact({ artifact, labels, callbacks }) {
1883
2824
  const onDownload = callbacks?.onDownload;
1884
2825
  const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
1885
2826
  if (!validConfig || !validColumns) {
1886
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
1887
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
1888
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", {}),
1889
- presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2827
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2828
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2829
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", {}),
2830
+ presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1890
2831
  ArtifactDownloadButton,
1891
2832
  {
1892
2833
  href: presignedUrl,
@@ -1895,17 +2836,17 @@ function TableArtifact({ artifact, labels, callbacks }) {
1895
2836
  }
1896
2837
  ) }) : null
1897
2838
  ] }),
1898
- /* @__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 }) })
2839
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
1899
2840
  ] });
1900
2841
  }
1901
2842
  return (
1902
2843
  // The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
1903
2844
  // Disable the outer overflow container so only one scroll context exists — this prevents
1904
2845
  // double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
1905
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
1906
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
1907
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", {}),
1908
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2846
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2847
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2848
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", {}),
2849
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1909
2850
  ArtifactDownloadButton,
1910
2851
  {
1911
2852
  href: presignedUrl ?? "",
@@ -1914,7 +2855,7 @@ function TableArtifact({ artifact, labels, callbacks }) {
1914
2855
  }
1915
2856
  ) })
1916
2857
  ] }),
1917
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2858
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1918
2859
  TableArtifactContent,
1919
2860
  {
1920
2861
  columns: validColumns,
@@ -1945,7 +2886,8 @@ var TableArtifactService = {
1945
2886
  // src/components/artifacts/artifact-services/index.ts
1946
2887
  var ArtifactServices = {
1947
2888
  [artifactTypes.TABLE]: TableArtifactService,
1948
- [artifactTypes.CHART]: ChartArtifactService
2889
+ [artifactTypes.CHART]: ChartArtifactService,
2890
+ [artifactTypes.DECK]: DeckArtifactService
1949
2891
  };
1950
2892
  function artifactToClipboardText(artifact) {
1951
2893
  const entry = ArtifactServices[artifact.type];
@@ -1962,10 +2904,14 @@ function artifactToClipboardText(artifact) {
1962
2904
  ArtifactServices,
1963
2905
  ChartArtifact,
1964
2906
  DEFAULT_CHART_ARTIFACT_LABELS,
2907
+ DEFAULT_DECK_ARTIFACT_LABELS,
1965
2908
  DEFAULT_TABLE_ARTIFACT_LABELS,
2909
+ DeckArtifact,
1966
2910
  TableArtifact,
1967
2911
  artifactToClipboardText,
1968
2912
  artifactTypes,
2913
+ deckBlockTypes,
2914
+ deckSlideKinds,
1969
2915
  isSafeDownloadUrl
1970
2916
  });
1971
2917
  /*! Bundled license information:
@@ -1973,7 +2919,11 @@ function artifactToClipboardText(artifact) {
1973
2919
  @tabler/icons-react/dist/esm/defaultAttributes.mjs:
1974
2920
  @tabler/icons-react/dist/esm/createReactComponent.mjs:
1975
2921
  @tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs:
2922
+ @tabler/icons-react/dist/esm/icons/IconArrowsMaximize.mjs:
2923
+ @tabler/icons-react/dist/esm/icons/IconArrowsMinimize.mjs:
1976
2924
  @tabler/icons-react/dist/esm/icons/IconCheck.mjs:
2925
+ @tabler/icons-react/dist/esm/icons/IconChevronLeft.mjs:
2926
+ @tabler/icons-react/dist/esm/icons/IconChevronRight.mjs:
1977
2927
  @tabler/icons-react/dist/esm/icons/IconCopy.mjs:
1978
2928
  @tabler/icons-react/dist/esm/icons/IconDownload.mjs:
1979
2929
  @tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs: