@shapesos/clay 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +1010 -60
- 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 +15 -6
- package/dist/badge.cjs +70 -0
- package/dist/badge.cjs.map +1 -0
- package/dist/badge.d.cts +28 -0
- package/dist/badge.d.ts +28 -0
- package/dist/badge.js +9 -0
- package/dist/blocks.cjs +981 -96
- package/dist/blocks.cjs.map +1 -1
- package/dist/blocks.css +1 -1
- package/dist/blocks.d.cts +15 -4
- package/dist/blocks.d.ts +15 -4
- package/dist/blocks.js +20 -8
- 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 +986 -151
- 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 +13 -8
- package/dist/{chunk-JGMN6W72.js → chunk-2X4KUXYP.js} +1 -1
- package/dist/chunk-BHHJOG5X.js +1 -0
- package/dist/{chunk-B4U37WIH.js → chunk-CFCLVJIO.js} +2 -2
- package/dist/chunk-CSTCTO3B.js +161 -0
- package/dist/chunk-CSTCTO3B.js.map +1 -0
- package/dist/{chunk-6YZ65KPW.js → chunk-DC5KYT2G.js} +669 -171
- package/dist/chunk-DC5KYT2G.js.map +1 -0
- package/dist/{chunk-PYDVANWI.js → chunk-E36VI2HA.js} +2 -2
- package/dist/chunk-EIAWZXE4.js +69 -0
- package/dist/chunk-EIAWZXE4.js.map +1 -0
- package/dist/chunk-EXRNGIQ2.js +41 -0
- package/dist/chunk-EXRNGIQ2.js.map +1 -0
- package/dist/{chunk-B6GAPZ2R.js → chunk-FCSYVF4Z.js} +12 -46
- package/dist/chunk-FCSYVF4Z.js.map +1 -0
- package/dist/{chunk-PUVZ2S3F.js → chunk-G4NXVFXU.js} +2 -2
- package/dist/{chunk-JAGNXEWK.js → chunk-GK4XW4BC.js} +2 -2
- package/dist/{chunk-4MZZH3WX.js → chunk-HU5W7CGE.js} +37 -2
- package/dist/chunk-HU5W7CGE.js.map +1 -0
- package/dist/chunk-JMHE3Q5K.js +406 -0
- package/dist/chunk-JMHE3Q5K.js.map +1 -0
- package/dist/{chunk-4VE6ZXXW.js → chunk-MQP57DOP.js} +3 -3
- 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/copy-button.cjs +439 -0
- package/dist/copy-button.cjs.map +1 -0
- package/dist/copy-button.d.cts +20 -0
- package/dist/copy-button.d.ts +20 -0
- package/dist/copy-button.js +12 -0
- package/dist/copy-button.js.map +1 -0
- package/dist/{dom-to-image-NATF3446.js → dom-to-image-QB7KMTAE.js} +3 -3
- package/dist/dom-to-image-QB7KMTAE.js.map +1 -0
- package/dist/icon.cjs +3 -1
- package/dist/icon.cjs.map +1 -1
- package/dist/icon.js +2 -2
- package/dist/index.cjs +1070 -209
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +42 -17
- package/dist/keyboard-shortcut.cjs +3 -1
- package/dist/keyboard-shortcut.cjs.map +1 -1
- package/dist/keyboard-shortcut.js +2 -2
- package/dist/table.cjs +40 -0
- package/dist/table.cjs.map +1 -1
- package/dist/table.d.cts +37 -2
- package/dist/table.d.ts +37 -2
- package/dist/table.js +11 -1
- 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-Bhg0_ES8.d.cts} +75 -3
- 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/dist/{types-D1b8v7EY.d.ts → types-orOQcI2z.d.ts} +75 -3
- package/package.json +11 -1
- package/dist/chunk-46ZYTBX5.js +0 -250
- package/dist/chunk-46ZYTBX5.js.map +0 -1
- package/dist/chunk-4MZZH3WX.js.map +0 -1
- package/dist/chunk-6YZ65KPW.js.map +0 -1
- package/dist/chunk-B6GAPZ2R.js.map +0 -1
- package/dist/chunk-RSRNSWJN.js +0 -1
- /package/dist/{chunk-RSRNSWJN.js.map → badge.js.map} +0 -0
- /package/dist/{chunk-JGMN6W72.js.map → chunk-2X4KUXYP.js.map} +0 -0
- /package/dist/{dom-to-image-NATF3446.js.map → chunk-BHHJOG5X.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/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,18 +278,20 @@ __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_react23 = require("react");
|
|
280
282
|
|
|
281
283
|
// src/components/blocks/types.ts
|
|
282
284
|
var blockTypes = {
|
|
283
285
|
TEXT: "TEXT",
|
|
284
|
-
ARTIFACT_REF: "ARTIFACT_REF"
|
|
286
|
+
ARTIFACT_REF: "ARTIFACT_REF",
|
|
287
|
+
NOTIFICATION_DRAFT: "NOTIFICATION_DRAFT"
|
|
285
288
|
};
|
|
286
289
|
|
|
287
290
|
// src/components/artifacts/artifact-base.ts
|
|
288
291
|
var artifactTypes = {
|
|
289
292
|
TABLE: "TABLE",
|
|
290
|
-
CHART: "CHART"
|
|
293
|
+
CHART: "CHART",
|
|
294
|
+
DECK: "DECK"
|
|
291
295
|
};
|
|
292
296
|
|
|
293
297
|
// src/components/artifacts/chart-artifact/types.ts
|
|
@@ -312,6 +316,34 @@ var DEFAULT_TABLE_ARTIFACT_LABELS = {
|
|
|
312
316
|
empty: "No rows to display."
|
|
313
317
|
};
|
|
314
318
|
|
|
319
|
+
// src/components/artifacts/deck-artifact/types.ts
|
|
320
|
+
var deckBlockTypes = {
|
|
321
|
+
TEXT: "TEXT",
|
|
322
|
+
CHART: "CHART",
|
|
323
|
+
TABLE: "TABLE"
|
|
324
|
+
};
|
|
325
|
+
var deckSlideKinds = {
|
|
326
|
+
TITLE: "TITLE",
|
|
327
|
+
AGENDA: "AGENDA",
|
|
328
|
+
SECTION: "SECTION",
|
|
329
|
+
CONTENT: "CONTENT",
|
|
330
|
+
CLOSING: "CLOSING"
|
|
331
|
+
};
|
|
332
|
+
var DEFAULT_DECK_ARTIFACT_LABELS = {
|
|
333
|
+
previous: "Previous slide",
|
|
334
|
+
next: "Next slide",
|
|
335
|
+
position: "Slide {current} of {total}",
|
|
336
|
+
download: "Download",
|
|
337
|
+
unavailable: "Deck content is unavailable.",
|
|
338
|
+
enterFullscreen: "Fullscreen",
|
|
339
|
+
exitFullscreen: "Exit fullscreen",
|
|
340
|
+
thankYou: "Thank you",
|
|
341
|
+
questions: "Questions?",
|
|
342
|
+
agenda: "Agenda",
|
|
343
|
+
chart: DEFAULT_CHART_ARTIFACT_LABELS,
|
|
344
|
+
table: DEFAULT_TABLE_ARTIFACT_LABELS
|
|
345
|
+
};
|
|
346
|
+
|
|
315
347
|
// src/components/artifacts/chart-artifact/chart-artifact.tsx
|
|
316
348
|
var import_react13 = require("react");
|
|
317
349
|
|
|
@@ -404,37 +436,61 @@ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
|
|
|
404
436
|
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
437
|
var IconAlertCircle = createReactComponent("outline", "alert-circle", "AlertCircle", __iconNode);
|
|
406
438
|
|
|
439
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconArrowsMaximize.mjs
|
|
440
|
+
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" }]];
|
|
441
|
+
var IconArrowsMaximize = createReactComponent("outline", "arrows-maximize", "ArrowsMaximize", __iconNode2);
|
|
442
|
+
|
|
443
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconArrowsMinimize.mjs
|
|
444
|
+
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" }]];
|
|
445
|
+
var IconArrowsMinimize = createReactComponent("outline", "arrows-minimize", "ArrowsMinimize", __iconNode3);
|
|
446
|
+
|
|
407
447
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
|
|
408
|
-
var
|
|
409
|
-
var IconCheck = createReactComponent("outline", "check", "Check",
|
|
448
|
+
var __iconNode4 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
|
|
449
|
+
var IconCheck = createReactComponent("outline", "check", "Check", __iconNode4);
|
|
450
|
+
|
|
451
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconChevronDown.mjs
|
|
452
|
+
var __iconNode5 = [["path", { "d": "M6 9l6 6l6 -6", "key": "svg-0" }]];
|
|
453
|
+
var IconChevronDown = createReactComponent("outline", "chevron-down", "ChevronDown", __iconNode5);
|
|
454
|
+
|
|
455
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconChevronLeft.mjs
|
|
456
|
+
var __iconNode6 = [["path", { "d": "M15 6l-6 6l6 6", "key": "svg-0" }]];
|
|
457
|
+
var IconChevronLeft = createReactComponent("outline", "chevron-left", "ChevronLeft", __iconNode6);
|
|
458
|
+
|
|
459
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconChevronRight.mjs
|
|
460
|
+
var __iconNode7 = [["path", { "d": "M9 6l6 6l-6 6", "key": "svg-0" }]];
|
|
461
|
+
var IconChevronRight = createReactComponent("outline", "chevron-right", "ChevronRight", __iconNode7);
|
|
410
462
|
|
|
411
463
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
|
|
412
|
-
var
|
|
413
|
-
var IconCopy = createReactComponent("outline", "copy", "Copy",
|
|
464
|
+
var __iconNode8 = [["path", { "d": "M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666", "key": "svg-0" }], ["path", { "d": "M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1", "key": "svg-1" }]];
|
|
465
|
+
var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode8);
|
|
414
466
|
|
|
415
467
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconDownload.mjs
|
|
416
|
-
var
|
|
417
|
-
var IconDownload = createReactComponent("outline", "download", "Download",
|
|
468
|
+
var __iconNode9 = [["path", { "d": "M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2", "key": "svg-0" }], ["path", { "d": "M7 11l5 5l5 -5", "key": "svg-1" }], ["path", { "d": "M12 4l0 12", "key": "svg-2" }]];
|
|
469
|
+
var IconDownload = createReactComponent("outline", "download", "Download", __iconNode9);
|
|
418
470
|
|
|
419
471
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs
|
|
420
|
-
var
|
|
421
|
-
var IconFileSpreadsheet = createReactComponent("outline", "file-spreadsheet", "FileSpreadsheet",
|
|
472
|
+
var __iconNode10 = [["path", { "d": "M14 3v4a1 1 0 0 0 1 1h4", "key": "svg-0" }], ["path", { "d": "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2", "key": "svg-1" }], ["path", { "d": "M8 11h8v7h-8l0 -7", "key": "svg-2" }], ["path", { "d": "M8 15h8", "key": "svg-3" }], ["path", { "d": "M11 11v7", "key": "svg-4" }]];
|
|
473
|
+
var IconFileSpreadsheet = createReactComponent("outline", "file-spreadsheet", "FileSpreadsheet", __iconNode10);
|
|
422
474
|
|
|
423
475
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconLoader2.mjs
|
|
424
|
-
var
|
|
425
|
-
var IconLoader2 = createReactComponent("outline", "loader-2", "Loader2",
|
|
476
|
+
var __iconNode11 = [["path", { "d": "M12 3a9 9 0 1 0 9 9", "key": "svg-0" }]];
|
|
477
|
+
var IconLoader2 = createReactComponent("outline", "loader-2", "Loader2", __iconNode11);
|
|
426
478
|
|
|
427
479
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconPhoto.mjs
|
|
428
|
-
var
|
|
429
|
-
var IconPhoto = createReactComponent("outline", "photo", "Photo",
|
|
480
|
+
var __iconNode12 = [["path", { "d": "M15 8h.01", "key": "svg-0" }], ["path", { "d": "M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12", "key": "svg-1" }], ["path", { "d": "M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5", "key": "svg-2" }], ["path", { "d": "M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3", "key": "svg-3" }]];
|
|
481
|
+
var IconPhoto = createReactComponent("outline", "photo", "Photo", __iconNode12);
|
|
430
482
|
|
|
431
483
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
|
|
432
|
-
var
|
|
433
|
-
var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown",
|
|
484
|
+
var __iconNode13 = [["path", { "d": "M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3", "key": "svg-0" }]];
|
|
485
|
+
var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode13);
|
|
434
486
|
|
|
435
487
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
|
|
436
|
-
var
|
|
437
|
-
var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp",
|
|
488
|
+
var __iconNode14 = [["path", { "d": "M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3", "key": "svg-0" }]];
|
|
489
|
+
var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode14);
|
|
490
|
+
|
|
491
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconFlask2Filled.mjs
|
|
492
|
+
var __iconNode15 = [["path", { "d": "M15 2a1 1 0 0 1 0 2v5.674l.062 .03a7 7 0 0 1 3.85 5.174l.037 .262a7 7 0 0 1 -3.078 6.693a1 1 0 0 1 -.553 .167h-6.635a1 1 0 0 1 -.552 -.166a7 7 0 0 1 .807 -12.134l.062 -.028v-5.672a1 1 0 1 1 0 -2h6zm-2 2h-2v6.34a1 1 0 0 1 -.551 .894l-.116 .049a5 5 0 0 0 -2.92 2.717h9.172a5 5 0 0 0 -2.918 -2.715a1 1 0 0 1 -.667 -.943v-6.342z", "key": "svg-0" }]];
|
|
493
|
+
var IconFlask2Filled = createReactComponent("filled", "flask-2-filled", "Flask2Filled", __iconNode15);
|
|
438
494
|
|
|
439
495
|
// src/components/artifacts/artifact-copy-as-image-button/artifact-copy-as-image-button.tsx
|
|
440
496
|
var import_react6 = require("react");
|
|
@@ -2007,8 +2063,13 @@ var ChartArtifactService = {
|
|
|
2007
2063
|
toClipboardText: chartArtifactToClipboardText
|
|
2008
2064
|
};
|
|
2009
2065
|
|
|
2010
|
-
// src/components/artifacts/
|
|
2011
|
-
var
|
|
2066
|
+
// src/components/artifacts/deck-artifact/deck-artifact.tsx
|
|
2067
|
+
var import_react17 = require("react");
|
|
2068
|
+
var import_react_dom = require("react-dom");
|
|
2069
|
+
init_capture_exclude_attribute();
|
|
2070
|
+
|
|
2071
|
+
// src/components/artifacts/deck-artifact/deck-artifact-content.tsx
|
|
2072
|
+
var import_react16 = require("react");
|
|
2012
2073
|
|
|
2013
2074
|
// src/components/ui/table.tsx
|
|
2014
2075
|
var React3 = __toESM(require("react"), 1);
|
|
@@ -2087,6 +2148,36 @@ function useScrollShadow() {
|
|
|
2087
2148
|
return { targetRef, isScrolled };
|
|
2088
2149
|
}
|
|
2089
2150
|
|
|
2151
|
+
// src/components/table/data-table.tsx
|
|
2152
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2153
|
+
var DATA_TABLE_HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
|
|
2154
|
+
var DATA_TABLE_CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
|
|
2155
|
+
var DATA_TABLE_ROW_CLASS = "border-b-brown-30 bg-background/70 hover:bg-secondary";
|
|
2156
|
+
var DATA_TABLE_SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
|
|
2157
|
+
function DataTable({ header, children, maxBodyHeight, className }) {
|
|
2158
|
+
const { targetRef, isScrolled } = useScrollShadow();
|
|
2159
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2160
|
+
"div",
|
|
2161
|
+
{
|
|
2162
|
+
ref: targetRef,
|
|
2163
|
+
className: cn("overscroll-none", className),
|
|
2164
|
+
style: maxBodyHeight !== void 0 ? { maxHeight: maxBodyHeight, overflowY: "auto" } : void 0,
|
|
2165
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Table, { containerClassName: "overflow-visible", children: [
|
|
2166
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2167
|
+
TableHeader,
|
|
2168
|
+
{
|
|
2169
|
+
"data-scrolled": isScrolled ? "true" : void 0,
|
|
2170
|
+
className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
|
|
2171
|
+
style: isScrolled ? { boxShadow: DATA_TABLE_SCROLL_SHADOW } : void 0,
|
|
2172
|
+
children: header
|
|
2173
|
+
}
|
|
2174
|
+
),
|
|
2175
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableBody, { children })
|
|
2176
|
+
] })
|
|
2177
|
+
}
|
|
2178
|
+
);
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2090
2181
|
// src/components/artifacts/table-artifact/table-artifact-content.constants.ts
|
|
2091
2182
|
var TABLE_STATUS = {
|
|
2092
2183
|
LOADING: "loading",
|
|
@@ -2099,14 +2190,10 @@ var TABLE_STATUS = {
|
|
|
2099
2190
|
function formatCell(row, column) {
|
|
2100
2191
|
return row[column.key] ?? "";
|
|
2101
2192
|
}
|
|
2102
|
-
var
|
|
2103
|
-
var CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
|
|
2104
|
-
var ROW_CLASSES = "border-b-brown-30 bg-background/70 hover:bg-secondary";
|
|
2105
|
-
var DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;
|
|
2106
|
-
var SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
|
|
2193
|
+
var DATA_ROW_CLASSES = `${DATA_TABLE_ROW_CLASS} animate-in fade-in duration-300`;
|
|
2107
2194
|
|
|
2108
2195
|
// src/components/artifacts/table-artifact/table-artifact-content.tsx
|
|
2109
|
-
var
|
|
2196
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2110
2197
|
function TableArtifactContent({
|
|
2111
2198
|
columns,
|
|
2112
2199
|
data,
|
|
@@ -2116,48 +2203,367 @@ function TableArtifactContent({
|
|
|
2116
2203
|
labels
|
|
2117
2204
|
}) {
|
|
2118
2205
|
if (data.status === TABLE_STATUS.ERROR) {
|
|
2119
|
-
return /* @__PURE__ */ (0,
|
|
2206
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "error", children: labels.loadError });
|
|
2120
2207
|
}
|
|
2121
2208
|
if (data.status === TABLE_STATUS.UNAVAILABLE) {
|
|
2122
|
-
return /* @__PURE__ */ (0,
|
|
2209
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
|
|
2123
2210
|
}
|
|
2124
2211
|
if (data.status === TABLE_STATUS.LOADING) {
|
|
2125
2212
|
if (typeof knownRowCount === "number" && knownRowCount > 0) {
|
|
2126
2213
|
const shimmerCount = Math.min(knownRowCount, maxShimmerRows);
|
|
2127
|
-
return /* @__PURE__ */ (0,
|
|
2214
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
|
|
2128
2215
|
}
|
|
2129
|
-
return /* @__PURE__ */ (0,
|
|
2216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StatusMessage, { $tone: "info", children: labels.loading });
|
|
2130
2217
|
}
|
|
2131
|
-
return /* @__PURE__ */ (0,
|
|
2218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ArtifactTable, { columns, maxBodyHeight, children: data.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data.rows) });
|
|
2132
2219
|
}
|
|
2133
2220
|
function ArtifactTable({ columns, maxBodyHeight, children }) {
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2221
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2222
|
+
DataTable,
|
|
2223
|
+
{
|
|
2224
|
+
maxBodyHeight,
|
|
2225
|
+
header: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: "hover:bg-transparent", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: column.label }, column.key)) }),
|
|
2226
|
+
children
|
|
2227
|
+
}
|
|
2228
|
+
);
|
|
2229
|
+
}
|
|
2230
|
+
function renderShimmerRows(columns, count) {
|
|
2231
|
+
return Array.from({ length: count }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: DATA_TABLE_ROW_CLASS, "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20" }) }, column.key)) }, `shimmer-${index}`));
|
|
2232
|
+
}
|
|
2233
|
+
function renderDataRows(columns, rows) {
|
|
2234
|
+
return rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: DATA_ROW_CLASSES, children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: formatCell(row, column) }, column.key)) }, index));
|
|
2235
|
+
}
|
|
2236
|
+
function renderEmptyRow(colSpan, emptyMessage) {
|
|
2237
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TableCell, { colSpan, className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) });
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
// src/components/artifacts/deck-artifact/deck-markdown.tsx
|
|
2241
|
+
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
2242
|
+
var import_remark_breaks = __toESM(require("remark-breaks"), 1);
|
|
2243
|
+
var import_remark_gfm = __toESM(require("remark-gfm"), 1);
|
|
2244
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2245
|
+
function sanitize(text) {
|
|
2246
|
+
return text.split("\n").filter((line) => {
|
|
2247
|
+
const t = line.trim();
|
|
2248
|
+
return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
|
|
2249
|
+
}).join("\n");
|
|
2250
|
+
}
|
|
2251
|
+
var MARKDOWN_COMPONENTS = {
|
|
2252
|
+
h1: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: "text-[30px] font-semibold leading-tight text-foreground mb-3", ...props }),
|
|
2253
|
+
h2: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "text-[26px] font-semibold leading-tight text-foreground mb-2", ...props }),
|
|
2254
|
+
h3: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
|
|
2255
|
+
h4: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h4", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
|
|
2256
|
+
h5: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h5", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
|
|
2257
|
+
h6: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h6", { className: "text-[24px] font-semibold leading-tight text-foreground mb-2", ...props }),
|
|
2258
|
+
p: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[22px] leading-relaxed text-foreground my-2", ...props }),
|
|
2259
|
+
ul: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("ul", { className: "list-disc pl-7 text-[22px] leading-relaxed text-foreground my-2", ...props }),
|
|
2260
|
+
ol: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("ol", { className: "list-decimal pl-7 text-[22px] leading-relaxed text-foreground my-2", ...props }),
|
|
2261
|
+
// react-markdown injects list metadata (`ordered` / `index` / `checked`) that must not leak to the DOM.
|
|
2262
|
+
li: ({ node: _node, ordered: _ordered, index: _index, checked: _checked, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("li", { className: "my-1", ...props }),
|
|
2263
|
+
strong: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("strong", { className: "font-semibold", ...props }),
|
|
2264
|
+
em: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("em", { className: "italic", ...props }),
|
|
2265
|
+
// Gate `<img src>` against an http(s) allowlist. react-markdown v8 percent-encodes the URL but
|
|
2266
|
+
// does NOT protocol-filter image src (unlike link href), so an LLM-authored
|
|
2267
|
+
// `` / `` or a tracking-pixel `` would otherwise render
|
|
2268
|
+
// with the raw URL. Unsafe src → render nothing.
|
|
2269
|
+
img: ({ node: _node, src, ...props }) => typeof src === "string" && isSafeDownloadUrl(src) ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src, className: "max-w-full", ...props }) : null,
|
|
2270
|
+
a: ({ node: _node, ...props }) => (
|
|
2271
|
+
// `rel` is forced AFTER `{...props}` so it can't be overridden — if a consumer ever adds
|
|
2272
|
+
// `linkTarget="_blank"`, LLM-authored links still can't reach `window.opener`.
|
|
2273
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("a", { className: "underline underline-offset-2", ...props, rel: "noopener noreferrer" })
|
|
2274
|
+
),
|
|
2275
|
+
// react-markdown passes `inline` to distinguish inline code from fenced blocks — strip it from the DOM.
|
|
2276
|
+
code: ({ node: _node, inline: _inline, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("code", { className: "rounded bg-muted px-1.5 py-0.5 font-mono text-[18px]", ...props }),
|
|
2277
|
+
blockquote: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("blockquote", { className: "border-l-2 border-brown-alpha-12 pl-4 text-[22px] text-muted-foreground", ...props }),
|
|
2278
|
+
hr: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("hr", { className: "my-4 border-brown-alpha-12", ...props }),
|
|
2279
|
+
table: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("table", { className: "w-full border-collapse text-[20px]", ...props }) }),
|
|
2280
|
+
// react-markdown passes `isHeader` to cell renderers — strip it so it never reaches the DOM.
|
|
2281
|
+
th: ({ node: _node, isHeader: _isHeader, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "border-b border-brown-alpha-12 px-3 py-1.5 text-left font-medium", ...props }),
|
|
2282
|
+
td: ({ node: _node, isHeader: _isHeader, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "border-b border-brown-alpha-12 px-3 py-1.5", ...props })
|
|
2283
|
+
};
|
|
2284
|
+
function DeckMarkdown({ markdown }) {
|
|
2285
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: MARKDOWN_COMPONENTS, children: sanitize(markdown) });
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
// src/components/artifacts/deck-artifact/slide-renderers.tsx
|
|
2289
|
+
var import_react15 = require("react");
|
|
2290
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2291
|
+
function safeLogoUrl(meta) {
|
|
2292
|
+
return meta?.logoUrl && isSafeDownloadUrl(meta.logoUrl) ? meta.logoUrl : null;
|
|
2293
|
+
}
|
|
2294
|
+
var DESIGN_W = 1280;
|
|
2295
|
+
var DESIGN_H = 720;
|
|
2296
|
+
var EYEBROW_H = 84;
|
|
2297
|
+
var CANVAS_LOGO_MAX_H = 48;
|
|
2298
|
+
var ACCENT_FONT = { fontFamily: `"${fontFamilies.CRIMSON_PRO}", serif`, fontStyle: "italic" };
|
|
2299
|
+
function SlideFrame({ meta, children, accent = false, bare = false }) {
|
|
2300
|
+
const frameRef = (0, import_react15.useRef)(null);
|
|
2301
|
+
const [scale, setScale] = (0, import_react15.useState)(null);
|
|
2302
|
+
(0, import_react15.useLayoutEffect)(() => {
|
|
2303
|
+
const el = frameRef.current;
|
|
2304
|
+
if (!el) return;
|
|
2305
|
+
const apply = (width) => {
|
|
2306
|
+
if (width > 0) setScale(width / DESIGN_W);
|
|
2307
|
+
};
|
|
2308
|
+
apply(el.clientWidth);
|
|
2309
|
+
const ro = new ResizeObserver((entries) => apply(entries[0]?.contentRect.width ?? 0));
|
|
2310
|
+
ro.observe(el);
|
|
2311
|
+
return () => ro.disconnect();
|
|
2312
|
+
}, []);
|
|
2313
|
+
const bg = accent ? "bg-indigo-600" : "bg-deck-canvas";
|
|
2314
|
+
const eyebrowColor = accent ? "text-white/70" : "text-brown-60";
|
|
2315
|
+
const borderColor = accent ? "border-white/20" : "border-brown-alpha-12";
|
|
2316
|
+
const logoSrc = safeLogoUrl(meta);
|
|
2317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: frameRef, className: `relative aspect-[16/9] w-full overflow-hidden rounded-lg ${bg}`, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2318
|
+
"div",
|
|
2319
|
+
{
|
|
2320
|
+
className: "absolute left-0 top-0 origin-top-left",
|
|
2321
|
+
style: {
|
|
2322
|
+
width: DESIGN_W,
|
|
2323
|
+
height: DESIGN_H,
|
|
2324
|
+
transform: `scale(${scale ?? 0})`,
|
|
2325
|
+
visibility: scale === null ? "hidden" : "visible"
|
|
2326
|
+
},
|
|
2327
|
+
children: [
|
|
2328
|
+
!bare ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2329
|
+
"div",
|
|
2330
|
+
{
|
|
2331
|
+
className: `absolute inset-x-0 top-0 flex items-center justify-between border-b px-16 ${borderColor}`,
|
|
2332
|
+
style: { height: EYEBROW_H },
|
|
2333
|
+
children: [
|
|
2334
|
+
meta?.eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: eyebrowColor, style: { ...ACCENT_FONT, fontSize: 22 }, children: meta.eyebrow }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", {}),
|
|
2335
|
+
logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: logoSrc, alt: "", className: "object-contain", style: { maxHeight: CANVAS_LOGO_MAX_H } }) : null
|
|
2336
|
+
]
|
|
2337
|
+
}
|
|
2338
|
+
) : null,
|
|
2339
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute inset-x-0 bottom-0 overflow-hidden", style: { top: bare ? 0 : EYEBROW_H }, children })
|
|
2340
|
+
]
|
|
2341
|
+
}
|
|
2342
|
+
) });
|
|
2343
|
+
}
|
|
2344
|
+
function TitleSlide({ slide, meta }) {
|
|
2345
|
+
const logoSrc = safeLogoUrl(meta);
|
|
2346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, bare: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full flex-col justify-center px-24 py-16", children: [
|
|
2347
|
+
logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2348
|
+
"img",
|
|
2138
2349
|
{
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2350
|
+
src: logoSrc,
|
|
2351
|
+
alt: "",
|
|
2352
|
+
className: "mb-16 object-contain object-left",
|
|
2353
|
+
style: { maxHeight: 56, maxWidth: 380 }
|
|
2354
|
+
}
|
|
2355
|
+
) : null,
|
|
2356
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2357
|
+
"h1",
|
|
2358
|
+
{
|
|
2359
|
+
className: "font-bold tracking-tight text-brown-100",
|
|
2360
|
+
style: { fontSize: 92, lineHeight: 1.04, maxWidth: 1060 },
|
|
2361
|
+
children: slide.title
|
|
2143
2362
|
}
|
|
2144
2363
|
),
|
|
2145
|
-
/* @__PURE__ */ (0,
|
|
2364
|
+
slide.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-7 text-brown-70", style: { ...ACCENT_FONT, fontSize: 34 }, children: slide.subtitle }) : null,
|
|
2365
|
+
slide.description ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-4 leading-relaxed text-brown-70", style: { fontSize: 24, maxWidth: 880 }, children: slide.description }) : null,
|
|
2366
|
+
meta?.date ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-10 text-brown-70", style: { ...ACCENT_FONT, fontSize: 30 }, children: meta.date }) : null
|
|
2146
2367
|
] }) });
|
|
2147
2368
|
}
|
|
2148
|
-
function
|
|
2149
|
-
|
|
2369
|
+
function AgendaSlide({ slide, meta, labels }) {
|
|
2370
|
+
const items = slide.items ?? [];
|
|
2371
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "h-full px-24 py-14", children: [
|
|
2372
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "mb-10 font-bold text-brown-90", style: { fontSize: 40 }, children: slide.title || labels.agenda }),
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex flex-col", children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-baseline gap-6 border-b border-brown-alpha-12 py-5", children: [
|
|
2374
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "shrink-0 text-indigo-600", style: { ...ACCENT_FONT, fontSize: 28, width: 64 }, children: String(i + 1).padStart(2, "0") }),
|
|
2375
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-brown-90", style: { fontSize: 28 }, children: item })
|
|
2376
|
+
] }, i)) })
|
|
2377
|
+
] }) });
|
|
2150
2378
|
}
|
|
2151
|
-
function
|
|
2152
|
-
return
|
|
2379
|
+
function SectionSlide({ slide, meta }) {
|
|
2380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, accent: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full flex-col justify-center gap-6 px-24", children: [
|
|
2381
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { className: "font-bold text-white", style: { fontSize: 72, lineHeight: 1.05, maxWidth: 940 }, children: slide.title }),
|
|
2382
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-2 bg-white/50", style: { width: 96, height: 5 } })
|
|
2383
|
+
] }) });
|
|
2153
2384
|
}
|
|
2154
|
-
function
|
|
2155
|
-
return /* @__PURE__ */ (0,
|
|
2385
|
+
function ClosingSlide({ meta, labels }) {
|
|
2386
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-full flex-col items-center justify-center gap-6 px-24 text-center", children: [
|
|
2387
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h1", { className: "font-bold text-brown-100", style: { fontSize: 72 }, children: labels.thankYou }),
|
|
2388
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-indigo-600", style: { ...ACCENT_FONT, fontSize: 36 }, children: labels.questions })
|
|
2389
|
+
] }) });
|
|
2156
2390
|
}
|
|
2157
2391
|
|
|
2158
|
-
// src/components/artifacts/
|
|
2159
|
-
|
|
2160
|
-
|
|
2392
|
+
// src/components/artifacts/deck-artifact/deck-artifact-content.tsx
|
|
2393
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2394
|
+
var TABLE_BLOCK_MAX_SHIMMER_ROWS = 10;
|
|
2395
|
+
var TABLE_CHROME_RESERVE = 56;
|
|
2396
|
+
var VISUAL_FALLBACK_HEIGHT = 360;
|
|
2397
|
+
function DeckArtifactContent({
|
|
2398
|
+
slides,
|
|
2399
|
+
labels,
|
|
2400
|
+
onNavigate,
|
|
2401
|
+
meta,
|
|
2402
|
+
onDark = false,
|
|
2403
|
+
currentSlide,
|
|
2404
|
+
onSlideChange
|
|
2405
|
+
}) {
|
|
2406
|
+
const navBtnClass = onDark ? "[&_svg]:!text-white hover:!bg-white/20 disabled:opacity-40" : void 0;
|
|
2407
|
+
const navBtnSize = onDark ? "medium" : "small";
|
|
2408
|
+
const isControlled = currentSlide !== void 0;
|
|
2409
|
+
const [internalIndex, setInternalIndex] = (0, import_react16.useState)(0);
|
|
2410
|
+
const index = isControlled ? currentSlide : internalIndex;
|
|
2411
|
+
const current = Math.min(index, slides.length - 1);
|
|
2412
|
+
const slide = slides[current];
|
|
2413
|
+
const goTo = (0, import_react16.useCallback)(
|
|
2414
|
+
(next) => {
|
|
2415
|
+
const clamped = Math.max(0, Math.min(next, slides.length - 1));
|
|
2416
|
+
if (isControlled) onSlideChange?.(clamped);
|
|
2417
|
+
else setInternalIndex(clamped);
|
|
2418
|
+
onNavigate?.(clamped);
|
|
2419
|
+
},
|
|
2420
|
+
[slides.length, onNavigate, isControlled, onSlideChange]
|
|
2421
|
+
);
|
|
2422
|
+
const position = labels.position.replace("{current}", String(current + 1)).replace("{total}", String(slides.length));
|
|
2423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideDispatch, { slide, labels, meta }),
|
|
2425
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
2426
|
+
"div",
|
|
2427
|
+
{
|
|
2428
|
+
className: `flex items-center justify-between border-t pt-2 ${onDark ? "border-white/20" : "border-brown-alpha-12"}`,
|
|
2429
|
+
children: [
|
|
2430
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2431
|
+
IconButton,
|
|
2432
|
+
{
|
|
2433
|
+
icon: IconChevronLeft,
|
|
2434
|
+
size: navBtnSize,
|
|
2435
|
+
className: navBtnClass,
|
|
2436
|
+
"aria-label": labels.previous,
|
|
2437
|
+
disabled: current === 0,
|
|
2438
|
+
onClick: () => goTo(current - 1)
|
|
2439
|
+
}
|
|
2440
|
+
),
|
|
2441
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: `text-xs font-medium ${onDark ? "text-white/70" : "text-brown-70"}`, children: position }),
|
|
2442
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2443
|
+
IconButton,
|
|
2444
|
+
{
|
|
2445
|
+
icon: IconChevronRight,
|
|
2446
|
+
size: navBtnSize,
|
|
2447
|
+
className: navBtnClass,
|
|
2448
|
+
"aria-label": labels.next,
|
|
2449
|
+
disabled: current === slides.length - 1,
|
|
2450
|
+
onClick: () => goTo(current + 1)
|
|
2451
|
+
}
|
|
2452
|
+
)
|
|
2453
|
+
]
|
|
2454
|
+
}
|
|
2455
|
+
)
|
|
2456
|
+
] });
|
|
2457
|
+
}
|
|
2458
|
+
function SlideDispatch({ slide, labels, meta }) {
|
|
2459
|
+
const kind = slide.kind ?? deckSlideKinds.CONTENT;
|
|
2460
|
+
switch (kind) {
|
|
2461
|
+
case deckSlideKinds.TITLE:
|
|
2462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TitleSlide, { slide, meta });
|
|
2463
|
+
case deckSlideKinds.AGENDA:
|
|
2464
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AgendaSlide, { slide, meta, labels });
|
|
2465
|
+
case deckSlideKinds.SECTION:
|
|
2466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SectionSlide, { slide, meta });
|
|
2467
|
+
case deckSlideKinds.CLOSING:
|
|
2468
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ClosingSlide, { meta, labels });
|
|
2469
|
+
case deckSlideKinds.CONTENT:
|
|
2470
|
+
default:
|
|
2471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ContentSlide, { slide, meta, labels });
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
function isVisualBlock(block) {
|
|
2475
|
+
return block.type === deckBlockTypes.CHART || block.type === deckBlockTypes.TABLE;
|
|
2476
|
+
}
|
|
2477
|
+
function ContentSlide({ slide, meta, labels }) {
|
|
2478
|
+
const content = slide.content ?? [];
|
|
2479
|
+
const visuals = content.filter(isVisualBlock);
|
|
2480
|
+
const texts = content.filter(
|
|
2481
|
+
(b) => b.type === deckBlockTypes.TEXT
|
|
2482
|
+
);
|
|
2483
|
+
if (visuals.length === 1 && texts.length > 0) {
|
|
2484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex h-full items-stretch gap-12 px-16 py-12", children: [
|
|
2485
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex w-[42%] shrink-0 flex-col overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(AutoFit, { children: [
|
|
2486
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "mb-5 font-bold leading-tight text-foreground", style: { fontSize: 34 }, children: slide.title }),
|
|
2487
|
+
texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
|
|
2488
|
+
] }) }),
|
|
2489
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "min-h-0 min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FillVisual, { block: visuals[0], labels }) })
|
|
2490
|
+
] }) });
|
|
2491
|
+
}
|
|
2492
|
+
if (visuals.length > 0) {
|
|
2493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex h-full flex-col gap-5 px-16 py-10", children: [
|
|
2494
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "shrink-0 font-bold leading-tight text-foreground", style: { fontSize: 32 }, children: slide.title }),
|
|
2495
|
+
content.map(
|
|
2496
|
+
(block, i) => isVisualBlock(block) ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "min-h-0 min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FillVisual, { block, labels }) }, i) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "shrink-0 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }) }, i)
|
|
2497
|
+
)
|
|
2498
|
+
] }) });
|
|
2499
|
+
}
|
|
2500
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SlideFrame, { meta, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-full px-24 py-12", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(AutoFit, { children: [
|
|
2501
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h3", { className: "mb-6 font-bold leading-tight text-foreground", style: { fontSize: 38 }, children: slide.title }),
|
|
2502
|
+
texts.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeckMarkdown, { markdown: block.markdown }, i))
|
|
2503
|
+
] }) }) });
|
|
2504
|
+
}
|
|
2505
|
+
function AutoFit({ children }) {
|
|
2506
|
+
const boxRef = (0, import_react16.useRef)(null);
|
|
2507
|
+
const contentRef = (0, import_react16.useRef)(null);
|
|
2508
|
+
const [fit, setFit] = (0, import_react16.useState)({ scale: 1, height: 0 });
|
|
2509
|
+
(0, import_react16.useLayoutEffect)(() => {
|
|
2510
|
+
const boxEl = boxRef.current;
|
|
2511
|
+
const contentEl = contentRef.current;
|
|
2512
|
+
if (!boxEl || !contentEl) return;
|
|
2513
|
+
const measure = () => {
|
|
2514
|
+
const avail = boxEl.clientHeight;
|
|
2515
|
+
const natural = contentEl.offsetHeight;
|
|
2516
|
+
const scale = avail > 0 && natural > avail ? avail / natural : 1;
|
|
2517
|
+
setFit({ scale, height: natural * scale });
|
|
2518
|
+
};
|
|
2519
|
+
measure();
|
|
2520
|
+
const ro = new ResizeObserver(measure);
|
|
2521
|
+
ro.observe(boxEl);
|
|
2522
|
+
ro.observe(contentEl);
|
|
2523
|
+
return () => ro.disconnect();
|
|
2524
|
+
}, []);
|
|
2525
|
+
const scaled = fit.scale < 1;
|
|
2526
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: boxRef, className: "flex h-full min-h-0 w-full flex-col justify-center overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: scaled ? { height: fit.height } : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2527
|
+
"div",
|
|
2528
|
+
{
|
|
2529
|
+
ref: contentRef,
|
|
2530
|
+
className: "w-full origin-top-left",
|
|
2531
|
+
style: scaled ? { transform: `scale(${fit.scale})` } : void 0,
|
|
2532
|
+
children
|
|
2533
|
+
}
|
|
2534
|
+
) }) });
|
|
2535
|
+
}
|
|
2536
|
+
function FillVisual({ block, labels }) {
|
|
2537
|
+
const ref = (0, import_react16.useRef)(null);
|
|
2538
|
+
const [height, setHeight] = (0, import_react16.useState)(VISUAL_FALLBACK_HEIGHT);
|
|
2539
|
+
(0, import_react16.useLayoutEffect)(() => {
|
|
2540
|
+
const el = ref.current;
|
|
2541
|
+
if (!el) return;
|
|
2542
|
+
const apply = (h) => {
|
|
2543
|
+
if (h > 0) setHeight(h);
|
|
2544
|
+
};
|
|
2545
|
+
apply(el.clientHeight);
|
|
2546
|
+
const ro = new ResizeObserver((entries) => apply(entries[0]?.contentRect.height ?? 0));
|
|
2547
|
+
ro.observe(el);
|
|
2548
|
+
return () => ro.disconnect();
|
|
2549
|
+
}, []);
|
|
2550
|
+
const chartLabels = labels.chart ?? DEFAULT_CHART_ARTIFACT_LABELS;
|
|
2551
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref, className: "h-full min-h-0 w-full overflow-hidden", children: block.type === deckBlockTypes.CHART ? (
|
|
2552
|
+
// ChartArtifactContent assumes a non-empty rowset (the standalone ChartArtifact guards
|
|
2553
|
+
// `rows.length > 0` upstream); mirror that guard here so an empty inline chart shows the
|
|
2554
|
+
// localized empty status instead of a blank chart area.
|
|
2555
|
+
block.rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusMessage, { $tone: "info", children: chartLabels.empty }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { height }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ChartArtifactContent, { config: block.config, rows: block.rows, labels: chartLabels }) })
|
|
2556
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2557
|
+
TableArtifactContent,
|
|
2558
|
+
{
|
|
2559
|
+
columns: block.config.columns,
|
|
2560
|
+
data: { status: "ready", rows: block.rows, error: null },
|
|
2561
|
+
knownRowCount: block.config.stats?.rowCount ?? block.rows.length,
|
|
2562
|
+
maxShimmerRows: TABLE_BLOCK_MAX_SHIMMER_ROWS,
|
|
2563
|
+
maxBodyHeight: Math.max(0, height - TABLE_CHROME_RESERVE),
|
|
2564
|
+
labels: labels.table ?? DEFAULT_TABLE_ARTIFACT_LABELS
|
|
2565
|
+
}
|
|
2566
|
+
) });
|
|
2161
2567
|
}
|
|
2162
2568
|
|
|
2163
2569
|
// src/components/artifacts/table-artifact/validate.ts
|
|
@@ -2176,19 +2582,265 @@ function isValidTableColumn(column) {
|
|
|
2176
2582
|
return true;
|
|
2177
2583
|
}
|
|
2178
2584
|
|
|
2179
|
-
// src/components/artifacts/
|
|
2180
|
-
|
|
2585
|
+
// src/components/artifacts/deck-artifact/validate.ts
|
|
2586
|
+
function isValidDeckConfig(config) {
|
|
2587
|
+
if (!config || typeof config !== "object") return false;
|
|
2588
|
+
const candidate = config;
|
|
2589
|
+
if (!Array.isArray(candidate.slides)) return false;
|
|
2590
|
+
if (candidate.slides.length === 0) return false;
|
|
2591
|
+
return candidate.slides.every(isValidDeckSlide);
|
|
2592
|
+
}
|
|
2593
|
+
function isValidDeckSlide(slide) {
|
|
2594
|
+
if (!slide || typeof slide !== "object") return false;
|
|
2595
|
+
const candidate = slide;
|
|
2596
|
+
if (typeof candidate.title !== "string") return false;
|
|
2597
|
+
const kind = typeof candidate.kind === "string" ? candidate.kind : deckSlideKinds.CONTENT;
|
|
2598
|
+
if (kind === deckSlideKinds.CONTENT && !Array.isArray(candidate.content)) return false;
|
|
2599
|
+
const content = Array.isArray(candidate.content) ? candidate.content : [];
|
|
2600
|
+
if (candidate.items != null) {
|
|
2601
|
+
if (!Array.isArray(candidate.items)) return false;
|
|
2602
|
+
if (!candidate.items.every((item) => typeof item === "string")) return false;
|
|
2603
|
+
}
|
|
2604
|
+
return content.every(isValidDeckBlock);
|
|
2605
|
+
}
|
|
2606
|
+
function isValidDeckBlock(block) {
|
|
2607
|
+
if (!block || typeof block !== "object") return false;
|
|
2608
|
+
const candidate = block;
|
|
2609
|
+
switch (candidate.type) {
|
|
2610
|
+
case deckBlockTypes.TEXT:
|
|
2611
|
+
return typeof candidate.markdown === "string";
|
|
2612
|
+
case deckBlockTypes.CHART:
|
|
2613
|
+
return isValidChartConfig(candidate.config) && Array.isArray(candidate.rows);
|
|
2614
|
+
case deckBlockTypes.TABLE:
|
|
2615
|
+
return isValidTableConfig(candidate.config) && Array.isArray(candidate.rows);
|
|
2616
|
+
default:
|
|
2617
|
+
return false;
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
// src/components/artifacts/deck-artifact/deck-artifact.tsx
|
|
2622
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2181
2623
|
var TITLE_CLASSES2 = "text-sm font-semibold text-foreground";
|
|
2624
|
+
function DeckArtifact({ artifact, labels, callbacks }) {
|
|
2625
|
+
const validConfig = isValidDeckConfig(artifact.config);
|
|
2626
|
+
const [isFullscreen, setIsFullscreen] = (0, import_react17.useState)(false);
|
|
2627
|
+
const [currentSlide, setCurrentSlide] = (0, import_react17.useState)(0);
|
|
2628
|
+
(0, import_react17.useEffect)(() => {
|
|
2629
|
+
if (validConfig) return;
|
|
2630
|
+
console.warn("[clay] DeckArtifact: malformed `config` \u2014 skipping render.");
|
|
2631
|
+
}, [validConfig]);
|
|
2632
|
+
(0, import_react17.useEffect)(() => {
|
|
2633
|
+
if (!isFullscreen) return;
|
|
2634
|
+
const handleKey = (e) => {
|
|
2635
|
+
if (e.key === "Escape") setIsFullscreen(false);
|
|
2636
|
+
};
|
|
2637
|
+
document.addEventListener("keydown", handleKey);
|
|
2638
|
+
const previousOverflow = document.documentElement.style.overflow;
|
|
2639
|
+
document.documentElement.style.overflow = "hidden";
|
|
2640
|
+
return () => {
|
|
2641
|
+
document.removeEventListener("keydown", handleKey);
|
|
2642
|
+
document.documentElement.style.overflow = previousOverflow;
|
|
2643
|
+
};
|
|
2644
|
+
}, [isFullscreen]);
|
|
2645
|
+
const resolvedLabels = (0, import_react17.useMemo)(
|
|
2646
|
+
() => ({
|
|
2647
|
+
...DEFAULT_DECK_ARTIFACT_LABELS,
|
|
2648
|
+
...labels ?? {},
|
|
2649
|
+
chart: { ...DEFAULT_CHART_ARTIFACT_LABELS, ...labels?.chart ?? {} },
|
|
2650
|
+
table: { ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels?.table ?? {} }
|
|
2651
|
+
}),
|
|
2652
|
+
[labels]
|
|
2653
|
+
);
|
|
2654
|
+
const onNavigate = callbacks?.onNavigate;
|
|
2655
|
+
const handleNavigate = onNavigate ? (slideIndex) => onNavigate(artifact, slideIndex) : void 0;
|
|
2656
|
+
const onDownload = callbacks?.onDownload;
|
|
2657
|
+
const handleDownload = onDownload ? () => onDownload(artifact) : void 0;
|
|
2658
|
+
const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
|
|
2659
|
+
const showDownload = presignedUrl !== null && isSafeDownloadUrl(presignedUrl);
|
|
2660
|
+
const meta = artifact.config?.meta;
|
|
2661
|
+
const handleOpenFullscreen = () => setIsFullscreen(true);
|
|
2662
|
+
const handleCloseFullscreen = () => setIsFullscreen(false);
|
|
2663
|
+
const actions = /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactActions, { ...{ [CAPTURE_EXCLUDE_ATTRIBUTE]: "" }, children: [
|
|
2664
|
+
showDownload ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactDownloadButton, { href: presignedUrl ?? "", label: resolvedLabels.download, onClick: handleDownload }) : null,
|
|
2665
|
+
validConfig ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2666
|
+
IconButton,
|
|
2667
|
+
{
|
|
2668
|
+
icon: IconArrowsMaximize,
|
|
2669
|
+
size: "small",
|
|
2670
|
+
"aria-label": resolvedLabels.enterFullscreen,
|
|
2671
|
+
onClick: handleOpenFullscreen
|
|
2672
|
+
}
|
|
2673
|
+
) : null
|
|
2674
|
+
] });
|
|
2675
|
+
if (!validConfig) {
|
|
2676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
2677
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
|
|
2678
|
+
artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
|
|
2679
|
+
actions
|
|
2680
|
+
] }),
|
|
2681
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
|
|
2682
|
+
] });
|
|
2683
|
+
}
|
|
2684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
2685
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
2686
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
|
|
2687
|
+
artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", {}),
|
|
2688
|
+
actions
|
|
2689
|
+
] }),
|
|
2690
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactContent, { className: "p-0", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2691
|
+
DeckArtifactContent,
|
|
2692
|
+
{
|
|
2693
|
+
slides: artifact.config.slides,
|
|
2694
|
+
labels: resolvedLabels,
|
|
2695
|
+
onNavigate: handleNavigate,
|
|
2696
|
+
meta,
|
|
2697
|
+
currentSlide,
|
|
2698
|
+
onSlideChange: setCurrentSlide
|
|
2699
|
+
}
|
|
2700
|
+
) })
|
|
2701
|
+
] }),
|
|
2702
|
+
isFullscreen && (0, import_react_dom.createPortal)(
|
|
2703
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2704
|
+
FullscreenOverlay,
|
|
2705
|
+
{
|
|
2706
|
+
artifact,
|
|
2707
|
+
resolvedLabels,
|
|
2708
|
+
onNavigate: handleNavigate,
|
|
2709
|
+
currentSlide,
|
|
2710
|
+
onSlideChange: setCurrentSlide,
|
|
2711
|
+
onClose: handleCloseFullscreen
|
|
2712
|
+
}
|
|
2713
|
+
),
|
|
2714
|
+
document.body
|
|
2715
|
+
)
|
|
2716
|
+
] });
|
|
2717
|
+
}
|
|
2718
|
+
function FullscreenOverlay({
|
|
2719
|
+
artifact,
|
|
2720
|
+
resolvedLabels,
|
|
2721
|
+
onNavigate,
|
|
2722
|
+
currentSlide,
|
|
2723
|
+
onSlideChange,
|
|
2724
|
+
onClose
|
|
2725
|
+
}) {
|
|
2726
|
+
const meta = artifact.config?.meta;
|
|
2727
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2728
|
+
"div",
|
|
2729
|
+
{
|
|
2730
|
+
className: "fixed inset-0 z-[2147483647] flex items-center justify-center bg-black/80",
|
|
2731
|
+
role: "dialog",
|
|
2732
|
+
"aria-modal": "true",
|
|
2733
|
+
"aria-label": resolvedLabels.exitFullscreen,
|
|
2734
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "relative", style: { width: "min(94vw, calc(82vh * 16 / 9))" }, children: [
|
|
2735
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2736
|
+
DeckArtifactContent,
|
|
2737
|
+
{
|
|
2738
|
+
slides: artifact.config.slides,
|
|
2739
|
+
labels: resolvedLabels,
|
|
2740
|
+
onNavigate,
|
|
2741
|
+
meta,
|
|
2742
|
+
currentSlide,
|
|
2743
|
+
onSlideChange,
|
|
2744
|
+
onDark: true
|
|
2745
|
+
}
|
|
2746
|
+
),
|
|
2747
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
2748
|
+
"button",
|
|
2749
|
+
{
|
|
2750
|
+
className: "absolute -top-10 right-6 flex items-center gap-1.5 text-sm text-white/80 hover:text-white",
|
|
2751
|
+
"aria-label": resolvedLabels.exitFullscreen,
|
|
2752
|
+
onClick: onClose,
|
|
2753
|
+
children: [
|
|
2754
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IconArrowsMinimize, { size: 16 }),
|
|
2755
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: resolvedLabels.exitFullscreen })
|
|
2756
|
+
]
|
|
2757
|
+
}
|
|
2758
|
+
)
|
|
2759
|
+
] })
|
|
2760
|
+
}
|
|
2761
|
+
);
|
|
2762
|
+
}
|
|
2763
|
+
|
|
2764
|
+
// src/components/artifacts/deck-artifact/to-clipboard-text.ts
|
|
2765
|
+
function deckArtifactToClipboardText(artifact) {
|
|
2766
|
+
const header = artifact.title?.trim() || "Deck";
|
|
2767
|
+
const slides = artifact.config?.slides ?? [];
|
|
2768
|
+
const body = slides.map((slide, i) => slideToText(slide, i)).join("\n\n");
|
|
2769
|
+
return body ? `${header}
|
|
2770
|
+
|
|
2771
|
+
${body}` : header;
|
|
2772
|
+
}
|
|
2773
|
+
function slideToText(slide, index) {
|
|
2774
|
+
const kind = slide.kind ?? deckSlideKinds.CONTENT;
|
|
2775
|
+
const prefix = `Slide ${index + 1}: `;
|
|
2776
|
+
switch (kind) {
|
|
2777
|
+
case deckSlideKinds.TITLE: {
|
|
2778
|
+
const parts = [slide.title];
|
|
2779
|
+
if (slide.subtitle) parts.push(slide.subtitle);
|
|
2780
|
+
if (slide.description) parts.push(slide.description);
|
|
2781
|
+
return `${prefix}${parts.join(" \u2014 ")}`.trim();
|
|
2782
|
+
}
|
|
2783
|
+
case deckSlideKinds.AGENDA: {
|
|
2784
|
+
const items = (slide.items ?? []).map((item, i) => ` ${String(i + 1).padStart(2, "0")}. ${item}`).join("\n");
|
|
2785
|
+
return `${prefix}${slide.title || "Agenda"}${items ? `
|
|
2786
|
+
${items}` : ""}`.trim();
|
|
2787
|
+
}
|
|
2788
|
+
case deckSlideKinds.SECTION:
|
|
2789
|
+
return `${prefix}${slide.title}`.trim();
|
|
2790
|
+
case deckSlideKinds.CLOSING:
|
|
2791
|
+
return `${prefix}Thank you`.trim();
|
|
2792
|
+
case deckSlideKinds.CONTENT:
|
|
2793
|
+
default: {
|
|
2794
|
+
const blocks = (slide.content ?? []).map(blockToText).filter(Boolean).join("\n\n");
|
|
2795
|
+
return `${prefix}${slide.title}${blocks ? `
|
|
2796
|
+
${blocks}` : ""}`.trim();
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
function blockToText(block) {
|
|
2801
|
+
switch (block.type) {
|
|
2802
|
+
case deckBlockTypes.TEXT:
|
|
2803
|
+
return block.markdown.trim();
|
|
2804
|
+
case deckBlockTypes.CHART:
|
|
2805
|
+
return `[Chart: ${block.config.variant}]`;
|
|
2806
|
+
case deckBlockTypes.TABLE: {
|
|
2807
|
+
const columnCount = block.config.columns.length;
|
|
2808
|
+
const rowCount = block.rows.length;
|
|
2809
|
+
return `[Table: ${columnCount} column${columnCount === 1 ? "" : "s"} \xD7 ${rowCount} row${rowCount === 1 ? "" : "s"}]`;
|
|
2810
|
+
}
|
|
2811
|
+
default:
|
|
2812
|
+
return "";
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
// src/components/artifacts/artifact-services/deck-artifact-service.ts
|
|
2817
|
+
var DeckArtifactService = {
|
|
2818
|
+
type: artifactTypes.DECK,
|
|
2819
|
+
Component: DeckArtifact,
|
|
2820
|
+
toClipboardText: deckArtifactToClipboardText
|
|
2821
|
+
};
|
|
2822
|
+
|
|
2823
|
+
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
2824
|
+
var import_react18 = require("react");
|
|
2825
|
+
|
|
2826
|
+
// src/components/artifacts/table-artifact/use-table-artifact-data.ts
|
|
2827
|
+
function useTableArtifactData(presignedUrl, columns) {
|
|
2828
|
+
return useRowsArtifactData(presignedUrl, columns, parseCsv);
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
2832
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2833
|
+
var TITLE_CLASSES3 = "text-sm font-semibold text-foreground";
|
|
2182
2834
|
var TABLE_MAX_BODY_HEIGHT = 480;
|
|
2183
2835
|
var MAX_SHIMMER_ROWS = 10;
|
|
2184
2836
|
function TableArtifact({ artifact, labels, callbacks }) {
|
|
2185
2837
|
const validConfig = isValidTableConfig(artifact.config);
|
|
2186
2838
|
const validColumns = validConfig ? artifact.config.columns : null;
|
|
2187
|
-
(0,
|
|
2839
|
+
(0, import_react18.useEffect)(() => {
|
|
2188
2840
|
if (validConfig) return;
|
|
2189
2841
|
console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
|
|
2190
2842
|
}, [validConfig]);
|
|
2191
|
-
const resolvedLabels = (0,
|
|
2843
|
+
const resolvedLabels = (0, import_react18.useMemo)(
|
|
2192
2844
|
() => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels ?? {} }),
|
|
2193
2845
|
[labels]
|
|
2194
2846
|
);
|
|
@@ -2200,10 +2852,10 @@ function TableArtifact({ artifact, labels, callbacks }) {
|
|
|
2200
2852
|
const onDownload = callbacks?.onDownload;
|
|
2201
2853
|
const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
|
|
2202
2854
|
if (!validConfig || !validColumns) {
|
|
2203
|
-
return /* @__PURE__ */ (0,
|
|
2204
|
-
/* @__PURE__ */ (0,
|
|
2205
|
-
artifact.title ? /* @__PURE__ */ (0,
|
|
2206
|
-
presignedUrl ? /* @__PURE__ */ (0,
|
|
2855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
2856
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
|
|
2857
|
+
artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", {}),
|
|
2858
|
+
presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
2207
2859
|
ArtifactDownloadButton,
|
|
2208
2860
|
{
|
|
2209
2861
|
href: presignedUrl,
|
|
@@ -2212,17 +2864,17 @@ function TableArtifact({ artifact, labels, callbacks }) {
|
|
|
2212
2864
|
}
|
|
2213
2865
|
) }) : null
|
|
2214
2866
|
] }),
|
|
2215
|
-
/* @__PURE__ */ (0,
|
|
2867
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
|
|
2216
2868
|
] });
|
|
2217
2869
|
}
|
|
2218
2870
|
return (
|
|
2219
2871
|
// The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
|
|
2220
2872
|
// Disable the outer overflow container so only one scroll context exists — this prevents
|
|
2221
2873
|
// 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,
|
|
2874
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
2875
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
|
|
2876
|
+
artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactTitle, { className: TITLE_CLASSES3, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", {}),
|
|
2877
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
2226
2878
|
ArtifactDownloadButton,
|
|
2227
2879
|
{
|
|
2228
2880
|
href: presignedUrl ?? "",
|
|
@@ -2231,7 +2883,7 @@ function TableArtifact({ artifact, labels, callbacks }) {
|
|
|
2231
2883
|
}
|
|
2232
2884
|
) })
|
|
2233
2885
|
] }),
|
|
2234
|
-
/* @__PURE__ */ (0,
|
|
2886
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
2235
2887
|
TableArtifactContent,
|
|
2236
2888
|
{
|
|
2237
2889
|
columns: validColumns,
|
|
@@ -2262,7 +2914,8 @@ var TableArtifactService = {
|
|
|
2262
2914
|
// src/components/artifacts/artifact-services/index.ts
|
|
2263
2915
|
var ArtifactServices = {
|
|
2264
2916
|
[artifactTypes.TABLE]: TableArtifactService,
|
|
2265
|
-
[artifactTypes.CHART]: ChartArtifactService
|
|
2917
|
+
[artifactTypes.CHART]: ChartArtifactService,
|
|
2918
|
+
[artifactTypes.DECK]: DeckArtifactService
|
|
2266
2919
|
};
|
|
2267
2920
|
function artifactToClipboardText(artifact) {
|
|
2268
2921
|
const entry = ArtifactServices[artifact.type];
|
|
@@ -2273,13 +2926,13 @@ function artifactToClipboardText(artifact) {
|
|
|
2273
2926
|
}
|
|
2274
2927
|
|
|
2275
2928
|
// src/components/blocks/artifact-ref-block/artifact-ref-block.tsx
|
|
2276
|
-
var
|
|
2929
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
2277
2930
|
function ArtifactRefBlock({ block }) {
|
|
2278
2931
|
const { artifact, labels, callbacks } = block.payload;
|
|
2279
2932
|
const entry = ArtifactServices[artifact.type];
|
|
2280
2933
|
if (!entry) return null;
|
|
2281
2934
|
const Component = entry.Component;
|
|
2282
|
-
return /* @__PURE__ */ (0,
|
|
2935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Component, { artifact, labels, callbacks });
|
|
2283
2936
|
}
|
|
2284
2937
|
|
|
2285
2938
|
// src/components/blocks/block-services/artifact-ref-block-service.ts
|
|
@@ -2294,29 +2947,102 @@ var ArtifactRefBlockService = {
|
|
|
2294
2947
|
toClipboardText: (block) => artifactToClipboardText(block.payload.artifact)
|
|
2295
2948
|
};
|
|
2296
2949
|
|
|
2297
|
-
// src/
|
|
2298
|
-
var
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2950
|
+
// src/components/blocks/notification-draft-block/notification-draft-block.tsx
|
|
2951
|
+
var import_react20 = require("react");
|
|
2952
|
+
|
|
2953
|
+
// src/components/badge/badge.tsx
|
|
2954
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
2955
|
+
var BASE = "inline-flex items-center whitespace-nowrap rounded-full";
|
|
2956
|
+
var SIZES = {
|
|
2957
|
+
// `sm` is a uniform scale-down of `md` (text 10/12 of caption): padding and line-height keep
|
|
2958
|
+
// md's proportions (caption is 12px text on a 16px line = 1.333 ratio) so the pill shape matches.
|
|
2959
|
+
md: "px-2.5 py-0.5 text-geist-label-caption-medium",
|
|
2960
|
+
sm: "px-2 py-0.5 text-[11px]/[1.333] font-medium"
|
|
2961
|
+
};
|
|
2962
|
+
var SUBTLE = {
|
|
2963
|
+
neutral: "bg-brown-20 text-brown-70",
|
|
2964
|
+
warning: "bg-orange-50 text-orange-600",
|
|
2965
|
+
violet: "bg-violet-50 text-violet-600"
|
|
2966
|
+
};
|
|
2967
|
+
var OUTLINE = {
|
|
2968
|
+
neutral: "border border-brown-30 bg-white text-brown-100",
|
|
2969
|
+
warning: "border border-orange-200 bg-white text-orange-600",
|
|
2970
|
+
violet: "border border-violet-400 bg-white text-violet-600"
|
|
2971
|
+
};
|
|
2972
|
+
var VARIANTS = {
|
|
2973
|
+
subtle: SUBTLE,
|
|
2974
|
+
outline: OUTLINE
|
|
2975
|
+
};
|
|
2976
|
+
function Badge({
|
|
2977
|
+
variant = "subtle",
|
|
2978
|
+
tone = "neutral",
|
|
2979
|
+
size = "md",
|
|
2980
|
+
className,
|
|
2981
|
+
children
|
|
2982
|
+
}) {
|
|
2983
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cn(BASE, SIZES[size], VARIANTS[variant][tone], className), children });
|
|
2303
2984
|
}
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2985
|
+
|
|
2986
|
+
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
2987
|
+
var import_react19 = require("react");
|
|
2988
|
+
|
|
2989
|
+
// src/utils/clipboard.ts
|
|
2990
|
+
function copyToClipboard(text, options) {
|
|
2991
|
+
navigator.clipboard.writeText(text).then(
|
|
2992
|
+
() => options?.onSuccess?.(),
|
|
2993
|
+
(error) => options?.onFailure?.(error)
|
|
2994
|
+
);
|
|
2314
2995
|
}
|
|
2315
2996
|
|
|
2316
|
-
// src/components/
|
|
2317
|
-
var
|
|
2318
|
-
|
|
2319
|
-
|
|
2997
|
+
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
2998
|
+
var RESET_DELAY_MS = 2e3;
|
|
2999
|
+
function useCopyToClipboard() {
|
|
3000
|
+
const [isCopied, setIsCopied] = (0, import_react19.useState)(false);
|
|
3001
|
+
const timeoutRef = (0, import_react19.useRef)(null);
|
|
3002
|
+
(0, import_react19.useEffect)(() => {
|
|
3003
|
+
return () => {
|
|
3004
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
3005
|
+
};
|
|
3006
|
+
}, []);
|
|
3007
|
+
const copy = (0, import_react19.useCallback)((text) => {
|
|
3008
|
+
copyToClipboard(text, {
|
|
3009
|
+
onSuccess: () => {
|
|
3010
|
+
setIsCopied(true);
|
|
3011
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
3012
|
+
timeoutRef.current = setTimeout(() => {
|
|
3013
|
+
setIsCopied(false);
|
|
3014
|
+
timeoutRef.current = null;
|
|
3015
|
+
}, RESET_DELAY_MS);
|
|
3016
|
+
}
|
|
3017
|
+
});
|
|
3018
|
+
}, []);
|
|
3019
|
+
return { isCopied, copy };
|
|
3020
|
+
}
|
|
3021
|
+
|
|
3022
|
+
// src/components/copy-button/copy-button.tsx
|
|
3023
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
3024
|
+
function CopyButton({
|
|
3025
|
+
text,
|
|
3026
|
+
copyLabel = "Copy",
|
|
3027
|
+
copiedLabel = "Copied",
|
|
3028
|
+
className
|
|
3029
|
+
}) {
|
|
3030
|
+
const { isCopied, copy } = useCopyToClipboard();
|
|
3031
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
3032
|
+
IconButton,
|
|
3033
|
+
{
|
|
3034
|
+
icon: isCopied ? IconCheck : IconCopy,
|
|
3035
|
+
onClick: () => copy(text),
|
|
3036
|
+
"aria-label": isCopied ? copiedLabel : copyLabel,
|
|
3037
|
+
className
|
|
3038
|
+
}
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
// src/components/blocks/markdown/markdown.tsx
|
|
3043
|
+
var import_react_markdown2 = __toESM(require("react-markdown"), 1);
|
|
3044
|
+
var import_remark_breaks2 = __toESM(require("remark-breaks"), 1);
|
|
3045
|
+
var import_remark_gfm2 = __toESM(require("remark-gfm"), 1);
|
|
2320
3046
|
|
|
2321
3047
|
// src/components/blocks/scrollable-table/scrollable-table-styles.ts
|
|
2322
3048
|
var import_styled_components3 = __toESM(require("styled-components"), 1);
|
|
@@ -2331,13 +3057,13 @@ var TableScroll = import_styled_components3.default.div`
|
|
|
2331
3057
|
`;
|
|
2332
3058
|
|
|
2333
3059
|
// src/components/blocks/scrollable-table/scrollable-table.tsx
|
|
2334
|
-
var
|
|
3060
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
2335
3061
|
function ScrollableTable({ node: _node, ...props }) {
|
|
2336
|
-
return /* @__PURE__ */ (0,
|
|
3062
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TableContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("table", { ...props }) }) });
|
|
2337
3063
|
}
|
|
2338
3064
|
|
|
2339
3065
|
// src/components/blocks/text-block/sanitize.ts
|
|
2340
|
-
function
|
|
3066
|
+
function sanitize2(text) {
|
|
2341
3067
|
return text.split("\n").filter((line) => {
|
|
2342
3068
|
const t = line.trim();
|
|
2343
3069
|
return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
|
|
@@ -2476,13 +3202,151 @@ var TextBlockWrapper = import_styled_components4.default.div`
|
|
|
2476
3202
|
}
|
|
2477
3203
|
`;
|
|
2478
3204
|
|
|
2479
|
-
// src/components/blocks/
|
|
2480
|
-
var
|
|
3205
|
+
// src/components/blocks/markdown/markdown.tsx
|
|
3206
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
2481
3207
|
var markdownComponents = {
|
|
2482
|
-
table: ((tableProps) => /* @__PURE__ */ (0,
|
|
3208
|
+
table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ScrollableTable, { ...tableProps }))
|
|
3209
|
+
};
|
|
3210
|
+
function Markdown({ children }) {
|
|
3211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TextBlockWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react_markdown2.default, { remarkPlugins: [import_remark_gfm2.default, import_remark_breaks2.default], components: markdownComponents, children: sanitize2(children) }) });
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
// src/utils/markdown-to-plain-text.ts
|
|
3215
|
+
var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
|
|
3216
|
+
var PLACEHOLDER_SUFFIX = "\u200B\u200B";
|
|
3217
|
+
var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
|
|
3218
|
+
function stripInlineMarks(text) {
|
|
3219
|
+
return text.replace(/\*{3}(.+?)\*{3}/g, "$1").replace(/\*{2}(.+?)\*{2}/g, "$1").replace(/_{2}(.+?)_{2}/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1");
|
|
3220
|
+
}
|
|
3221
|
+
function markdownToPlainText(markdown) {
|
|
3222
|
+
if (!markdown) return "";
|
|
3223
|
+
const inlineCodeSnippets = [];
|
|
3224
|
+
let result = markdown.replace(/^<!--[\s\S]*?--!?>\n?/gm, "").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
|
|
3225
|
+
inlineCodeSnippets.push(code);
|
|
3226
|
+
return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
|
|
3227
|
+
}).replace(/^#{1,6}\s+/gm, "").replace(/^(?:---|\*\*\*|___)\s*$/gm, "");
|
|
3228
|
+
result = stripInlineMarks(result).replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/^>\s?/gm, "").replace(/^\|[-:\s|]+\|\s*$/gm, "").replace(/^\|\s?/gm, "").replace(/\s?\|$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
3229
|
+
result = result.replace(PLACEHOLDER_REGEX, (_match, index) => inlineCodeSnippets[Number(index)]);
|
|
3230
|
+
return result;
|
|
3231
|
+
}
|
|
3232
|
+
|
|
3233
|
+
// src/components/blocks/notification-draft-block/types.ts
|
|
3234
|
+
var notificationChannels = {
|
|
3235
|
+
/** Branded email — renders a From/subject header. */
|
|
3236
|
+
EMAIL: "email",
|
|
3237
|
+
/** Slack DM — renders as a chat bubble, no subject. */
|
|
3238
|
+
SLACK: "slack",
|
|
3239
|
+
/** Microsoft Teams DM — renders as a chat bubble, no subject. */
|
|
3240
|
+
TEAMS: "teams"
|
|
2483
3241
|
};
|
|
3242
|
+
|
|
3243
|
+
// src/components/blocks/notification-draft-block/to-text.ts
|
|
3244
|
+
function notificationDraftToText(payload) {
|
|
3245
|
+
const { channel, subject, body } = payload;
|
|
3246
|
+
const text = markdownToPlainText(body);
|
|
3247
|
+
return channel === notificationChannels.EMAIL && subject ? `${subject}
|
|
3248
|
+
|
|
3249
|
+
${text}` : text;
|
|
3250
|
+
}
|
|
3251
|
+
|
|
3252
|
+
// src/components/blocks/notification-draft-block/notification-draft-block.tsx
|
|
3253
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
3254
|
+
var CHIP_LIMIT = 3;
|
|
3255
|
+
var RECIPIENTS_MAX_HEIGHT = 320;
|
|
3256
|
+
function chipLabel(recipient) {
|
|
3257
|
+
return recipient.name ?? recipient.email ?? recipient.employeeId;
|
|
3258
|
+
}
|
|
3259
|
+
function channelCellText(recipient) {
|
|
3260
|
+
return recipient.fallback ? `${recipient.channelLabel} (fallback)` : recipient.channelLabel;
|
|
3261
|
+
}
|
|
3262
|
+
function FieldLabel({ children }) {
|
|
3263
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-geist-label-caption-medium tracking-wide text-brown-60", children });
|
|
3264
|
+
}
|
|
3265
|
+
function RecipientChips({ recipients }) {
|
|
3266
|
+
const shown = recipients.slice(0, CHIP_LIMIT);
|
|
3267
|
+
const overflow = recipients.length - shown.length;
|
|
3268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
3269
|
+
shown.map((recipient) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Badge, { variant: "outline", children: chipLabel(recipient) }, recipient.employeeId)),
|
|
3270
|
+
overflow > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Badge, { variant: "subtle", children: `+${overflow}` })
|
|
3271
|
+
] });
|
|
3272
|
+
}
|
|
3273
|
+
function RecipientsTable({ recipients }) {
|
|
3274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
3275
|
+
DataTable,
|
|
3276
|
+
{
|
|
3277
|
+
maxBodyHeight: RECIPIENTS_MAX_HEIGHT,
|
|
3278
|
+
header: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TableRow, { className: "hover:bg-transparent", children: [
|
|
3279
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: "Name" }),
|
|
3280
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: "Email" }),
|
|
3281
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableHead, { scope: "col", className: DATA_TABLE_HEAD_CLASS, children: "Channel" })
|
|
3282
|
+
] }),
|
|
3283
|
+
children: recipients.map((recipient) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(TableRow, { className: DATA_TABLE_ROW_CLASS, children: [
|
|
3284
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: recipient.name ?? "\u2014" }),
|
|
3285
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: recipient.email ?? "\u2014" }),
|
|
3286
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableCell, { className: DATA_TABLE_CELL_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Badge, { tone: recipient.fallback ? "warning" : "neutral", variant: "subtle", children: channelCellText(recipient) }) })
|
|
3287
|
+
] }, recipient.employeeId))
|
|
3288
|
+
}
|
|
3289
|
+
);
|
|
3290
|
+
}
|
|
3291
|
+
function NotificationDraftBlock({ block }) {
|
|
3292
|
+
const { channel, subject, body, recipients } = block.payload;
|
|
3293
|
+
const [detailsOpen, setDetailsOpen] = (0, import_react20.useState)(false);
|
|
3294
|
+
const showSubject = channel === notificationChannels.EMAIL && subject;
|
|
3295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "overflow-hidden rounded-2xl border border-brown-30 bg-white", children: [
|
|
3296
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-3 border-b border-brown-30 px-4 py-3", children: [
|
|
3297
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
|
|
3298
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3299
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-geist-body-s-semi-bold text-brown-100", children: "Notification draft" }),
|
|
3300
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Badge, { tone: "violet", variant: "subtle", size: "sm", className: "gap-1 py-1", children: [
|
|
3301
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Icon, { icon: IconFlask2Filled, size: 12 }),
|
|
3302
|
+
"Labs"
|
|
3303
|
+
] })
|
|
3304
|
+
] }),
|
|
3305
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CopyButton, { text: notificationDraftToText(block.payload), copyLabel: "Copy draft", copiedLabel: "Copied" })
|
|
3306
|
+
] }),
|
|
3307
|
+
showSubject && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
|
|
3308
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldLabel, { children: "Title" }),
|
|
3309
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "text-geist-body-s-medium text-brown-100", children: subject })
|
|
3310
|
+
] }),
|
|
3311
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
3312
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
|
|
3313
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FieldLabel, { children: `Recipients (${recipients.length})` }),
|
|
3314
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
3315
|
+
"button",
|
|
3316
|
+
{
|
|
3317
|
+
type: "button",
|
|
3318
|
+
"aria-expanded": detailsOpen,
|
|
3319
|
+
onClick: () => setDetailsOpen((open) => !open),
|
|
3320
|
+
className: "inline-flex items-center gap-1 text-geist-label-caption-medium text-brown-70 transition-colors hover:text-brown-100",
|
|
3321
|
+
children: [
|
|
3322
|
+
"Details",
|
|
3323
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Icon, { icon: IconChevronDown, size: 14, className: detailsOpen ? "rotate-180" : void 0 })
|
|
3324
|
+
]
|
|
3325
|
+
}
|
|
3326
|
+
)
|
|
3327
|
+
] }),
|
|
3328
|
+
detailsOpen ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(RecipientsTable, { recipients }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(RecipientChips, { recipients })
|
|
3329
|
+
] })
|
|
3330
|
+
] }),
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Markdown, { children: body }) })
|
|
3332
|
+
] });
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
// src/components/blocks/block-services/notification-draft-block-service.ts
|
|
3336
|
+
var NotificationDraftBlockService = {
|
|
3337
|
+
type: blockTypes.NOTIFICATION_DRAFT,
|
|
3338
|
+
Component: NotificationDraftBlock,
|
|
3339
|
+
/**
|
|
3340
|
+
* Plain-text clipboard form of the drafted notification — shared with the in-block copy button
|
|
3341
|
+
* via {@link notificationDraftToText} so both copy the same text.
|
|
3342
|
+
*/
|
|
3343
|
+
toClipboardText: (block) => notificationDraftToText(block.payload)
|
|
3344
|
+
};
|
|
3345
|
+
|
|
3346
|
+
// src/components/blocks/text-block/text-block.tsx
|
|
3347
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
2484
3348
|
function TextBlock({ block }) {
|
|
2485
|
-
return /* @__PURE__ */ (0,
|
|
3349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Markdown, { children: block.payload.text });
|
|
2486
3350
|
}
|
|
2487
3351
|
|
|
2488
3352
|
// src/components/blocks/block-services/text-block-service.ts
|
|
@@ -2500,16 +3364,17 @@ var TextBlockService = {
|
|
|
2500
3364
|
// src/components/blocks/block-services/index.ts
|
|
2501
3365
|
var BlockServices = {
|
|
2502
3366
|
[blockTypes.TEXT]: TextBlockService,
|
|
2503
|
-
[blockTypes.ARTIFACT_REF]: ArtifactRefBlockService
|
|
3367
|
+
[blockTypes.ARTIFACT_REF]: ArtifactRefBlockService,
|
|
3368
|
+
[blockTypes.NOTIFICATION_DRAFT]: NotificationDraftBlockService
|
|
2504
3369
|
};
|
|
2505
3370
|
|
|
2506
3371
|
// src/components/blocks/block/block.tsx
|
|
2507
|
-
var
|
|
3372
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2508
3373
|
function Block({ block }) {
|
|
2509
3374
|
const service = BlockServices[block.type];
|
|
2510
3375
|
if (!service) return null;
|
|
2511
3376
|
const { Component } = service;
|
|
2512
|
-
return /* @__PURE__ */ (0,
|
|
3377
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Component, { block });
|
|
2513
3378
|
}
|
|
2514
3379
|
|
|
2515
3380
|
// src/components/chat/hooks/copy-message-text.ts
|
|
@@ -2527,55 +3392,19 @@ function copyMessageText(message) {
|
|
|
2527
3392
|
}
|
|
2528
3393
|
|
|
2529
3394
|
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
2530
|
-
var
|
|
3395
|
+
var import_react22 = require("react");
|
|
2531
3396
|
|
|
2532
3397
|
// src/components/chat/chat-context/chat-context.ts
|
|
2533
|
-
var
|
|
2534
|
-
var ChatContext = (0,
|
|
3398
|
+
var import_react21 = require("react");
|
|
3399
|
+
var ChatContext = (0, import_react21.createContext)(null);
|
|
2535
3400
|
function useChatContext() {
|
|
2536
|
-
const context = (0,
|
|
3401
|
+
const context = (0, import_react21.useContext)(ChatContext);
|
|
2537
3402
|
if (!context) {
|
|
2538
3403
|
throw new Error("useChatContext must be used within a Chat.Root component");
|
|
2539
3404
|
}
|
|
2540
3405
|
return context;
|
|
2541
3406
|
}
|
|
2542
3407
|
|
|
2543
|
-
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
2544
|
-
var import_react17 = require("react");
|
|
2545
|
-
|
|
2546
|
-
// src/utils/clipboard.ts
|
|
2547
|
-
function copyToClipboard(text, options) {
|
|
2548
|
-
navigator.clipboard.writeText(text).then(
|
|
2549
|
-
() => options?.onSuccess?.(),
|
|
2550
|
-
(error) => options?.onFailure?.(error)
|
|
2551
|
-
);
|
|
2552
|
-
}
|
|
2553
|
-
|
|
2554
|
-
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
2555
|
-
var RESET_DELAY_MS = 2e3;
|
|
2556
|
-
function useCopyToClipboard() {
|
|
2557
|
-
const [isCopied, setIsCopied] = (0, import_react17.useState)(false);
|
|
2558
|
-
const timeoutRef = (0, import_react17.useRef)(null);
|
|
2559
|
-
(0, import_react17.useEffect)(() => {
|
|
2560
|
-
return () => {
|
|
2561
|
-
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
2562
|
-
};
|
|
2563
|
-
}, []);
|
|
2564
|
-
const copy = (0, import_react17.useCallback)((text) => {
|
|
2565
|
-
copyToClipboard(text, {
|
|
2566
|
-
onSuccess: () => {
|
|
2567
|
-
setIsCopied(true);
|
|
2568
|
-
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
2569
|
-
timeoutRef.current = setTimeout(() => {
|
|
2570
|
-
setIsCopied(false);
|
|
2571
|
-
timeoutRef.current = null;
|
|
2572
|
-
}, RESET_DELAY_MS);
|
|
2573
|
-
}
|
|
2574
|
-
});
|
|
2575
|
-
}, []);
|
|
2576
|
-
return { isCopied, copy };
|
|
2577
|
-
}
|
|
2578
|
-
|
|
2579
3408
|
// src/components/chat/constants.ts
|
|
2580
3409
|
var MESSAGE_ROLE = {
|
|
2581
3410
|
USER: "user",
|
|
@@ -2601,24 +3430,24 @@ var AnimatedAction = import_styled_components5.default.div`
|
|
|
2601
3430
|
`;
|
|
2602
3431
|
|
|
2603
3432
|
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
2604
|
-
var
|
|
3433
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2605
3434
|
function ChatMessageActions({ className, messageId, content, role, isHelpful }) {
|
|
2606
3435
|
const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
|
|
2607
3436
|
const { isCopied, copy } = useCopyToClipboard();
|
|
2608
|
-
const handleCopy = (0,
|
|
3437
|
+
const handleCopy = (0, import_react22.useCallback)(() => {
|
|
2609
3438
|
copy(content);
|
|
2610
3439
|
onCopyMessage?.(messageId);
|
|
2611
3440
|
}, [content, messageId, copy, onCopyMessage]);
|
|
2612
|
-
const handleThumbUp = (0,
|
|
3441
|
+
const handleThumbUp = (0, import_react22.useCallback)(() => {
|
|
2613
3442
|
onThumbUpClick?.(messageId, isHelpful === true ? null : true);
|
|
2614
3443
|
}, [messageId, isHelpful, onThumbUpClick]);
|
|
2615
|
-
const handleThumbDown = (0,
|
|
3444
|
+
const handleThumbDown = (0, import_react22.useCallback)(() => {
|
|
2616
3445
|
onThumbDownClick?.(messageId, isHelpful === false ? null : false);
|
|
2617
3446
|
}, [messageId, isHelpful, onThumbDownClick]);
|
|
2618
3447
|
const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
|
|
2619
3448
|
const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
|
|
2620
|
-
return /* @__PURE__ */ (0,
|
|
2621
|
-
/* @__PURE__ */ (0,
|
|
3449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(ActionsContainer, { $role: role, className, children: [
|
|
3450
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2622
3451
|
IconButton,
|
|
2623
3452
|
{
|
|
2624
3453
|
icon: isCopied ? IconCheck : IconCopy,
|
|
@@ -2626,7 +3455,7 @@ function ChatMessageActions({ className, messageId, content, role, isHelpful })
|
|
|
2626
3455
|
"aria-label": isCopied ? "Copied" : "Copy message"
|
|
2627
3456
|
}
|
|
2628
3457
|
),
|
|
2629
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
3458
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2630
3459
|
IconButton,
|
|
2631
3460
|
{
|
|
2632
3461
|
icon: IconThumbUp,
|
|
@@ -2635,7 +3464,7 @@ function ChatMessageActions({ className, messageId, content, role, isHelpful })
|
|
|
2635
3464
|
"aria-label": "Good response"
|
|
2636
3465
|
}
|
|
2637
3466
|
) }),
|
|
2638
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
3467
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2639
3468
|
IconButton,
|
|
2640
3469
|
{
|
|
2641
3470
|
icon: IconThumbDown,
|
|
@@ -2686,12 +3515,12 @@ var MessageBubble = import_styled_components6.default.div`
|
|
|
2686
3515
|
`;
|
|
2687
3516
|
|
|
2688
3517
|
// src/components/chat/chat-message/chat-message.tsx
|
|
2689
|
-
var
|
|
3518
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2690
3519
|
function ChatMessage({ message }) {
|
|
2691
|
-
const clipboardText = (0,
|
|
2692
|
-
return /* @__PURE__ */ (0,
|
|
2693
|
-
/* @__PURE__ */ (0,
|
|
2694
|
-
/* @__PURE__ */ (0,
|
|
3520
|
+
const clipboardText = (0, import_react23.useMemo)(() => copyMessageText(message), [message]);
|
|
3521
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(MessageContainer, { $role: message.role, children: [
|
|
3522
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MessageBubble, { $role: message.role, "data-testid": "message-bubble", children: message.blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Block, { block }, index)) }),
|
|
3523
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2695
3524
|
ChatMessageActions,
|
|
2696
3525
|
{
|
|
2697
3526
|
messageId: message.id,
|
|
@@ -2716,7 +3545,12 @@ function ChatMessage({ message }) {
|
|
|
2716
3545
|
@tabler/icons-react/dist/esm/defaultAttributes.mjs:
|
|
2717
3546
|
@tabler/icons-react/dist/esm/createReactComponent.mjs:
|
|
2718
3547
|
@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs:
|
|
3548
|
+
@tabler/icons-react/dist/esm/icons/IconArrowsMaximize.mjs:
|
|
3549
|
+
@tabler/icons-react/dist/esm/icons/IconArrowsMinimize.mjs:
|
|
2719
3550
|
@tabler/icons-react/dist/esm/icons/IconCheck.mjs:
|
|
3551
|
+
@tabler/icons-react/dist/esm/icons/IconChevronDown.mjs:
|
|
3552
|
+
@tabler/icons-react/dist/esm/icons/IconChevronLeft.mjs:
|
|
3553
|
+
@tabler/icons-react/dist/esm/icons/IconChevronRight.mjs:
|
|
2720
3554
|
@tabler/icons-react/dist/esm/icons/IconCopy.mjs:
|
|
2721
3555
|
@tabler/icons-react/dist/esm/icons/IconDownload.mjs:
|
|
2722
3556
|
@tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs:
|
|
@@ -2724,6 +3558,7 @@ function ChatMessage({ message }) {
|
|
|
2724
3558
|
@tabler/icons-react/dist/esm/icons/IconPhoto.mjs:
|
|
2725
3559
|
@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
|
|
2726
3560
|
@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
|
|
3561
|
+
@tabler/icons-react/dist/esm/icons/IconFlask2Filled.mjs:
|
|
2727
3562
|
@tabler/icons-react/dist/esm/tabler-icons-react.mjs:
|
|
2728
3563
|
(**
|
|
2729
3564
|
* @license @tabler/icons-react v3.37.1 - MIT
|