@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
package/dist/index.cjs CHANGED
@@ -122,7 +122,9 @@ var init_colors = __esm({
122
122
  "red-200": "#FECACA",
123
123
  "red-400": "#F7776C",
124
124
  "red-500": "#EF4444",
125
- "red-600": "#DC2626"
125
+ "red-600": "#DC2626",
126
+ // Deck
127
+ "deck-canvas": "#faf8f5"
126
128
  };
127
129
  }
128
130
  });
@@ -16587,6 +16589,7 @@ __export(src_exports, {
16587
16589
  BUTTON_INTENT: () => BUTTON_INTENT,
16588
16590
  BUTTON_SIZE: () => BUTTON_SIZE,
16589
16591
  BUTTON_VARIANT: () => BUTTON_VARIANT,
16592
+ Badge: () => Badge,
16590
16593
  Block: () => Block,
16591
16594
  BlockContext: () => BlockContext,
16592
16595
  BlockServices: () => BlockServices,
@@ -16595,8 +16598,11 @@ __export(src_exports, {
16595
16598
  ChartArtifact: () => ChartArtifact,
16596
16599
  ChatContext: () => ChatContext,
16597
16600
  ChatMessage: () => ChatMessage,
16601
+ CopyButton: () => CopyButton,
16598
16602
  DEFAULT_CHART_ARTIFACT_LABELS: () => DEFAULT_CHART_ARTIFACT_LABELS,
16603
+ DEFAULT_DECK_ARTIFACT_LABELS: () => DEFAULT_DECK_ARTIFACT_LABELS,
16599
16604
  DEFAULT_TABLE_ARTIFACT_LABELS: () => DEFAULT_TABLE_ARTIFACT_LABELS,
16605
+ DeckArtifact: () => DeckArtifact,
16600
16606
  ICON_POSITION: () => ICON_POSITION,
16601
16607
  Icon: () => Icon,
16602
16608
  IconButton: () => IconButton,
@@ -16606,6 +16612,8 @@ __export(src_exports, {
16606
16612
  Lottie: () => Lottie,
16607
16613
  MESSAGE_ROLE: () => MESSAGE_ROLE,
16608
16614
  MouseGrid: () => MouseGrid,
16615
+ NotificationDraftBlock: () => NotificationDraftBlock,
16616
+ NotificationDraftBlockService: () => NotificationDraftBlockService,
16609
16617
  PromptInput: () => PromptInput,
16610
16618
  PromptInputFooter: () => PromptInputFooter,
16611
16619
  PromptInputSubmit: () => PromptInputSubmit,
@@ -16622,11 +16630,15 @@ __export(src_exports, {
16622
16630
  colors: () => colors,
16623
16631
  convertTableToCSV: () => convertTableToCSV,
16624
16632
  copyMessageText: () => copyMessageText,
16633
+ deckBlockTypes: () => deckBlockTypes,
16634
+ deckSlideKinds: () => deckSlideKinds,
16625
16635
  escapeCsvField: () => escapeCsvField,
16626
16636
  fontFamilies: () => fontFamilies,
16627
16637
  isSafeDownloadUrl: () => isSafeDownloadUrl,
16628
16638
  markdownToPlainText: () => markdownToPlainText,
16629
16639
  mergeRefs: () => mergeRefs,
16640
+ notificationChannels: () => notificationChannels,
16641
+ notificationEmailTypes: () => notificationEmailTypes,
16630
16642
  parseMarkdownTable: () => parseMarkdownTable,
16631
16643
  typographyMixin: () => typographyMixin,
16632
16644
  typographyStyles: () => typographyStyles,
@@ -16948,13 +16960,15 @@ function typographyMixin(type) {
16948
16960
  // src/components/blocks/types.ts
16949
16961
  var blockTypes = {
16950
16962
  TEXT: "TEXT",
16951
- ARTIFACT_REF: "ARTIFACT_REF"
16963
+ ARTIFACT_REF: "ARTIFACT_REF",
16964
+ NOTIFICATION_DRAFT: "NOTIFICATION_DRAFT"
16952
16965
  };
16953
16966
 
16954
16967
  // src/components/artifacts/artifact-base.ts
16955
16968
  var artifactTypes = {
16956
16969
  TABLE: "TABLE",
16957
- CHART: "CHART"
16970
+ CHART: "CHART",
16971
+ DECK: "DECK"
16958
16972
  };
16959
16973
 
16960
16974
  // src/components/artifacts/chart-artifact/types.ts
@@ -16979,6 +16993,34 @@ var DEFAULT_TABLE_ARTIFACT_LABELS = {
16979
16993
  empty: "No rows to display."
16980
16994
  };
16981
16995
 
16996
+ // src/components/artifacts/deck-artifact/types.ts
16997
+ var deckBlockTypes = {
16998
+ TEXT: "TEXT",
16999
+ CHART: "CHART",
17000
+ TABLE: "TABLE"
17001
+ };
17002
+ var deckSlideKinds = {
17003
+ TITLE: "TITLE",
17004
+ AGENDA: "AGENDA",
17005
+ SECTION: "SECTION",
17006
+ CONTENT: "CONTENT",
17007
+ CLOSING: "CLOSING"
17008
+ };
17009
+ var DEFAULT_DECK_ARTIFACT_LABELS = {
17010
+ previous: "Previous slide",
17011
+ next: "Next slide",
17012
+ position: "Slide {current} of {total}",
17013
+ download: "Download",
17014
+ unavailable: "Deck content is unavailable.",
17015
+ enterFullscreen: "Fullscreen",
17016
+ exitFullscreen: "Exit fullscreen",
17017
+ thankYou: "Thank you",
17018
+ questions: "Questions?",
17019
+ agenda: "Agenda",
17020
+ chart: DEFAULT_CHART_ARTIFACT_LABELS,
17021
+ table: DEFAULT_TABLE_ARTIFACT_LABELS
17022
+ };
17023
+
16982
17024
  // src/components/artifacts/chart-artifact/chart-artifact.tsx
16983
17025
  var import_react13 = require("react");
16984
17026
 
@@ -17071,37 +17113,61 @@ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
17071
17113
  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" }]];
17072
17114
  var IconAlertCircle = createReactComponent("outline", "alert-circle", "AlertCircle", __iconNode);
17073
17115
 
17116
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconArrowsMaximize.mjs
17117
+ 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" }]];
17118
+ var IconArrowsMaximize = createReactComponent("outline", "arrows-maximize", "ArrowsMaximize", __iconNode2);
17119
+
17120
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconArrowsMinimize.mjs
17121
+ 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" }]];
17122
+ var IconArrowsMinimize = createReactComponent("outline", "arrows-minimize", "ArrowsMinimize", __iconNode3);
17123
+
17074
17124
  // node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
17075
- var __iconNode2 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
17076
- var IconCheck = createReactComponent("outline", "check", "Check", __iconNode2);
17125
+ var __iconNode4 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
17126
+ var IconCheck = createReactComponent("outline", "check", "Check", __iconNode4);
17127
+
17128
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconChevronDown.mjs
17129
+ var __iconNode5 = [["path", { "d": "M6 9l6 6l6 -6", "key": "svg-0" }]];
17130
+ var IconChevronDown = createReactComponent("outline", "chevron-down", "ChevronDown", __iconNode5);
17131
+
17132
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconChevronLeft.mjs
17133
+ var __iconNode6 = [["path", { "d": "M15 6l-6 6l6 6", "key": "svg-0" }]];
17134
+ var IconChevronLeft = createReactComponent("outline", "chevron-left", "ChevronLeft", __iconNode6);
17135
+
17136
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconChevronRight.mjs
17137
+ var __iconNode7 = [["path", { "d": "M9 6l6 6l-6 6", "key": "svg-0" }]];
17138
+ var IconChevronRight = createReactComponent("outline", "chevron-right", "ChevronRight", __iconNode7);
17077
17139
 
17078
17140
  // node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
17079
- 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" }]];
17080
- var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode3);
17141
+ var __iconNode8 = [["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" }]];
17142
+ var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode8);
17081
17143
 
17082
17144
  // node_modules/@tabler/icons-react/dist/esm/icons/IconDownload.mjs
17083
- 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" }]];
17084
- var IconDownload = createReactComponent("outline", "download", "Download", __iconNode4);
17145
+ var __iconNode9 = [["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" }]];
17146
+ var IconDownload = createReactComponent("outline", "download", "Download", __iconNode9);
17085
17147
 
17086
17148
  // node_modules/@tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs
17087
- 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" }]];
17088
- var IconFileSpreadsheet = createReactComponent("outline", "file-spreadsheet", "FileSpreadsheet", __iconNode5);
17149
+ var __iconNode10 = [["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" }]];
17150
+ var IconFileSpreadsheet = createReactComponent("outline", "file-spreadsheet", "FileSpreadsheet", __iconNode10);
17089
17151
 
17090
17152
  // node_modules/@tabler/icons-react/dist/esm/icons/IconLoader2.mjs
17091
- var __iconNode6 = [["path", { "d": "M12 3a9 9 0 1 0 9 9", "key": "svg-0" }]];
17092
- var IconLoader2 = createReactComponent("outline", "loader-2", "Loader2", __iconNode6);
17153
+ var __iconNode11 = [["path", { "d": "M12 3a9 9 0 1 0 9 9", "key": "svg-0" }]];
17154
+ var IconLoader2 = createReactComponent("outline", "loader-2", "Loader2", __iconNode11);
17093
17155
 
17094
17156
  // node_modules/@tabler/icons-react/dist/esm/icons/IconPhoto.mjs
17095
- 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" }]];
17096
- var IconPhoto = createReactComponent("outline", "photo", "Photo", __iconNode7);
17157
+ var __iconNode12 = [["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" }]];
17158
+ var IconPhoto = createReactComponent("outline", "photo", "Photo", __iconNode12);
17097
17159
 
17098
17160
  // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
17099
- 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" }]];
17100
- var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode8);
17161
+ var __iconNode13 = [["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" }]];
17162
+ var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode13);
17101
17163
 
17102
17164
  // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
17103
- 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" }]];
17104
- var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode9);
17165
+ var __iconNode14 = [["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" }]];
17166
+ var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode14);
17167
+
17168
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconFlask2Filled.mjs
17169
+ var __iconNode15 = [["path", { "d": "M15 2a1 1 0 0 1 0 2v5.674l.062 .03a7 7 0 0 1 3.85 5.174l.037 .262a7 7 0 0 1 -3.078 6.693a1 1 0 0 1 -.553 .167h-6.635a1 1 0 0 1 -.552 -.166a7 7 0 0 1 .807 -12.134l.062 -.028v-5.672a1 1 0 1 1 0 -2h6zm-2 2h-2v6.34a1 1 0 0 1 -.551 .894l-.116 .049a5 5 0 0 0 -2.92 2.717h9.172a5 5 0 0 0 -2.918 -2.715a1 1 0 0 1 -.667 -.943v-6.342z", "key": "svg-0" }]];
17170
+ var IconFlask2Filled = createReactComponent("filled", "flask-2-filled", "Flask2Filled", __iconNode15);
17105
17171
 
17106
17172
  // src/components/artifacts/artifact-copy-as-image-button/artifact-copy-as-image-button.tsx
17107
17173
  var import_react6 = require("react");
@@ -18366,8 +18432,13 @@ var ChartArtifactService = {
18366
18432
  toClipboardText: chartArtifactToClipboardText
18367
18433
  };
18368
18434
 
