@antadesign/anta 0.3.1 → 0.3.2

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 (42) hide show
  1. package/dist/anta_helpers.d.ts +10 -0
  2. package/dist/anta_helpers.js +13 -1
  3. package/dist/components/Button.js +8 -17
  4. package/dist/components/Checkbox.d.ts +16 -15
  5. package/dist/components/Checkbox.js +10 -6
  6. package/dist/components/Input.d.ts +4 -4
  7. package/dist/components/Input.js +5 -5
  8. package/dist/components/RadioGroup.d.ts +15 -15
  9. package/dist/components/RadioGroup.js +8 -8
  10. package/dist/components/Tab.d.ts +34 -0
  11. package/dist/components/Tab.js +4 -0
  12. package/dist/components/TabPanel.d.ts +22 -0
  13. package/dist/components/TabPanel.js +4 -0
  14. package/dist/components/Tabs.d.ts +112 -0
  15. package/dist/components/Tabs.js +174 -0
  16. package/dist/components/Tabs.module.css +1 -0
  17. package/dist/components/Tooltip.d.ts +10 -1
  18. package/dist/components/Tooltip.js +4 -0
  19. package/dist/elements/a-button.css +1 -1
  20. package/dist/elements/a-checkbox.css +1 -1
  21. package/dist/elements/a-expander.js +6 -1
  22. package/dist/elements/a-input.js +1 -1
  23. package/dist/elements/a-radio.css +1 -1
  24. package/dist/elements/a-tab.css +1 -0
  25. package/dist/elements/a-tab.d.ts +14 -0
  26. package/dist/elements/a-tab.js +46 -0
  27. package/dist/elements/a-tabpanel.css +1 -0
  28. package/dist/elements/a-tabs.css +1 -0
  29. package/dist/elements/a-tabs.d.ts +31 -0
  30. package/dist/elements/a-tabs.js +157 -0
  31. package/dist/elements/a-text.css +1 -1
  32. package/dist/elements/a-title.css +1 -1
  33. package/dist/elements/a-tooltip.d.ts +18 -0
  34. package/dist/elements/a-tooltip.js +45 -0
  35. package/dist/elements/index.d.ts +3 -0
  36. package/dist/elements/index.js +7 -0
  37. package/dist/general_types.d.ts +146 -20
  38. package/dist/index.d.ts +6 -0
  39. package/dist/index.js +6 -0
  40. package/dist/jsx-runtime.d.ts +5 -1
  41. package/dist/tokens.css +1 -1
  42. package/package.json +1 -1
@@ -1,4 +1,14 @@
1
1
  export declare function hasChildren(children: React.ReactNode): boolean;
