@shapesos/clay 0.11.0 → 0.13.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 (69) hide show
  1. package/README.md +60 -0
  2. package/dist/artifacts.cjs +1420 -245
  3. package/dist/artifacts.cjs.map +1 -1
  4. package/dist/artifacts.d.cts +167 -6
  5. package/dist/artifacts.d.ts +167 -6
  6. package/dist/artifacts.js +18 -3
  7. package/dist/blocks.cjs +1696 -532
  8. package/dist/blocks.cjs.map +1 -1
  9. package/dist/blocks.css +1 -1
  10. package/dist/blocks.d.cts +21 -10
  11. package/dist/blocks.d.ts +21 -10
  12. package/dist/blocks.js +7 -3
  13. package/dist/capture.cjs +220 -0
  14. package/dist/capture.cjs.map +1 -0
  15. package/dist/capture.d.cts +113 -0
  16. package/dist/capture.d.ts +113 -0
  17. package/dist/capture.js +17 -0
  18. package/dist/chart.cjs +594 -0
  19. package/dist/chart.cjs.map +1 -0
  20. package/dist/chart.d.cts +439 -0
  21. package/dist/chart.d.ts +439 -0
  22. package/dist/chart.js +32 -0
  23. package/dist/chart.js.map +1 -0
  24. package/dist/chat.cjs +1687 -532
  25. package/dist/chat.cjs.map +1 -1
  26. package/dist/chat.d.cts +3 -2
  27. package/dist/chat.d.ts +3 -2
  28. package/dist/chat.js +8 -4
  29. package/dist/{chunk-MXOPG747.js → chunk-26XVDY6Z.js} +8 -8
  30. package/dist/chunk-26XVDY6Z.js.map +1 -0
  31. package/dist/{chunk-L35M3OD5.js → chunk-4MZZH3WX.js} +5 -11
  32. package/dist/chunk-4MZZH3WX.js.map +1 -0
  33. package/dist/chunk-DT44KNCV.js +1004 -0
  34. package/dist/chunk-DT44KNCV.js.map +1 -0
  35. package/dist/chunk-JAGNXEWK.js +116 -0
  36. package/dist/chunk-JAGNXEWK.js.map +1 -0
  37. package/dist/chunk-LXYCT4YO.js +7 -0
  38. package/dist/chunk-LXYCT4YO.js.map +1 -0
  39. package/dist/chunk-P6GUNIAE.js +11 -0
  40. package/dist/chunk-P6GUNIAE.js.map +1 -0
  41. package/dist/{chunk-OUW6PUEB.js → chunk-QH2WW2MW.js} +7 -7
  42. package/dist/chunk-QXGYMDIA.js +477 -0
  43. package/dist/chunk-QXGYMDIA.js.map +1 -0
  44. package/dist/chunk-RSRNSWJN.js +1 -0
  45. package/dist/chunk-RSRNSWJN.js.map +1 -0
  46. package/dist/dom-to-image-NATF3446.js +21 -0
  47. package/dist/dom-to-image-NATF3446.js.map +1 -0
  48. package/dist/index.cjs +1489 -317
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.d.cts +4 -3
  51. package/dist/index.d.ts +4 -3
  52. package/dist/index.js +28 -15
  53. package/dist/table.js +2 -1
  54. package/dist/types-B2aYk82c.d.cts +29 -0
  55. package/dist/types-B2aYk82c.d.ts +29 -0
  56. package/dist/types-BzXPBy6s.d.cts +330 -0
  57. package/dist/{types-DuuRI4ll.d.cts → types-CW45GBXl.d.cts} +31 -4
  58. package/dist/{types-C9XX-Uhk.d.ts → types-D1b8v7EY.d.ts} +31 -4
  59. package/dist/types-GCkXbyFm.d.ts +330 -0
  60. package/package.json +24 -2
  61. package/dist/chunk-BX5TCEPR.js +0 -436
  62. package/dist/chunk-BX5TCEPR.js.map +0 -1
  63. package/dist/chunk-L35M3OD5.js.map +0 -1
  64. package/dist/chunk-MEJESPTZ.js +0 -1
  65. package/dist/chunk-MXOPG747.js.map +0 -1
  66. package/dist/types-3Gzk7cRt.d.cts +0 -121
  67. package/dist/types-3Gzk7cRt.d.ts +0 -121
  68. /package/dist/{chunk-MEJESPTZ.js.map → capture.js.map} +0 -0
  69. /package/dist/{chunk-OUW6PUEB.js.map → chunk-QH2WW2MW.js.map} +0 -0