18369
- // src/components/artifacts/table-artifact/table-artifact.tsx
18370
- var import_react15 = require("react");
18435
+ // src/components/artifacts/deck-artifact/deck-artifact.tsx
18436
+ var import_react17 = require("react");
18437
+ var import_react_dom = require("react-dom");
18438
+ init_capture_exclude_attribute();
18439
+
18440
+ // src/components/artifacts/deck-artifact/deck-artifact-content.tsx
18441
+ var import_react16 = require("react");
18371
18442
 
18372
18443
  // src/components/ui/table.tsx
18373
18444
  var React3 = __toESM(require("react"), 1);
@@ -18446,6 +18517,36 @@ function useScrollShadow() {
18446
18517
  return { targetRef, isScrolled };
18447
18518
  }
18448
18519
 
18520
+ // src/components/table/data-table.tsx
18521
+ var import_jsx_runtime21 = require("react/jsx-runtime");
18522
+ var DATA_TABLE_HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
18523
+ var DATA_TABLE_CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
18524
+ var DATA_TABLE_ROW_CLASS = "border-b-brown-30 bg-background/70 hover:bg-secondary";
18525
+ var DATA_TABLE_SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
18526
+ function DataTable({ header, children, maxBodyHeight, className }) {
18527
+ const { targetRef, isScrolled } = useScrollShadow();
18528
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
18529
+ "div",
18530
+ {
18531
+ ref: targetRef,
18532
+ className: cn("overscroll-none", className),
18533
+ style: maxBodyHeight !== void 0 ? { maxHeight: maxBodyHeight, overflowY: "auto" } : void 0,
18534
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Table, { containerClassName: "overflow-visible", children: [
18535
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
18536
+ TableHeader,
18537
+ {
18538
+ "data-scrolled": isScrolled ? "true" : void 0,
18539
+ className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
18540
+ style: isScrolled ? { boxShadow: DATA_TABLE_SCROLL_SHADOW } : void 0,
18541
+ children: header
18542
+ }
18543
+ ),
18544
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableBody, { children })
18545
+ ] })
18546
+ }
18547
+ );
18548
+ }
18549
+
18449
18550
  // src/components/artifacts/table-artifact/table-artifact-content.constants.ts
18450
18551
  var TABLE_STATUS = {
18451
18552
  LOADING: "loading",
@@ -18458,14 +18559,10 @@ var TABLE_STATUS = {
18458
18559
  function formatCell(row, column) {
18459
18560
  return row[column.key] ?? "";
18460
18561
  }
18461
- var HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
18462
- var CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
18463
- var ROW_CLASSES = "border-b-brown-30 bg-background/70 hover:bg-secondary";
18464
- var DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;
18465
- var SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
18562
+ var DATA_ROW_CLASSES = `${DATA_TABLE_ROW_CLASS} animate-in fade-in duration-300`;
18466
18563
 
18467
18564
  // src/components/artifacts/table-artifact/table-artifact-content.tsx
18468
- var import_jsx_runtime21 = require("react/jsx-runtime");
18565
+ var import_jsx_runtime22 = require("react/jsx-runtime");
18469
18566
  function TableArtifactContent({
18470
18567
  columns,
18471
18568
  data: data2,
@@ -18475,48 +18572,367 @@ function TableArtifactContent({
18475
18572
  labels
18476
18573
  }) {
18477
18574
  if (data2.status === TABLE_STATUS.ERROR) {
18478
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusMessage, { $tone: "error", children: labels.loadError });
18575
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "error", children: labels.loadError });
18479
18576
  }
18480
18577
  if (data2.status === TABLE_STATUS.UNAVAILABLE) {
18481
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
18578
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
18482
18579
  }
18483
18580
  if (data2.status === TABLE_STATUS.LOADING) {
18484
18581
  if (typeof knownRowCount === "number" && knownRowCount > 0) {
18485
18582
  const shimmerCount = Math.min(knownRowCount, maxShimmerRows);
18486
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
18583
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
18487
18584
  }
18488
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusMessage, { $tone: "info", children: labels.loading });
18585
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "info", children: labels.loading });
18489
18586
  }
18490
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ArtifactTable, { columns, maxBodyHeight, children: data2.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data2.rows) });
18587
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTable, { columns, maxBodyHeight, children: data2.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data2.rows) });
18491
18588
  }
