@shapesos/clay 0.18.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 (60) hide show
  1. package/dist/artifacts.cjs +151 -130
  2. package/dist/artifacts.cjs.map +1 -1
  3. package/dist/artifacts.js +3 -2
  4. package/dist/badge.cjs +70 -0
  5. package/dist/badge.cjs.map +1 -0
  6. package/dist/badge.d.cts +28 -0
  7. package/dist/badge.d.ts +28 -0
  8. package/dist/badge.js +9 -0
  9. package/dist/badge.js.map +1 -0
  10. package/dist/blocks.cjs +434 -176
  11. package/dist/blocks.cjs.map +1 -1
  12. package/dist/blocks.css +1 -1
  13. package/dist/blocks.d.cts +14 -3
  14. package/dist/blocks.d.ts +14 -3
  15. package/dist/blocks.js +17 -5
  16. package/dist/chat.cjs +439 -231
  17. package/dist/chat.cjs.map +1 -1
  18. package/dist/chat.d.cts +1 -1
  19. package/dist/chat.d.ts +1 -1
  20. package/dist/chat.js +10 -5
  21. package/dist/{chunk-JGMN6W72.js → chunk-2X4KUXYP.js} +1 -1
  22. package/dist/chunk-CSTCTO3B.js +161 -0
  23. package/dist/chunk-CSTCTO3B.js.map +1 -0
  24. package/dist/{chunk-QR4VBGK4.js → chunk-DC5KYT2G.js} +65 -198
  25. package/dist/chunk-DC5KYT2G.js.map +1 -0
  26. package/dist/chunk-EIAWZXE4.js +69 -0
  27. package/dist/chunk-EIAWZXE4.js.map +1 -0
  28. package/dist/chunk-EXRNGIQ2.js +41 -0
  29. package/dist/chunk-EXRNGIQ2.js.map +1 -0
  30. package/dist/{chunk-CATIRDZP.js → chunk-FCSYVF4Z.js} +10 -44
  31. package/dist/chunk-FCSYVF4Z.js.map +1 -0
  32. package/dist/{chunk-4MZZH3WX.js → chunk-HU5W7CGE.js} +37 -2
  33. package/dist/chunk-HU5W7CGE.js.map +1 -0
  34. package/dist/chunk-JMHE3Q5K.js +406 -0
  35. package/dist/chunk-JMHE3Q5K.js.map +1 -0
  36. package/dist/copy-button.cjs +439 -0
  37. package/dist/copy-button.cjs.map +1 -0
  38. package/dist/copy-button.d.cts +20 -0
  39. package/dist/copy-button.d.ts +20 -0
  40. package/dist/copy-button.js +12 -0
  41. package/dist/copy-button.js.map +1 -0
  42. package/dist/index.cjs +515 -289
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.cts +4 -2
  45. package/dist/index.d.ts +4 -2
  46. package/dist/index.js +26 -9
  47. package/dist/table.cjs +40 -0
  48. package/dist/table.cjs.map +1 -1
  49. package/dist/table.d.cts +37 -2
  50. package/dist/table.d.ts +37 -2
  51. package/dist/table.js +11 -1
  52. package/dist/{types-BDYPVP2N.d.cts → types-Bhg0_ES8.d.cts} +74 -2
  53. package/dist/{types-BMwa4bPW.d.ts → types-orOQcI2z.d.ts} +74 -2
  54. package/package.json +11 -1
  55. package/dist/chunk-4MZZH3WX.js.map +0 -1
  56. package/dist/chunk-7MY4X4YL.js +0 -250
  57. package/dist/chunk-7MY4X4YL.js.map +0 -1
  58. package/dist/chunk-CATIRDZP.js.map +0 -1
  59. package/dist/chunk-QR4VBGK4.js.map +0 -1
  60. /package/dist/{chunk-JGMN6W72.js.map → chunk-2X4KUXYP.js.map} +0 -0
package/dist/chat.cjs CHANGED
@@ -278,12 +278,13 @@ __export(chat_exports, {
278
278
  module.exports = __toCommonJS(chat_exports);
279
279
 
280
280
  // src/components/chat/chat-message/chat-message.tsx
281
- var import_react22 = require("react");
281
+ var import_react23 = require("react");
282
282
 
283
283
  // src/components/blocks/types.ts
284
284
  var blockTypes = {
285
285
  TEXT: "TEXT",
286
- ARTIFACT_REF: "ARTIFACT_REF"
286
+ ARTIFACT_REF: "ARTIFACT_REF",
287
+ NOTIFICATION_DRAFT: "NOTIFICATION_DRAFT"
287
288
  };
288
289
 
289
290
  // src/components/artifacts/artifact-base.ts
@@ -447,41 +448,49 @@ var IconArrowsMinimize = createReactComponent("outline", "arrows-minimize", "Arr
447
448
  var __iconNode4 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
448
449
  var IconCheck = createReactComponent("outline", "check", "Check", __iconNode4);
449
450
 
451
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconChevronDown.mjs
452
+ var __iconNode5 = [["path", { "d": "M6 9l6 6l6 -6", "key": "svg-0" }]];
453
+ var IconChevronDown = createReactComponent("outline", "chevron-down", "ChevronDown", __iconNode5);
454
+
450
455
  // node_modules/@tabler/icons-react/dist/esm/icons/IconChevronLeft.mjs
451
- var __iconNode5 = [["path", { "d": "M15 6l-6 6l6 6", "key": "svg-0" }]];
452
- var IconChevronLeft = createReactComponent("outline", "chevron-left", "ChevronLeft", __iconNode5);
456
+ var __iconNode6 = [["path", { "d": "M15 6l-6 6l6 6", "key": "svg-0" }]];
457
+ var IconChevronLeft = createReactComponent("outline", "chevron-left", "ChevronLeft", __iconNode6);
453
458
 
454
459
  // node_modules/@tabler/icons-react/dist/esm/icons/IconChevronRight.mjs
455
- var __iconNode6 = [["path", { "d": "M9 6l6 6l-6 6", "key": "svg-0" }]];
456
- var IconChevronRight = createReactComponent("outline", "chevron-right", "ChevronRight", __iconNode6);
460
+ var __iconNode7 = [["path", { "d": "M9 6l6 6l-6 6", "key": "svg-0" }]];
461
+ var IconChevronRight = createReactComponent("outline", "chevron-right", "ChevronRight", __iconNode7);
457
462
 
458
463
  // node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
459
- var __iconNode7 = [["path", { "d": "M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666", "key": "svg-0" }], ["path", { "d": "M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1", "key": "svg-1" }]];
460
- var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode7);
464
+ 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" }]];
465
+ var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode8);
461
466
 
462
467
  // node_modules/@tabler/icons-react/dist/esm/icons/IconDownload.mjs
463
- var __iconNode8 = [["path", { "d": "M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2", "key": "svg-0" }], ["path", { "d": "M7 11l5 5l5 -5", "key": "svg-1" }], ["path", { "d": "M12 4l0 12", "key": "svg-2" }]];
464
- var IconDownload = createReactComponent("outline", "download", "Download", __iconNode8);
468
+ 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" }]];
469
+ var IconDownload = createReactComponent("outline", "download", "Download", __iconNode9);
465
470
 
466
471
  // node_modules/@tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs
467
- var __iconNode9 = [["path", { "d": "M14 3v4a1 1 0 0 0 1 1h4", "key": "svg-0" }], ["path", { "d": "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2", "key": "svg-1" }], ["path", { "d": "M8 11h8v7h-8l0 -7", "key": "svg-2" }], ["path", { "d": "M8 15h8", "key": "svg-3" }], ["path", { "d": "M11 11v7", "key": "svg-4" }]];
468
- var IconFileSpreadsheet = createReactComponent("outline", "file-spreadsheet", "FileSpreadsheet", __iconNode9);
472
+ 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" }]];
473
+ var IconFileSpreadsheet = createReactComponent("outline", "file-spreadsheet", "FileSpreadsheet", __iconNode10);
469
474
 
470
475
  // node_modules/@tabler/icons-react/dist/esm/icons/IconLoader2.mjs
471
- var __iconNode10 = [["path", { "d": "M12 3a9 9 0 1 0 9 9", "key": "svg-0" }]];
472
- var IconLoader2 = createReactComponent("outline", "loader-2", "Loader2", __iconNode10);
476
+ var __iconNode11 = [["path", { "d": "M12 3a9 9 0 1 0 9 9", "key": "svg-0" }]];
477
+ var IconLoader2 = createReactComponent("outline", "loader-2", "Loader2", __iconNode11);
473
478
 
474
479
  // node_modules/@tabler/icons-react/dist/esm/icons/IconPhoto.mjs
475
- var __iconNode11 = [["path", { "d": "M15 8h.01", "key": "svg-0" }], ["path", { "d": "M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12", "key": "svg-1" }], ["path", { "d": "M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5", "key": "svg-2" }], ["path", { "d": "M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3", "key": "svg-3" }]];
476
- var IconPhoto = createReactComponent("outline", "photo", "Photo", __iconNode11);
480
+ 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" }]];
481
+ var IconPhoto = createReactComponent("outline", "photo", "Photo", __iconNode12);
477
482
 
478
483
  // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
479
- var __iconNode12 = [["path", { "d": "M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3", "key": "svg-0" }]];
480
- var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode12);
484
+ 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" }]];
485
+ var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode13);
481
486
 