2
+ /**
3
+ * Normalize a wrapper's label content the way `Button` / `Tabs` do: a bare string
4
+ * or number becomes a `<tag>` — the ellipsis-capable label part (`a-button-label`,
5
+ * `a-tab-label`, …) that carries the optical baseline nudge and truncates cleanly;
6
+ * empty / whitespace strings and `NaN` carry no content and are dropped; a JSX
7
+ * element is the consumer's own structure, passed through unwrapped (so an icon-only
8
+ * child keeps its layout). Shared so the rule lives in one place — don't re-implement
9
+ * it per component.
10
+ */
11
+ export declare function wrapLabel(kids: React.ReactNode, tag: string): React.ReactNode;
2
12
  /**
3
13
  * Unwrap a `statechange` (or any) `CustomEvent` a renderer may deliver wrapped:
4
14
  * React hands a synthetic event with the real one on `.nativeEvent`; Preact passes
@@ -1,6 +1,17 @@
1
+ import { jsx } from "./jsx-runtime";
1
2
  function hasChildren(children) {
2
3
  return Array.isArray(children) ? children.length > 0 : children != null;
3
4
  }
5
+ function wrapLabel(kids, tag) {
6
+ if (kids == null) return kids;
7
+ const arr = Array.isArray(kids) ? kids : [kids];
8
+ return arr.map((child, i) => {
9
+ if (typeof child === "string") return child.trim() === "" ? null : jsx(tag, { children: child }, i);
10
+ if (typeof child === "number") return Number.isNaN(child) ? null : jsx(tag, { children: child }, i);
11
+ if (child == null || typeof child === "boolean") return null;
12
+ return child;
13
+ });
14
+ }
4
15
  function nativeStateChange(e) {
5
16
  const event = "nativeEvent" in e ? e.nativeEvent : e;
6
17
  return { event, detail: event?.detail };
@@ -33,5 +44,6 @@ export {
33
44
  NAMED_TONES,
34
45
  hasChildren,
35
46
  nativeStateChange,
36
- toneStyle
47
+ toneStyle,
48
+ wrapLabel
37
49
  };
@@ -1,19 +1,5 @@
1
1
  import { Fragment, jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
- import { toneStyle } from "../anta_helpers";
3
- const wrapChildren = (kids) => {
4
- if (kids == null) return kids;
5
- const arr = Array.isArray(kids) ? kids : [kids];
6
- return arr.map((child, i) => {
7
- if (typeof child === "string") {
8
- return child.trim() === "" ? null : /* @__PURE__ */ jsx("a-button-label", { children: child }, i);
9
- }
10
- if (typeof child === "number") {
11
- return Number.isNaN(child) ? null : /* @__PURE__ */ jsx("a-button-label", { children: child }, i);
12
- }
13
- if (child == null || typeof child === "boolean") return null;
14
- return child;
15
- });
16
- };
2
+ import { toneStyle, wrapLabel } from "../anta_helpers";
17
3
  const Button = ({
18
4
  priority,
19
5
  tone,
@@ -38,6 +24,12 @@ const Button = ({
38
24
  const computedStyle = toneStyle(toneAttr, "--button-tone-source", style);
39
25
  const isIconOnly = icon != null && label == null && children == null && iconTrailing == null;
40
26
  const sharedAttrs = {
27
+ // `<a-button>` is a custom element with no implicit ARIA role, so AT would
28
+ // announce it as a generic clickable — and `aria-pressed` below is only
29
+ // valid on a button/switch role. Publish `role="button"` from the wrapper
30
+ // (ARIA lives in the wrapper) for both the element and the `<a href>` path;
31
+ // a consumer's own `role` in `...rest` still wins by spread order.
32
+ role: "button",
41
33
  priority,
42
34
  tone: toneAttr,
43
35
  underline,
@@ -68,7 +60,7 @@ const Button = ({
68
60
  const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
69
61
  icon && /* @__PURE__ */ jsx("a-icon", { shape: icon, "aria-hidden": "true" }),
70
62
  label != null && /* @__PURE__ */ jsx("a-button-label", { children: label }),
71
- wrapChildren(children),
63
+ wrapLabel(children, "a-button-label"),
72
64
  iconTrailing && /* @__PURE__ */ jsx("a-icon", { shape: iconTrailing, "aria-hidden": "true" })
73
65
  ] });
74
66
  if (href != null) {
@@ -76,7 +68,6 @@ const Button = ({
76
68
  "a",
77
69
  {
78
70
  href,
79
- role: "button",
80
71
  ...sharedAttrs,
81
72
  ...rest,
82
73
  children: inner
@@ -11,9 +11,9 @@ type StateDetail = {
11
11
  prev: CheckboxState;
12
12
  };
13
13
  type StateChangeEvent = CustomEvent<StateDetail>;
14
- /** Snapshot passed as the 2nd argument to `onAnyChange` — the new value plus
14
+ /** Snapshot passed as the 2nd argument to `onValueChange` — the new value plus
15
15
  * form-relevant fields, so you don't poke at `event.target`. Mirrors `Input`'s
16
- * `onAnyChange` convention. */
16
+ * `onValueChange` convention. */
17
17
  export interface CheckboxChangeAttrs {
18
18
  checked: boolean;
19
19
  indeterminate: boolean;
@@ -48,21 +48,22 @@ export interface CheckboxProps extends BaseProps {
48
48
  /** Value submitted with the form when checked — like a native checkbox.
49
49
  * @defaultValue "on" */
50
50
  value?: string;
51
- /** Colour variant, or any literal CSS color (`'#ff1493'`, `'rebeccapurple'`)
52
- * for a one-off custom tone. Tints fill, label, hint, and the unselected box
53
- * border. Named tones track light/dark mode automatically via the theme-aware
54
- * role tokens; a custom colour keeps its hue + chroma and pins lightness to the
55
- * fill curve.
51
+ /** Colour of the **mark** the checked-box fill and the unselected box border.
52
+ * A named tone or any literal CSS color (`'#ff1493'`, `'rebeccapurple'`) for a
53
+ * one-off custom tone. Named tones track light/dark mode automatically via the
54
+ * theme-aware role tokens; a custom colour keeps its hue + chroma and pins
55
+ * lightness to the fill curve. The label + hint stay neutral — use `toneText`
56
+ * to recolour those.
56
57
  * @defaultValue 'neutral' */
57
58
  tone?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
59
+ /** Colour of the **text** — the label and hint — independent of `tone`. A named
60
+ * tone or any literal CSS color. Named tones track light/dark via the theme-aware
61
+ * `--text-*` role tokens. Omit to leave the text neutral.
62
+ * @defaultValue 'neutral' */
63
+ toneText?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
58
64
  /** Size variant. small=14px, medium=16px, large=18px box.
59
65
  * @defaultValue 'medium' */
60
66
  size?: 'small' | 'medium' | 'large';
61
- /** Visual priority. `primary` fills the checked box with the tone colour and
62
- * draws a white checkmark; `secondary` keeps the box unfilled and draws the
63
- * border + checkmark in the tone colour (an outlined look).
64
- * @defaultValue 'primary' */
65
- priority?: 'primary' | 'secondary';
66
67
  /** Fired on click / Space *before* the element applies any change. Event-first
67
68
  * so `event.preventDefault()` is the synchronous veto (uncontrolled mode);
68
69
  * `detail` carries `{ next, prev }`. In controlled mode the element never
@@ -77,8 +78,8 @@ export interface CheckboxProps extends BaseProps {
77
78
  onChange?: (event: Event) => void;
78
79
  /** Like `onChange`, but with a `{ checked, indeterminate, name, value }` snapshot
79
80
  * as the 2nd argument — the ergonomic "just give me the new value" callback
80
- * (mirrors `Input`'s `onAnyChange`). */
81
- onAnyChange?: (event: Event, attrs: CheckboxChangeAttrs) => void;
81
+ * (mirrors `Input`'s `onValueChange`). */
82
+ onValueChange?: (event: Event, attrs: CheckboxChangeAttrs) => void;
82
83
  }
83
84
  /**
84
85
  * Checkbox. Renders an `<a-checkbox>` web component that owns the visual
@@ -93,5 +94,5 @@ export interface CheckboxProps extends BaseProps {
93
94
  * <Checkbox defaultChecked label="Remember me" hint="On this device" />
94
95
  * ```
95
96
  */
96
- export declare const Checkbox: ({ checked, defaultChecked, disabled, tone, size, priority, onStateChange, onChange, onAnyChange, label, hint, className, style, children, tabIndex, ...rest }: CheckboxProps) => any;
97
+ export declare const Checkbox: ({ checked, defaultChecked, disabled, tone, toneText, size, onStateChange, onChange, onValueChange, label, hint, className, style, children, tabIndex, ...rest }: CheckboxProps) => any;
97
98
  export {};
@@ -13,11 +13,11 @@ const Checkbox = ({
13
13
  defaultChecked,
14
14
  disabled,
15
15
  tone,
16
+ toneText,
16
17
  size,
17
- priority,
18
18
  onStateChange,
19
19
  onChange,
20
- onAnyChange,
20
+ onValueChange,
21
21
  label,
22
22
  hint,
23
23
  className,
@@ -26,7 +26,11 @@ const Checkbox = ({
26
26
  tabIndex,
27
27
  ...rest
28
28
  }) => {
29
- const computedStyle = toneStyle(tone, "--checkbox-tone-source", style);
29
+ const computedStyle = toneStyle(
30
+ toneText,
31
+ "--checkbox-tone-text-source",
32
+ toneStyle(tone, "--checkbox-tone-source", style)
33
+ );
30
34
  const explicitAriaLabel = rest["aria-label"];
31
35
  const ariaLabel = (typeof explicitAriaLabel === "string" ? explicitAriaLabel : void 0) ?? label ?? (typeof children === "string" ? children : void 0);
32
36
  const onstatechange = onStateChange ? (e) => {
@@ -37,9 +41,9 @@ const Checkbox = ({
37
41
  prev: stateToValue(detail.prev)
38
42
  });
39
43
  } : void 0;
40
- const onchange = onChange || onAnyChange ? (e) => {
44
+ const onchange = onChange || onValueChange ? (e) => {
41
45
  onChange?.(e);
42
- onAnyChange?.(e, checkboxAttrsOf(e.currentTarget));
46
+ onValueChange?.(e, checkboxAttrsOf(e.currentTarget));
43
47
  } : void 0;
44
48
  const stateAttr = checked !== void 0 ? valueToState(checked) : void 0;
45
49
  const defaultStateAttr = checked === void 0 && defaultChecked !== void 0 ? valueToState(defaultChecked) : void 0;
@@ -55,8 +59,8 @@ const Checkbox = ({
55
59
  "default-state": defaultStateAttr,
56
60
  disabled: disabled ? "" : void 0,
57
61
  tone: tone && tone !== "neutral" ? tone : void 0,
62
+ "tone-text": toneText && toneText !== "neutral" ? toneText : void 0,
58
63
  size: size && size !== "medium" ? size : void 0,
59
- priority: priority && priority !== "primary" ? priority : void 0,
60
64
  tabIndex: disabled ? -1 : tabIndex ?? 0,
61
65
  onstatechange,
62
66
  onchange,
@@ -1,6 +1,6 @@
1
1
  import type { BaseProps, DOMEventHandlers } from '../general_types';
2
2
  import type { IconShape } from '../elements/a-icon.shapes';
3
- /** Convenience snapshot passed as the 2nd argument to `onAnyChange`. */
3
+ /** Convenience snapshot passed as the 2nd argument to `onValueChange`. */
4
4
  export interface InputChangeAttrs {
5
5
  /** Current value. */
6
6
  value: string;
@@ -114,7 +114,7 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
114
114
  onInput?: (e: any) => void;
115
115
  /** Fires on **commit** (blur / Enter) — the platform `change` semantics, **not**
116
116
  * React's per-keystroke `onChange`. This is a web component, so `onChange` keeps
117
- * the native meaning; reach for `onInput` (every keystroke) or `onAnyChange`
117
+ * the native meaning; reach for `onInput` (every keystroke) or `onValueChange`
118
118
  * (both) for live updates. Read `e.target.value`. */
119
119
  onChange?: (e: any) => void;
120
120
  /** Unified value-change handler — the easy path for state. Fires on `input`
@@ -123,7 +123,7 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
123
123
  * you can do `setForm(s => ({ ...s, [attrs.name]: attrs.value }))` without
124
124
  * digging into the event. Use `event.type` to tell a live edit (`input`) from
125
125
  * a commit (`change`); read `id` / `type` / `className` off `event.target`. */
126
- onAnyChange?: (event: any, attrs: InputChangeAttrs) => void;
126
+ onValueChange?: (event: any, attrs: InputChangeAttrs) => void;
127
127
  /** Fires when the built-in clear button (`clearable`) is clicked, *before*
128
128
  * the field is cleared. Call `e.preventDefault()` to keep the current value
129
129
  * — the clear is cancelled and `onClearInput` won't fire. Backed by the
@@ -156,4 +156,4 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
156
156
  * <Input label="Email" type="email" placeholder="you@example.com" clearable />
157
157
  * ```
158
158
  */
159
- export declare const Input: ({ label, hint, status, statusIcon, tone, size, value, defaultValue, multiline, rows, maxRows, clearable, leading, trailing, type, autoComplete, inputMode, name, placeholder, disabled, readOnly, required, dimActions, spellCheck, maxLength, minLength, pattern, min, max, step, onInput, onChange, onAnyChange, onClearClick, onClearInput, children, className, style, ...rest }: InputProps) => any;
159
+ export declare const Input: ({ label, hint, status, statusIcon, tone, size, value, defaultValue, multiline, rows, maxRows, clearable, leading, trailing, type, autoComplete, inputMode, name, placeholder, disabled, readOnly, required, dimActions, spellCheck, maxLength, minLength, pattern, min, max, step, onInput, onChange, onValueChange, onClearClick, onClearInput, children, className, style, ...rest }: InputProps) => any;
@@ -62,7 +62,7 @@ const Input = ({
62
62
  step,
63
63
  onInput,
64
64
  onChange,
65
- onAnyChange,
65
+ onValueChange,
66
66
  onClearClick,
67
67
  onClearInput,
68
68
  children,
@@ -100,13 +100,13 @@ const Input = ({
100
100
  max,
101
101
  step,
102
102
  "aria-invalid": status === "critical" ? "true" : void 0,
103
- oninput: onInput || onAnyChange ? (e) => {
103
+ oninput: onInput || onValueChange ? (e) => {
104
104
  onInput?.(e);
105
- onAnyChange?.(e, attrsOf(e));
105
+ onValueChange?.(e, attrsOf(e));
106
106
  } : void 0,
107
- onchange: onChange || onAnyChange ? (e) => {
107
+ onchange: onChange || onValueChange ? (e) => {
108
108
  onChange?.(e);
109
- onAnyChange?.(e, attrsOf(e));
109
+ onValueChange?.(e, attrsOf(e));
110
110
  } : void 0,
111
111
  onclearclick: onClearClick ? (e) => onClearClick(nativeStateChange(e).event) : void 0,
112
112
  onclearinput: onClearInput ? (e) => onClearInput(nativeStateChange(e).event) : void 0,
@@ -8,7 +8,7 @@ type StateDetail = {
8
8
  reason: StateReason;
9
9
  };
10
10
  type StateChangeEvent = CustomEvent<StateDetail>;
11
- /** Snapshot passed as the 2nd argument to `onAnyChange` — the new value plus the
11
+ /** Snapshot passed as the 2nd argument to `onValueChange` — the new value plus the
12
12
  * field name, so you don't poke at `event.target`. Mirrors `Input`/`Checkbox`. */
13
13
  export interface RadioChangeAttrs {
14
14
  value: string | null;
@@ -25,12 +25,12 @@ export interface RadioOption {
25
25
  hint?: React.ReactNode;
26
26
  /** Disable just this option (skipped by keyboard, dropped from the tab order). */
27
27
  disabled?: boolean;
28
- /** Override this one option's tone (defaults to the group's `tone`). */
28
+ /** Override this one option's mark tone (defaults to the group's `tone`). */
29
29
  tone?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
30
+ /** Override this one option's text tone (defaults to the group's `toneText`). */
31
+ toneText?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
30
32
  /** Override this one option's size (defaults to the group's `size`). */
31
33
  size?: "small" | "medium" | "large";
32
- /** Override this one option's priority (defaults to the group's `priority`). */
33
- priority?: "primary" | "secondary";
34
34
  }
35
35
  /** Public props for `<RadioGroup>` — the single-select container. */
36
36
  export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"> {
@@ -58,7 +58,7 @@ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"
58
58
  onChange?: (event: Event) => void;
59
59
  /** Like `onChange`, but with a `{ value, name }` snapshot as the 2nd argument —
60
60
  * the ergonomic "just give me the new value" callback (mirrors `Input`). */
61
- onAnyChange?: (event: Event, attrs: RadioChangeAttrs) => void;
61
+ onValueChange?: (event: Event, attrs: RadioChangeAttrs) => void;
62
62
  /** Fired when focus enters the group (any option) — wired to `focusin`, since
63
63
  * focus lands on an individual option, not the group element itself. */
64
64
  onFocus?: (event: FocusEvent) => void;
@@ -78,20 +78,20 @@ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"
78
78
  * the neutral default.
79
79
  * @defaultValue 'neutral' */
80
80
  status?: "neutral" | "brand" | "info" | "success" | "warning" | "critical";
81
- /** Tone applied to every option (an option's own `tone` wins), or any literal
82
- * CSS color for a one-off custom tone. Tints fill, label, hint, and the
83
- * unselected ring border. Named tones track light/dark mode.
81
+ /** Mark tone applied to every option (an option's own `tone` wins), or any literal
82
+ * CSS color for a one-off custom tone. Colours the selected-ring fill + dot and
83
+ * the unselected ring border. Named tones track light/dark mode. The option text
84
+ * stays neutral — use `toneText` for that.
84
85
  * @defaultValue 'neutral' */
85
86
  tone?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
87
+ /** Text tone applied to every option's label + hint (an option's own `toneText`
88
+ * wins), independent of `tone`. A named tone or any literal CSS color. Omit to
89
+ * leave the text neutral.
90
+ * @defaultValue 'neutral' */
91
+ toneText?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
86
92
  /** Size applied to every option (an option's own `size` wins).
87
93
  * @defaultValue 'medium' */
88
94
  size?: "small" | "medium" | "large";
89
- /** Visual priority applied to every option (an option's own `priority` wins).
90
- * `primary` fills the selected ring with the tone colour and draws a white dot;
91
- * `secondary` keeps the ring unfilled and draws the border + dot in the tone
92
- * colour (an outlined look).
93
- * @defaultValue 'primary' */
94
- priority?: "primary" | "secondary";
95
95
  /** Disable the whole group. */
96
96
  disabled?: boolean;
97
97
  /** Layout + arrow-key axis.
@@ -115,5 +115,5 @@ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"
115
115
  *
116
116
  * Requires `@antadesign/anta/elements` (client-side only).
117
117
  */
118
- export declare const RadioGroup: ({ options, value, defaultValue, onStateChange, onChange, onAnyChange, onFocus, onBlur, name, label, hint, status, tone, size, priority, disabled, orientation, className, style, ...rest }: RadioGroupProps) => any;
118
+ export declare const RadioGroup: ({ options, value, defaultValue, onStateChange, onChange, onValueChange, onFocus, onBlur, name, label, hint, status, tone, toneText, size, disabled, orientation, className, style, ...rest }: RadioGroupProps) => any;
119
119
  export {};
@@ -11,7 +11,7 @@ const RadioGroup = ({
11
11
  defaultValue,
12
12
  onStateChange,
13
13
  onChange,
14
- onAnyChange,
14
+ onValueChange,
15
15
  onFocus,
16
16
  onBlur,
17
17
  name,
@@ -19,8 +19,8 @@ const RadioGroup = ({
19
19
  hint,
20
20
  status,
21
21
  tone,
22
+ toneText,
22
23
  size,
23
- priority,
24
24
  disabled,
25
25
  orientation,
26
26
  className,
@@ -47,9 +47,9 @@ const RadioGroup = ({
47
47
  if (detail.reason === "user" && event.defaultPrevented) return;
48
48
  setInternalValue(detail.next ?? void 0);
49
49
  };
50
- const onchange = onChange || onAnyChange ? (e) => {
50
+ const onchange = onChange || onValueChange ? (e) => {
51
51
  onChange?.(e);
52
- onAnyChange?.(e, radioAttrsOf(e.currentTarget));
52
+ onValueChange?.(e, radioAttrsOf(e.currentTarget));
53
53
  } : void 0;
54
54
  return /* @__PURE__ */ jsxs(
55
55
  "a-radio-group",
@@ -64,8 +64,8 @@ const RadioGroup = ({
64
64
  name,
65
65
  status: status && status !== "neutral" ? status : void 0,
66
66
  tone: tone && tone !== "neutral" ? tone : void 0,
67
+ "tone-text": toneText && toneText !== "neutral" ? toneText : void 0,
67
68
  size: size && size !== "medium" ? size : void 0,
68
- priority: priority && priority !== "primary" ? priority : void 0,
69
69
  disabled: disabled ? "" : void 0,
70
70
  orientation: orientation && orientation !== "vertical" ? orientation : void 0,
71
71
  onstatechange,
@@ -73,7 +73,7 @@ const RadioGroup = ({
73
73
  onfocusin: onFocus,
74
74
  onfocusout: onBlur,
75
75
  class: className,
76
- style: toneStyle(tone, "--radio-tone-source", style),
76
+ style: toneStyle(toneText, "--radio-tone-text-source", toneStyle(tone, "--radio-tone-source", style)),
77
77
  children: [
78
78
  label && /* @__PURE__ */ jsx("a-radio-group-label", { id: labelId, children: label }),
79
79
  hint && /* @__PURE__ */ jsx("a-radio-group-hint", { id: hintId, children: hint }),
@@ -87,10 +87,10 @@ const RadioGroup = ({
87
87
  "aria-disabled": optDisabled ? "true" : void 0,
88
88
  tabIndex: o.value === tabStopValue ? 0 : -1,
89
89
  tone: o.tone && o.tone !== "neutral" ? o.tone : void 0,
90
+ "tone-text": o.toneText && o.toneText !== "neutral" ? o.toneText : void 0,
90
91
  size: o.size && o.size !== "medium" ? o.size : void 0,
91
- priority: o.priority && o.priority !== "primary" ? o.priority : void 0,
92
92
  disabled: o.disabled ? "" : void 0,
93
- style: toneStyle(o.tone, "--radio-tone-source"),
93
+ style: toneStyle(o.toneText, "--radio-tone-text-source", toneStyle(o.tone, "--radio-tone-source")),
94
94
  children: [
95
95
  /* @__PURE__ */ jsx("a-radio-label", { children: o.label }),
96
96
  o.hint != null && /* @__PURE__ */ jsx("a-radio-hint", { children: o.hint })
@@ -0,0 +1,34 @@
1
+ import type { IconShape } from "../elements/a-icon.shapes";
2
+ /** One tab in a `<Tabs>` strip. A **config component**: `Tabs` reads these props to
3
+ * render the underlying `<a-tab>` (`tabindex`, `role`, `aria-controls`, and
4
+ * selection are all `Tabs`' job), so `<Tab>` renders nothing on its own. */
5
+ export interface TabProps {
6
+ /** This tab's identity — pairs it with the `<TabPanel value="…">` of the same
7
+ * value, and the value reported by `onStateChange` / `onChange`. Unique per strip. */
8
+ value: string;
9
+ /** Visible label. Alternatively pass `children`. */
10
+ label?: React.ReactNode;
11
+ /** Tab content when you need more than a string — used if `label` is omitted. */
12
+ children?: React.ReactNode;
13
+ /** Leading icon shape, rendered before the label. */
14
+ icon?: IconShape;
15
+ /** Trailing icon shape, rendered after the label. */
16
+ iconTrailing?: IconShape;
17
+ /** Per-tab tone override, same vocabulary as `<Tabs tone>` — colours this one tab's
18
+ * label + icons (all priorities/modes, named or custom colour) and, when it's the
19
+ * active tab, its indicator. For a **custom literal colour** the sliding indicator can't
20
+ * adopt it (the shared moving element can't read a descendant's colour), so a custom tone
21
+ * colours the label everywhere and the indicator only in `noslide`; the six **named**
22
+ * tones colour both in every mode. Overrides the strip's `tone` for this tab.
23
+ * @defaultValue inherits the strip's `tone` */
24
+ tone?: "neutral" | "brand" | "info" | "success" | "warning" | "critical" | (string & {});
25
+ /** Disable just this tab — skipped by keyboard nav and dropped from the tab order
26
+ * (a disabled-but-selected tab stays reachable, per the ARIA pattern). */
27
+ disabled?: boolean;
28
+ }
29
+ /**
30
+ * A tab inside `<Tabs>`. Configuration only — `Tabs` reads its props and renders the
31
+ * real `<a-tab>`, so this component itself produces no DOM. Use it as a direct child
32
+ * of `<Tabs>`; rendering it elsewhere does nothing.
33
+ */
34
+ export declare const Tab: (_props: TabProps) => null;
@@ -0,0 +1,4 @@
1
+ const Tab = (_props) => null;
2
+ export {
3
+ Tab
4
+ };
@@ -0,0 +1,22 @@
1
+ import type { TabsMounting } from "./Tabs";
2
+ /** A panel paired to the `<Tab>` of the same `value`. A **config component**: `Tabs`
3
+ * reads these props and renders the underlying `<a-tabpanel>` (id wiring, show/hide,
4
+ * `inert`, and the mounting strategy are all `Tabs`' job). */
5
+ export interface TabPanelProps {
6
+ /** Pairs this panel with the `<Tab value="…">` of the same value. */
7
+ value: string;
8
+ /** Panel content — arbitrary React/Preact. */
9
+ children?: React.ReactNode;
10
+ /** Override the `<Tabs mounting>` strategy for just this panel. See `TabsMounting`. */
11
+ mounting?: TabsMounting;
12
+ /** CSS class on the rendered `<a-tabpanel>`. */
13
+ className?: string;
14
+ /** Inline style on the rendered `<a-tabpanel>`. */
15
+ style?: React.CSSProperties;
16
+ }
17
+ /**
18
+ * A tab panel inside `<Tabs>`. Configuration only — `Tabs` reads its props and renders
19
+ * the real `<a-tabpanel>`, so this component itself produces no DOM. Use it as a direct
20
+ * child of `<Tabs>`; rendering it elsewhere does nothing.
21
+ */
22
+ export declare const TabPanel: (_props: TabPanelProps) => null;
@@ -0,0 +1,4 @@
1
+ const TabPanel = (_props) => null;
2
+ export {
3
+ TabPanel
4
+ };
@@ -0,0 +1,112 @@
1
+ import type { BaseProps } from "../general_types";
2
+ /** The element's `statechange` payload — `next`/`prev` are tab values (`null` = none). */
3
+ type StateDetail = {
4
+ next: string | null;
5
+ prev: string | null;
6
+ };
7
+ type StateChangeEvent = CustomEvent<StateDetail>;
8
+ /** Snapshot passed as the 2nd argument to `onValueChange`. */
9
+ export interface TabsChangeAttrs {
10
+ value: string | null;
11
+ }
12
+ /**
13
+ * How `<TabPanel>`s that aren't the active one are handled.
14
+ * - `'display'` *(default)* — all panels mounted; inactive ones hidden via
15
+ * `display:none`. Preserves panel DOM/form state; correct a11y for free.
16
+ * - `'visibility'` — all mounted; inactive hidden via `visibility:hidden`, so each
17
+ * panel keeps its layout box (useful to avoid reflow / for measuring).
18
+ * - `'active'` — only the active panel is rendered; React unmounts the rest (state
19
+ * resets on switch; defers expensive subtrees).
20
+ * - `'lazy'` — a panel mounts on first activation, then stays mounted+hidden.
21
+ */
22
+ export type TabsMounting = "display" | "visibility" | "active" | "lazy";
23
+ /** Public props for `<Tabs>`. */
24
+ export interface TabsProps extends Omit<BaseProps, "onChange"> {
25
+ /** The strip's contents, as config-only elements `Tabs` reads (they render
26
+ * nothing themselves): one `<Tab value="…" label="…">` per tab, and optionally a
27
+ * `<TabPanel value="…">` whose `value` matches a tab — `Tabs` then shows that
28
+ * panel's body when its tab is active. Omit the panels to use `Tabs` as a bare
29
+ * selectable strip. Order is free; tabs and panels can interleave. */
30
+ children?: React.ReactNode;
31
+ /** Controlled active value — the `value` of the `<Tab>` to mark selected (and, when a
32
+ * `<TabPanel value="…">` shares it, the panel to reveal). When set, you own selection:
33
+ * the strip renders exactly what this says, and a user pick only *requests* a change
34
+ * via `onStateChange` — apply it by updating this prop, reject it by leaving it
35
+ * unchanged. Leave undefined (and use `defaultValue`) for uncontrolled. */
36
+ value?: string;
37
+ /** Initial active value for the uncontrolled case — the `value` of the `<Tab>` selected
38
+ * on first render. After that `Tabs` owns selection itself. */
39
+ defaultValue?: string;
40
+ /** Fired whenever the active tab changes — event-first. `detail` is
41
+ * `{ next, prev }` (values; `null` = none). Cancelable: `event.preventDefault()`
42
+ * vetoes it (uncontrolled), or in controlled mode answer by updating `value`. */
43
+ onStateChange?: (event: StateChangeEvent, detail: StateDetail) => void;
44
+ /** Fired *after* the active tab changes — a native `change` event. */
45
+ onChange?: (event: Event) => void;
46
+ /** Like `onChange`, but with a `{ value }` snapshot as the 2nd argument. */
47
+ onValueChange?: (event: Event, attrs: TabsChangeAttrs) => void;
48
+ /** Focus entered the strip (any tab) — wired to `focusin` (focus lands on a tab,
49
+ * not the tablist). */
50
+ onFocus?: (event: FocusEvent) => void;
51
+ /** Focus left the strip entirely — wired to `focusout`. */
52
+ onBlur?: (event: FocusEvent) => void;
53
+ /** Accessible name for the tablist (`aria-label`). */
54
+ label?: string;
55
+ /** Visual priority. `primary` is the raised pill on a recessed track (the
56
+ * segmented-control look); `secondary` keeps that sizing but drops the track, marking
57
+ * the selected tab with a subtle active background fill; `tertiary` is a bottom-underline
58
+ * indicator under the selected tab (no track, no rest line). `tone` colours `secondary` +
59
+ * `tertiary`; `primary` stays neutral.
60
+ * @defaultValue 'primary' */
61
+ priority?: "primary" | "secondary" | "tertiary";
62
+ /** Tone applied to the selected indicator/label, or any literal CSS color for a
63
+ * one-off custom tone (derived in oklch). Named tones track light/dark.
64
+ * @defaultValue 'neutral' */
65
+ tone?: "neutral" | "brand" | "info" | "success" | "warning" | "critical" | (string & {});
66
+ /** Size — small 24px · medium 28px · large 32px tall, matching Button's scale (the tab's
67
+ * label leading runs a touch tighter, offset by 1px more block padding per side).
68
+ * @defaultValue 'medium' */
69
+ size?: "small" | "medium" | "large";
70
+ /** Layout + arrow-key axis. Horizontal ellipsizes labels when tabs overflow (scroll
71
+ * is opt-in via CSS); vertical stacks them.
72
+ * @defaultValue 'horizontal' */
73
+ orientation?: "horizontal" | "vertical";
74
+ /** How inactive panels are mounted/hidden. Per-panel `<TabPanel mounting>` overrides.
75
+ * @defaultValue 'display' */
76
+ mounting?: TabsMounting;
77
+ /** Disable the sliding indicator. By default the selected-tab indicator animates
78
+ * between tabs (a single rectangle, via CSS anchor positioning); `noslide` paints it
79
+ * per tab so it snaps with no movement. (Browsers without anchor positioning get that
80
+ * per-tab paint automatically — `noslide` is the explicit opt-out.) */
81
+ noslide?: boolean;
82
+ /** Disable the whole strip. */
83
+ disabled?: boolean;
84
+ }
85
+ /**
86
+ * `<Tabs>` — a tablist with optional panels, rendered from `<Tab>` / `<TabPanel>`
87
+ * children.
88
+ *
89
+ * Like `RadioGroup`, this wrapper owns the **declarative** DOM concerns the elements
90
+ * deliberately don't touch — each tab's **`tabindex`** (every enabled tab is its own
91
+ * tab stop), `role`, the `aria-controls`/`aria-labelledby` wiring, and which panel
92
+ * shows (per `mounting`). Selection itself lives in `<a-tabs>` off-DOM (it sets each
93
+ * tab's `selected` property), so the elements never mutate the DOM; this wrapper
94
+ * reflects the current value into panel visibility on re-render.
95
+ *
96
+ * Controlled (`value` + `onStateChange`) or uncontrolled (`defaultValue`). Drop the
97
+ * `<TabPanel>`s and it's just a selectable strip emitting `statechange` / `change`.
98
+ *
99
+ * Requires `@antadesign/anta/elements` (client-side only).
100
+ *
101
+ * @example
102
+ * ```tsx
103
+ * <Tabs defaultValue="account" label="Settings">
104
+ * <Tab value="account" label="Account" icon="user" />
105
+ * <Tab value="security" label="Security" />
106
+ * <TabPanel value="account"><AccountForm /></TabPanel>
107
+ * <TabPanel value="security"><SecurityForm /></TabPanel>
108
+ * </Tabs>
109
+ * ```
110
+ */
111
+ export declare const Tabs: ({ children, value, defaultValue, onStateChange, onChange, onValueChange, onFocus, onBlur, label, priority, tone, size, orientation, mounting, noslide, disabled, className, style, id, ...rest }: TabsProps) => any;
112
+ export {};