18492
18589
  function ArtifactTable({ columns, maxBodyHeight, children }) {
18493
- const { targetRef, isScrolled } = useScrollShadow();
18494
- 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: [
18495
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
18496
- TableHeader,
18590
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
18591
+ DataTable,
18592
+ {
18593
+ maxBodyHeight,
18594
+ 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)) }),
18595
+ children
18596
+ }
18597
+ );
18598
+ }
18599
+ function renderShimmerRows(columns, count) {
18600
+ return Array.from({ length: count }).map((_, index2) => /* @__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-${index2}`));
18601
+ }
18602
+ function renderDataRows(columns, rows) {
18603
+ return rows.map((row, index2) => /* @__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)) }, index2));
18604
+ }
18605
+ function renderEmptyRow(colSpan, emptyMessage) {
18606
+ 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 }) });
18607
+ }
18608
+
18609
+ // src/components/artifacts/deck-artifact/deck-markdown.tsx
18610
+ var import_react_markdown = __toESM(require("react-markdown"), 1);
18611
+ var import_remark_breaks = __toESM(require("remark-breaks"), 1);
18612
+ var import_remark_gfm = __toESM(require("remark-gfm"), 1);
18613
+ var import_jsx_runtime23 = require("react/jsx-runtime");
18614
+ function sanitize(text2) {
18615
+ return text2.split("\n").filter((line) => {
18616
+ const t = line.trim();
18617
+ return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
18618
+ }).join("\n");
18619
+ }
18620
+ var MARKDOWN_COMPONENTS = {
18621
+ h1: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: "text-[30px] font-semibold leading-tight text-foreground mb-3", ...props }),
18622
+ h2: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "text-[26px] font-semibold leading-tight text-foreground mb-2", ...props }),
18623
+ h3: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
18624
+ h4: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h4", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
18625
+ h5: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h5", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
18626
+ h6: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h6", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
18627
+ p: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[22px] leading-relaxed text-foreground my-2", ...props }),
18628
+ 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 }),
18629
+ 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 }),
18630
+ // react-markdown injects list metadata (`ordered` / `index` / `checked`) that must not leak to the DOM.
18631
+ li: ({ node: _node, ordered: _ordered, index: _index, checked: _checked, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("li", { className: "my-1", ...props }),
18632
+ strong: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("strong", { className: "font-semibold", ...props }),
18633
+ em: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("em", { className: "italic", ...props }),
18634
+ // Gate `<img src>` against an http(s) allowlist. react-markdown v8 percent-encodes the URL but
18635
+ // does NOT protocol-filter image src (unlike link href), so an LLM-authored
18636
+ // `![](javascript:…)` / `![](data:…)` or a tracking-pixel `![](http://…)` would otherwise render
18637
+ // with the raw URL. Unsafe src → render nothing.
18638
+ img: ({ node: _node, src, ...props }) => typeof src === "string" && isSafeDownloadUrl(src) ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src, className: "max-w-full", ...props }) : null,
18639
+ a: ({ node: _node, ...props }) => (
18640
+ // `rel` is forced AFTER `{...props}` so it can't be overridden — if a consumer ever adds
18641
+ // `linkTarget="_blank"`, LLM-authored links still can't reach `window.opener`.
18642
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("a", { className: "underline underline-offset-2", ...props, rel: "noopener noreferrer" })
18643
+ ),
18644
+ // react-markdown passes `inline` to distinguish inline code from fenced blocks — strip it from the DOM.
18645
+ 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 }),
18646
+ 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 }),
18647
+ hr: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("hr", { className: "my-4 border-brown-alpha-12", ...props }),
18648
+ 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 }) }),
18649
+ // react-markdown passes `isHeader` to cell renderers — strip it so it never reaches the DOM.
18650
+ 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 }),
18651
+ 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 })
18652
+ };
18653
+ function DeckMarkdown({ markdown }) {
18654
+ 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) });
18655
+ }
18656
+
18657
+ // src/components/artifacts/deck-artifact/slide-renderers.tsx
18658
+ var import_react15 = require("react");
18659
+ var import_jsx_runtime24 = require("react/jsx-runtime");
18660
+ function safeLogoUrl(meta) {
18661
+ return meta?.logoUrl && isSafeDownloadUrl(meta.logoUrl) ? meta.logoUrl : null;
18662
+ }
18663
+ var DESIGN_W = 1280;
18664
+ var DESIGN_H = 720;
18665
+ var EYEBROW_H = 84;
18666
+ var CANVAS_LOGO_MAX_H = 48;
18667
+ var ACCENT_FONT = { fontFamily: `"${fontFamilies.CRIMSON_PRO}", serif`, fontStyle: "italic" };
18668
+ function SlideFrame({ meta, children, accent = false, bare = false }) {
18669
+ const frameRef = (0, import_react15.useRef)(null);
18670
+ const [scale2, setScale] = (0, import_react15.useState)(null);
18671
+ (0, import_react15.useLayoutEffect)(() => {
18672
+ const el = frameRef.current;
18673
+ if (!el) return;
18674
+ const apply = (width2) => {
18675
+ if (width2 > 0) setScale(width2 / DESIGN_W);
18676
+ };
18677
+ apply(el.clientWidth);
18678
+ const ro = new ResizeObserver((entries) => apply(entries[0]?.contentRect.width ?? 0));
18679
+ ro.observe(el);
18680
+ return () => ro.disconnect();
18681
+ }, []);
18682
+ const bg = accent ? "bg-indigo-600" : "bg-deck-canvas";
18683
+ const eyebrowColor = accent ? "text-white/70" : "text-brown-60";
18684
+ const borderColor = accent ? "border-white/20" : "border-brown-alpha-12";
18685
+ const logoSrc = safeLogoUrl(meta);
18686
+ 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)(
18687
+ "div",
18688
+ {
18689
+ className: "absolute left-0 top-0 origin-top-left",
18690
+ style: {
18691
+ width: DESIGN_W,
18692
+ height: DESIGN_H,
18693
+ transform: `scale(${scale2 ?? 0})`,
18694
+ visibility: scale2 === null ? "hidden" : "visible"
18695
+ },
18696
+ children: [
18697
+ !bare ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
18698
+ "div",
18699
+ {
18700
+ className: `absolute inset-x-0 top-0 flex items-center justify-between border-b px-16 ${borderColor}`,
18701
+ style: { height: EYEBROW_H },
18702
+ children: [
18703
+ 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", {}),
18704
+ logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: logoSrc, alt: "", className: "object-contain", style: { maxHeight: CANVAS_LOGO_MAX_H } }) : null
18705
+ ]
18706
+ }
18707
+ ) : null,
18708
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute inset-x-0 bottom-0 overflow-hidden", style: { top: bare ? 0 : EYEBROW_H }, children })
18709
+ ]
18710
+ }
18711
+ ) });
18712
+ }
18713
+ function TitleSlide({ slide, meta }) {
18714
+ const logoSrc = safeLogoUrl(meta);
18715
+ 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: [
18716
+ logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
18717
+ "img",
18497
18718
  {
18498
- "data-scrolled": isScrolled ? "true" : void 0,
18499
- className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
18500
- style: isScrolled ? { boxShadow: SCROLL_SHADOW } : void 0,
18501
- 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)) })
18719
+ src: logoSrc,
18720
+ alt: "",
18721
+ className: "mb-16 object-contain object-left",
18722
+ style: { maxHeight: 56, maxWidth: 380 }
18723
+ }
18724
+ ) : null,
18725
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
18726
+ "h1",
18727
+ {
18728
+ className: "font-bold tracking-tight text-brown-100",
18729
+ style: { fontSize: 92, lineHeight: 1.04, maxWidth: 1060 },
18730
+ children: slide.title
18502
18731
  }
18503
18732
  ),
18504
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableBody, { children })
18733
+ slide.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-7 text-brown-70", style: { ...ACCENT_FONT, fontSize: 34 }, children: slide.subtitle }) : null,
18734
+ 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,
18735
+ meta?.date ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-10 text-brown-70", style: { ...ACCENT_FONT, fontSize: 30 }, children: meta.date }) : null
18505
18736
  ] }) });
18506
18737
  }
18507
- function renderShimmerRows(columns, count) {
18508
- return Array.from({ length: count }).map((_, index2) => /* @__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-${index2}`));
18738
+ function AgendaSlide({ slide, meta, labels }) {
18739
+ const items = slide.items ?? [];
18740
+ 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: [
18741
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "mb-10 font-bold text-brown-90", style: { fontSize: 40 }, children: slide.title || labels.agenda }),
18742
+ /* @__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: [
18743
+ /* @__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") }),
18744
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-brown-90", style: { fontSize: 28 }, children: item })
18745
+ ] }, i)) })
18746
+ ] }) });
18509
18747
  }
18510
- function renderDataRows(columns, rows) {
18511
- return rows.map((row, index2) => /* @__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)) }, index2));
18748
+ function SectionSlide({ slide, meta }) {
18749
+ 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: [
18750
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "font-bold text-white", style: { fontSize: 72, lineHeight: 1.05, maxWidth: 940 }, children: slide.title }),
18751
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-2 bg-white/50", style: { width: 96, height: 5 } })
18752
+ ] }) });
18512
18753
  }
18513
- function renderEmptyRow(colSpan, emptyMessage) {
18514
- 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 }) });
18754
+ function ClosingSlide({ meta, labels }) {
18755
+ 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: [
18756
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h1", { className: "font-bold text-brown-100", style: { fontSize: 72 }, children: labels.thankYou }),
18757
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-indigo-600", style: { ...ACCENT_FONT, fontSize: 36 }, children: labels.questions })
18758
+ ] }) });
18515
18759
  }
18516
18760
 
18517
- // src/components/artifacts/table-artifact/use-table-artifact-data.ts
18518
- function useTableArtifactData(presignedUrl, columns) {
18519
- return useRowsArtifactData(presignedUrl, columns, parseCsv);
18761
+ // src/components/artifacts/deck-artifact/deck-artifact-content.tsx
18762
+ var import_jsx_runtime25 = require("react/jsx-runtime");
18763
+ var TABLE_BLOCK_MAX_SHIMMER_ROWS = 10;
18764
+ var TABLE_CHROME_RESERVE = 56;
18765
+ var VISUAL_FALLBACK_HEIGHT = 360;
18766
+ function DeckArtifactContent({
18767
+ slides,
18768
+ labels,
18769
+ onNavigate,
18770
+ meta,
18771
+ onDark = false,
18772
+ currentSlide,
18773
+ onSlideChange
18774
+ }) {
18775
+ const navBtnClass = onDark ? "[&_svg]:!text-white hover:!bg-white/20 disabled:opacity-40" : void 0;
18776
+ const navBtnSize = onDark ? "medium" : "small";
18777
+ const isControlled = currentSlide !== void 0;
18778
+ const [internalIndex, setInternalIndex] = (0, import_react16.useState)(0);
18779
+ const index2 = isControlled ? currentSlide : internalIndex;
18780
+ const current = Math.min(index2, slides.length - 1);
18781
+ const slide = slides[current];
18782
+ const goTo = (0, import_react16.useCallback)(
18783
+ (next) => {
18784
+ const clamped = Math.max(0, Math.min(next, slides.length - 1));
18785
+ if (isControlled) onSlideChange?.(clamped);
18786
+ else setInternalIndex(clamped);
18787
+ onNavigate?.(clamped);
18788
+ },
18789
+ [slides.length, onNavigate, isControlled, onSlideChange]
18790
+ );
18791
+ const position2 = labels.position.replace("{current}", String(current + 1)).replace("{total}", String(slides.length));
18792
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
18793
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideDispatch, { slide, labels, meta }),
18794
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
18795
+ "div",
18796
+ {
18797
+ className: `flex items-center justify-between border-t pt-2 ${onDark ? "border-white/20" : "border-brown-alpha-12"}`,
18798
+ children: [
18799
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
18800
+ IconButton,
18801
+ {
18802
+ icon: IconChevronLeft,
18803
+ size: navBtnSize,
18804
+ className: navBtnClass,
18805
+ "aria-label": labels.previous,
18806
+ disabled: current === 0,
18807
+ onClick: () => goTo(current - 1)
18808
+ }
18809
+ ),
18810
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: `text-xs font-medium ${onDark ? "text-white/70" : "text-brown-70"}`, children: position2 }),
18811
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
18812
+ IconButton,
18813
+ {
18814
+ icon: IconChevronRight,
18815
+ size: navBtnSize,
18816
+ className: navBtnClass,
18817
+ "aria-label": labels.next,
18818
+ disabled: current === slides.length - 1,
18819
+ onClick: () => goTo(current + 1)
18820
+ }
18821
+ )
18822
+ ]
18823
+ }
18824
+ )
18825
+ ] });
18826
+ }
18827
+ function SlideDispatch({ slide, labels, meta }) {
18828
+ const kind = slide.kind ?? deckSlideKinds.CONTENT;
18829
+ switch (kind) {
18830
+ case deckSlideKinds.TITLE:
18831
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TitleSlide, { slide, meta });
18832
+ case deckSlideKinds.AGENDA:
18833
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AgendaSlide, { slide, meta, labels });
18834
+ case deckSlideKinds.SECTION:
18835
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SectionSlide, { slide, meta });
18836
+ case deckSlideKinds.CLOSING:
18837
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ClosingSlide, { meta, labels });
18838
+ case deckSlideKinds.CONTENT:
18839
+ default:
18840
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ContentSlide, { slide, meta, labels });
18841
+ }
18842
+ }
18843
+ function isVisualBlock(block) {
18844
+ return block.type === deckBlockTypes.CHART || block.type === deckBlockTypes.TABLE;
18845
+ }
18846
+ function ContentSlide({ slide, meta, labels }) {
18847
+ const content2 = slide.content ?? [];
18848
+ const visuals = content2.filter(isVisualBlock);
18849
+ const texts = content2.filter(
18850
+ (b) => b.type === deckBlockTypes.TEXT
18851
+ );
18852
+ if (visuals.length === 1 && texts.length > 0) {
18853
+ 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: [
18854
+ /* @__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: [
18855
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "mb-5 font-bold leading-tight text-foreground", style: { fontSize: 34 }, children: slide.title }),
18856
+ texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
18857
+ ] }) }),
18858
+ /* @__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 }) })
18859
+ ] }) });
18860
+ }
18861
+ if (visuals.length > 0) {
18862
+ 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: [
18863
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "shrink-0 font-bold leading-tight text-foreground", style: { fontSize: 32 }, children: slide.title }),
18864
+ content2.map(
18865
+ (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)
18866
+ )
18867
+ ] }) });
18868
+ }
18869
+ 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: [
18870
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "mb-6 font-bold leading-tight text-foreground", style: { fontSize: 38 }, children: slide.title }),
18871
+ texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
18872
+ ] }) }) });
18873
+ }
18874
+ function AutoFit({ children }) {
18875
+ const boxRef = (0, import_react16.useRef)(null);
18876
+ const contentRef = (0, import_react16.useRef)(null);
18877
+ const [fit, setFit] = (0, import_react16.useState)({ scale: 1, height: 0 });
18878
+ (0, import_react16.useLayoutEffect)(() => {
18879
+ const boxEl = boxRef.current;
18880
+ const contentEl = contentRef.current;
18881
+ if (!boxEl || !contentEl) return;
18882
+ const measure = () => {
18883
+ const avail = boxEl.clientHeight;
18884
+ const natural = contentEl.offsetHeight;
18885
+ const scale2 = avail > 0 && natural > avail ? avail / natural : 1;
18886
+ setFit({ scale: scale2, height: natural * scale2 });
18887
+ };
18888
+ measure();
18889
+ const ro = new ResizeObserver(measure);
18890
+ ro.observe(boxEl);
18891
+ ro.observe(contentEl);
18892
+ return () => ro.disconnect();
18893
+ }, []);
18894
+ const scaled = fit.scale < 1;
18895
+ 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)(
18896
+ "div",
18897
+ {
18898
+ ref: contentRef,
18899
+ className: "w-full origin-top-left",
18900
+ style: scaled ? { transform: `scale(${fit.scale})` } : void 0,
18901
+ children
18902
+ }
18903
+ ) }) });
18904
+ }
18905
+ function FillVisual({ block, labels }) {
18906
+ const ref = (0, import_react16.useRef)(null);
18907
+ const [height2, setHeight] = (0, import_react16.useState)(VISUAL_FALLBACK_HEIGHT);
18908
+ (0, import_react16.useLayoutEffect)(() => {
18909
+ const el = ref.current;
18910
+ if (!el) return;
18911
+ const apply = (h) => {
18912
+ if (h > 0) setHeight(h);
18913
+ };
18914
+ apply(el.clientHeight);
18915
+ const ro = new ResizeObserver((entries) => apply(entries[0]?.contentRect.height ?? 0));
18916
+ ro.observe(el);
18917
+ return () => ro.disconnect();
18918
+ }, []);
18919
+ const chartLabels = labels.chart ?? DEFAULT_CHART_ARTIFACT_LABELS;
18920
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref, className: "h-full min-h-0 w-full overflow-hidden", children: block.type === deckBlockTypes.CHART ? (
18921
+ // ChartArtifactContent assumes a non-empty rowset (the standalone ChartArtifact guards
18922
+ // `rows.length > 0` upstream); mirror that guard here so an empty inline chart shows the
18923
+ // localized empty status instead of a blank chart area.
18924
+ 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: height2 }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChartArtifactContent, { config: block.config, rows: block.rows, labels: chartLabels }) })
18925
+ ) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
18926
+ TableArtifactContent,
18927
+ {
18928
+ columns: block.config.columns,
18929
+ data: { status: "ready", rows: block.rows, error: null },
18930
+ knownRowCount: block.config.stats?.rowCount ?? block.rows.length,
18931
+ maxShimmerRows: TABLE_BLOCK_MAX_SHIMMER_ROWS,
18932
+ maxBodyHeight: Math.max(0, height2 - TABLE_CHROME_RESERVE),
18933
+ labels: labels.table ?? DEFAULT_TABLE_ARTIFACT_LABELS
18934
+ }
18935
+ ) });
18520
18936
  }
18521
18937
 
18522
18938
  // src/components/artifacts/table-artifact/validate.ts
@@ -18535,19 +18951,265 @@ function isValidTableColumn(column) {
18535
18951
  return true;
18536
18952
  }
18537
18953
 
18538
- // src/components/artifacts/table-artifact/table-artifact.tsx
18539
- var import_jsx_runtime22 = require("react/jsx-runtime");
18954
+ // src/components/artifacts/deck-artifact/validate.ts
18955
+ function isValidDeckConfig(config) {
18956
+ if (!config || typeof config !== "object") return false;
18957
+ const candidate = config;
18958
+ if (!Array.isArray(candidate.slides)) return false;
18959
+ if (candidate.slides.length === 0) return false;
18960
+ return candidate.slides.every(isValidDeckSlide);
18961
+ }
18962
+ function isValidDeckSlide(slide) {
18963
+ if (!slide || typeof slide !== "object") return false;
18964
+ const candidate = slide;
18965
+ if (typeof candidate.title !== "string") return false;
18966
+ const kind = typeof candidate.kind === "string" ? candidate.kind : deckSlideKinds.CONTENT;
18967
+ if (kind === deckSlideKinds.CONTENT && !Array.isArray(candidate.content)) return false;
18968
+ const content2 = Array.isArray(candidate.content) ? candidate.content : [];
18969
+ if (candidate.items != null) {
18970
+ if (!Array.isArray(candidate.items)) return false;
18971
+ if (!candidate.items.every((item) => typeof item === "string")) return false;
18972
+ }
18973
+ return content2.every(isValidDeckBlock);
18974
+ }
18975
+ function isValidDeckBlock(block) {
18976
+ if (!block || typeof block !== "object") return false;
18977
+ const candidate = block;
18978
+ switch (candidate.type) {
18979
+ case deckBlockTypes.TEXT:
18980
+ return typeof candidate.markdown === "string";
18981
+ case deckBlockTypes.CHART:
18982
+ return isValidChartConfig(candidate.config) && Array.isArray(candidate.rows);
18983
+ case deckBlockTypes.TABLE:
18984
+ return isValidTableConfig(candidate.config) && Array.isArray(candidate.rows);
18985
+ default:
18986
+ return false;
18987
+ }
18988
+ }
18989
+
18990
+ // src/components/artifacts/deck-artifact/deck-artifact.tsx
18991
+ var import_jsx_runtime26 = require("react/jsx-runtime");
18540
18992
  var TITLE_CLASSES2 = "text-sm font-semibold text-foreground";
18993
+ function DeckArtifact({ artifact, labels, callbacks }) {
18994
+ const validConfig = isValidDeckConfig(artifact.config);
18995
+ const [isFullscreen, setIsFullscreen] = (0, import_react17.useState)(false);
18996
+ const [currentSlide, setCurrentSlide] = (0, import_react17.useState)(0);
18997
+ (0, import_react17.useEffect)(() => {
18998
+ if (validConfig) return;
18999
+ console.warn("[clay] DeckArtifact: malformed `config` \u2014 skipping render.");
19000
+ }, [validConfig]);
19001
+ (0, import_react17.useEffect)(() => {
19002
+ if (!isFullscreen) return;
19003
+ const handleKey = (e) => {
19004
+ if (e.key === "Escape") setIsFullscreen(false);
19005
+ };
19006
+ document.addEventListener("keydown", handleKey);
19007
+ const previousOverflow = document.documentElement.style.overflow;
19008
+ document.documentElement.style.overflow = "hidden";
19009
+ return () => {
19010
+ document.removeEventListener("keydown", handleKey);
19011
+ document.documentElement.style.overflow = previousOverflow;
19012
+ };
19013
+ }, [isFullscreen]);
19014
+ const resolvedLabels = (0, import_react17.useMemo)(
19015
+ () => ({
19016
+ ...DEFAULT_DECK_ARTIFACT_LABELS,
19017
+ ...labels ?? {},
19018
+ chart: { ...DEFAULT_CHART_ARTIFACT_LABELS, ...labels?.chart ?? {} },
19019
+ table: { ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels?.table ?? {} }
19020
+ }),
19021
+ [labels]
19022
+ );
19023
+ const onNavigate = callbacks?.onNavigate;
19024
+ const handleNavigate = onNavigate ? (slideIndex) => onNavigate(artifact, slideIndex) : void 0;
19025
+ const onDownload = callbacks?.onDownload;
19026
+ const handleDownload = onDownload ? () => onDownload(artifact) : void 0;
19027
+ const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
19028
+ const showDownload = presignedUrl !== null && isSafeDownloadUrl(presignedUrl);
19029
+ const meta = artifact.config?.meta;
19030
+ const handleOpenFullscreen = () => setIsFullscreen(true);
19031
+ const handleCloseFullscreen = () => setIsFullscreen(false);
19032
+ const actions = /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactActions, { ...{ [CAPTURE_EXCLUDE_ATTRIBUTE]: "" }, children: [
19033
+ showDownload ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactDownloadButton, { href: presignedUrl ?? "", label: resolvedLabels.download, onClick: handleDownload }) : null,
19034
+ validConfig ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
19035
+ IconButton,
19036
+ {
19037
+ icon: IconArrowsMaximize,
19038
+ size: "small",
19039
+ "aria-label": resolvedLabels.enterFullscreen,
19040
+ onClick: handleOpenFullscreen
19041
+ }
19042
+ ) : null
19043
+ ] });
19044
+ if (!validConfig) {
19045
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
19046
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
19047
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
19048
+ actions
19049
+ ] }),
19050
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
19051
+ ] });
19052
+ }
19053
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
19054
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
19055
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
19056
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
19057
+ actions
19058
+ ] }),
19059
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
19060
+ DeckArtifactContent,
19061
+ {
19062
+ slides: artifact.config.slides,
19063
+ labels: resolvedLabels,
19064
+ onNavigate: handleNavigate,
19065
+ meta,
19066
+ currentSlide,
19067
+ onSlideChange: setCurrentSlide
19068
+ }
19069
+ ) })
19070
+ ] }),
19071
+ isFullscreen && (0, import_react_dom.createPortal)(
19072
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
19073
+ FullscreenOverlay,
19074
+ {
19075
+ artifact,
19076
+ resolvedLabels,
19077
+ onNavigate: handleNavigate,
19078
+ currentSlide,
19079
+ onSlideChange: setCurrentSlide,
19080
+ onClose: handleCloseFullscreen
19081
+ }
19082
+ ),
19083
+ document.body
19084
+ )
19085
+ ] });
19086
+ }
19087
+ function FullscreenOverlay({
19088
+ artifact,
19089
+ resolvedLabels,
19090
+ onNavigate,
19091
+ currentSlide,
19092
+ onSlideChange,
19093
+ onClose
19094
+ }) {
19095
+ const meta = artifact.config?.meta;
19096
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
19097
+ "div",
19098
+ {
19099
+ className: "fixed inset-0 z-[2147483647] flex items-center justify-center bg-black/80",
19100
+ role: "dialog",
19101
+ "aria-modal": "true",
19102
+ "aria-label": resolvedLabels.exitFullscreen,
19103
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "relative", style: { width: "min(94vw, calc(82vh * 16 / 9))" }, children: [
19104
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
19105
+ DeckArtifactContent,
19106
+ {
19107
+ slides: artifact.config.slides,
19108
+ labels: resolvedLabels,
19109
+ onNavigate,
19110
+ meta,
19111
+ currentSlide,
19112
+ onSlideChange,
19113
+ onDark: true
19114
+ }
19115
+ ),
19116
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
19117
+ "button",
19118
+ {
19119
+ className: "absolute -top-10 right-6 flex items-center gap-1.5 text-sm text-white/80 hover:text-white",
19120
+ "aria-label": resolvedLabels.exitFullscreen,
19121
+ onClick: onClose,
19122
+ children: [
19123
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IconArrowsMinimize, { size: 16 }),
19124
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: resolvedLabels.exitFullscreen })
19125
+ ]
19126
+ }
19127
+ )
19128
+ ] })
19129
+ }
19130
+ );
19131
+ }
19132
+
19133
+ // src/components/artifacts/deck-artifact/to-clipboard-text.ts
19134
+ function deckArtifactToClipboardText(artifact) {
19135
+ const header = artifact.title?.trim() || "Deck";
19136
+ const slides = artifact.config?.slides ?? [];
19137
+ const body = slides.map((slide, i) => slideToText(slide, i)).join("\n\n");
19138
+ return body ? `${header}
19139
+
19140
+ ${body}` : header;
19141
+ }
19142
+ function slideToText(slide, index2) {
19143
+ const kind = slide.kind ?? deckSlideKinds.CONTENT;
19144
+ const prefix = `Slide ${index2 + 1}: `;
19145
+ switch (kind) {
19146
+ case deckSlideKinds.TITLE: {
19147
+ const parts = [slide.title];
19148
+ if (slide.subtitle) parts.push(slide.subtitle);
19149
+ if (slide.description) parts.push(slide.description);
19150
+ return `${prefix}${parts.join(" \u2014 ")}`.trim();
19151
+ }
19152
+ case deckSlideKinds.AGENDA: {
19153
+ const items = (slide.items ?? []).map((item, i) => ` ${String(i + 1).padStart(2, "0")}. ${item}`).join("\n");
19154
+ return `${prefix}${slide.title || "Agenda"}${items ? `
19155
+ ${items}` : ""}`.trim();
19156
+ }
19157
+ case deckSlideKinds.SECTION:
19158
+ return `${prefix}${slide.title}`.trim();
19159
+ case deckSlideKinds.CLOSING:
19160
+ return `${prefix}Thank you`.trim();
19161
+ case deckSlideKinds.CONTENT:
19162
+ default: {
19163
+ const blocks = (slide.content ?? []).map(blockToText).filter(Boolean).join("\n\n");
19164
+ return `${prefix}${slide.title}${blocks ? `
19165
+ ${blocks}` : ""}`.trim();
19166
+ }
19167
+ }
19168
+ }
19169
+ function blockToText(block) {
19170
+ switch (block.type) {
19171
+ case deckBlockTypes.TEXT:
19172
+ return block.markdown.trim();
19173
+ case deckBlockTypes.CHART:
19174
+ return `[Chart: ${block.config.variant}]`;
19175
+ case deckBlockTypes.TABLE: {
19176
+ const columnCount = block.config.columns.length;
19177
+ const rowCount = block.rows.length;
19178
+ return `[Table: ${columnCount} column${columnCount === 1 ? "" : "s"} \xD7 ${rowCount} row${rowCount === 1 ? "" : "s"}]`;
19179
+ }
19180
+ default:
19181
+ return "";
19182
+ }
19183
+ }
19184
+
19185
+ // src/components/artifacts/artifact-services/deck-artifact-service.ts
19186
+ var DeckArtifactService = {
19187
+ type: artifactTypes.DECK,
19188
+ Component: DeckArtifact,
19189
+ toClipboardText: deckArtifactToClipboardText
19190
+ };
19191
+
19192
+ // src/components/artifacts/table-artifact/table-artifact.tsx
19193
+ var import_react18 = require("react");
19194
+
19195
+ // src/components/artifacts/table-artifact/use-table-artifact-data.ts
19196
+ function useTableArtifactData(presignedUrl, columns) {
19197
+ return useRowsArtifactData(presignedUrl, columns, parseCsv);
19198
+ }
19199
+
19200
+ // src/components/artifacts/table-artifact/table-artifact.tsx
19201
+ var import_jsx_runtime27 = require("react/jsx-runtime");
19202
+ var TITLE_CLASSES3 = "text-sm font-semibold text-foreground";
18541
19203
  var TABLE_MAX_BODY_HEIGHT = 480;
18542
19204
  var MAX_SHIMMER_ROWS = 10;
18543
19205
  function TableArtifact({ artifact, labels, callbacks }) {
18544
19206
  const validConfig = isValidTableConfig(artifact.config);
18545
19207
  const validColumns = validConfig ? artifact.config.columns : null;
18546
- (0, import_react15.useEffect)(() => {
19208
+ (0, import_react18.useEffect)(() => {
18547
19209
  if (validConfig) return;
18548
19210
  console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
18549
19211
  }, [validConfig]);
18550
- const resolvedLabels = (0, import_react15.useMemo)(
19212
+ const resolvedLabels = (0, import_react18.useMemo)(
18551
19213
  () => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels ?? {} }),
18552
19214
  [labels]
18553
19215
  );
@@ -18559,10 +19221,10 @@ function TableArtifact({ artifact, labels, callbacks }) {
18559
19221
  const onDownload = callbacks?.onDownload;
18560
19222
  const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
18561
19223
  if (!validConfig || !validColumns) {
18562
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
18563
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
18564
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", {}),
18565
- presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
19224
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
19225
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
19226
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", {}),
19227
+ presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
18566
19228
  ArtifactDownloadButton,
18567
19229
  {
18568
19230
  href: presignedUrl,
@@ -18571,17 +19233,17 @@ function TableArtifact({ artifact, labels, callbacks }) {
18571
19233
  }
18572
19234
  ) }) : null
18573
19235
  ] }),
18574
- /* @__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 }) })
19236
+ /* @__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 }) })
18575
19237
  ] });
18576
19238
  }
18577
19239
  return (
18578
19240
  // The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
18579
19241
  // Disable the outer overflow container so only one scroll context exists — this prevents
18580
19242
  // double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
18581
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
18582
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
18583
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", {}),
18584
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
19243
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
19244
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
19245
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", {}),
19246
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
18585
19247
  ArtifactDownloadButton,
18586
19248
  {
18587
19249
  href: presignedUrl ?? "",
@@ -18590,7 +19252,7 @@ function TableArtifact({ artifact, labels, callbacks }) {
18590
19252
  }
18591
19253
  ) })
18592
19254
  ] }),
18593
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
19255
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
18594
19256
  TableArtifactContent,
18595
19257
  {
18596
19258
  columns: validColumns,
@@ -18621,7 +19283,8 @@ var TableArtifactService = {
18621
19283
  // src/components/artifacts/artifact-services/index.ts
18622
19284
  var ArtifactServices = {
18623
19285
  [artifactTypes.TABLE]: TableArtifactService,
18624
- [artifactTypes.CHART]: ChartArtifactService
19286
+ [artifactTypes.CHART]: ChartArtifactService,
19287
+ [artifactTypes.DECK]: DeckArtifactService
18625
19288
  };
18626
19289
  function artifactToClipboardText(artifact) {
18627
19290
  const entry = ArtifactServices[artifact.type];
@@ -18632,13 +19295,13 @@ function artifactToClipboardText(artifact) {
18632
19295
  }
18633
19296
 
18634
19297
  // src/components/blocks/artifact-ref-block/artifact-ref-block.tsx
18635
- var import_jsx_runtime23 = require("react/jsx-runtime");
19298
+ var import_jsx_runtime28 = require("react/jsx-runtime");
18636
19299
  function ArtifactRefBlock({ block }) {
18637
19300
  const { artifact, labels, callbacks } = block.payload;
18638
19301
  const entry = ArtifactServices[artifact.type];
18639
19302
  if (!entry) return null;
18640
19303
  const Component = entry.Component;
18641
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Component, { artifact, labels, callbacks });
19304
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Component, { artifact, labels, callbacks });
18642
19305
  }
18643
19306
 
18644
19307
  // src/components/blocks/block-services/artifact-ref-block-service.ts
@@ -18653,29 +19316,102 @@ var ArtifactRefBlockService = {
18653
19316
  toClipboardText: (block) => artifactToClipboardText(block.payload.artifact)
18654
19317
  };
18655
19318
 
18656
- // src/utils/markdown-to-plain-text.ts
18657
- var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
18658
- var PLACEHOLDER_SUFFIX = "\u200B\u200B";
18659
- var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
18660
- function stripInlineMarks(text2) {
18661
- return text2.replace(/\*{3}(.+?)\*{3}/g, "$1").replace(/\*{2}(.+?)\*{2}/g, "$1").replace(/_{2}(.+?)_{2}/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1");
19319
+ // src/components/blocks/notification-draft-block/notification-draft-block.tsx
19320
+ var import_react20 = require("react");
19321
+
19322
+ // src/components/badge/badge.tsx
19323
+ var import_jsx_runtime29 = require("react/jsx-runtime");
19324
+ var BASE = "inline-flex items-center whitespace-nowrap rounded-full";
19325
+ var SIZES = {
19326
+ // `sm` is a uniform scale-down of `md` (text 10/12 of caption): padding and line-height keep
19327
+ // md's proportions (caption is 12px text on a 16px line = 1.333 ratio) so the pill shape matches.
19328
+ md: "px-2.5 py-0.5 text-geist-label-caption-medium",
19329
+ sm: "px-2 py-0.5 text-[11px]/[1.333] font-medium"
19330
+ };
19331
+ var SUBTLE = {
19332
+ neutral: "bg-brown-20 text-brown-70",
19333
+ warning: "bg-orange-50 text-orange-600",
19334
+ violet: "bg-violet-50 text-violet-600"
19335
+ };
19336
+ var OUTLINE = {
19337
+ neutral: "border border-brown-30 bg-white text-brown-100",
19338
+ warning: "border border-orange-200 bg-white text-orange-600",
19339
+ violet: "border border-violet-400 bg-white text-violet-600"
19340
+ };
19341
+ var VARIANTS = {
19342
+ subtle: SUBTLE,
19343
+ outline: OUTLINE
19344
+ };
19345
+ function Badge({
19346
+ variant = "subtle",
19347
+ tone = "neutral",
19348
+ size = "md",
19349
+ className,
19350
+ children
19351
+ }) {
19352
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cn(BASE, SIZES[size], VARIANTS[variant][tone], className), children });
18662
19353
  }
18663
- function markdownToPlainText(markdown) {
18664
- if (!markdown) return "";
18665
- const inlineCodeSnippets = [];
18666
- let result = markdown.replace(/^<!--[\s\S]*?--!?>\n?/gm, "").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
18667
- inlineCodeSnippets.push(code);
18668
- return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
18669
- }).replace(/^#{1,6}\s+/gm, "").replace(/^(?:---|\*\*\*|___)\s*$/gm, "");
18670
- result = stripInlineMarks(result).replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/^>\s?/gm, "").replace(/^\|[-:\s|]+\|\s*$/gm, "").replace(/^\|\s?/gm, "").replace(/\s?\|$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
18671
- result = result.replace(PLACEHOLDER_REGEX, (_match, index2) => inlineCodeSnippets[Number(index2)]);
18672
- return result;
19354
+
19355
+ // src/components/chat/hooks/use-copy-to-clipboard.ts
19356
+ var import_react19 = require("react");
19357
+
19358
+ // src/utils/clipboard.ts
19359
+ function copyToClipboard(text2, options) {
19360
+ navigator.clipboard.writeText(text2).then(
19361
+ () => options?.onSuccess?.(),
19362
+ (error) => options?.onFailure?.(error)
19363
+ );
18673
19364
  }
18674
19365
 
18675
- // src/components/blocks/text-block/text-block.tsx
18676
- var import_react_markdown = __toESM(require("react-markdown"), 1);
18677
- var import_remark_breaks = __toESM(require("remark-breaks"), 1);
18678
- var import_remark_gfm = __toESM(require("remark-gfm"), 1);
19366
+ // src/components/chat/hooks/use-copy-to-clipboard.ts
19367
+ var RESET_DELAY_MS = 2e3;
19368
+ function useCopyToClipboard() {
19369
+ const [isCopied, setIsCopied] = (0, import_react19.useState)(false);
19370
+ const timeoutRef = (0, import_react19.useRef)(null);
19371
+ (0, import_react19.useEffect)(() => {
19372
+ return () => {
19373
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
19374
+ };
19375
+ }, []);
19376
+ const copy = (0, import_react19.useCallback)((text2) => {
19377
+ copyToClipboard(text2, {
19378
+ onSuccess: () => {
19379
+ setIsCopied(true);
19380
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
19381
+ timeoutRef.current = setTimeout(() => {
19382
+ setIsCopied(false);
19383
+ timeoutRef.current = null;
19384
+ }, RESET_DELAY_MS);
19385
+ }
19386
+ });
19387
+ }, []);
19388
+ return { isCopied, copy };
19389
+ }
19390
+
19391
+ // src/components/copy-button/copy-button.tsx
19392
+ var import_jsx_runtime30 = require("react/jsx-runtime");
19393
+ function CopyButton({
19394
+ text: text2,
19395
+ copyLabel = "Copy",
19396
+ copiedLabel = "Copied",
19397
+ className
19398
+ }) {
19399
+ const { isCopied, copy } = useCopyToClipboard();
19400
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
19401
+ IconButton,
19402
+ {
19403
+ icon: isCopied ? IconCheck : IconCopy,
19404
+ onClick: () => copy(text2),
19405
+ "aria-label": isCopied ? copiedLabel : copyLabel,
19406
+ className
19407
+ }
19408
+ );
19409
+ }
19410
+
19411
+ // src/components/blocks/markdown/markdown.tsx
19412
+ var import_react_markdown2 = __toESM(require("react-markdown"), 1);
19413
+ var import_remark_breaks2 = __toESM(require("remark-breaks"), 1);
19414
+ var import_remark_gfm2 = __toESM(require("remark-gfm"), 1);
18679
19415
 
18680
19416
  // src/components/blocks/scrollable-table/scrollable-table-styles.ts
18681
19417
  var import_styled_components3 = __toESM(require("styled-components"), 1);
@@ -18690,13 +19426,13 @@ var TableScroll = import_styled_components3.default.div`
18690
19426
  `;
18691
19427
 
18692
19428
  // src/components/blocks/scrollable-table/scrollable-table.tsx
18693
- var import_jsx_runtime24 = require("react/jsx-runtime");
19429
+ var import_jsx_runtime31 = require("react/jsx-runtime");
18694
19430
  function ScrollableTable({ node: _node, ...props }) {
18695
- 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 }) }) });
19431
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TableContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("table", { ...props }) }) });
18696
19432
  }
18697
19433
 
18698
19434
  // src/components/blocks/text-block/sanitize.ts
18699
- function sanitize(text2) {
19435
+ function sanitize2(text2) {
18700
19436
  return text2.split("\n").filter((line) => {
18701
19437
  const t = line.trim();
18702
19438
  return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
@@ -18835,13 +19571,157 @@ var TextBlockWrapper = import_styled_components4.default.div`
18835
19571
  }
18836
19572
  `;
18837
19573
 
18838
- // src/components/blocks/text-block/text-block.tsx
18839
- var import_jsx_runtime25 = require("react/jsx-runtime");
19574
+ // src/components/blocks/markdown/markdown.tsx
19575
+ var import_jsx_runtime32 = require("react/jsx-runtime");
18840
19576
  var markdownComponents = {
18841
- table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ScrollableTable, { ...tableProps }))
19577
+ table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ScrollableTable, { ...tableProps }))
19578
+ };
19579
+ function Markdown({ children }) {
19580
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TextBlockWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_markdown2.default, { remarkPlugins: [import_remark_gfm2.default, import_remark_breaks2.default], components: markdownComponents, children: sanitize2(children) }) });
19581
+ }
19582
+
19583
+ // src/utils/markdown-to-plain-text.ts
19584
+ var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
19585
+ var PLACEHOLDER_SUFFIX = "\u200B\u200B";
19586
+ var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
19587
+ function stripInlineMarks(text2) {
19588
+ return text2.replace(/\*{3}(.+?)\*{3}/g, "$1").replace(/\*{2}(.+?)\*{2}/g, "$1").replace(/_{2}(.+?)_{2}/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1");
19589
+ }
19590
+ function markdownToPlainText(markdown) {
19591
+ if (!markdown) return "";
19592
+ const inlineCodeSnippets = [];
19593
+ let result = markdown.replace(/^<!--[\s\S]*?--!?>\n?/gm, "").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
19594
+ inlineCodeSnippets.push(code);
19595
+ return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
19596
+ }).replace(/^#{1,6}\s+/gm, "").replace(/^(?:---|\*\*\*|___)\s*$/gm, "");
19597
+ result = stripInlineMarks(result).replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/^>\s?/gm, "").replace(/^\|[-:\s|]+\|\s*$/gm, "").replace(/^\|\s?/gm, "").replace(/\s?\|$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
19598
+ result = result.replace(PLACEHOLDER_REGEX, (_match, index2) => inlineCodeSnippets[Number(index2)]);
19599
+ return result;
19600
+ }
19601
+
19602
+ // src/components/blocks/notification-draft-block/types.ts
19603
+ var notificationChannels = {
19604
+ /** Branded email — renders a From/subject header. */
19605
+ EMAIL: "email",
19606
+ /** Slack DM — renders as a chat bubble, no subject. */
19607
+ SLACK: "slack",
19608
+ /** Microsoft Teams DM — renders as a chat bubble, no subject. */
19609
+ TEAMS: "teams"
19610
+ };
19611
+ var notificationEmailTypes = {
19612
+ /** Recipient's work email. */
19613
+ WORK: "work",
19614
+ /** Recipient's personal email. */
19615
+ PERSONAL: "personal"
18842
19616
  };
19617
+
19618
+ // src/components/blocks/notification-draft-block/to-text.ts
19619
+ function notificationDraftToText(payload) {
19620
+ const { channel, subject, body } = payload;
19621
+ const text2 = markdownToPlainText(body);
19622
+ return channel === notificationChannels.EMAIL && subject ? `${subject}
19623
+
19624
+ ${text2}` : text2;
19625
+ }
19626
+
19627
+ // src/components/blocks/notification-draft-block/notification-draft-block.tsx
19628
+ var import_jsx_runtime33 = require("react/jsx-runtime");
19629
+ var CHIP_LIMIT = 3;
19630
+ var RECIPIENTS_MAX_HEIGHT = 320;
19631
+ function chipLabel(recipient) {
19632
+ return recipient.name ?? recipient.email ?? recipient.employeeId;
19633
+ }
19634
+ function channelCellText(recipient) {
19635
+ return recipient.fallback ? `${recipient.channelLabel} (fallback)` : recipient.channelLabel;
19636
+ }
19637
+ function FieldLabel({ children }) {
19638
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-geist-label-caption-medium tracking-wide text-brown-60", children });
19639
+ }
19640
+ function RecipientChips({ recipients }) {
19641
+ const shown = recipients.slice(0, CHIP_LIMIT);
19642
+ const overflow = recipients.length - shown.length;
19643
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
19644
+ shown.map((recipient) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Badge, { variant: "outline", children: chipLabel(recipient) }, recipient.employeeId)),
19645
+ overflow > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Badge, { variant: "subtle", children: `+${overflow}` })
19646
+ ] });
19647
+ }
19648
+ function RecipientsTable({ recipients }) {
19649
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
19650
+ DataTable,
19651
+ {
19652
+ maxBodyHeight: RECIPIENTS_MAX_HEIGHT,
19653
+ header: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TableRow, { className: "hover:bg-transparent", children: [
19654
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: "Name" }),
19655
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: "Email" }),
19656
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: "Channel" })
19657
+ ] }),
19658
+ children: recipients.map((recipient) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TableRow, { className: DATA_TABLE_ROW_CLASS, children: [
19659
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: recipient.name ?? "\u2014" }),
19660
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: recipient.email ?? "\u2014" }),
19661
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Badge, { tone: recipient.fallback ? "warning" : "neutral", variant: "subtle", children: channelCellText(recipient) }) })
19662
+ ] }, recipient.employeeId))
19663
+ }
19664
+ );
19665
+ }
19666
+ function NotificationDraftBlock({ block }) {
19667
+ const { channel, subject, body, recipients } = block.payload;
19668
+ const [detailsOpen, setDetailsOpen] = (0, import_react20.useState)(false);
19669
+ const showSubject = channel === notificationChannels.EMAIL && subject;
19670
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "overflow-hidden rounded-2xl border border-brown-30 bg-white", children: [
19671
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-3 border-b border-brown-30 px-4 py-3", children: [
19672
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
19673
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-2", children: [
19674
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-geist-body-s-semi-bold text-brown-100", children: "Notification draft" }),
19675
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Badge, { tone: "violet", variant: "subtle", size: "sm", className: "gap-1 py-1", children: [
19676
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Icon, { icon: IconFlask2Filled, size: 12 }),
19677
+ "Labs"
19678
+ ] })
19679
+ ] }),
19680
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CopyButton, { text: notificationDraftToText(block.payload), copyLabel: "Copy draft", copiedLabel: "Copied" })
19681
+ ] }),
19682
+ showSubject && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
19683
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldLabel, { children: "Title" }),
19684
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "text-geist-body-s-medium text-brown-100", children: subject })
19685
+ ] }),
19686
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-1", children: [
19687
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
19688
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldLabel, { children: `Recipients (${recipients.length})` }),
19689
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
19690
+ "button",
19691
+ {
19692
+ type: "button",
19693
+ "aria-expanded": detailsOpen,
19694
+ onClick: () => setDetailsOpen((open) => !open),
19695
+ className: "inline-flex items-center gap-1 text-geist-label-caption-medium text-brown-70 transition-colors hover:text-brown-100",
19696
+ children: [
19697
+ "Details",
19698
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Icon, { icon: IconChevronDown, size: 14, className: detailsOpen ? "rotate-180" : void 0 })
19699
+ ]
19700
+ }
19701
+ )
19702
+ ] }),
19703
+ detailsOpen ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(RecipientsTable, { recipients }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(RecipientChips, { recipients })
19704
+ ] })
19705
+ ] }),
19706
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Markdown, { children: body }) })
19707
+ ] });
19708
+ }
19709
+
19710
+ // src/components/blocks/block-services/notification-draft-block-service.ts
19711
+ var NotificationDraftBlockService = {
19712
+ type: blockTypes.NOTIFICATION_DRAFT,
19713
+ Component: NotificationDraftBlock,
19714
+ /**
19715
+ * Plain-text clipboard form of the drafted notification — shared with the in-block copy button
19716
+ * via {@link notificationDraftToText} so both copy the same text.
19717
+ */
19718
+ toClipboardText: (block) => notificationDraftToText(block.payload)
19719
+ };
19720
+
19721
+ // src/components/blocks/text-block/text-block.tsx
19722
+ var import_jsx_runtime34 = require("react/jsx-runtime");
18843
19723
  function TextBlock({ block }) {
18844
- 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) }) });
19724
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Markdown, { children: block.payload.text });
18845
19725
  }