482
487
  // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
483
- var __iconNode13 = [["path", { "d": "M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3", "key": "svg-0" }]];
484
- var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode13);
488
+ 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" }]];
489
+ var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode14);
490
+
491
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconFlask2Filled.mjs
492
+ 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" }]];
493
+ var IconFlask2Filled = createReactComponent("filled", "flask-2-filled", "Flask2Filled", __iconNode15);
485
494
 
486
495
  // src/components/artifacts/artifact-copy-as-image-button/artifact-copy-as-image-button.tsx
487
496
  var import_react6 = require("react");
@@ -2139,6 +2148,36 @@ function useScrollShadow() {
2139
2148
  return { targetRef, isScrolled };
2140
2149
  }
2141
2150
 
2151
+ // src/components/table/data-table.tsx
2152
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2153
+ var DATA_TABLE_HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
2154
+ var DATA_TABLE_CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
2155
+ var DATA_TABLE_ROW_CLASS = "border-b-brown-30 bg-background/70 hover:bg-secondary";
2156
+ var DATA_TABLE_SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
2157
+ function DataTable({ header, children, maxBodyHeight, className }) {
2158
+ const { targetRef, isScrolled } = useScrollShadow();
2159
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2160
+ "div",
2161
+ {
2162
+ ref: targetRef,
2163
+ className: cn("overscroll-none", className),
2164
+ style: maxBodyHeight !== void 0 ? { maxHeight: maxBodyHeight, overflowY: "auto" } : void 0,
2165
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Table, { containerClassName: "overflow-visible", children: [
2166
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2167
+ TableHeader,
2168
+ {
2169
+ "data-scrolled": isScrolled ? "true" : void 0,
2170
+ className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
2171
+ style: isScrolled ? { boxShadow: DATA_TABLE_SCROLL_SHADOW } : void 0,
2172
+ children: header
2173
+ }
2174
+ ),
2175
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableBody, { children })
2176
+ ] })
2177
+ }
2178
+ );
2179
+ }
2180
+
2142
2181
  // src/components/artifacts/table-artifact/table-artifact-content.constants.ts
2143
2182
  var TABLE_STATUS = {
2144
2183
  LOADING: "loading",
@@ -2151,14 +2190,10 @@ var TABLE_STATUS = {
2151
2190
  function formatCell(row, column) {
2152
2191
  return row[column.key] ?? "";
2153
2192
  }
2154
- var HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
2155
- var CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
2156
- var ROW_CLASSES = "border-b-brown-30 bg-background/70 hover:bg-secondary";
2157
- var DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;
2158
- var SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
2193
+ var DATA_ROW_CLASSES = `${DATA_TABLE_ROW_CLASS} animate-in fade-in duration-300`;
2159
2194
 
2160
2195
  // src/components/artifacts/table-artifact/table-artifact-content.tsx
2161
- var import_jsx_runtime21 = require("react/jsx-runtime");
2196
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2162
2197
  function TableArtifactContent({
2163
2198
  columns,
2164
2199
  data,
@@ -2168,50 +2203,45 @@ function TableArtifactContent({
2168
2203
  labels
2169
2204
  }) {
2170
2205
  if (data.status === TABLE_STATUS.ERROR) {
2171
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusMessage, { $tone: "error", children: labels.loadError });
2206
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "error", children: labels.loadError });
2172
2207
  }
2173
2208
  if (data.status === TABLE_STATUS.UNAVAILABLE) {
2174
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
2209
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
2175
2210
  }
2176
2211
  if (data.status === TABLE_STATUS.LOADING) {
2177
2212
  if (typeof knownRowCount === "number" && knownRowCount > 0) {
2178
2213
  const shimmerCount = Math.min(knownRowCount, maxShimmerRows);
2179
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
2214
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
2180
2215
  }
2181
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusMessage, { $tone: "info", children: labels.loading });
2216
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "info", children: labels.loading });
2182
2217
  }
2183
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ArtifactTable, { columns, maxBodyHeight, children: data.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data.rows) });
2218
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTable, { columns, maxBodyHeight, children: data.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data.rows) });
2184
2219
  }
2185
2220
  function ArtifactTable({ columns, maxBodyHeight, children }) {
2186
- const { targetRef, isScrolled } = useScrollShadow();
2187
- 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: [
2188
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2189
- TableHeader,
2190
- {
2191
- "data-scrolled": isScrolled ? "true" : void 0,
2192
- className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
2193
- style: isScrolled ? { boxShadow: SCROLL_SHADOW } : void 0,
2194
- 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)) })
2195
- }
2196
- ),
2197
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableBody, { children })
2198
- ] }) });
2221
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2222
+ DataTable,
2223
+ {
2224
+ maxBodyHeight,
2225
+ 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)) }),
2226
+ children
2227
+ }
2228
+ );
2199
2229
  }
2200
2230
  function renderShimmerRows(columns, count) {
2201
- return Array.from({ length: count }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableRow, { className: ROW_CLASSES, "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableCell, { className: CELL_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20" }) }, column.key)) }, `shimmer-${index}`));
2231
+ return Array.from({ length: count }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: DATA_TABLE_ROW_CLASS, "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20" }) }, column.key)) }, `shimmer-${index}`));
2202
2232
  }
2203
2233
  function renderDataRows(columns, rows) {
2204
- return rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableRow, { className: DATA_ROW_CLASSES, children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableCell, { className: CELL_CLASS, children: formatCell(row, column) }, column.key)) }, index));
2234
+ return rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: DATA_ROW_CLASSES, children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: formatCell(row, column) }, column.key)) }, index));
2205
2235
  }
2206
2236
  function renderEmptyRow(colSpan, emptyMessage) {
2207
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableCell, { colSpan, className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) });
2237
+ 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 }) });
2208
2238
  }
2209
2239
 
2210
2240
  // src/components/artifacts/deck-artifact/deck-markdown.tsx
2211
2241
  var import_react_markdown = __toESM(require("react-markdown"), 1);
2212
2242
  var import_remark_breaks = __toESM(require("remark-breaks"), 1);
2213
2243
  var import_remark_gfm = __toESM(require("remark-gfm"), 1);
