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