@shapesos/clay 0.10.0 → 0.12.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 +60 -0
- package/dist/artifacts.cjs +1467 -0
- package/dist/artifacts.cjs.map +1 -0
- package/dist/artifacts.d.cts +89 -0
- package/dist/artifacts.d.ts +89 -0
- package/dist/artifacts.js +33 -0
- package/dist/blocks.cjs +1418 -68
- package/dist/blocks.cjs.map +1 -1
- package/dist/blocks.css +2 -0
- package/dist/blocks.d.cts +36 -11
- package/dist/blocks.d.ts +36 -11
- package/dist/blocks.js +18 -5
- package/dist/button.d.cts +2 -2
- package/dist/button.d.ts +2 -2
- package/dist/chart.cjs +594 -0
- package/dist/chart.cjs.map +1 -0
- package/dist/chart.d.cts +439 -0
- package/dist/chart.d.ts +439 -0
- package/dist/chart.js +32 -0
- package/dist/chart.js.map +1 -0
- package/dist/chat.cjs +1462 -312
- package/dist/chat.cjs.map +1 -1
- package/dist/chat.d.cts +28 -10
- package/dist/chat.d.ts +28 -10
- package/dist/chat.js +10 -3
- package/dist/{chunk-R3BGPOAM.js → chunk-36CB624W.js} +53 -45
- package/dist/chunk-36CB624W.js.map +1 -0
- package/dist/chunk-4MZZH3WX.js +93 -0
- package/dist/chunk-4MZZH3WX.js.map +1 -0
- package/dist/chunk-AQEJRMRN.js +1 -0
- package/dist/chunk-AQEJRMRN.js.map +1 -0
- package/dist/{chunk-WS4IPADR.js → chunk-FFX3CAOX.js} +41 -109
- package/dist/chunk-FFX3CAOX.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-MLCRDVQ2.js → chunk-OBOXCBDL.js} +13 -5
- package/dist/chunk-OBOXCBDL.js.map +1 -0
- package/dist/chunk-P6GUNIAE.js +11 -0
- package/dist/chunk-P6GUNIAE.js.map +1 -0
- package/dist/chunk-QXGYMDIA.js +477 -0
- package/dist/chunk-QXGYMDIA.js.map +1 -0
- package/dist/chunk-Z5JWF24N.js +719 -0
- package/dist/chunk-Z5JWF24N.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 +1520 -332
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +58 -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 +25 -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-B2aYk82c.d.cts +29 -0
- package/dist/types-B2aYk82c.d.ts +29 -0
- package/dist/types-C0BvwliI.d.cts +332 -0
- package/dist/types-C5bFH4v3.d.ts +332 -0
- package/dist/types-DCutaXjZ.d.cts +83 -0
- package/dist/types-uPfn67Dc.d.ts +83 -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 +41 -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,
|
|
@@ -16349,8 +16353,11 @@ __export(src_exports, {
|
|
|
16349
16353
|
BlockContext: () => BlockContext,
|
|
16350
16354
|
BlockServices: () => BlockServices,
|
|
16351
16355
|
Button: () => Button2,
|
|
16356
|
+
ChartArtifact: () => ChartArtifact,
|
|
16352
16357
|
ChatContext: () => ChatContext,
|
|
16353
16358
|
ChatMessage: () => ChatMessage,
|
|
16359
|
+
DEFAULT_CHART_ARTIFACT_LABELS: () => DEFAULT_CHART_ARTIFACT_LABELS,
|
|
16360
|
+
DEFAULT_TABLE_ARTIFACT_LABELS: () => DEFAULT_TABLE_ARTIFACT_LABELS,
|
|
16354
16361
|
ICON_POSITION: () => ICON_POSITION,
|
|
16355
16362
|
Icon: () => Icon,
|
|
16356
16363
|
IconButton: () => IconButton,
|
|
@@ -16359,12 +16366,18 @@ __export(src_exports, {
|
|
|
16359
16366
|
KeyboardShortcut: () => KeyboardShortcut,
|
|
16360
16367
|
Lottie: () => Lottie,
|
|
16361
16368
|
MESSAGE_ROLE: () => MESSAGE_ROLE,
|
|
16369
|
+
TableArtifact: () => TableArtifact,
|
|
16362
16370
|
TextArea: () => TextArea,
|
|
16363
16371
|
TextBlockService: () => TextBlockService,
|
|
16372
|
+
artifactToClipboardText: () => artifactToClipboardText,
|
|
16373
|
+
artifactTypes: () => artifactTypes,
|
|
16364
16374
|
blockTypes: () => blockTypes,
|
|
16365
16375
|
colors: () => colors,
|
|
16366
16376
|
convertTableToCSV: () => convertTableToCSV,
|
|
16377
|
+
copyMessageText: () => copyMessageText,
|
|
16378
|
+
escapeCsvField: () => escapeCsvField,
|
|
16367
16379
|
fontFamilies: () => fontFamilies,
|
|
16380
|
+
isSafeDownloadUrl: () => isSafeDownloadUrl,
|
|
16368
16381
|
markdownToPlainText: () => markdownToPlainText,
|
|
16369
16382
|
mergeRefs: () => mergeRefs,
|
|
16370
16383
|
parseMarkdownTable: () => parseMarkdownTable,
|
|
@@ -16760,55 +16773,1398 @@ function typographyMixin(type) {
|
|
|
16760
16773
|
].join(";\n ");
|
|
16761
16774
|
}
|
|
16762
16775
|
|
|
16776
|
+
// src/components/blocks/types.ts
|
|
16777
|
+
var blockTypes = {
|
|
16778
|
+
TEXT: "TEXT",
|
|
16779
|
+
ARTIFACT_REF: "ARTIFACT_REF"
|
|
16780
|
+
};
|
|
16781
|
+
|
|
16782
|
+
// src/components/artifacts/artifact-base.ts
|
|
16783
|
+
var artifactTypes = {
|
|
16784
|
+
TABLE: "TABLE",
|
|
16785
|
+
CHART: "CHART"
|
|
16786
|
+
};
|
|
16787
|
+
|
|
16788
|
+
// src/components/artifacts/chart-artifact/types.ts
|
|
16789
|
+
var DEFAULT_CHART_ARTIFACT_LABELS = {
|
|
16790
|
+
download: "Download CSV",
|
|
16791
|
+
unavailable: "Chart data is unavailable.",
|
|
16792
|
+
loadError: "Couldn't load chart data.",
|
|
16793
|
+
loading: "Loading chart\u2026",
|
|
16794
|
+
empty: "No data to chart.",
|
|
16795
|
+
othersCategoryLabels: ["Others", "Other"]
|
|
16796
|
+
};
|
|
16797
|
+
|
|
16798
|
+
// src/components/artifacts/table-artifact/types.ts
|
|
16799
|
+
var DEFAULT_TABLE_ARTIFACT_LABELS = {
|
|
16800
|
+
download: "Download CSV",
|
|
16801
|
+
unavailable: "Table data is unavailable.",
|
|
16802
|
+
loadError: "Couldn't load table data.",
|
|
16803
|
+
loading: "Loading table\u2026",
|
|
16804
|
+
empty: "No rows to display."
|
|
16805
|
+
};
|
|
16806
|
+
|
|
16807
|
+
// src/components/artifacts/chart-artifact/chart-artifact.tsx
|
|
16808
|
+
var import_react9 = require("react");
|
|
16809
|
+
|
|
16810
|
+
// src/lib/utils.ts
|
|
16811
|
+
var import_clsx = require("clsx");
|
|
16812
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
16813
|
+
function cn(...inputs) {
|
|
16814
|
+
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
16815
|
+
}
|
|
16816
|
+
|
|
16817
|
+
// src/components/ai-elements/artifact.tsx
|
|
16818
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
16819
|
+
var Artifact = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
16820
|
+
"div",
|
|
16821
|
+
{
|
|
16822
|
+
className: cn("flex flex-col overflow-hidden rounded-lg border bg-background shadow-sm", className),
|
|
16823
|
+
...props
|
|
16824
|
+
}
|
|
16825
|
+
);
|
|
16826
|
+
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 });
|
|
16827
|
+
var ArtifactTitle = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: cn("font-medium text-foreground text-sm", className), ...props });
|
|
16828
|
+
var ArtifactActions = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("flex items-center gap-1", className), ...props });
|
|
16829
|
+
var ArtifactContent = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("flex-1 overflow-auto p-4", className), ...props });
|
|
16830
|
+
|
|
16831
|
+
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
16832
|
+
var import_react = require("react");
|
|
16833
|
+
|
|
16834
|
+
// node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs
|
|
16835
|
+
var defaultAttributes = {
|
|
16836
|
+
outline: {
|
|
16837
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
16838
|
+
width: 24,
|
|
16839
|
+
height: 24,
|
|
16840
|
+
viewBox: "0 0 24 24",
|
|
16841
|
+
fill: "none",
|
|
16842
|
+
stroke: "currentColor",
|
|
16843
|
+
strokeWidth: 2,
|
|
16844
|
+
strokeLinecap: "round",
|
|
16845
|
+
strokeLinejoin: "round"
|
|
16846
|
+
},
|
|
16847
|
+
filled: {
|
|
16848
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
16849
|
+
width: 24,
|
|
16850
|
+
height: 24,
|
|
16851
|
+
viewBox: "0 0 24 24",
|
|
16852
|
+
fill: "currentColor",
|
|
16853
|
+
stroke: "none"
|
|
16854
|
+
}
|
|
16855
|
+
};
|
|
16856
|
+
|
|
16857
|
+
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
16858
|
+
var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
|
|
16859
|
+
const Component = (0, import_react.forwardRef)(
|
|
16860
|
+
({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => (0, import_react.createElement)(
|
|
16861
|
+
"svg",
|
|
16862
|
+
{
|
|
16863
|
+
ref,
|
|
16864
|
+
...defaultAttributes[type],
|
|
16865
|
+
width: size,
|
|
16866
|
+
height: size,
|
|
16867
|
+
className: [`tabler-icon`, `tabler-icon-${iconName}`, className].join(" "),
|
|
16868
|
+
...type === "filled" ? {
|
|
16869
|
+
fill: color
|
|
16870
|
+
} : {
|
|
16871
|
+
strokeWidth: stroke,
|
|
16872
|
+
stroke: color
|
|
16873
|
+
},
|
|
16874
|
+
...rest
|
|
16875
|
+
},
|
|
16876
|
+
[
|
|
16877
|
+
title && (0, import_react.createElement)("title", { key: "svg-title" }, title),
|
|
16878
|
+
...iconNode.map(([tag, attrs]) => (0, import_react.createElement)(tag, attrs)),
|
|
16879
|
+
...Array.isArray(children) ? children : [children]
|
|
16880
|
+
]
|
|
16881
|
+
)
|
|
16882
|
+
);
|
|
16883
|
+
Component.displayName = `${iconNamePascal}`;
|
|
16884
|
+
return Component;
|
|
16885
|
+
};
|
|
16886
|
+
|
|
16887
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
|
|
16888
|
+
var __iconNode = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
|
|
16889
|
+
var IconCheck = createReactComponent("outline", "check", "Check", __iconNode);
|
|
16890
|
+
|
|
16891
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
|
|
16892
|
+
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" }]];
|
|
16893
|
+
var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode2);
|
|
16894
|
+
|
|
16895
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconDownload.mjs
|
|
16896
|
+
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" }]];
|
|
16897
|
+
var IconDownload = createReactComponent("outline", "download", "Download", __iconNode3);
|
|
16898
|
+
|
|
16899
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
|
|
16900
|
+
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" }]];
|
|
16901
|
+
var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode4);
|
|
16902
|
+
|
|
16903
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
|
|
16904
|
+
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" }]];
|
|
16905
|
+
var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode5);
|
|
16906
|
+
|
|
16907
|
+
// src/components/icon-button/icon-button.tsx
|
|
16908
|
+
var import_react3 = require("react");
|
|
16909
|
+
|
|
16910
|
+
// src/components/icon/icon.tsx
|
|
16911
|
+
var import_react2 = require("react");
|
|
16912
|
+
|
|
16913
|
+
// src/components/icon/icon-styles.ts
|
|
16914
|
+
var import_styled_components = __toESM(require("styled-components"), 1);
|
|
16915
|
+
var STROKE_WIDTH_BY_SIZE = {
|
|
16916
|
+
12: 1.4,
|
|
16917
|
+
14: 1.4,
|
|
16918
|
+
16: 1.8,
|
|
16919
|
+
18: 1.8,
|
|
16920
|
+
20: 1.8,
|
|
16921
|
+
24: 1.8
|
|
16922
|
+
};
|
|
16923
|
+
var DEFAULT_STROKE_WIDTH = 1.8;
|
|
16924
|
+
function getStrokeWidth(size) {
|
|
16925
|
+
return STROKE_WIDTH_BY_SIZE[size] ?? DEFAULT_STROKE_WIDTH;
|
|
16926
|
+
}
|
|
16927
|
+
var IconWrapper = import_styled_components.default.span`
|
|
16928
|
+
display: inline-flex;
|
|
16929
|
+
align-items: center;
|
|
16930
|
+
justify-content: center;
|
|
16931
|
+
color: ${({ $color }) => $color ?? "currentColor"};
|
|
16932
|
+
flex-shrink: 0;
|
|
16933
|
+
`;
|
|
16934
|
+
|
|
16935
|
+
// src/components/icon/icon.tsx
|
|
16936
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
16937
|
+
var DEFAULT_SIZE = 16;
|
|
16938
|
+
var Icon = (0, import_react2.forwardRef)(function Icon2({ icon: IconComponent, size = DEFAULT_SIZE, color, className, "aria-label": ariaLabel }, ref) {
|
|
16939
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
16940
|
+
IconWrapper,
|
|
16941
|
+
{
|
|
16942
|
+
ref,
|
|
16943
|
+
className,
|
|
16944
|
+
$color: color,
|
|
16945
|
+
"aria-label": ariaLabel,
|
|
16946
|
+
role: ariaLabel ? "img" : void 0,
|
|
16947
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconComponent, { width: size, height: size, strokeWidth: getStrokeWidth(size) })
|
|
16948
|
+
}
|
|
16949
|
+
);
|
|
16950
|
+
});
|
|
16951
|
+
|
|
16952
|
+
// src/components/icon-button/icon-button-styles.ts
|
|
16953
|
+
var import_styled_components2 = __toESM(require("styled-components"), 1);
|
|
16954
|
+
var PADDING = {
|
|
16955
|
+
short: {
|
|
16956
|
+
small: "4px",
|
|
16957
|
+
medium: "6px"
|
|
16958
|
+
},
|
|
16959
|
+
long: {
|
|
16960
|
+
small: "4px 6px",
|
|
16961
|
+
medium: "6px 10px"
|
|
16962
|
+
}
|
|
16963
|
+
};
|
|
16964
|
+
var BORDER_RADIUS = {
|
|
16965
|
+
small: 6,
|
|
16966
|
+
medium: 10
|
|
16967
|
+
};
|
|
16968
|
+
var Button = import_styled_components2.default.button`
|
|
16969
|
+
display: inline-flex;
|
|
16970
|
+
align-items: center;
|
|
16971
|
+
justify-content: center;
|
|
16972
|
+
padding: ${({ $size, $variant }) => PADDING[$variant][$size]};
|
|
16973
|
+
border: none;
|
|
16974
|
+
border-radius: ${({ $size }) => BORDER_RADIUS[$size]}px;
|
|
16975
|
+
background: ${({ $isSelected }) => $isSelected ? colors["brown-40"] : "transparent"};
|
|
16976
|
+
color: ${colors["brown-100"]};
|
|
16977
|
+
cursor: pointer;
|
|
16978
|
+
transition: background-color 100ms ease;
|
|
16979
|
+
|
|
16980
|
+
&:hover {
|
|
16981
|
+
background: ${({ $isSelected }) => $isSelected ? colors["brown-40"] : colors["brown-20"]};
|
|
16982
|
+
}
|
|
16983
|
+
|
|
16984
|
+
&:active {
|
|
16985
|
+
background: ${colors["brown-40"]};
|
|
16986
|
+
}
|
|
16987
|
+
|
|
16988
|
+
&:disabled {
|
|
16989
|
+
color: ${colors["brown-50"]};
|
|
16990
|
+
background: transparent;
|
|
16991
|
+
cursor: not-allowed;
|
|
16992
|
+
}
|
|
16993
|
+
`;
|
|
16994
|
+
|
|
16995
|
+
// src/components/icon-button/icon-button.tsx
|
|
16996
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
16997
|
+
var ICON_SIZE_BY_BUTTON_SIZE = {
|
|
16998
|
+
small: 16,
|
|
16999
|
+
medium: 20
|
|
17000
|
+
};
|
|
17001
|
+
var IconButton = (0, import_react3.forwardRef)(function IconButton2({
|
|
17002
|
+
icon,
|
|
17003
|
+
size = "small",
|
|
17004
|
+
variant = "short",
|
|
17005
|
+
isSelected = false,
|
|
17006
|
+
disabled = false,
|
|
17007
|
+
onClick,
|
|
17008
|
+
className,
|
|
17009
|
+
id,
|
|
17010
|
+
as,
|
|
17011
|
+
"aria-label": ariaLabel,
|
|
17012
|
+
...rest
|
|
17013
|
+
}, ref) {
|
|
17014
|
+
const isNativeButton = as === void 0 || as === "button";
|
|
17015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
17016
|
+
Button,
|
|
17017
|
+
{
|
|
17018
|
+
ref,
|
|
17019
|
+
className,
|
|
17020
|
+
id,
|
|
17021
|
+
as,
|
|
17022
|
+
$size: size,
|
|
17023
|
+
$variant: variant,
|
|
17024
|
+
$isSelected: isSelected,
|
|
17025
|
+
disabled,
|
|
17026
|
+
onClick: disabled ? void 0 : onClick,
|
|
17027
|
+
"aria-label": ariaLabel,
|
|
17028
|
+
...isNativeButton ? { type: "button" } : {},
|
|
17029
|
+
...rest,
|
|
17030
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { icon, size: ICON_SIZE_BY_BUTTON_SIZE[size] })
|
|
17031
|
+
}
|
|
17032
|
+
);
|
|
17033
|
+
});
|
|
17034
|
+
|
|
17035
|
+
// src/components/ui/tooltip.tsx
|
|
17036
|
+
var React = __toESM(require("react"), 1);
|
|
17037
|
+
var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"), 1);
|
|
17038
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
17039
|
+
var TooltipProvider = TooltipPrimitive.Provider;
|
|
17040
|
+
var Tooltip = TooltipPrimitive.Root;
|
|
17041
|
+
var TooltipTrigger = TooltipPrimitive.Trigger;
|
|
17042
|
+
var TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
17043
|
+
TooltipPrimitive.Content,
|
|
17044
|
+
{
|
|
17045
|
+
ref,
|
|
17046
|
+
sideOffset,
|
|
17047
|
+
className: cn(
|
|
17048
|
+
"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]",
|
|
17049
|
+
className
|
|
17050
|
+
),
|
|
17051
|
+
...props
|
|
17052
|
+
}
|
|
17053
|
+
));
|
|
17054
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
17055
|
+
|
|
17056
|
+
// src/components/artifacts/artifact-download-button/artifact-download-button.tsx
|
|
17057
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
17058
|
+
var DEFAULT_LABEL = "Download CSV";
|
|
17059
|
+
function ArtifactDownloadButton({
|
|
17060
|
+
href,
|
|
17061
|
+
label = DEFAULT_LABEL,
|
|
17062
|
+
onClick
|
|
17063
|
+
}) {
|
|
17064
|
+
if (!isSafeDownloadUrl(href)) return null;
|
|
17065
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Tooltip, { children: [
|
|
17066
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
17067
|
+
IconButton,
|
|
17068
|
+
{
|
|
17069
|
+
as: "a",
|
|
17070
|
+
href,
|
|
17071
|
+
download: true,
|
|
17072
|
+
rel: "noopener noreferrer",
|
|
17073
|
+
onClick,
|
|
17074
|
+
icon: IconDownload,
|
|
17075
|
+
size: "small",
|
|
17076
|
+
"aria-label": label
|
|
17077
|
+
}
|
|
17078
|
+
) }),
|
|
17079
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TooltipContent, { children: label })
|
|
17080
|
+
] }) });
|
|
17081
|
+
}
|
|
17082
|
+
function isSafeDownloadUrl(url) {
|
|
17083
|
+
try {
|
|
17084
|
+
const parsed = new URL(url);
|
|
17085
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
17086
|
+
} catch {
|
|
17087
|
+
return false;
|
|
17088
|
+
}
|
|
17089
|
+
}
|
|
17090
|
+
|
|
17091
|
+
// src/components/artifacts/status-message.tsx
|
|
17092
|
+
var import_react4 = require("react");
|
|
17093
|
+
function StatusMessage({ $tone, children }) {
|
|
17094
|
+
return (0, import_react4.createElement)(
|
|
17095
|
+
"div",
|
|
17096
|
+
{
|
|
17097
|
+
className: `py-6 px-2 text-center text-sm font-medium leading-5 ${$tone === "error" ? "text-red-600" : "text-brown-70"}`
|
|
17098
|
+
},
|
|
17099
|
+
children
|
|
17100
|
+
);
|
|
17101
|
+
}
|
|
17102
|
+
|
|
17103
|
+
// src/components/chart/bar-chart/bar-chart.tsx
|
|
17104
|
+
var import_react5 = require("react");
|
|
17105
|
+
var import_recharts2 = require("recharts");
|
|
17106
|
+
|
|
17107
|
+
// src/components/chart/chart-container.tsx
|
|
17108
|
+
var import_recharts = require("recharts");
|
|
17109
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
17110
|
+
function ChartContainer({
|
|
17111
|
+
children,
|
|
17112
|
+
height: height2 = 320,
|
|
17113
|
+
width: width2 = "100%",
|
|
17114
|
+
className,
|
|
17115
|
+
style
|
|
17116
|
+
}) {
|
|
17117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: cn("text-xs text-foreground", className), style: { width: width2, height: height2, ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.ResponsiveContainer, { width: "100%", height: "100%", children }) });
|
|
17118
|
+
}
|
|
17119
|
+
|
|
17120
|
+
// src/components/chart/chart-legend-content.tsx
|
|
17121
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
17122
|
+
function ChartLegendContent({ payload, className, iconType = "square" }) {
|
|
17123
|
+
if (!payload || payload.length === 0) return null;
|
|
17124
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
17125
|
+
"ul",
|
|
17126
|
+
{
|
|
17127
|
+
className: cn("flex flex-wrap items-center justify-center gap-x-4 gap-y-2 text-xs text-brown-80", className),
|
|
17128
|
+
children: payload.map((entry, i) => {
|
|
17129
|
+
const swatchColor = typeof entry.color === "string" ? entry.color : "transparent";
|
|
17130
|
+
const label = entry.value !== void 0 ? String(entry.value) : "";
|
|
17131
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("li", { className: "flex items-center gap-1.5", children: [
|
|
17132
|
+
iconType === "square" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "inline-block h-2.5 w-2.5 shrink-0 rounded-sm", style: { background: swatchColor } }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "inline-block h-[3px] w-4 shrink-0 rounded-full", style: { background: swatchColor } }),
|
|
17133
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: label })
|
|
17134
|
+
] }, `${label}-${i}`);
|
|
17135
|
+
})
|
|
17136
|
+
}
|
|
17137
|
+
);
|
|
17138
|
+
}
|
|
17139
|
+
|
|
17140
|
+
// src/components/chart/chart-tooltip-content.tsx
|
|
17141
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
17142
|
+
function ChartTooltipContent({
|
|
17143
|
+
active: active2,
|
|
17144
|
+
payload,
|
|
17145
|
+
label,
|
|
17146
|
+
className,
|
|
17147
|
+
showLabel = true,
|
|
17148
|
+
formatValue
|
|
17149
|
+
}) {
|
|
17150
|
+
if (!active2 || !payload || payload.length === 0) return null;
|
|
17151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
17152
|
+
"div",
|
|
17153
|
+
{
|
|
17154
|
+
className: cn(
|
|
17155
|
+
"rounded-lg border border-brown-40 bg-brown-10 px-3 py-2 text-xs shadow-sm",
|
|
17156
|
+
"min-w-32 text-foreground",
|
|
17157
|
+
className
|
|
17158
|
+
),
|
|
17159
|
+
children: [
|
|
17160
|
+
showLabel && label !== void 0 && label !== null ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mb-1.5 font-medium text-brown-90", children: String(label) }) : null,
|
|
17161
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { className: "space-y-1", children: payload.map((entry, i) => {
|
|
17162
|
+
const name2 = entry.name !== void 0 ? String(entry.name) : "";
|
|
17163
|
+
const rawValue = entry.value;
|
|
17164
|
+
const display = formatValue ? formatValue(rawValue, name2) : rawValue === void 0 ? "" : String(rawValue);
|
|
17165
|
+
const swatch = typeof entry.color === "string" ? entry.color : "transparent";
|
|
17166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("li", { className: "flex items-center gap-2", children: [
|
|
17167
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-block h-2.5 w-2.5 shrink-0 rounded-sm", style: { background: swatch } }),
|
|
17168
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-brown-70", children: name2 }),
|
|
17169
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ml-auto font-semibold tabular-nums text-brown-90", children: display })
|
|
17170
|
+
] }, `${name2}-${i}`);
|
|
17171
|
+
}) })
|
|
17172
|
+
]
|
|
17173
|
+
}
|
|
17174
|
+
);
|
|
17175
|
+
}
|
|
17176
|
+
|
|
17177
|
+
// src/components/chart/chart-palette.ts
|
|
17178
|
+
var CHART_PALETTE = [
|
|
17179
|
+
colors["blue-600"],
|
|
17180
|
+
// #2563EB — primary
|
|
17181
|
+
colors["blue-400"],
|
|
17182
|
+
// #60A5FA — mid
|
|
17183
|
+
colors["blue-300"],
|
|
17184
|
+
// #93C5FD — light
|
|
17185
|
+
colors["blue-100"],
|
|
17186
|
+
// #DBEAFE — very light
|
|
17187
|
+
colors["indigo-400"],
|
|
17188
|
+
// #818CF8
|
|
17189
|
+
colors["indigo-500"],
|
|
17190
|
+
// #6366F1
|
|
17191
|
+
colors["indigo-600"],
|
|
17192
|
+
// #4F46E5
|
|
17193
|
+
colors["indigo-800"],
|
|
17194
|
+
// #3730A3
|
|
17195
|
+
colors["blue-800"]
|
|
17196
|
+
// #1E40AF — deepest
|
|
17197
|
+
];
|
|
17198
|
+
var OTHERS_SLICE_COLOR = colors["brown-60"];
|
|
17199
|
+
var DEFAULT_OTHERS_CATEGORY_LABELS = ["others", "other"];
|
|
17200
|
+
function isOthersCategory(value2, labels) {
|
|
17201
|
+
if (value2 === null || value2 === void 0) return false;
|
|
17202
|
+
if (labels.length === 0) return false;
|
|
17203
|
+
const normalized = String(value2).trim().toLowerCase();
|
|
17204
|
+
for (const label of labels) {
|
|
17205
|
+
if (normalized === label.toLowerCase()) return true;
|
|
17206
|
+
}
|
|
17207
|
+
return false;
|
|
17208
|
+
}
|
|
17209
|
+
function colorForSeriesIndex(index2, palette = CHART_PALETTE) {
|
|
17210
|
+
return palette[index2 % palette.length] ?? CHART_PALETTE[0];
|
|
17211
|
+
}
|
|
17212
|
+
|
|
17213
|
+
// src/components/chart/chart-styles.ts
|
|
17214
|
+
var GRID_STROKE = colors["brown-40"];
|
|
17215
|
+
var AXIS_STROKE = colors["brown-50"];
|
|
17216
|
+
var AXIS_TICK_STYLE = {
|
|
17217
|
+
fill: colors["brown-70"],
|
|
17218
|
+
fontSize: 12,
|
|
17219
|
+
fontWeight: 500
|
|
17220
|
+
};
|
|
17221
|
+
var CHART_VALUE_LABEL_STYLE = {
|
|
17222
|
+
fill: colors["brown-70"],
|
|
17223
|
+
fontSize: 12,
|
|
17224
|
+
fontWeight: 500
|
|
17225
|
+
};
|
|
17226
|
+
var BAR_TOOLTIP_CURSOR_FILL = colors["brown-alpha-12"];
|
|
17227
|
+
var LINE_ACTIVE_DOT_STROKE = colors["brown-10"];
|
|
17228
|
+
var CHART_MARGIN = { top: 8, right: 16, left: 0, bottom: 4 };
|
|
17229
|
+
var PIE_CHART_MARGIN = { top: 0, right: 24, left: 24, bottom: 4 };
|
|
17230
|
+
var CHART_AXIS_PROPS = {
|
|
17231
|
+
stroke: AXIS_STROKE,
|
|
17232
|
+
tick: AXIS_TICK_STYLE,
|
|
17233
|
+
tickLine: false,
|
|
17234
|
+
axisLine: false
|
|
17235
|
+
};
|
|
17236
|
+
var CHART_GRID_PROPS = {
|
|
17237
|
+
stroke: GRID_STROKE,
|
|
17238
|
+
strokeDasharray: "3 3",
|
|
17239
|
+
vertical: false
|
|
17240
|
+
};
|
|
17241
|
+
|
|
17242
|
+
// src/components/chart/chart-tick-utils.ts
|
|
17243
|
+
function maxTickCharsByCategoryCount(n) {
|
|
17244
|
+
if (n <= 5) return 24;
|
|
17245
|
+
if (n <= 8) return 14;
|
|
17246
|
+
if (n <= 12) return 10;
|
|
17247
|
+
if (n <= 16) return 7;
|
|
17248
|
+
return 5;
|
|
17249
|
+
}
|
|
17250
|
+
function truncateLabel(value2, maxChars) {
|
|
17251
|
+
const s = String(value2 ?? "");
|
|
17252
|
+
if (s.length <= maxChars) return s;
|
|
17253
|
+
return s.slice(0, Math.max(1, maxChars - 1)).trimEnd() + "\u2026";
|
|
17254
|
+
}
|
|
17255
|
+
function evenlyDistributedVisibleIndices(n, target) {
|
|
17256
|
+
if (n <= target) {
|
|
17257
|
+
return new Set(Array.from({ length: n }, (_, i) => i));
|
|
17258
|
+
}
|
|
17259
|
+
const set = /* @__PURE__ */ new Set();
|
|
17260
|
+
const step = (n - 1) / (target - 1);
|
|
17261
|
+
for (let i = 0; i < target; i++) {
|
|
17262
|
+
set.add(Math.round(i * step));
|
|
17263
|
+
}
|
|
17264
|
+
return set;
|
|
17265
|
+
}
|
|
17266
|
+
function defaultBarTickFormatter(categoryCount) {
|
|
17267
|
+
const max = maxTickCharsByCategoryCount(categoryCount);
|
|
17268
|
+
return (value2) => truncateLabel(value2, max);
|
|
17269
|
+
}
|
|
17270
|
+
function defaultLineChartTickFormatter(categoryCount, visibleIndices) {
|
|
17271
|
+
const max = maxTickCharsByCategoryCount(visibleIndices.size || categoryCount);
|
|
17272
|
+
return (value2, index2) => {
|
|
17273
|
+
if (!visibleIndices.has(index2)) return "";
|
|
17274
|
+
return truncateLabel(value2, max);
|
|
17275
|
+
};
|
|
17276
|
+
}
|
|
17277
|
+
|
|
17278
|
+
// src/components/chart/coerce-numeric.ts
|
|
17279
|
+
function coerceNumericColumns(rows, numericKeys) {
|
|
17280
|
+
return rows.map((row) => {
|
|
17281
|
+
const out = { ...row };
|
|
17282
|
+
for (const k of numericKeys) {
|
|
17283
|
+
const v = out[k];
|
|
17284
|
+
if (v == null) continue;
|
|
17285
|
+
const n = Number(v);
|
|
17286
|
+
out[k] = Number.isFinite(n) ? n : NaN;
|
|
17287
|
+
}
|
|
17288
|
+
return out;
|
|
17289
|
+
});
|
|
17290
|
+
}
|
|
17291
|
+
|
|
17292
|
+
// src/components/chart/bar-chart/bar-chart.tsx
|
|
17293
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
17294
|
+
function BarChart({
|
|
17295
|
+
data: data2,
|
|
17296
|
+
xKey,
|
|
17297
|
+
series,
|
|
17298
|
+
stacked = false,
|
|
17299
|
+
height: height2 = 320,
|
|
17300
|
+
width: width2 = "100%",
|
|
17301
|
+
className,
|
|
17302
|
+
palette = CHART_PALETTE,
|
|
17303
|
+
showTooltip = true,
|
|
17304
|
+
showLegend,
|
|
17305
|
+
showGrid = true,
|
|
17306
|
+
showXAxis = true,
|
|
17307
|
+
showYAxis = true,
|
|
17308
|
+
showValueLabels,
|
|
17309
|
+
xAxisInterval = 0,
|
|
17310
|
+
xAxisAngle,
|
|
17311
|
+
xAxisTickFormatter
|
|
17312
|
+
}) {
|
|
17313
|
+
const seriesKeys = (0, import_react5.useMemo)(() => series.map((s) => s.key), [series]);
|
|
17314
|
+
const coercedData = (0, import_react5.useMemo)(
|
|
17315
|
+
() => coerceNumericColumns(data2, seriesKeys),
|
|
17316
|
+
[data2, seriesKeys]
|
|
17317
|
+
);
|
|
17318
|
+
const resolvedShowLegend = showLegend ?? series.length > 1;
|
|
17319
|
+
const resolvedShowValueLabels = showValueLabels ?? (!stacked && series.length === 1);
|
|
17320
|
+
const resolvedAngle = xAxisAngle ?? (coercedData.length >= 8 ? -30 : 0);
|
|
17321
|
+
const resolvedTickFormatter = (0, import_react5.useMemo)(
|
|
17322
|
+
() => xAxisTickFormatter ?? defaultBarTickFormatter(coercedData.length),
|
|
17323
|
+
[xAxisTickFormatter, coercedData.length]
|
|
17324
|
+
);
|
|
17325
|
+
const angledLabelPad = resolvedAngle === 0 ? 0 : Math.min(Math.abs(resolvedAngle) * 0.7, 40);
|
|
17326
|
+
const chartMargin = { ...CHART_MARGIN, bottom: CHART_MARGIN.bottom + angledLabelPad };
|
|
17327
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChartContainer, { height: height2, width: width2, className, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_recharts2.BarChart, { data: coercedData, margin: chartMargin, barCategoryGap: "22%", children: [
|
|
17328
|
+
showGrid ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_recharts2.CartesianGrid, { ...CHART_GRID_PROPS }) : null,
|
|
17329
|
+
showXAxis ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
17330
|
+
import_recharts2.XAxis,
|
|
17331
|
+
{
|
|
17332
|
+
dataKey: xKey,
|
|
17333
|
+
...CHART_AXIS_PROPS,
|
|
17334
|
+
interval: xAxisInterval,
|
|
17335
|
+
angle: resolvedAngle,
|
|
17336
|
+
textAnchor: resolvedAngle !== 0 ? "end" : "middle",
|
|
17337
|
+
tickMargin: resolvedAngle === 0 ? 8 : 12,
|
|
17338
|
+
height: resolvedAngle !== 0 ? 60 : void 0,
|
|
17339
|
+
tickFormatter: resolvedTickFormatter
|
|
17340
|
+
}
|
|
17341
|
+
) : null,
|
|
17342
|
+
showYAxis ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_recharts2.YAxis, { ...CHART_AXIS_PROPS, width: 40 }) : null,
|
|
17343
|
+
showTooltip ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_recharts2.Tooltip, { cursor: { fill: BAR_TOOLTIP_CURSOR_FILL }, content: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChartTooltipContent, {}) }) : null,
|
|
17344
|
+
resolvedShowLegend ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
17345
|
+
import_recharts2.Legend,
|
|
17346
|
+
{
|
|
17347
|
+
verticalAlign: "top",
|
|
17348
|
+
align: "center",
|
|
17349
|
+
wrapperStyle: { top: 0 },
|
|
17350
|
+
itemSorter: null,
|
|
17351
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChartLegendContent, { iconType: "square" })
|
|
17352
|
+
}
|
|
17353
|
+
) : null,
|
|
17354
|
+
series.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
17355
|
+
import_recharts2.Bar,
|
|
17356
|
+
{
|
|
17357
|
+
dataKey: s.key,
|
|
17358
|
+
name: s.label,
|
|
17359
|
+
fill: colorForSeriesIndex(i, palette),
|
|
17360
|
+
stackId: stacked ? "default" : s.key,
|
|
17361
|
+
radius: barRadius(stacked, i, series.length),
|
|
17362
|
+
children: resolvedShowValueLabels ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_recharts2.LabelList, { dataKey: s.key, position: "top", style: CHART_VALUE_LABEL_STYLE }) : null
|
|
17363
|
+
},
|
|
17364
|
+
s.key
|
|
17365
|
+
))
|
|
17366
|
+
] }) });
|
|
17367
|
+
}
|
|
17368
|
+
function barRadius(stacked, seriesIndex, seriesCount) {
|
|
17369
|
+
if (!stacked) return [6, 6, 0, 0];
|
|
17370
|
+
const isTopSegment = seriesIndex === seriesCount - 1;
|
|
17371
|
+
return isTopSegment ? [6, 6, 0, 0] : [0, 0, 0, 0];
|
|
17372
|
+
}
|
|
17373
|
+
|
|
17374
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/constants.ts
|
|
17375
|
+
var VARIANT_CHART_HEIGHT = "100%";
|
|
17376
|
+
|
|
17377
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/bar-chart-variant-component.tsx
|
|
17378
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
17379
|
+
function BarChartVariantComponent({ config, rows }) {
|
|
17380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
17381
|
+
BarChart,
|
|
17382
|
+
{
|
|
17383
|
+
data: rows,
|
|
17384
|
+
xKey: config.xKey,
|
|
17385
|
+
series: config.series,
|
|
17386
|
+
stacked: config.stacked,
|
|
17387
|
+
height: VARIANT_CHART_HEIGHT
|
|
17388
|
+
}
|
|
17389
|
+
);
|
|
17390
|
+
}
|
|
17391
|
+
|
|
17392
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/shared-column-keys.ts
|
|
17393
|
+
function seriesBasedColumnKeys(config) {
|
|
17394
|
+
return [config.xKey, ...config.series.map((s) => s.key)];
|
|
17395
|
+
}
|
|
17396
|
+
function pieColumnKeys(config) {
|
|
17397
|
+
return [config.categoryKey, config.valueKey];
|
|
17398
|
+
}
|
|
17399
|
+
|
|
17400
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/shared-validators.ts
|
|
17401
|
+
function isValidChartSeries(series) {
|
|
17402
|
+
if (!series || typeof series !== "object") return false;
|
|
17403
|
+
const candidate = series;
|
|
17404
|
+
if (typeof candidate.key !== "string" || candidate.key.length === 0) return false;
|
|
17405
|
+
if (typeof candidate.label !== "string") return false;
|
|
17406
|
+
return true;
|
|
17407
|
+
}
|
|
17408
|
+
|
|
17409
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/bar-chart-variant-service.tsx
|
|
17410
|
+
function isValidBarChartConfig(config) {
|
|
17411
|
+
if (!config || typeof config !== "object") return false;
|
|
17412
|
+
const candidate = config;
|
|
17413
|
+
if (candidate.variant !== "BAR") return false;
|
|
17414
|
+
if (typeof candidate.xKey !== "string" || candidate.xKey.length === 0) return false;
|
|
17415
|
+
if (!Array.isArray(candidate.series) || candidate.series.length === 0) return false;
|
|
17416
|
+
if (!candidate.series.every(isValidChartSeries)) return false;
|
|
17417
|
+
return true;
|
|
17418
|
+
}
|
|
17419
|
+
var BarChartVariantService = {
|
|
17420
|
+
variant: "BAR",
|
|
17421
|
+
isValidConfig: isValidBarChartConfig,
|
|
17422
|
+
columnKeys: seriesBasedColumnKeys,
|
|
17423
|
+
Component: BarChartVariantComponent
|
|
17424
|
+
};
|
|
17425
|
+
|
|
17426
|
+
// src/components/chart/line-chart/line-chart.tsx
|
|
17427
|
+
var import_react6 = require("react");
|
|
17428
|
+
var import_recharts3 = require("recharts");
|
|
17429
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
17430
|
+
var TARGET_VISIBLE_LABELS = 5;
|
|
17431
|
+
function LineChart({
|
|
17432
|
+
data: data2,
|
|
17433
|
+
xKey,
|
|
17434
|
+
series,
|
|
17435
|
+
smooth: smooth2 = true,
|
|
17436
|
+
showDots = true,
|
|
17437
|
+
strokeWidth = 2,
|
|
17438
|
+
height: height2 = 320,
|
|
17439
|
+
width: width2 = "100%",
|
|
17440
|
+
className,
|
|
17441
|
+
palette = CHART_PALETTE,
|
|
17442
|
+
showTooltip = true,
|
|
17443
|
+
showLegend,
|
|
17444
|
+
showGrid = true,
|
|
17445
|
+
showXAxis = true,
|
|
17446
|
+
showYAxis = true,
|
|
17447
|
+
showValueLabels = false,
|
|
17448
|
+
xAxisInterval = 0,
|
|
17449
|
+
xAxisAngle = 0,
|
|
17450
|
+
xAxisTickFormatter
|
|
17451
|
+
}) {
|
|
17452
|
+
const seriesKeys = (0, import_react6.useMemo)(() => series.map((s) => s.key), [series]);
|
|
17453
|
+
const coercedData = (0, import_react6.useMemo)(
|
|
17454
|
+
() => coerceNumericColumns(data2, seriesKeys),
|
|
17455
|
+
[data2, seriesKeys]
|
|
17456
|
+
);
|
|
17457
|
+
const lineType = smooth2 ? "monotone" : "linear";
|
|
17458
|
+
const resolvedShowLegend = showLegend ?? series.length > 1;
|
|
17459
|
+
const resolvedTickFormatter = (0, import_react6.useMemo)(() => {
|
|
17460
|
+
if (xAxisTickFormatter) return xAxisTickFormatter;
|
|
17461
|
+
const visible = evenlyDistributedVisibleIndices(coercedData.length, TARGET_VISIBLE_LABELS);
|
|
17462
|
+
return defaultLineChartTickFormatter(coercedData.length, visible);
|
|
17463
|
+
}, [xAxisTickFormatter, coercedData.length]);
|
|
17464
|
+
const angledLabelPad = xAxisAngle === 0 ? 0 : Math.min(Math.abs(xAxisAngle) * 0.7, 40);
|
|
17465
|
+
const chartMargin = { ...CHART_MARGIN, right: CHART_MARGIN.right + 16, bottom: CHART_MARGIN.bottom + angledLabelPad };
|
|
17466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ChartContainer, { height: height2, width: width2, className, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_recharts3.LineChart, { data: coercedData, margin: chartMargin, children: [
|
|
17467
|
+
showGrid ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_recharts3.CartesianGrid, { ...CHART_GRID_PROPS }) : null,
|
|
17468
|
+
showXAxis ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
17469
|
+
import_recharts3.XAxis,
|
|
17470
|
+
{
|
|
17471
|
+
dataKey: xKey,
|
|
17472
|
+
...CHART_AXIS_PROPS,
|
|
17473
|
+
interval: xAxisInterval,
|
|
17474
|
+
angle: xAxisAngle,
|
|
17475
|
+
textAnchor: xAxisAngle !== 0 ? "end" : "middle",
|
|
17476
|
+
tickMargin: xAxisAngle === 0 ? 8 : 12,
|
|
17477
|
+
height: xAxisAngle !== 0 ? 60 : void 0,
|
|
17478
|
+
tickFormatter: resolvedTickFormatter
|
|
17479
|
+
}
|
|
17480
|
+
) : null,
|
|
17481
|
+
showYAxis ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_recharts3.YAxis, { ...CHART_AXIS_PROPS, width: 40 }) : null,
|
|
17482
|
+
showTooltip ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_recharts3.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ChartTooltipContent, {}) }) : null,
|
|
17483
|
+
resolvedShowLegend ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
17484
|
+
import_recharts3.Legend,
|
|
17485
|
+
{
|
|
17486
|
+
verticalAlign: "top",
|
|
17487
|
+
align: "center",
|
|
17488
|
+
wrapperStyle: { top: 0 },
|
|
17489
|
+
itemSorter: null,
|
|
17490
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ChartLegendContent, { iconType: "line" })
|
|
17491
|
+
}
|
|
17492
|
+
) : null,
|
|
17493
|
+
series.map((s, i) => {
|
|
17494
|
+
const color = colorForSeriesIndex(i, palette);
|
|
17495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
17496
|
+
import_recharts3.Line,
|
|
17497
|
+
{
|
|
17498
|
+
type: lineType,
|
|
17499
|
+
dataKey: s.key,
|
|
17500
|
+
name: s.label,
|
|
17501
|
+
stroke: color,
|
|
17502
|
+
strokeWidth,
|
|
17503
|
+
dot: showDots ? { r: 3, fill: color, stroke: color, strokeWidth: 0 } : false,
|
|
17504
|
+
activeDot: { r: 5, fill: color, stroke: LINE_ACTIVE_DOT_STROKE, strokeWidth: 2 },
|
|
17505
|
+
children: showValueLabels ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_recharts3.LabelList, { dataKey: s.key, position: "top", style: CHART_VALUE_LABEL_STYLE }) : null
|
|
17506
|
+
},
|
|
17507
|
+
s.key
|
|
17508
|
+
);
|
|
17509
|
+
})
|
|
17510
|
+
] }) });
|
|
17511
|
+
}
|
|
17512
|
+
|
|
17513
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/line-chart-variant-component.tsx
|
|
17514
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
17515
|
+
function LineChartVariantComponent({ config, rows }) {
|
|
17516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LineChart, { data: rows, xKey: config.xKey, series: config.series, height: VARIANT_CHART_HEIGHT });
|
|
17517
|
+
}
|
|
17518
|
+
|
|
17519
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/line-chart-variant-service.tsx
|
|
17520
|
+
function isValidLineChartConfig(config) {
|
|
17521
|
+
if (!config || typeof config !== "object") return false;
|
|
17522
|
+
const candidate = config;
|
|
17523
|
+
if (candidate.variant !== "LINE") return false;
|
|
17524
|
+
if (typeof candidate.xKey !== "string" || candidate.xKey.length === 0) return false;
|
|
17525
|
+
if (!Array.isArray(candidate.series) || candidate.series.length === 0) return false;
|
|
17526
|
+
if (!candidate.series.every(isValidChartSeries)) return false;
|
|
17527
|
+
return true;
|
|
17528
|
+
}
|
|
17529
|
+
var LineChartVariantService = {
|
|
17530
|
+
variant: "LINE",
|
|
17531
|
+
isValidConfig: isValidLineChartConfig,
|
|
17532
|
+
columnKeys: seriesBasedColumnKeys,
|
|
17533
|
+
Component: LineChartVariantComponent
|
|
17534
|
+
};
|
|
17535
|
+
|
|
17536
|
+
// src/components/chart/pie-chart/pie-chart.tsx
|
|
17537
|
+
var import_react7 = require("react");
|
|
17538
|
+
var import_recharts4 = require("recharts");
|
|
17539
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
17540
|
+
function PieChart({
|
|
17541
|
+
data: data2,
|
|
17542
|
+
categoryKey,
|
|
17543
|
+
valueKey,
|
|
17544
|
+
height: height2 = 320,
|
|
17545
|
+
width: width2 = "100%",
|
|
17546
|
+
className,
|
|
17547
|
+
palette = CHART_PALETTE,
|
|
17548
|
+
showLabels = true,
|
|
17549
|
+
showTooltip = true,
|
|
17550
|
+
showLegend = true,
|
|
17551
|
+
innerRadius = 0,
|
|
17552
|
+
outerRadius = "68%",
|
|
17553
|
+
othersCategoryLabels = DEFAULT_OTHERS_CATEGORY_LABELS
|
|
17554
|
+
}) {
|
|
17555
|
+
const { orderedData, sliceColors } = (0, import_react7.useMemo)(() => {
|
|
17556
|
+
const coerced = coerceNumericColumns(data2, [valueKey]);
|
|
17557
|
+
const namedRows = [];
|
|
17558
|
+
const namedColors = [];
|
|
17559
|
+
const othersRows = [];
|
|
17560
|
+
const othersColors = [];
|
|
17561
|
+
for (const row of coerced) {
|
|
17562
|
+
if (isOthersCategory(row[categoryKey], othersCategoryLabels)) {
|
|
17563
|
+
othersRows.push(row);
|
|
17564
|
+
othersColors.push(OTHERS_SLICE_COLOR);
|
|
17565
|
+
} else {
|
|
17566
|
+
namedRows.push(row);
|
|
17567
|
+
namedColors.push(colorForSeriesIndex(namedRows.length - 1, palette));
|
|
17568
|
+
}
|
|
17569
|
+
}
|
|
17570
|
+
return {
|
|
17571
|
+
orderedData: [...namedRows, ...othersRows],
|
|
17572
|
+
sliceColors: [...namedColors, ...othersColors]
|
|
17573
|
+
};
|
|
17574
|
+
}, [data2, valueKey, categoryKey, othersCategoryLabels, palette]);
|
|
17575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChartContainer, { height: height2, width: width2, className, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_recharts4.PieChart, { margin: PIE_CHART_MARGIN, children: [
|
|
17576
|
+
showTooltip ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_recharts4.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChartTooltipContent, {}) }) : null,
|
|
17577
|
+
showLegend ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
17578
|
+
import_recharts4.Legend,
|
|
17579
|
+
{
|
|
17580
|
+
verticalAlign: "top",
|
|
17581
|
+
align: "center",
|
|
17582
|
+
wrapperStyle: { top: 0 },
|
|
17583
|
+
itemSorter: null,
|
|
17584
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChartLegendContent, { iconType: "square" })
|
|
17585
|
+
}
|
|
17586
|
+
) : null,
|
|
17587
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
17588
|
+
import_recharts4.Pie,
|
|
17589
|
+
{
|
|
17590
|
+
data: orderedData,
|
|
17591
|
+
dataKey: valueKey,
|
|
17592
|
+
nameKey: categoryKey,
|
|
17593
|
+
cx: "50%",
|
|
17594
|
+
cy: "52%",
|
|
17595
|
+
startAngle: 90,
|
|
17596
|
+
endAngle: -270,
|
|
17597
|
+
innerRadius,
|
|
17598
|
+
outerRadius,
|
|
17599
|
+
label: showLabels ? (entry) => {
|
|
17600
|
+
const v = entry.value;
|
|
17601
|
+
if (v === void 0 || v === null) return null;
|
|
17602
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
17603
|
+
"text",
|
|
17604
|
+
{
|
|
17605
|
+
x: entry.x,
|
|
17606
|
+
y: entry.y,
|
|
17607
|
+
fill: CHART_VALUE_LABEL_STYLE.fill,
|
|
17608
|
+
fontSize: CHART_VALUE_LABEL_STYLE.fontSize,
|
|
17609
|
+
fontWeight: CHART_VALUE_LABEL_STYLE.fontWeight,
|
|
17610
|
+
textAnchor: entry.textAnchor,
|
|
17611
|
+
dominantBaseline: "central",
|
|
17612
|
+
children: String(v)
|
|
17613
|
+
}
|
|
17614
|
+
);
|
|
17615
|
+
} : false,
|
|
17616
|
+
labelLine: false,
|
|
17617
|
+
stroke: "none",
|
|
17618
|
+
strokeWidth: 0,
|
|
17619
|
+
children: orderedData.map((_row, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_recharts4.Cell, { fill: sliceColors[i] }, i))
|
|
17620
|
+
}
|
|
17621
|
+
)
|
|
17622
|
+
] }) });
|
|
17623
|
+
}
|
|
17624
|
+
|
|
17625
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/pie-chart-variant-component.tsx
|
|
17626
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
17627
|
+
function PieChartVariantComponent({
|
|
17628
|
+
config,
|
|
17629
|
+
rows,
|
|
17630
|
+
labels
|
|
17631
|
+
}) {
|
|
17632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
17633
|
+
PieChart,
|
|
17634
|
+
{
|
|
17635
|
+
data: rows,
|
|
17636
|
+
categoryKey: config.categoryKey,
|
|
17637
|
+
valueKey: config.valueKey,
|
|
17638
|
+
othersCategoryLabels: labels.othersCategoryLabels,
|
|
17639
|
+
height: VARIANT_CHART_HEIGHT
|
|
17640
|
+
}
|
|
17641
|
+
);
|
|
17642
|
+
}
|
|
17643
|
+
|
|
17644
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/pie-chart-variant-service.tsx
|
|
17645
|
+
function isValidPieChartConfig(config) {
|
|
17646
|
+
if (!config || typeof config !== "object") return false;
|
|
17647
|
+
const candidate = config;
|
|
17648
|
+
if (candidate.variant !== "PIE") return false;
|
|
17649
|
+
if (typeof candidate.categoryKey !== "string" || candidate.categoryKey.length === 0) return false;
|
|
17650
|
+
if (typeof candidate.valueKey !== "string" || candidate.valueKey.length === 0) return false;
|
|
17651
|
+
if (!Array.isArray(candidate.series)) return false;
|
|
17652
|
+
return true;
|
|
17653
|
+
}
|
|
17654
|
+
var PieChartVariantService = {
|
|
17655
|
+
variant: "PIE",
|
|
17656
|
+
isValidConfig: isValidPieChartConfig,
|
|
17657
|
+
columnKeys: pieColumnKeys,
|
|
17658
|
+
Component: PieChartVariantComponent
|
|
17659
|
+
};
|
|
17660
|
+
|
|
17661
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/index.ts
|
|
17662
|
+
var ChartVariantServices = {
|
|
17663
|
+
LINE: LineChartVariantService,
|
|
17664
|
+
BAR: BarChartVariantService,
|
|
17665
|
+
PIE: PieChartVariantService
|
|
17666
|
+
};
|
|
17667
|
+
|
|
17668
|
+
// src/components/artifacts/chart-artifact/chart-artifact-content.tsx
|
|
17669
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
17670
|
+
function ChartArtifactContent({ config, rows, labels }) {
|
|
17671
|
+
const service = ChartVariantServices[config.variant];
|
|
17672
|
+
if (!service) {
|
|
17673
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
|
|
17674
|
+
}
|
|
17675
|
+
const Component = service.Component;
|
|
17676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Component, { config, rows, labels });
|
|
17677
|
+
}
|
|
17678
|
+
|
|
17679
|
+
// src/components/artifacts/parse-csv.ts
|
|
17680
|
+
var import_papaparse = __toESM(require("papaparse"), 1);
|
|
17681
|
+
function parseCsv(text2, columns) {
|
|
17682
|
+
const result = import_papaparse.default.parse(text2, {
|
|
17683
|
+
header: true,
|
|
17684
|
+
skipEmptyLines: true,
|
|
17685
|
+
dynamicTyping: false
|
|
17686
|
+
});
|
|
17687
|
+
const csvHeaders = new Set(result.meta?.fields ?? []);
|
|
17688
|
+
const presentColumns = columns.filter((col) => csvHeaders.has(col.key));
|
|
17689
|
+
if (presentColumns.length === 0) return [];
|
|
17690
|
+
return result.data.map((rawRow) => {
|
|
17691
|
+
const row = {};
|
|
17692
|
+
for (const column of presentColumns) {
|
|
17693
|
+
const value2 = rawRow[column.key];
|
|
17694
|
+
row[column.key] = value2 === void 0 || value2 === "" ? null : value2;
|
|
17695
|
+
}
|
|
17696
|
+
return row;
|
|
17697
|
+
});
|
|
17698
|
+
}
|
|
17699
|
+
|
|
17700
|
+
// src/components/artifacts/use-rows-artifact-data.ts
|
|
17701
|
+
var import_react8 = require("react");
|
|
17702
|
+
var LOADING = { status: "loading", rows: null, error: null };
|
|
17703
|
+
var UNAVAILABLE = { status: "unavailable", rows: null, error: null };
|
|
17704
|
+
var INITIAL_INTERNAL = { cacheKey: null, data: LOADING };
|
|
17705
|
+
function columnsFingerprint(columns) {
|
|
17706
|
+
return columns.map((c) => c.key).join("|");
|
|
17707
|
+
}
|
|
17708
|
+
function scrubUrl(url) {
|
|
17709
|
+
const q = url.indexOf("?");
|
|
17710
|
+
return q === -1 ? url : `${url.slice(0, q)}?<redacted>`;
|
|
17711
|
+
}
|
|
17712
|
+
function useRowsArtifactData(presignedUrl, columns, parse) {
|
|
17713
|
+
const colsKey = (0, import_react8.useMemo)(() => columnsFingerprint(columns), [columns]);
|
|
17714
|
+
const safeUrl = presignedUrl && isSafeDownloadUrl(presignedUrl) ? presignedUrl : null;
|
|
17715
|
+
const cacheKey = safeUrl ? `${safeUrl}::${colsKey}` : null;
|
|
17716
|
+
const [state, setState] = (0, import_react8.useState)(INITIAL_INTERNAL);
|
|
17717
|
+
(0, import_react8.useEffect)(() => {
|
|
17718
|
+
if (!safeUrl) return;
|
|
17719
|
+
const controller = new AbortController();
|
|
17720
|
+
fetch(safeUrl, {
|
|
17721
|
+
signal: controller.signal,
|
|
17722
|
+
headers: { Accept: "text/csv" },
|
|
17723
|
+
// Presigned URLs are cross-origin S3 in production and don't need credentials. Explicit
|
|
17724
|
+
// omit so a same-origin URL (compromised payload, local dev) can't accidentally receive
|
|
17725
|
+
// session cookies or auth headers.
|
|
17726
|
+
credentials: "omit"
|
|
17727
|
+
}).then(async (response) => {
|
|
17728
|
+
if (!response.ok) throw new Error(`Failed to load artifact data (${response.status})`);
|
|
17729
|
+
return response.text();
|
|
17730
|
+
}).then((text2) => {
|
|
17731
|
+
if (controller.signal.aborted) return;
|
|
17732
|
+
try {
|
|
17733
|
+
const rows = parse(text2, columns);
|
|
17734
|
+
setState({ cacheKey: `${safeUrl}::${colsKey}`, data: { status: "ready", rows, error: null } });
|
|
17735
|
+
} catch (parseError) {
|
|
17736
|
+
const err = parseError instanceof Error ? parseError : new Error(String(parseError));
|
|
17737
|
+
console.error("[ArtifactData] CSV parse failed:", err.message);
|
|
17738
|
+
setState({ cacheKey: `${safeUrl}::${colsKey}`, data: { status: "error", rows: null, error: err } });
|
|
17739
|
+
}
|
|
17740
|
+
}).catch((error) => {
|
|
17741
|
+
if (controller.signal.aborted) return;
|
|
17742
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
17743
|
+
console.error(`[ArtifactData] Fetch failed [${scrubUrl(safeUrl)}]:`, err.message);
|
|
17744
|
+
setState({ cacheKey: `${safeUrl}::${colsKey}`, data: { status: "error", rows: null, error: err } });
|
|
17745
|
+
});
|
|
17746
|
+
return () => {
|
|
17747
|
+
controller.abort();
|
|
17748
|
+
};
|
|
17749
|
+
}, [safeUrl, colsKey]);
|
|
17750
|
+
if (!safeUrl) return UNAVAILABLE;
|
|
17751
|
+
if (state.cacheKey !== cacheKey) return LOADING;
|
|
17752
|
+
return state.data;
|
|
17753
|
+
}
|
|
17754
|
+
|
|
17755
|
+
// src/components/artifacts/chart-artifact/use-chart-artifact-data.ts
|
|
17756
|
+
function useChartArtifactData(presignedUrl, config) {
|
|
17757
|
+
const service = ChartVariantServices[config.variant];
|
|
17758
|
+
const keys = service ? service.columnKeys(config) : [];
|
|
17759
|
+
const columns = keys.map((key2) => ({ key: key2 }));
|
|
17760
|
+
return useRowsArtifactData(presignedUrl, columns, parseCsv);
|
|
17761
|
+
}
|
|
17762
|
+
|
|
17763
|
+
// src/components/artifacts/chart-artifact/validate.ts
|
|
17764
|
+
function isValidChartConfig(config) {
|
|
17765
|
+
if (!config || typeof config !== "object") return false;
|
|
17766
|
+
const variant = config.variant;
|
|
17767
|
+
if (typeof variant !== "string") return false;
|
|
17768
|
+
const service = ChartVariantServices[variant];
|
|
17769
|
+
if (!service) return false;
|
|
17770
|
+
return service.isValidConfig(config);
|
|
17771
|
+
}
|
|
17772
|
+
|
|
17773
|
+
// src/components/artifacts/chart-artifact/chart-artifact.tsx
|
|
17774
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
17775
|
+
var TITLE_CLASSES = "text-sm font-semibold text-foreground";
|
|
17776
|
+
var CHART_HEIGHT = 320;
|
|
17777
|
+
function ChartArtifact({ artifact, labels, callbacks }) {
|
|
17778
|
+
const validConfig = isValidChartConfig(artifact.config);
|
|
17779
|
+
(0, import_react9.useEffect)(() => {
|
|
17780
|
+
if (validConfig) return;
|
|
17781
|
+
console.warn("[clay] ChartArtifact: malformed `config` \u2014 skipping render.");
|
|
17782
|
+
}, [validConfig]);
|
|
17783
|
+
const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
|
|
17784
|
+
const resolvedLabels = (0, import_react9.useMemo)(
|
|
17785
|
+
() => ({ ...DEFAULT_CHART_ARTIFACT_LABELS, ...labels?.[artifactTypes.CHART] ?? {} }),
|
|
17786
|
+
[labels]
|
|
17787
|
+
);
|
|
17788
|
+
const data2 = useChartArtifactData(
|
|
17789
|
+
validConfig ? presignedUrl : null,
|
|
17790
|
+
validConfig ? artifact.config : { variant: "LINE", series: [], xKey: "x" }
|
|
17791
|
+
);
|
|
17792
|
+
const onDownload = callbacks?.[artifactTypes.CHART]?.onDownload;
|
|
17793
|
+
const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
|
|
17794
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
17795
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
|
|
17796
|
+
artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ArtifactTitle, { className: TITLE_CLASSES, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", {}),
|
|
17797
|
+
presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ArtifactDownloadButton, { href: presignedUrl, label: resolvedLabels.download, onClick: handleDownloadClick }) }) : null
|
|
17798
|
+
] }),
|
|
17799
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
17800
|
+
ArtifactContent,
|
|
17801
|
+
{
|
|
17802
|
+
className: "p-4 overflow-visible flex flex-none items-center justify-center",
|
|
17803
|
+
style: { height: CHART_HEIGHT },
|
|
17804
|
+
children: renderBody(validConfig, artifact, data2, resolvedLabels)
|
|
17805
|
+
}
|
|
17806
|
+
)
|
|
17807
|
+
] });
|
|
17808
|
+
}
|
|
17809
|
+
function renderBody(validConfig, artifact, data2, labels) {
|
|
17810
|
+
if (!validConfig) {
|
|
17811
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
|
|
17812
|
+
}
|
|
17813
|
+
if (data2.status === "error") {
|
|
17814
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StatusMessage, { $tone: "error", children: labels.loadError });
|
|
17815
|
+
}
|
|
17816
|
+
if (data2.status === "unavailable") {
|
|
17817
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
|
|
17818
|
+
}
|
|
17819
|
+
if (data2.status === "loading") {
|
|
17820
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StatusMessage, { $tone: "info", children: labels.loading });
|
|
17821
|
+
}
|
|
17822
|
+
if (data2.rows.length === 0) {
|
|
17823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StatusMessage, { $tone: "info", children: labels.empty });
|
|
17824
|
+
}
|
|
17825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ChartArtifactContent, { config: artifact.config, rows: data2.rows, labels });
|
|
17826
|
+
}
|
|
17827
|
+
|
|
17828
|
+
// src/components/artifacts/chart-artifact/to-clipboard-text.ts
|
|
17829
|
+
function chartArtifactToClipboardText(artifact) {
|
|
17830
|
+
const trimmedTitle = artifact.title?.trim();
|
|
17831
|
+
return trimmedTitle || "Chart";
|
|
17832
|
+
}
|
|
17833
|
+
|
|
17834
|
+
// src/components/artifacts/artifact-services/chart-artifact-service.ts
|
|
17835
|
+
var ChartArtifactService = {
|
|
17836
|
+
type: artifactTypes.CHART,
|
|
17837
|
+
Component: ChartArtifact,
|
|
17838
|
+
toClipboardText: chartArtifactToClipboardText
|
|
17839
|
+
};
|
|
17840
|
+
|
|
17841
|
+
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
17842
|
+
var import_react11 = require("react");
|
|
17843
|
+
|
|
17844
|
+
// src/components/ui/table.tsx
|
|
17845
|
+
var React2 = __toESM(require("react"), 1);
|
|
17846
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
17847
|
+
var Table = React2.forwardRef(({ className, containerClassName, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: cn("relative w-full overflow-auto", containerClassName), children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("table", { ref, className: cn("w-full caption-bottom text-sm", className), ...props }) }));
|
|
17848
|
+
Table.displayName = "Table";
|
|
17849
|
+
var TableHeader = React2.forwardRef(
|
|
17850
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("thead", { ref, className: cn("[&_tr]:border-b", className), ...props })
|
|
17851
|
+
);
|
|
17852
|
+
TableHeader.displayName = "TableHeader";
|
|
17853
|
+
var TableBody = React2.forwardRef(
|
|
17854
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props })
|
|
17855
|
+
);
|
|
17856
|
+
TableBody.displayName = "TableBody";
|
|
17857
|
+
var TableFooter = React2.forwardRef(
|
|
17858
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("tfoot", { ref, className: cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className), ...props })
|
|
17859
|
+
);
|
|
17860
|
+
TableFooter.displayName = "TableFooter";
|
|
17861
|
+
var TableRow = React2.forwardRef(
|
|
17862
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
17863
|
+
"tr",
|
|
17864
|
+
{
|
|
17865
|
+
ref,
|
|
17866
|
+
className: cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className),
|
|
17867
|
+
...props
|
|
17868
|
+
}
|
|
17869
|
+
)
|
|
17870
|
+
);
|
|
17871
|
+
TableRow.displayName = "TableRow";
|
|
17872
|
+
var TableHead = React2.forwardRef(
|
|
17873
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
17874
|
+
"th",
|
|
17875
|
+
{
|
|
17876
|
+
ref,
|
|
17877
|
+
className: cn(
|
|
17878
|
+
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
|
17879
|
+
className
|
|
17880
|
+
),
|
|
17881
|
+
...props
|
|
17882
|
+
}
|
|
17883
|
+
)
|
|
17884
|
+
);
|
|
17885
|
+
TableHead.displayName = "TableHead";
|
|
17886
|
+
var TableCell = React2.forwardRef(
|
|
17887
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("td", { ref, className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className), ...props })
|
|
17888
|
+
);
|
|
17889
|
+
TableCell.displayName = "TableCell";
|
|
17890
|
+
var TableCaption = React2.forwardRef(
|
|
17891
|
+
({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("caption", { ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props })
|
|
17892
|
+
);
|
|
17893
|
+
TableCaption.displayName = "TableCaption";
|
|
17894
|
+
|
|
17895
|
+
// src/components/table/use-scroll-shadow.ts
|
|
17896
|
+
var import_react10 = require("react");
|
|
17897
|
+
function useScrollShadow() {
|
|
17898
|
+
const targetRef = (0, import_react10.useRef)(null);
|
|
17899
|
+
const [isScrolled, setIsScrolled] = (0, import_react10.useState)(false);
|
|
17900
|
+
(0, import_react10.useEffect)(() => {
|
|
17901
|
+
const target = targetRef.current;
|
|
17902
|
+
if (!target) return;
|
|
17903
|
+
let scrollContainer = target;
|
|
17904
|
+
while (scrollContainer) {
|
|
17905
|
+
const overflowY = getComputedStyle(scrollContainer).overflowY;
|
|
17906
|
+
if (overflowY === "auto" || overflowY === "scroll") break;
|
|
17907
|
+
scrollContainer = scrollContainer.parentElement;
|
|
17908
|
+
}
|
|
17909
|
+
if (!scrollContainer) return;
|
|
17910
|
+
setIsScrolled(scrollContainer.scrollTop > 0);
|
|
17911
|
+
const handleScroll = () => {
|
|
17912
|
+
if (!scrollContainer) return;
|
|
17913
|
+
setIsScrolled(scrollContainer.scrollTop > 0);
|
|
17914
|
+
};
|
|
17915
|
+
scrollContainer.addEventListener("scroll", handleScroll, { passive: true });
|
|
17916
|
+
return () => scrollContainer.removeEventListener("scroll", handleScroll);
|
|
17917
|
+
}, []);
|
|
17918
|
+
return { targetRef, isScrolled };
|
|
17919
|
+
}
|
|
17920
|
+
|
|
17921
|
+
// src/components/artifacts/table-artifact/table-artifact-content.constants.ts
|
|
17922
|
+
var TABLE_STATUS = {
|
|
17923
|
+
LOADING: "loading",
|
|
17924
|
+
READY: "ready",
|
|
17925
|
+
ERROR: "error",
|
|
17926
|
+
UNAVAILABLE: "unavailable"
|
|
17927
|
+
};
|
|
17928
|
+
|
|
17929
|
+
// src/components/artifacts/table-artifact/table-artifact-content.utils.ts
|
|
17930
|
+
function formatCell(row, column) {
|
|
17931
|
+
return row[column.key] ?? "";
|
|
17932
|
+
}
|
|
17933
|
+
var HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
|
|
17934
|
+
var CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
|
|
17935
|
+
var ROW_CLASSES = "border-b-brown-30 bg-background/70 hover:bg-secondary";
|
|
17936
|
+
var DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;
|
|
17937
|
+
var SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
|
|
17938
|
+
|
|
17939
|
+
// src/components/artifacts/table-artifact/table-artifact-content.tsx
|
|
17940
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
17941
|
+
function TableArtifactContent({
|
|
17942
|
+
columns,
|
|
17943
|
+
data: data2,
|
|
17944
|
+
knownRowCount,
|
|
17945
|
+
maxShimmerRows,
|
|
17946
|
+
maxBodyHeight,
|
|
17947
|
+
labels
|
|
17948
|
+
}) {
|
|
17949
|
+
if (data2.status === TABLE_STATUS.ERROR) {
|
|
17950
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StatusMessage, { $tone: "error", children: labels.loadError });
|
|
17951
|
+
}
|
|
17952
|
+
if (data2.status === TABLE_STATUS.UNAVAILABLE) {
|
|
17953
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StatusMessage, { $tone: "info", children: labels.unavailable });
|
|
17954
|
+
}
|
|
17955
|
+
if (data2.status === TABLE_STATUS.LOADING) {
|
|
17956
|
+
if (typeof knownRowCount === "number" && knownRowCount > 0) {
|
|
17957
|
+
const shimmerCount = Math.min(knownRowCount, maxShimmerRows);
|
|
17958
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
|
|
17959
|
+
}
|
|
17960
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StatusMessage, { $tone: "info", children: labels.loading });
|
|
17961
|
+
}
|
|
17962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ArtifactTable, { columns, maxBodyHeight, children: data2.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data2.rows) });
|
|
17963
|
+
}
|
|
17964
|
+
function ArtifactTable({ columns, maxBodyHeight, children }) {
|
|
17965
|
+
const { targetRef, isScrolled } = useScrollShadow();
|
|
17966
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { ref: targetRef, className: "overscroll-none", style: { maxHeight: maxBodyHeight, overflowY: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Table, { containerClassName: "overflow-visible", children: [
|
|
17967
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
17968
|
+
TableHeader,
|
|
17969
|
+
{
|
|
17970
|
+
"data-scrolled": isScrolled ? "true" : void 0,
|
|
17971
|
+
className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
|
|
17972
|
+
style: isScrolled ? { boxShadow: SCROLL_SHADOW } : void 0,
|
|
17973
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TableRow, { className: "hover:bg-transparent", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TableHead, { scope: "col", className: HEAD_CLASS, children: column.label }, column.key)) })
|
|
17974
|
+
}
|
|
17975
|
+
),
|
|
17976
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TableBody, { children })
|
|
17977
|
+
] }) });
|
|
17978
|
+
}
|
|
17979
|
+
function renderShimmerRows(columns, count) {
|
|
17980
|
+
return Array.from({ length: count }).map((_, index2) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TableRow, { className: ROW_CLASSES, "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TableCell, { className: CELL_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20" }) }, column.key)) }, `shimmer-${index2}`));
|
|
17981
|
+
}
|
|
17982
|
+
function renderDataRows(columns, rows) {
|
|
17983
|
+
return rows.map((row, index2) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TableRow, { className: DATA_ROW_CLASSES, children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TableCell, { className: CELL_CLASS, children: formatCell(row, column) }, column.key)) }, index2));
|
|
17984
|
+
}
|
|
17985
|
+
function renderEmptyRow(colSpan, emptyMessage) {
|
|
17986
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TableCell, { colSpan, className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) });
|
|
17987
|
+
}
|
|
17988
|
+
|
|
17989
|
+
// src/components/artifacts/table-artifact/use-table-artifact-data.ts
|
|
17990
|
+
function useTableArtifactData(presignedUrl, columns) {
|
|
17991
|
+
return useRowsArtifactData(presignedUrl, columns, parseCsv);
|
|
17992
|
+
}
|
|
17993
|
+
|
|
17994
|
+
// src/components/artifacts/table-artifact/validate.ts
|
|
17995
|
+
function isValidTableConfig(config) {
|
|
17996
|
+
if (!config || typeof config !== "object") return false;
|
|
17997
|
+
const candidate = config;
|
|
17998
|
+
if (!Array.isArray(candidate.columns)) return false;
|
|
17999
|
+
if (candidate.columns.length === 0) return false;
|
|
18000
|
+
return candidate.columns.every(isValidTableColumn);
|
|
18001
|
+
}
|
|
18002
|
+
function isValidTableColumn(column) {
|
|
18003
|
+
if (!column || typeof column !== "object") return false;
|
|
18004
|
+
const candidate = column;
|
|
18005
|
+
if (typeof candidate.key !== "string" || candidate.key.length === 0) return false;
|
|
18006
|
+
if (typeof candidate.label !== "string") return false;
|
|
18007
|
+
return true;
|
|
18008
|
+
}
|
|
18009
|
+
|
|
18010
|
+
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
18011
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
18012
|
+
var TITLE_CLASSES2 = "text-sm font-semibold text-foreground";
|
|
18013
|
+
var TABLE_MAX_BODY_HEIGHT = 480;
|
|
18014
|
+
var MAX_SHIMMER_ROWS = 10;
|
|
18015
|
+
function TableArtifact({ artifact, labels, callbacks }) {
|
|
18016
|
+
const validConfig = isValidTableConfig(artifact.config);
|
|
18017
|
+
const validColumns = validConfig ? artifact.config.columns : null;
|
|
18018
|
+
(0, import_react11.useEffect)(() => {
|
|
18019
|
+
if (validConfig) return;
|
|
18020
|
+
console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
|
|
18021
|
+
}, [validConfig]);
|
|
18022
|
+
const resolvedLabels = (0, import_react11.useMemo)(
|
|
18023
|
+
() => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels?.[artifactTypes.TABLE] ?? {} }),
|
|
18024
|
+
[labels]
|
|
18025
|
+
);
|
|
18026
|
+
const data2 = useTableArtifactData(
|
|
18027
|
+
validConfig ? artifact.protectedAsset?.presignedUrl ?? null : null,
|
|
18028
|
+
validColumns ?? []
|
|
18029
|
+
);
|
|
18030
|
+
const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
|
|
18031
|
+
const onDownload = callbacks?.[artifactTypes.TABLE]?.onDownload;
|
|
18032
|
+
const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
|
|
18033
|
+
if (!validConfig || !validColumns) {
|
|
18034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
18035
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
|
|
18036
|
+
artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", {}),
|
|
18037
|
+
presignedUrl ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18038
|
+
ArtifactDownloadButton,
|
|
18039
|
+
{
|
|
18040
|
+
href: presignedUrl,
|
|
18041
|
+
label: resolvedLabels.download,
|
|
18042
|
+
onClick: handleDownloadClick
|
|
18043
|
+
}
|
|
18044
|
+
) }) : null
|
|
18045
|
+
] }),
|
|
18046
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
|
|
18047
|
+
] });
|
|
18048
|
+
}
|
|
18049
|
+
return (
|
|
18050
|
+
// The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
|
|
18051
|
+
// Disable the outer overflow container so only one scroll context exists — this prevents
|
|
18052
|
+
// double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
|
|
18053
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
18054
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(ArtifactHeader, { className: "bg-background/70", children: [
|
|
18055
|
+
artifact.title ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", {}),
|
|
18056
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactActions, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18057
|
+
ArtifactDownloadButton,
|
|
18058
|
+
{
|
|
18059
|
+
href: presignedUrl ?? "",
|
|
18060
|
+
label: resolvedLabels.download,
|
|
18061
|
+
onClick: handleDownloadClick
|
|
18062
|
+
}
|
|
18063
|
+
) })
|
|
18064
|
+
] }),
|
|
18065
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18066
|
+
TableArtifactContent,
|
|
18067
|
+
{
|
|
18068
|
+
columns: validColumns,
|
|
18069
|
+
data: data2,
|
|
18070
|
+
knownRowCount: artifact.config.stats?.rowCount,
|
|
18071
|
+
maxShimmerRows: MAX_SHIMMER_ROWS,
|
|
18072
|
+
maxBodyHeight: TABLE_MAX_BODY_HEIGHT,
|
|
18073
|
+
labels: resolvedLabels
|
|
18074
|
+
}
|
|
18075
|
+
) })
|
|
18076
|
+
] })
|
|
18077
|
+
);
|
|
18078
|
+
}
|
|
18079
|
+
|
|
18080
|
+
// src/components/artifacts/table-artifact/to-clipboard-text.ts
|
|
18081
|
+
function tableArtifactToClipboardText(artifact) {
|
|
18082
|
+
const trimmedTitle = artifact.title?.trim();
|
|
18083
|
+
return trimmedTitle || "Table";
|
|
18084
|
+
}
|
|
18085
|
+
|
|
18086
|
+
// src/components/artifacts/artifact-services/table-artifact-service.ts
|
|
18087
|
+
var TableArtifactService = {
|
|
18088
|
+
type: artifactTypes.TABLE,
|
|
18089
|
+
Component: TableArtifact,
|
|
18090
|
+
toClipboardText: tableArtifactToClipboardText
|
|
18091
|
+
};
|
|
18092
|
+
|
|
18093
|
+
// src/components/artifacts/artifact-services/index.ts
|
|
18094
|
+
var ArtifactServices = {
|
|
18095
|
+
[artifactTypes.TABLE]: TableArtifactService,
|
|
18096
|
+
[artifactTypes.CHART]: ChartArtifactService
|
|
18097
|
+
};
|
|
18098
|
+
function artifactToClipboardText(artifact) {
|
|
18099
|
+
const entry = ArtifactServices[artifact.type];
|
|
18100
|
+
if (!entry) {
|
|
18101
|
+
return `[Artifact: ${artifact.title ?? artifact.type}]`;
|
|
18102
|
+
}
|
|
18103
|
+
return entry.toClipboardText(artifact);
|
|
18104
|
+
}
|
|
18105
|
+
|
|
18106
|
+
// src/components/blocks/artifact-ref-block/artifact-ref-block.tsx
|
|
18107
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18108
|
+
function ArtifactRefBlock({ block }) {
|
|
18109
|
+
const { artifact, labels, callbacks } = block.payload;
|
|
18110
|
+
const entry = ArtifactServices[artifact.type];
|
|
18111
|
+
if (!entry) return null;
|
|
18112
|
+
const { Component } = entry;
|
|
18113
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Component, { artifact, labels, callbacks });
|
|
18114
|
+
}
|
|
18115
|
+
|
|
18116
|
+
// src/components/blocks/block-services/artifact-ref-block-service.ts
|
|
18117
|
+
var ArtifactRefBlockService = {
|
|
18118
|
+
type: blockTypes.ARTIFACT_REF,
|
|
18119
|
+
Component: ArtifactRefBlock,
|
|
18120
|
+
/**
|
|
18121
|
+
* Delegates to the registered artifact component's `toClipboardText`. Falls back to
|
|
18122
|
+
* `[Artifact: <title>]` via `artifactToClipboardText`'s own fallback when the artifact type
|
|
18123
|
+
* has no registered component, so copy never silently produces an empty string.
|
|
18124
|
+
*/
|
|
18125
|
+
toClipboardText: (block) => artifactToClipboardText(block.payload.artifact)
|
|
18126
|
+
};
|
|
18127
|
+
|
|
18128
|
+
// src/utils/markdown-to-plain-text.ts
|
|
18129
|
+
var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
|
|
18130
|
+
var PLACEHOLDER_SUFFIX = "\u200B\u200B";
|
|
18131
|
+
var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
|
|
18132
|
+
function stripInlineMarks(text2) {
|
|
18133
|
+
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");
|
|
18134
|
+
}
|
|
18135
|
+
function markdownToPlainText(markdown) {
|
|
18136
|
+
if (!markdown) return "";
|
|
18137
|
+
const inlineCodeSnippets = [];
|
|
18138
|
+
let result = markdown.replace(/^<!--[\s\S]*?--!?>\n?/gm, "").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
|
|
18139
|
+
inlineCodeSnippets.push(code);
|
|
18140
|
+
return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
|
|
18141
|
+
}).replace(/^#{1,6}\s+/gm, "").replace(/^(?:---|\*\*\*|___)\s*$/gm, "");
|
|
18142
|
+
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();
|
|
18143
|
+
result = result.replace(PLACEHOLDER_REGEX, (_match, index2) => inlineCodeSnippets[Number(index2)]);
|
|
18144
|
+
return result;
|
|
18145
|
+
}
|
|
18146
|
+
|
|
16763
18147
|
// src/components/blocks/text-block/text-block.tsx
|
|
16764
18148
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
16765
18149
|
var import_remark_breaks = __toESM(require("remark-breaks"), 1);
|
|
16766
18150
|
var import_remark_gfm = __toESM(require("remark-gfm"), 1);
|
|
16767
18151
|
|
|
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
18152
|
// src/components/blocks/scrollable-table/scrollable-table-styles.ts
|
|
16776
|
-
var
|
|
16777
|
-
var TableContainer =
|
|
18153
|
+
var import_styled_components3 = __toESM(require("styled-components"), 1);
|
|
18154
|
+
var TableContainer = import_styled_components3.default.div`
|
|
16778
18155
|
position: relative;
|
|
16779
18156
|
margin-block: 8px 16px;
|
|
16780
18157
|
`;
|
|
16781
|
-
var TableScroll =
|
|
18158
|
+
var TableScroll = import_styled_components3.default.div`
|
|
16782
18159
|
width: 100%;
|
|
16783
18160
|
overflow-x: auto;
|
|
16784
18161
|
overflow-y: hidden;
|
|
16785
18162
|
`;
|
|
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
18163
|
|
|
16797
18164
|
// 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
|
-
] });
|
|
18165
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
18166
|
+
function ScrollableTable({ node: _node, ...props }) {
|
|
18167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("table", { ...props }) }) });
|
|
16812
18168
|
}
|
|
16813
18169
|
|
|
16814
18170
|
// src/components/blocks/text-block/sanitize.ts
|
|
@@ -16820,8 +18176,8 @@ function sanitize(text2) {
|
|
|
16820
18176
|
}
|
|
16821
18177
|
|
|
16822
18178
|
// src/components/blocks/text-block/text-block-styles.ts
|
|
16823
|
-
var
|
|
16824
|
-
var TextBlockWrapper =
|
|
18179
|
+
var import_styled_components4 = __toESM(require("styled-components"), 1);
|
|
18180
|
+
var TextBlockWrapper = import_styled_components4.default.div`
|
|
16825
18181
|
${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
|
|
16826
18182
|
color: ${colors["brown-100"]};
|
|
16827
18183
|
word-break: break-word;
|
|
@@ -16939,251 +18295,81 @@ var TextBlockWrapper = import_styled_components2.default.div`
|
|
|
16939
18295
|
`;
|
|
16940
18296
|
|
|
16941
18297
|
// src/components/blocks/text-block/text-block.tsx
|
|
16942
|
-
var
|
|
18298
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
18299
|
+
var markdownComponents = {
|
|
18300
|
+
table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ScrollableTable, { ...tableProps }))
|
|
18301
|
+
};
|
|
16943
18302
|
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) }) });
|
|
18303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TextBlockWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: markdownComponents, children: sanitize(block.payload.text) }) });
|
|
16949
18304
|
}
|
|
16950
18305
|
|
|
16951
|
-
// src/components/blocks/types.ts
|
|
16952
|
-
var blockTypes = {
|
|
16953
|
-
TEXT: "TEXT"
|
|
16954
|
-
};
|
|
16955
|
-
|
|
16956
18306
|
// src/components/blocks/block-services/text-block-service.ts
|
|
16957
18307
|
var TextBlockService = {
|
|
16958
18308
|
type: blockTypes.TEXT,
|
|
16959
|
-
Component: TextBlock
|
|
18309
|
+
Component: TextBlock,
|
|
18310
|
+
/**
|
|
18311
|
+
* Converts the block's markdown source to plain text so the final clipboard value is clean
|
|
18312
|
+
* when pasted into tools that don't render markdown. Each block type owns its own clipboard
|
|
18313
|
+
* conversion so `useCopyToClipboard` can write text verbatim without a second pass.
|
|
18314
|
+
*/
|
|
18315
|
+
toClipboardText: (block) => markdownToPlainText(block.payload.text)
|
|
16960
18316
|
};
|
|
16961
18317
|
|
|
16962
18318
|
// src/components/blocks/block-services/index.ts
|
|
16963
18319
|
var BlockServices = {
|
|
16964
|
-
[
|
|
18320
|
+
[blockTypes.TEXT]: TextBlockService,
|
|
18321
|
+
[blockTypes.ARTIFACT_REF]: ArtifactRefBlockService
|
|
16965
18322
|
};
|
|
16966
18323
|
|
|
16967
18324
|
// src/components/blocks/block/block.tsx
|
|
16968
|
-
var
|
|
18325
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
16969
18326
|
function Block({ block }) {
|
|
16970
18327
|
const service = BlockServices[block.type];
|
|
16971
18328
|
if (!service) return null;
|
|
16972
18329
|
const { Component } = service;
|
|
16973
|
-
return /* @__PURE__ */ (0,
|
|
18330
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Component, { block });
|
|
16974
18331
|
}
|
|
16975
18332
|
|
|
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;
|
|
18333
|
+
// src/components/blocks/block-context/block-context.tsx
|
|
18334
|
+
var import_react12 = require("react");
|
|
18335
|
+
var BlockContext = (0, import_react12.createContext)(null);
|
|
18336
|
+
function useBlockContext() {
|
|
18337
|
+
return (0, import_react12.useContext)(BlockContext) ?? {};
|
|
16988
18338
|
}
|
|
16989
18339
|
|
|
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");
|
|
18340
|
+
// src/components/chat/chat-message/chat-message.tsx
|
|
18341
|
+
var import_react16 = require("react");
|
|
16995
18342
|
|
|
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"
|
|
18343
|
+
// src/components/chat/hooks/copy-message-text.ts
|
|
18344
|
+
function copyMessageText(message) {
|
|
18345
|
+
const parts = [];
|
|
18346
|
+
for (const block of message.blocks) {
|
|
18347
|
+
const service = BlockServices[block.type];
|
|
18348
|
+
if (!service) continue;
|
|
18349
|
+
if (!service.toClipboardText) continue;
|
|
18350
|
+
const text2 = service.toClipboardText(block);
|
|
18351
|
+
if (text2) parts.push(text2);
|
|
17016
18352
|
}
|
|
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;
|
|
18353
|
+
if (parts.length === 0) return message.fallbackText;
|
|
18354
|
+
return parts.join("\n\n");
|
|
17081
18355
|
}
|
|
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
18356
|
|
|
17139
|
-
|
|
17140
|
-
|
|
17141
|
-
}
|
|
18357
|
+
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
18358
|
+
var import_react15 = require("react");
|
|
17142
18359
|
|
|
17143
|
-
|
|
17144
|
-
|
|
17145
|
-
|
|
17146
|
-
|
|
18360
|
+
// src/components/chat/chat-context/chat-context.ts
|
|
18361
|
+
var import_react13 = require("react");
|
|
18362
|
+
var ChatContext = (0, import_react13.createContext)(null);
|
|
18363
|
+
function useChatContext() {
|
|
18364
|
+
const context = (0, import_react13.useContext)(ChatContext);
|
|
18365
|
+
if (!context) {
|
|
18366
|
+
throw new Error("useChatContext must be used within a Chat.Root component");
|
|
17147
18367
|
}
|
|
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
|
-
);
|
|
18368
|
+
return context;
|
|
17183
18369
|
}
|
|
17184
18370
|
|
|
17185
18371
|
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
17186
|
-
var
|
|
18372
|
+
var import_react14 = require("react");
|
|
17187
18373
|
|
|
17188
18374
|
// src/utils/clipboard.ts
|
|
17189
18375
|
function copyToClipboard(text2, options) {
|
|
@@ -17193,37 +18379,18 @@ function copyToClipboard(text2, options) {
|
|
|
17193
18379
|
);
|
|
17194
18380
|
}
|
|
17195
18381
|
|
|
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
18382
|
// src/components/chat/hooks/use-copy-to-clipboard.ts
|
|
17216
18383
|
var RESET_DELAY_MS = 2e3;
|
|
17217
18384
|
function useCopyToClipboard() {
|
|
17218
|
-
const [isCopied, setIsCopied] = (0,
|
|
17219
|
-
const timeoutRef = (0,
|
|
17220
|
-
(0,
|
|
18385
|
+
const [isCopied, setIsCopied] = (0, import_react14.useState)(false);
|
|
18386
|
+
const timeoutRef = (0, import_react14.useRef)(null);
|
|
18387
|
+
(0, import_react14.useEffect)(() => {
|
|
17221
18388
|
return () => {
|
|
17222
18389
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
17223
18390
|
};
|
|
17224
18391
|
}, []);
|
|
17225
|
-
const copy = (0,
|
|
17226
|
-
copyToClipboard(
|
|
18392
|
+
const copy = (0, import_react14.useCallback)((text2) => {
|
|
18393
|
+
copyToClipboard(text2, {
|
|
17227
18394
|
onSuccess: () => {
|
|
17228
18395
|
setIsCopied(true);
|
|
17229
18396
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
@@ -17262,24 +18429,24 @@ var AnimatedAction = import_styled_components5.default.div`
|
|
|
17262
18429
|
`;
|
|
17263
18430
|
|
|
17264
18431
|
// src/components/chat/chat-message-actions/chat-message-actions.tsx
|
|
17265
|
-
var
|
|
18432
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
17266
18433
|
function ChatMessageActions({ className, messageId, content: content2, role, isHelpful }) {
|
|
17267
18434
|
const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
|
|
17268
18435
|
const { isCopied, copy } = useCopyToClipboard();
|
|
17269
|
-
const handleCopy = (0,
|
|
18436
|
+
const handleCopy = (0, import_react15.useCallback)(() => {
|
|
17270
18437
|
copy(content2);
|
|
17271
18438
|
onCopyMessage?.(messageId);
|
|
17272
18439
|
}, [content2, messageId, copy, onCopyMessage]);
|
|
17273
|
-
const handleThumbUp = (0,
|
|
18440
|
+
const handleThumbUp = (0, import_react15.useCallback)(() => {
|
|
17274
18441
|
onThumbUpClick?.(messageId, isHelpful === true ? null : true);
|
|
17275
18442
|
}, [messageId, isHelpful, onThumbUpClick]);
|
|
17276
|
-
const handleThumbDown = (0,
|
|
18443
|
+
const handleThumbDown = (0, import_react15.useCallback)(() => {
|
|
17277
18444
|
onThumbDownClick?.(messageId, isHelpful === false ? null : false);
|
|
17278
18445
|
}, [messageId, isHelpful, onThumbDownClick]);
|
|
17279
18446
|
const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
|
|
17280
18447
|
const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
|
|
17281
|
-
return /* @__PURE__ */ (0,
|
|
17282
|
-
/* @__PURE__ */ (0,
|
|
18448
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(ActionsContainer, { $role: role, className, children: [
|
|
18449
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
17283
18450
|
IconButton,
|
|
17284
18451
|
{
|
|
17285
18452
|
icon: isCopied ? IconCheck : IconCopy,
|
|
@@ -17287,7 +18454,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
|
|
|
17287
18454
|
"aria-label": isCopied ? "Copied" : "Copy message"
|
|
17288
18455
|
}
|
|
17289
18456
|
),
|
|
17290
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
18457
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
17291
18458
|
IconButton,
|
|
17292
18459
|
{
|
|
17293
18460
|
icon: IconThumbUp,
|
|
@@ -17296,7 +18463,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
|
|
|
17296
18463
|
"aria-label": "Good response"
|
|
17297
18464
|
}
|
|
17298
18465
|
) }),
|
|
17299
|
-
hasFeedback && /* @__PURE__ */ (0,
|
|
18466
|
+
hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
17300
18467
|
IconButton,
|
|
17301
18468
|
{
|
|
17302
18469
|
icon: IconThumbDown,
|
|
@@ -17334,26 +18501,28 @@ var MessageBubble = import_styled_components6.default.div`
|
|
|
17334
18501
|
padding: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "12px 16px" : "0"};
|
|
17335
18502
|
border-radius: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "16px" : "0"};
|
|
17336
18503
|
max-width: 100%;
|
|
18504
|
+
width: 100%;
|
|
17337
18505
|
min-width: 0;
|
|
18506
|
+
/* Vertical rhythm between consecutive blocks — renderer-owned, not agent-emitted.
|
|
18507
|
+
* Industry standard (Claude, ChatGPT, Vercel AI Elements): the chat renderer applies
|
|
18508
|
+
* spacing via CSS; agents emit semantic blocks only. Value matches the MessageContainer
|
|
18509
|
+
* gap. TODO: replace 12px with a clay spacing token when a spacing scale is added. */
|
|
18510
|
+
display: flex;
|
|
18511
|
+
flex-direction: column;
|
|
18512
|
+
gap: 12px;
|
|
17338
18513
|
`;
|
|
17339
18514
|
|
|
17340
18515
|
// src/components/chat/chat-message/chat-message.tsx
|
|
17341
|
-
var
|
|
18516
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
17342
18517
|
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)(
|
|
18518
|
+
const clipboardText = (0, import_react16.useMemo)(() => copyMessageText(message), [message]);
|
|
18519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(MessageContainer, { $role: message.role, children: [
|
|
18520
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(MessageBubble, { $role: message.role, "data-testid": "message-bubble", children: message.blocks.map((block, index2) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Block, { block }, index2)) }),
|
|
18521
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
17353
18522
|
ChatMessageActions,
|
|
17354
18523
|
{
|
|
17355
18524
|
messageId: message.id,
|
|
17356
|
-
content:
|
|
18525
|
+
content: clipboardText,
|
|
17357
18526
|
role: message.role,
|
|
17358
18527
|
isHelpful: message.isHelpful
|
|
17359
18528
|
}
|
|
@@ -17398,20 +18567,20 @@ var Key = import_styled_components7.default.kbd`
|
|
|
17398
18567
|
`;
|
|
17399
18568
|
|
|
17400
18569
|
// src/components/keyboard-shortcut/keyboard-shortcut.tsx
|
|
17401
|
-
var
|
|
18570
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
17402
18571
|
function KeyboardShortcut({
|
|
17403
18572
|
keys,
|
|
17404
18573
|
variant = KEYBOARD_SHORTCUT_VARIANTS.OUTLINED,
|
|
17405
18574
|
className
|
|
17406
18575
|
}) {
|
|
17407
|
-
return /* @__PURE__ */ (0,
|
|
18576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Wrapper, { className, children: keys.map((KeyComponent, index2) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Key, { $variant: variant, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Icon, { icon: KeyComponent, size: 12 }) }, index2)) });
|
|
17408
18577
|
}
|
|
17409
18578
|
|
|
17410
18579
|
// src/components/keyboard-shortcut/icons/icon-ctrl.tsx
|
|
17411
|
-
var
|
|
18580
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
17412
18581
|
function IconCtrl(props) {
|
|
17413
18582
|
const { width: width2 = 24, height: height2 = 24, ...rest } = props;
|
|
17414
|
-
return /* @__PURE__ */ (0,
|
|
18583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.jsx)(
|
|
17415
18584
|
"text",
|
|
17416
18585
|
{
|
|
17417
18586
|
x: "50%",
|
|
@@ -17428,7 +18597,7 @@ function IconCtrl(props) {
|
|
|
17428
18597
|
}
|
|
17429
18598
|
|
|
17430
18599
|
// src/components/lottie/lottie.tsx
|
|
17431
|
-
var
|
|
18600
|
+
var import_react18 = require("react");
|
|
17432
18601
|
|
|
17433
18602
|
// src/components/lottie/lottie-styles.ts
|
|
17434
18603
|
var import_styled_components8 = __toESM(require("styled-components"), 1);
|
|
@@ -17444,7 +18613,7 @@ var LottieContainer = import_styled_components8.default.div`
|
|
|
17444
18613
|
`;
|
|
17445
18614
|
|
|
17446
18615
|
// src/components/lottie/use-lottie.ts
|
|
17447
|
-
var
|
|
18616
|
+
var import_react17 = require("react");
|
|
17448
18617
|
var import_lottie_web = __toESM(require_lottie(), 1);
|
|
17449
18618
|
function useLottie({
|
|
17450
18619
|
animationData: animationData2,
|
|
@@ -17459,17 +18628,17 @@ function useLottie({
|
|
|
17459
18628
|
onLoopComplete,
|
|
17460
18629
|
onEnterFrame
|
|
17461
18630
|
}) {
|
|
17462
|
-
const containerRef = (0,
|
|
17463
|
-
const animationRef = (0,
|
|
17464
|
-
const onAnimationLoadedRef = (0,
|
|
17465
|
-
const onCompleteRef = (0,
|
|
17466
|
-
const onLoopCompleteRef = (0,
|
|
17467
|
-
const onEnterFrameRef = (0,
|
|
18631
|
+
const containerRef = (0, import_react17.useRef)(null);
|
|
18632
|
+
const animationRef = (0, import_react17.useRef)(null);
|
|
18633
|
+
const onAnimationLoadedRef = (0, import_react17.useRef)(onAnimationLoaded);
|
|
18634
|
+
const onCompleteRef = (0, import_react17.useRef)(onComplete);
|
|
18635
|
+
const onLoopCompleteRef = (0, import_react17.useRef)(onLoopComplete);
|
|
18636
|
+
const onEnterFrameRef = (0, import_react17.useRef)(onEnterFrame);
|
|
17468
18637
|
onAnimationLoadedRef.current = onAnimationLoaded;
|
|
17469
18638
|
onCompleteRef.current = onComplete;
|
|
17470
18639
|
onLoopCompleteRef.current = onLoopComplete;
|
|
17471
18640
|
onEnterFrameRef.current = onEnterFrame;
|
|
17472
|
-
(0,
|
|
18641
|
+
(0, import_react17.useEffect)(() => {
|
|
17473
18642
|
if (!containerRef.current) return;
|
|
17474
18643
|
const anim = import_lottie_web.default.loadAnimation({
|
|
17475
18644
|
container: containerRef.current,
|
|
@@ -17561,8 +18730,8 @@ function createLottieRef(animationRef) {
|
|
|
17561
18730
|
}
|
|
17562
18731
|
|
|
17563
18732
|
// src/components/lottie/lottie.tsx
|
|
17564
|
-
var
|
|
17565
|
-
var Lottie = (0,
|
|
18733
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
18734
|
+
var Lottie = (0, import_react18.forwardRef)(function Lottie2({
|
|
17566
18735
|
animationData: animationData2,
|
|
17567
18736
|
autoplay,
|
|
17568
18737
|
loop,
|
|
@@ -17592,8 +18761,8 @@ var Lottie = (0, import_react9.forwardRef)(function Lottie2({
|
|
|
17592
18761
|
onLoopComplete,
|
|
17593
18762
|
onEnterFrame
|
|
17594
18763
|
});
|
|
17595
|
-
(0,
|
|
17596
|
-
return /* @__PURE__ */ (0,
|
|
18764
|
+
(0, import_react18.useImperativeHandle)(ref, () => createLottieRef(animationRef), [animationRef]);
|
|
18765
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
17597
18766
|
LottieContainer,
|
|
17598
18767
|
{
|
|
17599
18768
|
ref: containerRef,
|
|
@@ -17607,7 +18776,7 @@ var Lottie = (0, import_react9.forwardRef)(function Lottie2({
|
|
|
17607
18776
|
});
|
|
17608
18777
|
|
|
17609
18778
|
// src/components/text-area/text-area.tsx
|
|
17610
|
-
var
|
|
18779
|
+
var import_react19 = require("react");
|
|
17611
18780
|
|
|
17612
18781
|
// src/utils/merge-refs.ts
|
|
17613
18782
|
function mergeRefs(...refs) {
|
|
@@ -17647,23 +18816,23 @@ var StyledTextArea = import_styled_components9.default.textarea`
|
|
|
17647
18816
|
`;
|
|
17648
18817
|
|
|
17649
18818
|
// src/components/text-area/text-area.tsx
|
|
17650
|
-
var
|
|
17651
|
-
var TextArea = (0,
|
|
17652
|
-
const internalRef = (0,
|
|
17653
|
-
(0,
|
|
18819
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
18820
|
+
var TextArea = (0, import_react19.forwardRef)(function TextArea2({ value: value2, onChange, placeholder, maxHeight, rows = 1, autoFocus, onKeyDown, disabled, className }, externalRef) {
|
|
18821
|
+
const internalRef = (0, import_react19.useRef)(null);
|
|
18822
|
+
(0, import_react19.useLayoutEffect)(() => {
|
|
17654
18823
|
const el = internalRef.current;
|
|
17655
18824
|
if (el) {
|
|
17656
18825
|
el.style.height = "auto";
|
|
17657
18826
|
el.style.height = `${el.scrollHeight}px`;
|
|
17658
18827
|
}
|
|
17659
18828
|
}, [value2]);
|
|
17660
|
-
const handleChange = (0,
|
|
18829
|
+
const handleChange = (0, import_react19.useCallback)(
|
|
17661
18830
|
(e) => {
|
|
17662
18831
|
onChange(e.target.value);
|
|
17663
18832
|
},
|
|
17664
18833
|
[onChange]
|
|
17665
18834
|
);
|
|
17666
|
-
return /* @__PURE__ */ (0,
|
|
18835
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
17667
18836
|
StyledTextArea,
|
|
17668
18837
|
{
|
|
17669
18838
|
ref: mergeRefs(internalRef, externalRef),
|
|
@@ -17733,21 +18902,26 @@ function parseMarkdownTable(markdown, tableIndex = 0) {
|
|
|
17733
18902
|
return null;
|
|
17734
18903
|
}
|
|
17735
18904
|
|
|
17736
|
-
// src/utils/
|
|
17737
|
-
|
|
17738
|
-
|
|
17739
|
-
|
|
18905
|
+
// src/utils/escape-csv-field.ts
|
|
18906
|
+
var FORMULA_TRIGGERS = /* @__PURE__ */ new Set(["=", "+", "@", " ", "\r"]);
|
|
18907
|
+
function escapeCsvField(field) {
|
|
18908
|
+
const needsNeutralise = field.length > 0 && FORMULA_TRIGGERS.has(field[0]);
|
|
18909
|
+
const safeField = needsNeutralise ? ` ${field}` : field;
|
|
18910
|
+
if (needsNeutralise || safeField.includes(",") || safeField.includes('"') || safeField.includes("\n") || safeField.includes("\r")) {
|
|
18911
|
+
return `"${safeField.replace(/"/g, '""')}"`;
|
|
17740
18912
|
}
|
|
17741
|
-
return
|
|
18913
|
+
return safeField;
|
|
17742
18914
|
}
|
|
18915
|
+
|
|
18916
|
+
// src/utils/convert-table-to-csv.ts
|
|
17743
18917
|
function convertTableToCSV(table) {
|
|
17744
|
-
const headerRow = table.columns.map(
|
|
17745
|
-
const dataRows = table.rows.map((row) => row.map(
|
|
18918
|
+
const headerRow = table.columns.map(escapeCsvField).join(",");
|
|
18919
|
+
const dataRows = table.rows.map((row) => row.map(escapeCsvField).join(","));
|
|
17746
18920
|
return [headerRow, ...dataRows].join("\r\n");
|
|
17747
18921
|
}
|
|
17748
18922
|
|
|
17749
18923
|
// src/components/button/button.tsx
|
|
17750
|
-
var
|
|
18924
|
+
var import_react20 = require("react");
|
|
17751
18925
|
|
|
17752
18926
|
// src/components/button/button-styles.ts
|
|
17753
18927
|
var import_styled_components10 = __toESM(require("styled-components"), 1);
|
|
@@ -17869,8 +19043,8 @@ var StyledButton = import_styled_components10.default.button`
|
|
|
17869
19043
|
`;
|
|
17870
19044
|
|
|
17871
19045
|
// src/components/button/button.tsx
|
|
17872
|
-
var
|
|
17873
|
-
var Button2 = (0,
|
|
19046
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
19047
|
+
var Button2 = (0, import_react20.forwardRef)(function Button3({
|
|
17874
19048
|
children,
|
|
17875
19049
|
variant = BUTTON_VARIANT.SOLID,
|
|
17876
19050
|
intent = BUTTON_INTENT.PRIMARY,
|
|
@@ -17882,8 +19056,8 @@ var Button2 = (0, import_react11.forwardRef)(function Button3({
|
|
|
17882
19056
|
className,
|
|
17883
19057
|
"aria-label": ariaLabel
|
|
17884
19058
|
}, ref) {
|
|
17885
|
-
const iconElement = icon ? /* @__PURE__ */ (0,
|
|
17886
|
-
return /* @__PURE__ */ (0,
|
|
19059
|
+
const iconElement = icon ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Icon, { icon, size: 16 }) : null;
|
|
19060
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
17887
19061
|
StyledButton,
|
|
17888
19062
|
{
|
|
17889
19063
|
ref,
|
|
@@ -17897,7 +19071,7 @@ var Button2 = (0, import_react11.forwardRef)(function Button3({
|
|
|
17897
19071
|
"aria-label": ariaLabel,
|
|
17898
19072
|
children: [
|
|
17899
19073
|
iconPosition === ICON_POSITION.LEADING && iconElement,
|
|
17900
|
-
/* @__PURE__ */ (0,
|
|
19074
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children }),
|
|
17901
19075
|
iconPosition === ICON_POSITION.TRAILING && iconElement
|
|
17902
19076
|
]
|
|
17903
19077
|
}
|
|
@@ -17905,6 +19079,10 @@ var Button2 = (0, import_react11.forwardRef)(function Button3({
|
|
|
17905
19079
|
});
|
|
17906
19080
|
// Annotate the CommonJS export names for ESM import in node:
|
|
17907
19081
|
0 && (module.exports = {
|
|
19082
|
+
ArtifactDownloadButton,
|
|
19083
|
+
ArtifactRefBlock,
|
|
19084
|
+
ArtifactRefBlockService,
|
|
19085
|
+
ArtifactServices,
|
|
17908
19086
|
BUTTON_INTENT,
|
|
17909
19087
|
BUTTON_SIZE,
|
|
17910
19088
|
BUTTON_VARIANT,
|
|
@@ -17912,8 +19090,11 @@ var Button2 = (0, import_react11.forwardRef)(function Button3({
|
|
|
17912
19090
|
BlockContext,
|
|
17913
19091
|
BlockServices,
|
|
17914
19092
|
Button,
|
|
19093
|
+
ChartArtifact,
|
|
17915
19094
|
ChatContext,
|
|
17916
19095
|
ChatMessage,
|
|
19096
|
+
DEFAULT_CHART_ARTIFACT_LABELS,
|
|
19097
|
+
DEFAULT_TABLE_ARTIFACT_LABELS,
|
|
17917
19098
|
ICON_POSITION,
|
|
17918
19099
|
Icon,
|
|
17919
19100
|
IconButton,
|
|
@@ -17922,12 +19103,18 @@ var Button2 = (0, import_react11.forwardRef)(function Button3({
|
|
|
17922
19103
|
KeyboardShortcut,
|
|
17923
19104
|
Lottie,
|
|
17924
19105
|
MESSAGE_ROLE,
|
|
19106
|
+
TableArtifact,
|
|
17925
19107
|
TextArea,
|
|
17926
19108
|
TextBlockService,
|
|
19109
|
+
artifactToClipboardText,
|
|
19110
|
+
artifactTypes,
|
|
17927
19111
|
blockTypes,
|
|
17928
19112
|
colors,
|
|
17929
19113
|
convertTableToCSV,
|
|
19114
|
+
copyMessageText,
|
|
19115
|
+
escapeCsvField,
|
|
17930
19116
|
fontFamilies,
|
|
19117
|
+
isSafeDownloadUrl,
|
|
17931
19118
|
markdownToPlainText,
|
|
17932
19119
|
mergeRefs,
|
|
17933
19120
|
parseMarkdownTable,
|
|
@@ -17954,6 +19141,7 @@ lottie-web/build/player/lottie.js:
|
|
|
17954
19141
|
@tabler/icons-react/dist/esm/createReactComponent.mjs:
|
|
17955
19142
|
@tabler/icons-react/dist/esm/icons/IconCheck.mjs:
|
|
17956
19143
|
@tabler/icons-react/dist/esm/icons/IconCopy.mjs:
|
|
19144
|
+
@tabler/icons-react/dist/esm/icons/IconDownload.mjs:
|
|
17957
19145
|
@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
|
|
17958
19146
|
@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
|
|
17959
19147
|
@tabler/icons-react/dist/esm/tabler-icons-react.mjs:
|