2214
- var import_jsx_runtime22 = require("react/jsx-runtime");
2244
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2215
2245
  function sanitize(text) {
2216
2246
  return text.split("\n").filter((line) => {
2217
2247
  const t = line.trim();
@@ -2219,45 +2249,45 @@ function sanitize(text) {
2219
2249
  }).join("\n");
2220
2250
  }
2221
2251
  var MARKDOWN_COMPONENTS = {
2222
- h1: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h1", { className: "text-[30px] font-semibold leading-tight text-foreground mb-3", ...props }),
2223
- h2: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h2", { className: "text-[26px] font-semibold leading-tight text-foreground mb-2", ...props }),
2224
- h3: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2225
- h4: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h4", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2226
- h5: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h5", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2227
- h6: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h6", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2228
- p: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-[22px] leading-relaxed text-foreground my-2", ...props }),
2229
- ul: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ul", { className: "list-disc pl-7 text-[22px] leading-relaxed text-foreground my-2", ...props }),
2230
- ol: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ol", { className: "list-decimal pl-7 text-[22px] leading-relaxed text-foreground my-2", ...props }),
2252
+ h1: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: "text-[30px] font-semibold leading-tight text-foreground mb-3", ...props }),
2253
+ h2: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "text-[26px] font-semibold leading-tight text-foreground mb-2", ...props }),
2254
+ h3: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2255
+ h4: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h4", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2256
+ h5: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h5", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2257
+ h6: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h6", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
2258
+ p: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[22px] leading-relaxed text-foreground my-2", ...props }),
2259
+ 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 }),
2260
+ 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 }),
2231
2261
  // react-markdown injects list metadata (`ordered` / `index` / `checked`) that must not leak to the DOM.
2232
- li: ({ node: _node, ordered: _ordered, index: _index, checked: _checked, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("li", { className: "my-1", ...props }),
2233
- strong: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("strong", { className: "font-semibold", ...props }),
2234
- em: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("em", { className: "italic", ...props }),
2262
+ li: ({ node: _node, ordered: _ordered, index: _index, checked: _checked, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("li", { className: "my-1", ...props }),
2263
+ strong: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("strong", { className: "font-semibold", ...props }),
2264
+ em: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("em", { className: "italic", ...props }),
2235
2265
  // Gate `<img src>` against an http(s) allowlist. react-markdown v8 percent-encodes the URL but
2236
2266
  // does NOT protocol-filter image src (unlike link href), so an LLM-authored
2237
2267
  // `![](javascript:…)` / `![](data:…)` or a tracking-pixel `![](http://…)` would otherwise render
2238
2268
  // with the raw URL. Unsafe src → render nothing.
2239
- img: ({ node: _node, src, ...props }) => typeof src === "string" && isSafeDownloadUrl(src) ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src, className: "max-w-full", ...props }) : null,
2269
+ img: ({ node: _node, src, ...props }) => typeof src === "string" && isSafeDownloadUrl(src) ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src, className: "max-w-full", ...props }) : null,
2240
2270
  a: ({ node: _node, ...props }) => (
2241
2271
  // `rel` is forced AFTER `{...props}` so it can't be overridden — if a consumer ever adds
2242
2272
  // `linkTarget="_blank"`, LLM-authored links still can't reach `window.opener`.
2243
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("a", { className: "underline underline-offset-2", ...props, rel: "noopener noreferrer" })
2273
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("a", { className: "underline underline-offset-2", ...props, rel: "noopener noreferrer" })
2244
2274
  ),
2245
2275
  // react-markdown passes `inline` to distinguish inline code from fenced blocks — strip it from the DOM.
2246
- code: ({ node: _node, inline: _inline, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("code", { className: "rounded bg-muted px-1.5 py-0.5 font-mono text-[18px]", ...props }),
2247
- blockquote: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("blockquote", { className: "border-l-2 border-brown-alpha-12 pl-4 text-[22px] text-muted-foreground", ...props }),
2248
- hr: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("hr", { className: "my-4 border-brown-alpha-12", ...props }),
2249
- table: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("table", { className: "w-full border-collapse text-[20px]", ...props }) }),
2276
+ 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 }),
2277
+ 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 }),
2278
+ hr: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("hr", { className: "my-4 border-brown-alpha-12", ...props }),
2279
+ 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 }) }),
2250
2280
  // react-markdown passes `isHeader` to cell renderers — strip it so it never reaches the DOM.
2251
- th: ({ node: _node, isHeader: _isHeader, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("th", { className: "border-b border-brown-alpha-12 px-3 py-1.5 text-left font-medium", ...props }),
2252
- td: ({ node: _node, isHeader: _isHeader, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("td", { className: "border-b border-brown-alpha-12 px-3 py-1.5", ...props })
2281
+ 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 }),
2282
+ 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 })
2253
2283
  };
2254
2284
  function DeckMarkdown({ markdown }) {
2255
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: MARKDOWN_COMPONENTS, children: sanitize(markdown) });
2285
+ 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) });
2256
2286
  }
2257
2287
 
2258
2288
  // src/components/artifacts/deck-artifact/slide-renderers.tsx
2259
2289
  var import_react15 = require("react");
2260
- var import_jsx_runtime23 = require("react/jsx-runtime");
2290
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2261
2291
  function safeLogoUrl(meta) {
2262
2292
  return meta?.logoUrl && isSafeDownloadUrl(meta.logoUrl) ? meta.logoUrl : null;
2263
2293
  }
@@ -2284,7 +2314,7 @@ function SlideFrame({ meta, children, accent = false, bare = false }) {
2284
2314
  const eyebrowColor = accent ? "text-white/70" : "text-brown-60";
2285
2315
  const borderColor = accent ? "border-white/20" : "border-brown-alpha-12";
2286
2316
  const logoSrc = safeLogoUrl(meta);
2287
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: frameRef, className: `relative aspect-[16/9] w-full overflow-hidden rounded-lg ${bg}`, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2317
+ 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)(
2288
2318
  "div",
2289
2319
  {
2290
2320
  className: "absolute left-0 top-0 origin-top-left",
@@ -2295,26 +2325,26 @@ function SlideFrame({ meta, children, accent = false, bare = false }) {
2295
2325
  visibility: scale === null ? "hidden" : "visible"
2296
2326
  },
2297
2327
  children: [
2298
- !bare ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2328
+ !bare ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2299
2329
  "div",
2300
2330
  {
2301
2331
  className: `absolute inset-x-0 top-0 flex items-center justify-between border-b px-16 ${borderColor}`,
2302
2332
  style: { height: EYEBROW_H },
2303
2333
  children: [
2304
- meta?.eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: eyebrowColor, style: { ...ACCENT_FONT, fontSize: 22 }, children: meta.eyebrow }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", {}),
2305
- logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: logoSrc, alt: "", className: "object-contain", style: { maxHeight: CANVAS_LOGO_MAX_H } }) : null
2334
+ 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", {}),
2335
+ logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: logoSrc, alt: "", className: "object-contain", style: { maxHeight: CANVAS_LOGO_MAX_H } }) : null
2306
2336
  ]
2307
2337
  }
2308
2338
  ) : null,
2309
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute inset-x-0 bottom-0 overflow-hidden", style: { top: bare ? 0 : EYEBROW_H }, children })
2339
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute inset-x-0 bottom-0 overflow-hidden", style: { top: bare ? 0 : EYEBROW_H }, children })
2310
2340
  ]
2311
2341
  }
2312
2342
  ) });
2313
2343
  }
2314
2344
  function TitleSlide({ slide, meta }) {
2315
2345
  const logoSrc = safeLogoUrl(meta);
2316
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SlideFrame, { meta, bare: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex h-full flex-col justify-center px-24 py-16", children: [
2317
- logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2346
+ 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: [
2347
+ logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2318
2348
  "img",
2319
2349
  {
2320
2350
  src: logoSrc,
@@ -2323,7 +2353,7 @@ function TitleSlide({ slide, meta }) {
2323
2353
  style: { maxHeight: 56, maxWidth: 380 }
2324
2354
  }
2325
2355
  ) : null,
2326
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2356
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2327
2357
  "h1",
2328
2358
  {
2329
2359
  className: "font-bold tracking-tight text-brown-100",
@@ -2331,36 +2361,36 @@ function TitleSlide({ slide, meta }) {
2331
2361
  children: slide.title
2332
2362
  }
2333
2363
  ),
2334
- slide.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "mt-7 text-brown-70", style: { ...ACCENT_FONT, fontSize: 34 }, children: slide.subtitle }) : null,
2335
- slide.description ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "mt-4 leading-relaxed text-brown-70", style: { fontSize: 24, maxWidth: 880 }, children: slide.description }) : null,
2336
- meta?.date ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "mt-10 text-brown-70", style: { ...ACCENT_FONT, fontSize: 30 }, children: meta.date }) : null
2364
+ slide.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-7 text-brown-70", style: { ...ACCENT_FONT, fontSize: 34 }, children: slide.subtitle }) : null,
2365
+ 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,
2366
+ meta?.date ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-10 text-brown-70", style: { ...ACCENT_FONT, fontSize: 30 }, children: meta.date }) : null
2337
2367
  ] }) });
