@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.
- package/dist/anta_helpers.d.ts +10 -0
- package/dist/anta_helpers.js +13 -1
- package/dist/components/Button.js +8 -17
- package/dist/components/Checkbox.d.ts +16 -15
- package/dist/components/Checkbox.js +10 -6
- package/dist/components/Input.d.ts +4 -4
- package/dist/components/Input.js +5 -5
- package/dist/components/RadioGroup.d.ts +15 -15
- package/dist/components/RadioGroup.js +8 -8
- package/dist/components/Tab.d.ts +34 -0
- package/dist/components/Tab.js +4 -0
- package/dist/components/TabPanel.d.ts +22 -0
- package/dist/components/TabPanel.js +4 -0
- package/dist/components/Tabs.d.ts +112 -0
- package/dist/components/Tabs.js +174 -0
- package/dist/components/Tabs.module.css +1 -0
- package/dist/components/Tooltip.d.ts +10 -1
- package/dist/components/Tooltip.js +4 -0
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-checkbox.css +1 -1
- package/dist/elements/a-expander.js +6 -1
- package/dist/elements/a-input.js +1 -1
- package/dist/elements/a-radio.css +1 -1
- package/dist/elements/a-tab.css +1 -0
- package/dist/elements/a-tab.d.ts +14 -0
- package/dist/elements/a-tab.js +46 -0
- package/dist/elements/a-tabpanel.css +1 -0
- package/dist/elements/a-tabs.css +1 -0
- package/dist/elements/a-tabs.d.ts +31 -0
- package/dist/elements/a-tabs.js +157 -0
- package/dist/elements/a-text.css +1 -1
- package/dist/elements/a-title.css +1 -1
- package/dist/elements/a-tooltip.d.ts +18 -0
- package/dist/elements/a-tooltip.js +45 -0
- package/dist/elements/index.d.ts +3 -0
- package/dist/elements/index.js +7 -0
- package/dist/general_types.d.ts +146 -20
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/jsx-runtime.d.ts +5 -1
- package/dist/tokens.css +1 -1
- package/package.json +1 -1
package/dist/anta_helpers.d.ts
CHANGED
|
@@ -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
|
package/dist/anta_helpers.js
CHANGED
|
@@ -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
|
-
|
|
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 `
|
|
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
|
-
* `
|
|
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
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* role tokens; a custom colour keeps its hue + chroma and pins
|
|
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 `
|
|
81
|
-
|
|
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,
|
|
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
|
-
|
|
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(
|
|
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 ||
|
|
44
|
+
const onchange = onChange || onValueChange ? (e) => {
|
|
41
45
|
onChange?.(e);
|
|
42
|
-
|
|
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 `
|
|
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 `
|
|
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
|
-
|
|
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,
|
|
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;
|
package/dist/components/Input.js
CHANGED
|
@@ -62,7 +62,7 @@ const Input = ({
|
|
|
62
62
|
step,
|
|
63
63
|
onInput,
|
|
64
64
|
onChange,
|
|
65
|
-
|
|
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 ||
|
|
103
|
+
oninput: onInput || onValueChange ? (e) => {
|
|
104
104
|
onInput?.(e);
|
|
105
|
-
|
|
105
|
+
onValueChange?.(e, attrsOf(e));
|
|
106
106
|
} : void 0,
|
|
107
|
-
onchange: onChange ||
|
|
107
|
+
onchange: onChange || onValueChange ? (e) => {
|
|
108
108
|
onChange?.(e);
|
|
109
|
-
|
|
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 `
|
|
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
|
-
|
|
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
|
-
/**
|
|
82
|
-
* CSS color for a one-off custom tone.
|
|
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,
|
|
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
|
-
|
|
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 ||
|
|
50
|
+
const onchange = onChange || onValueChange ? (e) => {
|
|
51
51
|
onChange?.(e);
|
|
52
|
-
|
|
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,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,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 {};
|