18846
19726
 
18847
19727
  // src/components/blocks/block-services/text-block-service.ts
@@ -18859,30 +19739,31 @@ var TextBlockService = {
18859
19739
  // src/components/blocks/block-services/index.ts
18860
19740
  var BlockServices = {
18861
19741
  [blockTypes.TEXT]: TextBlockService,
18862
- [blockTypes.ARTIFACT_REF]: ArtifactRefBlockService
19742
+ [blockTypes.ARTIFACT_REF]: ArtifactRefBlockService,
19743
+ [blockTypes.NOTIFICATION_DRAFT]: NotificationDraftBlockService
18863
19744
  };
18864
19745
 
18865
19746
  // src/components/blocks/block/block.tsx
18866
- var import_jsx_runtime26 = require("react/jsx-runtime");
19747
+ var import_jsx_runtime35 = require("react/jsx-runtime");
18867
19748
  function Block({ block }) {
18868
19749
  const service = BlockServices[block.type];
18869
19750
  if (!service) return null;
18870
19751
  const { Component } = service;
18871
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Component, { block });
19752
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Component, { block });
18872
19753
  }
18873
19754
 
18874
19755
  // src/components/blocks/block-context/block-context.tsx
18875
- var import_react16 = require("react");
18876
- var BlockContext = (0, import_react16.createContext)(null);
19756
+ var import_react21 = require("react");
19757
+ var BlockContext = (0, import_react21.createContext)(null);
18877
19758
  function useBlockContext() {
18878
- return (0, import_react16.useContext)(BlockContext) ?? {};
19759
+ return (0, import_react21.useContext)(BlockContext) ?? {};
18879
19760
  }