2338
2368
  }
2339
2369
  function AgendaSlide({ slide, meta, labels }) {
2340
2370
  const items = slide.items ?? [];
2341
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "h-full px-24 py-14", children: [
2342
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "mb-10 font-bold text-brown-90", style: { fontSize: 40 }, children: slide.title || labels.agenda }),
2343
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-col", children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-baseline gap-6 border-b border-brown-alpha-12 py-5", children: [
2344
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "shrink-0 text-indigo-600", style: { ...ACCENT_FONT, fontSize: 28, width: 64 }, children: String(i + 1).padStart(2, "0") }),
2345
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-brown-90", style: { fontSize: 28 }, children: item })
2371
+ 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: [
2372
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "mb-10 font-bold text-brown-90", style: { fontSize: 40 }, children: slide.title || labels.agenda }),
2373
+ /* @__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: [
2374
+ /* @__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") }),
2375
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-brown-90", style: { fontSize: 28 }, children: item })
2346
2376
  ] }, i)) })
2347
2377
  ] }) });
2348
2378
  }
2349
2379
  function SectionSlide({ slide, meta }) {
2350
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SlideFrame, { meta, accent: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex h-full flex-col justify-center gap-6 px-24", children: [
2351
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "font-bold text-white", style: { fontSize: 72, lineHeight: 1.05, maxWidth: 940 }, children: slide.title }),
2352
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "mt-2 bg-white/50", style: { width: 96, height: 5 } })
2380
+ 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: [
2381
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "font-bold text-white", style: { fontSize: 72, lineHeight: 1.05, maxWidth: 940 }, children: slide.title }),
2382
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-2 bg-white/50", style: { width: 96, height: 5 } })
2353
2383
  ] }) });
2354
2384
  }
2355
2385
  function ClosingSlide({ meta, labels }) {
2356
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex h-full flex-col items-center justify-center gap-6 px-24 text-center", children: [
2357
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: "font-bold text-brown-100", style: { fontSize: 72 }, children: labels.thankYou }),
2358
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-indigo-600", style: { ...ACCENT_FONT, fontSize: 36 }, children: labels.questions })
2386
+ 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: [
2387
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h1", { className: "font-bold text-brown-100", style: { fontSize: 72 }, children: labels.thankYou }),
2388
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-indigo-600", style: { ...ACCENT_FONT, fontSize: 36 }, children: labels.questions })
2359
2389
  ] }) });
2360
2390
  }
2361
2391
 
2362
2392
  // src/components/artifacts/deck-artifact/deck-artifact-content.tsx
2363
- var import_jsx_runtime24 = require("react/jsx-runtime");
2393
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2364
2394
  var TABLE_BLOCK_MAX_SHIMMER_ROWS = 10;
2365
2395
  var TABLE_CHROME_RESERVE = 56;
2366
2396
  var VISUAL_FALLBACK_HEIGHT = 360;
@@ -2390,14 +2420,14 @@ function DeckArtifactContent({
2390
2420
  [slides.length, onNavigate, isControlled, onSlideChange]
2391
2421
  );
2392
2422
  const position = labels.position.replace("{current}", String(current + 1)).replace("{total}", String(slides.length));
2393
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
2394
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideDispatch, { slide, labels, meta }),
2395
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
2423
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
2424
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideDispatch, { slide, labels, meta }),
2425
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
2396
2426
  "div",
2397
2427
  {
2398
2428
  className: `flex items-center justify-between border-t pt-2 ${onDark ? "border-white/20" : "border-brown-alpha-12"}`,
2399
2429
  children: [
2400
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2430
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2401
2431
  IconButton,
2402
2432
  {
2403
2433
  icon: IconChevronLeft,
@@ -2408,8 +2438,8 @@ function DeckArtifactContent({
2408
2438
  onClick: () => goTo(current - 1)
2409
2439
  }
2410
2440
  ),
2411
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: `text-xs font-medium ${onDark ? "text-white/70" : "text-brown-70"}`, children: position }),
2412
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2441
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: `text-xs font-medium ${onDark ? "text-white/70" : "text-brown-70"}`, children: position }),
2442
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2413
2443
  IconButton,
2414
2444
  {
2415
2445
  icon: IconChevronRight,
@@ -2429,16 +2459,16 @@ function SlideDispatch({ slide, labels, meta }) {
2429
2459
  const kind = slide.kind ?? deckSlideKinds.CONTENT;
2430
2460
  switch (kind) {
2431
2461
  case deckSlideKinds.TITLE:
2432
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TitleSlide, { slide, meta });
2462
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TitleSlide, { slide, meta });
2433
2463
  case deckSlideKinds.AGENDA:
2434
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AgendaSlide, { slide, meta, labels });
2464
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AgendaSlide, { slide, meta, labels });
2435
2465
  case deckSlideKinds.SECTION:
2436
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SectionSlide, { slide, meta });
2466
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SectionSlide, { slide, meta });
2437
2467
  case deckSlideKinds.CLOSING:
2438
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ClosingSlide, { meta, labels });
2468
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ClosingSlide, { meta, labels });
2439
2469
  case deckSlideKinds.CONTENT:
2440
2470
  default:
2441
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ContentSlide, { slide, meta, labels });
2471
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ContentSlide, { slide, meta, labels });
2442
2472
  }
2443
2473
  }
2444
2474
  function isVisualBlock(block) {
@@ -2451,25 +2481,25 @@ function ContentSlide({ slide, meta, labels }) {
2451
2481
  (b) => b.type === deckBlockTypes.TEXT
2452
2482
  );
2453
2483
  if (visuals.length === 1 && texts.length > 0) {
2454
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full items-stretch gap-12 px-16 py-12", children: [
2455
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex w-[42%] shrink-0 flex-col overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AutoFit, { children: [
2456
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "mb-5 font-bold leading-tight text-foreground", style: { fontSize: 34 }, children: slide.title }),
2457
- texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
2484
+ 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: [
2485
+ /* @__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: [
2486
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "mb-5 font-bold leading-tight text-foreground", style: { fontSize: 34 }, children: slide.title }),
2487
+ texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
2458
2488
  ] }) }),
2459
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "min-h-0 min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(FillVisual, { block: visuals[0], labels }) })
2489
+ /* @__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 }) })
2460
2490
  ] }) });
2461
2491
  }
2462
2492
  if (visuals.length > 0) {
2463
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full flex-col gap-5 px-16 py-10", children: [
2464
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "shrink-0 font-bold leading-tight text-foreground", style: { fontSize: 32 }, children: slide.title }),
2493
+ 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: [
2494
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "shrink-0 font-bold leading-tight text-foreground", style: { fontSize: 32 }, children: slide.title }),
2465
2495
  content.map(
2466
- (block, i) => isVisualBlock(block) ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "min-h-0 min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(FillVisual, { block, labels }) }, i) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "shrink-0 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DeckMarkdown, { markdown: block.markdown }) }, i)
2496
+ (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)
2467
2497
  )
2468
2498
  ] }) });
2469
2499
  }
2470
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "h-full px-24 py-12", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AutoFit, { children: [
2471
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "mb-6 font-bold leading-tight text-foreground", style: { fontSize: 38 }, children: slide.title }),
2472
- texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
2500
+ 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: [
2501
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "mb-6 font-bold leading-tight text-foreground", style: { fontSize: 38 }, children: slide.title }),
2502
+ texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
2473
2503
  ] }) }) });
2474
2504
  }
2475
2505
  function AutoFit({ children }) {
@@ -2493,7 +2523,7 @@ function AutoFit({ children }) {
2493
2523
  return () => ro.disconnect();
2494
2524
  }, []);
2495
2525
  const scaled = fit.scale < 1;
2496
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: boxRef, className: "flex h-full min-h-0 w-full flex-col justify-center overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: scaled ? { height: fit.height } : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2526
+ 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)(
2497
2527
  "div",
2498
2528
  {
2499
2529
  ref: contentRef,
@@ -2518,12 +2548,12 @@ function FillVisual({ block, labels }) {
2518
2548
  return () => ro.disconnect();
2519
2549
  }, []);
2520
2550
  const chartLabels = labels.chart ?? DEFAULT_CHART_ARTIFACT_LABELS;
2521
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref, className: "h-full min-h-0 w-full overflow-hidden", children: block.type === deckBlockTypes.CHART ? (
2551
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref, className: "h-full min-h-0 w-full overflow-hidden", children: block.type === deckBlockTypes.CHART ? (
2522
2552
  // ChartArtifactContent assumes a non-empty rowset (the standalone ChartArtifact guards
2523
2553
  // `rows.length > 0` upstream); mirror that guard here so an empty inline chart shows the
2524
2554
  // localized empty status instead of a blank chart area.
2525
- block.rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(StatusMessage, { $tone: "info", children: chartLabels.empty }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { height }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ChartArtifactContent, { config: block.config, rows: block.rows, labels: chartLabels }) })
2526
- ) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2555
+ block.rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusMessage, { $tone: "info", children: chartLabels.empty }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { height }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChartArtifactContent, { config: block.config, rows: block.rows, labels: chartLabels }) })
2556
+ ) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2527
2557
  TableArtifactContent,
2528
2558
  {
2529
2559
  columns: block.config.columns,
@@ -2589,7 +2619,7 @@ function isValidDeckBlock(block) {
2589
2619
  }
2590
2620
 
2591
2621
  // src/components/artifacts/deck-artifact/deck-artifact.tsx
2592
- var import_jsx_runtime25 = require("react/jsx-runtime");
2622
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2593
2623
  var TITLE_CLASSES2 = "text-sm font-semibold text-foreground";
2594
2624
  function DeckArtifact({ artifact, labels, callbacks }) {
2595
2625
  const validConfig = isValidDeckConfig(artifact.config);
@@ -2630,9 +2660,9 @@ function DeckArtifact({ artifact, labels, callbacks }) {
2630
2660
  const meta = artifact.config?.meta;
2631
2661
  const handleOpenFullscreen = () => setIsFullscreen(true);
2632
2662
  const handleCloseFullscreen = () => setIsFullscreen(false);
2633
- const actions = /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(ArtifactActions, { ...{ [CAPTURE_EXCLUDE_ATTRIBUTE]: "" }, children: [
2634
- showDownload ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactDownloadButton, { href: presignedUrl ?? "", label: resolvedLabels.download, onClick: handleDownload }) : null,
2635
- validConfig ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2663
+ const actions = /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactActions, { ...{ [CAPTURE_EXCLUDE_ATTRIBUTE]: "" }, children: [
2664
+ showDownload ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactDownloadButton, { href: presignedUrl ?? "", label: resolvedLabels.download, onClick: handleDownload }) : null,
2665
+ validConfig ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2636
2666
  IconButton,
2637
2667
  {
2638
2668
  icon: IconArrowsMaximize,
@@ -2643,21 +2673,21 @@ function DeckArtifact({ artifact, labels, callbacks }) {
2643
2673
  ) : null
2644
2674
  ] });
2645
2675
  if (!validConfig) {
2646
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2647
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2648
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", {}),
2676
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2677
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2678
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
2649
2679
  actions
2650
2680
  ] }),
2651
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
2681
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
2652
2682
  ] });
2653
2683
  }
2654
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
2655
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2656
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2657
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", {}),
2684
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
2685
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2686
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2687
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
2658
2688
  actions
2659
2689
  ] }),
2660
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2690
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2661
2691
  DeckArtifactContent,
2662
2692
  {
2663
2693
  slides: artifact.config.slides,
@@ -2670,7 +2700,7 @@ function DeckArtifact({ artifact, labels, callbacks }) {
2670
2700
  ) })
2671
2701
  ] }),
2672
2702
  isFullscreen && (0, import_react_dom.createPortal)(
2673
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2703
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2674
2704
  FullscreenOverlay,
2675
2705
  {
2676
2706
  artifact,
@@ -2694,15 +2724,15 @@ function FullscreenOverlay({
2694
2724
  onClose
2695
2725
  }) {
2696
2726
  const meta = artifact.config?.meta;
2697
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2727
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2698
2728
  "div",
2699
2729
  {
2700
2730
  className: "fixed inset-0 z-[2147483647] flex items-center justify-center bg-black/80",
2701
2731
  role: "dialog",
2702
2732
  "aria-modal": "true",
2703
2733
  "aria-label": resolvedLabels.exitFullscreen,
2704
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "relative", style: { width: "min(94vw, calc(82vh * 16 / 9))" }, children: [
2705
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2734
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "relative", style: { width: "min(94vw, calc(82vh * 16 / 9))" }, children: [
2735
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2706
2736
  DeckArtifactContent,
2707
2737
  {
2708
2738
  slides: artifact.config.slides,
@@ -2714,15 +2744,15 @@ function FullscreenOverlay({
2714
2744
  onDark: true
2715
2745
  }
2716
2746
  ),
2717
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
2747
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
2718
2748
  "button",
2719
2749
  {
2720
2750
  className: "absolute -top-10 right-6 flex items-center gap-1.5 text-sm text-white/80 hover:text-white",
2721
2751
  "aria-label": resolvedLabels.exitFullscreen,
2722
2752
  onClick: onClose,
2723
2753
  children: [
2724
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(IconArrowsMinimize, { size: 16 }),
2725
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: resolvedLabels.exitFullscreen })
2754
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IconArrowsMinimize, { size: 16 }),
2755
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: resolvedLabels.exitFullscreen })
2726
2756
  ]
2727
2757
  }
2728
2758
  )
@@ -2799,7 +2829,7 @@ function useTableArtifactData(presignedUrl, columns) {
2799
2829
  }
2800
2830
 
2801
2831
  // src/components/artifacts/table-artifact/table-artifact.tsx
2802
- var import_jsx_runtime26 = require("react/jsx-runtime");
2832
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2803
2833
  var TITLE_CLASSES3 = "text-sm font-semibold text-foreground";
2804
2834
  var TABLE_MAX_BODY_HEIGHT = 480;
2805
2835
  var MAX_SHIMMER_ROWS = 10;
@@ -2822,10 +2852,10 @@ function TableArtifact({ artifact, labels, callbacks }) {
2822
2852
  const onDownload = callbacks?.onDownload;
2823
2853
  const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
2824
2854
  if (!validConfig || !validColumns) {
2825
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2826
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2827
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
2828
- presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2855
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2856
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2857
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", {}),
2858
+ presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2829
2859
  ArtifactDownloadButton,
2830
2860
  {
2831
2861
  href: presignedUrl,
@@ -2834,17 +2864,17 @@ function TableArtifact({ artifact, labels, callbacks }) {
2834
2864
  }
2835
2865
  ) }) : null
2836
2866
  ] }),
2837
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
2867
+ /* @__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 }) })
2838
2868
  ] });
2839
2869
  }
2840
2870
  return (
2841
2871
  // The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
2842
2872
  // Disable the outer overflow container so only one scroll context exists — this prevents
2843
2873
  // double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
2844
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2845
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2846
- artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
2847
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2874
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
2875
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
2876
+ artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", {}),
2877
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2848
2878
  ArtifactDownloadButton,
2849
2879
  {
2850
2880
  href: presignedUrl ?? "",
@@ -2853,7 +2883,7 @@ function TableArtifact({ artifact, labels, callbacks }) {
2853
2883
  }
2854
2884
  ) })
2855
2885
  ] }),
2856
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2886
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2857
2887
  TableArtifactContent,
2858
2888
  {
2859
2889
  columns: validColumns,
@@ -2896,13 +2926,13 @@ function artifactToClipboardText(artifact) {
2896
2926
  }
2897
2927
 
2898
2928
  // src/components/blocks/artifact-ref-block/artifact-ref-block.tsx
2899
- var import_jsx_runtime27 = require("react/jsx-runtime");
2929
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2900
2930
  function ArtifactRefBlock({ block }) {
2901
2931
  const { artifact, labels, callbacks } = block.payload;
2902
2932
  const entry = ArtifactServices[artifact.type];
2903
2933
  if (!entry) return null;
2904
2934
  const Component = entry.Component;
2905
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Component, { artifact, labels, callbacks });
2935
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Component, { artifact, labels, callbacks });
2906
2936
  }
2907
2937
 
2908
2938
  // src/components/blocks/block-services/artifact-ref-block-service.ts
@@ -2917,26 +2947,99 @@ var ArtifactRefBlockService = {
2917
2947
  toClipboardText: (block) => artifactToClipboardText(block.payload.artifact)
2918
2948
  };
2919
2949
 
2920
- // src/utils/markdown-to-plain-text.ts
2921
- var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
2922
- var PLACEHOLDER_SUFFIX = "\u200B\u200B";
2923
- var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
2924
- function stripInlineMarks(text) {
2925
- return text.replace(/\*{3}(.+?)\*{3}/g, "$1").replace(/\*{2}(.+?)\*{2}/g, "$1").replace(/_{2}(.+?)_{2}/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1");
2950
+ // src/components/blocks/notification-draft-block/notification-draft-block.tsx
2951
+ var import_react20 = require("react");
2952
+
2953
+ // src/components/badge/badge.tsx
2954
+ var import_jsx_runtime29 = require("react/jsx-runtime");
2955
+ var BASE = "inline-flex items-center whitespace-nowrap rounded-full";
2956
+ var SIZES = {
2957
+ // `sm` is a uniform scale-down of `md` (text 10/12 of caption): padding and line-height keep
2958
+ // md's proportions (caption is 12px text on a 16px line = 1.333 ratio) so the pill shape matches.
2959
+ md: "px-2.5 py-0.5 text-geist-label-caption-medium",
2960
+ sm: "px-2 py-0.5 text-[11px]/[1.333] font-medium"
2961
+ };
2962
+ var SUBTLE = {
2963
+ neutral: "bg-brown-20 text-brown-70",
2964
+ warning: "bg-orange-50 text-orange-600",
2965
+ violet: "bg-violet-50 text-violet-600"
2966
+ };
2967
+ var OUTLINE = {
2968
+ neutral: "border border-brown-30 bg-white text-brown-100",
2969
+ warning: "border border-orange-200 bg-white text-orange-600",
2970
+ violet: "border border-violet-400 bg-white text-violet-600"
2971
+ };
2972
+ var VARIANTS = {
2973
+ subtle: SUBTLE,
2974
+ outline: OUTLINE
2975
+ };
2976
+ function Badge({
2977
+ variant = "subtle",
2978
+ tone = "neutral",
2979
+ size = "md",
2980
+ className,
2981
+ children
2982
+ }) {
2983
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cn(BASE, SIZES[size], VARIANTS[variant][tone], className), children });
2926
2984
  }
2927
- function markdownToPlainText(markdown) {
2928
- if (!markdown) return "";
2929
- const inlineCodeSnippets = [];
2930
- let result = markdown.replace(/^<!--[\s\S]*?--!?>\n?/gm, "").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
2931
- inlineCodeSnippets.push(code);
2932
- return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
2933
- }).replace(/^#{1,6}\s+/gm, "").replace(/^(?:---|\*\*\*|___)\s*$/gm, "");
2934
- 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();
2935
- result = result.replace(PLACEHOLDER_REGEX, (_match, index) => inlineCodeSnippets[Number(index)]);
2936
- return result;
2985
+
2986
+ // src/components/chat/hooks/use-copy-to-clipboard.ts
2987
+ var import_react19 = require("react");
2988
+
2989
+ // src/utils/clipboard.ts
2990
+ function copyToClipboard(text, options) {
2991
+ navigator.clipboard.writeText(text).then(
2992
+ () => options?.onSuccess?.(),
2993
+ (error) => options?.onFailure?.(error)
2994
+ );
2937
2995
  }
2938
2996
 
2939
- // src/components/blocks/text-block/text-block.tsx
2997
+ // src/components/chat/hooks/use-copy-to-clipboard.ts
2998
+ var RESET_DELAY_MS = 2e3;
2999
+ function useCopyToClipboard() {
3000
+ const [isCopied, setIsCopied] = (0, import_react19.useState)(false);
3001
+ const timeoutRef = (0, import_react19.useRef)(null);
3002
+ (0, import_react19.useEffect)(() => {
3003
+ return () => {
3004
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
3005
+ };
3006
+ }, []);
3007
+ const copy = (0, import_react19.useCallback)((text) => {
3008
+ copyToClipboard(text, {
3009
+ onSuccess: () => {
3010
+ setIsCopied(true);
3011
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
3012
+ timeoutRef.current = setTimeout(() => {
3013
+ setIsCopied(false);
3014
+ timeoutRef.current = null;
3015
+ }, RESET_DELAY_MS);
3016
+ }
3017
+ });
3018
+ }, []);
3019
+ return { isCopied, copy };
3020
+ }
3021
+
3022
+ // src/components/copy-button/copy-button.tsx
3023
+ var import_jsx_runtime30 = require("react/jsx-runtime");
3024
+ function CopyButton({
3025
+ text,
3026
+ copyLabel = "Copy",
3027
+ copiedLabel = "Copied",
3028
+ className
3029
+ }) {
3030
+ const { isCopied, copy } = useCopyToClipboard();
3031
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
3032
+ IconButton,
3033
+ {
3034
+ icon: isCopied ? IconCheck : IconCopy,
3035
+ onClick: () => copy(text),
3036
+ "aria-label": isCopied ? copiedLabel : copyLabel,
3037
+ className
3038
+ }
3039
+ );
3040
+ }
3041
+
3042
+ // src/components/blocks/markdown/markdown.tsx
2940
3043
  var import_react_markdown2 = __toESM(require("react-markdown"), 1);
2941
3044
  var import_remark_breaks2 = __toESM(require("remark-breaks"), 1);
2942
3045
  var import_remark_gfm2 = __toESM(require("remark-gfm"), 1);
@@ -2954,9 +3057,9 @@ var TableScroll = import_styled_components3.default.div`
2954
3057
  `;
2955
3058
 
2956
3059
  // src/components/blocks/scrollable-table/scrollable-table.tsx
2957
- var import_jsx_runtime28 = require("react/jsx-runtime");
3060
+ var import_jsx_runtime31 = require("react/jsx-runtime");
2958
3061
  function ScrollableTable({ node: _node, ...props }) {
2959
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TableContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("table", { ...props }) }) });
3062
+ 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 }) }) });
2960
3063
  }
2961
3064
 
2962
3065
  // src/components/blocks/text-block/sanitize.ts
@@ -3099,13 +3202,151 @@ var TextBlockWrapper = import_styled_components4.default.div`
3099
3202
  }
3100
3203
  `;
3101
3204
 
3102
- // src/components/blocks/text-block/text-block.tsx
3103
- var import_jsx_runtime29 = require("react/jsx-runtime");
3205
+ // src/components/blocks/markdown/markdown.tsx
3206
+ var import_jsx_runtime32 = require("react/jsx-runtime");
3104
3207
  var markdownComponents = {
3105
- table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ScrollableTable, { ...tableProps }))
3208
+ table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ScrollableTable, { ...tableProps }))
3209
+ };
3210
+ function Markdown({ children }) {
3211
+ 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) }) });
3212
+ }
3213
+
3214
+ // src/utils/markdown-to-plain-text.ts
3215
+ var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
3216
+ var PLACEHOLDER_SUFFIX = "\u200B\u200B";
3217
+ var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
3218
+ function stripInlineMarks(text) {
3219
+ return text.replace(/\*{3}(.+?)\*{3}/g, "$1").replace(/\*{2}(.+?)\*{2}/g, "$1").replace(/_{2}(.+?)_{2}/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1");
3220
+ }
3221
+ function markdownToPlainText(markdown) {
3222
+ if (!markdown) return "";
3223
+ const inlineCodeSnippets = [];
3224
+ let result = markdown.replace(/^<!--[\s\S]*?--!?>\n?/gm, "").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
3225
+ inlineCodeSnippets.push(code);
3226
+ return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
3227
+ }).replace(/^#{1,6}\s+/gm, "").replace(/^(?:---|\*\*\*|___)\s*$/gm, "");
3228
+ 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();
3229
+ result = result.replace(PLACEHOLDER_REGEX, (_match, index) => inlineCodeSnippets[Number(index)]);
3230
+ return result;
3231
+ }
3232
+
3233
+ // src/components/blocks/notification-draft-block/types.ts
3234
+ var notificationChannels = {
3235
+ /** Branded email — renders a From/subject header. */
3236
+ EMAIL: "email",
3237
+ /** Slack DM — renders as a chat bubble, no subject. */
3238
+ SLACK: "slack",
3239
+ /** Microsoft Teams DM — renders as a chat bubble, no subject. */
3240
+ TEAMS: "teams"
3106
3241
  };
