@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.
Files changed (51) hide show
  1. package/DESIGN.md +98 -57
  2. package/README.md +19 -7
  3. package/components/answer.js +1 -1
  4. package/components/assistant-ui/composer-harness.js +13 -10
  5. package/components/body-page-header.d.ts +9 -4
  6. package/components/body-page-header.js +10 -10
  7. package/components/breadcrumbs.js +22 -22
  8. package/components/card.js +18 -18
  9. package/components/chart.d.ts +9 -0
  10. package/components/chart.js +738 -717
  11. package/components/chip.js +12 -12
  12. package/components/collection-header.js +4 -4
  13. package/components/connector-card.js +30 -30
  14. package/components/date-range-picker.js +1 -1
  15. package/components/detail-list.d.ts +28 -0
  16. package/components/detail-list.js +52 -0
  17. package/components/drawer.d.ts +38 -15
  18. package/components/drawer.js +150 -86
  19. package/components/empty-state.d.ts +3 -2
  20. package/components/empty-state.js +22 -22
  21. package/components/field.d.ts +16 -0
  22. package/components/field.js +63 -42
  23. package/components/file-dropzone.d.ts +15 -4
  24. package/components/file-dropzone.js +100 -64
  25. package/components/filter-bar.d.ts +44 -0
  26. package/components/filter-bar.js +89 -0
  27. package/components/index.d.ts +3 -0
  28. package/components/index.js +526 -513
  29. package/components/input-field.d.ts +1 -1
  30. package/components/input-field.js +24 -22
  31. package/components/modal.js +56 -53
  32. package/components/panel.js +26 -27
  33. package/components/sidebar.js +54 -54
  34. package/components/sparkline.d.ts +30 -0
  35. package/components/sparkline.js +69 -0
  36. package/demo/components/add-to-artifact.js +5 -2
  37. package/examples/README.md +4 -2
  38. package/examples/call-logs-screen.tsx +381 -0
  39. package/examples/campaign-analysis-screen.tsx +114 -72
  40. package/examples/campaigns-screen.tsx +218 -160
  41. package/examples/guardrails-settings-screen.tsx +123 -0
  42. package/fonts/geist-variable.woff2 +0 -0
  43. package/fonts.css +12 -17
  44. package/lib/icons.js +3 -3
  45. package/llms.txt +107 -39
  46. package/manifest.json +3100 -892
  47. package/package.json +1 -1
  48. package/styles.css +102 -59
  49. package/theme.css +81 -37
  50. package/fonts/aribau-grotesk-medium.woff2 +0 -0
  51. package/fonts/aribau-grotesk-regular.woff2 +0 -0
@@ -5,7 +5,7 @@ import { cva as w } from "class-variance-authority";
5
5
  import { Close as y } from "../lib/icons.js";
6
6
  import { cn as i } from "../lib/cn.js";
