@actioneer/ads 1.0.7 → 1.0.9

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 (87) hide show
  1. package/DESIGN.md +119 -91
  2. package/README.md +19 -1
  3. package/components/ai-elements/chart.js +20 -20
  4. package/components/ai-elements/inline-citation.js +50 -50
  5. package/components/ai-elements/message.js +1 -1
  6. package/components/ai-elements/tool.js +5 -5
  7. package/components/alert.d.ts +3 -2
  8. package/components/alert.js +25 -25
  9. package/components/answer.js +1 -1
  10. package/components/assistant-ui/action-bar.js +1 -1
  11. package/components/assistant-ui/attachment.js +68 -49
  12. package/components/assistant-ui/composer-add-context.js +1 -1
  13. package/components/assistant-ui/composer-harness.js +5 -4
  14. package/components/assistant-ui/composer-trigger-popover.js +1 -1
  15. package/components/assistant-ui/composer.js +13 -13
  16. package/components/assistant-ui/message-timing.js +6 -6
  17. package/components/assistant-ui/selection-toolbar.js +5 -5
  18. package/components/assistant-ui/sources.js +15 -15
  19. package/components/assistant-ui/tooltip-icon-button.js +18 -14
  20. package/components/audio-waveform.d.ts +21 -8
  21. package/components/audio-waveform.js +371 -94
  22. package/components/autocomplete.js +9 -9
  23. package/components/breadcrumbs.js +36 -42
  24. package/components/button.d.ts +16 -1
  25. package/components/button.js +86 -73
  26. package/components/card.js +1 -1
  27. package/components/chart.d.ts +31 -4
  28. package/components/chart.js +900 -666
  29. package/components/chip.d.ts +2 -1
  30. package/components/chip.js +56 -51
  31. package/components/command-palette.js +12 -12
  32. package/components/connector-card.d.ts +1 -2
  33. package/components/connector-card.js +17 -17
  34. package/components/date-range-picker.js +1 -2
  35. package/components/drawer.js +9 -10
  36. package/components/dropdown.js +1 -1
  37. package/components/empty-state.d.ts +2 -0
  38. package/components/empty-state.js +17 -15
  39. package/components/field.js +9 -10
  40. package/components/file-dropzone.d.ts +6 -3
  41. package/components/file-dropzone.js +72 -60
  42. package/components/filters.d.ts +37 -0
  43. package/components/filters.js +129 -0
  44. package/components/index.d.ts +1 -0
  45. package/components/index.js +447 -444
  46. package/components/infinite-canvas.js +9 -9
  47. package/components/modal.d.ts +2 -1
  48. package/components/modal.js +102 -91
  49. package/components/page-body.js +8 -8
  50. package/components/popover.d.ts +6 -1
  51. package/components/popover.js +75 -65
  52. package/components/progress-circle.d.ts +1 -1
  53. package/components/progress-circle.js +57 -48
  54. package/components/segmented.d.ts +1 -0
  55. package/components/segmented.js +34 -36
  56. package/components/select.js +2 -2
  57. package/components/selection-action-bar.js +32 -31
  58. package/components/setting-row.js +10 -10
  59. package/components/sidebar.d.ts +15 -0
  60. package/components/sidebar.js +186 -149
  61. package/components/slider.js +5 -5
  62. package/components/stepper.d.ts +1 -1
  63. package/components/stepper.js +1 -1
  64. package/components/switch.js +10 -10
  65. package/components/table.d.ts +10 -2
  66. package/components/table.js +380 -366
  67. package/components/tabs.d.ts +6 -1
  68. package/components/tabs.js +32 -29
  69. package/components/timeline.js +3 -3
  70. package/components/toast.js +53 -56
  71. package/components/ui/button.js +4 -4
  72. package/components/ui/dialog.js +1 -1
  73. package/components/viz-charts.js +263 -221
  74. package/demo/components/add-to-artifact.js +3 -2
  75. package/examples/README.md +31 -0
  76. package/examples/agents-screen.tsx +477 -0
  77. package/examples/campaign-analysis-screen.tsx +138 -0
  78. package/examples/campaigns-screen.tsx +439 -0
  79. package/examples/settings-screen.tsx +90 -0
  80. package/examples/workspace-header.tsx +71 -0
  81. package/lib/icons.d.ts +8 -0
  82. package/lib/icons.js +171 -118
  83. package/llms.txt +93 -29
  84. package/manifest.json +1660 -113
  85. package/package.json +1 -1
  86. package/styles.css +55 -68
  87. package/theme.css +50 -59