18880
19761
 
18881
19762
  // src/components/ai-elements/prompt-input/prompt-input.tsx
18882
- var import_react19 = require("react");
19763
+ var import_react24 = require("react");
18883
19764
 
18884
19765
  // src/components/button/button.tsx
18885
- var import_react17 = require("react");
19766
+ var import_react22 = require("react");
18886
19767
 
18887
19768
  // src/components/button/button-styles.ts
18888
19769
  var import_styled_components5 = __toESM(require("styled-components"), 1);
@@ -19005,8 +19886,8 @@ var StyledButton = import_styled_components5.default.button`
19005
19886
  `;
19006
19887
 
19007
19888
  // src/components/button/button.tsx
19008
- var import_jsx_runtime27 = require("react/jsx-runtime");
19009
- var Button2 = (0, import_react17.forwardRef)(function Button3({
19889
+ var import_jsx_runtime36 = require("react/jsx-runtime");
19890
+ var Button2 = (0, import_react22.forwardRef)(function Button3({
19010
19891
  children,
19011
19892
  variant = BUTTON_VARIANT.SOLID,
19012
19893
  intent = BUTTON_INTENT.PRIMARY,
@@ -19018,8 +19899,8 @@ var Button2 = (0, import_react17.forwardRef)(function Button3({
19018
19899
  className,
19019
19900
  "aria-label": ariaLabel
19020
19901
  }, ref) {
19021
- const iconElement = icon ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Icon, { icon, size: 16 }) : null;
19022
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
19902
+ const iconElement = icon ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Icon, { icon, size: 16 }) : null;
19903
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
19023
19904
  StyledButton,
19024
19905
  {
19025
19906
  ref,
@@ -19033,7 +19914,7 @@ var Button2 = (0, import_react17.forwardRef)(function Button3({
19033
19914
  "aria-label": ariaLabel,
19034
19915
  children: [
19035
19916
  iconPosition === ICON_POSITION.LEADING && iconElement,
19036
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children }),
19917
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children }),
19037
19918
  iconPosition === ICON_POSITION.TRAILING && iconElement
19038
19919
  ]
19039
19920
  }
@@ -19041,7 +19922,7 @@ var Button2 = (0, import_react17.forwardRef)(function Button3({
19041
19922
  });
19042
19923
 
19043
19924
  // src/components/text-area/text-area.tsx
19044
- var import_react18 = require("react");
19925
+ var import_react23 = require("react");
19045
19926
 
19046
19927
  // src/utils/merge-refs.ts
19047
19928
  function mergeRefs(...refs) {
@@ -19082,23 +19963,23 @@ var StyledTextArea = import_styled_components6.default.textarea`
19082
19963
  `;
19083
19964
 
19084
19965
  // src/components/text-area/text-area.tsx
19085
- var import_jsx_runtime28 = require("react/jsx-runtime");
19086
- var TextArea = (0, import_react18.forwardRef)(function TextArea2({ value: value2, onChange, placeholder, maxHeight, rows = 1, autoFocus, onKeyDown, disabled, className }, externalRef) {
19087
- const internalRef = (0, import_react18.useRef)(null);
19088
- (0, import_react18.useLayoutEffect)(() => {
19966
+ var import_jsx_runtime37 = require("react/jsx-runtime");
19967
+ var TextArea = (0, import_react23.forwardRef)(function TextArea2({ value: value2, onChange, placeholder, maxHeight, rows = 1, autoFocus, onKeyDown, disabled, className }, externalRef) {
19968
+ const internalRef = (0, import_react23.useRef)(null);
19969
+ (0, import_react23.useLayoutEffect)(() => {
19089
19970
  const el = internalRef.current;
19090
19971
  if (el) {
19091
19972
  el.style.height = "auto";
19092
19973
  el.style.height = `${el.scrollHeight}px`;
19093
19974
  }
19094
19975
  }, [value2]);
19095
- const handleChange = (0, import_react18.useCallback)(
19976
+ const handleChange = (0, import_react23.useCallback)(
19096
19977
  (e) => {
19097
19978
  onChange(e.target.value);
19098
19979
  },
19099
19980
  [onChange]
19100
19981
  );
19101
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
19982
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
19102
19983
  StyledTextArea,
19103
19984
  {
19104
19985
  ref: mergeRefs(internalRef, externalRef),
@@ -19124,9 +20005,9 @@ var CHAT_STATUS = {
19124
20005
  };
19125
20006
 
19126
20007
  // src/components/ai-elements/prompt-input/prompt-input.tsx
19127
- var import_jsx_runtime29 = require("react/jsx-runtime");
20008
+ var import_jsx_runtime38 = require("react/jsx-runtime");
19128
20009
  var PromptInput = ({ className, onSubmit, disabled, children, ...props }) => {
19129
- const handleSubmit = (0, import_react19.useCallback)(
20010
+ const handleSubmit = (0, import_react24.useCallback)(
19130
20011
  (event) => {
19131
20012
  event.preventDefault();
19132
20013
  if (disabled) {
@@ -19141,7 +20022,7 @@ var PromptInput = ({ className, onSubmit, disabled, children, ...props }) => {
19141
20022
  },
19142
20023
  [disabled, onSubmit]
19143
20024
  );
19144
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
20025
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
19145
20026
  "form",
19146
20027
  {
19147
20028
  className: cn(
@@ -19154,9 +20035,9 @@ var PromptInput = ({ className, onSubmit, disabled, children, ...props }) => {
19154
20035
  }
19155
20036
  );
19156
20037
  };
19157
- var PromptInputTextarea = (0, import_react19.forwardRef)(
20038
+ var PromptInputTextarea = (0, import_react24.forwardRef)(
19158
20039
  function PromptInputTextarea2({ className, onKeyDown, placeholder = "What would you like to know?", ...props }, ref) {
19159
- const handleKeyDown = (0, import_react19.useCallback)(
20040
+ const handleKeyDown = (0, import_react24.useCallback)(
19160
20041
  (event) => {
19161
20042
  onKeyDown?.(event);
19162
20043
  if (event.defaultPrevented) {
@@ -19169,21 +20050,21 @@ var PromptInputTextarea = (0, import_react19.forwardRef)(
19169
20050
  },
19170
20051
  [onKeyDown]
19171
20052
  );
19172
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn("py-3", className), children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TextArea, { ref, className: "px-4", onKeyDown: handleKeyDown, placeholder, ...props }) });
20053
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: cn("py-3", className), children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(TextArea, { ref, className: "px-4", onKeyDown: handleKeyDown, placeholder, ...props }) });
19173
20054
  }
19174
20055
  );
19175
- var PromptInputFooter = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn("flex items-center justify-between gap-1 px-4 pb-3", className), ...props });
19176
- var PromptInputTools = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn("flex min-w-0 items-center gap-1", className), ...props });
20056
+ var PromptInputFooter = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: cn("flex items-center justify-between gap-1 px-4 pb-3", className), ...props });
20057
+ var PromptInputTools = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: cn("flex min-w-0 items-center gap-1", className), ...props });
19177
20058
  var PromptInputSubmit = ({
19178
20059
  label = "Submit",
19179
20060
  status = CHAT_STATUS.READY,
19180
20061
  disabled,
19181
20062
  className
19182
20063
  }) => {
19183
- const handleClick = (0, import_react19.useCallback)((event) => {
20064
+ const handleClick = (0, import_react24.useCallback)((event) => {
19184
20065
  event.currentTarget.form?.requestSubmit();
19185
20066
  }, []);
19186
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
20067
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
19187
20068
  Button2,
19188
20069
  {
19189
20070
  intent: status === CHAT_STATUS.ERROR ? BUTTON_INTENT.ERROR : BUTTON_INTENT.PRIMARY,
@@ -19197,7 +20078,7 @@ var PromptInputSubmit = ({
19197
20078
  };
19198
20079
 
19199
20080
  // src/components/ai-elements/mouse-grid/mouse-grid.tsx
19200
- var import_react20 = require("react");
20081
+ var import_react25 = require("react");
19201
20082
 
19202
20083
  // src/utils/prefers-reduced-motion.ts
19203
20084
  function prefersReducedMotion() {
@@ -19205,11 +20086,11 @@ function prefersReducedMotion() {
19205
20086
  }
19206
20087
 
19207
20088
  // src/components/ai-elements/mouse-grid/mouse-grid.tsx
19208
- var import_jsx_runtime30 = require("react/jsx-runtime");
20089
+ var import_jsx_runtime39 = require("react/jsx-runtime");
19209
20090
  function MouseGrid({ glowColor, colorCycleMs = 4e3, autoDrift = false } = {}) {
19210
- const layerRef = (0, import_react20.useRef)(null);
19211
- const glowRef = (0, import_react20.useRef)(null);
19212
- (0, import_react20.useEffect)(() => {
20091
+ const layerRef = (0, import_react25.useRef)(null);
20092
+ const glowRef = (0, import_react25.useRef)(null);
20093
+ (0, import_react25.useEffect)(() => {
19213
20094
  const driftEnabled = autoDrift && !prefersReducedMotion();
19214
20095
  let raf = 0;
19215
20096
  let driftRaf = 0;
@@ -19310,7 +20191,7 @@ function MouseGrid({ glowColor, colorCycleMs = 4e3, autoDrift = false } = {}) {
19310
20191
  }, [autoDrift]);
19311
20192
  const colorList = Array.isArray(glowColor) ? glowColor : glowColor != null ? [glowColor] : [];
19312
20193
  const glowColorsKey = JSON.stringify(colorList);
19313
- (0, import_react20.useEffect)(() => {
20194
+ (0, import_react25.useEffect)(() => {
19314
20195
  const glow = glowRef.current;
19315
20196
  if (!glow) {
19316
20197
  return;
@@ -19337,19 +20218,19 @@ function MouseGrid({ glowColor, colorCycleMs = 4e3, autoDrift = false } = {}) {
19337
20218
  clearColor();
19338
20219
  };
19339
20220
  }, [glowColorsKey, colorCycleMs]);
19340
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { ref: layerRef, "aria-hidden": "true", className: "vibe-mouse-grid-layer", children: [
19341
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "vibe-mouse-grid" }),
19342
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { ref: glowRef, className: "vibe-mouse-glow" })
20221
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { ref: layerRef, "aria-hidden": "true", className: "vibe-mouse-grid-layer", children: [
20222
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "vibe-mouse-grid" }),
20223
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { ref: glowRef, className: "vibe-mouse-glow" })
19343
20224
  ] });
19344
20225
  }
19345
20226
 
19346
20227
  // src/components/ai-elements/suggestion/suggestion.tsx
19347
- var import_react21 = require("react");
19348
- var import_jsx_runtime31 = require("react/jsx-runtime");
19349
- var Suggestions = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("flex flex-wrap items-center justify-center gap-3", className), ...props });
20228
+ var import_react26 = require("react");
20229
+ var import_jsx_runtime40 = require("react/jsx-runtime");
20230
+ var Suggestions = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: cn("flex flex-wrap items-center justify-center gap-3", className), ...props });
19350
20231
  var Suggestion = ({ suggestion, onClick, className, children, ...props }) => {
19351
- const handleClick = (0, import_react21.useCallback)(() => onClick?.(suggestion), [onClick, suggestion]);
19352
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
20232
+ const handleClick = (0, import_react26.useCallback)(() => onClick?.(suggestion), [onClick, suggestion]);
20233
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
19353
20234
  "button",
19354
20235
  {
19355
20236
  type: "button",
@@ -19365,7 +20246,7 @@ var Suggestion = ({ suggestion, onClick, className, children, ...props }) => {
19365
20246
  };
19366
20247
 
19367
20248
  // src/components/chat/chat-message/chat-message.tsx
19368
- var import_react25 = require("react");
20249
+ var import_react29 = require("react");
19369
20250
 
19370
20251
  // src/components/chat/hooks/copy-message-text.ts
19371
20252
  function copyMessageText(message) {
@@ -19382,55 +20263,19 @@ function copyMessageText(message) {
19382
20263
  }
19383
20264
 
19384
20265
  // src/components/chat/chat-message-actions/chat-message-actions.tsx
19385
- var import_react24 = require("react");
20266
+ var import_react28 = require("react");
19386
20267
 
19387
20268
  // src/components/chat/chat-context/chat-context.ts
19388
- var import_react22 = require("react");
19389
- var ChatContext = (0, import_react22.createContext)(null);
20269
+ var import_react27 = require("react");
20270
+ var ChatContext = (0, import_react27.createContext)(null);
19390
20271
  function useChatContext() {
19391
- const context = (0, import_react22.useContext)(ChatContext);
20272
+ const context = (0, import_react27.useContext)(ChatContext);
19392
20273
  if (!context) {
19393
20274
  throw new Error("useChatContext must be used within a Chat.Root component");
19394
20275
  }
19395
20276
  return context;
19396
20277
  }
19397
20278
 
19398
- // src/components/chat/hooks/use-copy-to-clipboard.ts
19399
- var import_react23 = require("react");
19400
-
19401
- // src/utils/clipboard.ts
19402
- function copyToClipboard(text2, options) {
19403
- navigator.clipboard.writeText(text2).then(
19404
- () => options?.onSuccess?.(),
19405
- (error) => options?.onFailure?.(error)
19406
- );
19407
- }
19408
-
19409
- // src/components/chat/hooks/use-copy-to-clipboard.ts
19410
- var RESET_DELAY_MS = 2e3;
19411
- function useCopyToClipboard() {
19412
- const [isCopied, setIsCopied] = (0, import_react23.useState)(false);
19413
- const timeoutRef = (0, import_react23.useRef)(null);
19414
- (0, import_react23.useEffect)(() => {
19415
- return () => {
19416
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
19417
- };
19418
- }, []);
19419
- const copy = (0, import_react23.useCallback)((text2) => {
19420
- copyToClipboard(text2, {
19421
- onSuccess: () => {
19422
- setIsCopied(true);
19423
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
19424
- timeoutRef.current = setTimeout(() => {
19425
- setIsCopied(false);
19426
- timeoutRef.current = null;
19427
- }, RESET_DELAY_MS);
19428
- }
19429
- });
19430
- }, []);
19431
- return { isCopied, copy };
19432
- }
19433
-
19434
20279
  // src/components/chat/constants.ts
19435
20280
  var MESSAGE_ROLE = {
19436
20281
  USER: "user",
@@ -19456,24 +20301,24 @@ var AnimatedAction = import_styled_components7.default.div`
19456
20301
  `;
19457
20302
 
19458
20303
  // src/components/chat/chat-message-actions/chat-message-actions.tsx
19459
- var import_jsx_runtime32 = require("react/jsx-runtime");
20304
+ var import_jsx_runtime41 = require("react/jsx-runtime");
19460
20305
  function ChatMessageActions({ className, messageId, content: content2, role, isHelpful }) {
19461
20306
  const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
19462
20307
  const { isCopied, copy } = useCopyToClipboard();
19463
- const handleCopy = (0, import_react24.useCallback)(() => {
20308
+ const handleCopy = (0, import_react28.useCallback)(() => {
19464
20309
  copy(content2);
19465
20310
  onCopyMessage?.(messageId);
19466
20311
  }, [content2, messageId, copy, onCopyMessage]);
19467
- const handleThumbUp = (0, import_react24.useCallback)(() => {
20312
+ const handleThumbUp = (0, import_react28.useCallback)(() => {
19468
20313
  onThumbUpClick?.(messageId, isHelpful === true ? null : true);
19469
20314
  }, [messageId, isHelpful, onThumbUpClick]);
19470
- const handleThumbDown = (0, import_react24.useCallback)(() => {
20315
+ const handleThumbDown = (0, import_react28.useCallback)(() => {
19471
20316
  onThumbDownClick?.(messageId, isHelpful === false ? null : false);
19472
20317
  }, [messageId, isHelpful, onThumbDownClick]);
19473
20318
  const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
19474
20319
  const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
19475
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(ActionsContainer, { $role: role, className, children: [
19476
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
20320
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(ActionsContainer, { $role: role, className, children: [
20321
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
19477
20322
  IconButton,
19478
20323
  {
19479
20324
  icon: isCopied ? IconCheck : IconCopy,
@@ -19481,7 +20326,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
19481
20326
  "aria-label": isCopied ? "Copied" : "Copy message"
19482
20327
  }
19483
20328
  ),
19484
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
20329
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
19485
20330
  IconButton,
19486
20331
  {
19487
20332
  icon: IconThumbUp,
@@ -19490,7 +20335,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
19490
20335
  "aria-label": "Good response"
19491
20336
  }
19492
20337
  ) }),
19493
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
20338
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
19494
20339
  IconButton,
19495
20340
  {
19496
20341
  icon: IconThumbDown,
@@ -19541,12 +20386,12 @@ var MessageBubble = import_styled_components8.default.div`
19541
20386
  `;
19542
20387
 
19543
20388
  // src/components/chat/chat-message/chat-message.tsx
19544
- var import_jsx_runtime33 = require("react/jsx-runtime");
20389
+ var import_jsx_runtime42 = require("react/jsx-runtime");
19545
20390
  function ChatMessage({ message }) {
19546
- const clipboardText = (0, import_react25.useMemo)(() => copyMessageText(message), [message]);
19547
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(MessageContainer, { $role: message.role, children: [
19548
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MessageBubble, { $role: message.role, "data-testid": "message-bubble", children: message.blocks.map((block, index2) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Block, { block }, index2)) }),
19549
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
20391
+ const clipboardText = (0, import_react29.useMemo)(() => copyMessageText(message), [message]);
20392
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(MessageContainer, { $role: message.role, children: [
20393
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MessageBubble, { $role: message.role, "data-testid": "message-bubble", children: message.blocks.map((block, index2) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Block, { block }, index2)) }),
20394
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
19550
20395
  ChatMessageActions,
19551
20396
  {
19552
20397
  messageId: message.id,
@@ -19606,21 +20451,21 @@ var Key = import_styled_components9.default.kbd`
19606
20451
  `;
19607
20452
 
19608
20453
  // src/components/keyboard-shortcut/keyboard-shortcut.tsx
19609
- var import_jsx_runtime34 = require("react/jsx-runtime");
20454
+ var import_jsx_runtime43 = require("react/jsx-runtime");
19610
20455
  function KeyboardShortcut({
19611
20456
  keys,
19612
20457
  variant = KEYBOARD_SHORTCUT_VARIANTS.OUTLINED,
19613
20458
  adaptive = false,
19614
20459
  className
19615
20460
  }) {
19616
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Wrapper, { className, children: keys.map((KeyComponent, index2) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Key, { $variant: variant, $adaptive: adaptive, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Icon, { icon: KeyComponent, size: 12 }) }, index2)) });
20461
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Wrapper, { className, children: keys.map((KeyComponent, index2) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Key, { $variant: variant, $adaptive: adaptive, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Icon, { icon: KeyComponent, size: 12 }) }, index2)) });
19617
20462
  }
19618
20463
 
19619
20464
  // src/components/keyboard-shortcut/icons/icon-ctrl.tsx
19620
- var import_jsx_runtime35 = require("react/jsx-runtime");
20465
+ var import_jsx_runtime44 = require("react/jsx-runtime");
19621
20466
  function IconCtrl(props) {
19622
20467
  const { width: width2 = 24, height: height2 = 24, ...rest } = props;
19623
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: width2, height: height2, fill: "none", ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
20468
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: width2, height: height2, fill: "none", ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
19624
20469
  "text",
19625
20470
  {
19626
20471
  x: "50%",
@@ -19637,7 +20482,7 @@ function IconCtrl(props) {
19637
20482
  }
19638
20483
 
19639
20484
  // src/components/lottie/lottie.tsx
19640
- var import_react27 = require("react");
20485
+ var import_react31 = require("react");
19641
20486
 
19642
20487
  // src/components/lottie/lottie-styles.ts
19643
20488
  var import_styled_components10 = __toESM(require("styled-components"), 1);
@@ -19653,7 +20498,7 @@ var LottieContainer = import_styled_components10.default.div`
19653
20498
  `;
19654
20499
 
19655
20500
  // src/components/lottie/use-lottie.ts
19656
- var import_react26 = require("react");
20501
+ var import_react30 = require("react");
19657
20502
  var import_lottie_web = __toESM(require_lottie(), 1);
19658
20503
  function useLottie({
19659
20504
  animationData: animationData2,
@@ -19668,17 +20513,17 @@ function useLottie({
19668
20513
  onLoopComplete,
19669
20514
  onEnterFrame
19670
20515
  }) {
19671
- const containerRef = (0, import_react26.useRef)(null);
19672
- const animationRef = (0, import_react26.useRef)(null);
19673
- const onAnimationLoadedRef = (0, import_react26.useRef)(onAnimationLoaded);
19674
- const onCompleteRef = (0, import_react26.useRef)(onComplete);
19675
- const onLoopCompleteRef = (0, import_react26.useRef)(onLoopComplete);
19676
- const onEnterFrameRef = (0, import_react26.useRef)(onEnterFrame);
20516
+ const containerRef = (0, import_react30.useRef)(null);
20517
+ const animationRef = (0, import_react30.useRef)(null);
20518
+ const onAnimationLoadedRef = (0, import_react30.useRef)(onAnimationLoaded);
20519
+ const onCompleteRef = (0, import_react30.useRef)(onComplete);
20520
+ const onLoopCompleteRef = (0, import_react30.useRef)(onLoopComplete);
20521
+ const onEnterFrameRef = (0, import_react30.useRef)(onEnterFrame);
19677
20522
  onAnimationLoadedRef.current = onAnimationLoaded;
19678
20523
  onCompleteRef.current = onComplete;
19679
20524
  onLoopCompleteRef.current = onLoopComplete;
19680
20525
  onEnterFrameRef.current = onEnterFrame;
19681
- (0, import_react26.useEffect)(() => {
20526
+ (0, import_react30.useEffect)(() => {
19682
20527
  if (!containerRef.current) return;
19683
20528
  const anim = import_lottie_web.default.loadAnimation({
19684
20529
  container: containerRef.current,
@@ -19770,8 +20615,8 @@ function createLottieRef(animationRef) {
19770
20615
  }
19771
20616
 
19772
20617
  // src/components/lottie/lottie.tsx
19773
- var import_jsx_runtime36 = require("react/jsx-runtime");
19774
- var Lottie = (0, import_react27.forwardRef)(function Lottie2({
20618
+ var import_jsx_runtime45 = require("react/jsx-runtime");
20619
+ var Lottie = (0, import_react31.forwardRef)(function Lottie2({
19775
20620
  animationData: animationData2,
19776
20621
  autoplay,
19777
20622
  loop,
@@ -19801,8 +20646,8 @@ var Lottie = (0, import_react27.forwardRef)(function Lottie2({
19801
20646
  onLoopComplete,
19802
20647
  onEnterFrame
19803
20648
  });
19804
- (0, import_react27.useImperativeHandle)(ref, () => createLottieRef(animationRef), [animationRef]);
19805
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
20649
+ (0, import_react31.useImperativeHandle)(ref, () => createLottieRef(animationRef), [animationRef]);
20650
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
19806
20651
  LottieContainer,
19807
20652
  {
19808
20653
  ref: containerRef,
@@ -19896,6 +20741,7 @@ function convertTableToCSV(table) {
19896
20741
  BUTTON_INTENT,
19897
20742
  BUTTON_SIZE,
19898
20743
  BUTTON_VARIANT,
20744
+ Badge,
19899
20745
  Block,
19900
20746
  BlockContext,
19901
20747
  BlockServices,
@@ -19904,8 +20750,11 @@ function convertTableToCSV(table) {
19904
20750
  ChartArtifact,
19905
20751
  ChatContext,
19906
20752
  ChatMessage,
20753
+ CopyButton,
19907
20754
  DEFAULT_CHART_ARTIFACT_LABELS,
20755
+ DEFAULT_DECK_ARTIFACT_LABELS,
19908
20756
  DEFAULT_TABLE_ARTIFACT_LABELS,
20757
+ DeckArtifact,
19909
20758
  ICON_POSITION,
19910
20759
  Icon,
19911
20760
  IconButton,
@@ -19915,6 +20764,8 @@ function convertTableToCSV(table) {
19915
20764
  Lottie,
19916
20765
  MESSAGE_ROLE,
19917
20766
  MouseGrid,
20767
+ NotificationDraftBlock,
20768
+ NotificationDraftBlockService,
19918
20769
  PromptInput,
19919
20770
  PromptInputFooter,
19920
20771
  PromptInputSubmit,
@@ -19931,11 +20782,15 @@ function convertTableToCSV(table) {
19931
20782
  colors,
19932
20783
  convertTableToCSV,
19933
20784
  copyMessageText,
20785
+ deckBlockTypes,
20786
+ deckSlideKinds,
19934
20787
  escapeCsvField,
19935
20788
  fontFamilies,
19936
20789
  isSafeDownloadUrl,
19937
20790
  markdownToPlainText,
19938
20791
  mergeRefs,
20792
+ notificationChannels,
20793
+ notificationEmailTypes,
19939
20794
  parseMarkdownTable,
19940
20795
  typographyMixin,
19941
20796
  typographyStyles,
@@ -19959,7 +20814,12 @@ lottie-web/build/player/lottie.js:
19959
20814
  @tabler/icons-react/dist/esm/defaultAttributes.mjs:
19960
20815
  @tabler/icons-react/dist/esm/createReactComponent.mjs:
19961
20816
  @tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs:
20817
+ @tabler/icons-react/dist/esm/icons/IconArrowsMaximize.mjs:
20818
+ @tabler/icons-react/dist/esm/icons/IconArrowsMinimize.mjs:
19962
20819
  @tabler/icons-react/dist/esm/icons/IconCheck.mjs:
20820
+ @tabler/icons-react/dist/esm/icons/IconChevronDown.mjs:
20821
+ @tabler/icons-react/dist/esm/icons/IconChevronLeft.mjs:
20822
+ @tabler/icons-react/dist/esm/icons/IconChevronRight.mjs:
19963
20823
  @tabler/icons-react/dist/esm/icons/IconCopy.mjs:
19964
20824
  @tabler/icons-react/dist/esm/icons/IconDownload.mjs:
19965
20825
  @tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs:
@@ -19967,6 +20827,7 @@ lottie-web/build/player/lottie.js:
19967
20827
  @tabler/icons-react/dist/esm/icons/IconPhoto.mjs:
19968
20828
  @tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
19969
20829
  @tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
20830
+ @tabler/icons-react/dist/esm/icons/IconFlask2Filled.mjs:
19970
20831
  @tabler/icons-react/dist/esm/tabler-icons-react.mjs:
19971
20832
  (**
19972
20833
  * @license @tabler/icons-react v3.37.1 - MIT