@actioneer/ads 1.0.6 → 1.0.7

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 CHANGED
@@ -179,7 +179,7 @@ components:
179
179
 
180
180
  TASTE.md puts it in one line: On a quiet, neutral ground, colour and motion are spent like money — rarely, deliberately, and only where the eye should go.
181
181
 
182
- ADS 1.0.6 is a library first and a look second. 323 components across 10 families (Primitives / utilities, Foundations, Form controls, Overlays, Data display, Feedback, Navigation, Layout, AI Elements, Chat) ship from one barrel, and every product that consumes them inherits the judgment encoded in 56 semantic tokens and 11 principles rather than re-deciding it per screen.
182
+ ADS 1.0.7 is a library first and a look second. 323 components across 10 families (Primitives / utilities, Foundations, Form controls, Overlays, Data display, Feedback, Navigation, Layout, AI Elements, Chat) ship from one barrel, and every product that consumes them inherits the judgment encoded in 56 semantic tokens and 11 principles rather than re-deciding it per screen.
183
183
 
184
184
  The ground is warm grey and the ink is warm near-black. One hue is spent by default, the Studio teal CTA family, and four more carry semantic status. Everything else stays neutral. A consumer product may narrow that further, and one already does: Baby Sentinel drops the teal and runs every action on ink.
185
185
 
@@ -1,10 +1,10 @@
1
1
  import { VariantProps } from 'class-variance-authority';
2
2
  import * as React from "react";
3
3
  /**
4
- * Alert — inline status messaging on a raised white surface. Status color is
5
- * confined to the indicator, title, and optional timeout progress bar; the
6
- * description stays muted. Timed alerts enter from the right and leave to the
7
- * left once their progress completes.
4
+ * Alert — inline status messaging in an outlined white container. A softly tinted
5
+ * indicator carries status while the title and description stay neutral.
6
+ * Buttons are 24px tall and actions sit 16px below the message. Timed alerts
7
+ * retain their countdown and dismiss after it completes.
8
8
  */