3242
+
3243
+ // src/components/blocks/notification-draft-block/to-text.ts
3244
+ function notificationDraftToText(payload) {
3245
+ const { channel, subject, body } = payload;
3246
+ const text = markdownToPlainText(body);
3247
+ return channel === notificationChannels.EMAIL && subject ? `${subject}
3248
+
3249
+ ${text}` : text;
3250
+ }
3251
+
3252
+ // src/components/blocks/notification-draft-block/notification-draft-block.tsx
3253
+ var import_jsx_runtime33 = require("react/jsx-runtime");
3254
+ var CHIP_LIMIT = 3;
3255
+ var RECIPIENTS_MAX_HEIGHT = 320;
3256
+ function chipLabel(recipient) {
3257
+ return recipient.name ?? recipient.email ?? recipient.employeeId;
3258
+ }
3259
+ function channelCellText(recipient) {
3260
+ return recipient.fallback ? `${recipient.channelLabel} (fallback)` : recipient.channelLabel;
3261
+ }
3262
+ function FieldLabel({ children }) {
3263
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-geist-label-caption-medium tracking-wide text-brown-60", children });
3264
+ }
3265
+ function RecipientChips({ recipients }) {
3266
+ const shown = recipients.slice(0, CHIP_LIMIT);
3267
+ const overflow = recipients.length - shown.length;
3268
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
3269
+ shown.map((recipient) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Badge, { variant: "outline", children: chipLabel(recipient) }, recipient.employeeId)),
3270
+ overflow > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Badge, { variant: "subtle", children: `+${overflow}` })
3271
+ ] });
3272
+ }
3273
+ function RecipientsTable({ recipients }) {
3274
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
3275
+ DataTable,
3276
+ {
3277
+ maxBodyHeight: RECIPIENTS_MAX_HEIGHT,
3278
+ header: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TableRow, { className: "hover:bg-transparent", children: [
3279
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: "Name" }),
3280
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: "Email" }),
3281
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: "Channel" })
3282
+ ] }),
3283
+ children: recipients.map((recipient) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TableRow, { className: DATA_TABLE_ROW_CLASS, children: [
3284
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: recipient.name ?? "\u2014" }),
3285
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: recipient.email ?? "\u2014" }),
3286
+ /* @__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) }) })
3287
+ ] }, recipient.employeeId))
3288
+ }
3289
+ );
3290
+ }
3291
+ function NotificationDraftBlock({ block }) {
3292
+ const { channel, subject, body, recipients } = block.payload;
3293
+ const [detailsOpen, setDetailsOpen] = (0, import_react20.useState)(false);
3294
+ const showSubject = channel === notificationChannels.EMAIL && subject;
3295
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "overflow-hidden rounded-2xl border border-brown-30 bg-white", children: [
3296
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-3 border-b border-brown-30 px-4 py-3", children: [
3297
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
3298
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-2", children: [
3299
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-geist-body-s-semi-bold text-brown-100", children: "Notification draft" }),
3300
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Badge, { tone: "violet", variant: "subtle", size: "sm", className: "gap-1 py-1", children: [
3301
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Icon, { icon: IconFlask2Filled, size: 12 }),
3302
+ "Labs"
3303
+ ] })
3304
+ ] }),
3305
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CopyButton, { text: notificationDraftToText(block.payload), copyLabel: "Copy draft", copiedLabel: "Copied" })
3306
+ ] }),
3307
+ showSubject && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
3308
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldLabel, { children: "Title" }),
3309
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "text-geist-body-s-medium text-brown-100", children: subject })
3310
+ ] }),
3311
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-1", children: [
3312
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
3313
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldLabel, { children: `Recipients (${recipients.length})` }),
3314
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
3315
+ "button",
3316
+ {
3317
+ type: "button",
3318
+ "aria-expanded": detailsOpen,
3319
+ onClick: () => setDetailsOpen((open) => !open),
3320
+ className: "inline-flex items-center gap-1 text-geist-label-caption-medium text-brown-70 transition-colors hover:text-brown-100",
3321
+ children: [
3322
+ "Details",
3323
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Icon, { icon: IconChevronDown, size: 14, className: detailsOpen ? "rotate-180" : void 0 })
3324
+ ]
3325
+ }
3326
+ )
3327
+ ] }),
3328
+ detailsOpen ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(RecipientsTable, { recipients }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(RecipientChips, { recipients })
3329
+ ] })
3330
+ ] }),
3331
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Markdown, { children: body }) })
3332
+ ] });
3333
+ }
3334
+
3335
+ // src/components/blocks/block-services/notification-draft-block-service.ts
3336
+ var NotificationDraftBlockService = {
3337
+ type: blockTypes.NOTIFICATION_DRAFT,
3338
+ Component: NotificationDraftBlock,
3339
+ /**
3340
+ * Plain-text clipboard form of the drafted notification — shared with the in-block copy button
3341
+ * via {@link notificationDraftToText} so both copy the same text.
3342
+ */
3343
+ toClipboardText: (block) => notificationDraftToText(block.payload)
3344
+ };
3345
+
3346
+ // src/components/blocks/text-block/text-block.tsx
3347
+ var import_jsx_runtime34 = require("react/jsx-runtime");
3107
3348
  function TextBlock({ block }) {
3108
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TextBlockWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react_markdown2.default, { remarkPlugins: [import_remark_gfm2.default, import_remark_breaks2.default], components: markdownComponents, children: sanitize2(block.payload.text) }) });
3349
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Markdown, { children: block.payload.text });
3109
3350
  }
