@shapesos/clay 0.10.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/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/blocks.cjs +685 -53
- package/dist/blocks.cjs.map +1 -1
- package/dist/blocks.css +2 -0
- package/dist/blocks.d.cts +22 -10
- package/dist/blocks.d.ts +22 -10
- package/dist/blocks.js +15 -5
- package/dist/button.d.cts +2 -2
- package/dist/button.d.ts +2 -2
- package/dist/chat.cjs +728 -296
- package/dist/chat.cjs.map +1 -1
- package/dist/chat.d.cts +27 -10
- package/dist/chat.d.ts +27 -10
- package/dist/chat.js +7 -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-R3BGPOAM.js → chunk-MXOPG747.js} +53 -45
- 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-WS4IPADR.js → chunk-OUW6PUEB.js} +42 -110
- package/dist/chunk-OUW6PUEB.js.map +1 -0
- 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 +794 -332
- 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 +50 -25
- 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/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 +29 -4
- package/dist/chunk-27GJUWVN.js.map +0 -1
- package/dist/chunk-MLCRDVQ2.js.map +0 -1
- package/dist/chunk-OKPNST44.js +0 -1
- package/dist/chunk-R3BGPOAM.js.map +0 -1
- package/dist/chunk-WS4IPADR.js.map +0 -1
- package/dist/types-Q9aqd9nq.d.cts +0 -34
- package/dist/types-Q9aqd9nq.d.ts +0 -34
- /package/dist/{chunk-OKPNST44.js.map → artifacts.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -16342,6 +16342,10 @@ 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,
|
|
@@ -16359,12 +16363,18 @@ __export(src_exports, {
|
|
|
16359
16363
|
KeyboardShortcut: () => KeyboardShortcut,
|
|
16360
16364
|
Lottie: () => Lottie,
|
|
16361
16365
|
MESSAGE_ROLE: () => MESSAGE_ROLE,
|
|
16366
|
+
TableArtifact: () => TableArtifact,
|
|
16362
16367
|
TextArea: () => TextArea,
|
|
16363
16368
|
TextBlockService: () => TextBlockService,
|
|
16369
|
+
artifactToClipboardText: () => artifactToClipboardText,
|
|
16370
|
+
artifactTypes: () => artifactTypes,
|
|
16364
16371
|
blockTypes: () => blockTypes,
|
|
16365
16372
|
colors: () => colors,
|
|
16366
16373
|
convertTableToCSV: () => convertTableToCSV,
|
|
16374
|
+
copyMessageText: () => copyMessageText,
|
|
16375
|
+
escapeCsvField: () => escapeCsvField,
|
|
16367
16376
|
fontFamilies: () => fontFamilies,
|
|
16377
|
+
isSafeDownloadUrl: () => isSafeDownloadUrl,
|
|
16368
16378
|
markdownToPlainText: () => markdownToPlainText,
|
|
16369
16379
|
mergeRefs: () => mergeRefs,
|
|
16370
16380
|
parseMarkdownTable: () => parseMarkdownTable,
|
|
@@ -16760,55 +16770,678 @@ function typographyMixin(type) {
|
|
|
16760
16770
|
].join(";\n ");
|
|
16761
16771
|
}
|
|
16762
16772
|
|
|
16773
|
+
// src/components/blocks/types.ts
|
|
16774
|
+
var blockTypes = {
|
|
16775
|
+
TEXT: "TEXT",
|
|
16776
|
+
ARTIFACT_REF: "ARTIFACT_REF"
|
|
16777
|
+
};
|
|
16778
|
+
|
|
16779
|
+
// src/components/artifacts/types.ts
|
|
16780
|
+
var artifactTypes = {
|
|
16781
|
+
TABLE: "TABLE"
|
|
16782
|
+
};
|
|
16783
|
+
|
|
16784
|
+
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
16785
|
+
var import_react7 = require("react");
|
|
16786
|
+
|
|
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));
|
|
16792
|
+
}
|
|
16793
|
+
|
|
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
|
|
16801
|
+
}
|
|
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 });
|
|
16807
|
+
|
|
16808
|
+
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
16809
|
+
var import_react = require("react");
|
|
16810
|
+
|
|
16811
|
+
// node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs
|
|
16812
|
+
var defaultAttributes = {
|
|
16813
|
+
outline: {
|
|
16814
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
16815
|
+
width: 24,
|
|
16816
|
+
height: 24,
|
|
16817
|
+
viewBox: "0 0 24 24",
|
|
16818
|
+
fill: "none",
|
|
16819
|
+
stroke: "currentColor",
|
|
16820
|
+
strokeWidth: 2,
|
|
16821
|
+
strokeLinecap: "round",
|
|
16822
|
+
strokeLinejoin: "round"
|
|
16823
|
+
},
|
|
16824
|
+
filled: {
|
|
16825
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
16826
|
+
width: 24,
|
|
16827
|
+
height: 24,
|
|
16828
|
+
viewBox: "0 0 24 24",
|
|
16829
|
+
fill: "currentColor",
|
|
16830
|
+
stroke: "none"
|
|
16831
|
+
}
|
|
16832
|
+
};
|
|
16833
|
+
|
|
16834
|
+
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
16835
|
+
var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
|
|
16836
|
+
const Component = (0, import_react.forwardRef)(
|
|
16837
|
+
({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => (0, import_react.createElement)(
|
|
16838
|
+
"svg",
|
|
16839
|
+
{
|
|
16840
|
+
ref,
|
|
16841
|
+
...defaultAttributes[type],
|
|
16842
|
+
width: size,
|
|
16843
|
+
height: size,
|
|
16844
|
+
className: [`tabler-icon`, `tabler-icon-${iconName}`, className].join(" "),
|
|
16845
|
+
...type === "filled" ? {
|
|
16846
|
+
fill: color
|
|
16847
|
+
} : {
|
|
16848
|
+
strokeWidth: stroke,
|
|
16849
|
+
stroke: color
|
|
16850
|
+
},
|
|
16851
|
+
...rest
|
|
16852
|
+
},
|
|
16853
|
+
[
|
|
16854
|
+
title && (0, import_react.createElement)("title", { key: "svg-title" }, title),
|
|
16855
|
+
...iconNode.map(([tag, attrs]) => (0, import_react.createElement)(tag, attrs)),
|
|
16856
|
+
...Array.isArray(children) ? children : [children]
|
|
16857
|
+
]
|
|
16858
|
+
)
|
|
16859
|
+
);
|
|
16860
|
+
Component.displayName = `${iconNamePascal}`;
|
|
16861
|
+
return Component;
|
|
16862
|
+
};
|
|
16863
|
+
|
|
16864
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
|
|
16865
|
+
var __iconNode = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
|
|
16866
|
+
var IconCheck = createReactComponent("outline", "check", "Check", __iconNode);
|
|
16867
|
+
|
|
16868
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
|
|
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" }]];
|
|
16870
|
+
var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode2);
|
|
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
|
+
|
|
16876
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
|
|
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);
|
|
16879
|
+
|
|
16880
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
|
|
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");
|
|
16886
|
+
|
|
16887
|
+
// src/components/icon/icon.tsx
|
|
16888
|
+
var import_react2 = require("react");
|
|
16889
|
+
|
|
16890
|
+
// src/components/icon/icon-styles.ts
|
|
16891
|
+
var import_styled_components = __toESM(require("styled-components"), 1);
|
|
16892
|
+
var STROKE_WIDTH_BY_SIZE = {
|
|
16893
|
+
12: 1.4,
|
|
16894
|
+
14: 1.4,
|
|
16895
|
+
16: 1.8,
|
|
16896
|
+
18: 1.8,
|
|
16897
|
+
20: 1.8,
|
|
16898
|
+
24: 1.8
|
|
16899
|
+
};
|
|
16900
|
+
var DEFAULT_STROKE_WIDTH = 1.8;
|
|
16901
|
+
function getStrokeWidth(size) {
|
|
16902
|
+
return STROKE_WIDTH_BY_SIZE[size] ?? DEFAULT_STROKE_WIDTH;
|
|
16903
|
+
}
|
|
16904
|
+
var IconWrapper = import_styled_components.default.span`
|
|
16905
|
+
display: inline-flex;
|
|
16906
|
+
align-items: center;
|
|
16907
|
+
justify-content: center;
|
|
16908
|
+
color: ${({ $color }) => $color ?? "currentColor"};
|
|
16909
|
+
flex-shrink: 0;
|
|
16910
|
+
`;
|
|
16911
|
+
|
|
16912
|
+
// src/components/icon/icon.tsx
|
|
16913
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
16914
|
+
var DEFAULT_SIZE = 16;
|
|
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)(
|
|
16917
|
+
IconWrapper,
|
|
16918
|
+
{
|
|
16919
|
+
ref,
|
|
16920
|
+
className,
|
|
16921
|
+
$color: color,
|
|
16922
|
+
"aria-label": ariaLabel,
|
|
16923
|
+
role: ariaLabel ? "img" : void 0,
|
|
16924
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconComponent, { width: size, height: size, strokeWidth: getStrokeWidth(size) })
|
|
16925
|
+
}
|
|
16926
|
+
);
|
|
16927
|
+
});
|
|
16928
|
+
|
|
16929
|
+
// src/components/icon-button/icon-button-styles.ts
|
|
16930
|
+
var import_styled_components2 = __toESM(require("styled-components"), 1);
|
|
16931
|
+
var PADDING = {
|
|
16932
|
+
short: {
|
|
16933
|
+
small: "4px",
|
|
16934
|
+
medium: "6px"
|
|
16935
|
+
},
|
|
16936
|
+
long: {
|
|
16937
|
+
small: "4px 6px",
|
|
16938
|
+
medium: "6px 10px"
|
|
16939
|
+
}
|
|
16940
|
+
};
|
|
16941
|
+
var BORDER_RADIUS = {
|
|
16942
|
+
small: 6,
|
|
16943
|
+
medium: 10
|
|
16944
|
+
};
|
|
16945
|
+
var Button = import_styled_components2.default.button`
|
|
16946
|
+
display: inline-flex;
|
|
16947
|
+
align-items: center;
|
|
16948
|
+
justify-content: center;
|
|
16949
|
+
padding: ${({ $size, $variant }) => PADDING[$variant][$size]};
|
|
16950
|
+
border: none;
|
|
16951
|
+
border-radius: ${({ $size }) => BORDER_RADIUS[$size]}px;
|
|
16952
|
+
background: ${({ $isSelected }) => $isSelected ? colors["brown-40"] : "transparent"};
|
|
16953
|
+
color: ${colors["brown-100"]};
|
|
16954
|
+
cursor: pointer;
|
|
16955
|
+
transition: background-color 100ms ease;
|
|
16956
|
+
|
|
16957
|
+
&:hover {
|
|
16958
|
+
background: ${({ $isSelected }) => $isSelected ? colors["brown-40"] : colors["brown-20"]};
|
|
16959
|
+
}
|
|
16960
|
+
|
|
16961
|
+
&:active {
|
|
16962
|
+
background: ${colors["brown-40"]};
|
|
16963
|
+
}
|
|
16964
|
+
|
|
16965
|
+
&:disabled {
|
|
16966
|
+
color: ${colors["brown-50"]};
|
|
16967
|
+
background: transparent;
|
|
16968
|
+
cursor: not-allowed;
|
|
16969
|
+
}
|
|
16970
|
+
`;
|
|
16971
|
+
|
|
16972
|
+
// src/components/icon-button/icon-button.tsx
|
|
16973
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
16974
|
+
var ICON_SIZE_BY_BUTTON_SIZE = {
|
|
16975
|
+
small: 16,
|
|
16976
|
+
medium: 20
|
|
16977
|
+
};
|
|
16978
|
+
var IconButton = (0, import_react3.forwardRef)(function IconButton2({
|
|
16979
|
+
icon,
|
|
16980
|
+
size = "small",
|
|
16981
|
+
variant = "short",
|
|
16982
|
+
isSelected = false,
|
|
16983
|
+
disabled = false,
|
|
16984
|
+
onClick,
|
|
16985
|
+
className,
|
|
16986
|
+
id,
|
|
16987
|
+
as,
|
|
16988
|
+
"aria-label": ariaLabel,
|
|
16989
|
+
...rest
|
|
16990
|
+
}, ref) {
|
|
16991
|
+
const isNativeButton = as === void 0 || as === "button";
|
|
16992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
16993
|
+
Button,
|
|
16994
|
+
{
|
|
16995
|
+
ref,
|
|
16996
|
+
className,
|
|
16997
|
+
id,
|
|
16998
|
+
as,
|
|
16999
|
+
$size: size,
|
|
17000
|
+
$variant: variant,
|
|
17001
|
+
$isSelected: isSelected,
|
|
17002
|
+
disabled,
|
|
17003
|
+
onClick: disabled ? void 0 : onClick,
|
|
17004
|
+
"aria-label": ariaLabel,
|
|
17005
|
+
...isNativeButton ? { type: "button" } : {},
|
|
17006
|
+
...rest,
|
|
17007
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { icon, size: ICON_SIZE_BY_BUTTON_SIZE[size] })
|
|
17008
|
+
}
|
|
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
|
+
}
|
|
17060
|
+
}
|
|
17061
|
+
|
|
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
|
|
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
|
+
}
|
|
17150
|
+
|
|
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 ?? []
|
|
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 });
|
|
17391
|
+
}
|
|
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
|
+
|
|
17405
|
+
// src/utils/markdown-to-plain-text.ts
|
|
17406
|
+
var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
|
|
17407
|
+
var PLACEHOLDER_SUFFIX = "\u200B\u200B";
|
|
17408
|
+
var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
|
|
17409
|
+
function stripInlineMarks(text2) {
|
|
17410
|
+
return text2.replace(/\*{3}(.+?)\*{3}/g, "$1").replace(/\*{2}(.+?)\*{2}/g, "$1").replace(/_{2}(.+?)_{2}/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1");
|
|
17411
|
+
}
|
|
17412
|
+
function markdownToPlainText(markdown) {
|
|
17413
|
+
if (!markdown) return "";
|
|
17414
|
+
const inlineCodeSnippets = [];
|
|
17415
|
+
let result = markdown.replace(/^<!--[\s\S]*?--!?>\n?/gm, "").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
|
|
17416
|
+
inlineCodeSnippets.push(code);
|
|
17417
|
+
return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
|
|
17418
|
+
}).replace(/^#{1,6}\s+/gm, "").replace(/^(?:---|\*\*\*|___)\s*$/gm, "");
|
|
17419
|
+
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();
|
|
17420
|
+
result = result.replace(PLACEHOLDER_REGEX, (_match, index2) => inlineCodeSnippets[Number(index2)]);
|
|
17421
|
+
return result;
|
|
17422
|
+
}
|
|
17423
|
+
|
|
16763
17424
|
// src/components/blocks/text-block/text-block.tsx
|
|
16764
17425
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
16765
17426
|
var import_remark_breaks = __toESM(require("remark-breaks"), 1);
|
|
16766
17427
|
var import_remark_gfm = __toESM(require("remark-gfm"), 1);
|
|
16767
17428
|
|
|
16768
|
-
// src/components/blocks/block-context/block-context.tsx
|
|
16769
|
-
var import_react = require("react");
|
|
16770
|
-
var BlockContext = (0, import_react.createContext)(null);
|
|
16771
|
-
function useBlockContext() {
|
|
16772
|
-
return (0, import_react.useContext)(BlockContext) ?? {};
|
|
16773
|
-
}
|
|
16774
|
-
|
|
16775
17429
|
// src/components/blocks/scrollable-table/scrollable-table-styles.ts
|
|
16776
|
-
var
|
|
16777
|
-
var TableContainer =
|
|
17430
|
+
var import_styled_components3 = __toESM(require("styled-components"), 1);
|
|
17431
|
+
var TableContainer = import_styled_components3.default.div`
|
|
16778
17432
|
position: relative;
|
|
16779
17433
|
margin-block: 8px 16px;
|
|
16780
17434
|
`;
|
|
16781
|
-
var TableScroll =
|
|
17435
|
+
var TableScroll = import_styled_components3.default.div`
|
|
16782
17436
|
width: 100%;
|
|
16783
17437
|
overflow-x: auto;
|
|
16784
17438
|
overflow-y: hidden;
|
|
16785
17439
|
`;
|
|
16786
|
-
var TableActionsWrapper = import_styled_components.default.div`
|
|
16787
|
-
display: flex;
|
|
16788
|
-
justify-content: flex-start;
|
|
16789
|
-
margin-block: 8px 0;
|
|
16790
|
-
`;
|
|
16791
|
-
var TableActionsDivider = import_styled_components.default.div`
|
|
16792
|
-
height: 1px;
|
|
16793
|
-
background: ${colors["brown-40"]};
|
|
16794
|
-
margin-block: 8px 0;
|
|
16795
|
-
`;
|
|
16796
17440
|
|
|
16797
17441
|
// src/components/blocks/scrollable-table/scrollable-table.tsx
|
|
16798
|
-
var
|
|
16799
|
-
function ScrollableTable({ node: _node,
|
|
16800
|
-
|
|
16801
|
-
if (counter) {
|
|
16802
|
-
counter.value += 1;
|
|
16803
|
-
}
|
|
16804
|
-
const { TableActions } = useBlockContext();
|
|
16805
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableContainer, { children: [
|
|
16806
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { ...props }) }),
|
|
16807
|
-
TableActions && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
16808
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableActionsWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableActions, { tableIndex: currentIndex }) }),
|
|
16809
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableActionsDivider, {})
|
|
16810
|
-
] })
|
|
16811
|
-
] });
|
|
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 }) }) });
|
|
16812
17445
|
}
|
|
16813
17446
|
|
|
16814
17447
|
// src/components/blocks/text-block/sanitize.ts
|
|
@@ -16820,8 +17453,8 @@ function sanitize(text2) {
|
|
|
16820
17453
|
}
|
|
16821
17454
|
|
|
16822
17455
|
// src/components/blocks/text-block/text-block-styles.ts
|
|
16823
|
-
var
|
|
16824
|
-
var TextBlockWrapper =
|
|
17456
|
+
var import_styled_components4 = __toESM(require("styled-components"), 1);
|
|
17457
|
+
var TextBlockWrapper = import_styled_components4.default.div`
|
|
16825
17458
|
${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
|
|
16826
17459
|
color: ${colors["brown-100"]};
|
|
16827
17460
|
word-break: break-word;
|
|
@@ -16939,251 +17572,81 @@ var TextBlockWrapper = import_styled_components2.default.div`
|
|
|
16939
17572
|
`;
|
|
16940
17573
|
|
|
16941
17574
|
// src/components/blocks/text-block/text-block.tsx
|
|
16942
|
-
var
|
|
17575
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
17576
|
+
var markdownComponents = {
|
|
17577
|
+
table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScrollableTable, { ...tableProps }))
|
|
17578
|
+
};
|
|
16943
17579
|
function TextBlock({ block }) {
|
|
16944
|
-
|
|
16945
|
-
const markdownComponents = {
|
|
16946
|
-
table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ScrollableTable, { ...tableProps, counter }))
|
|
16947
|
-
};
|
|
16948
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TextBlockWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: markdownComponents, children: sanitize(block.payload.text) }) });
|
|
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) }) });
|
|
16949
17581
|
}
|
|
16950
17582
|
|
|
16951
|
-
// src/components/blocks/types.ts
|
|
16952
|
-
var blockTypes = {
|
|
16953
|
-
TEXT: "TEXT"
|
|
16954
|
-
};
|
|
16955
|
-
|
|
16956
17583
|
// src/components/blocks/block-services/text-block-service.ts
|
|
16957
17584
|
var TextBlockService = {
|
|
16958
17585
|
type: blockTypes.TEXT,
|
|
16959
|
-
Component: TextBlock
|
|
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)
|
|
16960
17593
|
};
|
|
16961
17594
|
|
|
16962
17595
|
// src/components/blocks/block-services/index.ts
|
|
16963
17596
|
var BlockServices = {
|
|
16964
|
-
[
|
|
17597
|
+
[blockTypes.TEXT]: TextBlockService,
|
|
17598
|
+
[blockTypes.ARTIFACT_REF]: ArtifactRefBlockService
|
|
16965
17599
|
};
|
|
16966
17600
|
|
|
16967
17601
|
// src/components/blocks/block/block.tsx
|
|
16968
|
-
var
|
|
17602
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
16969
17603
|
function Block({ block }) {
|
|
16970
17604
|
const service = BlockServices[block.type];
|
|
16971
17605
|
if (!service) return null;
|
|
16972
17606
|
const { Component } = service;
|
|
16973
|
-
return /* @__PURE__ */ (0,
|
|
17607
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Component, { block });
|
|
16974
17608
|
}
|
|
16975
17609
|
|
|
16976
|
-
// src/components/
|
|
16977
|
-
var
|
|
16978
|
-
|
|
16979
|
-
|
|
16980
|
-
|
|
16981
|
-
var ChatContext = (0, import_react2.createContext)(null);
|
|
16982
|
-
function useChatContext() {
|
|
16983
|
-
const context = (0, import_react2.useContext)(ChatContext);
|
|
16984
|
-
if (!context) {
|
|
16985
|
-
throw new Error("useChatContext must be used within a Chat.Root component");
|
|
16986
|
-
}
|
|
16987
|
-
return context;
|
|
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) ?? {};
|
|
16988
17615
|
}
|
|
16989
17616
|
|
|
16990
|
-
// src/components/chat/chat-message
|
|
16991
|
-
var
|
|
16992
|
-
|
|
16993
|
-
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
16994
|
-
var import_react3 = require("react");
|
|
17617
|
+
// src/components/chat/chat-message/chat-message.tsx
|
|
17618
|
+
var import_react12 = require("react");
|
|
16995
17619
|
|
|
16996
|
-
//
|
|
16997
|
-
|
|
16998
|
-
|
|
16999
|
-
|
|
17000
|
-
|
|
17001
|
-
|
|
17002
|
-
|
|
17003
|
-
|
|
17004
|
-
|
|
17005
|
-
strokeWidth: 2,
|
|
17006
|
-
strokeLinecap: "round",
|
|
17007
|
-
strokeLinejoin: "round"
|
|
17008
|
-
},
|
|
17009
|
-
filled: {
|
|
17010
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
17011
|
-
width: 24,
|
|
17012
|
-
height: 24,
|
|
17013
|
-
viewBox: "0 0 24 24",
|
|
17014
|
-
fill: "currentColor",
|
|
17015
|
-
stroke: "none"
|
|
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);
|
|
17016
17629
|
}
|
|
17017
|
-
|
|
17018
|
-
|
|
17019
|
-
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
17020
|
-
var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
|
|
17021
|
-
const Component = (0, import_react3.forwardRef)(
|
|
17022
|
-
({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => (0, import_react3.createElement)(
|
|
17023
|
-
"svg",
|
|
17024
|
-
{
|
|
17025
|
-
ref,
|
|
17026
|
-
...defaultAttributes[type],
|
|
17027
|
-
width: size,
|
|
17028
|
-
height: size,
|
|
17029
|
-
className: [`tabler-icon`, `tabler-icon-${iconName}`, className].join(" "),
|
|
17030
|
-
...type === "filled" ? {
|
|
17031
|
-
fill: color
|
|
17032
|
-
} : {
|
|
17033
|
-
strokeWidth: stroke,
|
|
17034
|
-
stroke: color
|
|
17035
|
-
},
|
|
17036
|
-
...rest
|
|
17037
|
-
},
|
|
17038
|
-
[
|
|
17039
|
-
title && (0, import_react3.createElement)("title", { key: "svg-title" }, title),
|
|
17040
|
-
...iconNode.map(([tag, attrs]) => (0, import_react3.createElement)(tag, attrs)),
|
|
17041
|
-
...Array.isArray(children) ? children : [children]
|
|
17042
|
-
]
|
|
17043
|
-
)
|
|
17044
|
-
);
|
|
17045
|
-
Component.displayName = `${iconNamePascal}`;
|
|
17046
|
-
return Component;
|
|
17047
|
-
};
|
|
17048
|
-
|
|
17049
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
|
|
17050
|
-
var __iconNode = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
|
|
17051
|
-
var IconCheck = createReactComponent("outline", "check", "Check", __iconNode);
|
|
17052
|
-
|
|
17053
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
|
|
17054
|
-
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" }]];
|
|
17055
|
-
var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode2);
|
|
17056
|
-
|
|
17057
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
|
|
17058
|
-
var __iconNode3 = [["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" }]];
|
|
17059
|
-
var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode3);
|
|
17060
|
-
|
|
17061
|
-
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
|
|
17062
|
-
var __iconNode4 = [["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" }]];
|
|
17063
|
-
var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode4);
|
|
17064
|
-
|
|
17065
|
-
// src/components/icon/icon.tsx
|
|
17066
|
-
var import_react4 = require("react");
|
|
17067
|
-
|
|
17068
|
-
// src/components/icon/icon-styles.ts
|
|
17069
|
-
var import_styled_components3 = __toESM(require("styled-components"), 1);
|
|
17070
|
-
var STROKE_WIDTH_BY_SIZE = {
|
|
17071
|
-
12: 1.4,
|
|
17072
|
-
14: 1.4,
|
|
17073
|
-
16: 1.8,
|
|
17074
|
-
18: 1.8,
|
|
17075
|
-
20: 1.8,
|
|
17076
|
-
24: 1.8
|
|
17077
|
-
};
|
|
17078
|
-
var DEFAULT_STROKE_WIDTH = 1.8;
|
|
17079
|
-
function getStrokeWidth(size) {
|
|
17080
|
-
return STROKE_WIDTH_BY_SIZE[size] ?? DEFAULT_STROKE_WIDTH;
|
|
17630
|
+
if (parts.length === 0) return message.fallbackText;
|
|
17631
|
+
return parts.join("\n\n");
|
|
17081
17632
|
}
|
|
17082
|
-
var IconWrapper = import_styled_components3.default.span`
|
|
17083
|
-
display: inline-flex;
|
|
17084
|
-
align-items: center;
|
|
17085
|
-
justify-content: center;
|
|
17086
|
-
color: ${({ $color }) => $color ?? "currentColor"};
|
|
17087
|
-
flex-shrink: 0;
|
|
17088
|
-
`;
|
|
17089
|
-
|
|
17090
|
-
// src/components/icon/icon.tsx
|
|
17091
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
17092
|
-
var DEFAULT_SIZE = 16;
|
|
17093
|
-
var Icon = (0, import_react4.forwardRef)(function Icon2({ icon: IconComponent, size = DEFAULT_SIZE, color, className, "aria-label": ariaLabel }, ref) {
|
|
17094
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
17095
|
-
IconWrapper,
|
|
17096
|
-
{
|
|
17097
|
-
ref,
|
|
17098
|
-
className,
|
|
17099
|
-
$color: color,
|
|
17100
|
-
"aria-label": ariaLabel,
|
|
17101
|
-
role: ariaLabel ? "img" : void 0,
|
|
17102
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IconComponent, { width: size, height: size, strokeWidth: getStrokeWidth(size) })
|
|
17103
|
-
}
|
|
17104
|
-
);
|
|
17105
|
-
});
|
|
17106
|
-
|
|
17107
|
-
// src/components/icon-button/icon-button-styles.ts
|
|
17108
|
-
var import_styled_components4 = __toESM(require("styled-components"), 1);
|
|
17109
|
-
var PADDING = {
|
|
17110
|
-
short: {
|
|
17111
|
-
small: "4px",
|
|
17112
|
-
medium: "6px"
|
|
17113
|
-
},
|
|
17114
|
-
long: {
|
|
17115
|
-
small: "4px 6px",
|
|
17116
|
-
medium: "6px 10px"
|
|
17117
|
-
}
|
|
17118
|
-
};
|
|
17119
|
-
var BORDER_RADIUS = {
|
|
17120
|
-
small: 6,
|
|
17121
|
-
medium: 10
|
|
17122
|
-
};
|
|
17123
|
-
var Button = import_styled_components4.default.button`
|
|
17124
|
-
display: inline-flex;
|
|
17125
|
-
align-items: center;
|
|
17126
|
-
justify-content: center;
|
|
17127
|
-
padding: ${({ $size, $variant }) => PADDING[$variant][$size]};
|
|
17128
|
-
border: none;
|
|
17129
|
-
border-radius: ${({ $size }) => BORDER_RADIUS[$size]}px;
|
|
17130
|
-
background: ${({ $isSelected }) => $isSelected ? colors["brown-40"] : "transparent"};
|
|
17131
|
-
color: ${colors["brown-100"]};
|
|
17132
|
-
cursor: pointer;
|
|
17133
|
-
transition: background-color 100ms ease;
|
|
17134
|
-
|
|
17135
|
-
&:hover {
|
|
17136
|
-
background: ${({ $isSelected }) => $isSelected ? colors["brown-40"] : colors["brown-20"]};
|
|
17137
|
-
}
|
|
17138
17633
|
|
|
17139
|
-
|
|
17140
|
-
|
|
17141
|
-
}
|
|
17634
|
+
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
17635
|
+
var import_react11 = require("react");
|
|
17142
17636
|
|
|
17143
|
-
|
|
17144
|
-
|
|
17145
|
-
|
|
17146
|
-
|
|
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");
|
|
17147
17644
|
}
|
|
17148
|
-
|
|
17149
|
-
|
|
17150
|
-
// src/components/icon-button/icon-button.tsx
|
|
17151
|
-
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
17152
|
-
var ICON_SIZE_BY_BUTTON_SIZE = {
|
|
17153
|
-
small: 16,
|
|
17154
|
-
medium: 20
|
|
17155
|
-
};
|
|
17156
|
-
function IconButton({
|
|
17157
|
-
icon,
|
|
17158
|
-
size = "small",
|
|
17159
|
-
variant = "short",
|
|
17160
|
-
isSelected = false,
|
|
17161
|
-
disabled = false,
|
|
17162
|
-
onClick,
|
|
17163
|
-
className,
|
|
17164
|
-
id,
|
|
17165
|
-
as,
|
|
17166
|
-
"aria-label": ariaLabel
|
|
17167
|
-
}) {
|
|
17168
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
17169
|
-
Button,
|
|
17170
|
-
{
|
|
17171
|
-
className,
|
|
17172
|
-
id,
|
|
17173
|
-
as,
|
|
17174
|
-
$size: size,
|
|
17175
|
-
$variant: variant,
|
|
17176
|
-
$isSelected: isSelected,
|
|
17177
|
-
disabled,
|
|
17178
|
-
onClick: disabled ? void 0 : onClick,
|
|
17179
|
-
"aria-label": ariaLabel,
|
|
17180
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { icon, size: ICON_SIZE_BY_BUTTON_SIZE[size] })
|
|
17181
|
-
}
|
|
17182
|
-
);
|
|
17645
|
+
return context;
|
|
17183
17646
|
}
|
|
17184
17647
|
|
|
17185
17648
|
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
17186
|
-
var
|
|
17649
|
+
var import_react10 = require("react");
|
|
17187
17650
|
|
|
17188
17651
|
// src/utils/clipboard.ts
|
|
17189
17652
|
function copyToClipboard(text2, options) {
|
|
@@ -17193,37 +17656,18 @@ function copyToClipboard(text2, options) {
|
|
|
17193
17656
|
);
|
|
17194
17657
|
}
|
|
17195
17658
|
|
|
17196
|
-
// src/utils/markdown-to-plain-text.ts
|
|
17197
|
-
var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
|
|
17198
|
-
var PLACEHOLDER_SUFFIX = "\u200B\u200B";
|
|
17199
|
-
var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
|
|
17200
|
-
function stripInlineMarks(text2) {
|
|
17201
|
-
return text2.replace(/\*{3}(.+?)\*{3}/g, "$1").replace(/\*{2}(.+?)\*{2}/g, "$1").replace(/_{2}(.+?)_{2}/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1");
|
|
17202
|
-
}
|
|
17203
|
-
function markdownToPlainText(markdown) {
|
|
17204
|
-
if (!markdown) return "";
|
|
17205
|
-
const inlineCodeSnippets = [];
|
|
17206
|
-
let result = markdown.replace(/^<!--[\s\S]*?--!?>\n?/gm, "").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
|
|
17207
|
-
inlineCodeSnippets.push(code);
|
|
17208
|
-
return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
|
|
17209
|
-
}).replace(/^#{1,6}\s+/gm, "").replace(/^(?:---|\*\*\*|___)\s*$/gm, "");
|
|
17210
|
-
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();
|
|
17211
|
-
result = result.replace(PLACEHOLDER_REGEX, (_match, index2) => inlineCodeSnippets[Number(index2)]);
|
|
17212
|
-
return result;
|
|
17213
|
-
}
|
|
17214
|
-
|
|
17215
17659
|
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
17216
17660
|
var RESET_DELAY_MS = 2e3;
|
|
17217
17661
|
function useCopyToClipboard() {
|
|
17218
|
-
const [isCopied, setIsCopied] = (0,
|
|
17219
|
-
const timeoutRef = (0,
|
|
17220
|
-
(0,
|
|
17662
|
+
const [isCopied, setIsCopied] = (0, import_react10.useState)(false);
|
|
17663
|
+
const timeoutRef = (0, import_react10.useRef)(null);
|
|
17664
|
+
(0, import_react10.useEffect)(() => {
|
|
17221
17665
|
return () => {
|
|
17222
17666
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
17223
17667
|
};
|
|
17224
17668
|
}, []);
|
|
17225
|
-
const copy = (0,
|
|
17226
|
-
copyToClipboard(
|
|
17669
|
+
const copy = (0, import_react10.useCallback)((text2) => {
|
|
17670
|
+
copyToClipboard(text2, {
|
|
17227
17671
|
onSuccess: () => {
|
|
17228
17672
|
setIsCopied(true);
|
|
17229
17673
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
@@ -17262,24 +17706,24 @@ var AnimatedAction = import_styled_components5.default.div`
|
|
|
17262
17706
|
`;
|
|
17263
17707
|
|
|
17264
17708
|
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
17265
|
-
var
|
|
17709
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
17266
17710
|
function ChatMessageActions({ className, messageId, content: content2, role, isHelpful }) {
|
|
17267
17711
|
const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
|
|
17268
17712
|
const { isCopied, copy } = useCopyToClipboard();
|
|
17269
|
-
const handleCopy = (0,
|
|
17713
|
+
const handleCopy = (0, import_react11.useCallback)(() => {
|
|
17270
17714
|
copy(content2);
|
|
17271
17715
|
onCopyMessage?.(messageId);
|
|
17272
17716
|
}, [content2, messageId, copy, onCopyMessage]);
|
|
17273
|
-
const handleThumbUp = (0,
|
|
17717
|
+
const handleThumbUp = (0, import_react11.useCallback)(() => {
|
|
17274
17718
|
onThumbUpClick?.(messageId, isHelpful === true ? null : true);
|
|
17275
17719
|
}, [messageId, isHelpful, onThumbUpClick]);
|
|
17276
|
-
const handleThumbDown = (0,
|
|
17720
|
+
const handleThumbDown = (0, import_react11.useCallback)(() => {
|
|
17277
17721
|
onThumbDownClick?.(messageId, isHelpful === false ? null : false);
|
|
17278
17722
|
}, [messageId, isHelpful, onThumbDownClick]);
|
|
17279
17723
|
const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
|
|
17280
17724
|
const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
|
|
17281
|
-
return /* @__PURE__ */ (0,
|
|
17282
|
-
/* @__PURE__ */ (0,
|
|
17725
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ActionsContainer, { $role: role, className, children: [
|
|
17726
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
17283
17727
|
IconButton,
|
|
17284
17728
|
{
|
|
17285
17729
|
icon: isCopied ? IconCheck : IconCopy,
|
|
@@ -17287,7 +17731,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
|
|
|
17287
17731
|
"aria-label": isCopied ? "Copied" : "Copy message"
|
|
17288
17732
|
}
|
|
17289
17733
|
),
|
|
17290
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
17734
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
17291
17735
|
IconButton,
|
|
17292
17736
|
{
|
|
17293
17737
|
icon: IconThumbUp,
|
|
@@ -17296,7 +17740,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
|
|
|
17296
17740
|
"aria-label": "Good response"
|
|
17297
17741
|
}
|
|
17298
17742
|
) }),
|
|
17299
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
17743
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
17300
17744
|
IconButton,
|
|
17301
17745
|
{
|
|
17302
17746
|
icon: IconThumbDown,
|
|
@@ -17334,26 +17778,28 @@ var MessageBubble = import_styled_components6.default.div`
|
|
|
17334
17778
|
padding: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "12px 16px" : "0"};
|
|
17335
17779
|
border-radius: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "16px" : "0"};
|
|
17336
17780
|
max-width: 100%;
|
|
17781
|
+
width: 100%;
|
|
17337
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;
|
|
17338
17790
|
`;
|
|
17339
17791
|
|
|
17340
17792
|
// src/components/chat/chat-message/chat-message.tsx
|
|
17341
|
-
var
|
|
17793
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
17342
17794
|
function ChatMessage({ message }) {
|
|
17343
|
-
const
|
|
17344
|
-
|
|
17345
|
-
() => ({
|
|
17346
|
-
|
|
17347
|
-
}),
|
|
17348
|
-
[ChatTableActions, message.id]
|
|
17349
|
-
);
|
|
17350
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(MessageContainer, { $role: message.role, children: [
|
|
17351
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessageBubble, { $role: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BlockContext.Provider, { value: blockContextValue, children: message.blocks.map((block, index2) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Block, { block }, index2)) }) }),
|
|
17352
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
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)(
|
|
17353
17799
|
ChatMessageActions,
|
|
17354
17800
|
{
|
|
17355
17801
|
messageId: message.id,
|
|
17356
|
-
content:
|
|
17802
|
+
content: clipboardText,
|
|
17357
17803
|
role: message.role,
|
|
17358
17804
|
isHelpful: message.isHelpful
|
|
17359
17805
|
}
|
|
@@ -17398,20 +17844,20 @@ var Key = import_styled_components7.default.kbd`
|
|
|
17398
17844
|
`;
|
|
17399
17845
|
|
|
17400
17846
|
// src/components/keyboard-shortcut/keyboard-shortcut.tsx
|
|
17401
|
-
var
|
|
17847
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
17402
17848
|
function KeyboardShortcut({
|
|
17403
17849
|
keys,
|
|
17404
17850
|
variant = KEYBOARD_SHORTCUT_VARIANTS.OUTLINED,
|
|
17405
17851
|
className
|
|
17406
17852
|
}) {
|
|
17407
|
-
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)) });
|
|
17408
17854
|
}
|
|
17409
17855
|
|
|
17410
17856
|
// src/components/keyboard-shortcut/icons/icon-ctrl.tsx
|
|
17411
|
-
var
|
|
17857
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
17412
17858
|
function IconCtrl(props) {
|
|
17413
17859
|
const { width: width2 = 24, height: height2 = 24, ...rest } = props;
|
|
17414
|
-
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)(
|
|
17415
17861
|
"text",
|
|
17416
17862
|
{
|
|
17417
17863
|
x: "50%",
|
|
@@ -17428,7 +17874,7 @@ function IconCtrl(props) {
|
|
|
17428
17874
|
}
|
|
17429
17875
|
|
|
17430
17876
|
// src/components/lottie/lottie.tsx
|
|
17431
|
-
var
|
|
17877
|
+
var import_react14 = require("react");
|
|
17432
17878
|
|
|
17433
17879
|
// src/components/lottie/lottie-styles.ts
|
|
17434
17880
|
var import_styled_components8 = __toESM(require("styled-components"), 1);
|
|
@@ -17444,7 +17890,7 @@ var LottieContainer = import_styled_components8.default.div`
|
|
|
17444
17890
|
`;
|
|
17445
17891
|
|
|
17446
17892
|
// src/components/lottie/use-lottie.ts
|
|
17447
|
-
var
|
|
17893
|
+
var import_react13 = require("react");
|
|
17448
17894
|
var import_lottie_web = __toESM(require_lottie(), 1);
|
|
17449
17895
|
function useLottie({
|
|
17450
17896
|
animationData: animationData2,
|
|
@@ -17459,17 +17905,17 @@ function useLottie({
|
|
|
17459
17905
|
onLoopComplete,
|
|
17460
17906
|
onEnterFrame
|
|
17461
17907
|
}) {
|
|
17462
|
-
const containerRef = (0,
|
|
17463
|
-
const animationRef = (0,
|
|
17464
|
-
const onAnimationLoadedRef = (0,
|
|
17465
|
-
const onCompleteRef = (0,
|
|
17466
|
-
const onLoopCompleteRef = (0,
|
|
17467
|
-
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);
|
|
17468
17914
|
onAnimationLoadedRef.current = onAnimationLoaded;
|
|
17469
17915
|
onCompleteRef.current = onComplete;
|
|
17470
17916
|
onLoopCompleteRef.current = onLoopComplete;
|
|
17471
17917
|
onEnterFrameRef.current = onEnterFrame;
|
|
17472
|
-
(0,
|
|
17918
|
+
(0, import_react13.useEffect)(() => {
|
|
17473
17919
|
if (!containerRef.current) return;
|
|
17474
17920
|
const anim = import_lottie_web.default.loadAnimation({
|
|
17475
17921
|
container: containerRef.current,
|
|
@@ -17561,8 +18007,8 @@ function createLottieRef(animationRef) {
|
|
|
17561
18007
|
}
|
|
17562
18008
|
|
|
17563
18009
|
// src/components/lottie/lottie.tsx
|
|
17564
|
-
var
|
|
17565
|
-
var Lottie = (0,
|
|
18010
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
18011
|
+
var Lottie = (0, import_react14.forwardRef)(function Lottie2({
|
|
17566
18012
|
animationData: animationData2,
|
|
17567
18013
|
autoplay,
|
|
17568
18014
|
loop,
|
|
@@ -17592,8 +18038,8 @@ var Lottie = (0, import_react9.forwardRef)(function Lottie2({
|
|
|
17592
18038
|
onLoopComplete,
|
|
17593
18039
|
onEnterFrame
|
|
17594
18040
|
});
|
|
17595
|
-
(0,
|
|
17596
|
-
return /* @__PURE__ */ (0,
|
|
18041
|
+
(0, import_react14.useImperativeHandle)(ref, () => createLottieRef(animationRef), [animationRef]);
|
|
18042
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
17597
18043
|
LottieContainer,
|
|
17598
18044
|
{
|
|
17599
18045
|
ref: containerRef,
|
|
@@ -17607,7 +18053,7 @@ var Lottie = (0, import_react9.forwardRef)(function Lottie2({
|
|
|
17607
18053
|
});
|
|
17608
18054
|
|
|
17609
18055
|
// src/components/text-area/text-area.tsx
|
|
17610
|
-
var
|
|
18056
|
+
var import_react15 = require("react");
|
|
17611
18057
|
|
|
17612
18058
|
// src/utils/merge-refs.ts
|
|
17613
18059
|
function mergeRefs(...refs) {
|
|
@@ -17647,23 +18093,23 @@ var StyledTextArea = import_styled_components9.default.textarea`
|
|
|
17647
18093
|
`;
|
|
17648
18094
|
|
|
17649
18095
|
// src/components/text-area/text-area.tsx
|
|
17650
|
-
var
|
|
17651
|
-
var TextArea = (0,
|
|
17652
|
-
const internalRef = (0,
|
|
17653
|
-
(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)(() => {
|
|
17654
18100
|
const el = internalRef.current;
|
|
17655
18101
|
if (el) {
|
|
17656
18102
|
el.style.height = "auto";
|
|
17657
18103
|
el.style.height = `${el.scrollHeight}px`;
|
|
17658
18104
|
}
|
|
17659
18105
|
}, [value2]);
|
|
17660
|
-
const handleChange = (0,
|
|
18106
|
+
const handleChange = (0, import_react15.useCallback)(
|
|
17661
18107
|
(e) => {
|
|
17662
18108
|
onChange(e.target.value);
|
|
17663
18109
|
},
|
|
17664
18110
|
[onChange]
|
|
17665
18111
|
);
|
|
17666
|
-
return /* @__PURE__ */ (0,
|
|
18112
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
17667
18113
|
StyledTextArea,
|
|
17668
18114
|
{
|
|
17669
18115
|
ref: mergeRefs(internalRef, externalRef),
|
|
@@ -17733,21 +18179,26 @@ function parseMarkdownTable(markdown, tableIndex = 0) {
|
|
|
17733
18179
|
return null;
|
|
17734
18180
|
}
|
|
17735
18181
|
|
|
17736
|
-
// src/utils/
|
|
17737
|
-
|
|
17738
|
-
|
|
17739
|
-
|
|
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, '""')}"`;
|
|
17740
18189
|
}
|
|
17741
|
-
return
|
|
18190
|
+
return safeField;
|
|
17742
18191
|
}
|
|
18192
|
+
|
|
18193
|
+
// src/utils/convert-table-to-csv.ts
|
|
17743
18194
|
function convertTableToCSV(table) {
|
|
17744
|
-
const headerRow = table.columns.map(
|
|
17745
|
-
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(","));
|
|
17746
18197
|
return [headerRow, ...dataRows].join("\r\n");
|
|
17747
18198
|
}
|
|
17748
18199
|
|
|
17749
18200
|
// src/components/button/button.tsx
|
|
17750
|
-
var
|
|
18201
|
+
var import_react16 = require("react");
|
|
17751
18202
|
|
|
17752
18203
|
// src/components/button/button-styles.ts
|
|
17753
18204
|
var import_styled_components10 = __toESM(require("styled-components"), 1);
|
|
@@ -17869,8 +18320,8 @@ var StyledButton = import_styled_components10.default.button`
|
|
|
17869
18320
|
`;
|
|
17870
18321
|
|
|
17871
18322
|
// src/components/button/button.tsx
|
|
17872
|
-
var
|
|
17873
|
-
var Button2 = (0,
|
|
18323
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
18324
|
+
var Button2 = (0, import_react16.forwardRef)(function Button3({
|
|
17874
18325
|
children,
|
|
17875
18326
|
variant = BUTTON_VARIANT.SOLID,
|
|
17876
18327
|
intent = BUTTON_INTENT.PRIMARY,
|
|
@@ -17882,8 +18333,8 @@ var Button2 = (0, import_react11.forwardRef)(function Button3({
|
|
|
17882
18333
|
className,
|
|
17883
18334
|
"aria-label": ariaLabel
|
|
17884
18335
|
}, ref) {
|
|
17885
|
-
const iconElement = icon ? /* @__PURE__ */ (0,
|
|
17886
|
-
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)(
|
|
17887
18338
|
StyledButton,
|
|
17888
18339
|
{
|
|
17889
18340
|
ref,
|
|
@@ -17897,7 +18348,7 @@ var Button2 = (0, import_react11.forwardRef)(function Button3({
|
|
|
17897
18348
|
"aria-label": ariaLabel,
|
|
17898
18349
|
children: [
|
|
17899
18350
|
iconPosition === ICON_POSITION.LEADING && iconElement,
|
|
17900
|
-
/* @__PURE__ */ (0,
|
|
18351
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children }),
|
|
17901
18352
|
iconPosition === ICON_POSITION.TRAILING && iconElement
|
|
17902
18353
|
]
|
|
17903
18354
|
}
|
|
@@ -17905,6 +18356,10 @@ var Button2 = (0, import_react11.forwardRef)(function Button3({
|
|
|
17905
18356
|
});
|
|
17906
18357
|
// Annotate the CommonJS export names for ESM import in node:
|
|
17907
18358
|
0 && (module.exports = {
|
|
18359
|
+
ArtifactDownloadButton,
|
|
18360
|
+
ArtifactRefBlock,
|
|
18361
|
+
ArtifactRefBlockService,
|
|
18362
|
+
ArtifactServices,
|
|
17908
18363
|
BUTTON_INTENT,
|
|
17909
18364
|
BUTTON_SIZE,
|
|
17910
18365
|
BUTTON_VARIANT,
|
|
@@ -17922,12 +18377,18 @@ var Button2 = (0, import_react11.forwardRef)(function Button3({
|
|
|
17922
18377
|
KeyboardShortcut,
|
|
17923
18378
|
Lottie,
|
|
17924
18379
|
MESSAGE_ROLE,
|
|
18380
|
+
TableArtifact,
|
|
17925
18381
|
TextArea,
|
|
17926
18382
|
TextBlockService,
|
|
18383
|
+
artifactToClipboardText,
|
|
18384
|
+
artifactTypes,
|
|
17927
18385
|
blockTypes,
|
|
17928
18386
|
colors,
|
|
17929
18387
|
convertTableToCSV,
|
|
18388
|
+
copyMessageText,
|
|
18389
|
+
escapeCsvField,
|
|
17930
18390
|
fontFamilies,
|
|
18391
|
+
isSafeDownloadUrl,
|
|
17931
18392
|
markdownToPlainText,
|
|
17932
18393
|
mergeRefs,
|
|
17933
18394
|
parseMarkdownTable,
|
|
@@ -17954,6 +18415,7 @@ lottie-web/build/player/lottie.js:
|
|
|
17954
18415
|
@tabler/icons-react/dist/esm/createReactComponent.mjs:
|
|
17955
18416
|
@tabler/icons-react/dist/esm/icons/IconCheck.mjs:
|
|
17956
18417
|
@tabler/icons-react/dist/esm/icons/IconCopy.mjs:
|
|
18418
|
+
@tabler/icons-react/dist/esm/icons/IconDownload.mjs:
|
|
17957
18419
|
@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
|
|
17958
18420
|
@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
|
|
17959
18421
|
@tabler/icons-react/dist/esm/tabler-icons-react.mjs:
|