9
9
  declare const alertVariants: (props?: ({
10
10
  variant?: "success" | "warning" | "danger" | "info" | "default" | null | undefined;
@@ -1,90 +1,105 @@
1
1
  "use client";
2
- import { jsx as e, jsxs as k } from "react/jsx-runtime";
3
- import * as t from "react";
4
- import { cva as A } from "class-variance-authority";
5
- import { MotionConfig as E, motion as g } from "motion/react";
6
- import { Info as p, WarningCircle as C, Warning as I, CheckCircle as R, Close as j } from "../lib/icons.js";
7
- import { cn as d } from "../lib/cn.js";
8
- import { springOverlay as z } from "../lib/motion.js";
9
- const D = A(
10
- "relative flex w-full items-start gap-4 overflow-hidden rounded-2xl border border-border bg-card p-4 shadow-[var(--shadow-200)]",
2
+ import { jsx as t, jsxs as I } from "react/jsx-runtime";
3
+ import * as e from "react";
4
+ import { cva as R } from "class-variance-authority";
5
+ import { MotionConfig as j, motion as y } from "motion/react";
6
+ import { Info as h, WarningCircle as V, Warning as M, CheckCircle as S, Close as W } from "../lib/icons.js";
7
+ import { cn as m } from "../lib/cn.js";
8
+ import { fadeTransition as X, springOverlay as H } from "../lib/motion.js";
9
+ const O = R(
10
+ "relative grid w-full min-w-0 grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-4 overflow-hidden rounded-lg border border-border bg-card p-4 text-on-white-primary [&_button]:h-6",
11
11
  {
12
12
  variants: {
13
13
  variant: {
14
- default: "[--alert-accent:var(--foreground)]",
15
- success: "[--alert-accent:var(--color-success-700)]",
16
- warning: "[--alert-accent:var(--color-warning-700)]",
17
- danger: "[--alert-accent:var(--color-danger-700)]",
18
- info: "[--alert-accent:var(--color-info-700)]"
14
+ default: "[--alert-accent:var(--foreground)] [--alert-soft:var(--fill)]",
15
+ success: "[--alert-accent:var(--color-success-700)] [--alert-soft:var(--color-success-50)]",
16
+ warning: "[--alert-accent:var(--color-warning-700)] [--alert-soft:var(--color-warning-50)]",
17
+ danger: "[--alert-accent:var(--color-danger-700)] [--alert-soft:var(--color-danger-50)]",
18
+ info: "[--alert-accent:var(--color-info-700)] [--alert-soft:var(--color-info-50)]"
19
19
  }
20
20
  },
21
21
  defaultVariants: { variant: "default" }
22
22
  }
23
- ), T = {
24
- default: p,
25
- success: R,
26
- warning: I,
27
- danger: C,
28
- info: p
29
- }, M = t.forwardRef(
30
- ({ className: n, variant: r = "default", icon: s, duration: a = 0, onClose: l, children: x, ...v }, h) => {
31
- const b = T[r ?? "default"], [i, w] = t.useState(!1), [o, N] = t.useState(!1), c = t.useRef(l), m = t.useRef(!1);
32
- t.useEffect(() => {
33
- c.current = l;
23
+ ), q = {
24
+ default: h,
25
+ success: S,
26
+ warning: M,
27
+ danger: V,
28
+ info: h
29
+ }, B = e.forwardRef(
30
+ ({ className: o, variant: a = "default", icon: s, duration: i = 0, onClose: l, children: g, ...A }, E) => {
31
+ const T = q[a ?? "default"], [n, k] = e.useState(!1), [c, C] = e.useState(!1), d = e.useRef(l), w = e.useRef(!1), u = e.Children.toArray(g);
32
+ let f = -1;
33
+ u.forEach((r, D) => {
34
+ if (!e.isValidElement(r)) return;
35
+ const v = typeof r.type == "string" ? void 0 : r.type.displayName;
36
+ (r.type === b || r.type === N || v === "AlertTitle" || v === "AlertDescription") && (f = D);
37
+ });
38
+ const _ = f < 0 ? g : u.slice(0, f + 1), x = f < 0 ? [] : u.slice(f + 1);
39
+ e.useEffect(() => {
40
+ d.current = l;
34
41
  }, [l]);
35
- const u = t.useCallback(() => {
36
- o || w(!0);
37
- }, [o]);
38
- t.useEffect(() => {
39
- if (a <= 0 || i || o) return;
40
- const f = window.setTimeout(u, a);
41
- return () => window.clearTimeout(f);
42
- }, [u, a, o, i]);
43
- const y = t.useCallback(() => {
44
- var f;
45
- !i || m.current || (m.current = !0, N(!0), (f = c.current) == null || f.call(c));
46
- }, [i]);
47
- return o ? null : /* @__PURE__ */ e(E, { reducedMotion: "user", children: /* @__PURE__ */ e(
48
- g.div,
42
+ const p = e.useCallback(() => {
43
+ c || k(!0);
44
+ }, [c]);
45
+ e.useEffect(() => {
46
+ if (i <= 0 || n || c) return;
47
+ const r = window.setTimeout(p, i);
48
+ return () => window.clearTimeout(r);
49
+ }, [p, i, c, n]);
50
+ const z = e.useCallback(() => {
51
+ var r;
52
+ !n || w.current || (w.current = !0, C(!0), (r = d.current) == null || r.call(d));
53
+ }, [n]);
54
+ return c ? null : /* @__PURE__ */ t(j, { reducedMotion: "user", children: /* @__PURE__ */ t(
55
+ y.div,
49
56
  {
57
+ className: "w-full min-w-0",
50
58
  initial: { opacity: 1, x: 32 },
51
- animate: i ? { opacity: 0, x: -32 } : { opacity: 1, x: 0 },
52
- transition: i ? { duration: 0.18, ease: "easeIn" } : z,
53
- onAnimationComplete: y,
54
- children: /* @__PURE__ */ k(
59
+ animate: n ? { opacity: 0, x: -32 } : { opacity: 1, x: 0 },
60
+ transition: n ? X : H,
61
+ onAnimationComplete: z,
62
+ children: /* @__PURE__ */ I(
55
63
  "div",
56
64
  {
57
- ref: h,
65
+ ref: E,
66
+ "data-slot": "alert",
58
67
  role: "alert",
59
- className: d(D({ variant: r }), n),
60
- ...v,
68
+ className: m(
69
+ O({ variant: a }),
70
+ l && "grid-cols-[auto_minmax(0,1fr)_auto]",
71
+ o
72
+ ),
73
+ ...A,
61
74
  children: [
62
- /* @__PURE__ */ e("span", { className: "flex shrink-0 select-none items-center justify-center py-1 text-(--alert-accent) [&_svg]:size-4", children: s ?? /* @__PURE__ */ e(b, { "aria-hidden": !0 }) }),
63
- /* @__PURE__ */ e("div", { className: "flex min-w-0 grow flex-col items-start", children: x }),
64
- l && /* @__PURE__ */ e(
75
+ /* @__PURE__ */ t("span", { "data-slot": "alert-icon", className: "col-start-1 row-start-1 flex size-8 self-center select-none items-center justify-center rounded-md bg-(--alert-soft) text-(--alert-accent) [&_svg]:size-4", children: s ?? /* @__PURE__ */ t(T, { "aria-hidden": !0 }) }),
76
+ /* @__PURE__ */ t("div", { "data-slot": "alert-content", className: "col-start-2 row-start-1 flex min-w-0 flex-col items-start gap-0.5 self-center [overflow-wrap:anywhere]", children: _ }),
77
+ l && /* @__PURE__ */ t(
65
78
  "button",
66
79
  {
67
80
  type: "button",
68
81
  "aria-label": "Dismiss",
69
- onClick: u,
70
- className: d(
71
- "inline-flex size-6 shrink-0 items-center justify-center rounded-sm text-muted-foreground",
72
- "transition-colors hover:bg-fill hover:text-foreground",
82
+ onClick: p,
83
+ className: m(
84
+ "col-start-3 row-start-1 inline-flex size-6 cursor-pointer items-center justify-center self-start rounded-sm text-on-white-tertiary",
85
+ "transition-[background-color,color,transform] duration-150 ease-out hover:bg-fill hover:text-on-white-primary",
86
+ "active:scale-[0.97] motion-reduce:active:scale-100 motion-reduce:transition-none",
73
87
  "outline-none focus-visible:ring-3 focus-visible:ring-ring",
74
88
  "[&_svg]:size-4"
75
89
  ),
76
- children: /* @__PURE__ */ e(j, { "aria-hidden": !0 })
90
+ children: /* @__PURE__ */ t(W, { "aria-hidden": !0 })
77
91
  }
78
92
  ),
79
- a > 0 && /* @__PURE__ */ e("span", { "aria-hidden": !0, className: "absolute inset-x-0 bottom-0 h-0.5 bg-wg3", children: /* @__PURE__ */ e(
80
- g.span,
93
+ x.length > 0 && /* @__PURE__ */ t("div", { "data-slot": "alert-actions", className: "col-start-2 row-start-2 flex min-w-0 flex-wrap items-center gap-2 [&>*]:max-w-full", children: x }),
94
+ i > 0 && /* @__PURE__ */ t("span", { "aria-hidden": !0, className: "absolute inset-x-0 bottom-0 h-0.5 bg-wg3", children: /* @__PURE__ */ t(
95
+ y.span,
81
96
  {
82
97
  className: "block size-full origin-left bg-(--alert-accent)",
83
98
  initial: { scaleX: 1 },
84
99
  animate: { scaleX: 0 },
85
- transition: { duration: a / 1e3, ease: "linear" }
100
+ transition: { duration: i / 1e3, ease: "linear" }
86
101
  },
87
- a
102
+ i
88
103
  ) })
89
104
  ]
90
105
  }
@@ -93,32 +108,29 @@ const D = A(
93
108
  ) });
94
109
  }
95
110
  );
96
- M.displayName = "Alert";
97
- const S = t.forwardRef(({ className: n, ...r }, s) => /* @__PURE__ */ e(
111
+ B.displayName = "Alert";
112
+ const b = e.forwardRef(({ className: o, ...a }, s) => /* @__PURE__ */ t(
98
113
  "p",
99
114
  {
100
115
  ref: s,
101
- className: d("text-s font-normal leading-6 text-(--alert-accent)", n),
102
- ...r
116
+ "data-slot": "alert-title",
117
+ className: m("text-m font-medium leading-6 text-on-white-primary", o),
118
+ ...a
103
119
  }
104
120
  ));
105
- S.displayName = "AlertTitle";
106
- const V = t.forwardRef(({ className: n, ...r }, s) => (
107
- // leading-normal (150%) — the description is the only part of an alert that
108
- // regularly wraps, and the text-xs default (138%) sets multi-line copy too
109
- // tight to scan.
110
- /* @__PURE__ */ e(
111
- "p",
112
- {
113
- ref: s,
114
- className: d("text-xs leading-normal text-muted-foreground", n),
115
- ...r
116
- }
117
- )
121
+ b.displayName = "AlertTitle";
122
+ const N = e.forwardRef(({ className: o, ...a }, s) => /* @__PURE__ */ t(
123
+ "p",
124
+ {
125
+ ref: s,
126
+ "data-slot": "alert-description",
127
+ className: m("text-m leading-relaxed text-on-white-secondary [overflow-wrap:anywhere]", o),
128
+ ...a
129
+ }
118
130
  ));
119
- V.displayName = "AlertDescription";
131
+ N.displayName = "AlertDescription";
120
132
  export {
121
- M as Alert,
122
- V as AlertDescription,
123
- S as AlertTitle
133
+ B as Alert,
134
+ N as AlertDescription,
135
+ b as AlertTitle
124
136
  };
@@ -10,7 +10,7 @@ export interface RadioGroupProps extends Omit<React.HTMLAttributes<HTMLDivElemen
10
10
  disabled?: boolean;
11
11
  }
12
12
  export declare const RadioGroup: React.ForwardRefExoticComponent<RadioGroupProps & React.RefAttributes<HTMLDivElement>>;
13
- export interface RadioProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "value" | "onChange"> {
13
+ export interface RadioProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "value"> {
14
14
  value: string;
15
15
  }
16
16
  export declare const Radio: React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLInputElement>>;
@@ -1,111 +1,111 @@
1
1
  "use client";
2
- import { jsx as r, jsxs as R } from "react/jsx-runtime";
2
+ import { jsx as r, jsxs as y } from "react/jsx-runtime";
3
3
  import * as i from "react";
4
- import { MotionConfig as v, motion as y } from "motion/react";
5
- import { cn as b } from "../lib/cn.js";
6
- import { Field as N } from "./field.js";
7
- import { springRadio as w } from "../lib/motion.js";
8
- const x = i.createContext(null), k = i.forwardRef(
4
+ import { MotionConfig as N, motion as w } from "motion/react";
5
+ import { cn as g } from "../lib/cn.js";
6
+ import { Field as k } from "./field.js";
7
+ import { springRadio as C } from "../lib/motion.js";
8
+ const R = i.createContext(null), j = i.forwardRef(
9
9
  ({
10
- className: d,
11
- name: n,
10
+ className: u,
11
+ name: t,
12
12
  value: o,
13
- onChange: t,
14
- label: a,
15
- description: c,
16
- error: u,
17
- orientation: p = "vertical",
18
- disabled: e,
19
- children: s,
20
- ...l
21
- }, f) => {
13
+ onChange: a,
14
+ label: s,
15
+ description: p,
16
+ error: n,
17
+ orientation: f = "vertical",
18
+ disabled: l,
19
+ children: e,
20
+ ...d
21
+ }, c) => {
22
22
  const m = i.useMemo(
23
- () => ({ name: n, value: o, onValueChange: t, disabled: e }),
24
- [n, o, t, e]
23
+ () => ({ name: t, value: o, onValueChange: a, disabled: l }),
24
+ [t, o, a, l]
25
25
  );
26
26
  return /* @__PURE__ */ r(
27
- N,
27
+ k,
28
28
  {
29
- ref: f,
30
- label: a,
31
- description: c,
32
- error: u,
29
+ ref: c,
30
+ label: s,
31
+ description: p,
32
+ error: n,
33
33
  role: "radiogroup",
34
- className: d,
35
- ...l,
36
- children: /* @__PURE__ */ r(x.Provider, { value: m, children: /* @__PURE__ */ r(
34
+ className: u,
35
+ ...d,
36
+ children: /* @__PURE__ */ r(R.Provider, { value: m, children: /* @__PURE__ */ r(
37
37
  "div",
38
38
  {
39
- className: b(
39
+ className: g(
40
40
  "flex gap-3",
41
- p === "vertical" ? "flex-col" : "flex-row flex-wrap"
41
+ f === "vertical" ? "flex-col" : "flex-row flex-wrap"
42
42
  ),
43
- children: s
43
+ children: e
44
44
  }
45
45
  ) })
46
46
  }
47
47
  );
48
48
  }
49
49
  );
50
- k.displayName = "RadioGroup";
51
- const j = i.forwardRef(
52
- ({ className: d, children: n, value: o, disabled: t, checked: a, defaultChecked: c, ...u }, p) => {
53
- const e = i.useContext(x), s = t || (e == null ? void 0 : e.disabled), l = a !== void 0, [f, m] = i.useState(!!c), g = e ? e.value === o : l ? a : f;
54
- return /* @__PURE__ */ R(
50
+ j.displayName = "RadioGroup";
51
+ const G = i.forwardRef(
52
+ ({ className: u, children: t, value: o, disabled: a, checked: s, defaultChecked: p, onChange: n, ...f }, l) => {
53
+ const e = i.useContext(R), d = a || (e == null ? void 0 : e.disabled), c = s !== void 0, [m, v] = i.useState(!!p), b = e ? e.value === o : c ? s : m;
54
+ return /* @__PURE__ */ y(
55
55
  "label",
56
56
  {
57
- className: b(
57
+ className: g(
58
58
  "group inline-flex items-center gap-2 text-m text-foreground select-none",
59
- s ? "cursor-not-allowed opacity-50" : "cursor-pointer",
60
- d
59
+ d ? "cursor-not-allowed opacity-50" : "cursor-pointer",
60
+ u
61
61
  ),
62
62
  children: [
63
63
  /* @__PURE__ */ r(
64
64
  "input",
65
65
  {
66
- ref: p,
66
+ ref: l,
67
67
  type: "radio",
68
68
  name: e == null ? void 0 : e.name,
69
69
  value: o,
70
- checked: g,
71
- disabled: s,
72
- onChange: (C) => {
70
+ checked: b,
71
+ disabled: d,
72
+ onChange: (x) => {
73
73
  var h;
74
- C.target.checked && (e ? (h = e.onValueChange) == null || h.call(e, o) : l || m(!0));
74
+ x.target.checked && (e ? (h = e.onValueChange) == null || h.call(e, o) : c || v(!0), n == null || n(x));
75
75
  },
76
76
  className: "peer sr-only",
77
- ...u
77
+ ...f
78
78
  }
79
79
  ),
80
80
  /* @__PURE__ */ r(
81
81
  "span",
82
82
  {
83
83
  "aria-hidden": !0,
84
- className: b(
84
+ className: g(
85
85
  "flex size-4.5 shrink-0 items-center justify-center rounded-full border border-input bg-elevated",
86
86
  "transition-[border-color,box-shadow] duration-150 ease-out",
87
87
  "peer-checked:border-brand",
88
88
  "peer-focus-visible:ring-3 peer-focus-visible:ring-ring"
89
89
  ),
90
- children: /* @__PURE__ */ r(v, { reducedMotion: "user", children: /* @__PURE__ */ r(
91
- y.span,
90
+ children: /* @__PURE__ */ r(N, { reducedMotion: "user", children: /* @__PURE__ */ r(
91
+ w.span,
92
92
  {
93
93
  className: "size-2 rounded-full bg-brand",
94
94
  initial: !1,
95
- animate: { opacity: g ? 1 : 0, scale: g ? 1 : 0.9 },
96
- transition: w
95
+ animate: { opacity: b ? 1 : 0, scale: b ? 1 : 0.9 },
96
+ transition: C
97
97
  }
98
98
  ) })
99
99
  }
100
100
  ),
101
- n && /* @__PURE__ */ r("span", { children: n })
101
+ t && /* @__PURE__ */ r("span", { children: t })
102
102
  ]
103
103
  }
104
104
  );
105
105
  }
106
106
  );
107
- j.displayName = "Radio";
107
+ G.displayName = "Radio";
108
108
  export {
109
- j as Radio,
110
- k as RadioGroup
109
+ G as Radio,
110
+ j as RadioGroup
111
111
  };