@shapesos/clay 0.16.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 +976 -69
- 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 +690 -85
- 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 +16 -36
- package/dist/chart.cjs.map +1 -1
- package/dist/chart.d.cts +3 -11
- package/dist/chart.d.ts +3 -11
- package/dist/chart.js +2 -2
- package/dist/chat.cjs +714 -109
- 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-UZKNSAAD.js → chunk-7MY4X4YL.js} +3 -3
- package/dist/chunk-BHHJOG5X.js +1 -0
- package/dist/{chunk-GAZRZZRF.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-U3IXCSV6.js → chunk-G4NXVFXU.js} +18 -40
- package/dist/chunk-G4NXVFXU.js.map +1 -0
- package/dist/{chunk-JAGNXEWK.js → chunk-GK4XW4BC.js} +2 -2
- package/dist/{chunk-4VE6ZXXW.js → chunk-MQP57DOP.js} +3 -3
- package/dist/{chunk-2YCBDSPK.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 +780 -167
- 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-2YCBDSPK.js.map +0 -1
- package/dist/chunk-RSRNSWJN.js +0 -1
- package/dist/chunk-U3IXCSV6.js.map +0 -1
- /package/dist/{chunk-UZKNSAAD.js.map → chunk-7MY4X4YL.js.map} +0 -0
- /package/dist/{chunk-RSRNSWJN.js.map → chunk-BHHJOG5X.js.map} +0 -0
- /package/dist/{chunk-GAZRZZRF.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-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");
|
|
@@ -1404,11 +1451,6 @@ function coerceNumericColumns(rows, numericKeys) {
|
|
|
1404
1451
|
|
|
1405
1452
|
// src/components/chart/bar-chart/bar-chart.tsx
|
|
1406
1453
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1407
|
-
var STACK_TOTAL_KEY = "__stackTotal";
|
|
1408
|
-
var VALUE_LABEL_HEADROOM = 20;
|
|
1409
|
-
function sumSeries(row, keys) {
|
|
1410
|
-
return keys.reduce((sum, key) => sum + (Number(row[key]) || 0), 0);
|
|
1411
|
-
}
|
|
1412
1454
|
function BarChart({
|
|
1413
1455
|
data,
|
|
1414
1456
|
xKey,
|
|
@@ -1423,7 +1465,6 @@ function BarChart({
|
|
|
1423
1465
|
showGrid = true,
|
|
1424
1466
|
showXAxis = true,
|
|
1425
1467
|
showYAxis = true,
|
|
1426
|
-
showValueLabels,
|
|
1427
1468
|
xAxisInterval = 0,
|
|
1428
1469
|
xAxisAngle,
|
|
1429
1470
|
xAxisTickFormatter
|
|
@@ -1434,24 +1475,14 @@ function BarChart({
|
|
|
1434
1475
|
[data, seriesKeys]
|
|
1435
1476
|
);
|
|
1436
1477
|
const resolvedShowLegend = showLegend ?? series.length > 1;
|
|
1437
|
-
const resolvedShowValueLabels = showValueLabels ?? true;
|
|
1438
|
-
const plotData = (0, import_react9.useMemo)(() => {
|
|
1439
|
-
if (!stacked || !resolvedShowValueLabels) return coercedData;
|
|
1440
|
-
return coercedData.map((row) => ({ ...row, [STACK_TOTAL_KEY]: sumSeries(row, seriesKeys) }));
|
|
1441
|
-
}, [coercedData, stacked, resolvedShowValueLabels, seriesKeys]);
|
|
1442
1478
|
const resolvedAngle = xAxisAngle ?? (coercedData.length >= 8 ? -30 : 0);
|
|
1443
1479
|
const resolvedTickFormatter = (0, import_react9.useMemo)(
|
|
1444
1480
|
() => xAxisTickFormatter ?? defaultBarTickFormatter(coercedData.length),
|
|
1445
1481
|
[xAxisTickFormatter, coercedData.length]
|
|
1446
1482
|
);
|
|
1447
1483
|
const angledLabelPad = resolvedAngle === 0 ? 0 : Math.min(Math.abs(resolvedAngle) * 0.7, 40);
|
|
1448
|
-
const
|
|
1449
|
-
|
|
1450
|
-
...CHART_MARGIN,
|
|
1451
|
-
top: CHART_MARGIN.top + valueLabelHeadroom,
|
|
1452
|
-
bottom: CHART_MARGIN.bottom + angledLabelPad
|
|
1453
|
-
};
|
|
1454
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChartContainer, { height, width, className, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_recharts2.BarChart, { data: plotData, margin: chartMargin, barCategoryGap: "22%", children: [
|
|
1484
|
+
const chartMargin = { ...CHART_MARGIN, bottom: CHART_MARGIN.bottom + angledLabelPad };
|
|
1485
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChartContainer, { height, width, className, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_recharts2.BarChart, { data: coercedData, margin: chartMargin, barCategoryGap: "22%", children: [
|
|
1455
1486
|
showGrid ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_recharts2.CartesianGrid, { ...CHART_GRID_PROPS }) : null,
|
|
1456
1487
|
showXAxis ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1457
1488
|
import_recharts2.XAxis,
|
|
@@ -1478,23 +1509,17 @@ function BarChart({
|
|
|
1478
1509
|
content: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChartLegendContent, { iconType: "square" })
|
|
1479
1510
|
}
|
|
1480
1511
|
) : null,
|
|
1481
|
-
series.map((s, i) =>
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
radius: barRadius(stacked, i, series.length),
|
|
1493
|
-
children: showLabel ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_recharts2.LabelList, { dataKey: labelDataKey, position: "top", style: CHART_VALUE_LABEL_STYLE }) : null
|
|
1494
|
-
},
|
|
1495
|
-
s.key
|
|
1496
|
-
);
|
|
1497
|
-
})
|
|
1512
|
+
series.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1513
|
+
import_recharts2.Bar,
|
|
1514
|
+
{
|
|
1515
|
+
dataKey: s.key,
|
|
1516
|
+
name: s.label,
|
|
1517
|
+
fill: colorForSeriesIndex(i, palette),
|
|
1518
|
+
stackId: stacked ? "default" : s.key,
|
|
1519
|
+
radius: barRadius(stacked, i, series.length)
|
|
1520
|
+
},
|
|
1521
|
+
s.key
|
|
1522
|
+
))
|
|
1498
1523
|
] }) });
|
|
1499
1524
|
}
|
|
1500
1525
|
function barRadius(stacked, seriesIndex, seriesCount) {
|
|
@@ -2029,8 +2054,13 @@ var ChartArtifactService = {
|
|
|
2029
2054
|
toClipboardText: chartArtifactToClipboardText
|
|
2030
2055
|
};
|
|
2031
2056
|
|
|
2032
|
-
// src/components/artifacts/
|
|
2033
|
-
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");
|
|
2034
2064
|
|
|
2035
2065
|
// src/components/ui/table.tsx
|
|
2036
2066
|
var React3 = __toESM(require("react"), 1);
|
|
@@ -2177,9 +2207,333 @@ function renderEmptyRow(colSpan, emptyMessage) {
|
|
|
2177
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 }) });
|
|
2178
2208
|
}
|
|
2179
2209
|
|
|
2180
|
-
// src/components/artifacts/
|
|
2181
|
-
|
|
2182
|
-
|
|
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
|
+
) });
|
|
2183
2537
|
}
|
|
2184
2538
|
|
|
2185
2539
|
// src/components/artifacts/table-artifact/validate.ts
|
|
@@ -2198,19 +2552,265 @@ function isValidTableColumn(column) {
|
|
|
2198
2552
|
return true;
|
|
2199
2553
|
}
|
|
2200
2554
|
|
|
2201
|
-
// src/components/artifacts/
|
|
2202
|
-
|
|
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");
|
|
2203
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";
|
|
2204
2804
|
var TABLE_MAX_BODY_HEIGHT = 480;
|
|
2205
2805
|
var MAX_SHIMMER_ROWS = 10;
|
|
2206
2806
|
function TableArtifact({ artifact, labels, callbacks }) {
|
|
2207
2807
|
const validConfig = isValidTableConfig(artifact.config);
|
|
2208
2808
|
const validColumns = validConfig ? artifact.config.columns : null;
|
|
2209
|
-
(0,
|
|
2809
|
+
(0, import_react18.useEffect)(() => {
|
|
2210
2810
|
if (validConfig) return;
|
|
2211
2811
|
console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
|
|
2212
2812
|
}, [validConfig]);
|
|
2213
|
-
const resolvedLabels = (0,
|
|
2813
|
+
const resolvedLabels = (0, import_react18.useMemo)(
|
|
2214
2814
|
() => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels ?? {} }),
|
|
2215
2815
|
[labels]
|
|
2216
2816
|
);
|
|
@@ -2222,10 +2822,10 @@ function TableArtifact({ artifact, labels, callbacks }) {
|
|
|
2222
2822
|
const onDownload = callbacks?.onDownload;
|
|
2223
2823
|
const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
|
|
2224
2824
|
if (!validConfig || !validColumns) {
|
|
2225
|
-
return /* @__PURE__ */ (0,
|
|
2226
|
-
/* @__PURE__ */ (0,
|
|
2227
|
-
artifact.title ? /* @__PURE__ */ (0,
|
|
2228
|
-
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)(
|
|
2229
2829
|
ArtifactDownloadButton,
|
|
2230
2830
|
{
|
|
2231
2831
|
href: presignedUrl,
|
|
@@ -2234,17 +2834,17 @@ function TableArtifact({ artifact, labels, callbacks }) {
|
|
|
2234
2834
|
}
|
|
2235
2835
|
) }) : null
|
|
2236
2836
|
] }),
|
|
2237
|
-
/* @__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 }) })
|
|
2238
2838
|
] });
|
|
2239
2839
|
}
|
|
2240
2840
|
return (
|
|
2241
2841
|
// The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
|
|
2242
2842
|
// Disable the outer overflow container so only one scroll context exists — this prevents
|
|
2243
2843
|
// double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
|
|
2244
|
-
/* @__PURE__ */ (0,
|
|
2245
|
-
/* @__PURE__ */ (0,
|
|
2246
|
-
artifact.title ? /* @__PURE__ */ (0,
|
|
2247
|
-
/* @__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)(
|
|
2248
2848
|
ArtifactDownloadButton,
|
|
2249
2849
|
{
|
|
2250
2850
|
href: presignedUrl ?? "",
|
|
@@ -2253,7 +2853,7 @@ function TableArtifact({ artifact, labels, callbacks }) {
|
|
|
2253
2853
|
}
|
|
2254
2854
|
) })
|
|
2255
2855
|
] }),
|
|
2256
|
-
/* @__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)(
|
|
2257
2857
|
TableArtifactContent,
|
|
2258
2858
|
{
|
|
2259
2859
|
columns: validColumns,
|
|
@@ -2284,7 +2884,8 @@ var TableArtifactService = {
|
|
|
2284
2884
|
// src/components/artifacts/artifact-services/index.ts
|
|
2285
2885
|
var ArtifactServices = {
|
|
2286
2886
|
[artifactTypes.TABLE]: TableArtifactService,
|
|
2287
|
-
[artifactTypes.CHART]: ChartArtifactService
|
|
2887
|
+
[artifactTypes.CHART]: ChartArtifactService,
|
|
2888
|
+
[artifactTypes.DECK]: DeckArtifactService
|
|
2288
2889
|
};
|
|
2289
2890
|
function artifactToClipboardText(artifact) {
|
|
2290
2891
|
const entry = ArtifactServices[artifact.type];
|
|
@@ -2295,13 +2896,13 @@ function artifactToClipboardText(artifact) {
|
|
|
2295
2896
|
}
|
|
2296
2897
|
|
|
2297
2898
|
// src/components/blocks/artifact-ref-block/artifact-ref-block.tsx
|
|
2298
|
-
var
|
|
2899
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2299
2900
|
function ArtifactRefBlock({ block }) {
|
|
2300
2901
|
const { artifact, labels, callbacks } = block.payload;
|
|
2301
2902
|
const entry = ArtifactServices[artifact.type];
|
|
2302
2903
|
if (!entry) return null;
|
|
2303
2904
|
const Component = entry.Component;
|
|
2304
|
-
return /* @__PURE__ */ (0,
|
|
2905
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Component, { artifact, labels, callbacks });
|
|
2305
2906
|
}
|
|
2306
2907
|
|
|
2307
2908
|
// src/components/blocks/block-services/artifact-ref-block-service.ts
|
|
@@ -2336,9 +2937,9 @@ function markdownToPlainText(markdown) {
|
|
|
2336
2937
|
}
|
|
2337
2938
|
|
|
2338
2939
|
// src/components/blocks/text-block/text-block.tsx
|
|
2339
|
-
var
|
|
2340
|
-
var
|
|
2341
|
-
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);
|
|
2342
2943
|
|
|
2343
2944
|
// src/components/blocks/scrollable-table/scrollable-table-styles.ts
|
|
2344
2945
|
var import_styled_components3 = __toESM(require("styled-components"), 1);
|
|
@@ -2353,13 +2954,13 @@ var TableScroll = import_styled_components3.default.div`
|
|
|
2353
2954
|
`;
|
|
2354
2955
|
|
|
2355
2956
|
// src/components/blocks/scrollable-table/scrollable-table.tsx
|
|
2356
|
-
var
|
|
2957
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
2357
2958
|
function ScrollableTable({ node: _node, ...props }) {
|
|
2358
|
-
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 }) }) });
|
|
2359
2960
|
}
|
|
2360
2961
|
|
|
2361
2962
|
// src/components/blocks/text-block/sanitize.ts
|
|
2362
|
-
function
|
|
2963
|
+
function sanitize2(text) {
|
|
2363
2964
|
return text.split("\n").filter((line) => {
|
|
2364
2965
|
const t = line.trim();
|
|
2365
2966
|
return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
|
|
@@ -2499,12 +3100,12 @@ var TextBlockWrapper = import_styled_components4.default.div`
|
|
|
2499
3100
|
`;
|
|
2500
3101
|
|
|
2501
3102
|
// src/components/blocks/text-block/text-block.tsx
|
|
2502
|
-
var
|
|
3103
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
2503
3104
|
var markdownComponents = {
|
|
2504
|
-
table: ((tableProps) => /* @__PURE__ */ (0,
|
|
3105
|
+
table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ScrollableTable, { ...tableProps }))
|
|
2505
3106
|
};
|
|
2506
3107
|
function TextBlock({ block }) {
|
|
2507
|
-
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) }) });
|
|
2508
3109
|
}
|
|
2509
3110
|
|
|
2510
3111
|
// src/components/blocks/block-services/text-block-service.ts
|
|
@@ -2526,12 +3127,12 @@ var BlockServices = {
|
|
|
2526
3127
|
};
|
|
2527
3128
|
|
|
2528
3129
|
// src/components/blocks/block/block.tsx
|
|
2529
|
-
var
|
|
3130
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
2530
3131
|
function Block({ block }) {
|
|
2531
3132
|
const service = BlockServices[block.type];
|
|
2532
3133
|
if (!service) return null;
|
|
2533
3134
|
const { Component } = service;
|
|
2534
|
-
return /* @__PURE__ */ (0,
|
|
3135
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Component, { block });
|
|
2535
3136
|
}
|
|
2536
3137
|
|
|
2537
3138
|
// src/components/chat/hooks/copy-message-text.ts
|
|
@@ -2549,13 +3150,13 @@ function copyMessageText(message) {
|
|
|
2549
3150
|
}
|
|
2550
3151
|
|
|
2551
3152
|
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
2552
|
-
var
|
|
3153
|
+
var import_react21 = require("react");
|
|
2553
3154
|
|
|
2554
3155
|
// src/components/chat/chat-context/chat-context.ts
|
|
2555
|
-
var
|
|
2556
|
-
var ChatContext = (0,
|
|
3156
|
+
var import_react19 = require("react");
|
|
3157
|
+
var ChatContext = (0, import_react19.createContext)(null);
|
|
2557
3158
|
function useChatContext() {
|
|
2558
|
-
const context = (0,
|
|
3159
|
+
const context = (0, import_react19.useContext)(ChatContext);
|
|
2559
3160
|
if (!context) {
|
|
2560
3161
|
throw new Error("useChatContext must be used within a Chat.Root component");
|
|
2561
3162
|
}
|
|
@@ -2563,7 +3164,7 @@ function useChatContext() {
|
|
|
2563
3164
|
}
|
|
2564
3165
|
|
|
2565
3166
|
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
2566
|
-
var
|
|
3167
|
+
var import_react20 = require("react");
|
|
2567
3168
|
|
|
2568
3169
|
// src/utils/clipboard.ts
|
|
2569
3170
|
function copyToClipboard(text, options) {
|
|
@@ -2576,14 +3177,14 @@ function copyToClipboard(text, options) {
|
|
|
2576
3177
|
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
2577
3178
|
var RESET_DELAY_MS = 2e3;
|
|
2578
3179
|
function useCopyToClipboard() {
|
|
2579
|
-
const [isCopied, setIsCopied] = (0,
|
|
2580
|
-
const timeoutRef = (0,
|
|
2581
|
-
(0,
|
|
3180
|
+
const [isCopied, setIsCopied] = (0, import_react20.useState)(false);
|
|
3181
|
+
const timeoutRef = (0, import_react20.useRef)(null);
|
|
3182
|
+
(0, import_react20.useEffect)(() => {
|
|
2582
3183
|
return () => {
|
|
2583
3184
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
2584
3185
|
};
|
|
2585
3186
|
}, []);
|
|
2586
|
-
const copy = (0,
|
|
3187
|
+
const copy = (0, import_react20.useCallback)((text) => {
|
|
2587
3188
|
copyToClipboard(text, {
|
|
2588
3189
|
onSuccess: () => {
|
|
2589
3190
|
setIsCopied(true);
|
|
@@ -2623,24 +3224,24 @@ var AnimatedAction = import_styled_components5.default.div`
|
|
|
2623
3224
|
`;
|
|
2624
3225
|
|
|
2625
3226
|
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
2626
|
-
var
|
|
3227
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
2627
3228
|
function ChatMessageActions({ className, messageId, content, role, isHelpful }) {
|
|
2628
3229
|
const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
|
|
2629
3230
|
const { isCopied, copy } = useCopyToClipboard();
|
|
2630
|
-
const handleCopy = (0,
|
|
3231
|
+
const handleCopy = (0, import_react21.useCallback)(() => {
|
|
2631
3232
|
copy(content);
|
|
2632
3233
|
onCopyMessage?.(messageId);
|
|
2633
3234
|
}, [content, messageId, copy, onCopyMessage]);
|
|
2634
|
-
const handleThumbUp = (0,
|
|
3235
|
+
const handleThumbUp = (0, import_react21.useCallback)(() => {
|
|
2635
3236
|
onThumbUpClick?.(messageId, isHelpful === true ? null : true);
|
|
2636
3237
|
}, [messageId, isHelpful, onThumbUpClick]);
|
|
2637
|
-
const handleThumbDown = (0,
|
|
3238
|
+
const handleThumbDown = (0, import_react21.useCallback)(() => {
|
|
2638
3239
|
onThumbDownClick?.(messageId, isHelpful === false ? null : false);
|
|
2639
3240
|
}, [messageId, isHelpful, onThumbDownClick]);
|
|
2640
3241
|
const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
|
|
2641
3242
|
const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
|
|
2642
|
-
return /* @__PURE__ */ (0,
|
|
2643
|
-
/* @__PURE__ */ (0,
|
|
3243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(ActionsContainer, { $role: role, className, children: [
|
|
3244
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2644
3245
|
IconButton,
|
|
2645
3246
|
{
|
|
2646
3247
|
icon: isCopied ? IconCheck : IconCopy,
|
|
@@ -2648,7 +3249,7 @@ function ChatMessageActions({ className, messageId, content, role, isHelpful })
|
|
|
2648
3249
|
"aria-label": isCopied ? "Copied" : "Copy message"
|
|
2649
3250
|
}
|
|
2650
3251
|
),
|
|
2651
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
3252
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2652
3253
|
IconButton,
|
|
2653
3254
|
{
|
|
2654
3255
|
icon: IconThumbUp,
|
|
@@ -2657,7 +3258,7 @@ function ChatMessageActions({ className, messageId, content, role, isHelpful })
|
|
|
2657
3258
|
"aria-label": "Good response"
|
|
2658
3259
|
}
|
|
2659
3260
|
) }),
|
|
2660
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
3261
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2661
3262
|
IconButton,
|
|
2662
3263
|
{
|
|
2663
3264
|
icon: IconThumbDown,
|
|
@@ -2708,12 +3309,12 @@ var MessageBubble = import_styled_components6.default.div`
|
|
|
2708
3309
|
`;
|
|
2709
3310
|
|
|
2710
3311
|
// src/components/chat/chat-message/chat-message.tsx
|
|
2711
|
-
var
|
|
3312
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
2712
3313
|
function ChatMessage({ message }) {
|
|
2713
|
-
const clipboardText = (0,
|
|
2714
|
-
return /* @__PURE__ */ (0,
|
|
2715
|
-
/* @__PURE__ */ (0,
|
|
2716
|
-
/* @__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)(
|
|
2717
3318
|
ChatMessageActions,
|
|
2718
3319
|
{
|
|
2719
3320
|
messageId: message.id,
|
|
@@ -2738,7 +3339,11 @@ function ChatMessage({ message }) {
|
|
|
2738
3339
|
@tabler/icons-react/dist/esm/defaultAttributes.mjs:
|
|
2739
3340
|
@tabler/icons-react/dist/esm/createReactComponent.mjs:
|
|
2740
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:
|
|
2741
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:
|
|
2742
3347
|
@tabler/icons-react/dist/esm/icons/IconCopy.mjs:
|
|
2743
3348
|
@tabler/icons-react/dist/esm/icons/IconDownload.mjs:
|
|
2744
3349
|
@tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs:
|