@@ -1,6 +1,7 @@
1
- import { c as ArtifactType, a as ArtifactService, A as ArtifactRecord, b as ArtifactServiceProps, T as TableArtifactRecord } from './types-3Gzk7cRt.cjs';
2
- export { d as TableColumn, e as TableConfig, f as TableRow, g as TableStats, h as artifactTypes } from './types-3Gzk7cRt.cjs';
3
- import { ReactNode } from 'react';
1
+ import { f as ArtifactType, d as ArtifactService, c as ArtifactRecord, e as ArtifactServiceProps, k as TableArtifactRecord, g as ChartArtifactRecord } from './types-BzXPBy6s.cjs';
2
+ export { A as ArtifactCallbacksOf, a as ArtifactDataRow, b as ArtifactLabelsOf, B as BarChartConfig, C as ChartArtifactLabels, h as ChartConfig, i as ChartStats, D as DEFAULT_CHART_ARTIFACT_LABELS, j as DEFAULT_TABLE_ARTIFACT_LABELS, L as LineChartConfig, P as PieChartConfig, T as TableArtifactLabels, l as TableColumn, m as TableConfig, n as TableRow, o as TableStats, p as artifactTypes } from './types-BzXPBy6s.cjs';
3
+ import { ReactNode, RefObject } from 'react';
4
+ export { C as ChartSeries, a as ChartVariant } from './types-B2aYk82c.cjs';
4
5
 
5
6
  /**
6
7
  * Map of artifact services keyed by `artifact.type`.
@@ -28,6 +29,19 @@ interface ArtifactDownloadButtonProps {
28
29
  * `data:` URIs smuggled into `presignedUrl`.
29
30
  */
30
31
  href: string;
32
+ /**
33
+ * Tooltip text + `aria-label` for the button. Optional — defaults to `"Download CSV"` so direct
34
+ * consumers don't have to pass anything for the common case. Per-type artifact orchestrators
35
+ * (`<ChartArtifact>`, `<TableArtifact>`) pass a translated value via their own `labels` prop so
36
+ * the button reads in the user's language.
37
+ */
38
+ label?: string;
39
+ /**
40
+ * Optional callback fired on click — runs alongside the browser's native download navigation
41
+ * (no `preventDefault`). Used for analytics / observability hooks; per-type artifact
42
+ * orchestrators wire this from their `callbacks` prop.
43
+ */
44
+ onClick?: () => void;
31
45
  }
32
46
  /**
33
47
  * Reusable download button for artifact headers. Anchor-based so the browser handles the download
@@ -36,13 +50,136 @@ interface ArtifactDownloadButtonProps {
36
50
  *
37
51
  * Drop this inside `<ArtifactActions>` in any per-type artifact orchestrator.
38
52
  */
39
- declare function ArtifactDownloadButton({ href }: ArtifactDownloadButtonProps): ReactNode;
53
+ declare function ArtifactDownloadButton({ href, label, onClick, }: ArtifactDownloadButtonProps): ReactNode;
40
54
  /**
41
55
  * Returns `true` only for `http:` and `https:` URLs. Rejects `javascript:`, `data:`, and any
42
56
  * other scheme that could execute code on click.
43
57
  */
44
58
  declare function isSafeDownloadUrl(url: string): boolean;
45
59
 
