@actioneer/ads 1.0.9 → 1.0.10
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/DESIGN.md +98 -57
- package/README.md +19 -7
- package/components/answer.js +1 -1
- package/components/assistant-ui/composer-harness.js +13 -10
- package/components/body-page-header.d.ts +9 -4
- package/components/body-page-header.js +10 -10
- package/components/breadcrumbs.js +22 -22
- package/components/card.js +18 -18
- package/components/chart.d.ts +9 -0
- package/components/chart.js +738 -717
- package/components/chip.js +12 -12
- package/components/collection-header.js +4 -4
- package/components/connector-card.js +30 -30
- package/components/date-range-picker.js +1 -1
- package/components/detail-list.d.ts +28 -0
- package/components/detail-list.js +52 -0
- package/components/drawer.d.ts +38 -15
- package/components/drawer.js +150 -86
- package/components/empty-state.d.ts +3 -2
- package/components/empty-state.js +22 -22
- package/components/field.d.ts +16 -0
- package/components/field.js +63 -42
- package/components/file-dropzone.d.ts +15 -4
- package/components/file-dropzone.js +100 -64
- package/components/filter-bar.d.ts +44 -0
- package/components/filter-bar.js +89 -0
- package/components/index.d.ts +3 -0
- package/components/index.js +526 -513
- package/components/input-field.d.ts +1 -1
- package/components/input-field.js +24 -22
- package/components/modal.js +56 -53
- package/components/panel.js +26 -27
- package/components/sidebar.js +54 -54
- package/components/sparkline.d.ts +30 -0
- package/components/sparkline.js +69 -0
- package/demo/components/add-to-artifact.js +5 -2
- package/examples/README.md +4 -2
- package/examples/call-logs-screen.tsx +381 -0
- package/examples/campaign-analysis-screen.tsx +114 -72
- package/examples/campaigns-screen.tsx +218 -160
- package/examples/guardrails-settings-screen.tsx +123 -0
- package/fonts/geist-variable.woff2 +0 -0
- package/fonts.css +12 -17
- package/lib/icons.js +3 -3
- package/llms.txt +107 -39
- package/manifest.json +3100 -892
- package/package.json +1 -1
- package/styles.css +102 -59
- package/theme.css +81 -37
- package/fonts/aribau-grotesk-medium.woff2 +0 -0
- package/fonts/aribau-grotesk-regular.woff2 +0 -0
package/components/sidebar.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as r, jsxs as c } from "react/jsx-runtime";
|
|
3
|
-
import * as
|
|
3
|
+
import * as o from "react";
|
|
4
4
|
import { MotionConfig as j, motion as _ } from "motion/react";
|
|
5
5
|
import { User as E, PanelLeft as H } from "../lib/icons.js";
|
|
6
|
-
import { cn as
|
|
6
|
+
import { cn as n } from "../lib/cn.js";
|
|
7
7
|
import { springSidebar as I } from "../lib/motion.js";
|
|
8
8
|
import { Tooltip as L } from "./tooltip.js";
|
|
9
9
|
import { Avatar as M } from "./avatar.js";
|
|
10
|
-
const z =
|
|
10
|
+
const z = o.createContext({
|
|
11
11
|
collapsed: !1,
|
|
12
12
|
toggle: () => {
|
|
13
13
|
},
|
|
@@ -15,9 +15,9 @@ const z = n.createContext({
|
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
17
|
function W() {
|
|
18
|
-
return
|
|
18
|
+
return o.useContext(z);
|
|
19
19
|
}
|
|
20
|
-
const K =
|
|
20
|
+
const K = o.forwardRef(
|
|
21
21
|
({
|
|
22
22
|
className: a,
|
|
23
23
|
collapsed: e,
|
|
@@ -27,27 +27,27 @@ const K = n.forwardRef(
|
|
|
27
27
|
keyboardToggle: d = !0,
|
|
28
28
|
...l
|
|
29
29
|
}, b) => {
|
|
30
|
-
const [g, y] =
|
|
30
|
+
const [g, y] = o.useState(i), f = e !== void 0, u = f ? e : g, m = o.useCallback(
|
|
31
31
|
(p) => {
|
|
32
32
|
f || y(p), t == null || t(p);
|
|
33
33
|
},
|
|
34
34
|
[f, t]
|
|
35
|
-
),
|
|
35
|
+
), v = o.useCallback(
|
|
36
36
|
() => m(!u),
|
|
37
37
|
[u, m]
|
|
38
38
|
);
|
|
39
|
-
|
|
39
|
+
o.useEffect(() => {
|
|
40
40
|
if (!d) return;
|
|
41
41
|
const p = (h) => {
|
|
42
|
-
(h.metaKey || h.ctrlKey) && h.key.toLowerCase() === "b" && (h.preventDefault(),
|
|
42
|
+
(h.metaKey || h.ctrlKey) && h.key.toLowerCase() === "b" && (h.preventDefault(), v());
|
|
43
43
|
};
|
|
44
44
|
return document.addEventListener("keydown", p), () => document.removeEventListener("keydown", p);
|
|
45
|
-
}, [d,
|
|
46
|
-
const
|
|
47
|
-
() => ({ collapsed: u, toggle:
|
|
48
|
-
[u,
|
|
45
|
+
}, [d, v]);
|
|
46
|
+
const x = o.useMemo(
|
|
47
|
+
() => ({ collapsed: u, toggle: v, setCollapsed: m }),
|
|
48
|
+
[u, v, m]
|
|
49
49
|
);
|
|
50
|
-
return /* @__PURE__ */ r(z.Provider, { value:
|
|
50
|
+
return /* @__PURE__ */ r(z.Provider, { value: x, children: /* @__PURE__ */ r(j, { reducedMotion: "user", children: /* @__PURE__ */ r(
|
|
51
51
|
_.aside,
|
|
52
52
|
{
|
|
53
53
|
ref: b,
|
|
@@ -63,7 +63,7 @@ const K = n.forwardRef(
|
|
|
63
63
|
opacity: 1
|
|
64
64
|
},
|
|
65
65
|
transition: I,
|
|
66
|
-
className:
|
|
66
|
+
className: n(
|
|
67
67
|
"group/sidebar flex h-full shrink-0 flex-col bg-background",
|
|
68
68
|
a
|
|
69
69
|
),
|
|
@@ -103,7 +103,7 @@ function k({
|
|
|
103
103
|
onClick: (l) => {
|
|
104
104
|
e == null || e(l), d();
|
|
105
105
|
},
|
|
106
|
-
className:
|
|
106
|
+
className: n(
|
|
107
107
|
"inline-flex size-(--sidebar-item) shrink-0 items-center justify-center rounded-sm border border-transparent text-muted-foreground",
|
|
108
108
|
"transition-colors hover:border-border hover:bg-elevated hover:text-foreground",
|
|
109
109
|
"outline-none focus-visible:ring-3 focus-visible:ring-ring",
|
|
@@ -126,8 +126,8 @@ function Z({
|
|
|
126
126
|
className: d,
|
|
127
127
|
...l
|
|
128
128
|
}) {
|
|
129
|
-
const b =
|
|
130
|
-
b ? "flex min-w-0 items-center rounded-m outline-none focus-visible:ring-3 focus-visible:ring-ring" :
|
|
129
|
+
const b = o.isValidElement(a) && a.type === R, g = n(
|
|
130
|
+
b ? "flex min-w-0 items-center rounded-m outline-none focus-visible:ring-3 focus-visible:ring-ring" : n(
|
|
131
131
|
// 20px mark centered in a 32px square — the same box as every other rail icon.
|
|
132
132
|
// group/brand lets a BrandMark logo play its blip loop on hover.
|
|
133
133
|
"group/brand flex size-(--sidebar-item) items-center justify-center",
|
|
@@ -141,7 +141,7 @@ function Z({
|
|
|
141
141
|
return /* @__PURE__ */ c(
|
|
142
142
|
"div",
|
|
143
143
|
{
|
|
144
|
-
className:
|
|
144
|
+
className: n(
|
|
145
145
|
"flex h-(--sidebar-header) shrink-0 items-center justify-between gap-2 px-4",
|
|
146
146
|
"group-data-[collapsed=true]/sidebar:justify-center group-data-[collapsed=true]/sidebar:px-2",
|
|
147
147
|
d
|
|
@@ -158,14 +158,14 @@ function Z({
|
|
|
158
158
|
}
|
|
159
159
|
);
|
|
160
160
|
}
|
|
161
|
-
const R =
|
|
161
|
+
const R = o.forwardRef(
|
|
162
162
|
({ className: a, name: e, logoSrc: i, showName: t = !0, ...s }, d) => {
|
|
163
163
|
const l = e.trim().charAt(0).toUpperCase();
|
|
164
164
|
return /* @__PURE__ */ c(
|
|
165
165
|
"span",
|
|
166
166
|
{
|
|
167
167
|
ref: d,
|
|
168
|
-
className:
|
|
168
|
+
className: n("flex min-w-0 items-center gap-2.5", a),
|
|
169
169
|
...s,
|
|
170
170
|
children: [
|
|
171
171
|
i ? /* @__PURE__ */ r(
|
|
@@ -192,12 +192,12 @@ const R = n.forwardRef(
|
|
|
192
192
|
}
|
|
193
193
|
);
|
|
194
194
|
R.displayName = "SidebarWorkspace";
|
|
195
|
-
const q =
|
|
195
|
+
const q = o.forwardRef(
|
|
196
196
|
({ className: a, ...e }, i) => /* @__PURE__ */ r(
|
|
197
197
|
"div",
|
|
198
198
|
{
|
|
199
199
|
ref: i,
|
|
200
|
-
className:
|
|
200
|
+
className: n(
|
|
201
201
|
"flex h-(--sidebar-header) shrink-0 items-center justify-between gap-2 px-3",
|
|
202
202
|
"group-data-[collapsed=true]/sidebar:justify-center group-data-[collapsed=true]/sidebar:px-2",
|
|
203
203
|
a
|
|
@@ -207,31 +207,31 @@ const q = n.forwardRef(
|
|
|
207
207
|
)
|
|
208
208
|
);
|
|
209
209
|
q.displayName = "SidebarHeader";
|
|
210
|
-
const A =
|
|
211
|
-
({ className: a, ...e }, i) => /* @__PURE__ */ r("nav", { ref: i, className:
|
|
210
|
+
const A = o.forwardRef(
|
|
211
|
+
({ className: a, ...e }, i) => /* @__PURE__ */ r("nav", { ref: i, className: n("min-h-0 flex-1 space-y-5 overflow-y-auto p-3", a), ...e })
|
|
212
212
|
);
|
|
213
213
|
A.displayName = "SidebarNav";
|
|
214
|
-
const B =
|
|
214
|
+
const B = o.forwardRef(
|
|
215
215
|
({ className: a, label: e, children: i, ...t }, s) => /* @__PURE__ */ c("div", { ref: s, className: a, ...t, children: [
|
|
216
216
|
e && /* @__PURE__ */ r("div", { className: "mb-1.5 px-3 text-s font-normal uppercase leading-4 tracking-wider text-tertiary group-data-[collapsed=true]/sidebar:hidden", children: e }),
|
|
217
217
|
/* @__PURE__ */ r("div", { className: "flex flex-col gap-0.5 group-data-[collapsed=true]/sidebar:gap-2", children: i })
|
|
218
218
|
] })
|
|
219
219
|
);
|
|
220
220
|
B.displayName = "SidebarSection";
|
|
221
|
-
const D =
|
|
221
|
+
const D = o.forwardRef(
|
|
222
222
|
({ className: a, icon: e, isActive: i, endContent: t, children: s, title: d, ...l }, b) => /* @__PURE__ */ c(
|
|
223
223
|
"a",
|
|
224
224
|
{
|
|
225
225
|
ref: b,
|
|
226
226
|
"aria-current": i ? "page" : void 0,
|
|
227
227
|
title: d ?? (typeof s == "string" ? s : void 0),
|
|
228
|
-
className:
|
|
228
|
+
className: n(
|
|
229
229
|
"group/sidebar-item flex h-9 items-center gap-2.5 rounded-md border border-transparent px-3 text-m leading-[var(--text-m--line-height)] font-normal text-sidebar-foreground",
|
|
230
|
-
"transition-[background-color,border-color,color] duration-150 ease-out motion-reduce:transition-none",
|
|
230
|
+
"transition-[background-color,border-color,color,box-shadow] duration-150 ease-out motion-reduce:transition-none",
|
|
231
231
|
"outline-none focus-visible:ring-3 focus-visible:ring-ring",
|
|
232
232
|
// Collapsed: a centered square (--sidebar-item) so every rail item lines up.
|
|
233
233
|
"group-data-[collapsed=true]/sidebar:mx-auto group-data-[collapsed=true]/sidebar:size-(--sidebar-item) group-data-[collapsed=true]/sidebar:justify-center group-data-[collapsed=true]/sidebar:p-0",
|
|
234
|
-
i ? "bg-sidebar-accent text-sidebar-accent-foreground" : "hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
|
|
234
|
+
i ? "bg-sidebar-accent text-sidebar-accent-foreground shadow-nav-active" : "hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
|
|
235
235
|
a
|
|
236
236
|
),
|
|
237
237
|
...l,
|
|
@@ -241,7 +241,7 @@ const D = n.forwardRef(
|
|
|
241
241
|
{
|
|
242
242
|
"aria-hidden": !0,
|
|
243
243
|
className: "flex shrink-0 items-center justify-center transition-transform duration-150 ease-out group-hover/sidebar-item:scale-110 motion-reduce:transition-none motion-reduce:group-hover/sidebar-item:scale-100 [&_svg]:size-4 [&_svg]:shrink-0",
|
|
244
|
-
children: i &&
|
|
244
|
+
children: i && o.isValidElement(e) ? o.cloneElement(e, { weight: "fill" }) : e
|
|
245
245
|
}
|
|
246
246
|
),
|
|
247
247
|
/* @__PURE__ */ r("span", { className: "min-w-0 flex-1 truncate group-data-[collapsed=true]/sidebar:hidden", children: s }),
|
|
@@ -251,24 +251,24 @@ const D = n.forwardRef(
|
|
|
251
251
|
)
|
|
252
252
|
);
|
|
253
253
|
D.displayName = "SidebarItem";
|
|
254
|
-
const F =
|
|
254
|
+
const F = o.forwardRef(
|
|
255
255
|
({ className: a, ...e }, i) => /* @__PURE__ */ r(
|
|
256
256
|
"div",
|
|
257
257
|
{
|
|
258
258
|
ref: i,
|
|
259
|
-
className:
|
|
259
|
+
className: n("shrink-0 p-3 group-data-[collapsed=true]/sidebar:px-2", a),
|
|
260
260
|
...e
|
|
261
261
|
}
|
|
262
262
|
)
|
|
263
263
|
);
|
|
264
264
|
F.displayName = "SidebarFooter";
|
|
265
|
-
const U =
|
|
265
|
+
const U = o.forwardRef(
|
|
266
266
|
({ className: a, icon: e, children: i, ...t }, s) => /* @__PURE__ */ r("div", { className: "px-3 pb-0.5 group-data-[collapsed=true]/sidebar:px-2", children: /* @__PURE__ */ c(
|
|
267
267
|
"button",
|
|
268
268
|
{
|
|
269
269
|
ref: s,
|
|
270
270
|
type: "button",
|
|
271
|
-
className:
|
|
271
|
+
className: n(
|
|
272
272
|
"flex h-9 w-full items-center justify-start gap-2 rounded-md px-3",
|
|
273
273
|
"text-m leading-[var(--text-m--line-height)] font-normal text-sidebar-foreground",
|
|
274
274
|
// Reads as a normal nav item: transparent at rest, the shared White
|
|
@@ -289,12 +289,12 @@ const U = n.forwardRef(
|
|
|
289
289
|
) })
|
|
290
290
|
);
|
|
291
291
|
U.displayName = "SidebarAction";
|
|
292
|
-
const V =
|
|
292
|
+
const V = o.forwardRef(
|
|
293
293
|
({ className: a, label: e, children: i, ...t }, s) => /* @__PURE__ */ c(
|
|
294
294
|
"div",
|
|
295
295
|
{
|
|
296
296
|
ref: s,
|
|
297
|
-
className:
|
|
297
|
+
className: n("group-data-[collapsed=true]/sidebar:hidden", a),
|
|
298
298
|
...t,
|
|
299
299
|
children: [
|
|
300
300
|
e && /* @__PURE__ */ r("div", { className: "mb-1.5 px-3 text-s font-normal uppercase leading-4 tracking-wider text-tertiary", children: e }),
|
|
@@ -304,27 +304,27 @@ const V = n.forwardRef(
|
|
|
304
304
|
)
|
|
305
305
|
);
|
|
306
306
|
V.displayName = "SidebarHistory";
|
|
307
|
-
const $ =
|
|
308
|
-
const g =
|
|
309
|
-
|
|
310
|
-
const
|
|
311
|
-
if (!
|
|
307
|
+
const $ = o.forwardRef(({ className: a, children: e, title: i, action: t, isActive: s, icon: d, ...l }, b) => {
|
|
308
|
+
const g = o.useRef(null), y = o.useRef(null), [f, u] = o.useState(0);
|
|
309
|
+
o.useLayoutEffect(() => {
|
|
310
|
+
const x = g.current, p = y.current;
|
|
311
|
+
if (!x || !p) return;
|
|
312
312
|
const h = () => {
|
|
313
|
-
const w = p.scrollWidth -
|
|
313
|
+
const w = p.scrollWidth - x.clientWidth;
|
|
314
314
|
u(w > 0 ? w + (t ? 32 : 0) : 0);
|
|
315
315
|
};
|
|
316
316
|
h();
|
|
317
317
|
const N = new ResizeObserver(h);
|
|
318
|
-
return N.observe(
|
|
318
|
+
return N.observe(x), N.observe(p), () => N.disconnect();
|
|
319
319
|
}, [e, t]);
|
|
320
|
-
const m = f > 0,
|
|
320
|
+
const m = f > 0, v = Math.max(500, Math.round(f * 18));
|
|
321
321
|
return /* @__PURE__ */ c(
|
|
322
322
|
"div",
|
|
323
323
|
{
|
|
324
|
-
className:
|
|
324
|
+
className: n(
|
|
325
325
|
"group/hist relative flex items-center rounded-md transition-colors",
|
|
326
326
|
"text-sidebar-foreground",
|
|
327
|
-
s ? "bg-sidebar-accent text-sidebar-accent-foreground" : "hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground"
|
|
327
|
+
s ? "bg-sidebar-accent text-sidebar-accent-foreground shadow-nav-active" : "hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground"
|
|
328
328
|
),
|
|
329
329
|
children: [
|
|
330
330
|
d && /* @__PURE__ */ r(
|
|
@@ -340,7 +340,7 @@ const $ = n.forwardRef(({ className: a, children: e, title: i, action: t, isActi
|
|
|
340
340
|
{
|
|
341
341
|
ref: b,
|
|
342
342
|
title: i ?? (typeof e == "string" ? e : void 0),
|
|
343
|
-
className:
|
|
343
|
+
className: n(
|
|
344
344
|
// Left pad matches a SidebarItem's text column (px-3 + icon size-4 +
|
|
345
345
|
// gap-2.5 = 2.375rem) so history titles line up under the nav labels.
|
|
346
346
|
"block min-w-0 flex-1 rounded-md py-1.5 pr-3 ps-(--sidebar-text-indent) text-m leading-[var(--text-m--line-height)] font-normal",
|
|
@@ -352,7 +352,7 @@ const $ = n.forwardRef(({ className: a, children: e, title: i, action: t, isActi
|
|
|
352
352
|
"span",
|
|
353
353
|
{
|
|
354
354
|
ref: g,
|
|
355
|
-
className:
|
|
355
|
+
className: n(
|
|
356
356
|
"block overflow-hidden",
|
|
357
357
|
// Rest: fade the right edge (no ellipsis). Hover: the title scrolls,
|
|
358
358
|
// so fade the LEFT edge where it exits; the action backdrop (or the
|
|
@@ -364,14 +364,14 @@ const $ = n.forwardRef(({ className: a, children: e, title: i, action: t, isActi
|
|
|
364
364
|
"span",
|
|
365
365
|
{
|
|
366
366
|
ref: y,
|
|
367
|
-
className:
|
|
367
|
+
className: n(
|
|
368
368
|
"block w-max whitespace-nowrap transition-transform ease-linear",
|
|
369
369
|
m && "group-hover/hist:[transform:translateX(var(--mq-x))]",
|
|
370
370
|
"motion-reduce:transition-none motion-reduce:group-hover/hist:[transform:none]"
|
|
371
371
|
),
|
|
372
372
|
style: {
|
|
373
373
|
"--mq-x": `-${f}px`,
|
|
374
|
-
transitionDuration: `${
|
|
374
|
+
transitionDuration: `${v}ms`
|
|
375
375
|
},
|
|
376
376
|
children: e
|
|
377
377
|
}
|
|
@@ -383,7 +383,7 @@ const $ = n.forwardRef(({ className: a, children: e, title: i, action: t, isActi
|
|
|
383
383
|
t && /* @__PURE__ */ r(
|
|
384
384
|
"span",
|
|
385
385
|
{
|
|
386
|
-
className:
|
|
386
|
+
className: n(
|
|
387
387
|
// Rounded end matches the row's radius so the backdrop doesn't
|
|
388
388
|
// square off the highlight's right corners.
|
|
389
389
|
"absolute inset-y-0 right-0 flex items-center rounded-e-md pl-8 pr-1",
|
|
@@ -401,12 +401,12 @@ const $ = n.forwardRef(({ className: a, children: e, title: i, action: t, isActi
|
|
|
401
401
|
);
|
|
402
402
|
});
|
|
403
403
|
$.displayName = "SidebarHistoryItem";
|
|
404
|
-
const O =
|
|
404
|
+
const O = o.forwardRef(
|
|
405
405
|
({ className: a, name: e, role: i, src: t, hideAvatar: s, ...d }, l) => /* @__PURE__ */ c(
|
|
406
406
|
"a",
|
|
407
407
|
{
|
|
408
408
|
ref: l,
|
|
409
|
-
className:
|
|
409
|
+
className: n(
|
|
410
410
|
"flex items-center gap-2.5 rounded-md border border-transparent p-2 transition-colors hover:border-wg10",
|
|
411
411
|
"outline-none focus-visible:ring-3 focus-visible:ring-ring",
|
|
412
412
|
"group-data-[collapsed=true]/sidebar:mx-auto group-data-[collapsed=true]/sidebar:size-(--sidebar-item) group-data-[collapsed=true]/sidebar:justify-center group-data-[collapsed=true]/sidebar:p-0",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Sparkline — a tiny, axis-less trend line for a stat card (principle
|
|
4
|
+
* `analytics-surfaces`, user-mandated 2026-11-14).
|
|
5
|
+
*
|
|
6
|
+
* It draws one series in a chart-palette colour: a 2px line, a wash under it
|
|
7
|
+
* that fades top-to-bottom from 20% of the colour to nothing (the same wash
|
|
8
|
+
* `LineChart` carries), and a dot on the latest value. There are no axes,
|
|
9
|
+
* gridlines, labels or tooltip — the stat card's number is the value; the
|
|
10
|
+
* sparkline only says which way it has been moving. It fills its container's
|
|
11
|
+
* width; give it a height.
|
|
12
|
+
*
|
|
13
|
+
* Use it inside a resting stat card, beside the number, or in a table's
|
|
14
|
+
* "Last 7 days" column at `height={28}` with `dot={false}` (principle
|
|
15
|
+
* `collection-screens`). For a trend people read values from, use `LineChart`.
|
|
16
|
+
*/
|
|
17
|
+
export type SparklineColor = 1 | 2 | 3 | 4 | 5 | 6;
|
|
18
|
+
export interface SparklineProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "color"> {
|
|
19
|
+
/** The series, oldest first. Needs at least two values to draw. */
|
|
20
|
+
data: number[];
|
|
21
|
+
/** Which `chart-1…6` series colour to draw in. @default 1 */
|
|
22
|
+
color?: SparklineColor;
|
|
23
|
+
/** Height in px. @default 48 */
|
|
24
|
+
height?: number;
|
|
25
|
+
/** Mark the latest value with a round dot. Turn off in table cells. @default true */
|
|
26
|
+
dot?: boolean;
|
|
27
|
+
/** Accessible summary of the trend, e.g. "Calls analysed rising over 7 days". */
|
|
28
|
+
label: string;
|
|
29
|
+
}
|
|
30
|
+
export declare const Sparkline: React.ForwardRefExoticComponent<SparklineProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as c, jsx as o } from "react/jsx-runtime";
|
|
3
|
+
import * as u from "react";
|
|
4
|
+
import { cn as j } from "../lib/cn.js";
|
|
5
|
+
const r = 100, m = 4, z = u.forwardRef(
|
|
6
|
+
({ className: $, data: k, color: h = 1, height: e = 48, dot: v = !0, label: x, style: b, ...y }, g) => {
|
|
7
|
+
const d = u.useId().replace(/[^a-zA-Z0-9]/g, ""), n = `var(--color-chart-${h})`, s = k.filter((a) => Number.isFinite(a)), p = Math.min(...s), w = Math.max(...s) - p || 1, t = s.map((a, i) => [
|
|
8
|
+
s.length > 1 ? i / (s.length - 1) * r : r,
|
|
9
|
+
m + (e - 2 * m) * (1 - (a - p) / w)
|
|
10
|
+
]), f = t.map(([a, i], N) => `${N === 0 ? "M" : "L"}${a.toFixed(2)},${i.toFixed(2)}`).join(" "), L = t.length > 1 ? `${f} L${r},${e} L0,${e} Z` : "", l = t[t.length - 1];
|
|
11
|
+
return /* @__PURE__ */ c(
|
|
12
|
+
"div",
|
|
13
|
+
{
|
|
14
|
+
ref: g,
|
|
15
|
+
"data-slot": "sparkline",
|
|
16
|
+
role: "img",
|
|
17
|
+
"aria-label": x,
|
|
18
|
+
className: j("relative w-full", $),
|
|
19
|
+
style: { height: e, ...b },
|
|
20
|
+
...y,
|
|
21
|
+
children: [
|
|
22
|
+
t.length > 1 && /* @__PURE__ */ c(
|
|
23
|
+
"svg",
|
|
24
|
+
{
|
|
25
|
+
"aria-hidden": !0,
|
|
26
|
+
className: "absolute inset-0 size-full overflow-visible",
|
|
27
|
+
viewBox: `0 0 ${r} ${e}`,
|
|
28
|
+
preserveAspectRatio: "none",
|
|
29
|
+
children: [
|
|
30
|
+
/* @__PURE__ */ o("defs", { children: /* @__PURE__ */ c("linearGradient", { id: `${d}-wash`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
31
|
+
/* @__PURE__ */ o("stop", { offset: "0%", stopColor: n, stopOpacity: 0.2 }),
|
|
32
|
+
/* @__PURE__ */ o("stop", { offset: "100%", stopColor: n, stopOpacity: 0 })
|
|
33
|
+
] }) }),
|
|
34
|
+
/* @__PURE__ */ o("path", { "data-slot": "sparkline-area", d: L, fill: `url(#${d}-wash)`, stroke: "none" }),
|
|
35
|
+
/* @__PURE__ */ o(
|
|
36
|
+
"path",
|
|
37
|
+
{
|
|
38
|
+
"data-slot": "sparkline-line",
|
|
39
|
+
d: f,
|
|
40
|
+
fill: "none",
|
|
41
|
+
stroke: n,
|
|
42
|
+
strokeWidth: 2,
|
|
43
|
+
strokeLinecap: "round",
|
|
44
|
+
strokeLinejoin: "round",
|
|
45
|
+
vectorEffect: "non-scaling-stroke"
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
),
|
|
51
|
+
v && l && t.length > 1 && // The end dot is HTML so it stays round while the SVG stretches.
|
|
52
|
+
/* @__PURE__ */ o(
|
|
53
|
+
"span",
|
|
54
|
+
{
|
|
55
|
+
"aria-hidden": !0,
|
|
56
|
+
"data-slot": "sparkline-dot",
|
|
57
|
+
className: "absolute size-2 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-card",
|
|
58
|
+
style: { left: `${l[0] / r * 100}%`, top: `${l[1] / e * 100}%`, background: n }
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
z.displayName = "Sparkline";
|
|
67
|
+
export {
|
|
68
|
+
z as Sparkline
|
|
69
|
+
};
|
|
@@ -36,6 +36,7 @@ import "../../components/autocomplete.js";
|
|
|
36
36
|
import "../../components/slider.js";
|
|
37
37
|
import "../../components/segmented.js";
|
|
38
38
|
import "../../components/filters.js";
|
|
39
|
+
import "../../components/filter-bar.js";
|
|
39
40
|
import { Modal as q, ModalHeader as J, ModalTitle as Q, ModalBody as x, ModalFooter as g } from "../../components/modal.js";
|
|
40
41
|
import "../../components/drawer.js";
|
|
41
42
|
import "../../components/popover.js";
|
|
@@ -56,6 +57,8 @@ import "../../components/avatar.js";
|
|
|
56
57
|
import "../../components/badge.js";
|
|
57
58
|
import "../../components/chip.js";
|
|
58
59
|
import "../../components/timeline.js";
|
|
60
|
+
import "../../components/detail-list.js";
|
|
61
|
+
import "../../components/sparkline.js";
|
|
59
62
|
import "../../components/alert.js";
|
|
60
63
|
import "../../components/surface-loader.js";
|
|
61
64
|
import "../../components/pixel-blast-svg.js";
|
|
@@ -107,7 +110,7 @@ import "../../components/assistant-ui/quote.js";
|
|
|
107
110
|
import "../../components/assistant-ui/sources.js";
|
|
108
111
|
import "../../components/assistant-ui/tool-fallback.js";
|
|
109
112
|
import "../../components/assistant-ui/tool-group.js";
|
|
110
|
-
function
|
|
113
|
+
function ni({
|
|
111
114
|
block: i,
|
|
112
115
|
trigger: v = "button",
|
|
113
116
|
className: A,
|
|
@@ -359,5 +362,5 @@ function ii({
|
|
|
359
362
|
] });
|
|
360
363
|
}
|
|
361
364
|
export {
|
|
362
|
-
|
|
365
|
+
ni as AddToArtifact
|
|
363
366
|
};
|
package/examples/README.md
CHANGED
|
@@ -13,8 +13,10 @@ root in `MotionConfig`, `ToastProvider` and `TooltipProvider`.
|
|
|
13
13
|
| `agents-screen.tsx` | `AgentsScreen` | A full list page: `PageHeader` with a primary action, a summary strip, `Tabs` with counts leading a `SearchDisclosure`, a filter `Dropdown`, a sortable `Table` with clickable rows and a pinned action column, per-row actions with `Tooltip`s, and filtered `EmptyState`s. |
|
|
14
14
|
| `settings-screen.tsx` | `SettingsScreen` | A settings card: `Card` header with a status `Badge`, an `InputField`, a `SettingList` of `SettingRow`s with `Switch` and `Button` controls, and one primary action. |
|
|
15
15
|
| `workspace-header.tsx` | `WorkspaceHeaderScreen` | A page header with a status `Badge` and trailing actions, then `Tabs` with counts whose panels hold `Card`s. |
|
|
16
|
-
| `campaigns-screen.tsx` | `CampaignsScreen` | The collection-screen recipe: `BodyPageHeader` with one primary action, counted `Tabs` leading `SearchDisclosure` + `Filters`, a multi-select `Table` (hover-revealed checkboxes, cohort child rows, `isActive` open row) whose page size fills the panel with `Pagination` at the bottom, a shell-level `Drawer` with status under the title and Performance / Details sections, and the fixed-height New campaign `Modal
|
|
17
|
-
| `
|
|
16
|
+
| `campaigns-screen.tsx` | `CampaignsScreen` | The collection-screen recipe: `BodyPageHeader` with one primary action, counted `Tabs` leading `SearchDisclosure` + `Filters`, a multi-select `Table` (hover-revealed checkboxes, cohort child rows, `isActive` open row) whose page size fills the panel with `Pagination` at the bottom, a shell-level `Drawer` with status under the title and Performance / Details sections, and the fixed-height New campaign `Modal` (`NewCampaignModal`: `Field info` for optional guidance, `Field actions` for the source switch, inline `FileDropzone`, single-select `Table` of saved audiences). |
|
|
17
|
+
| `call-logs-screen.tsx` | `CallLogsScreen`, `CallPanel` | The record-call-logs recipe: a campaign's Call logs tab titled by `Breadcrumbs` (status in `meta`, Test call + Launch in `actions`), a `Table` of calls (Number · plain-chip Status · Outcome · Duration) that fills the panel, and a footer-less call panel — grounded `DrawerHeader`, scrolling `DrawerSection`s (Summary, Recording, Transcript, Follow-ups, CRM write-back, Captured fields) with `DetailList` attributes and a collapsed Call metadata. |
|
|
18
|
+
| `guardrails-settings-screen.tsx` | `GuardrailsSettingsScreen` | The settings-screen recipe: `BodyPageHeader` with one save action and full-width setting groups (16px title over a `SettingList` of `SettingRow`s with Switch / value Button / Badge controls). |
|
|
19
|
+
| `campaign-analysis-screen.tsx` | `CampaignAnalysisScreen` | The record-analytics recipe: an 18px `Breadcrumbs` title with the primary action on the same row, record `Tabs`, outlined stat cards with `Progress`, and outlined `BarChart` / `LineChart` cards with header legends and printed values. |
|
|
18
20
|
|
|
19
21
|
```tsx
|
|
20
22
|
// app/agents/page.tsx
|