@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.
Files changed (85) hide show
  1. package/README.md +60 -0
  2. package/dist/artifacts.cjs +1467 -0
  3. package/dist/artifacts.cjs.map +1 -0
  4. package/dist/artifacts.d.cts +89 -0
  5. package/dist/artifacts.d.ts +89 -0
  6. package/dist/artifacts.js +33 -0
  7. package/dist/blocks.cjs +1418 -68
  8. package/dist/blocks.cjs.map +1 -1
  9. package/dist/blocks.css +2 -0
  10. package/dist/blocks.d.cts +36 -11
  11. package/dist/blocks.d.ts +36 -11
  12. package/dist/blocks.js +18 -5
  13. package/dist/button.d.cts +2 -2
  14. package/dist/button.d.ts +2 -2
  15. package/dist/chart.cjs +594 -0
  16. package/dist/chart.cjs.map +1 -0
  17. package/dist/chart.d.cts +439 -0
  18. package/dist/chart.d.ts +439 -0
  19. package/dist/chart.js +32 -0
  20. package/dist/chart.js.map +1 -0
  21. package/dist/chat.cjs +1462 -312
  22. package/dist/chat.cjs.map +1 -1
  23. package/dist/chat.d.cts +28 -10
  24. package/dist/chat.d.ts +28 -10
  25. package/dist/chat.js +10 -3
  26. package/dist/{chunk-R3BGPOAM.js → chunk-36CB624W.js} +53 -45
  27. package/dist/chunk-36CB624W.js.map +1 -0
  28. package/dist/chunk-4MZZH3WX.js +93 -0
  29. package/dist/chunk-4MZZH3WX.js.map +1 -0
  30. package/dist/chunk-AQEJRMRN.js +1 -0
  31. package/dist/chunk-AQEJRMRN.js.map +1 -0
  32. package/dist/{chunk-WS4IPADR.js → chunk-FFX3CAOX.js} +41 -109
  33. package/dist/chunk-FFX3CAOX.js.map +1 -0
  34. package/dist/chunk-JGMN6W72.js +12 -0
  35. package/dist/chunk-JGMN6W72.js.map +1 -0
  36. package/dist/{chunk-27GJUWVN.js → chunk-JJUIBBBU.js} +14 -8
  37. package/dist/chunk-JJUIBBBU.js.map +1 -0
  38. package/dist/{chunk-MLCRDVQ2.js → chunk-OBOXCBDL.js} +13 -5
  39. package/dist/chunk-OBOXCBDL.js.map +1 -0
  40. package/dist/chunk-P6GUNIAE.js +11 -0
  41. package/dist/chunk-P6GUNIAE.js.map +1 -0
  42. package/dist/chunk-QXGYMDIA.js +477 -0
  43. package/dist/chunk-QXGYMDIA.js.map +1 -0
  44. package/dist/chunk-Z5JWF24N.js +719 -0
  45. package/dist/chunk-Z5JWF24N.js.map +1 -0
  46. package/dist/icon.cjs +12 -4
  47. package/dist/icon.cjs.map +1 -1
  48. package/dist/icon.d.cts +19 -6
  49. package/dist/icon.d.ts +19 -6
  50. package/dist/icon.js +1 -1
  51. package/dist/index.cjs +1520 -332
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +7 -4
  54. package/dist/index.d.ts +7 -4
  55. package/dist/index.js +58 -25
  56. package/dist/lottie.d.cts +2 -2
  57. package/dist/lottie.d.ts +2 -2
  58. package/dist/table.cjs +142 -0
  59. package/dist/table.cjs.map +1 -0
  60. package/dist/table.d.cts +44 -0
  61. package/dist/table.d.ts +44 -0
  62. package/dist/table.js +25 -0
  63. package/dist/table.js.map +1 -0
  64. package/dist/text-area.d.cts +2 -2
  65. package/dist/text-area.d.ts +2 -2
  66. package/dist/types-B2aYk82c.d.cts +29 -0
  67. package/dist/types-B2aYk82c.d.ts +29 -0
  68. package/dist/types-C0BvwliI.d.cts +332 -0
  69. package/dist/types-C5bFH4v3.d.ts +332 -0
  70. package/dist/types-DCutaXjZ.d.cts +83 -0
  71. package/dist/types-uPfn67Dc.d.ts +83 -0
  72. package/dist/utils.cjs +14 -7
  73. package/dist/utils.cjs.map +1 -1
  74. package/dist/utils.d.cts +18 -1
  75. package/dist/utils.d.ts +18 -1
  76. package/dist/utils.js +6 -4
  77. package/package.json +41 -4
  78. package/dist/chunk-27GJUWVN.js.map +0 -1
  79. package/dist/chunk-MLCRDVQ2.js.map +0 -1
  80. package/dist/chunk-OKPNST44.js +0 -1
  81. package/dist/chunk-R3BGPOAM.js.map +0 -1
  82. package/dist/chunk-WS4IPADR.js.map +0 -1
  83. package/dist/types-Q9aqd9nq.d.cts +0 -34
  84. package/dist/types-Q9aqd9nq.d.ts +0 -34
  85. /package/dist/{chunk-OKPNST44.js.map → artifacts.js.map} +0 -0