60
+ /** Props for `ArtifactCopyAsImageButton`. */
61
+ interface ArtifactCopyAsImageButtonProps {
62
+ /**
63
+ * Ref to the DOM node to capture as an image. Typically the artifact card root. The capture
64
+ * walks the subtree and includes everything except elements marked with
65
+ * `data-clay-capture-exclude` (the action toolbar should carry that marker so it doesn't
66
+ * capture itself).
67
+ */
68
+ targetRef: RefObject<HTMLElement | null>;
69
+ /**
70
+ * Tooltip text + `aria-label` for the idle state. Defaults to `"Copy Image"`. Per-type
71
+ * artifact orchestrators pass a translated value via their own `labels` prop so the button
72
+ * reads in the user's language. The transient working / success / error tooltips remain
73
+ * English-hardcoded — they flash for ~1.5s and the cost of translating them is rarely worth it.
74
+ */
75
+ label?: string;
76
+ /** Disable the button (e.g. while artifact data is still loading and the captured image would
77
+ * be empty / partial). */
78
+ disabled?: boolean;
79
+ /**
80
+ * Optional callback fired on click — runs alongside the copy attempt itself. Used for analytics
81
+ * / observability hooks; per-type artifact orchestrators wire this from their `callbacks` prop.
82
+ * Fires regardless of whether the copy ultimately succeeds (the result is reported via the
83
+ * button's own state flash).
84
+ */
85
+ onClick?: () => void;
86
+ }
87
+
88
+ /**
89
+ * Reusable "copy artifact as image" button for artifact headers. Drop it inside
90
+ * `<ArtifactActions>` alongside `ArtifactDownloadButton`.
91
+ *
92
+ * Captures the DOM node referenced by `targetRef`, rasterises it to PNG, and writes the result
93
+ * to the system clipboard. Must be invoked from a user gesture (the button click is enough).
94
+ *
95
+ * The button flashes a check icon on success and an alert icon on failure, reverting to its
96
+ * idle photo icon after ~1.5s. While capturing, it disables itself and shows a spinner.
97
+ *
98
+ * On failure, the rejection is logged via `console.warn` so production errors are visible in
99
+ * observability tooling (any consumer wiring a global console transport — Sentry, Datadog,
100
+ * Logfire — picks them up). The user-visible affordance is the error-state flash + tooltip.
101
+ */
102
+ declare function ArtifactCopyAsImageButton({ targetRef, label, disabled, onClick, }: ArtifactCopyAsImageButtonProps): ReactNode;
103
+
104
+ /**
105
+ * Per-format props for the CSV menu item. Pass within `actions.csv` to expose the item;
106
+ * omit the slot entirely to hide it. The item is also auto-hidden if `href` doesn't satisfy
107
+ * the `http(s):` safety guard — mirrors `ArtifactDownloadButton`'s defense against
108
+ * `javascript:` / `data:` URIs smuggled into a presigned URL field.
109
+ */
110
+ interface ArtifactDownloadMenuCsvAction {
111
+ /** Presigned URL backing the CSV download. The browser uses whatever filename the server
112
+ * supplies via `Content-Disposition`. */
113
+ href: string;
114
+ /** Label for the menu item. Defaults to `"Download CSV"`. */
115
+ label?: string;
116
+ /** Optional analytics callback. Fires alongside the browser-native download navigation. */
117
+ onSelect?: () => void;
118
+ }
119
+ /**
120
+ * Per-format props for the PNG menu item. Pass within `actions.png` to expose the item; omit
121
+ * the slot entirely to hide it. PNG capture rasterises `targetRef.current` via
122
+ * `@shapesos/clay/capture`'s `downloadNodeAsPng`.
123
+ */
124
+ interface ArtifactDownloadMenuPngAction {
125
+ /** Ref to the DOM node to rasterise. Typically the artifact card root. The capture walks the
126
+ * subtree and excludes anything marked with `data-clay-capture-exclude`. */
127
+ targetRef: RefObject<HTMLElement | null>;
128
+ /** Suggested filename for the saved file (without extension — the menu appends `.png`).
129
+ * Defaults to `"artifact"`. Pass artifact-title-derived names for recognisable downloads. */
130
+ filename?: string;
131
+ /** Label for the menu item. Defaults to `"Download PNG"`. */
132
+ label?: string;
133
+ /** Disable the menu item (e.g. while artifact data is still loading). Default: `false`. */
134
+ disabled?: boolean;
135
+ /** Optional analytics callback. Fires alongside the rasterise + download — regardless of
136
+ * whether the download ultimately succeeds. */
137
+ onSelect?: () => void;
138
+ }
139
+ /** Props for `ArtifactDownloadMenu`. */
140
+ interface ArtifactDownloadMenuProps {
141
+ /**
142
+ * Format-keyed bag of action descriptors. Each entry exposes one menu item; omit the slot
143
+ * to hide it. Grouping per-format props this way (rather than spreading flat
144
+ * `csvHref` / `pngFilename` / `pngLabel` props at the top level) keeps the consumer's call
145
+ * site readable as more formats land — a future `actions.svg` or `actions.xlsx` follows the
146
+ * same shape without growing the prop list at the call site.
147
+ *
148
+ * Caller responsibility: include at least one action. An empty `{}` renders a menu with no
149
+ * items, which has no UX value — orchestrators should gate the entire `<ArtifactDownloadMenu>`
150
+ * mount on "at least one format reachable" before passing this prop.
151
+ *
152
+ * **Future generalisation** — if more action shapes land (SVG, XLSX, share-link, …), consider
153
+ * lifting these into a shared `ArtifactAction` discriminated union that both this menu and
154
+ * a future `<ArtifactActions>` toolbar can render generically. Postponed until a second
155
+ * non-Download action type appears — premature abstraction with two flavours.
156
+ */
157
+ actions: {
158
+ /** CSV download via presigned URL. Browser-native navigation; consumer i18n + analytics. */
159
+ csv?: ArtifactDownloadMenuCsvAction;
160
+ /** PNG download via DOM-to-image rasterise. Browser-only (capture entry). */
161
+ png?: ArtifactDownloadMenuPngAction;
162
+ };
163
+ /** Tooltip + `aria-label` for the trigger button. Defaults to `"Download"`. */
164
+ triggerLabel?: string;
165
+ }
166
+
167
+ /**
168
+ * Reusable "Download" affordance for artifact headers. Renders as a single icon-button trigger;
169
+ * clicking it opens a menu with one item per format the caller passes via `actions`. Today's
170
+ * formats: CSV (presigned URL) + PNG (DOM-to-image rasterise). Future formats (SVG, XLSX, …)
171
+ * slot into the same `actions` bag without touching the call-site prop list.
172
+ *
173
+ * Drop this inside `<ArtifactActions>` in any per-type artifact orchestrator that supports
174
+ * multiple download formats. For single-format artifacts (e.g. a future table artifact that
175
+ * only ships CSV), prefer the simpler `ArtifactDownloadButton` instead.
176
+ *
177
+ * The menu uses Radix's `DropdownMenu` primitive (vendored in `src/components/ui/dropdown-menu.tsx`)
178
+ * with `asChild` on the trigger so clay's `IconButton` is the real button — preserves the
179
+ * design-system look across all action affordances.
180
+ */
181
+ declare function ArtifactDownloadMenu({ actions, triggerLabel, }: ArtifactDownloadMenuProps): ReactNode;
182
+
46
183
  /**
47
184
  * Orchestrator for the `table`-typed artifact.
48
185
  *
@@ -51,6 +188,30 @@ declare function isSafeDownloadUrl(url: string): boolean;
51
188
  * Download is handled via `ArtifactDownloadButton` — a shared utility component that applies the
52
189
  * safe-URL guard and renders nothing for non-http(s) schemes.
53
190
  */