@@ -1,12 +1,12 @@
1
1
  "use client";
2
- import { jsxs as v, jsx as t, Fragment as k } from "react/jsx-runtime";
2
+ import { jsxs as x, jsx as t, Fragment as k } from "react/jsx-runtime";
3
3
  import * as r from "react";
4
4
  import { cn as d } from "../lib/cn.js";
5
5
  const N = r.createContext({
6
6
  count: 0
7
7
  }), w = r.createContext(0);
8
- function B(o) {
9
- let n = (o == null ? void 0 : o.parentElement) ?? null;
8
+ function B(a) {
9
+ let n = (a == null ? void 0 : a.parentElement) ?? null;
10
10
  for (; n; ) {
11
11
  const e = getComputedStyle(n).overflowY;
12
12
  if (e === "auto" || e === "scroll") return n;
@@ -15,31 +15,23 @@ function B(o) {
15
15
  return null;
16
16
  }
17
17
  const C = r.forwardRef(
18
- ({
19
- className: o,
20
- children: n,
21
- sticky: e,
22
- actions: c,
23
- center: i,
24
- meta: f,
25
- ...x
26
- }, a) => {
27
- const p = r.Children.toArray(n), b = r.useRef(null), u = r.useCallback(
18
+ ({ className: a, children: n, sticky: e, actions: i, center: c, meta: f, ...p }, l) => {
19
+ const h = r.Children.toArray(n), b = r.useRef(null), m = r.useCallback(
28
20
  (s) => {
29
- b.current = s, typeof a == "function" ? a(s) : a && (a.current = s);
21
+ b.current = s, typeof l == "function" ? l(s) : l && (l.current = s);
30
22
  },
31
- [a]
32
- ), [l, h] = r.useState(!1);
23
+ [l]
24
+ ), [o, g] = r.useState(!1);
33
25
  return r.useEffect(() => {
34
26
  if (!e) return;
35
- const s = B(b.current), m = s ?? window, g = () => h((s ? s.scrollTop : window.scrollY) > 2);
36
- return g(), m.addEventListener("scroll", g, { passive: !0 }), () => m.removeEventListener("scroll", g);
37
- }, [e]), /* @__PURE__ */ v(
27
+ const s = B(b.current), u = s ?? window, v = () => g((s ? s.scrollTop : window.scrollY) > 2);
28
+ return v(), u.addEventListener("scroll", v, { passive: !0 }), () => u.removeEventListener("scroll", v);
29
+ }, [e]), /* @__PURE__ */ x(
38
30
  "nav",
39
31
  {
40
- ref: u,
32
+ ref: m,
41
33
  "aria-label": "Breadcrumb",
42
- "data-stuck": e ? l ? "true" : "false" : void 0,
34
+ "data-stuck": e ? o ? "true" : "false" : void 0,
43
35
  className: d(
44
36
  "relative flex w-full items-center",
45
37
  e && "sticky top-0 z-40 bg-card transition-[border-color] duration-150 ease-out motion-reduce:transition-none",
@@ -49,56 +41,58 @@ const C = r.forwardRef(
49
41
  // background over that gap (a no-op at rest, where the strip is the
50
42
  // panel's empty padding).
51
43
  e && "before:absolute before:inset-x-0 before:-top-8 before:h-8 before:bg-inherit before:content-['']",
52
- e && (l ? "border-b border-border" : "border-b border-transparent"),
53
- o
44
+ e && (o ? "border-b border-border" : "border-b border-transparent"),
45
+ a
54
46
  ),
55
- ...x,
47
+ ...p,
56
48
  children: [
57
- /* @__PURE__ */ t("ol", { className: "flex min-w-0 shrink items-center gap-1.5 text-base", children: /* @__PURE__ */ t(N.Provider, { value: { count: p.length }, children: p.map((s, m) => /* @__PURE__ */ t(w.Provider, { value: m, children: s }, m)) }) }),
58
- f && /* @__PURE__ */ t("div", { className: "ml-4 flex shrink-0 items-center gap-3 text-xs text-muted-foreground", children: f }),
59
- i && /* @__PURE__ */ t("div", { className: "absolute left-1/2 top-1/2 z-50 flex -translate-x-1/2 -translate-y-1/2 items-center", children: i }),
60
- c && /* @__PURE__ */ t("div", { className: "ml-auto flex shrink-0 items-center gap-2 pl-4", children: c })
49
+ /* @__PURE__ */ x("div", { className: "flex min-w-0 shrink items-baseline", children: [
50
+ /* @__PURE__ */ t("ol", { className: "flex min-w-0 shrink items-center gap-1.5 text-l", children: /* @__PURE__ */ t(N.Provider, { value: { count: h.length }, children: h.map((s, u) => /* @__PURE__ */ t(w.Provider, { value: u, children: s }, u)) }) }),
51
+ f && /* @__PURE__ */ t("div", { className: "ml-3 flex shrink-0 items-baseline gap-3 text-s text-tertiary", children: f })
52
+ ] }),
53
+ c && /* @__PURE__ */ t("div", { className: "absolute left-1/2 top-1/2 z-50 flex -translate-x-1/2 -translate-y-1/2 items-center", children: c }),
54
+ i && /* @__PURE__ */ t("div", { className: "ml-auto flex shrink-0 items-center gap-2 pl-4", children: i })
61
55
  ]
62
56
  }
63
57
  );
64
58
  }
65
59
  );
66
60
  C.displayName = "Breadcrumbs";
67
- const R = r.forwardRef(({ className: o, href: n, isCurrent: e, icon: c, children: i, ...f }, x) => {
68
- const { count: a } = r.useContext(N), b = r.useContext(w) === a - 1, u = "inline-flex items-center gap-1.5", l = /* @__PURE__ */ v(k, { children: [
69
- c && /* @__PURE__ */ t("span", { "aria-hidden": !0, className: "flex shrink-0 items-center [&_svg]:size-4", children: c }),
70
- e ? /* @__PURE__ */ t("span", { className: "min-w-0 truncate", children: i }) : i
71
- ] }), h = e ? /* @__PURE__ */ t(
61
+ const R = r.forwardRef(({ className: a, href: n, isCurrent: e, icon: i, children: c, ...f }, p) => {
62
+ const { count: l } = r.useContext(N), b = r.useContext(w) === l - 1, m = "inline-flex items-center gap-1.5", o = /* @__PURE__ */ x(k, { children: [
63
+ i && /* @__PURE__ */ t("span", { "aria-hidden": !0, className: "flex shrink-0 items-center [&_svg]:size-4", children: i }),
64
+ e ? /* @__PURE__ */ t("span", { className: "min-w-0 truncate", children: c }) : c
65
+ ] }), g = e ? /* @__PURE__ */ t(
72
66
  "span",
73
67
  {
74
68
  "aria-current": "page",
75
- className: d(u, "min-w-0 text-base font-medium text-primary"),
76
- children: l
69
+ className: d(m, "min-w-0 text-l font-medium text-primary"),
70
+ children: o
77
71
  }
78
72
  ) : n ? /* @__PURE__ */ t(
79
73
  "a",
80
74
  {
81
75
  href: n,
82
76
  className: d(
83
- u,
77
+ m,
84
78
  "font-normal text-muted-foreground transition-colors hover:text-foreground",
85
79
  "outline-none focus-visible:ring-3 focus-visible:ring-ring rounded-sm"
86
80
  ),
87
- children: l
81
+ children: o
88
82
  }
89
- ) : /* @__PURE__ */ t("span", { className: d(u, "text-muted-foreground"), children: l });
90
- return /* @__PURE__ */ v(
83
+ ) : /* @__PURE__ */ t("span", { className: d(m, "text-muted-foreground"), children: o });
84
+ return /* @__PURE__ */ x(
91
85
  "li",
92
86
  {
93
- ref: x,
87
+ ref: p,
94
88
  className: d(
95
89
  "flex items-center gap-1.5",
96
90
  e ? "min-w-0 shrink" : "shrink-0",
97
- o
91
+ a
98
92
  ),
99
93
  ...f,
100
94
  children: [
101
- h,
95
+ g,
102
96
  !b && /* @__PURE__ */ t("span", { "aria-hidden": !0, className: "shrink-0 select-none text-border-strong", children: "/" })
103
97
  ]
104
98
  }
@@ -4,7 +4,22 @@ export declare const buttonVariants: (props?: ({
4
4
  variant?: "link" | "danger" | "outline" | "solid" | "secondary" | "ghost" | null | undefined;
5
5
  size?: "xs" | "sm" | "md" | "lg" | "icon" | "icon-sm" | "icon-xs" | null | undefined;
6
6
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
- export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
7
+ /** Every accepted `size` value, including the deprecated aliases. */
8
+ export type ButtonSize = "md" | "lg" | "icon" | "icon-sm" | "icon-xs"
9
+ /** @deprecated Renders identically to `md` (32px). Use `md`. */
10
+ | "xs"
11
+ /** @deprecated Renders identically to `md` (32px). Use `md`. */
12
+ | "sm";
13
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, Omit<VariantProps<typeof buttonVariants>, "size"> {
14
+ /**
15
+ * Button height. ADS has exactly two text-button heights: `md` (32px, the
16
+ * default) and `lg` (48px, 20px inline padding, radius-l). Icon-only sizes
17
+ * (`icon`, `icon-sm`, `icon-xs`) stay 32px tall.
18
+ *
19
+ * `xs` and `sm` are deprecated aliases kept for backward compatibility —
20
+ * they render identically to `md`.
21
+ */
22
+ size?: ButtonSize | null;
8
23
  isLoading?: boolean;
9
24
  startContent?: React.ReactNode;
10
25
  endContent?: React.ReactNode;
@@ -1,12 +1,13 @@
1
1
  "use client";
2
- import { jsxs as t, jsx as m } from "react/jsx-runtime";
3
- import * as p from "react";
4
- import { cva as u } from "class-variance-authority";
5
- import { cn as n } from "../lib/cn.js";
6
- import { Spinner as v } from "./spinner.js";
7
- const f = u(
2
+ import { jsx as o, jsxs as d } from "react/jsx-runtime";
3
+ import * as u from "react";
4
+ import { cva as v } from "class-variance-authority";
5
+ import { cn as i } from "../lib/cn.js";
6
+ import { IconHoverFillContext as f } from "../lib/icons.js";
7
+ import { Spinner as h } from "./spinner.js";
8
+ const x = v(
8
9
  [
9
- "relative inline-flex h-8 items-center justify-center gap-2 whitespace-nowrap",
10
+ "relative inline-flex items-center justify-center gap-2 whitespace-nowrap",
10
11
  "cursor-pointer text-m font-medium select-none",
11
12
  "rounded-md border border-transparent",
12
13
  "transition-[background,border,color,box-shadow,transform] duration-150 ease-out motion-reduce:transition-none",
@@ -21,88 +22,100 @@ const f = u(
21
22
  {
22
23
  variants: {
23
24
  variant: {
24
- solid: "bg-action-primary text-action-primary-foreground shadow-[var(--inner-glow-cta)] enabled:hover:bg-action-primary-hover enabled:active:bg-action-primary-hover",
25
+ solid: "bg-action-primary text-action-primary-foreground enabled:hover:bg-action-primary-hover enabled:active:bg-action-primary-hover",
25
26
  secondary: "border-action-primary bg-transparent text-action-primary-text shadow-none enabled:hover:bg-action-primary-soft enabled:active:bg-action-primary-soft",
26
27
  outline: "border-border bg-transparent text-foreground enabled:hover:border-action-primary enabled:hover:bg-action-primary-soft enabled:hover:text-action-primary-text enabled:active:border-action-primary enabled:active:bg-action-primary-soft enabled:active:text-action-primary-text",
27
- ghost: "bg-transparent text-foreground enabled:hover:bg-action-primary-soft enabled:hover:text-action-primary-text enabled:active:bg-action-primary-soft enabled:active:text-action-primary-text",
28
- link: "bg-transparent text-foreground underline-offset-4 enabled:hover:bg-action-primary-soft enabled:hover:text-action-primary-text enabled:hover:underline enabled:active:bg-action-primary-soft enabled:active:text-action-primary-text active:scale-none",
29
- danger: "bg-danger text-danger-foreground shadow-[var(--inner-glow-cta)] enabled:hover:bg-danger/90 enabled:active:bg-danger/90 focus-visible:ring-danger/40"
28
+ // Ghost answers hover with a WG12 outline and no fill; the label stays neutral.
29
+ ghost: "bg-transparent text-foreground enabled:hover:border-foreground enabled:active:border-foreground",
30
+ // Link only recolours its label on hover — no fill, no underline.
31
+ link: "bg-transparent text-foreground enabled:hover:text-action-primary-text enabled:active:text-action-primary-text active:scale-none",
32
+ danger: "bg-danger text-danger-foreground enabled:hover:bg-danger/90 enabled:active:bg-danger/90 focus-visible:ring-danger/40"
30
33
  },
31
34
  size: {
32
- xs: "rounded-sm px-2.5 [&_svg]:size-3.5",
33
- sm: "rounded-sm px-3 [&_svg]:size-4",
34
- md: "rounded-md px-3.5 [&_svg]:size-4",
35
- lg: "rounded-md px-4 [&_svg]:size-5",
36
- icon: "w-9 rounded-md [&_svg]:size-4",
37
- "icon-sm": "w-8 rounded-sm [&_svg]:size-4",
38
- "icon-xs": "w-7 rounded-sm [&_svg]:size-4"
35
+ // ADS has exactly two button heights: md (32px, default) and lg
36
+ // (48px). The 14px Medium label never changes between them.
37
+ // xs/sm are deprecated aliases kept for backward compatibility —
38
+ // they render identically to md.
39
+ xs: "h-8 rounded-md px-3.5 [&_svg]:size-4",
40
+ sm: "h-8 rounded-md px-3.5 [&_svg]:size-4",
41
+ md: "h-8 rounded-md px-3.5 [&_svg]:size-4",
42
+ lg: "h-12 rounded-lg px-5 [&_svg]:size-5",
43
+ icon: "h-8 w-9 rounded-md [&_svg]:size-4",
44
+ "icon-sm": "h-8 w-8 rounded-sm [&_svg]:size-4",
45
+ "icon-xs": "h-8 w-7 rounded-sm [&_svg]:size-4"
39
46
  }
40
47
  },
41
48
  defaultVariants: { variant: "solid", size: "md" }
42
49
  }
43
- ), x = {
50
+ ), y = {
44
51
  solid: "disabled:border-transparent disabled:bg-action-primary disabled:text-action-primary-foreground disabled:shadow-none",
45
52
  secondary: "disabled:border-action-primary disabled:bg-transparent disabled:text-action-primary-text disabled:shadow-none",
46
53
  outline: "disabled:border-border disabled:bg-transparent disabled:text-foreground disabled:shadow-none",
47
54
  ghost: "disabled:border-transparent disabled:bg-transparent disabled:text-foreground disabled:shadow-none",
48
55
  link: "disabled:border-transparent disabled:bg-transparent disabled:text-foreground disabled:shadow-none",
49
56
  danger: "disabled:border-transparent disabled:bg-danger disabled:text-danger-foreground disabled:shadow-none"
50
- }, y = p.forwardRef(
57
+ }, w = u.forwardRef(
51
58
  ({
52
- className: o,
53
- variant: r,
54
- size: i,
55
- isLoading: e = !1,
56
- startContent: d,
57
- endContent: s,
58
- fullWidth: b,
59
- disabled: a,
60
- children: l,
61
- ...c
62
- }, g) => /* @__PURE__ */ t(
63
- "button",
64
- {
65
- ref: g,
66
- disabled: a || e,
67
- "aria-busy": e || void 0,
68
- "data-loading": e || void 0,
69
- className: n(
70
- f({ variant: r, size: i }),
71
- b && "w-full",
72
- e ? x[r ?? "solid"] : a && "opacity-30",
73
- o
74
- ),
75
- ...c,
76
- children: [
77
- e && /* @__PURE__ */ m(
78
- v,
79
- {
80
- variant: "action",
81
- size: "sm",
82
- className: "absolute",
83
- "aria-hidden": !0
84
- }
59
+ className: s,
60
+ variant: e,
61
+ size: t,
62
+ isLoading: r = !1,
63
+ startContent: b,
64
+ endContent: l,
65
+ fullWidth: c,
66
+ disabled: n,
67
+ children: g,
68
+ ...p
69
+ }, m) => {
70
+ const a = typeof t == "string" && t.startsWith("icon") && (e === "ghost" || e === "outline" || e === "link");
71
+ return /* @__PURE__ */ o(f.Provider, { value: a, children: /* @__PURE__ */ d(
72
+ "button",
73
+ {
74
+ ref: m,
75
+ disabled: n || r,
76
+ "aria-busy": r || void 0,
77
+ "data-loading": r || void 0,
78
+ "data-icon-hover-fill": a || void 0,
79
+ className: i(
80
+ x({ variant: e, size: t }),
81
+ a && "enabled:hover:bg-transparent enabled:active:bg-transparent enabled:hover:text-action-primary enabled:active:text-action-primary",
82
+ a && e === "ghost" && "enabled:hover:border-transparent enabled:active:border-transparent",
83
+ c && "w-full",
84
+ r ? y[e ?? "solid"] : n && "opacity-30",
85
+ s
85
86
  ),
86
- /* @__PURE__ */ t(
87
- "span",
88
- {
89
- className: n(
90
- "inline-flex items-center gap-1.5",
91
- e && "opacity-0"
92
- ),
93
- children: [
94
- d,
95
- l,
96
- s
97
- ]
98
- }
99
- )
100
- ]
101
- }
102
- )
87
+ ...p,
88
+ children: [
89
+ r && /* @__PURE__ */ o(
90
+ h,
91
+ {
92
+ variant: "action",
93
+ size: "sm",
94
+ className: "absolute",
95
+ "aria-hidden": !0
96
+ }
97
+ ),
98
+ /* @__PURE__ */ d(
99
+ "span",
100
+ {
101
+ className: i(
102
+ "inline-flex items-center gap-1.5",
103
+ r && "opacity-0"
104
+ ),
105
+ children: [
106
+ b,
107
+ g,
108
+ l
109
+ ]
110
+ }
111
+ )
112
+ ]
113
+ }
114
+ ) });
115
+ }
103
116
  );
104
- y.displayName = "Button";
117
+ w.displayName = "Button";
105
118
  export {
106
- y as Button,
107
- f as buttonVariants
119
+ w as Button,
120
+ x as buttonVariants
108
121
  };
@@ -6,7 +6,7 @@ const l = d.forwardRef(
6
6
  ({ className: r, isHoverable: a, isPressable: e, children: s, ...n }, i) => {
7
7
  const c = o(
8
8
  "bg-card text-card-foreground rounded-xl",
9
- (e || a) && "shadow-elevation transition-[box-shadow,transform] duration-150 ease-out motion-reduce:transition-none",
9
+ (e || a) && "transition-[box-shadow,transform] duration-150 ease-out motion-reduce:transition-none",
10
10
  a && "hover:-translate-y-0.5",
11
11
  r
12
12
  );
@@ -2,6 +2,8 @@ import * as React from "react";
2
2
  /** One row of chart data. Gaps (null/undefined) render as breaks in the series. */
3
3
  export type ChartDatum = Record<string, string | number | null | undefined>;
4
4
  export type ChartColor = "primary" | "success" | "warning" | "danger" | "info";
5
+ /** Where a cartesian chart's series legend sits — see `BaseChartProps.legendPlacement`. */
6
+ export type ChartLegendPlacement = "header" | "top";
5
7
  /** Bounded Recharts domain surface — enough for fixed and data-driven axes. */
6
8
  export type ChartAxisDomain = [string | number, string | number];
7
9
  export type ChartTickFormatter = (value: string | number) => string | number;
@@ -82,6 +84,22 @@ interface BaseChartProps {
82
84
  grid?: boolean;
83
85
  /** Defaults to on when there is more than one series. */
84
86
  legend?: boolean;
87
+ /**
88
+ * Chart title, rendered in the chart's own header row (16px Medium). Spend
89
+ * the words on what the plot measures; scope goes in `subtitle`.
90
+ */
91
+ title?: React.ReactNode;
92
+ /** Scope line under the title — count, range, share (e.g. "442 calls · past 7 days"). */
93
+ subtitle?: React.ReactNode;
94
+ /**
95
+ * Where the series legend sits.
96
+ * • `"header"` — right-aligned at the end of the header row, opposite the
97
+ * title block, with 36px between the header and the plot. The default
98
+ * whenever a `title` or `subtitle` is set.
99
+ * • `"top"` — its own right-aligned row directly above the plot (12px
100
+ * gap). The default for an untitled chart (unchanged behavior).
101
+ */
102
+ legendPlacement?: ChartLegendPlacement;
85
103
  showYAxis?: boolean;
86
104
  formatValue?: (value: number) => string;
87
105
  /** Numeric/time x-axis scale. Time data must use numeric timestamps. */
@@ -103,9 +121,11 @@ export interface LineChartProps extends BaseChartProps {
103
121
  /** When set, only these series keys animate on mount/update. */
104
122
  animatedSeriesKeys?: string[];
105
123
  /**
106
- * Print each observation's value above its dot. On by default for a SINGLE
107
- * series (the reader shouldn't have to hover to read a number that fits);
108
- * off once there are several, where the labels would collide.
124
+ * Print each observation's value above its dot — ON by default for every
125
+ * series, so the numbers read without hovering (tooltips still work). The
126
+ * label takes its series color; light series (amber chart-2, grey chart-6,
127
+ * the context grey) use the secondary text color for contrast. Resting
128
+ * labels step aside while the plot is hovered. Pass `false` to opt out.
109
129
  */
110
130
  showValues?: boolean;
111
131
  }
@@ -123,7 +143,14 @@ export interface BarChartProps extends BaseChartProps {
123
143
  stacked?: boolean;
124
144
  /** Visual bar direction: vertical columns (default) or horizontal bars. */
125
145
  layout?: "vertical" | "horizontal";
126
- /** Print each bar's value past its end. On by default for a single series. */
146
+ /**
147
+ * Print values without hovering — ON by default (pass `false` to opt out).
148
+ * Single-series and grouped bars print their value past the bar's end in
149
+ * secondary text. Stacked bars print each segment's value centred inside it
150
+ * when the segment is at least 20px along the value axis (white ink on dark
151
+ * series, primary ink on light amber/grey), plus the stack total past the
152
+ * stack in Medium primary text. Tooltips still work on hover.
153
+ */
127
154
  showValues?: boolean;
128
155
  }
129
156
  export interface ComboChartProps extends BaseChartProps {