@@ -0,0 +1,719 @@
1
+ import {
2
+ BarChart,
3
+ LineChart,
4
+ PieChart
5
+ } from "./chunk-QXGYMDIA.js";
6
+ import {
7
+ Table,
8
+ TableBody,
9
+ TableCell,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ useScrollShadow
14
+ } from "./chunk-4MZZH3WX.js";
15
+ import {
16
+ cn
17
+ } from "./chunk-P6GUNIAE.js";
18
+ import {
19
+ IconButton
20
+ } from "./chunk-OBOXCBDL.js";
21
+
22
+ // src/components/artifacts/artifact-base.ts
23
+ var artifactTypes = {
24
+ TABLE: "TABLE",
25
+ CHART: "CHART"
26
+ };
27
+
28
+ // src/components/artifacts/chart-artifact/types.ts
29
+ var DEFAULT_CHART_ARTIFACT_LABELS = {
30
+ download: "Download CSV",
31
+ unavailable: "Chart data is unavailable.",
32
+ loadError: "Couldn't load chart data.",
33
+ loading: "Loading chart\u2026",
34
+ empty: "No data to chart.",
35
+ othersCategoryLabels: ["Others", "Other"]
36
+ };
37
+
38
+ // src/components/artifacts/table-artifact/types.ts
39
+ var DEFAULT_TABLE_ARTIFACT_LABELS = {
40
+ download: "Download CSV",
41
+ unavailable: "Table data is unavailable.",
42
+ loadError: "Couldn't load table data.",
43
+ loading: "Loading table\u2026",
44
+ empty: "No rows to display."
45
+ };
46
+
47
+ // node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
48
+ import { forwardRef, createElement } from "react";
49
+
50
+ // node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs
51
+ var defaultAttributes = {
52
+ outline: {
53
+ xmlns: "http://www.w3.org/2000/svg",
54
+ width: 24,
55
+ height: 24,
56
+ viewBox: "0 0 24 24",
57
+ fill: "none",
58
+ stroke: "currentColor",
59
+ strokeWidth: 2,
60
+ strokeLinecap: "round",
61
+ strokeLinejoin: "round"
62
+ },
63
+ filled: {
64
+ xmlns: "http://www.w3.org/2000/svg",
65
+ width: 24,
66
+ height: 24,
67
+ viewBox: "0 0 24 24",
68
+ fill: "currentColor",
69
+ stroke: "none"
70
+ }
71
+ };
72
+
73
+ // node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
74
+ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
75
+ const Component = forwardRef(
76
+ ({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => createElement(
77
+ "svg",
78
+ {
79
+ ref,
80
+ ...defaultAttributes[type],
81
+ width: size,
82
+ height: size,
83
+ className: [`tabler-icon`, `tabler-icon-${iconName}`, className].join(" "),
84
+ ...type === "filled" ? {
85
+ fill: color
86
+ } : {
87
+ strokeWidth: stroke,
88
+ stroke: color
89
+ },
90
+ ...rest
91
+ },
92
+ [
93
+ title && createElement("title", { key: "svg-title" }, title),
94
+ ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
95
+ ...Array.isArray(children) ? children : [children]
96
+ ]
97
+ )
98
+ );
99
+ Component.displayName = `${iconNamePascal}`;
100
+ return Component;
101
+ };
102
+
103
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
104
+ var __iconNode = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
105
+ var IconCheck = createReactComponent("outline", "check", "Check", __iconNode);
106
+
107
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
108
+ 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" }]];
109
+ var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode2);
110
+
111
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconDownload.mjs
112
+ 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" }]];
113
+ var IconDownload = createReactComponent("outline", "download", "Download", __iconNode3);
114
+
115
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
116
+ 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" }]];
117
+ var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode4);
118
+
119
+ // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
120
+ 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" }]];
121
+ var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode5);
122
+
123
+ // src/components/ui/tooltip.tsx
124
+ import * as React from "react";
125
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
126
+ import { jsx } from "react/jsx-runtime";
127
+ var TooltipProvider = TooltipPrimitive.Provider;
128
+ var Tooltip = TooltipPrimitive.Root;
129
+ var TooltipTrigger = TooltipPrimitive.Trigger;
130
+ var TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
131
+ TooltipPrimitive.Content,
132
+ {
133
+ ref,
134
+ sideOffset,
135
+ className: cn(
136
+ "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]",
137
+ className
138
+ ),
139
+ ...props
140
+ }
141
+ ));
142
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
143
+
144
+ // src/components/artifacts/artifact-download-button/artifact-download-button.tsx
145
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
146
+ var DEFAULT_LABEL = "Download CSV";
147
+ function ArtifactDownloadButton({
148
+ href,
149
+ label = DEFAULT_LABEL,
150
+ onClick
151
+ }) {
152
+ if (!isSafeDownloadUrl(href)) return null;
153
+ return /* @__PURE__ */ jsx2(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
154
+ /* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(
155
+ IconButton,
156
+ {
157
+ as: "a",
158
+ href,
159
+ download: true,
160
+ rel: "noopener noreferrer",
161
+ onClick,
162
+ icon: IconDownload,
163
+ size: "small",
164
+ "aria-label": label
165
+ }
166
+ ) }),
167
+ /* @__PURE__ */ jsx2(TooltipContent, { children: label })
168
+ ] }) });
169
+ }
170
+ function isSafeDownloadUrl(url) {
171
+ try {
172
+ const parsed = new URL(url);
173
+ return parsed.protocol === "https:" || parsed.protocol === "http:";
174
+ } catch {
175
+ return false;
176
+ }
177
+ }
178
+
179
+ // src/components/artifacts/chart-artifact/chart-artifact.tsx
180
+ import { useEffect as useEffect2, useMemo as useMemo2 } from "react";
181
+
182
+ // src/components/ai-elements/artifact.tsx
183
+ import { jsx as jsx3 } from "react/jsx-runtime";
184
+ var Artifact = ({ className, ...props }) => /* @__PURE__ */ jsx3(
185
+ "div",
186
+ {
187
+ className: cn("flex flex-col overflow-hidden rounded-lg border bg-background shadow-sm", className),
188
+ ...props
189
+ }
190
+ );
191
+ var ArtifactHeader = ({ className, ...props }) => /* @__PURE__ */ jsx3("div", { className: cn("flex items-center justify-between border-b bg-muted/50 px-4 py-3", className), ...props });
192
+ var ArtifactTitle = ({ className, ...props }) => /* @__PURE__ */ jsx3("p", { className: cn("font-medium text-foreground text-sm", className), ...props });
193
+ var ArtifactActions = ({ className, ...props }) => /* @__PURE__ */ jsx3("div", { className: cn("flex items-center gap-1", className), ...props });
194
+ var ArtifactContent = ({ className, ...props }) => /* @__PURE__ */ jsx3("div", { className: cn("flex-1 overflow-auto p-4", className), ...props });
195
+
196
+ // src/components/artifacts/status-message.tsx
197
+ import { createElement as createElement2 } from "react";
198
+ function StatusMessage({ $tone, children }) {
199
+ return createElement2(
200
+ "div",
201
+ {
202
+ className: `py-6 px-2 text-center text-sm font-medium leading-5 ${$tone === "error" ? "text-red-600" : "text-brown-70"}`
203
+ },
204
+ children
205
+ );
206
+ }
207
+
208
+ // src/components/artifacts/chart-artifact/chart-variant-services/constants.ts
209
+ var VARIANT_CHART_HEIGHT = "100%";
210
+
211
+ // src/components/artifacts/chart-artifact/chart-variant-services/bar-chart-variant-component.tsx
212
+ import { jsx as jsx4 } from "react/jsx-runtime";
213
+ function BarChartVariantComponent({ config, rows }) {
214
+ return /* @__PURE__ */ jsx4(
215
+ BarChart,
216
+ {
217
+ data: rows,
218
+ xKey: config.xKey,
219
+ series: config.series,
220
+ stacked: config.stacked,
221
+ height: VARIANT_CHART_HEIGHT
222
+ }
223
+ );
224
+ }
225
+
226
+ // src/components/artifacts/chart-artifact/chart-variant-services/shared-column-keys.ts
227
+ function seriesBasedColumnKeys(config) {
228
+ return [config.xKey, ...config.series.map((s) => s.key)];
229
+ }
230
+ function pieColumnKeys(config) {
231
+ return [config.categoryKey, config.valueKey];
232
+ }
233
+
234
+ // src/components/artifacts/chart-artifact/chart-variant-services/shared-validators.ts
235
+ function isValidChartSeries(series) {
236
+ if (!series || typeof series !== "object") return false;
237
+ const candidate = series;
238
+ if (typeof candidate.key !== "string" || candidate.key.length === 0) return false;
239
+ if (typeof candidate.label !== "string") return false;
240
+ return true;
241
+ }
242
+
243
+ // src/components/artifacts/chart-artifact/chart-variant-services/bar-chart-variant-service.tsx
244
+ function isValidBarChartConfig(config) {
245
+ if (!config || typeof config !== "object") return false;
246
+ const candidate = config;
247
+ if (candidate.variant !== "BAR") return false;
248
+ if (typeof candidate.xKey !== "string" || candidate.xKey.length === 0) return false;
249
+ if (!Array.isArray(candidate.series) || candidate.series.length === 0) return false;
250
+ if (!candidate.series.every(isValidChartSeries)) return false;
251
+ return true;
252
+ }
253
+ var BarChartVariantService = {
254
+ variant: "BAR",
255
+ isValidConfig: isValidBarChartConfig,
256
+ columnKeys: seriesBasedColumnKeys,
257
+ Component: BarChartVariantComponent
258
+ };
259
+
260
+ // src/components/artifacts/chart-artifact/chart-variant-services/line-chart-variant-component.tsx
261
+ import { jsx as jsx5 } from "react/jsx-runtime";
262
+ function LineChartVariantComponent({ config, rows }) {
263
+ return /* @__PURE__ */ jsx5(LineChart, { data: rows, xKey: config.xKey, series: config.series, height: VARIANT_CHART_HEIGHT });
264
+ }
265
+
266
+ // src/components/artifacts/chart-artifact/chart-variant-services/line-chart-variant-service.tsx
267
+ function isValidLineChartConfig(config) {
268
+ if (!config || typeof config !== "object") return false;
269
+ const candidate = config;
270
+ if (candidate.variant !== "LINE") return false;
271
+ if (typeof candidate.xKey !== "string" || candidate.xKey.length === 0) return false;
272
+ if (!Array.isArray(candidate.series) || candidate.series.length === 0) return false;
273
+ if (!candidate.series.every(isValidChartSeries)) return false;
274
+ return true;
275
+ }
276
+ var LineChartVariantService = {
277
+ variant: "LINE",
278
+ isValidConfig: isValidLineChartConfig,
279
+ columnKeys: seriesBasedColumnKeys,
280
+ Component: LineChartVariantComponent
281
+ };
282
+
283
+ // src/components/artifacts/chart-artifact/chart-variant-services/pie-chart-variant-component.tsx
284
+ import { jsx as jsx6 } from "react/jsx-runtime";
285
+ function PieChartVariantComponent({
286
+ config,
287
+ rows,
288
+ labels
289
+ }) {
290
+ return /* @__PURE__ */ jsx6(
291
+ PieChart,
292
+ {
293
+ data: rows,
294
+ categoryKey: config.categoryKey,
295
+ valueKey: config.valueKey,
296
+ othersCategoryLabels: labels.othersCategoryLabels,
297
+ height: VARIANT_CHART_HEIGHT
298
+ }
299
+ );
300
+ }
301
+
302
+ // src/components/artifacts/chart-artifact/chart-variant-services/pie-chart-variant-service.tsx
303
+ function isValidPieChartConfig(config) {
304
+ if (!config || typeof config !== "object") return false;
305
+ const candidate = config;
306
+ if (candidate.variant !== "PIE") return false;
307
+ if (typeof candidate.categoryKey !== "string" || candidate.categoryKey.length === 0) return false;
308
+ if (typeof candidate.valueKey !== "string" || candidate.valueKey.length === 0) return false;
309
+ if (!Array.isArray(candidate.series)) return false;
310
+ return true;
311
+ }
312
+ var PieChartVariantService = {
313
+ variant: "PIE",
314
+ isValidConfig: isValidPieChartConfig,
315
+ columnKeys: pieColumnKeys,
316
+ Component: PieChartVariantComponent
317
+ };
318
+
319
+ // src/components/artifacts/chart-artifact/chart-variant-services/index.ts
320
+ var ChartVariantServices = {
321
+ LINE: LineChartVariantService,
322
+ BAR: BarChartVariantService,
323
+ PIE: PieChartVariantService
324
+ };
325
+
326
+ // src/components/artifacts/chart-artifact/chart-artifact-content.tsx
327
+ import { jsx as jsx7 } from "react/jsx-runtime";
328
+ function ChartArtifactContent({ config, rows, labels }) {
329
+ const service = ChartVariantServices[config.variant];
330
+ if (!service) {
331
+ return /* @__PURE__ */ jsx7(StatusMessage, { $tone: "info", children: labels.unavailable });
332
+ }
333
+ const Component = service.Component;
334
+ return /* @__PURE__ */ jsx7(Component, { config, rows, labels });
335
+ }
336
+
337
+ // src/components/artifacts/parse-csv.ts
338
+ import Papa from "papaparse";
339
+ function parseCsv(text, columns) {
340
+ const result = Papa.parse(text, {
341
+ header: true,
342
+ skipEmptyLines: true,
343
+ dynamicTyping: false
344
+ });
345
+ const csvHeaders = new Set(result.meta?.fields ?? []);
346
+ const presentColumns = columns.filter((col) => csvHeaders.has(col.key));
347
+ if (presentColumns.length === 0) return [];
348
+ return result.data.map((rawRow) => {
349
+ const row = {};
350
+ for (const column of presentColumns) {
351
+ const value = rawRow[column.key];
352
+ row[column.key] = value === void 0 || value === "" ? null : value;
353
+ }
354
+ return row;
355
+ });
356
+ }
357
+
358
+ // src/components/artifacts/use-rows-artifact-data.ts
359
+ import { useEffect, useMemo, useState } from "react";
360
+ var LOADING = { status: "loading", rows: null, error: null };
361
+ var UNAVAILABLE = { status: "unavailable", rows: null, error: null };
362
+ var INITIAL_INTERNAL = { cacheKey: null, data: LOADING };
363
+ function columnsFingerprint(columns) {
364
+ return columns.map((c) => c.key).join("|");
365
+ }
366
+ function scrubUrl(url) {
367
+ const q = url.indexOf("?");
368
+ return q === -1 ? url : `${url.slice(0, q)}?<redacted>`;
369
+ }
370
+ function useRowsArtifactData(presignedUrl, columns, parse) {
371
+ const colsKey = useMemo(() => columnsFingerprint(columns), [columns]);
372
+ const safeUrl = presignedUrl && isSafeDownloadUrl(presignedUrl) ? presignedUrl : null;
373
+ const cacheKey = safeUrl ? `${safeUrl}::${colsKey}` : null;
374
+ const [state, setState] = useState(INITIAL_INTERNAL);
375
+ useEffect(() => {
376
+ if (!safeUrl) return;
377
+ const controller = new AbortController();
378
+ fetch(safeUrl, {
379
+ signal: controller.signal,
380
+ headers: { Accept: "text/csv" },
381
+ // Presigned URLs are cross-origin S3 in production and don't need credentials. Explicit
382
+ // omit so a same-origin URL (compromised payload, local dev) can't accidentally receive
383
+ // session cookies or auth headers.
384
+ credentials: "omit"
385
+ }).then(async (response) => {
386
+ if (!response.ok) throw new Error(`Failed to load artifact data (${response.status})`);
387
+ return response.text();
388
+ }).then((text) => {
389
+ if (controller.signal.aborted) return;
390
+ try {
391
+ const rows = parse(text, columns);
392
+ setState({ cacheKey: `${safeUrl}::${colsKey}`, data: { status: "ready", rows, error: null } });
393
+ } catch (parseError) {
394
+ const err = parseError instanceof Error ? parseError : new Error(String(parseError));
395
+ console.error("[ArtifactData] CSV parse failed:", err.message);
396
+ setState({ cacheKey: `${safeUrl}::${colsKey}`, data: { status: "error", rows: null, error: err } });
397
+ }
398
+ }).catch((error) => {
399
+ if (controller.signal.aborted) return;
400
+ const err = error instanceof Error ? error : new Error(String(error));
401
+ console.error(`[ArtifactData] Fetch failed [${scrubUrl(safeUrl)}]:`, err.message);
402
+ setState({ cacheKey: `${safeUrl}::${colsKey}`, data: { status: "error", rows: null, error: err } });
403
+ });
404
+ return () => {
405
+ controller.abort();
406
+ };
407
+ }, [safeUrl, colsKey]);
408
+ if (!safeUrl) return UNAVAILABLE;
409
+ if (state.cacheKey !== cacheKey) return LOADING;
410
+ return state.data;
411
+ }
412
+
413
+ // src/components/artifacts/chart-artifact/use-chart-artifact-data.ts
414
+ function useChartArtifactData(presignedUrl, config) {
415
+ const service = ChartVariantServices[config.variant];
416
+ const keys = service ? service.columnKeys(config) : [];
417
+ const columns = keys.map((key) => ({ key }));
418
+ return useRowsArtifactData(presignedUrl, columns, parseCsv);
419
+ }
420
+
421
+ // src/components/artifacts/chart-artifact/validate.ts
422
+ function isValidChartConfig(config) {
423
+ if (!config || typeof config !== "object") return false;
424
+ const variant = config.variant;
425
+ if (typeof variant !== "string") return false;
426
+ const service = ChartVariantServices[variant];
427
+ if (!service) return false;
428
+ return service.isValidConfig(config);
429
+ }
430
+
431
+ // src/components/artifacts/chart-artifact/chart-artifact.tsx
432
+ import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
433
+ var TITLE_CLASSES = "text-sm font-semibold text-foreground";
434
+ var CHART_HEIGHT = 320;
435
+ function ChartArtifact({ artifact, labels, callbacks }) {
436
+ const validConfig = isValidChartConfig(artifact.config);
437
+ useEffect2(() => {
438
+ if (validConfig) return;
439
+ console.warn("[clay] ChartArtifact: malformed `config` \u2014 skipping render.");
440
+ }, [validConfig]);
441
+ const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
442
+ const resolvedLabels = useMemo2(
443
+ () => ({ ...DEFAULT_CHART_ARTIFACT_LABELS, ...labels?.[artifactTypes.CHART] ?? {} }),
444
+ [labels]
445
+ );
446
+ const data = useChartArtifactData(
447
+ validConfig ? presignedUrl : null,
448
+ validConfig ? artifact.config : { variant: "LINE", series: [], xKey: "x" }
449
+ );
450
+ const onDownload = callbacks?.[artifactTypes.CHART]?.onDownload;
451
+ const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
452
+ return /* @__PURE__ */ jsxs2(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
453
+ /* @__PURE__ */ jsxs2(ArtifactHeader, { className: "bg-background/70", children: [
454
+ artifact.title ? /* @__PURE__ */ jsx8(ArtifactTitle, { className: TITLE_CLASSES, children: artifact.title }) : /* @__PURE__ */ jsx8("span", {}),
455
+ presignedUrl ? /* @__PURE__ */ jsx8(ArtifactActions, { children: /* @__PURE__ */ jsx8(ArtifactDownloadButton, { href: presignedUrl, label: resolvedLabels.download, onClick: handleDownloadClick }) }) : null
456
+ ] }),
457
+ /* @__PURE__ */ jsx8(
458
+ ArtifactContent,
459
+ {
460
+ className: "p-4 overflow-visible flex flex-none items-center justify-center",
461
+ style: { height: CHART_HEIGHT },
462
+ children: renderBody(validConfig, artifact, data, resolvedLabels)
463
+ }
464
+ )
465
+ ] });
466
+ }
467
+ function renderBody(validConfig, artifact, data, labels) {
468
+ if (!validConfig) {
469
+ return /* @__PURE__ */ jsx8(StatusMessage, { $tone: "info", children: labels.unavailable });
470
+ }
471
+ if (data.status === "error") {
472
+ return /* @__PURE__ */ jsx8(StatusMessage, { $tone: "error", children: labels.loadError });
473
+ }
474
+ if (data.status === "unavailable") {
475
+ return /* @__PURE__ */ jsx8(StatusMessage, { $tone: "info", children: labels.unavailable });
476
+ }
477
+ if (data.status === "loading") {
478
+ return /* @__PURE__ */ jsx8(StatusMessage, { $tone: "info", children: labels.loading });
479
+ }
480
+ if (data.rows.length === 0) {
481
+ return /* @__PURE__ */ jsx8(StatusMessage, { $tone: "info", children: labels.empty });
482
+ }
483
+ return /* @__PURE__ */ jsx8(ChartArtifactContent, { config: artifact.config, rows: data.rows, labels });
484
+ }
485
+
486
+ // src/components/artifacts/table-artifact/table-artifact.tsx
487
+ import { useEffect as useEffect3, useMemo as useMemo3 } from "react";
488
+
489
+ // src/components/artifacts/table-artifact/table-artifact-content.constants.ts
490
+ var TABLE_STATUS = {
491
+ LOADING: "loading",
492
+ READY: "ready",
493
+ ERROR: "error",
494
+ UNAVAILABLE: "unavailable"
495
+ };
496
+
497
+ // src/components/artifacts/table-artifact/table-artifact-content.utils.ts
498
+ function formatCell(row, column) {
499
+ return row[column.key] ?? "";
500
+ }
501
+ var HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
502
+ var CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
503
+ var ROW_CLASSES = "border-b-brown-30 bg-background/70 hover:bg-secondary";
504
+ var DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;
505
+ var SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
506
+
507
+ // src/components/artifacts/table-artifact/table-artifact-content.tsx
508
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
509
+ function TableArtifactContent({
510
+ columns,
511
+ data,
512
+ knownRowCount,
513
+ maxShimmerRows,
514
+ maxBodyHeight,
515
+ labels
516
+ }) {
517
+ if (data.status === TABLE_STATUS.ERROR) {
518
+ return /* @__PURE__ */ jsx9(StatusMessage, { $tone: "error", children: labels.loadError });
519
+ }
520
+ if (data.status === TABLE_STATUS.UNAVAILABLE) {
521
+ return /* @__PURE__ */ jsx9(StatusMessage, { $tone: "info", children: labels.unavailable });
522
+ }
523
+ if (data.status === TABLE_STATUS.LOADING) {
524
+ if (typeof knownRowCount === "number" && knownRowCount > 0) {
525
+ const shimmerCount = Math.min(knownRowCount, maxShimmerRows);
526
+ return /* @__PURE__ */ jsx9(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
527
+ }
528
+ return /* @__PURE__ */ jsx9(StatusMessage, { $tone: "info", children: labels.loading });
529
+ }
530
+ return /* @__PURE__ */ jsx9(ArtifactTable, { columns, maxBodyHeight, children: data.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data.rows) });
531
+ }
532
+ function ArtifactTable({ columns, maxBodyHeight, children }) {
533
+ const { targetRef, isScrolled } = useScrollShadow();
534
+ return /* @__PURE__ */ jsx9("div", { ref: targetRef, className: "overscroll-none", style: { maxHeight: maxBodyHeight, overflowY: "auto" }, children: /* @__PURE__ */ jsxs3(Table, { containerClassName: "overflow-visible", children: [
535
+ /* @__PURE__ */ jsx9(
536
+ TableHeader,
537
+ {
538
+ "data-scrolled": isScrolled ? "true" : void 0,
539
+ className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
540
+ style: isScrolled ? { boxShadow: SCROLL_SHADOW } : void 0,
541
+ children: /* @__PURE__ */ jsx9(TableRow, { className: "hover:bg-transparent", children: columns.map((column) => /* @__PURE__ */ jsx9(TableHead, { scope: "col", className: HEAD_CLASS, children: column.label }, column.key)) })
542
+ }
543
+ ),
544
+ /* @__PURE__ */ jsx9(TableBody, { children })
545
+ ] }) });
546
+ }
547
+ function renderShimmerRows(columns, count) {
548
+ return Array.from({ length: count }).map((_, index) => /* @__PURE__ */ jsx9(TableRow, { className: ROW_CLASSES, "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ jsx9(TableCell, { className: CELL_CLASS, children: /* @__PURE__ */ jsx9("span", { className: "block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20" }) }, column.key)) }, `shimmer-${index}`));
549
+ }
550
+ function renderDataRows(columns, rows) {
551
+ return rows.map((row, index) => /* @__PURE__ */ jsx9(TableRow, { className: DATA_ROW_CLASSES, children: columns.map((column) => /* @__PURE__ */ jsx9(TableCell, { className: CELL_CLASS, children: formatCell(row, column) }, column.key)) }, index));
552
+ }
553
+ function renderEmptyRow(colSpan, emptyMessage) {
554
+ return /* @__PURE__ */ jsx9(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx9(TableCell, { colSpan, className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) });
555
+ }
556
+
557
+ // src/components/artifacts/table-artifact/use-table-artifact-data.ts
558
+ function useTableArtifactData(presignedUrl, columns) {
559
+ return useRowsArtifactData(presignedUrl, columns, parseCsv);
560
+ }
561
+
562
+ // src/components/artifacts/table-artifact/validate.ts
563
+ function isValidTableConfig(config) {
564
+ if (!config || typeof config !== "object") return false;
565
+ const candidate = config;
566
+ if (!Array.isArray(candidate.columns)) return false;
567
+ if (candidate.columns.length === 0) return false;
568
+ return candidate.columns.every(isValidTableColumn);
569
+ }
570
+ function isValidTableColumn(column) {
571
+ if (!column || typeof column !== "object") return false;
572
+ const candidate = column;
573
+ if (typeof candidate.key !== "string" || candidate.key.length === 0) return false;
574
+ if (typeof candidate.label !== "string") return false;
575
+ return true;
576
+ }
577
+
578
+ // src/components/artifacts/table-artifact/table-artifact.tsx
579
+ import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
580
+ var TITLE_CLASSES2 = "text-sm font-semibold text-foreground";
581
+ var TABLE_MAX_BODY_HEIGHT = 480;
582
+ var MAX_SHIMMER_ROWS = 10;
583
+ function TableArtifact({ artifact, labels, callbacks }) {
584
+ const validConfig = isValidTableConfig(artifact.config);
585
+ const validColumns = validConfig ? artifact.config.columns : null;
586
+ useEffect3(() => {
587
+ if (validConfig) return;
588
+ console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
589
+ }, [validConfig]);
590
+ const resolvedLabels = useMemo3(
591
+ () => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels?.[artifactTypes.TABLE] ?? {} }),
592
+ [labels]
593
+ );
594
+ const data = useTableArtifactData(
595
+ validConfig ? artifact.protectedAsset?.presignedUrl ?? null : null,
596
+ validColumns ?? []
597
+ );
598
+ const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
599
+ const onDownload = callbacks?.[artifactTypes.TABLE]?.onDownload;
600
+ const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
601
+ if (!validConfig || !validColumns) {
602
+ return /* @__PURE__ */ jsxs4(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
603
+ /* @__PURE__ */ jsxs4(ArtifactHeader, { className: "bg-background/70", children: [
604
+ artifact.title ? /* @__PURE__ */ jsx10(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ jsx10("span", {}),
605
+ presignedUrl ? /* @__PURE__ */ jsx10(ArtifactActions, { children: /* @__PURE__ */ jsx10(
606
+ ArtifactDownloadButton,
607
+ {
608
+ href: presignedUrl,
609
+ label: resolvedLabels.download,
610
+ onClick: handleDownloadClick
611
+ }
612
+ ) }) : null
613
+ ] }),
614
+ /* @__PURE__ */ jsx10(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ jsx10(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
615
+ ] });
616
+ }
617
+ return (
618
+ // The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
619
+ // Disable the outer overflow container so only one scroll context exists — this prevents
620
+ // double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
621
+ /* @__PURE__ */ jsxs4(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
622
+ /* @__PURE__ */ jsxs4(ArtifactHeader, { className: "bg-background/70", children: [
623
+ artifact.title ? /* @__PURE__ */ jsx10(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ jsx10("span", {}),
624
+ /* @__PURE__ */ jsx10(ArtifactActions, { children: /* @__PURE__ */ jsx10(
625
+ ArtifactDownloadButton,
626
+ {
627
+ href: presignedUrl ?? "",
628
+ label: resolvedLabels.download,
629
+ onClick: handleDownloadClick
630
+ }
631
+ ) })
632
+ ] }),
633
+ /* @__PURE__ */ jsx10(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ jsx10(
634
+ TableArtifactContent,
635
+ {
636
+ columns: validColumns,
637
+ data,
638
+ knownRowCount: artifact.config.stats?.rowCount,
639
+ maxShimmerRows: MAX_SHIMMER_ROWS,
640
+ maxBodyHeight: TABLE_MAX_BODY_HEIGHT,
641
+ labels: resolvedLabels
642
+ }
643
+ ) })
644
+ ] })
645
+ );
646
+ }
647
+
648
+ // src/components/artifacts/chart-artifact/to-clipboard-text.ts
649
+ function chartArtifactToClipboardText(artifact) {
650
+ const trimmedTitle = artifact.title?.trim();
651
+ return trimmedTitle || "Chart";
652
+ }
653
+
654
+ // src/components/artifacts/artifact-services/chart-artifact-service.ts
655
+ var ChartArtifactService = {
656
+ type: artifactTypes.CHART,
657
+ Component: ChartArtifact,
658
+ toClipboardText: chartArtifactToClipboardText
659
+ };
660
+
661
+ // src/components/artifacts/table-artifact/to-clipboard-text.ts
662
+ function tableArtifactToClipboardText(artifact) {
663
+ const trimmedTitle = artifact.title?.trim();
664
+ return trimmedTitle || "Table";
665
+ }
666
+
667
+ // src/components/artifacts/artifact-services/table-artifact-service.ts
668
+ var TableArtifactService = {
669
+ type: artifactTypes.TABLE,
670
+ Component: TableArtifact,
671
+ toClipboardText: tableArtifactToClipboardText
672
+ };
673
+
674
+ // src/components/artifacts/artifact-services/index.ts
675
+ var ArtifactServices = {
676
+ [artifactTypes.TABLE]: TableArtifactService,
677
+ [artifactTypes.CHART]: ChartArtifactService
678
+ };
679
+ function artifactToClipboardText(artifact) {
680
+ const entry = ArtifactServices[artifact.type];
681
+ if (!entry) {
682
+ return `[Artifact: ${artifact.title ?? artifact.type}]`;
683
+ }
684
+ return entry.toClipboardText(artifact);
685
+ }
686
+
687
+ export {
688
+ artifactTypes,
689
+ DEFAULT_CHART_ARTIFACT_LABELS,
690
+ DEFAULT_TABLE_ARTIFACT_LABELS,
691
+ IconCheck,
692
+ IconCopy,
693
+ IconThumbDown,
694
+ IconThumbUp,
695
+ ArtifactDownloadButton,
696
+ isSafeDownloadUrl,
697
+ ChartArtifact,
698
+ TableArtifact,
699
+ ArtifactServices,
700
+ artifactToClipboardText
701
+ };
702
+ /*! Bundled license information:
703
+
704
+ @tabler/icons-react/dist/esm/defaultAttributes.mjs:
705
+ @tabler/icons-react/dist/esm/createReactComponent.mjs:
706
+ @tabler/icons-react/dist/esm/icons/IconCheck.mjs:
707
+ @tabler/icons-react/dist/esm/icons/IconCopy.mjs:
708
+ @tabler/icons-react/dist/esm/icons/IconDownload.mjs:
709
+ @tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
710
+ @tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
711
+ @tabler/icons-react/dist/esm/tabler-icons-react.mjs:
712
+ (**
713
+ * @license @tabler/icons-react v3.37.1 - MIT
714
+ *
715
+ * This source code is licensed under the MIT license.
716
+ * See the LICENSE file in the root directory of this source tree.
717
+ *)
718
+ */
719
+ //# sourceMappingURL=chunk-Z5JWF24N.js.map