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