@shapesos/clay 0.11.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 +858 -132
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.d.cts +38 -5
- package/dist/artifacts.d.ts +38 -5
- package/dist/artifacts.js +13 -3
- package/dist/blocks.cjs +1185 -467
- package/dist/blocks.cjs.map +1 -1
- package/dist/blocks.css +1 -1
- package/dist/blocks.d.cts +23 -10
- package/dist/blocks.d.ts +23 -10
- package/dist/blocks.js +6 -3
- 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/chat.cjs +1207 -489
- package/dist/chat.cjs.map +1 -1
- package/dist/chat.d.cts +3 -2
- package/dist/chat.d.ts +3 -2
- package/dist/chat.js +7 -4
- package/dist/{chunk-MXOPG747.js → chunk-36CB624W.js} +7 -7
- package/dist/chunk-36CB624W.js.map +1 -0
- package/dist/{chunk-L35M3OD5.js → chunk-4MZZH3WX.js} +5 -11
- 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-OUW6PUEB.js → chunk-FFX3CAOX.js} +7 -7
- 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-BX5TCEPR.js → chunk-Z5JWF24N.js} +388 -105
- package/dist/chunk-Z5JWF24N.js.map +1 -0
- package/dist/index.cjs +924 -198
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +23 -15
- package/dist/table.js +2 -1
- 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-DuuRI4ll.d.cts → types-DCutaXjZ.d.cts} +16 -1
- package/dist/{types-C9XX-Uhk.d.ts → types-uPfn67Dc.d.ts} +16 -1
- package/package.json +13 -1
- package/dist/chunk-BX5TCEPR.js.map +0 -1
- package/dist/chunk-L35M3OD5.js.map +0 -1
- package/dist/chunk-MEJESPTZ.js +0 -1
- package/dist/chunk-MXOPG747.js.map +0 -1
- package/dist/types-3Gzk7cRt.d.cts +0 -121
- package/dist/types-3Gzk7cRt.d.ts +0 -121
- /package/dist/{chunk-MEJESPTZ.js.map → chart.js.map} +0 -0
- /package/dist/{chunk-OUW6PUEB.js.map → chunk-FFX3CAOX.js.map} +0 -0
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BarChart,
|
|
3
|
+
LineChart,
|
|
4
|
+
PieChart
|
|
5
|
+
} from "./chunk-QXGYMDIA.js";
|
|
1
6
|
import {
|
|
2
7
|
Table,
|
|
3
8
|
TableBody,
|
|
@@ -5,16 +10,38 @@ import {
|
|
|
5
10
|
TableHead,
|
|
6
11
|
TableHeader,
|
|
7
12
|
TableRow,
|
|
8
|
-
cn,
|
|
9
13
|
useScrollShadow
|
|
10
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-4MZZH3WX.js";
|
|
15
|
+
import {
|
|
16
|
+
cn
|
|
17
|
+
} from "./chunk-P6GUNIAE.js";
|
|
11
18
|
import {
|
|
12
19
|
IconButton
|
|
13
20
|
} from "./chunk-OBOXCBDL.js";
|
|
14
21
|
|
|
15
|
-
// src/components/artifacts/
|
|
22
|
+
// src/components/artifacts/artifact-base.ts
|
|
16
23
|
var artifactTypes = {
|
|
17
|
-
TABLE: "TABLE"
|
|
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."
|
|
18
45
|
};
|
|
19
46
|
|
|
20
47
|
// node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
|
|
@@ -116,7 +143,12 @@ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
|
116
143
|
|
|
117
144
|
// src/components/artifacts/artifact-download-button/artifact-download-button.tsx
|
|
118
145
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
119
|
-
|
|
146
|
+
var DEFAULT_LABEL = "Download CSV";
|
|
147
|
+
function ArtifactDownloadButton({
|
|
148
|
+
href,
|
|
149
|
+
label = DEFAULT_LABEL,
|
|
150
|
+
onClick
|
|
151
|
+
}) {
|
|
120
152
|
if (!isSafeDownloadUrl(href)) return null;
|
|
121
153
|
return /* @__PURE__ */ jsx2(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
122
154
|
/* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(
|
|
@@ -126,12 +158,13 @@ function ArtifactDownloadButton({ href }) {
|
|
|
126
158
|
href,
|
|
127
159
|
download: true,
|
|
128
160
|
rel: "noopener noreferrer",
|
|
161
|
+
onClick,
|
|
129
162
|
icon: IconDownload,
|
|
130
163
|
size: "small",
|
|
131
|
-
"aria-label":
|
|
164
|
+
"aria-label": label
|
|
132
165
|
}
|
|
133
166
|
) }),
|
|
134
|
-
/* @__PURE__ */ jsx2(TooltipContent, { children:
|
|
167
|
+
/* @__PURE__ */ jsx2(TooltipContent, { children: label })
|
|
135
168
|
] }) });
|
|
136
169
|
}
|
|
137
170
|
function isSafeDownloadUrl(url) {
|
|
@@ -143,8 +176,8 @@ function isSafeDownloadUrl(url) {
|
|
|
143
176
|
}
|
|
144
177
|
}
|
|
145
178
|
|
|
146
|
-
// src/components/artifacts/
|
|
147
|
-
import { useEffect as useEffect2 } from "react";
|
|
179
|
+
// src/components/artifacts/chart-artifact/chart-artifact.tsx
|
|
180
|
+
import { useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
148
181
|
|
|
149
182
|
// src/components/ai-elements/artifact.tsx
|
|
150
183
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
@@ -160,7 +193,7 @@ var ArtifactTitle = ({ className, ...props }) => /* @__PURE__ */ jsx3("p", { cla
|
|
|
160
193
|
var ArtifactActions = ({ className, ...props }) => /* @__PURE__ */ jsx3("div", { className: cn("flex items-center gap-1", className), ...props });
|
|
161
194
|
var ArtifactContent = ({ className, ...props }) => /* @__PURE__ */ jsx3("div", { className: cn("flex-1 overflow-auto p-4", className), ...props });
|
|
162
195
|
|
|
163
|
-
// src/components/artifacts/
|
|
196
|
+
// src/components/artifacts/status-message.tsx
|
|
164
197
|
import { createElement as createElement2 } from "react";
|
|
165
198
|
function StatusMessage({ $tone, children }) {
|
|
166
199
|
return createElement2(
|
|
@@ -172,78 +205,136 @@ function StatusMessage({ $tone, children }) {
|
|
|
172
205
|
);
|
|
173
206
|
}
|
|
174
207
|
|
|
175
|
-
// src/components/artifacts/
|
|
176
|
-
var
|
|
177
|
-
LOADING: "loading",
|
|
178
|
-
READY: "ready",
|
|
179
|
-
ERROR: "error",
|
|
180
|
-
UNAVAILABLE: "unavailable"
|
|
181
|
-
};
|
|
208
|
+
// src/components/artifacts/chart-artifact/chart-variant-services/constants.ts
|
|
209
|
+
var VARIANT_CHART_HEIGHT = "100%";
|
|
182
210
|
|
|
183
|
-
// src/components/artifacts/
|
|
184
|
-
|
|
185
|
-
|
|
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
|
+
);
|
|
186
224
|
}
|
|
187
|
-
var HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
|
|
188
|
-
var CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
|
|
189
|
-
var ROW_CLASSES = "border-b-brown-30 bg-background/70 hover:bg-secondary";
|
|
190
|
-
var DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;
|
|
191
|
-
var SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
|
|
192
225
|
|
|
193
|
-
// src/components/artifacts/
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
columns,
|
|
197
|
-
data,
|
|
198
|
-
knownRowCount,
|
|
199
|
-
maxShimmerRows,
|
|
200
|
-
maxBodyHeight,
|
|
201
|
-
unavailableMessage
|
|
202
|
-
}) {
|
|
203
|
-
if (data.status === TABLE_STATUS.ERROR) {
|
|
204
|
-
return /* @__PURE__ */ jsx4(StatusMessage, { $tone: "error", children: "Couldn't load table data." });
|
|
205
|
-
}
|
|
206
|
-
if (data.status === TABLE_STATUS.UNAVAILABLE) {
|
|
207
|
-
return /* @__PURE__ */ jsx4(StatusMessage, { $tone: "info", children: unavailableMessage });
|
|
208
|
-
}
|
|
209
|
-
if (data.status === TABLE_STATUS.LOADING) {
|
|
210
|
-
if (typeof knownRowCount === "number" && knownRowCount > 0) {
|
|
211
|
-
const shimmerCount = Math.min(knownRowCount, maxShimmerRows);
|
|
212
|
-
return /* @__PURE__ */ jsx4(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
|
|
213
|
-
}
|
|
214
|
-
return /* @__PURE__ */ jsx4(StatusMessage, { $tone: "info", children: "Loading table\u2026" });
|
|
215
|
-
}
|
|
216
|
-
return /* @__PURE__ */ jsx4(ArtifactTable, { columns, maxBodyHeight, children: data.rows.length === 0 ? renderEmptyRow(columns.length) : renderDataRows(columns, data.rows) });
|
|
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)];
|
|
217
229
|
}
|
|
218
|
-
function
|
|
219
|
-
|
|
220
|
-
return /* @__PURE__ */ jsx4("div", { ref: targetRef, className: "overscroll-none", style: { maxHeight: maxBodyHeight, overflowY: "auto" }, children: /* @__PURE__ */ jsxs2(Table, { containerClassName: "overflow-visible", children: [
|
|
221
|
-
/* @__PURE__ */ jsx4(
|
|
222
|
-
TableHeader,
|
|
223
|
-
{
|
|
224
|
-
"data-scrolled": isScrolled ? "true" : void 0,
|
|
225
|
-
className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
|
|
226
|
-
style: isScrolled ? { boxShadow: SCROLL_SHADOW } : void 0,
|
|
227
|
-
children: /* @__PURE__ */ jsx4(TableRow, { className: "hover:bg-transparent", children: columns.map((column) => /* @__PURE__ */ jsx4(TableHead, { scope: "col", className: HEAD_CLASS, children: column.label }, column.key)) })
|
|
228
|
-
}
|
|
229
|
-
),
|
|
230
|
-
/* @__PURE__ */ jsx4(TableBody, { children })
|
|
231
|
-
] }) });
|
|
230
|
+
function pieColumnKeys(config) {
|
|
231
|
+
return [config.categoryKey, config.valueKey];
|
|
232
232
|
}
|
|
233
|
-
|
|
234
|
-
|
|
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;
|
|
235
241
|
}
|
|
236
|
-
|
|
237
|
-
|
|
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;
|
|
238
252
|
}
|
|
239
|
-
|
|
240
|
-
|
|
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 });
|
|
241
264
|
}
|
|
242
265
|
|
|
243
|
-
// src/components/artifacts/
|
|
244
|
-
|
|
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
|
+
}
|
|
245
301
|
|
|
246
|
-
// src/components/artifacts/
|
|
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
|
|
247
338
|
import Papa from "papaparse";
|
|
248
339
|
function parseCsv(text, columns) {
|
|
249
340
|
const result = Papa.parse(text, {
|
|
@@ -253,6 +344,7 @@ function parseCsv(text, columns) {
|
|
|
253
344
|
});
|
|
254
345
|
const csvHeaders = new Set(result.meta?.fields ?? []);
|
|
255
346
|
const presentColumns = columns.filter((col) => csvHeaders.has(col.key));
|
|
347
|
+
if (presentColumns.length === 0) return [];
|
|
256
348
|
return result.data.map((rawRow) => {
|
|
257
349
|
const row = {};
|
|
258
350
|
for (const column of presentColumns) {
|
|
@@ -263,21 +355,27 @@ function parseCsv(text, columns) {
|
|
|
263
355
|
});
|
|
264
356
|
}
|
|
265
357
|
|
|
266
|
-
// src/components/artifacts/
|
|
358
|
+
// src/components/artifacts/use-rows-artifact-data.ts
|
|
359
|
+
import { useEffect, useMemo, useState } from "react";
|
|
267
360
|
var LOADING = { status: "loading", rows: null, error: null };
|
|
268
361
|
var UNAVAILABLE = { status: "unavailable", rows: null, error: null };
|
|
269
362
|
var INITIAL_INTERNAL = { cacheKey: null, data: LOADING };
|
|
270
363
|
function columnsFingerprint(columns) {
|
|
271
|
-
return columns.map((c) =>
|
|
364
|
+
return columns.map((c) => c.key).join("|");
|
|
272
365
|
}
|
|
273
|
-
function
|
|
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) {
|
|
274
371
|
const colsKey = useMemo(() => columnsFingerprint(columns), [columns]);
|
|
275
|
-
const
|
|
372
|
+
const safeUrl = presignedUrl && isSafeDownloadUrl(presignedUrl) ? presignedUrl : null;
|
|
373
|
+
const cacheKey = safeUrl ? `${safeUrl}::${colsKey}` : null;
|
|
276
374
|
const [state, setState] = useState(INITIAL_INTERNAL);
|
|
277
375
|
useEffect(() => {
|
|
278
|
-
if (!
|
|
376
|
+
if (!safeUrl) return;
|
|
279
377
|
const controller = new AbortController();
|
|
280
|
-
fetch(
|
|
378
|
+
fetch(safeUrl, {
|
|
281
379
|
signal: controller.signal,
|
|
282
380
|
headers: { Accept: "text/csv" },
|
|
283
381
|
// Presigned URLs are cross-origin S3 in production and don't need credentials. Explicit
|
|
@@ -285,33 +383,182 @@ function useTableArtifactData(presignedUrl, columns) {
|
|
|
285
383
|
// session cookies or auth headers.
|
|
286
384
|
credentials: "omit"
|
|
287
385
|
}).then(async (response) => {
|
|
288
|
-
if (!response.ok) throw new Error(`Failed to load
|
|
386
|
+
if (!response.ok) throw new Error(`Failed to load artifact data (${response.status})`);
|
|
289
387
|
return response.text();
|
|
290
388
|
}).then((text) => {
|
|
291
389
|
if (controller.signal.aborted) return;
|
|
292
390
|
try {
|
|
293
|
-
const rows =
|
|
294
|
-
setState({ cacheKey: `${
|
|
391
|
+
const rows = parse(text, columns);
|
|
392
|
+
setState({ cacheKey: `${safeUrl}::${colsKey}`, data: { status: "ready", rows, error: null } });
|
|
295
393
|
} catch (parseError) {
|
|
296
|
-
console.error("[TableArtifact] CSV parse failed", parseError);
|
|
297
394
|
const err = parseError instanceof Error ? parseError : new Error(String(parseError));
|
|
298
|
-
|
|
395
|
+
console.error("[ArtifactData] CSV parse failed:", err.message);
|
|
396
|
+
setState({ cacheKey: `${safeUrl}::${colsKey}`, data: { status: "error", rows: null, error: err } });
|
|
299
397
|
}
|
|
300
398
|
}).catch((error) => {
|
|
301
399
|
if (controller.signal.aborted) return;
|
|
302
|
-
console.error("[TableArtifact] Fetch failed", error);
|
|
303
400
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
304
|
-
|
|
401
|
+
console.error(`[ArtifactData] Fetch failed [${scrubUrl(safeUrl)}]:`, err.message);
|
|
402
|
+
setState({ cacheKey: `${safeUrl}::${colsKey}`, data: { status: "error", rows: null, error: err } });
|
|
305
403
|
});
|
|
306
404
|
return () => {
|
|
307
405
|
controller.abort();
|
|
308
406
|
};
|
|
309
|
-
}, [
|
|
310
|
-
if (!
|
|
407
|
+
}, [safeUrl, colsKey]);
|
|
408
|
+
if (!safeUrl) return UNAVAILABLE;
|
|
311
409
|
if (state.cacheKey !== cacheKey) return LOADING;
|
|
312
410
|
return state.data;
|
|
313
411
|
}
|
|
314
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
|
+
|
|
315
562
|
// src/components/artifacts/table-artifact/validate.ts
|
|
316
563
|
function isValidTableConfig(config) {
|
|
317
564
|
if (!config || typeof config !== "object") return false;
|
|
@@ -329,42 +576,61 @@ function isValidTableColumn(column) {
|
|
|
329
576
|
}
|
|
330
577
|
|
|
331
578
|
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
332
|
-
import { jsx as
|
|
333
|
-
var
|
|
579
|
+
import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
580
|
+
var TITLE_CLASSES2 = "text-sm font-semibold text-foreground";
|
|
334
581
|
var TABLE_MAX_BODY_HEIGHT = 480;
|
|
335
582
|
var MAX_SHIMMER_ROWS = 10;
|
|
336
|
-
|
|
337
|
-
function TableArtifact({ artifact }) {
|
|
583
|
+
function TableArtifact({ artifact, labels, callbacks }) {
|
|
338
584
|
const validConfig = isValidTableConfig(artifact.config);
|
|
339
585
|
const validColumns = validConfig ? artifact.config.columns : null;
|
|
340
|
-
|
|
586
|
+
useEffect3(() => {
|
|
341
587
|
if (validConfig) return;
|
|
342
588
|
console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
|
|
343
589
|
}, [validConfig]);
|
|
590
|
+
const resolvedLabels = useMemo3(
|
|
591
|
+
() => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels?.[artifactTypes.TABLE] ?? {} }),
|
|
592
|
+
[labels]
|
|
593
|
+
);
|
|
344
594
|
const data = useTableArtifactData(
|
|
345
595
|
validConfig ? artifact.protectedAsset?.presignedUrl ?? null : null,
|
|
346
596
|
validColumns ?? []
|
|
347
597
|
);
|
|
348
598
|
const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
|
|
599
|
+
const onDownload = callbacks?.[artifactTypes.TABLE]?.onDownload;
|
|
600
|
+
const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
|
|
349
601
|
if (!validConfig || !validColumns) {
|
|
350
|
-
return /* @__PURE__ */
|
|
351
|
-
/* @__PURE__ */
|
|
352
|
-
artifact.title ? /* @__PURE__ */
|
|
353
|
-
presignedUrl ? /* @__PURE__ */
|
|
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
|
|
354
613
|
] }),
|
|
355
|
-
/* @__PURE__ */
|
|
614
|
+
/* @__PURE__ */ jsx10(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ jsx10(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
|
|
356
615
|
] });
|
|
357
616
|
}
|
|
358
617
|
return (
|
|
359
618
|
// The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
|
|
360
619
|
// Disable the outer overflow container so only one scroll context exists — this prevents
|
|
361
620
|
// double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
|
|
362
|
-
/* @__PURE__ */
|
|
363
|
-
/* @__PURE__ */
|
|
364
|
-
artifact.title ? /* @__PURE__ */
|
|
365
|
-
/* @__PURE__ */
|
|
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
|
+
) })
|
|
366
632
|
] }),
|
|
367
|
-
/* @__PURE__ */
|
|
633
|
+
/* @__PURE__ */ jsx10(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ jsx10(
|
|
368
634
|
TableArtifactContent,
|
|
369
635
|
{
|
|
370
636
|
columns: validColumns,
|
|
@@ -372,13 +638,26 @@ function TableArtifact({ artifact }) {
|
|
|
372
638
|
knownRowCount: artifact.config.stats?.rowCount,
|
|
373
639
|
maxShimmerRows: MAX_SHIMMER_ROWS,
|
|
374
640
|
maxBodyHeight: TABLE_MAX_BODY_HEIGHT,
|
|
375
|
-
|
|
641
|
+
labels: resolvedLabels
|
|
376
642
|
}
|
|
377
643
|
) })
|
|
378
644
|
] })
|
|
379
645
|
);
|
|
380
646
|
}
|
|
381
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
|
+
|
|
382
661
|
// src/components/artifacts/table-artifact/to-clipboard-text.ts
|
|
383
662
|
function tableArtifactToClipboardText(artifact) {
|
|
384
663
|
const trimmedTitle = artifact.title?.trim();
|
|
@@ -394,7 +673,8 @@ var TableArtifactService = {
|
|
|
394
673
|
|
|
395
674
|
// src/components/artifacts/artifact-services/index.ts
|
|
396
675
|
var ArtifactServices = {
|
|
397
|
-
[artifactTypes.TABLE]: TableArtifactService
|
|
676
|
+
[artifactTypes.TABLE]: TableArtifactService,
|
|
677
|
+
[artifactTypes.CHART]: ChartArtifactService
|
|
398
678
|
};
|
|
399
679
|
function artifactToClipboardText(artifact) {
|
|
400
680
|
const entry = ArtifactServices[artifact.type];
|
|
@@ -406,12 +686,15 @@ function artifactToClipboardText(artifact) {
|
|
|
406
686
|
|
|
407
687
|
export {
|
|
408
688
|
artifactTypes,
|
|
689
|
+
DEFAULT_CHART_ARTIFACT_LABELS,
|
|
690
|
+
DEFAULT_TABLE_ARTIFACT_LABELS,
|
|
409
691
|
IconCheck,
|
|
410
692
|
IconCopy,
|
|
411
693
|
IconThumbDown,
|
|
412
694
|
IconThumbUp,
|
|
413
695
|
ArtifactDownloadButton,
|
|
414
696
|
isSafeDownloadUrl,
|
|
697
|
+
ChartArtifact,
|
|
415
698
|
TableArtifact,
|
|
416
699
|
ArtifactServices,
|
|
417
700
|
artifactToClipboardText
|
|
@@ -433,4 +716,4 @@ export {
|
|
|
433
716
|
* See the LICENSE file in the root directory of this source tree.
|
|
434
717
|
*)
|
|
435
718
|
*/
|
|
436
|
-
//# sourceMappingURL=chunk-
|
|
719
|
+
//# sourceMappingURL=chunk-Z5JWF24N.js.map
|