54
- declare function TableArtifact({ artifact }: ArtifactServiceProps<TableArtifactRecord>): ReactNode;
191
+ declare function TableArtifact({ artifact, labels, callbacks }: ArtifactServiceProps<TableArtifactRecord>): ReactNode;
192
+
193
+ /**
194
+ * Orchestrator for the `CHART`-typed artifact.
195
+ *
196
+ * Composes the ai-elements chrome primitives (`Artifact`, `ArtifactHeader`, `ArtifactTitle`,
197
+ * `ArtifactActions`, `ArtifactContent`) directly around the chart body (`ChartArtifactContent`),
198
+ * matching `TableArtifact`'s shape. Loading / error / unavailable / empty states render an inline
199
+ * `StatusMessage`; the ready state delegates to per-variant recharts trees inside
200
+ * `ChartArtifactContent`.
201
+ *
202
+ * The renderer is variant-agnostic at this level — it doesn't know about LINE vs BAR vs PIE.
203
+ * Variant dispatch lives inside `ChartArtifactContent` so the orchestrator can focus on the
204
+ * data lifecycle and the chrome.
205
+ *
206
+ * Labels for action buttons (download, copy-as-image) are pulled from the optional `labels`
207
+ * prop with per-key fallback to `DEFAULT_CHART_ARTIFACT_LABELS`. Consumers translate via their
208
+ * own i18n layer and pass the bag; non-i18n consumers omit it and get English defaults.
209
+ *
210
+ * `ArtifactCopyAsImageButton` snapshots the card root to PNG. The ref attaches directly to the
211
+ * `<Artifact>` primitive (which forwards refs as of this PR), so the captured DOM contains the
212
+ * artifact chrome exactly — no extra wrapper div, no layout-contract drift. The action toolbar
213
+ * carries `data-clay-capture-exclude` so its own buttons don't end up in the captured image.
214
+ */
215
+ declare function ChartArtifact({ artifact, labels, callbacks }: ArtifactServiceProps<ChartArtifactRecord>): ReactNode;
55
216
 