7
7
  const k = w(
8
- "inline-flex h-6 items-center gap-1 whitespace-nowrap rounded-[4px] border px-2 py-0 text-s font-medium leading-[var(--text-s--line-height)]",
8
+ "inline-flex h-6 items-center gap-1 whitespace-nowrap rounded-[4px] border px-2 py-0 text-s font-normal leading-[var(--text-s--line-height)]",
9
9
  {
10
10
  variants: {
11
11
  variant: {
@@ -26,19 +26,19 @@ const k = w(
26
26
  },
27
27
  compoundVariants: [
28
28
  // solid — the default tinted surface
29
- { variant: "solid", color: "default", className: "border-wg4 bg-wg2 text-muted-foreground" },
30
- { variant: "solid", color: "primary", className: "border-t6 bg-action-primary-soft text-brand-text" },
31
- { variant: "solid", color: "success", className: "border-success-300 bg-success-50 text-success-700" },
32
- { variant: "solid", color: "warning", className: "border-warning-300 bg-warning-50 text-warning-700" },
33
- { variant: "solid", color: "danger", className: "border-danger-300 bg-danger-50 text-danger-700" },
34
- { variant: "solid", color: "info", className: "border-info-300 bg-info-50 text-info-700" },
29
+ { variant: "solid", color: "default", className: "border-wg3 bg-wg2 text-muted-foreground" },
30
+ { variant: "solid", color: "primary", className: "border-t4 bg-action-primary-soft text-brand-text" },
31
+ { variant: "solid", color: "success", className: "border-success-100 bg-success-50 text-success-700" },
32
+ { variant: "solid", color: "warning", className: "border-warning-100 bg-warning-50 text-warning-700" },
33
+ { variant: "solid", color: "danger", className: "border-danger-100 bg-danger-50 text-danger-700" },
34
+ { variant: "solid", color: "info", className: "border-info-100 bg-info-50 text-info-700" },
35
35
  // outline
36
36
  { variant: "outline", color: "default", className: "border-border bg-card text-foreground" },
37
- { variant: "outline", color: "primary", className: "border-t7 bg-card text-brand-text" },
38
- { variant: "outline", color: "success", className: "border-success-400 bg-success-50 text-success-700" },
39
- { variant: "outline", color: "warning", className: "border-warning-400 bg-warning-50 text-warning-700" },
40
- { variant: "outline", color: "danger", className: "border-danger-400 bg-danger-50 text-danger-700" },
41
- { variant: "outline", color: "info", className: "border-info-400 bg-info-50 text-info-700" }
37
+ { variant: "outline", color: "primary", className: "border-t5 bg-card text-brand-text" },
38
+ { variant: "outline", color: "success", className: "border-success-300 bg-success-50 text-success-700" },
39
+ { variant: "outline", color: "warning", className: "border-warning-300 bg-warning-50 text-warning-700" },
40
+ { variant: "outline", color: "danger", className: "border-danger-300 bg-danger-50 text-danger-700" },
41
+ { variant: "outline", color: "info", className: "border-info-300 bg-info-50 text-info-700" }
42
42
  ],
43
43
  defaultVariants: { variant: "solid", color: "default" }
44
44
  }
@@ -2,7 +2,7 @@
2
2
  import { jsxs as a, jsx as e } from "react/jsx-runtime";
3
3
  import * as c from "react";
4
4
  import { cn as d } from "../lib/cn.js";
5
- const f = c.forwardRef(
5
+ const m = c.forwardRef(
6
6
  ({ className: n, icon: s, title: i, meta: r, actions: t, ...l }, o) => /* @__PURE__ */ a(
7
7
  "header",
8
8
  {
@@ -17,7 +17,7 @@ const f = c.forwardRef(
17
17
  children: [
18
18
  /* @__PURE__ */ a("div", { className: "flex min-w-0 items-center gap-2.5", children: [
19
19
  /* @__PURE__ */ e("span", { className: "shrink-0 text-foreground [&_svg]:size-4", "aria-hidden": "true", children: s }),
20
- /* @__PURE__ */ e("h1", { className: "truncate text-base font-semibold text-foreground", children: i }),
20
+ /* @__PURE__ */ e("h1", { className: "truncate text-base font-medium text-foreground", children: i }),
21
21
  r ? /* @__PURE__ */ e("span", { className: "shrink-0 text-xs tabular-nums text-secondary", children: r }) : null
22
22
  ] }),
23
23
  t ? /* @__PURE__ */ e("div", { className: "flex shrink-0 items-center gap-2", children: t }) : null
@@ -25,7 +25,7 @@ const f = c.forwardRef(
25
25
  }
26
26
  )
27
27
  );
28
- f.displayName = "CollectionHeader";
28
+ m.displayName = "CollectionHeader";
29
29
  export {
30
- f as CollectionHeader
30
+ m as CollectionHeader
31
31
  };
@@ -8,32 +8,32 @@ const u = {
8
8
  issue: { band: "bg-linear-to-r from-danger-50 to-danger-50/0" },
9
9
  healthy: { band: "bg-linear-to-r from-success-50 to-success-50/0" }
10
10
  };
11
- function y(s) {
11
+ function y(r) {
12
12
  const e = /* @__PURE__ */ new Date();
13
- if (s.toDateString() === e.toDateString())
14
- return `Last sync at ${s.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" })}`;
15
- const n = Math.max(1, Math.floor((e.getTime() - s.getTime()) / 864e5));
13
+ if (r.toDateString() === e.toDateString())
14
+ return `Last sync at ${r.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" })}`;
15
+ const n = Math.max(1, Math.floor((e.getTime() - r.getTime()) / 864e5));
16
16
  if (n === 1) return "Last sync yesterday";
17
- let a;
18
- if (n < 7) a = `${n} days ago`;
17
+ let s;
18
+ if (n < 7) s = `${n} days ago`;
19
19
  else if (n < 30) {
20
- const r = Math.round(n / 7);
21
- a = `${r} week${r > 1 ? "s" : ""} ago`;
20
+ const a = Math.round(n / 7);
21
+ s = `${a} week${a > 1 ? "s" : ""} ago`;
22
22
  } else {
23
- const r = Math.round(n / 30);
24
- a = `${r} month${r > 1 ? "s" : ""} ago`;
23
+ const a = Math.round(n / 30);
24
+ s = `${a} month${a > 1 ? "s" : ""} ago`;
25
25
  }
26
- return `Last sync from ${a}`;
26
+ return `Last sync from ${s}`;
27
27
  }
28
28
  function N({
29
- connected: s,
29
+ connected: r,
30
30
  lastSync: e,
31
31
  label: n
32
32
  }) {
33
- const a = n ?? (s ? e ? y(e) : "Connected" : "Disconnected");
34
- return s ? /* @__PURE__ */ i("span", { className: "inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-xs text-tertiary", children: [
33
+ const s = n ?? (r ? e ? y(e) : "Connected" : "Disconnected");
34
+ return r ? /* @__PURE__ */ i("span", { className: "inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap text-xs text-tertiary", children: [
35
35
  /* @__PURE__ */ t("span", { "aria-hidden": !0, className: "size-2 rounded-dot bg-success" }),
36
- a
36
+ s
37
37
  ] }) : /* @__PURE__ */ t(
38
38
  x,
39
39
  {
@@ -41,12 +41,12 @@ function N({
41
41
  color: "danger",
42
42
  showDot: !0,
43
43
  className: "shrink-0",
44
- children: a
44
+ children: s
45
45
  }
46
46
  );
47
47
  }
48
- function v({ strip: s }) {
49
- const e = u[s.tint] ?? u.issue;
48
+ function v({ strip: r }) {
49
+ const e = u[r.tint] ?? u.issue;
50
50
  return /* @__PURE__ */ t(
51
51
  "div",
52
52
  {
@@ -60,17 +60,17 @@ function v({ strip: s }) {
60
60
  className: o(
61
61
  "min-w-0 flex-1 truncate text-xs text-foreground"
62
62
  ),
63
- children: s.message
63
+ children: r.message
64
64
  }
65
65
  )
66
66
  }
67
67
  );
68
68
  }
69
69
  const w = g.forwardRef(
70
- ({ className: s, card: e, onOpen: n, ...a }, r) => {
70
+ ({ className: r, card: e, onOpen: n, ...s }, a) => {
71
71
  var m;
72
72
  const c = !!n, h = ((m = e.action) == null ? void 0 : m.tone) === "reconnect", l = /* @__PURE__ */ i(f, { children: [
73
- /* @__PURE__ */ i("div", { className: "rounded-t-xl p-[var(--card-padding)]", children: [
73
+ /* @__PURE__ */ i("div", { className: "rounded-t-card p-[var(--card-padding)]", children: [
74
74
  /* @__PURE__ */ i("div", { className: "mb-5 flex items-center gap-3.5", children: [
75
75
  e.logo ? /* @__PURE__ */ t(
76
76
  "img",
@@ -79,7 +79,7 @@ const w = g.forwardRef(
79
79
  alt: "",
80
80
  className: "size-10 shrink-0 rounded-md object-contain"
81
81
  }
82
- ) : /* @__PURE__ */ t("span", { className: "grid size-10 shrink-0 place-items-center rounded-md bg-muted text-secondary", children: /* @__PURE__ */ t(b, { className: "size-5", "aria-hidden": !0 }) }),
82
+ ) : /* @__PURE__ */ t("span", { className: "grid size-10 shrink-0 place-items-center text-secondary", children: /* @__PURE__ */ t(b, { className: "size-5", "aria-hidden": !0 }) }),
83
83
  /* @__PURE__ */ i("div", { className: "min-w-0 flex-1", children: [
84
84
  /* @__PURE__ */ i("div", { className: "flex items-baseline justify-between gap-3", children: [
85
85
  /* @__PURE__ */ t("div", { className: "min-w-0 truncate text-base font-medium leading-tight text-foreground", children: e.name }),
@@ -96,7 +96,7 @@ const w = g.forwardRef(
96
96
  ] }),
97
97
  /* @__PURE__ */ t(v, { strip: e.strip })
98
98
  ] }),
99
- /* @__PURE__ */ i("div", { className: "flex items-center justify-between gap-3 rounded-b-xl bg-ink-100 px-[var(--card-padding)] py-3", children: [
99
+ /* @__PURE__ */ i("div", { className: "flex items-center justify-between gap-3 rounded-b-card bg-ink-100 px-[var(--card-padding)] py-3", children: [
100
100
  /* @__PURE__ */ t(
101
101
  "span",
102
102
  {
@@ -120,19 +120,19 @@ const w = g.forwardRef(
120
120
  )
121
121
  ] })
122
122
  ] }), d = o(
123
- // Each region shapes its own corners: top body carries rounded-t-xl,
124
- // footer carries rounded-b-xl. Layer promoted with translateZ(0) so
123
+ // Each region shapes its own corners: top body carries rounded-t-card,
124
+ // footer carries rounded-b-card. Layer promoted with translateZ(0) so
125
125
  // the rounded edges rasterize on their own GPU layer (subpixel corner
126
126
  // aliasing under transform is a real browser gotcha; forcing a
127
127
  // compositor layer fixes it deterministically).
128
- "rounded-xl bg-card text-card-foreground transform-gpu [will-change:transform] [backface-visibility:hidden]",
128
+ "rounded-card border border-border bg-card text-card-foreground shadow-card transform-gpu [will-change:transform] [backface-visibility:hidden]",
129
129
  c && "transition-[transform,box-shadow] duration-150 ease-out motion-reduce:transition-none",
130
- s
130
+ r
131
131
  );
132
132
  return c ? /* @__PURE__ */ t(
133
133
  "button",
134
134
  {
135
- ref: r,
135
+ ref: a,
136
136
  type: "button",
137
137
  onClick: () => n == null ? void 0 : n(e),
138
138
  className: o(
@@ -140,10 +140,10 @@ const w = g.forwardRef(
140
140
  "w-full cursor-pointer text-left hover:-translate-y-0.5",
141
141
  "outline-none focus-visible:ring-3 focus-visible:ring-ring active:translate-y-0"
142
142
  ),
143
- ...a,
143
+ ...s,
144
144
  children: l
145
145
  }
146
- ) : /* @__PURE__ */ t("div", { ref: r, className: d, ...a, children: l });
146
+ ) : /* @__PURE__ */ t("div", { ref: a, className: d, ...s, children: l });
147
147
  }
148
148
  );
149
149
  w.displayName = "ConnectorCard";
@@ -173,7 +173,7 @@ function se({
173
173
  children: /* @__PURE__ */ t(U, { className: "size-4" })
174
174
  }
175
175
  ),
176
- /* @__PURE__ */ t(Y, { className: "text-sm font-semibold" }),
176
+ /* @__PURE__ */ t(Y, { className: "text-sm font-medium" }),
177
177
  /* @__PURE__ */ t(
178
178
  m,
179
179
  {
@@ -0,0 +1,28 @@
1
+ import * as React from "react";
2
+ /**
3
+ * DetailList / DetailItem — label–value rows for a record's attributes
4
+ * (principle `record-detail-panels`).
5
+ *
6
+ * Each row reads label (14px, secondary) on the left and value (14px,
7
+ * primary) on the right. Long values wrap and stay right-aligned; rows
8
+ * separate with inset WG3 hairlines that stop at the content edge, never at
9
+ * the container edge. Labels are sentence case ("Type of loan"), never the
10
+ * raw field key. A value that was never captured renders `emptyLabel`
11
+ * ("Not stated" by default) in secondary grey (it must still clear AA) instead of an em dash or blank.
12
+ *
13
+ * Use it for Details / CRM write-back / Captured fields sections in a detail
14
+ * panel. It is not a table: when several records share the same fields, use
15
+ * `Table`.
16
+ */
17
+ export interface DetailListProps extends React.HTMLAttributes<HTMLDListElement> {
18
+ }
19
+ export declare const DetailList: React.ForwardRefExoticComponent<DetailListProps & React.RefAttributes<HTMLDListElement>>;
20
+ export interface DetailItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
21
+ /** What the value is, in sentence case. */
22
+ label: React.ReactNode;
23
+ /** The value. `null`, `undefined` or `""` renders `emptyLabel`. */
24
+ children?: React.ReactNode;
25
+ /** Shown in secondary grey when there is no value. */
26
+ emptyLabel?: React.ReactNode;
27
+ }
28
+ export declare const DetailItem: React.ForwardRefExoticComponent<DetailItemProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,52 @@
1
+ "use client";
2
+ import { jsx as r, jsxs as n } from "react/jsx-runtime";
3
+ import * as l from "react";
4
+ import { cn as i } from "../lib/cn.js";
5
+ const f = l.forwardRef(
6
+ ({ className: e, ...a }, t) => /* @__PURE__ */ r(
7
+ "dl",
8
+ {
9
+ ref: t,
10
+ "data-slot": "detail-list",
11
+ className: i("m-0 flex w-full flex-col", e),
12
+ ...a
13
+ }
14
+ )
15
+ );
16
+ f.displayName = "DetailList";
17
+ const c = l.forwardRef(
18
+ ({ className: e, label: a, children: t, emptyLabel: m = "Not stated", ...o }, d) => {
19
+ const s = t == null || t === "" || t === !1;
20
+ return /* @__PURE__ */ n(
21
+ "div",
22
+ {
23
+ ref: d,
24
+ "data-slot": "detail-item",
25
+ "data-empty": s || void 0,
26
+ className: i(
27
+ "flex items-start justify-between gap-4 border-b border-tertiary py-2.5 last:border-0",
28
+ e
29
+ ),
30
+ ...o,
31
+ children: [
32
+ /* @__PURE__ */ r("dt", { className: "shrink-0 text-m text-on-white-secondary", children: a }),
33
+ /* @__PURE__ */ r(
34
+ "dd",
35
+ {
36
+ className: i(
37
+ "m-0 flex min-w-0 max-w-[65%] items-center justify-end gap-2 text-right text-m wrap-break-word",
38
+ s ? "text-on-white-secondary" : "text-on-white-primary"
39
+ ),
40
+ children: s ? m : t
41
+ }
42
+ )
43
+ ]
44
+ }
45
+ );
46
+ }
47
+ );
48
+ c.displayName = "DetailItem";
49
+ export {
50
+ c as DetailItem,
51
+ f as DetailList
52
+ };
@@ -39,33 +39,56 @@ export declare function ModalDrawer({ open, onOpenChange, side: sideProp, size,
39
39
  * Drawer in ADS. Use `ModalDrawer` when a page-blocking overlay is genuinely
40
40
  * required.
41
41
  *
42
- * REQUIRES THE CANVAS GROUND. The panel is flat white (`bg-card`) with no
43
- * shadow and no border — it separates from its neighbour purely by fill
44
- * contrast, so it is INVISIBLE on a pure-white (`bg-card`) parent. Place it
45
- * and its sibling content inside a `bg-background` flex row — the SHELL
46
- * CANVAS tint (ink-100), the same color as the frame around the screen. Do
47
- * NOT use `bg-surface` (ink-200) for this row: it is one Radix step darker
48
- * than the shell frame, so the gutter between the panels renders as a dark
49
- * seam stripe instead of reading as canvas (field report 2026-08-06,
50
- * Artifacts v2). The ground is the parent's job, not the panel's (the inline
51
- * Drawer renders no ground of its own):
42
+ * ATTACHED TO THE PAGE (the window panel style, user-mandated 2026-11-12).
43
+ * The panel is part of the same white page as the content it details: it
44
+ * sits flush beside it, with no gap, no radius of its own and no shadow,
45
+ * split off by one full-height WG4 hairline on its leading edge. Its header
46
+ * and footer close with full-width hairlines too. Mount it as a flex sibling
47
+ * of the content inside the white page:
52
48
  *
53
- * <div className="flex gap-3 bg-background p-3">
54
- * <main className="flex-1 rounded-xl bg-card">…content…</main>
49
+ * <div className="flex min-h-0 flex-1">
50
+ * <main className="min-w-0 flex-1">…content…</main>
55
51
  * <Drawer open={open} onOpenChange={setOpen} aria-label="…">…</Drawer>
56
52
  * </div>
57
53
  *
58
- * This mirrors the shell's main + chat layout — white panels on the canvas.
59
- * If the panel doesn't read, fix the ground; never add a border or shadow to
60
- * force it (that fights principle 1).
54
+ * Never float it as a separate card with a strip of canvas between, and
55
+ * never nest it inside the content it details.
61
56
  */
62
57
  export declare function Drawer({ open, onOpenChange, dismissible, side: sideProp, size, containerClassName, className, children, "aria-label": ariaLabel, }: DrawerProps): React.JSX.Element;
63
58
  /** @deprecated Alias for `Drawer` — the canonical drawer is now the inline
64
59
  * variant. Kept for any code still importing `InlineDrawer`. */
65
60
  export declare const InlineDrawer: typeof Drawer;
66
61
  export type InlineDrawerProps = DrawerProps;
62
+ /**
63
+ * Record-panel anatomy (principle `record-detail-panels`):
64
+ *
65
+ * DrawerHeader kicker → title → DrawerMeta (status Chip + context),
66
+ * closed by a full-width WG4 hairline; it never scrolls.
67
+ * DrawerBody the only scrolling region; DrawerSections 32px apart.
68
+ * DrawerFooter OPTIONAL — only when an action leads somewhere real
69
+ * (a dedicated page that exists, a state change). No
70
+ * placeholder "Open full view" when there is no full view.
71
+ *
72
+ * A fact lives in one place: what the header says (status, time, length)
73
+ * is never repeated in the body.
74
+ */
67
75
  export declare const DrawerHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
76
+ /** Uppercase kind of the selected thing ("CALL", "CAMPAIGN") above the title. */
77
+ export declare const DrawerKicker: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
68
78
  export declare const DrawerTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLHeadingElement>>;
79
+ /**
80
+ * The status line under the title: a status Chip followed by 14px context
81
+ * ("12 Sep, 3:41 PM · 4s"), 8px below the title. Status never floats alone.
82
+ */
83
+ export declare const DrawerMeta: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
69
84
  export declare const DrawerBody: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
85
+ export interface DrawerSectionProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
86
+ /** 14px Medium section title ("Transcript"). */
87
+ title: React.ReactNode;
88
+ /** Optional scope after the title in Regular secondary ("1 turn", "0 of 10"). */
89
+ count?: React.ReactNode;
90
+ }
91
+ /** A titled group inside DrawerBody; stack sections with `gap-8` (32px). */
92
+ export declare const DrawerSection: React.ForwardRefExoticComponent<DrawerSectionProps & React.RefAttributes<HTMLElement>>;
70
93
  export declare const DrawerFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
71
94
  export {};