@shapesos/clay 0.9.0 → 0.11.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/README.md +46 -1
- package/dist/artifacts.cjs +741 -0
- package/dist/artifacts.cjs.map +1 -0
- package/dist/artifacts.d.cts +56 -0
- package/dist/artifacts.d.ts +56 -0
- package/dist/artifacts.js +23 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/blocks.cjs +1282 -0
- package/dist/blocks.cjs.map +1 -0
- package/dist/blocks.css +2 -0
- package/dist/blocks.d.cts +41 -0
- package/dist/blocks.d.ts +41 -0
- package/dist/blocks.js +31 -0
- package/dist/blocks.js.map +1 -0
- package/dist/button.d.cts +2 -2
- package/dist/button.d.ts +2 -2
- package/dist/chat.cjs +755 -281
- package/dist/chat.cjs.map +1 -1
- package/dist/chat.d.cts +31 -10
- package/dist/chat.d.ts +31 -10
- package/dist/chat.js +8 -3
- package/dist/chunk-BX5TCEPR.js +436 -0
- package/dist/chunk-BX5TCEPR.js.map +1 -0
- package/dist/chunk-JGMN6W72.js +12 -0
- package/dist/chunk-JGMN6W72.js.map +1 -0
- package/dist/{chunk-27GJUWVN.js → chunk-JJUIBBBU.js} +14 -8
- package/dist/chunk-JJUIBBBU.js.map +1 -0
- package/dist/chunk-L35M3OD5.js +99 -0
- package/dist/chunk-L35M3OD5.js.map +1 -0
- package/dist/chunk-MEJESPTZ.js +1 -0
- package/dist/chunk-MEJESPTZ.js.map +1 -0
- package/dist/chunk-MXOPG747.js +238 -0
- package/dist/chunk-MXOPG747.js.map +1 -0
- package/dist/{chunk-MLCRDVQ2.js → chunk-OBOXCBDL.js} +13 -5
- package/dist/chunk-OBOXCBDL.js.map +1 -0
- package/dist/chunk-OUW6PUEB.js +223 -0
- package/dist/chunk-OUW6PUEB.js.map +1 -0
- package/dist/{chunk-TDMJUF4A.js → chunk-WPQQVKWY.js} +4 -4
- package/dist/icon.cjs +12 -4
- package/dist/icon.cjs.map +1 -1
- package/dist/icon.d.cts +19 -6
- package/dist/icon.d.ts +19 -6
- package/dist/icon.js +1 -1
- package/dist/index.cjs +789 -273
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +61 -21
- package/dist/lottie.d.cts +2 -2
- package/dist/lottie.d.ts +2 -2
- package/dist/table.cjs +142 -0
- package/dist/table.cjs.map +1 -0
- package/dist/table.d.cts +44 -0
- package/dist/table.d.ts +44 -0
- package/dist/table.js +24 -0
- package/dist/table.js.map +1 -0
- package/dist/text-area.d.cts +2 -2
- package/dist/text-area.d.ts +2 -2
- package/dist/text-area.js +2 -2
- package/dist/types-3Gzk7cRt.d.cts +121 -0
- package/dist/types-3Gzk7cRt.d.ts +121 -0
- package/dist/types-C9XX-Uhk.d.ts +68 -0
- package/dist/types-DuuRI4ll.d.cts +68 -0
- package/dist/utils.cjs +14 -7
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +18 -1
- package/dist/utils.d.ts +18 -1
- package/dist/utils.js +6 -4
- package/package.json +34 -4
- package/dist/chunk-27GJUWVN.js.map +0 -1
- package/dist/chunk-A77BGJH4.js +0 -458
- package/dist/chunk-A77BGJH4.js.map +0 -1
- package/dist/chunk-MLCRDVQ2.js.map +0 -1
- /package/dist/{chunk-TDMJUF4A.js.map → chunk-WPQQVKWY.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -16342,9 +16342,16 @@ var require_lottie = __commonJS({
|
|
|
16342
16342
|
// src/index.ts
|
|
16343
16343
|
var src_exports = {};
|
|
16344
16344
|
__export(src_exports, {
|
|
16345
|
+
ArtifactDownloadButton: () => ArtifactDownloadButton,
|
|
16346
|
+
ArtifactRefBlock: () => ArtifactRefBlock,
|
|
16347
|
+
ArtifactRefBlockService: () => ArtifactRefBlockService,
|
|
16348
|
+
ArtifactServices: () => ArtifactServices,
|
|
16345
16349
|
BUTTON_INTENT: () => BUTTON_INTENT,
|
|
16346
16350
|
BUTTON_SIZE: () => BUTTON_SIZE,
|
|
16347
16351
|
BUTTON_VARIANT: () => BUTTON_VARIANT,
|
|
16352
|
+
Block: () => Block,
|
|
16353
|
+
BlockContext: () => BlockContext,
|
|
16354
|
+
BlockServices: () => BlockServices,
|
|
16348
16355
|
Button: () => Button2,
|
|
16349
16356
|
ChatContext: () => ChatContext,
|
|
16350
16357
|
ChatMessage: () => ChatMessage,
|
|
@@ -16356,16 +16363,25 @@ __export(src_exports, {
|
|
|
16356
16363
|
KeyboardShortcut: () => KeyboardShortcut,
|
|
16357
16364
|
Lottie: () => Lottie,
|
|
16358
16365
|
MESSAGE_ROLE: () => MESSAGE_ROLE,
|
|
16366
|
+
TableArtifact: () => TableArtifact,
|
|
16359
16367
|
TextArea: () => TextArea,
|
|
16368
|
+
TextBlockService: () => TextBlockService,
|
|
16369
|
+
artifactToClipboardText: () => artifactToClipboardText,
|
|
16370
|
+
artifactTypes: () => artifactTypes,
|
|
16371
|
+
blockTypes: () => blockTypes,
|
|
16360
16372
|
colors: () => colors,
|
|
16361
16373
|
convertTableToCSV: () => convertTableToCSV,
|
|
16374
|
+
copyMessageText: () => copyMessageText,
|
|
16375
|
+
escapeCsvField: () => escapeCsvField,
|
|
16362
16376
|
fontFamilies: () => fontFamilies,
|
|
16377
|
+
isSafeDownloadUrl: () => isSafeDownloadUrl,
|
|
16363
16378
|
markdownToPlainText: () => markdownToPlainText,
|
|
16364
16379
|
mergeRefs: () => mergeRefs,
|
|
16365
16380
|
parseMarkdownTable: () => parseMarkdownTable,
|
|
16366
16381
|
typographyMixin: () => typographyMixin,
|
|
16367
16382
|
typographyStyles: () => typographyStyles,
|
|
16368
16383
|
typographyTypes: () => typographyTypes,
|
|
16384
|
+
useBlockContext: () => useBlockContext,
|
|
16369
16385
|
useChatContext: () => useChatContext,
|
|
16370
16386
|
useCopyToClipboard: () => useCopyToClipboard
|
|
16371
16387
|
});
|
|
@@ -16754,203 +16770,43 @@ function typographyMixin(type) {
|
|
|
16754
16770
|
].join(";\n ");
|
|
16755
16771
|
}
|
|
16756
16772
|
|
|
16757
|
-
// src/components/
|
|
16758
|
-
var
|
|
16759
|
-
|
|
16760
|
-
|
|
16761
|
-
|
|
16762
|
-
// src/components/chat/scrollable-table/scrollable-table.tsx
|
|
16763
|
-
var import_react2 = require("react");
|
|
16773
|
+
// src/components/blocks/types.ts
|
|
16774
|
+
var blockTypes = {
|
|
16775
|
+
TEXT: "TEXT",
|
|
16776
|
+
ARTIFACT_REF: "ARTIFACT_REF"
|
|
16777
|
+
};
|
|
16764
16778
|
|
|
16765
|
-
// src/components/
|
|
16766
|
-
var
|
|
16767
|
-
|
|
16768
|
-
|
|
16769
|
-
const context = (0, import_react.useContext)(ChatContext);
|
|
16770
|
-
if (!context) {
|
|
16771
|
-
throw new Error("useChatContext must be used within a Chat.Root component");
|
|
16772
|
-
}
|
|
16773
|
-
return context;
|
|
16774
|
-
}
|
|
16779
|
+
// src/components/artifacts/types.ts
|
|
16780
|
+
var artifactTypes = {
|
|
16781
|
+
TABLE: "TABLE"
|
|
16782
|
+
};
|
|
16775
16783
|
|
|
16776
|
-
// src/components/
|
|
16777
|
-
var
|
|
16778
|
-
var TableContainer = import_styled_components.default.div`
|
|
16779
|
-
position: relative;
|
|
16780
|
-
margin-block: 8px 16px;
|
|
16781
|
-
`;
|
|
16782
|
-
var TableScroll = import_styled_components.default.div`
|
|
16783
|
-
width: 100%;
|
|
16784
|
-
overflow-x: auto;
|
|
16785
|
-
overflow-y: hidden;
|
|
16786
|
-
`;
|
|
16787
|
-
var TableActionsWrapper = import_styled_components.default.div`
|
|
16788
|
-
display: flex;
|
|
16789
|
-
justify-content: flex-start;
|
|
16790
|
-
margin-block: 8px 0;
|
|
16791
|
-
`;
|
|
16792
|
-
var TableActionsDivider = import_styled_components.default.div`
|
|
16793
|
-
height: 1px;
|
|
16794
|
-
background: ${colors["brown-40"]};
|
|
16795
|
-
margin-block: 8px 0;
|
|
16796
|
-
`;
|
|
16784
|
+
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
16785
|
+
var import_react7 = require("react");
|
|
16797
16786
|
|
|
16798
|
-
// src/
|
|
16799
|
-
var
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16803
|
-
counter.value += 1;
|
|
16804
|
-
}
|
|
16805
|
-
const context = (0, import_react2.useContext)(ChatContext);
|
|
16806
|
-
const TableActions = context?.TableActions;
|
|
16807
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableContainer, { children: [
|
|
16808
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { ...props }) }),
|
|
16809
|
-
TableActions && messageId && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
16810
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableActionsWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableActions, { messageId, tableIndex: currentIndex }) }),
|
|
16811
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableActionsDivider, {})
|
|
16812
|
-
] })
|
|
16813
|
-
] });
|
|
16787
|
+
// src/lib/utils.ts
|
|
16788
|
+
var import_clsx = require("clsx");
|
|
16789
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
16790
|
+
function cn(...inputs) {
|
|
16791
|
+
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
16814
16792
|
}
|
|
16815
16793
|
|
|
16816
|
-
// src/components/
|
|
16817
|
-
var
|
|
16818
|
-
var
|
|
16819
|
-
|
|
16820
|
-
|
|
16821
|
-
|
|
16822
|
-
|
|
16823
|
-
& h1 {
|
|
16824
|
-
${typographyMixin(typographyTypes.GEIST_HEADING_S_BOLD)};
|
|
16825
|
-
margin-block: 20px;
|
|
16826
|
-
}
|
|
16827
|
-
|
|
16828
|
-
& h2 {
|
|
16829
|
-
${typographyMixin(typographyTypes.GEIST_BODY_L_SEMI_BOLD)};
|
|
16830
|
-
margin-block: 12px;
|
|
16831
|
-
}
|
|
16832
|
-
|
|
16833
|
-
& h3,
|
|
16834
|
-
& h4,
|
|
16835
|
-
& h5,
|
|
16836
|
-
& h6 {
|
|
16837
|
-
${typographyMixin(typographyTypes.GEIST_BODY_M_SEMI_BOLD)};
|
|
16838
|
-
margin-block: 8px;
|
|
16839
|
-
}
|
|
16840
|
-
|
|
16841
|
-
& strong {
|
|
16842
|
-
${typographyMixin(typographyTypes.GEIST_BODY_S_SEMI_BOLD)};
|
|
16843
|
-
}
|
|
16844
|
-
|
|
16845
|
-
& p {
|
|
16846
|
-
margin-block: 0px;
|
|
16847
|
-
}
|
|
16848
|
-
|
|
16849
|
-
& p + p {
|
|
16850
|
-
margin-block: 8px 0px;
|
|
16851
|
-
}
|
|
16852
|
-
|
|
16853
|
-
& ul,
|
|
16854
|
-
& ol {
|
|
16855
|
-
margin-block: 16px;
|
|
16856
|
-
padding-left: 20px;
|
|
16857
|
-
}
|
|
16858
|
-
|
|
16859
|
-
& li + li {
|
|
16860
|
-
margin-block: 4px;
|
|
16861
|
-
}
|
|
16862
|
-
|
|
16863
|
-
& ol {
|
|
16864
|
-
list-style-type: decimal;
|
|
16865
|
-
}
|
|
16866
|
-
|
|
16867
|
-
& ol ol {
|
|
16868
|
-
list-style-type: lower-alpha;
|
|
16869
|
-
}
|
|
16870
|
-
|
|
16871
|
-
& ol ol ol {
|
|
16872
|
-
list-style-type: lower-roman;
|
|
16873
|
-
}
|
|
16874
|
-
|
|
16875
|
-
& a {
|
|
16876
|
-
color: inherit;
|
|
16877
|
-
text-decoration-line: underline;
|
|
16878
|
-
text-decoration-style: dotted;
|
|
16879
|
-
text-decoration-thickness: auto;
|
|
16880
|
-
text-underline-offset: auto;
|
|
16881
|
-
text-underline-position: from-font;
|
|
16882
|
-
transition: color 75ms ease-in-out;
|
|
16883
|
-
|
|
16884
|
-
&:hover {
|
|
16885
|
-
color: ${colors["blue-600"]};
|
|
16886
|
-
}
|
|
16887
|
-
}
|
|
16888
|
-
|
|
16889
|
-
& hr {
|
|
16890
|
-
border: none;
|
|
16891
|
-
border-top: 1px solid ${colors["brown-40"]};
|
|
16892
|
-
margin-block: 20px;
|
|
16893
|
-
}
|
|
16894
|
-
|
|
16895
|
-
& table {
|
|
16896
|
-
margin: 0;
|
|
16897
|
-
width: 100%;
|
|
16898
|
-
border-collapse: collapse;
|
|
16899
|
-
}
|
|
16900
|
-
|
|
16901
|
-
& th,
|
|
16902
|
-
& td {
|
|
16903
|
-
border: none;
|
|
16904
|
-
border-bottom: 1px solid ${colors["brown-40"]};
|
|
16905
|
-
text-align: left;
|
|
16906
|
-
}
|
|
16907
|
-
|
|
16908
|
-
& th {
|
|
16909
|
-
${typographyMixin(typographyTypes.GEIST_LABEL_CAPTION_MEDIUM)};
|
|
16910
|
-
padding: 8px;
|
|
16911
|
-
}
|
|
16912
|
-
|
|
16913
|
-
& td {
|
|
16914
|
-
${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
|
|
16915
|
-
padding: 16px 8px;
|
|
16916
|
-
min-width: 150px;
|
|
16917
|
-
width: 1%;
|
|
16918
|
-
}
|
|
16919
|
-
|
|
16920
|
-
& td strong {
|
|
16921
|
-
font-weight: inherit;
|
|
16922
|
-
font-size: inherit;
|
|
16923
|
-
line-height: inherit;
|
|
16924
|
-
}
|
|
16925
|
-
|
|
16926
|
-
& blockquote {
|
|
16927
|
-
margin-block: 4px;
|
|
16928
|
-
margin-inline: 0px;
|
|
16929
|
-
padding-left: 16px;
|
|
16930
|
-
border-left: 4px solid ${colors["brown-40"]};
|
|
16931
|
-
color: ${colors["brown-80"]};
|
|
16794
|
+
// src/components/ai-elements/artifact.tsx
|
|
16795
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
16796
|
+
var Artifact = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
16797
|
+
"div",
|
|
16798
|
+
{
|
|
16799
|
+
className: cn("flex flex-col overflow-hidden rounded-lg border bg-background shadow-sm", className),
|
|
16800
|
+
...props
|
|
16932
16801
|
}
|
|
16933
|
-
|
|
16934
|
-
|
|
16935
|
-
|
|
16936
|
-
var
|
|
16937
|
-
|
|
16938
|
-
const counter = { value: 0 };
|
|
16939
|
-
const sanitizedContent = content2.split("\n").filter((line) => {
|
|
16940
|
-
const t = line.trim();
|
|
16941
|
-
return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
|
|
16942
|
-
}).join("\n");
|
|
16943
|
-
const markdownComponents = {
|
|
16944
|
-
table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ScrollableTable, { ...tableProps, messageId, counter }))
|
|
16945
|
-
};
|
|
16946
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ContentWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: markdownComponents, children: sanitizedContent }) });
|
|
16947
|
-
}
|
|
16948
|
-
|
|
16949
|
-
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
16950
|
-
var import_react6 = require("react");
|
|
16802
|
+
);
|
|
16803
|
+
var ArtifactHeader = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("flex items-center justify-between border-b bg-muted/50 px-4 py-3", className), ...props });
|
|
16804
|
+
var ArtifactTitle = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: cn("font-medium text-foreground text-sm", className), ...props });
|
|
16805
|
+
var ArtifactActions = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("flex items-center gap-1", className), ...props });
|
|
16806
|
+
var ArtifactContent = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("flex-1 overflow-auto p-4", className), ...props });
|
|
16951
16807
|
|
|
16952
16808
|
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
16953
|
-
var
|
|
16809
|
+
var import_react = require("react");
|
|
16954
16810
|
|
|
16955
16811
|
// node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs
|
|
16956
16812
|
var defaultAttributes = {
|
|
@@ -16977,8 +16833,8 @@ var defaultAttributes = {
|
|
|
16977
16833
|
|
|
16978
16834
|
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
16979
16835
|
var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
|
|
16980
|
-
const Component = (0,
|
|
16981
|
-
({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => (0,
|
|
16836
|
+
const Component = (0, import_react.forwardRef)(
|
|
16837
|
+
({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => (0, import_react.createElement)(
|
|
16982
16838
|
"svg",
|
|
16983
16839
|
{
|
|
16984
16840
|
ref,
|
|
@@ -16995,8 +16851,8 @@ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
|
|
|
16995
16851
|
...rest
|
|
16996
16852
|
},
|
|
16997
16853
|
[
|
|
16998
|
-
title && (0,
|
|
16999
|
-
...iconNode.map(([tag, attrs]) => (0,
|
|
16854
|
+
title && (0, import_react.createElement)("title", { key: "svg-title" }, title),
|
|
16855
|
+
...iconNode.map(([tag, attrs]) => (0, import_react.createElement)(tag, attrs)),
|
|
17000
16856
|
...Array.isArray(children) ? children : [children]
|
|
17001
16857
|
]
|
|
17002
16858
|
)
|
|
@@ -17013,19 +16869,26 @@ var IconCheck = createReactComponent("outline", "check", "Check", __iconNode);
|
|
|
17013
16869
|
var __iconNode2 = [["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" }]];
|
|
17014
16870
|
var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode2);
|
|
17015
16871
|
|
|
16872
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconDownload.mjs
|
|
16873
|
+
var __iconNode3 = [["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" }]];
|
|
16874
|
+
var IconDownload = createReactComponent("outline", "download", "Download", __iconNode3);
|
|
16875
|
+
|
|
17016
16876
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
|
|
17017
|
-
var
|
|
17018
|
-
var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown",
|
|
16877
|
+
var __iconNode4 = [["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" }]];
|
|
16878
|
+
var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode4);
|
|
17019
16879
|
|
|
17020
16880
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
|
|
17021
|
-
var
|
|
17022
|
-
var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp",
|
|
16881
|
+
var __iconNode5 = [["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" }]];
|
|
16882
|
+
var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode5);
|
|
16883
|
+
|
|
16884
|
+
// src/components/icon-button/icon-button.tsx
|
|
16885
|
+
var import_react3 = require("react");
|
|
17023
16886
|
|
|
17024
16887
|
// src/components/icon/icon.tsx
|
|
17025
|
-
var
|
|
16888
|
+
var import_react2 = require("react");
|
|
17026
16889
|
|
|
17027
16890
|
// src/components/icon/icon-styles.ts
|
|
17028
|
-
var
|
|
16891
|
+
var import_styled_components = __toESM(require("styled-components"), 1);
|
|
17029
16892
|
var STROKE_WIDTH_BY_SIZE = {
|
|
17030
16893
|
12: 1.4,
|
|
17031
16894
|
14: 1.4,
|
|
@@ -17038,7 +16901,7 @@ var DEFAULT_STROKE_WIDTH = 1.8;
|
|
|
17038
16901
|
function getStrokeWidth(size) {
|
|
17039
16902
|
return STROKE_WIDTH_BY_SIZE[size] ?? DEFAULT_STROKE_WIDTH;
|
|
17040
16903
|
}
|
|
17041
|
-
var IconWrapper =
|
|
16904
|
+
var IconWrapper = import_styled_components.default.span`
|
|
17042
16905
|
display: inline-flex;
|
|
17043
16906
|
align-items: center;
|
|
17044
16907
|
justify-content: center;
|
|
@@ -17047,10 +16910,10 @@ var IconWrapper = import_styled_components3.default.span`
|
|
|
17047
16910
|
`;
|
|
17048
16911
|
|
|
17049
16912
|
// src/components/icon/icon.tsx
|
|
17050
|
-
var
|
|
16913
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
17051
16914
|
var DEFAULT_SIZE = 16;
|
|
17052
|
-
var Icon = (0,
|
|
17053
|
-
return /* @__PURE__ */ (0,
|
|
16915
|
+
var Icon = (0, import_react2.forwardRef)(function Icon2({ icon: IconComponent, size = DEFAULT_SIZE, color, className, "aria-label": ariaLabel }, ref) {
|
|
16916
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
17054
16917
|
IconWrapper,
|
|
17055
16918
|
{
|
|
17056
16919
|
ref,
|
|
@@ -17058,13 +16921,13 @@ var Icon = (0, import_react4.forwardRef)(function Icon2({ icon: IconComponent, s
|
|
|
17058
16921
|
$color: color,
|
|
17059
16922
|
"aria-label": ariaLabel,
|
|
17060
16923
|
role: ariaLabel ? "img" : void 0,
|
|
17061
|
-
children: /* @__PURE__ */ (0,
|
|
16924
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconComponent, { width: size, height: size, strokeWidth: getStrokeWidth(size) })
|
|
17062
16925
|
}
|
|
17063
16926
|
);
|
|
17064
16927
|
});
|
|
17065
16928
|
|
|
17066
16929
|
// src/components/icon-button/icon-button-styles.ts
|
|
17067
|
-
var
|
|
16930
|
+
var import_styled_components2 = __toESM(require("styled-components"), 1);
|
|
17068
16931
|
var PADDING = {
|
|
17069
16932
|
short: {
|
|
17070
16933
|
small: "4px",
|
|
@@ -17079,7 +16942,7 @@ var BORDER_RADIUS = {
|
|
|
17079
16942
|
small: 6,
|
|
17080
16943
|
medium: 10
|
|
17081
16944
|
};
|
|
17082
|
-
var Button =
|
|
16945
|
+
var Button = import_styled_components2.default.button`
|
|
17083
16946
|
display: inline-flex;
|
|
17084
16947
|
align-items: center;
|
|
17085
16948
|
justify-content: center;
|
|
@@ -17107,12 +16970,12 @@ var Button = import_styled_components4.default.button`
|
|
|
17107
16970
|
`;
|
|
17108
16971
|
|
|
17109
16972
|
// src/components/icon-button/icon-button.tsx
|
|
17110
|
-
var
|
|
16973
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
17111
16974
|
var ICON_SIZE_BY_BUTTON_SIZE = {
|
|
17112
16975
|
small: 16,
|
|
17113
16976
|
medium: 20
|
|
17114
16977
|
};
|
|
17115
|
-
|
|
16978
|
+
var IconButton = (0, import_react3.forwardRef)(function IconButton2({
|
|
17116
16979
|
icon,
|
|
17117
16980
|
size = "small",
|
|
17118
16981
|
variant = "short",
|
|
@@ -17122,11 +16985,14 @@ function IconButton({
|
|
|
17122
16985
|
className,
|
|
17123
16986
|
id,
|
|
17124
16987
|
as,
|
|
17125
|
-
"aria-label": ariaLabel
|
|
17126
|
-
|
|
17127
|
-
|
|
16988
|
+
"aria-label": ariaLabel,
|
|
16989
|
+
...rest
|
|
16990
|
+
}, ref) {
|
|
16991
|
+
const isNativeButton = as === void 0 || as === "button";
|
|
16992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
17128
16993
|
Button,
|
|
17129
16994
|
{
|
|
16995
|
+
ref,
|
|
17130
16996
|
className,
|
|
17131
16997
|
id,
|
|
17132
16998
|
as,
|
|
@@ -17136,22 +17002,406 @@ function IconButton({
|
|
|
17136
17002
|
disabled,
|
|
17137
17003
|
onClick: disabled ? void 0 : onClick,
|
|
17138
17004
|
"aria-label": ariaLabel,
|
|
17139
|
-
|
|
17005
|
+
...isNativeButton ? { type: "button" } : {},
|
|
17006
|
+
...rest,
|
|
17007
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { icon, size: ICON_SIZE_BY_BUTTON_SIZE[size] })
|
|
17140
17008
|
}
|
|
17141
17009
|
);
|
|
17010
|
+
});
|
|
17011
|
+
|
|
17012
|
+
// src/components/ui/tooltip.tsx
|
|
17013
|
+
var React = __toESM(require("react"), 1);
|
|
17014
|
+
var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"), 1);
|
|
17015
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
17016
|
+
var TooltipProvider = TooltipPrimitive.Provider;
|
|
17017
|
+
var Tooltip = TooltipPrimitive.Root;
|
|
17018
|
+
var TooltipTrigger = TooltipPrimitive.Trigger;
|
|
17019
|
+
var TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
17020
|
+
TooltipPrimitive.Content,
|
|
17021
|
+
{
|
|
17022
|
+
ref,
|
|
17023
|
+
sideOffset,
|
|
17024
|
+
className: cn(
|
|
17025
|
+
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-tooltip-content-transform-origin]",
|
|
17026
|
+
className
|
|
17027
|
+
),
|
|
17028
|
+
...props
|
|
17029
|
+
}
|
|
17030
|
+
));
|
|
17031
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
17032
|
+
|
|
17033
|
+
// src/components/artifacts/artifact-download-button/artifact-download-button.tsx
|
|
17034
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
17035
|
+
function ArtifactDownloadButton({ href }) {
|
|
17036
|
+
if (!isSafeDownloadUrl(href)) return null;
|
|
17037
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Tooltip, { children: [
|
|
17038
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
17039
|
+
IconButton,
|
|
17040
|
+
{
|
|
17041
|
+
as: "a",
|
|
17042
|
+
href,
|
|
17043
|
+
download: true,
|
|
17044
|
+
rel: "noopener noreferrer",
|
|
17045
|
+
icon: IconDownload,
|
|
17046
|
+
size: "small",
|
|
17047
|
+
"aria-label": "Download artifact"
|
|
17048
|
+
}
|
|
17049
|
+
) }),
|
|
17050
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TooltipContent, { children: "Download" })
|
|
17051
|
+
] }) });
|
|
17052
|
+
}
|
|
17053
|
+
function isSafeDownloadUrl(url) {
|
|
17054
|
+
try {
|
|
17055
|
+
const parsed = new URL(url);
|
|
17056
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
17057
|
+
} catch {
|
|
17058
|
+
return false;
|
|
17059
|
+
}
|
|
17142
17060
|
}
|
|
17143
17061
|
|
|
17144
|
-
// src/components/
|
|
17062
|
+
// src/components/ui/table.tsx
|
|
17063
|
+
var React2 = __toESM(require("react"), 1);
|
|
17064
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
17065
|
+
var Table = React2.forwardRef(({ className, containerClassName, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: cn("relative w-full overflow-auto", containerClassName), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("table", { ref, className: cn("w-full caption-bottom text-sm", className), ...props }) }));
|
|
17066
|
+
Table.displayName = "Table";
|
|
17067
|
+
var TableHeader = React2.forwardRef(
|
|
17068
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { ref, className: cn("[&_tr]:border-b", className), ...props })
|
|
17069
|
+
);
|
|
17070
|
+
TableHeader.displayName = "TableHeader";
|
|
17071
|
+
var TableBody = React2.forwardRef(
|
|
17072
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props })
|
|
17073
|
+
);
|
|
17074
|
+
TableBody.displayName = "TableBody";
|
|
17075
|
+
var TableFooter = React2.forwardRef(
|
|
17076
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tfoot", { ref, className: cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className), ...props })
|
|
17077
|
+
);
|
|
17078
|
+
TableFooter.displayName = "TableFooter";
|
|
17079
|
+
var TableRow = React2.forwardRef(
|
|
17080
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
17081
|
+
"tr",
|
|
17082
|
+
{
|
|
17083
|
+
ref,
|
|
17084
|
+
className: cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className),
|
|
17085
|
+
...props
|
|
17086
|
+
}
|
|
17087
|
+
)
|
|
17088
|
+
);
|
|
17089
|
+
TableRow.displayName = "TableRow";
|
|
17090
|
+
var TableHead = React2.forwardRef(
|
|
17091
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
17092
|
+
"th",
|
|
17093
|
+
{
|
|
17094
|
+
ref,
|
|
17095
|
+
className: cn(
|
|
17096
|
+
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
|
17097
|
+
className
|
|
17098
|
+
),
|
|
17099
|
+
...props
|
|
17100
|
+
}
|
|
17101
|
+
)
|
|
17102
|
+
);
|
|
17103
|
+
TableHead.displayName = "TableHead";
|
|
17104
|
+
var TableCell = React2.forwardRef(
|
|
17105
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { ref, className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className), ...props })
|
|
17106
|
+
);
|
|
17107
|
+
TableCell.displayName = "TableCell";
|
|
17108
|
+
var TableCaption = React2.forwardRef(
|
|
17109
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("caption", { ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props })
|
|
17110
|
+
);
|
|
17111
|
+
TableCaption.displayName = "TableCaption";
|
|
17112
|
+
|
|
17113
|
+
// src/components/table/use-scroll-shadow.ts
|
|
17114
|
+
var import_react4 = require("react");
|
|
17115
|
+
function useScrollShadow() {
|
|
17116
|
+
const targetRef = (0, import_react4.useRef)(null);
|
|
17117
|
+
const [isScrolled, setIsScrolled] = (0, import_react4.useState)(false);
|
|
17118
|
+
(0, import_react4.useEffect)(() => {
|
|
17119
|
+
const target = targetRef.current;
|
|
17120
|
+
if (!target) return;
|
|
17121
|
+
let scrollContainer = target;
|
|
17122
|
+
while (scrollContainer) {
|
|
17123
|
+
const overflowY = getComputedStyle(scrollContainer).overflowY;
|
|
17124
|
+
if (overflowY === "auto" || overflowY === "scroll") break;
|
|
17125
|
+
scrollContainer = scrollContainer.parentElement;
|
|
17126
|
+
}
|
|
17127
|
+
if (!scrollContainer) return;
|
|
17128
|
+
setIsScrolled(scrollContainer.scrollTop > 0);
|
|
17129
|
+
const handleScroll = () => {
|
|
17130
|
+
if (!scrollContainer) return;
|
|
17131
|
+
setIsScrolled(scrollContainer.scrollTop > 0);
|
|
17132
|
+
};
|
|
17133
|
+
scrollContainer.addEventListener("scroll", handleScroll, { passive: true });
|
|
17134
|
+
return () => scrollContainer.removeEventListener("scroll", handleScroll);
|
|
17135
|
+
}, []);
|
|
17136
|
+
return { targetRef, isScrolled };
|
|
17137
|
+
}
|
|
17138
|
+
|
|
17139
|
+
// src/components/artifacts/table-artifact/table-artifact-styles.ts
|
|
17145
17140
|
var import_react5 = require("react");
|
|
17141
|
+
function StatusMessage({ $tone, children }) {
|
|
17142
|
+
return (0, import_react5.createElement)(
|
|
17143
|
+
"div",
|
|
17144
|
+
{
|
|
17145
|
+
className: `py-6 px-2 text-center text-sm font-medium leading-5 ${$tone === "error" ? "text-red-600" : "text-brown-70"}`
|
|
17146
|
+
},
|
|
17147
|
+
children
|
|
17148
|
+
);
|
|
17149
|
+
}
|
|
17146
17150
|
|
|
17147
|
-
// src/
|
|
17148
|
-
|
|
17149
|
-
|
|
17150
|
-
|
|
17151
|
-
|
|
17151
|
+
// src/components/artifacts/table-artifact/table-artifact-content.constants.ts
|
|
17152
|
+
var TABLE_STATUS = {
|
|
17153
|
+
LOADING: "loading",
|
|
17154
|
+
READY: "ready",
|
|
17155
|
+
ERROR: "error",
|
|
17156
|
+
UNAVAILABLE: "unavailable"
|
|
17157
|
+
};
|
|
17158
|
+
|
|
17159
|
+
// src/components/artifacts/table-artifact/table-artifact-content.utils.ts
|
|
17160
|
+
function formatCell(row, column) {
|
|
17161
|
+
return row[column.key] ?? "";
|
|
17162
|
+
}
|
|
17163
|
+
var HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
|
|
17164
|
+
var CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
|
|
17165
|
+
var ROW_CLASSES = "border-b-brown-30 bg-background/70 hover:bg-secondary";
|
|
17166
|
+
var DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;
|
|
17167
|
+
var SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
|
|
17168
|
+
|
|
17169
|
+
// src/components/artifacts/table-artifact/table-artifact-content.tsx
|
|
17170
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
17171
|
+
function TableArtifactContent({
|
|
17172
|
+
columns,
|
|
17173
|
+
data: data2,
|
|
17174
|
+
knownRowCount,
|
|
17175
|
+
maxShimmerRows,
|
|
17176
|
+
maxBodyHeight,
|
|
17177
|
+
unavailableMessage
|
|
17178
|
+
}) {
|
|
17179
|
+
if (data2.status === TABLE_STATUS.ERROR) {
|
|
17180
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StatusMessage, { $tone: "error", children: "Couldn't load table data." });
|
|
17181
|
+
}
|
|
17182
|
+
if (data2.status === TABLE_STATUS.UNAVAILABLE) {
|
|
17183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StatusMessage, { $tone: "info", children: unavailableMessage });
|
|
17184
|
+
}
|
|
17185
|
+
if (data2.status === TABLE_STATUS.LOADING) {
|
|
17186
|
+
if (typeof knownRowCount === "number" && knownRowCount > 0) {
|
|
17187
|
+
const shimmerCount = Math.min(knownRowCount, maxShimmerRows);
|
|
17188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
|
|
17189
|
+
}
|
|
17190
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StatusMessage, { $tone: "info", children: "Loading table\u2026" });
|
|
17191
|
+
}
|
|
17192
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArtifactTable, { columns, maxBodyHeight, children: data2.rows.length === 0 ? renderEmptyRow(columns.length) : renderDataRows(columns, data2.rows) });
|
|
17193
|
+
}
|
|
17194
|
+
function ArtifactTable({ columns, maxBodyHeight, children }) {
|
|
17195
|
+
const { targetRef, isScrolled } = useScrollShadow();
|
|
17196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref: targetRef, className: "overscroll-none", style: { maxHeight: maxBodyHeight, overflowY: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Table, { containerClassName: "overflow-visible", children: [
|
|
17197
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
17198
|
+
TableHeader,
|
|
17199
|
+
{
|
|
17200
|
+
"data-scrolled": isScrolled ? "true" : void 0,
|
|
17201
|
+
className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
|
|
17202
|
+
style: isScrolled ? { boxShadow: SCROLL_SHADOW } : void 0,
|
|
17203
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableRow, { className: "hover:bg-transparent", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableHead, { scope: "col", className: HEAD_CLASS, children: column.label }, column.key)) })
|
|
17204
|
+
}
|
|
17205
|
+
),
|
|
17206
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableBody, { children })
|
|
17207
|
+
] }) });
|
|
17208
|
+
}
|
|
17209
|
+
function renderShimmerRows(columns, count) {
|
|
17210
|
+
return Array.from({ length: count }).map((_, index2) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableRow, { className: ROW_CLASSES, "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableCell, { className: CELL_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20" }) }, column.key)) }, `shimmer-${index2}`));
|
|
17211
|
+
}
|
|
17212
|
+
function renderDataRows(columns, rows) {
|
|
17213
|
+
return rows.map((row, index2) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableRow, { className: DATA_ROW_CLASSES, children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableCell, { className: CELL_CLASS, children: formatCell(row, column) }, column.key)) }, index2));
|
|
17214
|
+
}
|
|
17215
|
+
function renderEmptyRow(colSpan) {
|
|
17216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableCell, { colSpan, className: "py-6 text-center text-sm text-muted-foreground", children: "No rows to display." }) });
|
|
17217
|
+
}
|
|
17218
|
+
|
|
17219
|
+
// src/components/artifacts/table-artifact/use-table-artifact-data.ts
|
|
17220
|
+
var import_react6 = require("react");
|
|
17221
|
+
|
|
17222
|
+
// src/components/artifacts/table-artifact/parse-csv.ts
|
|
17223
|
+
var import_papaparse = __toESM(require("papaparse"), 1);
|
|
17224
|
+
function parseCsv(text2, columns) {
|
|
17225
|
+
const result = import_papaparse.default.parse(text2, {
|
|
17226
|
+
header: true,
|
|
17227
|
+
skipEmptyLines: true,
|
|
17228
|
+
dynamicTyping: false
|
|
17229
|
+
});
|
|
17230
|
+
const csvHeaders = new Set(result.meta?.fields ?? []);
|
|
17231
|
+
const presentColumns = columns.filter((col) => csvHeaders.has(col.key));
|
|
17232
|
+
return result.data.map((rawRow) => {
|
|
17233
|
+
const row = {};
|
|
17234
|
+
for (const column of presentColumns) {
|
|
17235
|
+
const value2 = rawRow[column.key];
|
|
17236
|
+
row[column.key] = value2 === void 0 || value2 === "" ? null : value2;
|
|
17237
|
+
}
|
|
17238
|
+
return row;
|
|
17239
|
+
});
|
|
17240
|
+
}
|
|
17241
|
+
|
|
17242
|
+
// src/components/artifacts/table-artifact/use-table-artifact-data.ts
|
|
17243
|
+
var LOADING = { status: "loading", rows: null, error: null };
|
|
17244
|
+
var UNAVAILABLE = { status: "unavailable", rows: null, error: null };
|
|
17245
|
+
var INITIAL_INTERNAL = { cacheKey: null, data: LOADING };
|
|
17246
|
+
function columnsFingerprint(columns) {
|
|
17247
|
+
return columns.map((c) => `${c.key}:${c.type ?? "string"}`).join("|");
|
|
17248
|
+
}
|
|
17249
|
+
function useTableArtifactData(presignedUrl, columns) {
|
|
17250
|
+
const colsKey = (0, import_react6.useMemo)(() => columnsFingerprint(columns), [columns]);
|
|
17251
|
+
const cacheKey = presignedUrl ? `${presignedUrl}::${colsKey}` : null;
|
|
17252
|
+
const [state, setState] = (0, import_react6.useState)(INITIAL_INTERNAL);
|
|
17253
|
+
(0, import_react6.useEffect)(() => {
|
|
17254
|
+
if (!presignedUrl) return;
|
|
17255
|
+
const controller = new AbortController();
|
|
17256
|
+
fetch(presignedUrl, {
|
|
17257
|
+
signal: controller.signal,
|
|
17258
|
+
headers: { Accept: "text/csv" },
|
|
17259
|
+
// Presigned URLs are cross-origin S3 in production and don't need credentials. Explicit
|
|
17260
|
+
// omit so a same-origin URL (compromised payload, local dev) can't accidentally receive
|
|
17261
|
+
// session cookies or auth headers.
|
|
17262
|
+
credentials: "omit"
|
|
17263
|
+
}).then(async (response) => {
|
|
17264
|
+
if (!response.ok) throw new Error(`Failed to load table data (${response.status})`);
|
|
17265
|
+
return response.text();
|
|
17266
|
+
}).then((text2) => {
|
|
17267
|
+
if (controller.signal.aborted) return;
|
|
17268
|
+
try {
|
|
17269
|
+
const rows = parseCsv(text2, columns);
|
|
17270
|
+
setState({ cacheKey: `${presignedUrl}::${colsKey}`, data: { status: "ready", rows, error: null } });
|
|
17271
|
+
} catch (parseError) {
|
|
17272
|
+
console.error("[TableArtifact] CSV parse failed", parseError);
|
|
17273
|
+
const err = parseError instanceof Error ? parseError : new Error(String(parseError));
|
|
17274
|
+
setState({ cacheKey: `${presignedUrl}::${colsKey}`, data: { status: "error", rows: null, error: err } });
|
|
17275
|
+
}
|
|
17276
|
+
}).catch((error) => {
|
|
17277
|
+
if (controller.signal.aborted) return;
|
|
17278
|
+
console.error("[TableArtifact] Fetch failed", error);
|
|
17279
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
17280
|
+
setState({ cacheKey: `${presignedUrl}::${colsKey}`, data: { status: "error", rows: null, error: err } });
|
|
17281
|
+
});
|
|
17282
|
+
return () => {
|
|
17283
|
+
controller.abort();
|
|
17284
|
+
};
|
|
17285
|
+
}, [presignedUrl, colsKey]);
|
|
17286
|
+
if (!presignedUrl) return UNAVAILABLE;
|
|
17287
|
+
if (state.cacheKey !== cacheKey) return LOADING;
|
|
17288
|
+
return state.data;
|
|
17289
|
+
}
|
|
17290
|
+
|
|
17291
|
+
// src/components/artifacts/table-artifact/validate.ts
|
|
17292
|
+
function isValidTableConfig(config) {
|
|
17293
|
+
if (!config || typeof config !== "object") return false;
|
|
17294
|
+
const candidate = config;
|
|
17295
|
+
if (!Array.isArray(candidate.columns)) return false;
|
|
17296
|
+
if (candidate.columns.length === 0) return false;
|
|
17297
|
+
return candidate.columns.every(isValidTableColumn);
|
|
17298
|
+
}
|
|
17299
|
+
function isValidTableColumn(column) {
|
|
17300
|
+
if (!column || typeof column !== "object") return false;
|
|
17301
|
+
const candidate = column;
|
|
17302
|
+
if (typeof candidate.key !== "string" || candidate.key.length === 0) return false;
|
|
17303
|
+
if (typeof candidate.label !== "string") return false;
|
|
17304
|
+
return true;
|
|
17305
|
+
}
|
|
17306
|
+
|
|
17307
|
+
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
17308
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
17309
|
+
var TITLE_CLASSES = "text-sm font-semibold text-foreground";
|
|
17310
|
+
var TABLE_MAX_BODY_HEIGHT = 480;
|
|
17311
|
+
var MAX_SHIMMER_ROWS = 10;
|
|
17312
|
+
var MSG_UNAVAILABLE = "Table data is unavailable.";
|
|
17313
|
+
function TableArtifact({ artifact }) {
|
|
17314
|
+
const validConfig = isValidTableConfig(artifact.config);
|
|
17315
|
+
const validColumns = validConfig ? artifact.config.columns : null;
|
|
17316
|
+
(0, import_react7.useEffect)(() => {
|
|
17317
|
+
if (validConfig) return;
|
|
17318
|
+
console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
|
|
17319
|
+
}, [validConfig]);
|
|
17320
|
+
const data2 = useTableArtifactData(
|
|
17321
|
+
validConfig ? artifact.protectedAsset?.presignedUrl ?? null : null,
|
|
17322
|
+
validColumns ?? []
|
|
17152
17323
|
);
|
|
17324
|
+
const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
|
|
17325
|
+
if (!validConfig || !validColumns) {
|
|
17326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
17327
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
|
|
17328
|
+
artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArtifactTitle, { className: TITLE_CLASSES, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", {}),
|
|
17329
|
+
presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArtifactDownloadButton, { href: presignedUrl }) }) : null
|
|
17330
|
+
] }),
|
|
17331
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StatusMessage, { $tone: "info", children: MSG_UNAVAILABLE }) })
|
|
17332
|
+
] });
|
|
17333
|
+
}
|
|
17334
|
+
return (
|
|
17335
|
+
// The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
|
|
17336
|
+
// Disable the outer overflow container so only one scroll context exists — this prevents
|
|
17337
|
+
// double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
|
|
17338
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
17339
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
|
|
17340
|
+
artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArtifactTitle, { className: TITLE_CLASSES, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", {}),
|
|
17341
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArtifactDownloadButton, { href: presignedUrl ?? "" }) })
|
|
17342
|
+
] }),
|
|
17343
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
17344
|
+
TableArtifactContent,
|
|
17345
|
+
{
|
|
17346
|
+
columns: validColumns,
|
|
17347
|
+
data: data2,
|
|
17348
|
+
knownRowCount: artifact.config.stats?.rowCount,
|
|
17349
|
+
maxShimmerRows: MAX_SHIMMER_ROWS,
|
|
17350
|
+
maxBodyHeight: TABLE_MAX_BODY_HEIGHT,
|
|
17351
|
+
unavailableMessage: MSG_UNAVAILABLE
|
|
17352
|
+
}
|
|
17353
|
+
) })
|
|
17354
|
+
] })
|
|
17355
|
+
);
|
|
17356
|
+
}
|
|
17357
|
+
|
|
17358
|
+
// src/components/artifacts/table-artifact/to-clipboard-text.ts
|
|
17359
|
+
function tableArtifactToClipboardText(artifact) {
|
|
17360
|
+
const trimmedTitle = artifact.title?.trim();
|
|
17361
|
+
return trimmedTitle || "Table";
|
|
17362
|
+
}
|
|
17363
|
+
|
|
17364
|
+
// src/components/artifacts/artifact-services/table-artifact-service.ts
|
|
17365
|
+
var TableArtifactService = {
|
|
17366
|
+
type: artifactTypes.TABLE,
|
|
17367
|
+
Component: TableArtifact,
|
|
17368
|
+
toClipboardText: tableArtifactToClipboardText
|
|
17369
|
+
};
|
|
17370
|
+
|
|
17371
|
+
// src/components/artifacts/artifact-services/index.ts
|
|
17372
|
+
var ArtifactServices = {
|
|
17373
|
+
[artifactTypes.TABLE]: TableArtifactService
|
|
17374
|
+
};
|
|
17375
|
+
function artifactToClipboardText(artifact) {
|
|
17376
|
+
const entry = ArtifactServices[artifact.type];
|
|
17377
|
+
if (!entry) {
|
|
17378
|
+
return `[Artifact: ${artifact.title ?? artifact.type}]`;
|
|
17379
|
+
}
|
|
17380
|
+
return entry.toClipboardText(artifact);
|
|
17381
|
+
}
|
|
17382
|
+
|
|
17383
|
+
// src/components/blocks/artifact-ref-block/artifact-ref-block.tsx
|
|
17384
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
17385
|
+
function ArtifactRefBlock({ block }) {
|
|
17386
|
+
const { artifact } = block.payload;
|
|
17387
|
+
const entry = ArtifactServices[artifact.type];
|
|
17388
|
+
if (!entry) return null;
|
|
17389
|
+
const { Component } = entry;
|
|
17390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Component, { artifact });
|
|
17153
17391
|
}
|
|
17154
17392
|
|
|
17393
|
+
// src/components/blocks/block-services/artifact-ref-block-service.ts
|
|
17394
|
+
var ArtifactRefBlockService = {
|
|
17395
|
+
type: blockTypes.ARTIFACT_REF,
|
|
17396
|
+
Component: ArtifactRefBlock,
|
|
17397
|
+
/**
|
|
17398
|
+
* Delegates to the registered artifact component's `toClipboardText`. Falls back to
|
|
17399
|
+
* `[Artifact: <title>]` via `artifactToClipboardText`'s own fallback when the artifact type
|
|
17400
|
+
* has no registered component, so copy never silently produces an empty string.
|
|
17401
|
+
*/
|
|
17402
|
+
toClipboardText: (block) => artifactToClipboardText(block.payload.artifact)
|
|
17403
|
+
};
|
|
17404
|
+
|
|
17155
17405
|
// src/utils/markdown-to-plain-text.ts
|
|
17156
17406
|
var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
|
|
17157
17407
|
var PLACEHOLDER_SUFFIX = "\u200B\u200B";
|
|
@@ -17171,18 +17421,253 @@ function markdownToPlainText(markdown) {
|
|
|
17171
17421
|
return result;
|
|
17172
17422
|
}
|
|
17173
17423
|
|
|
17424
|
+
// src/components/blocks/text-block/text-block.tsx
|
|
17425
|
+
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
17426
|
+
var import_remark_breaks = __toESM(require("remark-breaks"), 1);
|
|
17427
|
+
var import_remark_gfm = __toESM(require("remark-gfm"), 1);
|
|
17428
|
+
|
|
17429
|
+
// src/components/blocks/scrollable-table/scrollable-table-styles.ts
|
|
17430
|
+
var import_styled_components3 = __toESM(require("styled-components"), 1);
|
|
17431
|
+
var TableContainer = import_styled_components3.default.div`
|
|
17432
|
+
position: relative;
|
|
17433
|
+
margin-block: 8px 16px;
|
|
17434
|
+
`;
|
|
17435
|
+
var TableScroll = import_styled_components3.default.div`
|
|
17436
|
+
width: 100%;
|
|
17437
|
+
overflow-x: auto;
|
|
17438
|
+
overflow-y: hidden;
|
|
17439
|
+
`;
|
|
17440
|
+
|
|
17441
|
+
// src/components/blocks/scrollable-table/scrollable-table.tsx
|
|
17442
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
17443
|
+
function ScrollableTable({ node: _node, ...props }) {
|
|
17444
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TableContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("table", { ...props }) }) });
|
|
17445
|
+
}
|
|
17446
|
+
|
|
17447
|
+
// src/components/blocks/text-block/sanitize.ts
|
|
17448
|
+
function sanitize(text2) {
|
|
17449
|
+
return text2.split("\n").filter((line) => {
|
|
17450
|
+
const t = line.trim();
|
|
17451
|
+
return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
|
|
17452
|
+
}).join("\n");
|
|
17453
|
+
}
|
|
17454
|
+
|
|
17455
|
+
// src/components/blocks/text-block/text-block-styles.ts
|
|
17456
|
+
var import_styled_components4 = __toESM(require("styled-components"), 1);
|
|
17457
|
+
var TextBlockWrapper = import_styled_components4.default.div`
|
|
17458
|
+
${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
|
|
17459
|
+
color: ${colors["brown-100"]};
|
|
17460
|
+
word-break: break-word;
|
|
17461
|
+
|
|
17462
|
+
& h1 {
|
|
17463
|
+
${typographyMixin(typographyTypes.GEIST_HEADING_S_BOLD)};
|
|
17464
|
+
margin-block: 20px;
|
|
17465
|
+
}
|
|
17466
|
+
|
|
17467
|
+
& h2 {
|
|
17468
|
+
${typographyMixin(typographyTypes.GEIST_BODY_L_SEMI_BOLD)};
|
|
17469
|
+
margin-block: 12px;
|
|
17470
|
+
}
|
|
17471
|
+
|
|
17472
|
+
& h3,
|
|
17473
|
+
& h4,
|
|
17474
|
+
& h5,
|
|
17475
|
+
& h6 {
|
|
17476
|
+
${typographyMixin(typographyTypes.GEIST_BODY_M_SEMI_BOLD)};
|
|
17477
|
+
margin-block: 8px;
|
|
17478
|
+
}
|
|
17479
|
+
|
|
17480
|
+
& strong {
|
|
17481
|
+
${typographyMixin(typographyTypes.GEIST_BODY_S_SEMI_BOLD)};
|
|
17482
|
+
}
|
|
17483
|
+
|
|
17484
|
+
& p {
|
|
17485
|
+
margin-block: 0px;
|
|
17486
|
+
}
|
|
17487
|
+
|
|
17488
|
+
& p + p {
|
|
17489
|
+
margin-block: 8px 0px;
|
|
17490
|
+
}
|
|
17491
|
+
|
|
17492
|
+
& ul,
|
|
17493
|
+
& ol {
|
|
17494
|
+
margin-block: 16px;
|
|
17495
|
+
padding-left: 20px;
|
|
17496
|
+
}
|
|
17497
|
+
|
|
17498
|
+
& li + li {
|
|
17499
|
+
margin-block: 4px;
|
|
17500
|
+
}
|
|
17501
|
+
|
|
17502
|
+
& ol {
|
|
17503
|
+
list-style-type: decimal;
|
|
17504
|
+
}
|
|
17505
|
+
|
|
17506
|
+
& ol ol {
|
|
17507
|
+
list-style-type: lower-alpha;
|
|
17508
|
+
}
|
|
17509
|
+
|
|
17510
|
+
& ol ol ol {
|
|
17511
|
+
list-style-type: lower-roman;
|
|
17512
|
+
}
|
|
17513
|
+
|
|
17514
|
+
& a {
|
|
17515
|
+
color: inherit;
|
|
17516
|
+
text-decoration-line: underline;
|
|
17517
|
+
text-decoration-style: dotted;
|
|
17518
|
+
text-decoration-thickness: auto;
|
|
17519
|
+
text-underline-offset: auto;
|
|
17520
|
+
text-underline-position: from-font;
|
|
17521
|
+
transition: color 75ms ease-in-out;
|
|
17522
|
+
|
|
17523
|
+
&:hover {
|
|
17524
|
+
color: ${colors["blue-600"]};
|
|
17525
|
+
}
|
|
17526
|
+
}
|
|
17527
|
+
|
|
17528
|
+
& hr {
|
|
17529
|
+
border: none;
|
|
17530
|
+
border-top: 1px solid ${colors["brown-40"]};
|
|
17531
|
+
margin-block: 20px;
|
|
17532
|
+
}
|
|
17533
|
+
|
|
17534
|
+
& table {
|
|
17535
|
+
margin: 0;
|
|
17536
|
+
width: 100%;
|
|
17537
|
+
border-collapse: collapse;
|
|
17538
|
+
}
|
|
17539
|
+
|
|
17540
|
+
& th,
|
|
17541
|
+
& td {
|
|
17542
|
+
border: none;
|
|
17543
|
+
border-bottom: 1px solid ${colors["brown-40"]};
|
|
17544
|
+
text-align: left;
|
|
17545
|
+
}
|
|
17546
|
+
|
|
17547
|
+
& th {
|
|
17548
|
+
${typographyMixin(typographyTypes.GEIST_LABEL_CAPTION_MEDIUM)};
|
|
17549
|
+
padding: 8px;
|
|
17550
|
+
}
|
|
17551
|
+
|
|
17552
|
+
& td {
|
|
17553
|
+
${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
|
|
17554
|
+
padding: 16px 8px;
|
|
17555
|
+
min-width: 150px;
|
|
17556
|
+
width: 1%;
|
|
17557
|
+
}
|
|
17558
|
+
|
|
17559
|
+
& td strong {
|
|
17560
|
+
font-weight: inherit;
|
|
17561
|
+
font-size: inherit;
|
|
17562
|
+
line-height: inherit;
|
|
17563
|
+
}
|
|
17564
|
+
|
|
17565
|
+
& blockquote {
|
|
17566
|
+
margin-block: 4px;
|
|
17567
|
+
margin-inline: 0px;
|
|
17568
|
+
padding-left: 16px;
|
|
17569
|
+
border-left: 4px solid ${colors["brown-40"]};
|
|
17570
|
+
color: ${colors["brown-80"]};
|
|
17571
|
+
}
|
|
17572
|
+
`;
|
|
17573
|
+
|
|
17574
|
+
// src/components/blocks/text-block/text-block.tsx
|
|
17575
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
17576
|
+
var markdownComponents = {
|
|
17577
|
+
table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScrollableTable, { ...tableProps }))
|
|
17578
|
+
};
|
|
17579
|
+
function TextBlock({ block }) {
|
|
17580
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TextBlockWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: markdownComponents, children: sanitize(block.payload.text) }) });
|
|
17581
|
+
}
|
|
17582
|
+
|
|
17583
|
+
// src/components/blocks/block-services/text-block-service.ts
|
|
17584
|
+
var TextBlockService = {
|
|
17585
|
+
type: blockTypes.TEXT,
|
|
17586
|
+
Component: TextBlock,
|
|
17587
|
+
/**
|
|
17588
|
+
* Converts the block's markdown source to plain text so the final clipboard value is clean
|
|
17589
|
+
* when pasted into tools that don't render markdown. Each block type owns its own clipboard
|
|
17590
|
+
* conversion so `useCopyToClipboard` can write text verbatim without a second pass.
|
|
17591
|
+
*/
|
|
17592
|
+
toClipboardText: (block) => markdownToPlainText(block.payload.text)
|
|
17593
|
+
};
|
|
17594
|
+
|
|
17595
|
+
// src/components/blocks/block-services/index.ts
|
|
17596
|
+
var BlockServices = {
|
|
17597
|
+
[blockTypes.TEXT]: TextBlockService,
|
|
17598
|
+
[blockTypes.ARTIFACT_REF]: ArtifactRefBlockService
|
|
17599
|
+
};
|
|
17600
|
+
|
|
17601
|
+
// src/components/blocks/block/block.tsx
|
|
17602
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
17603
|
+
function Block({ block }) {
|
|
17604
|
+
const service = BlockServices[block.type];
|
|
17605
|
+
if (!service) return null;
|
|
17606
|
+
const { Component } = service;
|
|
17607
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Component, { block });
|
|
17608
|
+
}
|
|
17609
|
+
|
|
17610
|
+
// src/components/blocks/block-context/block-context.tsx
|
|
17611
|
+
var import_react8 = require("react");
|
|
17612
|
+
var BlockContext = (0, import_react8.createContext)(null);
|
|
17613
|
+
function useBlockContext() {
|
|
17614
|
+
return (0, import_react8.useContext)(BlockContext) ?? {};
|
|
17615
|
+
}
|
|
17616
|
+
|
|
17617
|
+
// src/components/chat/chat-message/chat-message.tsx
|
|
17618
|
+
var import_react12 = require("react");
|
|
17619
|
+
|
|
17620
|
+
// src/components/chat/hooks/copy-message-text.ts
|
|
17621
|
+
function copyMessageText(message) {
|
|
17622
|
+
const parts = [];
|
|
17623
|
+
for (const block of message.blocks) {
|
|
17624
|
+
const service = BlockServices[block.type];
|
|
17625
|
+
if (!service) continue;
|
|
17626
|
+
if (!service.toClipboardText) continue;
|
|
17627
|
+
const text2 = service.toClipboardText(block);
|
|
17628
|
+
if (text2) parts.push(text2);
|
|
17629
|
+
}
|
|
17630
|
+
if (parts.length === 0) return message.fallbackText;
|
|
17631
|
+
return parts.join("\n\n");
|
|
17632
|
+
}
|
|
17633
|
+
|
|
17634
|
+
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
17635
|
+
var import_react11 = require("react");
|
|
17636
|
+
|
|
17637
|
+
// src/components/chat/chat-context/chat-context.ts
|
|
17638
|
+
var import_react9 = require("react");
|
|
17639
|
+
var ChatContext = (0, import_react9.createContext)(null);
|
|
17640
|
+
function useChatContext() {
|
|
17641
|
+
const context = (0, import_react9.useContext)(ChatContext);
|
|
17642
|
+
if (!context) {
|
|
17643
|
+
throw new Error("useChatContext must be used within a Chat.Root component");
|
|
17644
|
+
}
|
|
17645
|
+
return context;
|
|
17646
|
+
}
|
|
17647
|
+
|
|
17648
|
+
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
17649
|
+
var import_react10 = require("react");
|
|
17650
|
+
|
|
17651
|
+
// src/utils/clipboard.ts
|
|
17652
|
+
function copyToClipboard(text2, options) {
|
|
17653
|
+
navigator.clipboard.writeText(text2).then(
|
|
17654
|
+
() => options?.onSuccess?.(),
|
|
17655
|
+
(error) => options?.onFailure?.(error)
|
|
17656
|
+
);
|
|
17657
|
+
}
|
|
17658
|
+
|
|
17174
17659
|
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
17175
17660
|
var RESET_DELAY_MS = 2e3;
|
|
17176
17661
|
function useCopyToClipboard() {
|
|
17177
|
-
const [isCopied, setIsCopied] = (0,
|
|
17178
|
-
const timeoutRef = (0,
|
|
17179
|
-
(0,
|
|
17662
|
+
const [isCopied, setIsCopied] = (0, import_react10.useState)(false);
|
|
17663
|
+
const timeoutRef = (0, import_react10.useRef)(null);
|
|
17664
|
+
(0, import_react10.useEffect)(() => {
|
|
17180
17665
|
return () => {
|
|
17181
17666
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
17182
17667
|
};
|
|
17183
17668
|
}, []);
|
|
17184
|
-
const copy = (0,
|
|
17185
|
-
copyToClipboard(
|
|
17669
|
+
const copy = (0, import_react10.useCallback)((text2) => {
|
|
17670
|
+
copyToClipboard(text2, {
|
|
17186
17671
|
onSuccess: () => {
|
|
17187
17672
|
setIsCopied(true);
|
|
17188
17673
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
@@ -17221,24 +17706,24 @@ var AnimatedAction = import_styled_components5.default.div`
|
|
|
17221
17706
|
`;
|
|
17222
17707
|
|
|
17223
17708
|
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
17224
|
-
var
|
|
17709
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
17225
17710
|
function ChatMessageActions({ className, messageId, content: content2, role, isHelpful }) {
|
|
17226
17711
|
const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
|
|
17227
17712
|
const { isCopied, copy } = useCopyToClipboard();
|
|
17228
|
-
const handleCopy = (0,
|
|
17713
|
+
const handleCopy = (0, import_react11.useCallback)(() => {
|
|
17229
17714
|
copy(content2);
|
|
17230
17715
|
onCopyMessage?.(messageId);
|
|
17231
17716
|
}, [content2, messageId, copy, onCopyMessage]);
|
|
17232
|
-
const handleThumbUp = (0,
|
|
17717
|
+
const handleThumbUp = (0, import_react11.useCallback)(() => {
|
|
17233
17718
|
onThumbUpClick?.(messageId, isHelpful === true ? null : true);
|
|
17234
17719
|
}, [messageId, isHelpful, onThumbUpClick]);
|
|
17235
|
-
const handleThumbDown = (0,
|
|
17720
|
+
const handleThumbDown = (0, import_react11.useCallback)(() => {
|
|
17236
17721
|
onThumbDownClick?.(messageId, isHelpful === false ? null : false);
|
|
17237
17722
|
}, [messageId, isHelpful, onThumbDownClick]);
|
|
17238
17723
|
const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
|
|
17239
17724
|
const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
|
|
17240
|
-
return /* @__PURE__ */ (0,
|
|
17241
|
-
/* @__PURE__ */ (0,
|
|
17725
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ActionsContainer, { $role: role, className, children: [
|
|
17726
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
17242
17727
|
IconButton,
|
|
17243
17728
|
{
|
|
17244
17729
|
icon: isCopied ? IconCheck : IconCopy,
|
|
@@ -17246,7 +17731,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
|
|
|
17246
17731
|
"aria-label": isCopied ? "Copied" : "Copy message"
|
|
17247
17732
|
}
|
|
17248
17733
|
),
|
|
17249
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
17734
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
17250
17735
|
IconButton,
|
|
17251
17736
|
{
|
|
17252
17737
|
icon: IconThumbUp,
|
|
@@ -17255,7 +17740,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
|
|
|
17255
17740
|
"aria-label": "Good response"
|
|
17256
17741
|
}
|
|
17257
17742
|
) }),
|
|
17258
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
17743
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
17259
17744
|
IconButton,
|
|
17260
17745
|
{
|
|
17261
17746
|
icon: IconThumbDown,
|
|
@@ -17293,19 +17778,28 @@ var MessageBubble = import_styled_components6.default.div`
|
|
|
17293
17778
|
padding: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "12px 16px" : "0"};
|
|
17294
17779
|
border-radius: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "16px" : "0"};
|
|
17295
17780
|
max-width: 100%;
|
|
17781
|
+
width: 100%;
|
|
17296
17782
|
min-width: 0;
|
|
17783
|
+
/* Vertical rhythm between consecutive blocks — renderer-owned, not agent-emitted.
|
|
17784
|
+
* Industry standard (Claude, ChatGPT, Vercel AI Elements): the chat renderer applies
|
|
17785
|
+
* spacing via CSS; agents emit semantic blocks only. Value matches the MessageContainer
|
|
17786
|
+
* gap. TODO: replace 12px with a clay spacing token when a spacing scale is added. */
|
|
17787
|
+
display: flex;
|
|
17788
|
+
flex-direction: column;
|
|
17789
|
+
gap: 12px;
|
|
17297
17790
|
`;
|
|
17298
17791
|
|
|
17299
17792
|
// src/components/chat/chat-message/chat-message.tsx
|
|
17300
|
-
var
|
|
17793
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
17301
17794
|
function ChatMessage({ message }) {
|
|
17302
|
-
|
|
17303
|
-
|
|
17304
|
-
/* @__PURE__ */ (0,
|
|
17795
|
+
const clipboardText = (0, import_react12.useMemo)(() => copyMessageText(message), [message]);
|
|
17796
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(MessageContainer, { $role: message.role, children: [
|
|
17797
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageBubble, { $role: message.role, "data-testid": "message-bubble", children: message.blocks.map((block, index2) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Block, { block }, index2)) }),
|
|
17798
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
17305
17799
|
ChatMessageActions,
|
|
17306
17800
|
{
|
|
17307
17801
|
messageId: message.id,
|
|
17308
|
-
content:
|
|
17802
|
+
content: clipboardText,
|
|
17309
17803
|
role: message.role,
|
|
17310
17804
|
isHelpful: message.isHelpful
|
|
17311
17805
|
}
|
|
@@ -17350,20 +17844,20 @@ var Key = import_styled_components7.default.kbd`
|
|
|
17350
17844
|
`;
|
|
17351
17845
|
|
|
17352
17846
|
// src/components/keyboard-shortcut/keyboard-shortcut.tsx
|
|
17353
|
-
var
|
|
17847
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
17354
17848
|
function KeyboardShortcut({
|
|
17355
17849
|
keys,
|
|
17356
17850
|
variant = KEYBOARD_SHORTCUT_VARIANTS.OUTLINED,
|
|
17357
17851
|
className
|
|
17358
17852
|
}) {
|
|
17359
|
-
return /* @__PURE__ */ (0,
|
|
17853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Wrapper, { className, children: keys.map((KeyComponent, index2) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Key, { $variant: variant, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Icon, { icon: KeyComponent, size: 12 }) }, index2)) });
|
|
17360
17854
|
}
|
|
17361
17855
|
|
|
17362
17856
|
// src/components/keyboard-shortcut/icons/icon-ctrl.tsx
|
|
17363
|
-
var
|
|
17857
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
17364
17858
|
function IconCtrl(props) {
|
|
17365
17859
|
const { width: width2 = 24, height: height2 = 24, ...rest } = props;
|
|
17366
|
-
return /* @__PURE__ */ (0,
|
|
17860
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: width2, height: height2, fill: "none", ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
17367
17861
|
"text",
|
|
17368
17862
|
{
|
|
17369
17863
|
x: "50%",
|
|
@@ -17380,7 +17874,7 @@ function IconCtrl(props) {
|
|
|
17380
17874
|
}
|
|
17381
17875
|
|
|
17382
17876
|
// src/components/lottie/lottie.tsx
|
|
17383
|
-
var
|
|
17877
|
+
var import_react14 = require("react");
|
|
17384
17878
|
|
|
17385
17879
|
// src/components/lottie/lottie-styles.ts
|
|
17386
17880
|
var import_styled_components8 = __toESM(require("styled-components"), 1);
|
|
@@ -17396,7 +17890,7 @@ var LottieContainer = import_styled_components8.default.div`
|
|
|
17396
17890
|
`;
|
|
17397
17891
|
|
|
17398
17892
|
// src/components/lottie/use-lottie.ts
|
|
17399
|
-
var
|
|
17893
|
+
var import_react13 = require("react");
|
|
17400
17894
|
var import_lottie_web = __toESM(require_lottie(), 1);
|
|
17401
17895
|
function useLottie({
|
|
17402
17896
|
animationData: animationData2,
|
|
@@ -17411,17 +17905,17 @@ function useLottie({
|
|
|
17411
17905
|
onLoopComplete,
|
|
17412
17906
|
onEnterFrame
|
|
17413
17907
|
}) {
|
|
17414
|
-
const containerRef = (0,
|
|
17415
|
-
const animationRef = (0,
|
|
17416
|
-
const onAnimationLoadedRef = (0,
|
|
17417
|
-
const onCompleteRef = (0,
|
|
17418
|
-
const onLoopCompleteRef = (0,
|
|
17419
|
-
const onEnterFrameRef = (0,
|
|
17908
|
+
const containerRef = (0, import_react13.useRef)(null);
|
|
17909
|
+
const animationRef = (0, import_react13.useRef)(null);
|
|
17910
|
+
const onAnimationLoadedRef = (0, import_react13.useRef)(onAnimationLoaded);
|
|
17911
|
+
const onCompleteRef = (0, import_react13.useRef)(onComplete);
|
|
17912
|
+
const onLoopCompleteRef = (0, import_react13.useRef)(onLoopComplete);
|
|
17913
|
+
const onEnterFrameRef = (0, import_react13.useRef)(onEnterFrame);
|
|
17420
17914
|
onAnimationLoadedRef.current = onAnimationLoaded;
|
|
17421
17915
|
onCompleteRef.current = onComplete;
|
|
17422
17916
|
onLoopCompleteRef.current = onLoopComplete;
|
|
17423
17917
|
onEnterFrameRef.current = onEnterFrame;
|
|
17424
|
-
(0,
|
|
17918
|
+
(0, import_react13.useEffect)(() => {
|
|
17425
17919
|
if (!containerRef.current) return;
|
|
17426
17920
|
const anim = import_lottie_web.default.loadAnimation({
|
|
17427
17921
|
container: containerRef.current,
|
|
@@ -17513,8 +18007,8 @@ function createLottieRef(animationRef) {
|
|
|
17513
18007
|
}
|
|
17514
18008
|
|
|
17515
18009
|
// src/components/lottie/lottie.tsx
|
|
17516
|
-
var
|
|
17517
|
-
var Lottie = (0,
|
|
18010
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
18011
|
+
var Lottie = (0, import_react14.forwardRef)(function Lottie2({
|
|
17518
18012
|
animationData: animationData2,
|
|
17519
18013
|
autoplay,
|
|
17520
18014
|
loop,
|
|
@@ -17544,8 +18038,8 @@ var Lottie = (0, import_react8.forwardRef)(function Lottie2({
|
|
|
17544
18038
|
onLoopComplete,
|
|
17545
18039
|
onEnterFrame
|
|
17546
18040
|
});
|
|
17547
|
-
(0,
|
|
17548
|
-
return /* @__PURE__ */ (0,
|
|
18041
|
+
(0, import_react14.useImperativeHandle)(ref, () => createLottieRef(animationRef), [animationRef]);
|
|
18042
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
17549
18043
|
LottieContainer,
|
|
17550
18044
|
{
|
|
17551
18045
|
ref: containerRef,
|
|
@@ -17559,7 +18053,7 @@ var Lottie = (0, import_react8.forwardRef)(function Lottie2({
|
|
|
17559
18053
|
});
|
|
17560
18054
|
|
|
17561
18055
|
// src/components/text-area/text-area.tsx
|
|
17562
|
-
var
|
|
18056
|
+
var import_react15 = require("react");
|
|
17563
18057
|
|
|
17564
18058
|
// src/utils/merge-refs.ts
|
|
17565
18059
|
function mergeRefs(...refs) {
|
|
@@ -17599,23 +18093,23 @@ var StyledTextArea = import_styled_components9.default.textarea`
|
|
|
17599
18093
|
`;
|
|
17600
18094
|
|
|
17601
18095
|
// src/components/text-area/text-area.tsx
|
|
17602
|
-
var
|
|
17603
|
-
var TextArea = (0,
|
|
17604
|
-
const internalRef = (0,
|
|
17605
|
-
(0,
|
|
18096
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
18097
|
+
var TextArea = (0, import_react15.forwardRef)(function TextArea2({ value: value2, onChange, placeholder, maxHeight, rows = 1, autoFocus, onKeyDown, disabled, className }, externalRef) {
|
|
18098
|
+
const internalRef = (0, import_react15.useRef)(null);
|
|
18099
|
+
(0, import_react15.useLayoutEffect)(() => {
|
|
17606
18100
|
const el = internalRef.current;
|
|
17607
18101
|
if (el) {
|
|
17608
18102
|
el.style.height = "auto";
|
|
17609
18103
|
el.style.height = `${el.scrollHeight}px`;
|
|
17610
18104
|
}
|
|
17611
18105
|
}, [value2]);
|
|
17612
|
-
const handleChange = (0,
|
|
18106
|
+
const handleChange = (0, import_react15.useCallback)(
|
|
17613
18107
|
(e) => {
|
|
17614
18108
|
onChange(e.target.value);
|
|
17615
18109
|
},
|
|
17616
18110
|
[onChange]
|
|
17617
18111
|
);
|
|
17618
|
-
return /* @__PURE__ */ (0,
|
|
18112
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
17619
18113
|
StyledTextArea,
|
|
17620
18114
|
{
|
|
17621
18115
|
ref: mergeRefs(internalRef, externalRef),
|
|
@@ -17685,21 +18179,26 @@ function parseMarkdownTable(markdown, tableIndex = 0) {
|
|
|
17685
18179
|
return null;
|
|
17686
18180
|
}
|
|
17687
18181
|
|
|
17688
|
-
// src/utils/
|
|
17689
|
-
|
|
17690
|
-
|
|
17691
|
-
|
|
18182
|
+
// src/utils/escape-csv-field.ts
|
|
18183
|
+
var FORMULA_TRIGGERS = /* @__PURE__ */ new Set(["=", "+", "@", " ", "\r"]);
|
|
18184
|
+
function escapeCsvField(field) {
|
|
18185
|
+
const needsNeutralise = field.length > 0 && FORMULA_TRIGGERS.has(field[0]);
|
|
18186
|
+
const safeField = needsNeutralise ? ` ${field}` : field;
|
|
18187
|
+
if (needsNeutralise || safeField.includes(",") || safeField.includes('"') || safeField.includes("\n") || safeField.includes("\r")) {
|
|
18188
|
+
return `"${safeField.replace(/"/g, '""')}"`;
|
|
17692
18189
|
}
|
|
17693
|
-
return
|
|
18190
|
+
return safeField;
|
|
17694
18191
|
}
|
|
18192
|
+
|
|
18193
|
+
// src/utils/convert-table-to-csv.ts
|
|
17695
18194
|
function convertTableToCSV(table) {
|
|
17696
|
-
const headerRow = table.columns.map(
|
|
17697
|
-
const dataRows = table.rows.map((row) => row.map(
|
|
18195
|
+
const headerRow = table.columns.map(escapeCsvField).join(",");
|
|
18196
|
+
const dataRows = table.rows.map((row) => row.map(escapeCsvField).join(","));
|
|
17698
18197
|
return [headerRow, ...dataRows].join("\r\n");
|
|
17699
18198
|
}
|
|
17700
18199
|
|
|
17701
18200
|
// src/components/button/button.tsx
|
|
17702
|
-
var
|
|
18201
|
+
var import_react16 = require("react");
|
|
17703
18202
|
|
|
17704
18203
|
// src/components/button/button-styles.ts
|
|
17705
18204
|
var import_styled_components10 = __toESM(require("styled-components"), 1);
|
|
@@ -17821,8 +18320,8 @@ var StyledButton = import_styled_components10.default.button`
|
|
|
17821
18320
|
`;
|
|
17822
18321
|
|
|
17823
18322
|
// src/components/button/button.tsx
|
|
17824
|
-
var
|
|
17825
|
-
var Button2 = (0,
|
|
18323
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
18324
|
+
var Button2 = (0, import_react16.forwardRef)(function Button3({
|
|
17826
18325
|
children,
|
|
17827
18326
|
variant = BUTTON_VARIANT.SOLID,
|
|
17828
18327
|
intent = BUTTON_INTENT.PRIMARY,
|
|
@@ -17834,8 +18333,8 @@ var Button2 = (0, import_react10.forwardRef)(function Button3({
|
|
|
17834
18333
|
className,
|
|
17835
18334
|
"aria-label": ariaLabel
|
|
17836
18335
|
}, ref) {
|
|
17837
|
-
const iconElement = icon ? /* @__PURE__ */ (0,
|
|
17838
|
-
return /* @__PURE__ */ (0,
|
|
18336
|
+
const iconElement = icon ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Icon, { icon, size: 16 }) : null;
|
|
18337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
17839
18338
|
StyledButton,
|
|
17840
18339
|
{
|
|
17841
18340
|
ref,
|
|
@@ -17849,7 +18348,7 @@ var Button2 = (0, import_react10.forwardRef)(function Button3({
|
|
|
17849
18348
|
"aria-label": ariaLabel,
|
|
17850
18349
|
children: [
|
|
17851
18350
|
iconPosition === ICON_POSITION.LEADING && iconElement,
|
|
17852
|
-
/* @__PURE__ */ (0,
|
|
18351
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children }),
|
|
17853
18352
|
iconPosition === ICON_POSITION.TRAILING && iconElement
|
|
17854
18353
|
]
|
|
17855
18354
|
}
|
|
@@ -17857,9 +18356,16 @@ var Button2 = (0, import_react10.forwardRef)(function Button3({
|
|
|
17857
18356
|
});
|
|
17858
18357
|
// Annotate the CommonJS export names for ESM import in node:
|
|
17859
18358
|
0 && (module.exports = {
|
|
18359
|
+
ArtifactDownloadButton,
|
|
18360
|
+
ArtifactRefBlock,
|
|
18361
|
+
ArtifactRefBlockService,
|
|
18362
|
+
ArtifactServices,
|
|
17860
18363
|
BUTTON_INTENT,
|
|
17861
18364
|
BUTTON_SIZE,
|
|
17862
18365
|
BUTTON_VARIANT,
|
|
18366
|
+
Block,
|
|
18367
|
+
BlockContext,
|
|
18368
|
+
BlockServices,
|
|
17863
18369
|
Button,
|
|
17864
18370
|
ChatContext,
|
|
17865
18371
|
ChatMessage,
|
|
@@ -17871,16 +18377,25 @@ var Button2 = (0, import_react10.forwardRef)(function Button3({
|
|
|
17871
18377
|
KeyboardShortcut,
|
|
17872
18378
|
Lottie,
|
|
17873
18379
|
MESSAGE_ROLE,
|
|
18380
|
+
TableArtifact,
|
|
17874
18381
|
TextArea,
|
|
18382
|
+
TextBlockService,
|
|
18383
|
+
artifactToClipboardText,
|
|
18384
|
+
artifactTypes,
|
|
18385
|
+
blockTypes,
|
|
17875
18386
|
colors,
|
|
17876
18387
|
convertTableToCSV,
|
|
18388
|
+
copyMessageText,
|
|
18389
|
+
escapeCsvField,
|
|
17877
18390
|
fontFamilies,
|
|
18391
|
+
isSafeDownloadUrl,
|
|
17878
18392
|
markdownToPlainText,
|
|
17879
18393
|
mergeRefs,
|
|
17880
18394
|
parseMarkdownTable,
|
|
17881
18395
|
typographyMixin,
|
|
17882
18396
|
typographyStyles,
|
|
17883
18397
|
typographyTypes,
|
|
18398
|
+
useBlockContext,
|
|
17884
18399
|
useChatContext,
|
|
17885
18400
|
useCopyToClipboard
|
|
17886
18401
|
});
|
|
@@ -17900,6 +18415,7 @@ lottie-web/build/player/lottie.js:
|
|
|
17900
18415
|
@tabler/icons-react/dist/esm/createReactComponent.mjs:
|
|
17901
18416
|
@tabler/icons-react/dist/esm/icons/IconCheck.mjs:
|
|
17902
18417
|
@tabler/icons-react/dist/esm/icons/IconCopy.mjs:
|
|
18418
|
+
@tabler/icons-react/dist/esm/icons/IconDownload.mjs:
|
|
17903
18419
|
@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
|
|
17904
18420
|
@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
|
|
17905
18421
|
@tabler/icons-react/dist/esm/tabler-icons-react.mjs:
|