56
- export { ArtifactDownloadButton, type ArtifactDownloadButtonProps, ArtifactRecord, ArtifactService, ArtifactServiceProps, ArtifactServices, ArtifactType, TableArtifact, TableArtifactRecord, artifactToClipboardText, isSafeDownloadUrl };
217
+ export { ArtifactCopyAsImageButton, type ArtifactCopyAsImageButtonProps, ArtifactDownloadButton, type ArtifactDownloadButtonProps, ArtifactDownloadMenu, type ArtifactDownloadMenuCsvAction, type ArtifactDownloadMenuPngAction, type ArtifactDownloadMenuProps, ArtifactRecord, ArtifactService, ArtifactServiceProps, ArtifactServices, ArtifactType, ChartArtifact, ChartArtifactRecord, TableArtifact, TableArtifactRecord, artifactToClipboardText, isSafeDownloadUrl };
@@ -1,6 +1,7 @@
1
- import { c as ArtifactType, a as ArtifactService, A as ArtifactRecord, b as ArtifactServiceProps, T as TableArtifactRecord } from './types-3Gzk7cRt.js';
2
- export { d as TableColumn, e as TableConfig, f as TableRow, g as TableStats, h as artifactTypes } from './types-3Gzk7cRt.js';
3
- import { ReactNode } from 'react';
1
+ import { f as ArtifactType, d as ArtifactService, c as ArtifactRecord, e as ArtifactServiceProps, k as TableArtifactRecord, g as ChartArtifactRecord } from './types-GCkXbyFm.js';
2
+ export { A as ArtifactCallbacksOf, a as ArtifactDataRow, b as ArtifactLabelsOf, B as BarChartConfig, C as ChartArtifactLabels, h as ChartConfig, i as ChartStats, D as DEFAULT_CHART_ARTIFACT_LABELS, j as DEFAULT_TABLE_ARTIFACT_LABELS, L as LineChartConfig, P as PieChartConfig, T as TableArtifactLabels, l as TableColumn, m as TableConfig, n as TableRow, o as TableStats, p as artifactTypes } from './types-GCkXbyFm.js';
3
+ import { ReactNode, RefObject } from 'react';
4
+ export { C as ChartSeries, a as ChartVariant } from './types-B2aYk82c.js';
4
5
 
5
6
  /**
6
7
  * Map of artifact services keyed by `artifact.type`.
@@ -28,6 +29,19 @@ interface ArtifactDownloadButtonProps {
28
29
  * `data:` URIs smuggled into `presignedUrl`.
29
30
  */
30
31
  href: string;
32
+ /**
33
+ * Tooltip text + `aria-label` for the button. Optional — defaults to `"Download CSV"` so direct
34
+ * consumers don't have to pass anything for the common case. Per-type artifact orchestrators
35
+ * (`<ChartArtifact>`, `<TableArtifact>`) pass a translated value via their own `labels` prop so
36
+ * the button reads in the user's language.
37
+ */
38
+ label?: string;
39
+ /**
40
+ * Optional callback fired on click — runs alongside the browser's native download navigation
41
+ * (no `preventDefault`). Used for analytics / observability hooks; per-type artifact
42
+ * orchestrators wire this from their `callbacks` prop.
43
+ */
44
+ onClick?: () => void;
31
45
  }
32
46
  /**
33
47
  * Reusable download button for artifact headers. Anchor-based so the browser handles the download
@@ -36,13 +50,136 @@ interface ArtifactDownloadButtonProps {
36
50
  *
37
51
  * Drop this inside `<ArtifactActions>` in any per-type artifact orchestrator.
38
52
  */
39
- declare function ArtifactDownloadButton({ href }: ArtifactDownloadButtonProps): ReactNode;
53
+ declare function ArtifactDownloadButton({ href, label, onClick, }: ArtifactDownloadButtonProps): ReactNode;
40
54
  /**
41
55
  * Returns `true` only for `http:` and `https:` URLs. Rejects `javascript:`, `data:`, and any
42
56
  * other scheme that could execute code on click.
43
57
  */