3110
3351
 
3111
3352
  // src/components/blocks/block-services/text-block-service.ts
@@ -3123,16 +3364,17 @@ var TextBlockService = {
3123
3364
  // src/components/blocks/block-services/index.ts
3124
3365
  var BlockServices = {
3125
3366
  [blockTypes.TEXT]: TextBlockService,
3126
- [blockTypes.ARTIFACT_REF]: ArtifactRefBlockService
3367
+ [blockTypes.ARTIFACT_REF]: ArtifactRefBlockService,
3368
+ [blockTypes.NOTIFICATION_DRAFT]: NotificationDraftBlockService
3127
3369
  };
3128
3370
 
3129
3371
  // src/components/blocks/block/block.tsx
3130
- var import_jsx_runtime30 = require("react/jsx-runtime");
3372
+ var import_jsx_runtime35 = require("react/jsx-runtime");
3131
3373
  function Block({ block }) {
3132
3374
  const service = BlockServices[block.type];
3133
3375
  if (!service) return null;
3134
3376
  const { Component } = service;
3135
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Component, { block });
3377
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Component, { block });
3136
3378
  }
3137
3379
 
3138
3380
  // src/components/chat/hooks/copy-message-text.ts
@@ -3150,55 +3392,19 @@ function copyMessageText(message) {
3150
3392
  }
