@shapesos/clay 0.12.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/artifacts.cjs +695 -246
- package/dist/artifacts.cjs.map +1 -1
- package/dist/artifacts.d.cts +133 -5
- package/dist/artifacts.d.ts +133 -5
- package/dist/artifacts.js +7 -2
- package/dist/blocks.cjs +717 -259
- package/dist/blocks.cjs.map +1 -1
- package/dist/blocks.css +1 -1
- package/dist/blocks.d.cts +8 -10
- package/dist/blocks.d.ts +8 -10
- package/dist/blocks.js +3 -2
- package/dist/capture.cjs +220 -0
- package/dist/capture.cjs.map +1 -0
- package/dist/capture.d.cts +113 -0
- package/dist/capture.d.ts +113 -0
- package/dist/capture.js +17 -0
- package/dist/chat.cjs +736 -287
- package/dist/chat.cjs.map +1 -1
- package/dist/chat.d.cts +2 -2
- package/dist/chat.d.ts +2 -2
- package/dist/chat.js +4 -3
- package/dist/{chunk-Z5JWF24N.js → chunk-DT44KNCV.js} +367 -82
- package/dist/chunk-DT44KNCV.js.map +1 -0
- package/dist/chunk-JAGNXEWK.js +116 -0
- package/dist/chunk-JAGNXEWK.js.map +1 -0
- package/dist/chunk-LXYCT4YO.js +7 -0
- package/dist/chunk-LXYCT4YO.js.map +1 -0
- package/dist/{chunk-36CB624W.js → chunk-QAK7NM5F.js} +15 -3
- package/dist/chunk-QAK7NM5F.js.map +1 -0
- package/dist/chunk-RSRNSWJN.js +1 -0
- package/dist/chunk-RSRNSWJN.js.map +1 -0
- package/dist/{chunk-FFX3CAOX.js → chunk-YSSLTXZG.js} +3 -3
- package/dist/dom-to-image-NATF3446.js +21 -0
- package/dist/dom-to-image-NATF3446.js.map +1 -0
- package/dist/index.cjs +775 -317
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +9 -4
- package/dist/{types-C0BvwliI.d.cts → types-BzXPBy6s.d.cts} +39 -41
- package/dist/{types-uPfn67Dc.d.ts → types-CW45GBXl.d.cts} +25 -13
- package/dist/{types-DCutaXjZ.d.cts → types-D1b8v7EY.d.ts} +25 -13
- package/dist/{types-C5bFH4v3.d.ts → types-GCkXbyFm.d.ts} +39 -41
- package/package.json +12 -2
- package/dist/chunk-36CB624W.js.map +0 -1
- package/dist/chunk-AQEJRMRN.js +0 -1
- package/dist/chunk-Z5JWF24N.js.map +0 -1
- /package/dist/{chunk-AQEJRMRN.js.map → capture.js.map} +0 -0
- /package/dist/{chunk-FFX3CAOX.js.map → chunk-YSSLTXZG.js.map} +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CAPTURE_EXCLUDE_ATTRIBUTE
|
|
3
|
+
} from "./chunk-LXYCT4YO.js";
|
|
1
4
|
import {
|
|
2
5
|
BarChart,
|
|
3
6
|
LineChart,
|
|
@@ -27,7 +30,10 @@ var artifactTypes = {
|
|
|
27
30
|
|
|
28
31
|
// src/components/artifacts/chart-artifact/types.ts
|
|
29
32
|
var DEFAULT_CHART_ARTIFACT_LABELS = {
|
|
30
|
-
download: "Download
|
|
33
|
+
download: "Download",
|
|
34
|
+
downloadCsv: "Download CSV",
|
|
35
|
+
downloadPng: "Download PNG",
|
|
36
|
+
copyAsImage: "Copy Image",
|
|
31
37
|
unavailable: "Chart data is unavailable.",
|
|
32
38
|
loadError: "Couldn't load chart data.",
|
|
33
39
|
loading: "Loading chart\u2026",
|
|
@@ -100,25 +106,44 @@ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
|
|
|
100
106
|
return Component;
|
|
101
107
|
};
|
|
102
108
|
|
|
109
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs
|
|
110
|
+
var __iconNode = [["path", { "d": "M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0", "key": "svg-0" }], ["path", { "d": "M12 8v4", "key": "svg-1" }], ["path", { "d": "M12 16h.01", "key": "svg-2" }]];
|
|
111
|
+
var IconAlertCircle = createReactComponent("outline", "alert-circle", "AlertCircle", __iconNode);
|
|
112
|
+
|
|
103
113
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
|
|
104
|
-
var
|
|
105
|
-
var IconCheck = createReactComponent("outline", "check", "Check",
|
|
114
|
+
var __iconNode2 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
|
|
115
|
+
var IconCheck = createReactComponent("outline", "check", "Check", __iconNode2);
|
|
106
116
|
|
|
107
117
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
|
|
108
|
-
var
|
|
109
|
-
var IconCopy = createReactComponent("outline", "copy", "Copy",
|
|
118
|
+
var __iconNode3 = [["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" }]];
|
|
119
|
+
var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode3);
|
|
110
120
|
|
|
111
121
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconDownload.mjs
|
|
112
|
-
var
|
|
113
|
-
var IconDownload = createReactComponent("outline", "download", "Download",
|
|
122
|
+
var __iconNode4 = [["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" }]];
|
|
123
|
+
var IconDownload = createReactComponent("outline", "download", "Download", __iconNode4);
|
|
124
|
+
|
|
125
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs
|
|
126
|
+
var __iconNode5 = [["path", { "d": "M14 3v4a1 1 0 0 0 1 1h4", "key": "svg-0" }], ["path", { "d": "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2", "key": "svg-1" }], ["path", { "d": "M8 11h8v7h-8l0 -7", "key": "svg-2" }], ["path", { "d": "M8 15h8", "key": "svg-3" }], ["path", { "d": "M11 11v7", "key": "svg-4" }]];
|
|
127
|
+
var IconFileSpreadsheet = createReactComponent("outline", "file-spreadsheet", "FileSpreadsheet", __iconNode5);
|
|
128
|
+
|
|
129
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconLoader2.mjs
|
|
130
|
+
var __iconNode6 = [["path", { "d": "M12 3a9 9 0 1 0 9 9", "key": "svg-0" }]];
|
|
131
|
+
var IconLoader2 = createReactComponent("outline", "loader-2", "Loader2", __iconNode6);
|
|
132
|
+
|
|
133
|
+
// node_modules/@tabler/icons-react/dist/esm/icons/IconPhoto.mjs
|
|
134
|
+
var __iconNode7 = [["path", { "d": "M15 8h.01", "key": "svg-0" }], ["path", { "d": "M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12", "key": "svg-1" }], ["path", { "d": "M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5", "key": "svg-2" }], ["path", { "d": "M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3", "key": "svg-3" }]];
|
|
135
|
+
var IconPhoto = createReactComponent("outline", "photo", "Photo", __iconNode7);
|
|
114
136
|
|
|
115
137
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
|
|
116
|
-
var
|
|
117
|
-
var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown",
|
|
138
|
+
var __iconNode8 = [["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" }]];
|
|
139
|
+
var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode8);
|
|
118
140
|
|
|
119
141
|
// node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
|
|
120
|
-
var
|
|
121
|
-
var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp",
|
|
142
|
+
var __iconNode9 = [["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" }]];
|
|
143
|
+
var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode9);
|
|
144
|
+
|
|
145
|
+
// src/components/artifacts/artifact-copy-as-image-button/artifact-copy-as-image-button.tsx
|
|
146
|
+
import { useCallback as useCallback2 } from "react";
|
|
122
147
|
|
|
123
148
|
// src/components/ui/tooltip.tsx
|
|
124
149
|
import * as React from "react";
|
|
@@ -141,17 +166,119 @@ var TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props },
|
|
|
141
166
|
));
|
|
142
167
|
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
143
168
|
|
|
144
|
-
// src/components/artifacts/artifact-
|
|
169
|
+
// src/components/artifacts/artifact-copy-as-image-button/use-copy-as-image.ts
|
|
170
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
171
|
+
var DEFAULT_RESET_AFTER_MS = 1500;
|
|
172
|
+
function useCopyAsImage(targetRef, options = {}) {
|
|
173
|
+
const [status, setStatus] = useState("idle");
|
|
174
|
+
const [error, setError] = useState(null);
|
|
175
|
+
const resetTimerRef = useRef(null);
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
return () => {
|
|
178
|
+
if (resetTimerRef.current !== null) clearTimeout(resetTimerRef.current);
|
|
179
|
+
};
|
|
180
|
+
}, []);
|
|
181
|
+
const copy = useCallback(async () => {
|
|
182
|
+
if (resetTimerRef.current !== null) {
|
|
183
|
+
clearTimeout(resetTimerRef.current);
|
|
184
|
+
resetTimerRef.current = null;
|
|
185
|
+
}
|
|
186
|
+
const { resetAfterMs = DEFAULT_RESET_AFTER_MS, ...nodeOptions } = options;
|
|
187
|
+
const scheduleReset = () => {
|
|
188
|
+
if (resetAfterMs <= 0) return;
|
|
189
|
+
resetTimerRef.current = setTimeout(() => {
|
|
190
|
+
resetTimerRef.current = null;
|
|
191
|
+
setStatus("idle");
|
|
192
|
+
setError(null);
|
|
193
|
+
}, resetAfterMs);
|
|
194
|
+
};
|
|
195
|
+
const node = targetRef.current;
|
|
196
|
+
if (!node) {
|
|
197
|
+
const err = new Error("ArtifactCopyAsImageButton: target ref is not attached to a DOM node.");
|
|
198
|
+
setError(err);
|
|
199
|
+
setStatus("error");
|
|
200
|
+
scheduleReset();
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
203
|
+
setError(null);
|
|
204
|
+
setStatus("working");
|
|
205
|
+
try {
|
|
206
|
+
const { copyNodeAsPng } = await import("./dom-to-image-NATF3446.js");
|
|
207
|
+
await copyNodeAsPng(node, nodeOptions);
|
|
208
|
+
setStatus("success");
|
|
209
|
+
scheduleReset();
|
|
210
|
+
} catch (err) {
|
|
211
|
+
const wrapped = err instanceof Error ? err : new Error(String(err));
|
|
212
|
+
setError(wrapped);
|
|
213
|
+
setStatus("error");
|
|
214
|
+
scheduleReset();
|
|
215
|
+
throw wrapped;
|
|
216
|
+
}
|
|
217
|
+
}, [targetRef, options]);
|
|
218
|
+
return { status, error, copy };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// src/components/artifacts/artifact-copy-as-image-button/artifact-copy-as-image-button.tsx
|
|
145
222
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
146
|
-
var
|
|
147
|
-
function
|
|
148
|
-
|
|
223
|
+
var MAX_ERROR_MESSAGE_CHARS = 120;
|
|
224
|
+
function truncateErrorMessage(message, max = MAX_ERROR_MESSAGE_CHARS) {
|
|
225
|
+
return message.length <= max ? message : `${message.slice(0, max - 1)}\u2026`;
|
|
226
|
+
}
|
|
227
|
+
var DEFAULT_LABEL = "Copy Image";
|
|
228
|
+
var ICON_BY_STATUS = {
|
|
229
|
+
// `IconCopy` reads as the clipboard-copy affordance (action-shaped), distinct from the
|
|
230
|
+
// download menu's format-shaped icons. The button only ever puts bytes on the clipboard, so
|
|
231
|
+
// the visual signal stays consistent across copy-aware artifact types.
|
|
232
|
+
idle: IconCopy,
|
|
233
|
+
working: IconLoader2,
|
|
234
|
+
success: IconCheck,
|
|
235
|
+
error: IconAlertCircle
|
|
236
|
+
};
|
|
237
|
+
var TRANSIENT_TOOLTIP_BY_STATUS = {
|
|
238
|
+
working: "Copying\u2026",
|
|
239
|
+
success: "Copied",
|
|
240
|
+
error: "Copy failed"
|
|
241
|
+
};
|
|
242
|
+
function ArtifactCopyAsImageButton({
|
|
243
|
+
targetRef,
|
|
149
244
|
label = DEFAULT_LABEL,
|
|
245
|
+
disabled = false,
|
|
150
246
|
onClick
|
|
151
247
|
}) {
|
|
152
|
-
|
|
248
|
+
const { status, error, copy } = useCopyAsImage(targetRef);
|
|
249
|
+
const handleClick = useCallback2(() => {
|
|
250
|
+
onClick?.();
|
|
251
|
+
copy().catch((err) => {
|
|
252
|
+
console.warn("[clay] ArtifactCopyAsImageButton: copy failed", err);
|
|
253
|
+
});
|
|
254
|
+
}, [copy, onClick]);
|
|
255
|
+
const statusLabel = status === "idle" ? label : status === "error" && error ? `Copy failed: ${truncateErrorMessage(error.message)}` : TRANSIENT_TOOLTIP_BY_STATUS[status] ?? label;
|
|
153
256
|
return /* @__PURE__ */ jsx2(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
154
257
|
/* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx2(
|
|
258
|
+
IconButton,
|
|
259
|
+
{
|
|
260
|
+
icon: ICON_BY_STATUS[status],
|
|
261
|
+
size: "small",
|
|
262
|
+
onClick: handleClick,
|
|
263
|
+
disabled: disabled || status === "working",
|
|
264
|
+
"aria-label": statusLabel
|
|
265
|
+
}
|
|
266
|
+
) }),
|
|
267
|
+
/* @__PURE__ */ jsx2(TooltipContent, { children: statusLabel })
|
|
268
|
+
] }) });
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/components/artifacts/artifact-download-button/artifact-download-button.tsx
|
|
272
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
273
|
+
var DEFAULT_LABEL2 = "Download CSV";
|
|
274
|
+
function ArtifactDownloadButton({
|
|
275
|
+
href,
|
|
276
|
+
label = DEFAULT_LABEL2,
|
|
277
|
+
onClick
|
|
278
|
+
}) {
|
|
279
|
+
if (!isSafeDownloadUrl(href)) return null;
|
|
280
|
+
return /* @__PURE__ */ jsx3(TooltipProvider, { children: /* @__PURE__ */ jsxs2(Tooltip, { children: [
|
|
281
|
+
/* @__PURE__ */ jsx3(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx3(
|
|
155
282
|
IconButton,
|
|
156
283
|
{
|
|
157
284
|
as: "a",
|
|
@@ -164,7 +291,7 @@ function ArtifactDownloadButton({
|
|
|
164
291
|
"aria-label": label
|
|
165
292
|
}
|
|
166
293
|
) }),
|
|
167
|
-
/* @__PURE__ */
|
|
294
|
+
/* @__PURE__ */ jsx3(TooltipContent, { children: label })
|
|
168
295
|
] }) });
|
|
169
296
|
}
|
|
170
297
|
function isSafeDownloadUrl(url) {
|
|
@@ -176,22 +303,135 @@ function isSafeDownloadUrl(url) {
|
|
|
176
303
|
}
|
|
177
304
|
}
|
|
178
305
|
|
|
306
|
+
// src/components/artifacts/artifact-download-menu/artifact-download-menu.tsx
|
|
307
|
+
import { useCallback as useCallback3 } from "react";
|
|
308
|
+
|
|
309
|
+
// src/components/ui/dropdown-menu.tsx
|
|
310
|
+
import * as React2 from "react";
|
|
311
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
312
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
313
|
+
var DropdownMenu = DropdownMenuPrimitive.Root;
|
|
314
|
+
var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
315
|
+
var DropdownMenuContent = React2.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx4(
|
|
316
|
+
DropdownMenuPrimitive.Content,
|
|
317
|
+
{
|
|
318
|
+
ref,
|
|
319
|
+
sideOffset,
|
|
320
|
+
className: cn(
|
|
321
|
+
// Stacking is consumer-configurable via the `--z-popover` CSS variable (default `99999`,
|
|
322
|
+
// declared in clay's generated `_theme-tokens.css` :root block). Consumers whose chat or
|
|
323
|
+
// modal layer sits even higher override on their own root once:
|
|
324
|
+
// :root { --z-popover: 9999999; }
|
|
325
|
+
// and every clay floating surface picks the new value up via cascade. The fallback in
|
|
326
|
+
// `var(...,99999)` only kicks in if the consumer also strips the clay stylesheet — which
|
|
327
|
+
// they shouldn't, but the safety net costs nothing.
|
|
328
|
+
"z-[var(--z-popover,99999)] min-w-[10rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
|
|
329
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
330
|
+
"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",
|
|
331
|
+
className
|
|
332
|
+
),
|
|
333
|
+
...props
|
|
334
|
+
}
|
|
335
|
+
) }));
|
|
336
|
+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
337
|
+
var DropdownMenuItem = React2.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx4(
|
|
338
|
+
DropdownMenuPrimitive.Item,
|
|
339
|
+
{
|
|
340
|
+
ref,
|
|
341
|
+
className: cn(
|
|
342
|
+
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors",
|
|
343
|
+
"focus:bg-accent focus:text-accent-foreground",
|
|
344
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
345
|
+
"[&_svg]:size-4 [&_svg]:shrink-0",
|
|
346
|
+
inset && "pl-8",
|
|
347
|
+
className
|
|
348
|
+
),
|
|
349
|
+
...props
|
|
350
|
+
}
|
|
351
|
+
));
|
|
352
|
+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
353
|
+
var DropdownMenuSeparator = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Separator, { ref, className: cn("-mx-1 my-1 h-px bg-muted", className), ...props }));
|
|
354
|
+
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
|
355
|
+
var DropdownMenuLabel = React2.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx4(
|
|
356
|
+
DropdownMenuPrimitive.Label,
|
|
357
|
+
{
|
|
358
|
+
ref,
|
|
359
|
+
className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
|
|
360
|
+
...props
|
|
361
|
+
}
|
|
362
|
+
));
|
|
363
|
+
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
|
364
|
+
|
|
365
|
+
// src/components/artifacts/artifact-download-menu/artifact-download-menu.tsx
|
|
366
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
367
|
+
var DEFAULT_TRIGGER_LABEL = "Download";
|
|
368
|
+
var DEFAULT_CSV_LABEL = "Download CSV";
|
|
369
|
+
var DEFAULT_PNG_LABEL = "Download PNG";
|
|
370
|
+
var DEFAULT_PNG_BASENAME = "artifact";
|
|
371
|
+
function ArtifactDownloadMenu({
|
|
372
|
+
actions,
|
|
373
|
+
triggerLabel = DEFAULT_TRIGGER_LABEL
|
|
374
|
+
}) {
|
|
375
|
+
const { csv, png } = actions;
|
|
376
|
+
const showCsv = csv !== void 0 && isSafeDownloadUrl(csv.href);
|
|
377
|
+
const showPng = png !== void 0;
|
|
378
|
+
const handlePngSelect = useCallback3(async () => {
|
|
379
|
+
if (!png) return;
|
|
380
|
+
png.onSelect?.();
|
|
381
|
+
const node = png.targetRef.current;
|
|
382
|
+
if (!node) return;
|
|
383
|
+
const filename = `${png.filename ?? DEFAULT_PNG_BASENAME}.png`;
|
|
384
|
+
try {
|
|
385
|
+
const { downloadNodeAsPng } = await import("./dom-to-image-NATF3446.js");
|
|
386
|
+
await downloadNodeAsPng(node, filename);
|
|
387
|
+
} catch (err) {
|
|
388
|
+
console.warn("[clay] ArtifactDownloadMenu: PNG download failed", err);
|
|
389
|
+
}
|
|
390
|
+
}, [png]);
|
|
391
|
+
return /* @__PURE__ */ jsxs3(DropdownMenu, { children: [
|
|
392
|
+
/* @__PURE__ */ jsx5(TooltipProvider, { children: /* @__PURE__ */ jsxs3(Tooltip, { children: [
|
|
393
|
+
/* @__PURE__ */ jsx5(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx5(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx5(IconButton, { icon: IconDownload, size: "small", "aria-label": triggerLabel }) }) }),
|
|
394
|
+
/* @__PURE__ */ jsx5(TooltipContent, { children: triggerLabel })
|
|
395
|
+
] }) }),
|
|
396
|
+
/* @__PURE__ */ jsxs3(DropdownMenuContent, { align: "end", children: [
|
|
397
|
+
showCsv ? (
|
|
398
|
+
// `asChild` lets Radix render the item as our anchor — the browser handles the
|
|
399
|
+
// download natively and respects `Content-Disposition`. The analytics callback rides
|
|
400
|
+
// on the anchor's own `onClick` (rather than Radix's `onSelect`) so the same handler
|
|
401
|
+
// fires whether the user mouse-clicks the item, hits Enter on it, or activates it via
|
|
402
|
+
// touch — `onSelect` is reliable only for keyboard activation when `asChild` is in use.
|
|
403
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs3("a", { href: csv.href, download: true, rel: "noopener noreferrer", onClick: csv.onSelect, children: [
|
|
404
|
+
/* @__PURE__ */ jsx5(IconFileSpreadsheet, {}),
|
|
405
|
+
csv.label ?? DEFAULT_CSV_LABEL
|
|
406
|
+
] }) })
|
|
407
|
+
) : null,
|
|
408
|
+
showPng ? /* @__PURE__ */ jsxs3(DropdownMenuItem, { onSelect: handlePngSelect, disabled: png.disabled ?? false, children: [
|
|
409
|
+
/* @__PURE__ */ jsx5(IconPhoto, {}),
|
|
410
|
+
png.label ?? DEFAULT_PNG_LABEL
|
|
411
|
+
] }) : null
|
|
412
|
+
] })
|
|
413
|
+
] });
|
|
414
|
+
}
|
|
415
|
+
|
|
179
416
|
// src/components/artifacts/chart-artifact/chart-artifact.tsx
|
|
180
|
-
import { useEffect as
|
|
417
|
+
import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2 } from "react";
|
|
181
418
|
|
|
182
419
|
// src/components/ai-elements/artifact.tsx
|
|
183
|
-
import {
|
|
184
|
-
|
|
420
|
+
import { forwardRef as forwardRef4 } from "react";
|
|
421
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
422
|
+
var Artifact = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
|
|
185
423
|
"div",
|
|
186
424
|
{
|
|
425
|
+
ref,
|
|
187
426
|
className: cn("flex flex-col overflow-hidden rounded-lg border bg-background shadow-sm", className),
|
|
188
427
|
...props
|
|
189
428
|
}
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
var
|
|
193
|
-
var
|
|
194
|
-
var
|
|
429
|
+
));
|
|
430
|
+
Artifact.displayName = "Artifact";
|
|
431
|
+
var ArtifactHeader = ({ className, ...props }) => /* @__PURE__ */ jsx6("div", { className: cn("flex items-center justify-between border-b bg-muted/50 px-4 py-3", className), ...props });
|
|
432
|
+
var ArtifactTitle = ({ className, ...props }) => /* @__PURE__ */ jsx6("p", { className: cn("font-medium text-foreground text-sm", className), ...props });
|
|
433
|
+
var ArtifactActions = ({ className, ...props }) => /* @__PURE__ */ jsx6("div", { className: cn("flex items-center gap-1", className), ...props });
|
|
434
|
+
var ArtifactContent = ({ className, ...props }) => /* @__PURE__ */ jsx6("div", { className: cn("flex-1 overflow-auto p-4", className), ...props });
|
|
195
435
|
|
|
196
436
|
// src/components/artifacts/status-message.tsx
|
|
197
437
|
import { createElement as createElement2 } from "react";
|
|
@@ -209,9 +449,9 @@ function StatusMessage({ $tone, children }) {
|
|
|
209
449
|
var VARIANT_CHART_HEIGHT = "100%";
|
|
210
450
|
|
|
211
451
|
// src/components/artifacts/chart-artifact/chart-variant-services/bar-chart-variant-component.tsx
|
|
212
|
-
import { jsx as
|
|
452
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
213
453
|
function BarChartVariantComponent({ config, rows }) {
|
|
214
|
-
return /* @__PURE__ */
|
|
454
|
+
return /* @__PURE__ */ jsx7(
|
|
215
455
|
BarChart,
|
|
216
456
|
{
|
|
217
457
|
data: rows,
|
|
@@ -258,9 +498,9 @@ var BarChartVariantService = {
|
|
|
258
498
|
};
|
|
259
499
|
|
|
260
500
|
// src/components/artifacts/chart-artifact/chart-variant-services/line-chart-variant-component.tsx
|
|
261
|
-
import { jsx as
|
|
501
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
262
502
|
function LineChartVariantComponent({ config, rows }) {
|
|
263
|
-
return /* @__PURE__ */
|
|
503
|
+
return /* @__PURE__ */ jsx8(LineChart, { data: rows, xKey: config.xKey, series: config.series, height: VARIANT_CHART_HEIGHT });
|
|
264
504
|
}
|
|
265
505
|
|
|
266
506
|
// src/components/artifacts/chart-artifact/chart-variant-services/line-chart-variant-service.tsx
|
|
@@ -281,13 +521,13 @@ var LineChartVariantService = {
|
|
|
281
521
|
};
|
|
282
522
|
|
|
283
523
|
// src/components/artifacts/chart-artifact/chart-variant-services/pie-chart-variant-component.tsx
|
|
284
|
-
import { jsx as
|
|
524
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
285
525
|
function PieChartVariantComponent({
|
|
286
526
|
config,
|
|
287
527
|
rows,
|
|
288
528
|
labels
|
|
289
529
|
}) {
|
|
290
|
-
return /* @__PURE__ */
|
|
530
|
+
return /* @__PURE__ */ jsx9(
|
|
291
531
|
PieChart,
|
|
292
532
|
{
|
|
293
533
|
data: rows,
|
|
@@ -324,14 +564,14 @@ var ChartVariantServices = {
|
|
|
324
564
|
};
|
|
325
565
|
|
|
326
566
|
// src/components/artifacts/chart-artifact/chart-artifact-content.tsx
|
|
327
|
-
import { jsx as
|
|
567
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
328
568
|
function ChartArtifactContent({ config, rows, labels }) {
|
|
329
569
|
const service = ChartVariantServices[config.variant];
|
|
330
570
|
if (!service) {
|
|
331
|
-
return /* @__PURE__ */
|
|
571
|
+
return /* @__PURE__ */ jsx10(StatusMessage, { $tone: "info", children: labels.unavailable });
|
|
332
572
|
}
|
|
333
573
|
const Component = service.Component;
|
|
334
|
-
return /* @__PURE__ */
|
|
574
|
+
return /* @__PURE__ */ jsx10(Component, { config, rows, labels });
|
|
335
575
|
}
|
|
336
576
|
|
|
337
577
|
// src/components/artifacts/parse-csv.ts
|
|
@@ -356,7 +596,7 @@ function parseCsv(text, columns) {
|
|
|
356
596
|
}
|
|
357
597
|
|
|
358
598
|
// src/components/artifacts/use-rows-artifact-data.ts
|
|
359
|
-
import { useEffect, useMemo, useState } from "react";
|
|
599
|
+
import { useEffect as useEffect2, useMemo, useState as useState2 } from "react";
|
|
360
600
|
var LOADING = { status: "loading", rows: null, error: null };
|
|
361
601
|
var UNAVAILABLE = { status: "unavailable", rows: null, error: null };
|
|
362
602
|
var INITIAL_INTERNAL = { cacheKey: null, data: LOADING };
|
|
@@ -371,8 +611,8 @@ function useRowsArtifactData(presignedUrl, columns, parse) {
|
|
|
371
611
|
const colsKey = useMemo(() => columnsFingerprint(columns), [columns]);
|
|
372
612
|
const safeUrl = presignedUrl && isSafeDownloadUrl(presignedUrl) ? presignedUrl : null;
|
|
373
613
|
const cacheKey = safeUrl ? `${safeUrl}::${colsKey}` : null;
|
|
374
|
-
const [state, setState] =
|
|
375
|
-
|
|
614
|
+
const [state, setState] = useState2(INITIAL_INTERNAL);
|
|
615
|
+
useEffect2(() => {
|
|
376
616
|
if (!safeUrl) return;
|
|
377
617
|
const controller = new AbortController();
|
|
378
618
|
fetch(safeUrl, {
|
|
@@ -429,32 +669,71 @@ function isValidChartConfig(config) {
|
|
|
429
669
|
}
|
|
430
670
|
|
|
431
671
|
// src/components/artifacts/chart-artifact/chart-artifact.tsx
|
|
432
|
-
import { jsx as
|
|
672
|
+
import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
433
673
|
var TITLE_CLASSES = "text-sm font-semibold text-foreground";
|
|
434
674
|
var CHART_HEIGHT = 320;
|
|
435
675
|
function ChartArtifact({ artifact, labels, callbacks }) {
|
|
436
676
|
const validConfig = isValidChartConfig(artifact.config);
|
|
437
|
-
|
|
677
|
+
const cardRef = useRef2(null);
|
|
678
|
+
useEffect3(() => {
|
|
438
679
|
if (validConfig) return;
|
|
439
680
|
console.warn("[clay] ChartArtifact: malformed `config` \u2014 skipping render.");
|
|
440
681
|
}, [validConfig]);
|
|
441
682
|
const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
|
|
442
683
|
const resolvedLabels = useMemo2(
|
|
443
|
-
() => ({ ...DEFAULT_CHART_ARTIFACT_LABELS, ...labels
|
|
684
|
+
() => ({ ...DEFAULT_CHART_ARTIFACT_LABELS, ...labels ?? {} }),
|
|
444
685
|
[labels]
|
|
445
686
|
);
|
|
446
687
|
const data = useChartArtifactData(
|
|
447
688
|
validConfig ? presignedUrl : null,
|
|
448
689
|
validConfig ? artifact.config : { variant: "LINE", series: [], xKey: "x" }
|
|
449
690
|
);
|
|
450
|
-
const onDownload = callbacks
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
691
|
+
const { onDownload, onDownloadPng, onCopyAsImage } = callbacks ?? {};
|
|
692
|
+
const handleDownloadCsvSelect = onDownload ? () => onDownload(artifact) : void 0;
|
|
693
|
+
const handleDownloadPngSelect = onDownloadPng ? () => onDownloadPng(artifact) : void 0;
|
|
694
|
+
const handleCopyAsImageClick = onCopyAsImage ? () => onCopyAsImage(artifact) : void 0;
|
|
695
|
+
const canCopyAsImage = data.status === "ready" && data.rows.length > 0;
|
|
696
|
+
const canDownloadPng = data.status === "ready" && data.rows.length > 0;
|
|
697
|
+
const isCsvDownloadAvailable = presignedUrl !== null && isSafeDownloadUrl(presignedUrl);
|
|
698
|
+
const showDownloadMenu = validConfig && canDownloadPng || isCsvDownloadAvailable;
|
|
699
|
+
const showActions = validConfig || showDownloadMenu;
|
|
700
|
+
const pngFilename = (artifact.title ?? "").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean).join("-") || "chart";
|
|
701
|
+
return /* @__PURE__ */ jsxs4(Artifact, { ref: cardRef, className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
702
|
+
/* @__PURE__ */ jsxs4(ArtifactHeader, { className: "bg-background/70", children: [
|
|
703
|
+
artifact.title ? /* @__PURE__ */ jsx11(ArtifactTitle, { className: TITLE_CLASSES, children: artifact.title }) : /* @__PURE__ */ jsx11("span", {}),
|
|
704
|
+
showActions ? /* @__PURE__ */ jsxs4(ArtifactActions, { ...{ [CAPTURE_EXCLUDE_ATTRIBUTE]: "" }, children: [
|
|
705
|
+
validConfig ? /* @__PURE__ */ jsx11(
|
|
706
|
+
ArtifactCopyAsImageButton,
|
|
707
|
+
{
|
|
708
|
+
targetRef: cardRef,
|
|
709
|
+
label: resolvedLabels.copyAsImage,
|
|
710
|
+
disabled: !canCopyAsImage,
|
|
711
|
+
onClick: handleCopyAsImageClick
|
|
712
|
+
}
|
|
713
|
+
) : null,
|
|
714
|
+
showDownloadMenu ? /* @__PURE__ */ jsx11(
|
|
715
|
+
ArtifactDownloadMenu,
|
|
716
|
+
{
|
|
717
|
+
triggerLabel: resolvedLabels.download,
|
|
718
|
+
actions: {
|
|
719
|
+
csv: isCsvDownloadAvailable ? {
|
|
720
|
+
href: presignedUrl ?? "",
|
|
721
|
+
label: resolvedLabels.downloadCsv,
|
|
722
|
+
onSelect: handleDownloadCsvSelect
|
|
723
|
+
} : void 0,
|
|
724
|
+
png: validConfig ? {
|
|
725
|
+
targetRef: cardRef,
|
|
726
|
+
filename: pngFilename,
|
|
727
|
+
label: resolvedLabels.downloadPng,
|
|
728
|
+
disabled: !canDownloadPng,
|
|
729
|
+
onSelect: handleDownloadPngSelect
|
|
730
|
+
} : void 0
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
) : null
|
|
734
|
+
] }) : null
|
|
456
735
|
] }),
|
|
457
|
-
/* @__PURE__ */
|
|
736
|
+
/* @__PURE__ */ jsx11(
|
|
458
737
|
ArtifactContent,
|
|
459
738
|
{
|
|
460
739
|
className: "p-4 overflow-visible flex flex-none items-center justify-center",
|
|
@@ -466,25 +745,25 @@ function ChartArtifact({ artifact, labels, callbacks }) {
|
|
|
466
745
|
}
|
|
467
746
|
function renderBody(validConfig, artifact, data, labels) {
|
|
468
747
|
if (!validConfig) {
|
|
469
|
-
return /* @__PURE__ */
|
|
748
|
+
return /* @__PURE__ */ jsx11(StatusMessage, { $tone: "info", children: labels.unavailable });
|
|
470
749
|
}
|
|
471
750
|
if (data.status === "error") {
|
|
472
|
-
return /* @__PURE__ */
|
|
751
|
+
return /* @__PURE__ */ jsx11(StatusMessage, { $tone: "error", children: labels.loadError });
|
|
473
752
|
}
|
|
474
753
|
if (data.status === "unavailable") {
|
|
475
|
-
return /* @__PURE__ */
|
|
754
|
+
return /* @__PURE__ */ jsx11(StatusMessage, { $tone: "info", children: labels.unavailable });
|
|
476
755
|
}
|
|
477
756
|
if (data.status === "loading") {
|
|
478
|
-
return /* @__PURE__ */
|
|
757
|
+
return /* @__PURE__ */ jsx11(StatusMessage, { $tone: "info", children: labels.loading });
|
|
479
758
|
}
|
|
480
759
|
if (data.rows.length === 0) {
|
|
481
|
-
return /* @__PURE__ */
|
|
760
|
+
return /* @__PURE__ */ jsx11(StatusMessage, { $tone: "info", children: labels.empty });
|
|
482
761
|
}
|
|
483
|
-
return /* @__PURE__ */
|
|
762
|
+
return /* @__PURE__ */ jsx11(ChartArtifactContent, { config: artifact.config, rows: data.rows, labels });
|
|
484
763
|
}
|
|
485
764
|
|
|
486
765
|
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
487
|
-
import { useEffect as
|
|
766
|
+
import { useEffect as useEffect4, useMemo as useMemo3 } from "react";
|
|
488
767
|
|
|
489
768
|
// src/components/artifacts/table-artifact/table-artifact-content.constants.ts
|
|
490
769
|
var TABLE_STATUS = {
|
|
@@ -505,7 +784,7 @@ var DATA_ROW_CLASSES = `${ROW_CLASSES} animate-in fade-in duration-300`;
|
|
|
505
784
|
var SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
|
|
506
785
|
|
|
507
786
|
// src/components/artifacts/table-artifact/table-artifact-content.tsx
|
|
508
|
-
import { jsx as
|
|
787
|
+
import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
509
788
|
function TableArtifactContent({
|
|
510
789
|
columns,
|
|
511
790
|
data,
|
|
@@ -515,43 +794,43 @@ function TableArtifactContent({
|
|
|
515
794
|
labels
|
|
516
795
|
}) {
|
|
517
796
|
if (data.status === TABLE_STATUS.ERROR) {
|
|
518
|
-
return /* @__PURE__ */
|
|
797
|
+
return /* @__PURE__ */ jsx12(StatusMessage, { $tone: "error", children: labels.loadError });
|
|
519
798
|
}
|
|
520
799
|
if (data.status === TABLE_STATUS.UNAVAILABLE) {
|
|
521
|
-
return /* @__PURE__ */
|
|
800
|
+
return /* @__PURE__ */ jsx12(StatusMessage, { $tone: "info", children: labels.unavailable });
|
|
522
801
|
}
|
|
523
802
|
if (data.status === TABLE_STATUS.LOADING) {
|
|
524
803
|
if (typeof knownRowCount === "number" && knownRowCount > 0) {
|
|
525
804
|
const shimmerCount = Math.min(knownRowCount, maxShimmerRows);
|
|
526
|
-
return /* @__PURE__ */
|
|
805
|
+
return /* @__PURE__ */ jsx12(ArtifactTable, { columns, maxBodyHeight, children: renderShimmerRows(columns, shimmerCount) });
|
|
527
806
|
}
|
|
528
|
-
return /* @__PURE__ */
|
|
807
|
+
return /* @__PURE__ */ jsx12(StatusMessage, { $tone: "info", children: labels.loading });
|
|
529
808
|
}
|
|
530
|
-
return /* @__PURE__ */
|
|
809
|
+
return /* @__PURE__ */ jsx12(ArtifactTable, { columns, maxBodyHeight, children: data.rows.length === 0 ? renderEmptyRow(columns.length, labels.empty) : renderDataRows(columns, data.rows) });
|
|
531
810
|
}
|
|
532
811
|
function ArtifactTable({ columns, maxBodyHeight, children }) {
|
|
533
812
|
const { targetRef, isScrolled } = useScrollShadow();
|
|
534
|
-
return /* @__PURE__ */
|
|
535
|
-
/* @__PURE__ */
|
|
813
|
+
return /* @__PURE__ */ jsx12("div", { ref: targetRef, className: "overscroll-none", style: { maxHeight: maxBodyHeight, overflowY: "auto" }, children: /* @__PURE__ */ jsxs5(Table, { containerClassName: "overflow-visible", children: [
|
|
814
|
+
/* @__PURE__ */ jsx12(
|
|
536
815
|
TableHeader,
|
|
537
816
|
{
|
|
538
817
|
"data-scrolled": isScrolled ? "true" : void 0,
|
|
539
818
|
className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
|
|
540
819
|
style: isScrolled ? { boxShadow: SCROLL_SHADOW } : void 0,
|
|
541
|
-
children: /* @__PURE__ */
|
|
820
|
+
children: /* @__PURE__ */ jsx12(TableRow, { className: "hover:bg-transparent", children: columns.map((column) => /* @__PURE__ */ jsx12(TableHead, { scope: "col", className: HEAD_CLASS, children: column.label }, column.key)) })
|
|
542
821
|
}
|
|
543
822
|
),
|
|
544
|
-
/* @__PURE__ */
|
|
823
|
+
/* @__PURE__ */ jsx12(TableBody, { children })
|
|
545
824
|
] }) });
|
|
546
825
|
}
|
|
547
826
|
function renderShimmerRows(columns, count) {
|
|
548
|
-
return Array.from({ length: count }).map((_, index) => /* @__PURE__ */
|
|
827
|
+
return Array.from({ length: count }).map((_, index) => /* @__PURE__ */ jsx12(TableRow, { className: ROW_CLASSES, "aria-hidden": "true", children: columns.map((column) => /* @__PURE__ */ jsx12(TableCell, { className: CELL_CLASS, children: /* @__PURE__ */ jsx12("span", { className: "block h-3 w-3/4 animate-pulse rounded bg-muted-foreground/20" }) }, column.key)) }, `shimmer-${index}`));
|
|
549
828
|
}
|
|
550
829
|
function renderDataRows(columns, rows) {
|
|
551
|
-
return rows.map((row, index) => /* @__PURE__ */
|
|
830
|
+
return rows.map((row, index) => /* @__PURE__ */ jsx12(TableRow, { className: DATA_ROW_CLASSES, children: columns.map((column) => /* @__PURE__ */ jsx12(TableCell, { className: CELL_CLASS, children: formatCell(row, column) }, column.key)) }, index));
|
|
552
831
|
}
|
|
553
832
|
function renderEmptyRow(colSpan, emptyMessage) {
|
|
554
|
-
return /* @__PURE__ */
|
|
833
|
+
return /* @__PURE__ */ jsx12(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx12(TableCell, { colSpan, className: "py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) });
|
|
555
834
|
}
|
|
556
835
|
|
|
557
836
|
// src/components/artifacts/table-artifact/use-table-artifact-data.ts
|
|
@@ -576,19 +855,19 @@ function isValidTableColumn(column) {
|
|
|
576
855
|
}
|
|
577
856
|
|
|
578
857
|
// src/components/artifacts/table-artifact/table-artifact.tsx
|
|
579
|
-
import { jsx as
|
|
858
|
+
import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
580
859
|
var TITLE_CLASSES2 = "text-sm font-semibold text-foreground";
|
|
581
860
|
var TABLE_MAX_BODY_HEIGHT = 480;
|
|
582
861
|
var MAX_SHIMMER_ROWS = 10;
|
|
583
862
|
function TableArtifact({ artifact, labels, callbacks }) {
|
|
584
863
|
const validConfig = isValidTableConfig(artifact.config);
|
|
585
864
|
const validColumns = validConfig ? artifact.config.columns : null;
|
|
586
|
-
|
|
865
|
+
useEffect4(() => {
|
|
587
866
|
if (validConfig) return;
|
|
588
867
|
console.warn("[clay] TableArtifact: malformed `config` \u2014 skipping render.");
|
|
589
868
|
}, [validConfig]);
|
|
590
869
|
const resolvedLabels = useMemo3(
|
|
591
|
-
() => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels
|
|
870
|
+
() => ({ ...DEFAULT_TABLE_ARTIFACT_LABELS, ...labels ?? {} }),
|
|
592
871
|
[labels]
|
|
593
872
|
);
|
|
594
873
|
const data = useTableArtifactData(
|
|
@@ -596,13 +875,13 @@ function TableArtifact({ artifact, labels, callbacks }) {
|
|
|
596
875
|
validColumns ?? []
|
|
597
876
|
);
|
|
598
877
|
const presignedUrl = artifact.protectedAsset?.presignedUrl ?? null;
|
|
599
|
-
const onDownload = callbacks?.
|
|
878
|
+
const onDownload = callbacks?.onDownload;
|
|
600
879
|
const handleDownloadClick = onDownload ? () => onDownload(artifact) : void 0;
|
|
601
880
|
if (!validConfig || !validColumns) {
|
|
602
|
-
return /* @__PURE__ */
|
|
603
|
-
/* @__PURE__ */
|
|
604
|
-
artifact.title ? /* @__PURE__ */
|
|
605
|
-
presignedUrl ? /* @__PURE__ */
|
|
881
|
+
return /* @__PURE__ */ jsxs6(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
882
|
+
/* @__PURE__ */ jsxs6(ArtifactHeader, { className: "bg-background/70", children: [
|
|
883
|
+
artifact.title ? /* @__PURE__ */ jsx13(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ jsx13("span", {}),
|
|
884
|
+
presignedUrl ? /* @__PURE__ */ jsx13(ArtifactActions, { children: /* @__PURE__ */ jsx13(
|
|
606
885
|
ArtifactDownloadButton,
|
|
607
886
|
{
|
|
608
887
|
href: presignedUrl,
|
|
@@ -611,17 +890,17 @@ function TableArtifact({ artifact, labels, callbacks }) {
|
|
|
611
890
|
}
|
|
612
891
|
) }) : null
|
|
613
892
|
] }),
|
|
614
|
-
/* @__PURE__ */
|
|
893
|
+
/* @__PURE__ */ jsx13(ArtifactContent, { className: "p-0 overflow-auto", style: { maxHeight: TABLE_MAX_BODY_HEIGHT }, children: /* @__PURE__ */ jsx13(StatusMessage, { $tone: "info", children: resolvedLabels.unavailable }) })
|
|
615
894
|
] });
|
|
616
895
|
}
|
|
617
896
|
return (
|
|
618
897
|
// The table body owns its own scroll container (`ArtifactTable` inside `TableArtifactContent`).
|
|
619
898
|
// Disable the outer overflow container so only one scroll context exists — this prevents
|
|
620
899
|
// double-scroll nesting and lets `useScrollShadow` find the correct scroll ancestor.
|
|
621
|
-
/* @__PURE__ */
|
|
622
|
-
/* @__PURE__ */
|
|
623
|
-
artifact.title ? /* @__PURE__ */
|
|
624
|
-
/* @__PURE__ */
|
|
900
|
+
/* @__PURE__ */ jsxs6(Artifact, { className: "shadow-none w-full rounded-2xl bg-background/70", children: [
|
|
901
|
+
/* @__PURE__ */ jsxs6(ArtifactHeader, { className: "bg-background/70", children: [
|
|
902
|
+
artifact.title ? /* @__PURE__ */ jsx13(ArtifactTitle, { className: TITLE_CLASSES2, children: artifact.title }) : /* @__PURE__ */ jsx13("span", {}),
|
|
903
|
+
/* @__PURE__ */ jsx13(ArtifactActions, { children: /* @__PURE__ */ jsx13(
|
|
625
904
|
ArtifactDownloadButton,
|
|
626
905
|
{
|
|
627
906
|
href: presignedUrl ?? "",
|
|
@@ -630,7 +909,7 @@ function TableArtifact({ artifact, labels, callbacks }) {
|
|
|
630
909
|
}
|
|
631
910
|
) })
|
|
632
911
|
] }),
|
|
633
|
-
/* @__PURE__ */
|
|
912
|
+
/* @__PURE__ */ jsx13(ArtifactContent, { className: "p-0 overflow-visible", style: { maxHeight: "none" }, children: /* @__PURE__ */ jsx13(
|
|
634
913
|
TableArtifactContent,
|
|
635
914
|
{
|
|
636
915
|
columns: validColumns,
|
|
@@ -692,8 +971,10 @@ export {
|
|
|
692
971
|
IconCopy,
|
|
693
972
|
IconThumbDown,
|
|
694
973
|
IconThumbUp,
|
|
974
|
+
ArtifactCopyAsImageButton,
|
|
695
975
|
ArtifactDownloadButton,
|
|
696
976
|
isSafeDownloadUrl,
|
|
977
|
+
ArtifactDownloadMenu,
|
|
697
978
|
ChartArtifact,
|
|
698
979
|
TableArtifact,
|
|
699
980
|
ArtifactServices,
|
|
@@ -703,9 +984,13 @@ export {
|
|
|
703
984
|
|
|
704
985
|
@tabler/icons-react/dist/esm/defaultAttributes.mjs:
|
|
705
986
|
@tabler/icons-react/dist/esm/createReactComponent.mjs:
|
|
987
|
+
@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs:
|
|
706
988
|
@tabler/icons-react/dist/esm/icons/IconCheck.mjs:
|
|
707
989
|
@tabler/icons-react/dist/esm/icons/IconCopy.mjs:
|
|
708
990
|
@tabler/icons-react/dist/esm/icons/IconDownload.mjs:
|
|
991
|
+
@tabler/icons-react/dist/esm/icons/IconFileSpreadsheet.mjs:
|
|
992
|
+
@tabler/icons-react/dist/esm/icons/IconLoader2.mjs:
|
|
993
|
+
@tabler/icons-react/dist/esm/icons/IconPhoto.mjs:
|
|
709
994
|
@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
|
|
710
995
|
@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
|
|
711
996
|
@tabler/icons-react/dist/esm/tabler-icons-react.mjs:
|
|
@@ -716,4 +1001,4 @@ export {
|
|
|
716
1001
|
* See the LICENSE file in the root directory of this source tree.
|
|
717
1002
|
*)
|
|
718
1003
|
*/
|
|
719
|
-
//# sourceMappingURL=chunk-
|
|
1004
|
+
//# sourceMappingURL=chunk-DT44KNCV.js.map
|