44
58
  declare function isSafeDownloadUrl(url: string): boolean;
45
59
 
60
+ /** Props for `ArtifactCopyAsImageButton`. */
61
+ interface ArtifactCopyAsImageButtonProps {
62
+ /**
63
+ * Ref to the DOM node to capture as an image. Typically the artifact card root. The capture
64
+ * walks the subtree and includes everything except elements marked with
65
+ * `data-clay-capture-exclude` (the action toolbar should carry that marker so it doesn't
66
+ * capture itself).
67
+ */
68
+ targetRef: RefObject<HTMLElement | null>;
69
+ /**
70
+ * Tooltip text + `aria-label` for the idle state. Defaults to `"Copy Image"`. Per-type
71
+ * artifact orchestrators pass a translated value via their own `labels` prop so the button
72
+ * reads in the user's language. The transient working / success / error tooltips remain
73
+ * English-hardcoded — they flash for ~1.5s and the cost of translating them is rarely worth it.
74
+ */
75
+ label?: string;
76
+ /** Disable the button (e.g. while artifact data is still loading and the captured image would
77
+ * be empty / partial). */
78
+ disabled?: boolean;
79
+ /**
80
+ * Optional callback fired on click — runs alongside the copy attempt itself. Used for analytics
81
+ * / observability hooks; per-type artifact orchestrators wire this from their `callbacks` prop.
82
+ * Fires regardless of whether the copy ultimately succeeds (the result is reported via the
83
+ * button's own state flash).
84
+ */
85
+ onClick?: () => void;
86
+ }
87
+
88
+ /**
89
+ * Reusable "copy artifact as image" button for artifact headers. Drop it inside
90
+ * `<ArtifactActions>` alongside `ArtifactDownloadButton`.
91
+ *
92
+ * Captures the DOM node referenced by `targetRef`, rasterises it to PNG, and writes the result
93
+ * to the system clipboard. Must be invoked from a user gesture (the button click is enough).
94
+ *
95
+ * The button flashes a check icon on success and an alert icon on failure, reverting to its
96
+ * idle photo icon after ~1.5s. While capturing, it disables itself and shows a spinner.
97
+ *
98
+ * On failure, the rejection is logged via `console.warn` so production errors are visible in
99
+ * observability tooling (any consumer wiring a global console transport — Sentry, Datadog,
100
+ * Logfire — picks them up). The user-visible affordance is the error-state flash + tooltip.
101
+ */
102
+ declare function ArtifactCopyAsImageButton({ targetRef, label, disabled, onClick, }: ArtifactCopyAsImageButtonProps): ReactNode;
103
+
104
+ /**
105
+ * Per-format props for the CSV menu item. Pass within `actions.csv` to expose the item;
106
+ * omit the slot entirely to hide it. The item is also auto-hidden if `href` doesn't satisfy
107
+ * the `http(s):` safety guard — mirrors `ArtifactDownloadButton`'s defense against
108
+ * `javascript:` / `data:` URIs smuggled into a presigned URL field.
109
+ */
110
+ interface ArtifactDownloadMenuCsvAction {
111
+ /** Presigned URL backing the CSV download. The browser uses whatever filename the server
112
+ * supplies via `Content-Disposition`. */
113
+ href: string;
114
+ /** Label for the menu item. Defaults to `"Download CSV"`. */
115
+ label?: string;
116
+ /** Optional analytics callback. Fires alongside the browser-native download navigation. */
117
+ onSelect?: () => void;
118
+ }
119
+ /**
120
+ * Per-format props for the PNG menu item. Pass within `actions.png` to expose the item; omit
121
+ * the slot entirely to hide it. PNG capture rasterises `targetRef.current` via
122
+ * `@shapesos/clay/capture`'s `downloadNodeAsPng`.
123
+ */
124
+ interface ArtifactDownloadMenuPngAction {
125
+ /** Ref to the DOM node to rasterise. Typically the artifact card root. The capture walks the
126
+ * subtree and excludes anything marked with `data-clay-capture-exclude`. */
127
+ targetRef: RefObject<HTMLElement | null>;
128
+ /** Suggested filename for the saved file (without extension — the menu appends `.png`).
129
+ * Defaults to `"artifact"`. Pass artifact-title-derived names for recognisable downloads. */
130
+ filename?: string;
131
+ /** Label for the menu item. Defaults to `"Download PNG"`. */
132
+ label?: string;
133
+ /** Disable the menu item (e.g. while artifact data is still loading). Default: `false`. */
134
+ disabled?: boolean;
135
+ /** Optional analytics callback. Fires alongside the rasterise + download — regardless of
136
+ * whether the download ultimately succeeds. */
137
+ onSelect?: () => void;
138
+ }
139
+ /** Props for `ArtifactDownloadMenu`. */
140
+ interface ArtifactDownloadMenuProps {
141
+ /**
142
+ * Format-keyed bag of action descriptors. Each entry exposes one menu item; omit the slot
143
+ * to hide it. Grouping per-format props this way (rather than spreading flat
144
+ * `csvHref` / `pngFilename` / `pngLabel` props at the top level) keeps the consumer's call
145
+ * site readable as more formats land — a future `actions.svg` or `actions.xlsx` follows the
146
+ * same shape without growing the prop list at the call site.
147
+ *
148
+ * Caller responsibility: include at least one action. An empty `{}` renders a menu with no
149
+ * items, which has no UX value — orchestrators should gate the entire `<ArtifactDownloadMenu>`
150
+ * mount on "at least one format reachable" before passing this prop.
151
+ *
152
+ * **Future generalisation** — if more action shapes land (SVG, XLSX, share-link, …), consider
153
+ * lifting these into a shared `ArtifactAction` discriminated union that both this menu and
154
+ * a future `<ArtifactActions>` toolbar can render generically. Postponed until a second
155
+ * non-Download action type appears — premature abstraction with two flavours.
156
+ */
157
+ actions: {
158
+ /** CSV download via presigned URL. Browser-native navigation; consumer i18n + analytics. */
159
+ csv?: ArtifactDownloadMenuCsvAction;
160
+ /** PNG download via DOM-to-image rasterise. Browser-only (capture entry). */
161
+ png?: ArtifactDownloadMenuPngAction;
162
+ };
163
+ /** Tooltip + `aria-label` for the trigger button. Defaults to `"Download"`. */
164
+ triggerLabel?: string;
165
+ }
166
+
167
+ /**
168
+ * Reusable "Download" affordance for artifact headers. Renders as a single icon-button trigger;
169
+ * clicking it opens a menu with one item per format the caller passes via `actions`. Today's
170
+ * formats: CSV (presigned URL) + PNG (DOM-to-image rasterise). Future formats (SVG, XLSX, …)
171
+ * slot into the same `actions` bag without touching the call-site prop list.
172
+ *
173
+ * Drop this inside `<ArtifactActions>` in any per-type artifact orchestrator that supports
174
+ * multiple download formats. For single-format artifacts (e.g. a future table artifact that
175
+ * only ships CSV), prefer the simpler `ArtifactDownloadButton` instead.
176
+ *
177
+ * The menu uses Radix's `DropdownMenu` primitive (vendored in `src/components/ui/dropdown-menu.tsx`)
178
+ * with `asChild` on the trigger so clay's `IconButton` is the real button — preserves the
179
+ * design-system look across all action affordances.
180
+ */
181
+ declare function ArtifactDownloadMenu({ actions, triggerLabel, }: ArtifactDownloadMenuProps): ReactNode;
182
+
46
183
  /**
47
184
  * Orchestrator for the `table`-typed artifact.
48
185
  *
@@ -51,6 +188,30 @@ declare function isSafeDownloadUrl(url: string): boolean;
51
188
  * Download is handled via `ArtifactDownloadButton` — a shared utility component that applies the
52
189
  * safe-URL guard and renders nothing for non-http(s) schemes.
53
190
  */