3151
3393
 
3152
3394
  // src/components/chat/chat-message-actions/chat-message-actions.tsx
3153
- var import_react21 = require("react");
3395
+ var import_react22 = require("react");
3154
3396
 
3155
3397
  // src/components/chat/chat-context/chat-context.ts
3156
- var import_react19 = require("react");
3157
- var ChatContext = (0, import_react19.createContext)(null);
3398
+ var import_react21 = require("react");
3399
+ var ChatContext = (0, import_react21.createContext)(null);
3158
3400
  function useChatContext() {
3159
- const context = (0, import_react19.useContext)(ChatContext);
3401
+ const context = (0, import_react21.useContext)(ChatContext);
3160
3402
  if (!context) {
3161
3403
  throw new Error("useChatContext must be used within a Chat.Root component");
3162
3404
  }
3163
3405
  return context;
3164
3406
  }
3165
3407
 
3166
- // src/components/chat/hooks/use-copy-to-clipboard.ts
3167
- var import_react20 = require("react");
3168
-
3169
- // src/utils/clipboard.ts
3170
- function copyToClipboard(text, options) {
3171
- navigator.clipboard.writeText(text).then(
3172
- () => options?.onSuccess?.(),
3173
- (error) => options?.onFailure?.(error)
3174
- );
3175
- }
3176
-
3177
- // src/components/chat/hooks/use-copy-to-clipboard.ts
3178
- var RESET_DELAY_MS = 2e3;
3179
- function useCopyToClipboard() {
3180
- const [isCopied, setIsCopied] = (0, import_react20.useState)(false);
3181
- const timeoutRef = (0, import_react20.useRef)(null);
3182
- (0, import_react20.useEffect)(() => {
3183
- return () => {
3184
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
3185
- };
3186
- }, []);
3187
- const copy = (0, import_react20.useCallback)((text) => {
3188
- copyToClipboard(text, {
3189
- onSuccess: () => {
3190
- setIsCopied(true);
3191
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
3192
- timeoutRef.current = setTimeout(() => {
3193
- setIsCopied(false);
3194
- timeoutRef.current = null;
3195
- }, RESET_DELAY_MS);
3196
- }
3197
- });
3198
- }, []);
3199
- return { isCopied, copy };
3200
- }
3201
-
3202
3408
  // src/components/chat/constants.ts
