@antadesign/anta 0.3.0 → 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/Menu.d.ts +7 -4
- package/dist/components/Menu.js +2 -2
- package/dist/components/MenuItem.d.ts +18 -7
- package/dist/components/MenuItem.js +11 -2
- 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-icon.shapes.css +1 -1
- package/dist/elements/a-icon.shapes.d.ts +2 -1
- package/dist/elements/a-icon.shapes.js +1 -0
- package/dist/elements/a-input.js +1 -1
- package/dist/elements/a-menu.d.ts +12 -0
- package/dist/elements/a-menu.js +70 -21
- 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 +150 -23
- 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,
|
|
@@ -13,9 +13,12 @@ export interface MenuProps extends BaseProps {
|
|
|
13
13
|
* Pairs naturally with `context`; on its own it positions a left-click
|
|
14
14
|
* menu at the cursor. */
|
|
15
15
|
coord?: boolean;
|
|
16
|
-
/**
|
|
17
|
-
* hover (with intent timing)
|
|
18
|
-
|
|
16
|
+
/** Submenu-only (a `<Menu>` nested inside a `MenuItem`); ignored on a root
|
|
17
|
+
* menu. Submenus open on hover by default (with intent timing) as well as on
|
|
18
|
+
* click — set `nohover` to make this submenu click-only. Hover-intent is
|
|
19
|
+
* mouse-only regardless: on touch (and pen) a submenu always opens on tap and
|
|
20
|
+
* stays open until dismissed. */
|
|
21
|
+
nohover?: boolean;
|
|
19
22
|
/** Gap in pixels between the trigger and the menu.
|
|
20
23
|
* @defaultValue 4 */
|
|
21
24
|
offset?: number;
|
|
@@ -67,4 +70,4 @@ export interface MenuProps extends BaseProps {
|
|
|
67
70
|
* </Menu>
|
|
68
71
|
* ```
|
|
69
72
|
*/
|
|
70
|
-
export declare const Menu: ({ placement, context, coord,
|
|
73
|
+
export declare const Menu: ({ placement, context, coord, nohover, offset, open, onStateChange, className, children, ...rest }: MenuProps) => any;
|
package/dist/components/Menu.js
CHANGED
|
@@ -4,7 +4,7 @@ const Menu = ({
|
|
|
4
4
|
placement,
|
|
5
5
|
context,
|
|
6
6
|
coord,
|
|
7
|
-
|
|
7
|
+
nohover,
|
|
8
8
|
offset,
|
|
9
9
|
open,
|
|
10
10
|
onStateChange,
|
|
@@ -18,7 +18,7 @@ const Menu = ({
|
|
|
18
18
|
placement: placement && placement !== "bottom-start" ? placement : void 0,
|
|
19
19
|
context: context ? "" : void 0,
|
|
20
20
|
coord: coord ? "" : void 0,
|
|
21
|
-
|
|
21
|
+
nohover: nohover ? "" : void 0,
|
|
22
22
|
offset: offset != null ? String(offset) : void 0,
|
|
23
23
|
state: open === void 0 ? void 0 : open ? "open" : "closed",
|
|
24
24
|
onstatechange: onStateChange ? (e) => {
|
|
@@ -7,8 +7,9 @@ export interface MenuItemProps extends BaseProps {
|
|
|
7
7
|
label?: string;
|
|
8
8
|
/** A trailing keyboard-shortcut hint, e.g. `"⌘E"`. */
|
|
9
9
|
kbd?: string;
|
|
10
|
-
/** A trailing icon
|
|
11
|
-
*
|
|
10
|
+
/** A trailing icon. On a `submenu` item this **overrides** the default
|
|
11
|
+
* chevron (omit it to keep the chevron); on a normal item it's the trailing
|
|
12
|
+
* glyph (omit for none). */
|
|
12
13
|
iconTrailing?: IconShape;
|
|
13
14
|
/** Disable the item: greyed out, not focusable for activation, no close. */
|
|
14
15
|
disabled?: boolean;
|
|
@@ -20,9 +21,19 @@ export interface MenuItemProps extends BaseProps {
|
|
|
20
21
|
* `aria-haspopup="menu"`, and an `aria-expanded` baseline (kept in sync by
|
|
21
22
|
* the nested menu). Nest the flyout as a `<Menu>` child. */
|
|
22
23
|
submenu?: boolean;
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
|
|
24
|
+
/** An opaque value identifying this item, handed back in `onSelect`'s detail
|
|
25
|
+
* so a shared handler can tell which row was chosen without a per-item
|
|
26
|
+
* closure. */
|
|
27
|
+
value?: string | number;
|
|
28
|
+
/** Activation handler — fires when *this* item is chosen (click / Enter /
|
|
29
|
+
* Space), unless it's `disabled`. It does **not** fire for a submenu parent
|
|
30
|
+
* (clicking that opens the flyout, which isn't a selection) nor for a
|
|
31
|
+
* selection bubbling up from a nested submenu. Receives the event plus a
|
|
32
|
+
* `{ value, label }` detail. */
|
|
33
|
+
onSelect?: (event: any, detail: {
|
|
34
|
+
value?: string | number;
|
|
35
|
+
label?: string;
|
|
36
|
+
}) => void;
|
|
26
37
|
/** Item content. With `label` set, children are extra content — most
|
|
27
38
|
* notably the nested `<Menu>` for a submenu parent. */
|
|
28
39
|
children?: React.ReactNode;
|
|
@@ -41,10 +52,10 @@ export interface MenuItemProps extends BaseProps {
|
|
|
41
52
|
* <MenuItem icon="copy" label="Duplicate" kbd="⌘D" onSelect={dup} />
|
|
42
53
|
* <MenuItem label="Word wrap" data-menu-open onSelect={toggleWrap} />
|
|
43
54
|
* <MenuItem label="Share" submenu>
|
|
44
|
-
* <Menu
|
|
55
|
+
* <Menu>
|
|
45
56
|
* <MenuItem label="Copy link" onSelect={copyLink} />
|
|
46
57
|
* </Menu>
|
|
47
58
|
* </MenuItem>
|
|
48
59
|
* ```
|
|
49
60
|
*/
|
|
50
|
-
export declare const MenuItem: ({ icon, label, kbd, iconTrailing, disabled, tone, submenu, onSelect, className, children, ...rest }: MenuItemProps) => any;
|
|
61
|
+
export declare const MenuItem: ({ icon, label, kbd, iconTrailing, disabled, tone, submenu, value, onSelect, className, children, ...rest }: MenuItemProps) => any;
|
|
@@ -7,6 +7,7 @@ const MenuItem = ({
|
|
|
7
7
|
disabled,
|
|
8
8
|
tone,
|
|
9
9
|
submenu,
|
|
10
|
+
value,
|
|
10
11
|
onSelect,
|
|
11
12
|
className,
|
|
12
13
|
children,
|
|
@@ -23,14 +24,22 @@ const MenuItem = ({
|
|
|
23
24
|
"aria-haspopup": submenu ? "menu" : void 0,
|
|
24
25
|
"aria-expanded": submenu ? "false" : void 0,
|
|
25
26
|
"aria-disabled": disabled ? "true" : void 0,
|
|
26
|
-
onClick: disabled ? void 0 :
|
|
27
|
+
onClick: disabled || !onSelect ? void 0 : (e) => {
|
|
28
|
+
if (submenu) return;
|
|
29
|
+
const t = e.target;
|
|
30
|
+
if (t?.closest?.("a-menu-item") !== e.currentTarget) return;
|
|
31
|
+
onSelect(e, { value, label });
|
|
32
|
+
},
|
|
27
33
|
class: className,
|
|
28
34
|
...rest,
|
|
29
35
|
children: [
|
|
30
36
|
icon && /* @__PURE__ */ jsx("a-icon", { shape: icon, "aria-hidden": "true" }),
|
|
31
37
|
label != null && /* @__PURE__ */ jsx("a-menu-item-label", { children: label }),
|
|
32
38
|
kbd && /* @__PURE__ */ jsx("kbd", { children: kbd }),
|
|
33
|
-
|
|
39
|
+
/* @__PURE__ */ (() => {
|
|
40
|
+
const trailing = submenu ? iconTrailing ?? "chevron-right" : iconTrailing;
|
|
41
|
+
return trailing ? /* @__PURE__ */ jsx("a-icon", { shape: trailing, "aria-hidden": "true" }) : null;
|
|
42
|
+
})(),
|
|
34
43
|
children
|
|
35
44
|
]
|
|
36
45
|
}
|
|
@@ -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;
|