54
- declare function TableArtifact({ artifact }: ArtifactServiceProps<TableArtifactRecord>): ReactNode;
191
+ declare function TableArtifact({ artifact, labels, callbacks }: ArtifactServiceProps<TableArtifactRecord>): ReactNode;
192
+
193
+ /**
194
+ * Orchestrator for the `CHART`-typed artifact.
195
+ *
196
+ * Composes the ai-elements chrome primitives (`Artifact`, `ArtifactHeader`, `ArtifactTitle`,
197
+ * `ArtifactActions`, `ArtifactContent`) directly around the chart body (`ChartArtifactContent`),
198
+ * matching `TableArtifact`'s shape. Loading / error / unavailable / empty states render an inline
199
+ * `StatusMessage`; the ready state delegates to per-variant recharts trees inside
200
+ * `ChartArtifactContent`.
201
+ *
202
+ * The renderer is variant-agnostic at this level — it doesn't know about LINE vs BAR vs PIE.
203
+ * Variant dispatch lives inside `ChartArtifactContent` so the orchestrator can focus on the
204
+ * data lifecycle and the chrome.
205
+ *
206
+ * Labels for action buttons (download, copy-as-image) are pulled from the optional `labels`
207
+ * prop with per-key fallback to `DEFAULT_CHART_ARTIFACT_LABELS`. Consumers translate via their
208
+ * own i18n layer and pass the bag; non-i18n consumers omit it and get English defaults.
209
+ *
210
+ * `ArtifactCopyAsImageButton` snapshots the card root to PNG. The ref attaches directly to the
211
+ * `<Artifact>` primitive (which forwards refs as of this PR), so the captured DOM contains the
212
+ * artifact chrome exactly — no extra wrapper div, no layout-contract drift. The action toolbar
213
+ * carries `data-clay-capture-exclude` so its own buttons don't end up in the captured image.
214
+ */
215
+ declare function ChartArtifact({ artifact, labels, callbacks }: ArtifactServiceProps<ChartArtifactRecord>): ReactNode;
55
216
 