3203
3409
  var MESSAGE_ROLE = {
3204
3410
  USER: "user",
@@ -3224,24 +3430,24 @@ var AnimatedAction = import_styled_components5.default.div`
3224
3430
  `;
3225
3431
 
3226
3432
  // src/components/chat/chat-message-actions/chat-message-actions.tsx
3227
- var import_jsx_runtime31 = require("react/jsx-runtime");
3433
+ var import_jsx_runtime36 = require("react/jsx-runtime");
3228
3434
  function ChatMessageActions({ className, messageId, content, role, isHelpful }) {
3229
3435
  const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
3230
3436
  const { isCopied, copy } = useCopyToClipboard();
3231
- const handleCopy = (0, import_react21.useCallback)(() => {
3437
+ const handleCopy = (0, import_react22.useCallback)(() => {
3232
3438
  copy(content);
3233
3439
  onCopyMessage?.(messageId);
3234
3440
  }, [content, messageId, copy, onCopyMessage]);
3235
- const handleThumbUp = (0, import_react21.useCallback)(() => {
3441
+ const handleThumbUp = (0, import_react22.useCallback)(() => {
3236
3442
  onThumbUpClick?.(messageId, isHelpful === true ? null : true);
3237
3443
  }, [messageId, isHelpful, onThumbUpClick]);
3238
- const handleThumbDown = (0, import_react21.useCallback)(() => {
3444
+ const handleThumbDown = (0, import_react22.useCallback)(() => {
3239
3445
  onThumbDownClick?.(messageId, isHelpful === false ? null : false);
3240
3446
  }, [messageId, isHelpful, onThumbDownClick]);
3241
3447
  const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
3242
3448
  const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
3243
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(ActionsContainer, { $role: role, className, children: [
3244
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
3449
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(ActionsContainer, { $role: role, className, children: [
3450
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3245
3451
  IconButton,
3246
3452
  {
3247
3453
  icon: isCopied ? IconCheck : IconCopy,
@@ -3249,7 +3455,7 @@ function ChatMessageActions({ className, messageId, content, role, isHelpful })
3249
3455
  "aria-label": isCopied ? "Copied" : "Copy message"
3250
3456
  }
3251
3457
  ),
3252
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
3458
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3253
3459
  IconButton,
3254
3460
  {
3255
3461
  icon: IconThumbUp,
@@ -3258,7 +3464,7 @@ function ChatMessageActions({ className, messageId, content, role, isHelpful })
3258
3464
  "aria-label": "Good response"
3259
3465
  }
3260
3466
  ) }),
3261
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
3467
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3262
3468
  IconButton,
3263
3469
  {
3264
3470
  icon: IconThumbDown,
@@ -3309,12 +3515,12 @@ var MessageBubble = import_styled_components6.default.div`
3309
3515
  `;
3310
3516
 
3311
3517
  // src/components/chat/chat-message/chat-message.tsx
3312
- var import_jsx_runtime32 = require("react/jsx-runtime");
3518
+ var import_jsx_runtime37 = require("react/jsx-runtime");
3313
3519
  function ChatMessage({ message }) {
3314
- const clipboardText = (0, import_react22.useMemo)(() => copyMessageText(message), [message]);
3315
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(MessageContainer, { $role: message.role, children: [
3316
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MessageBubble, { $role: message.role, "data-testid": "message-bubble", children: message.blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Block, { block }, index)) }),
3317
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3520
+ const clipboardText = (0, import_react23.useMemo)(() => copyMessageText(message), [message]);
3521
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(MessageContainer, { $role: message.role, children: [
3522
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MessageBubble, { $role: message.role, "data-testid": "message-bubble", children: message.blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Block, { block }, index)) }),
3523
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
3318
3524
  ChatMessageActions,
3319
3525
  {
3320
3526
  messageId: message.id,
@@ -3342,6 +3548,7 @@ function ChatMessage({ message }) {
3342
3548
  @tabler/icons-react/dist/esm/icons/IconArrowsMaximize.mjs:
3343
3549
  @tabler/icons-react/dist/esm/icons/IconArrowsMinimize.mjs:
3344
3550
  @tabler/icons-react/dist/esm/icons/IconCheck.mjs:
3551
+ @tabler/icons-react/dist/esm/icons/IconChevronDown.mjs:
3345
3552
  @tabler/icons-react/dist/esm/icons/IconChevronLeft.mjs:
3346
3553
  @tabler/icons-react/dist/esm/icons/IconChevronRight.mjs:
3347
3554
  @tabler/icons-react/dist/esm/icons/IconCopy.mjs:
@@ -3351,6 +3558,7 @@ function ChatMessage({ message }) {
3351
3558
  @tabler/icons-react/dist/esm/icons/IconPhoto.mjs:
3352
3559
  @tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
3353
3560
  @tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
3561
+ @tabler/icons-react/dist/esm/icons/IconFlask2Filled.mjs:
3354
3562
  @tabler/icons-react/dist/esm/tabler-icons-react.mjs:
3355
3563
  (**
3356
3564
  * @license @tabler/icons-react v3.37.1 - MIT