56
- export { ArtifactDownloadButton, type ArtifactDownloadButtonProps, ArtifactRecord, ArtifactService, ArtifactServiceProps, ArtifactServices, ArtifactType, TableArtifact, TableArtifactRecord, artifactToClipboardText, isSafeDownloadUrl };
217
+ export { ArtifactCopyAsImageButton, type ArtifactCopyAsImageButtonProps, ArtifactDownloadButton, type ArtifactDownloadButtonProps, ArtifactDownloadMenu, type ArtifactDownloadMenuCsvAction, type ArtifactDownloadMenuPngAction, type ArtifactDownloadMenuProps, ArtifactRecord, ArtifactService, ArtifactServiceProps, ArtifactServices, ArtifactType, ChartArtifact, ChartArtifactRecord, TableArtifact, TableArtifactRecord, artifactToClipboardText, isSafeDownloadUrl };
package/dist/artifacts.js CHANGED
@@ -1,20 +1,35 @@
1
- import "./chunk-MEJESPTZ.js";
1
+ import "./chunk-RSRNSWJN.js";
2
2
  import {
3
+ ArtifactCopyAsImageButton,
3
4
  ArtifactDownloadButton,
5
+ ArtifactDownloadMenu,
4
6
  ArtifactServices,
7
+ ChartArtifact,
8
+ DEFAULT_CHART_ARTIFACT_LABELS,
9
+ DEFAULT_TABLE_ARTIFACT_LABELS,
5
10
  TableArtifact,
6
11
  artifactToClipboardText,
7
12
  artifactTypes,
8
13
  isSafeDownloadUrl
9
- } from "./chunk-BX5TCEPR.js";
10
- import "./chunk-L35M3OD5.js";
14
+ } from "./chunk-DT44KNCV.js";
15
+ import "./chunk-LXYCT4YO.js";
16
+ import "./chunk-QXGYMDIA.js";
17
+ import "./chunk-C77QMQNT.js";
18
+ import "./chunk-SV24ONND.js";
19
+ import "./chunk-4MZZH3WX.js";
20
+ import "./chunk-P6GUNIAE.js";
11
21
  import "./chunk-OBOXCBDL.js";
12
22
  import "./chunk-OLJIJYB5.js";
13
23
  import "./chunk-JF3P66JF.js";
14
24
  import "./chunk-5WRI5ZAA.js";
15
25
  export {
26
+ ArtifactCopyAsImageButton,
16
27
  ArtifactDownloadButton,
28
+ ArtifactDownloadMenu,
17
29
  ArtifactServices,
30
+ ChartArtifact,
31
+ DEFAULT_CHART_ARTIFACT_LABELS,
32
+ DEFAULT_TABLE_ARTIFACT_LABELS,
18
33
  TableArtifact,
19
34
  artifactToClipboardText,
20
35
  artifactTypes,