@antadesign/anta 0.3.27 → 0.3.29

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 (162) hide show
  1. package/NOTICES.md +32 -1
  2. package/dist/anta_helpers.d.ts +25 -0
  3. package/dist/anta_helpers.js +28 -0
  4. package/dist/box-observation.d.ts +8 -0
  5. package/dist/box-observation.js +41 -0
  6. package/dist/box-types.d.ts +2 -0
  7. package/dist/bundle.css +1 -1
  8. package/dist/bundle.js +77 -46
  9. package/dist/components/Banner.js +2 -2
  10. package/dist/components/Box.d.ts +28 -12
  11. package/dist/components/Box.js +18 -11
  12. package/dist/components/Breadcrumbs.css +1 -1
  13. package/dist/components/Button.js +2 -2
  14. package/dist/components/Calendar.js +3 -5
  15. package/dist/components/Card.js +2 -2
  16. package/dist/components/Checkbox.d.ts +12 -13
  17. package/dist/components/Checkbox.js +5 -13
  18. package/dist/components/Expander.js +2 -2
  19. package/dist/components/Input.d.ts +8 -2
  20. package/dist/components/Input.js +6 -2
  21. package/dist/components/InputAutocomplete.js +3 -12
  22. package/dist/components/InputDate.css +1 -1
  23. package/dist/components/InputDate.js +2 -0
  24. package/dist/components/InputTime.js +2 -2
  25. package/dist/components/Loader.js +2 -1
  26. package/dist/components/Menu.d.ts +4 -4
  27. package/dist/components/Menu.js +1 -1
  28. package/dist/components/MenuItem.d.ts +7 -8
  29. package/dist/components/MenuItem.js +4 -4
  30. package/dist/components/Panel.d.ts +17 -0
  31. package/dist/components/Panel.js +22 -0
  32. package/dist/components/Progress.js +2 -2
  33. package/dist/components/RadioGroup.d.ts +14 -14
  34. package/dist/components/RadioGroup.js +7 -23
  35. package/dist/components/Select.d.ts +26 -21
  36. package/dist/components/Select.js +51 -38
  37. package/dist/components/SelectFaceted.d.ts +24 -11
  38. package/dist/components/SelectFaceted.js +65 -44
  39. package/dist/components/Slider.js +3 -3
  40. package/dist/components/Steps.css +1 -1
  41. package/dist/components/Switch.d.ts +10 -11
  42. package/dist/components/Switch.js +3 -11
  43. package/dist/components/TabPanel.d.ts +3 -8
  44. package/dist/components/TabPanel.js +2 -1
  45. package/dist/components/Tabs.d.ts +2 -2
  46. package/dist/components/Tabs.js +4 -3
  47. package/dist/components/Tag.d.ts +7 -9
  48. package/dist/components/Tag.js +2 -2
  49. package/dist/components/Text.js +2 -2
  50. package/dist/components/Title.js +2 -2
  51. package/dist/components/Tooltip.d.ts +1 -1
  52. package/dist/components/Tooltip.js +1 -1
  53. package/dist/components/select-parts.css +1 -1
  54. package/dist/elements/a-avatar.css +1 -1
  55. package/dist/elements/a-banner.css +1 -1
  56. package/dist/elements/a-box.css +1 -1
  57. package/dist/elements/a-box.d.ts +6 -6
  58. package/dist/elements/a-box.js +74 -23
  59. package/dist/elements/a-button.css +1 -1
  60. package/dist/elements/a-button.d.ts +16 -10
  61. package/dist/elements/a-button.js +64 -1
  62. package/dist/elements/a-calendar.css +1 -1
  63. package/dist/elements/a-capture.css +1 -1
  64. package/dist/elements/a-card.css +1 -1
  65. package/dist/elements/a-checkbox.css +1 -1
  66. package/dist/elements/a-checkbox.d.ts +3 -0
  67. package/dist/elements/a-checkbox.js +17 -1
  68. package/dist/elements/a-copy.css +1 -1
  69. package/dist/elements/a-dialog.css +1 -1
  70. package/dist/elements/a-expander.css +1 -1
  71. package/dist/elements/a-expander.js +1 -0
  72. package/dist/elements/a-icon.css +1 -1
  73. package/dist/elements/a-icon.shapes.css +1 -1
  74. package/dist/elements/a-input-time.css +1 -1
  75. package/dist/elements/a-input-time.d.ts +8 -0
  76. package/dist/elements/a-input-time.js +120 -15
  77. package/dist/elements/a-input.css +1 -1
  78. package/dist/elements/a-input.d.ts +27 -1
  79. package/dist/elements/a-input.js +180 -41
  80. package/dist/elements/a-loader.css +1 -1
  81. package/dist/elements/a-menu-group.css +1 -1
  82. package/dist/elements/a-menu-item.css +1 -1
  83. package/dist/elements/a-menu-item.js +1 -0
  84. package/dist/elements/a-menu-separator.css +1 -1
  85. package/dist/elements/a-menu.css +1 -1
  86. package/dist/elements/a-menu.d.ts +8 -13
  87. package/dist/elements/a-menu.js +146 -45
  88. package/dist/elements/a-panel.css +1 -0
  89. package/dist/elements/a-panel.d.ts +16 -0
  90. package/dist/elements/a-panel.js +153 -0
  91. package/dist/elements/a-progress.css +1 -1
  92. package/dist/elements/a-radio-group.css +1 -1
  93. package/dist/elements/a-radio.css +1 -1
  94. package/dist/elements/a-radio.d.ts +4 -0
  95. package/dist/elements/a-radio.js +18 -0
  96. package/dist/elements/a-slider.css +1 -1
  97. package/dist/elements/a-slider.d.ts +1 -0
  98. package/dist/elements/a-slider.js +3 -6
  99. package/dist/elements/a-switch.css +1 -1
  100. package/dist/elements/a-switch.d.ts +3 -0
  101. package/dist/elements/a-switch.js +17 -1
  102. package/dist/elements/a-tab.css +1 -1
  103. package/dist/elements/a-tabpanel.css +1 -1
  104. package/dist/elements/a-tabs.css +1 -1
  105. package/dist/elements/a-tag.css +1 -1
  106. package/dist/elements/a-text.css +1 -1
  107. package/dist/elements/a-text.js +1 -0
  108. package/dist/elements/a-title.css +1 -1
  109. package/dist/elements/a-toast.css +1 -1
  110. package/dist/elements/a-toaster.css +1 -1
  111. package/dist/elements/a-tooltip.css +1 -1
  112. package/dist/elements/a-tooltip.d.ts +3 -4
  113. package/dist/elements/a-tooltip.js +30 -8
  114. package/dist/elements/focus.d.ts +9 -0
  115. package/dist/elements/focus.js +41 -0
  116. package/dist/elements/index.d.ts +1 -0
  117. package/dist/elements/index.js +3 -0
  118. package/dist/elements/panel-focus.d.ts +10 -0
  119. package/dist/elements/panel-focus.js +86 -0
  120. package/dist/elements/shadow-aria.d.ts +10 -0
  121. package/dist/elements/shadow-aria.js +155 -0
  122. package/dist/general_types.d.ts +70 -42
  123. package/dist/generate-icons.mjs +3 -0
  124. package/dist/index.d.ts +5 -2
  125. package/dist/index.js +2 -0
  126. package/dist/jsx-runtime.d.ts +10 -1
  127. package/dist/reset.css +1 -1
  128. package/dist/theme-antithesis.css +1 -0
  129. package/dist/theme-antune.css +1 -0
  130. package/dist/tokens.css +1 -1
  131. package/docs/accessibility.md +4 -2
  132. package/docs/changelog.md +135 -0
  133. package/docs/colors.md +7 -7
  134. package/docs/comparison.md +2 -2
  135. package/docs/components/box.md +98 -34
  136. package/docs/components/breadcrumbs.md +75 -6
  137. package/docs/components/button.md +2 -2
  138. package/docs/components/capture.md +8 -8
  139. package/docs/components/checkbox.md +21 -16
  140. package/docs/components/input-autocomplete.md +6 -0
  141. package/docs/components/input-date.md +8 -2
  142. package/docs/components/input.md +99 -40
  143. package/docs/components/menu.md +5 -6
  144. package/docs/components/panel.md +189 -0
  145. package/docs/components/radio.md +16 -13
  146. package/docs/components/select-faceted.md +58 -2
  147. package/docs/components/select.md +72 -59
  148. package/docs/components/steps.md +4 -4
  149. package/docs/components/switch.md +16 -10
  150. package/docs/components/tabs.md +21 -8
  151. package/docs/components/tag.md +5 -3
  152. package/docs/components/tooltip.md +6 -4
  153. package/docs/index.md +1 -0
  154. package/docs/install-config.md +23 -12
  155. package/docs/normalization.md +6 -4
  156. package/docs/theming.md +95 -17
  157. package/package.json +8 -4
  158. package/dist/components/InputDate.module.css +0 -1
  159. package/dist/components/Select.module.css +0 -1
  160. package/dist/components/SelectFaceted.module.css +0 -1
  161. package/dist/search-index.json +0 -0
  162. package/dist/theme-anta.css +0 -1
@@ -0,0 +1,22 @@
1
+ import { jsx } from "@antadesign/anta/jsx-runtime";
2
+ import { nativeStateChange } from "../anta_helpers";
3
+ const Panel = ({ maximized, defaultMaximized, onStateChange, className, children, ...rest }) => /* @__PURE__ */ jsx(
4
+ "a-panel",
5
+ {
6
+ state: maximized === void 0 ? void 0 : maximized ? "maximized" : "normal",
7
+ "default-state": maximized === void 0 && defaultMaximized ? "maximized" : void 0,
8
+ onstatechange: onStateChange ? (event) => {
9
+ const { event: native, detail, isOwn } = nativeStateChange(event);
10
+ if (isOwn && detail) onStateChange(native, {
11
+ next: detail.next === "maximized",
12
+ prev: detail.prev === "maximized"
13
+ });
14
+ } : void 0,
15
+ class: className,
16
+ ...rest,
17
+ children
18
+ }
19
+ );
20
+ export {
21
+ Panel
22
+ };
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
- import { hasChildren, toneStyle, roundStyle, roundAttr } from "../anta_helpers";
2
+ import { hasChildren, neutralToneAttr, toneStyle, roundStyle, roundAttr } from "../anta_helpers";
3
3
  const Progress = ({ value, max = 100, tone, size, round, label, hint, className, style, children, ...rest }) => {
4
4
  const indeterminate = value == null || value === false;
5
5
  const numericValue = typeof value === "number" ? value : 0;
@@ -11,7 +11,7 @@ const Progress = ({ value, max = 100, tone, size, round, label, hint, className,
11
11
  {
12
12
  value: indeterminate ? false : numericValue,
13
13
  max,
14
- tone: tone && tone !== "neutral" ? tone : void 0,
14
+ tone: neutralToneAttr(tone),
15
15
  size: size && size !== "medium" ? size : void 0,
16
16
  round: roundAttr(round),
17
17
  role: "progressbar",
@@ -1,4 +1,4 @@
1
- import type { BaseProps, OptionPresentationProps } from "../general_types";
1
+ import type { BaseProps, OptionPresentationProps, ToneScope } from "../general_types";
2
2
  /** The element's `statechange` payload. `next`/`prev` are values (`null` = nothing
3
3
  * selected); `reason` distinguishes a user pick from a form reset / bfcache restore. */
4
4
  type StateReason = "user" | "reset" | "restore";
@@ -21,14 +21,15 @@ export interface RadioOption extends OptionPresentationProps {
21
21
  value: string;
22
22
  /** The visible label. */
23
23
  label?: React.ReactNode;
24
- /** Secondary text under the label — explanatory copy, like `Input`'s hint. */
24
+ /** Secondary text under the label and exposed as this radio option's
25
+ * accessible description. */
25
26
  hint?: React.ReactNode;
26
27
  /** Disable just this option (skipped by keyboard, dropped from the tab order). */
27
28
  disabled?: boolean;
28
29
  /** Override this one option's mark tone (defaults to the group's `tone`). */
29
30
  tone?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
30
- /** Override this one option's `toneSelected` (defaults to the group's). */
31
- toneSelected?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
31
+ /** Override this option's tone scope. The group scope is inherited when omitted. */
32
+ toneScope?: ToneScope;
32
33
  /** Override this one option's size (defaults to the group's `size`). */
33
34
  size?: "small" | "medium" | "large";
34
35
  }
@@ -78,18 +79,17 @@ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"
78
79
  * @defaultValue 'neutral' */
79
80
  status?: "neutral" | "brand" | "info" | "success" | "warning" | "critical";
80
81
  /** Mark tone applied to every option (an option's own `tone` wins), or any literal
81
- * CSS color for a one-off custom tone. Colors the selected-ring fill + dot *and*
82
- * the unselected ring border. Named tones track light/dark mode. Use `toneSelected`
83
- * instead to tone only the selected option and leave the rest neutral. The option
82
+ * CSS color for a one-off custom tone. In the default `all` scope it colors the
83
+ * selected-ring fill + dot and the unselected ring border. Named tones track
84
+ * light/dark mode. Set `toneScope="selected"` to tone only the selected option
85
+ * and leave the rest neutral. The option
84
86
  * text stays neutral — recolor it in plain CSS via the `--text-N-{tone}` tokens.
85
87
  * @defaultValue 'neutral' */
86
88
  tone?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
87
- /** Like `tone`, but colored onto the **selected option only** — every unselected
88
- * ring stays neutral grey. Applied to every option (an option's own `toneSelected`
89
- * wins). Prefer this over `tone` when a resting tinted border would read as a
90
- * validation state.
91
- * @defaultValue 'neutral' */
92
- toneSelected?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
89
+ /** Apply `tone` to every state, or only to the selected option so unselected
90
+ * rings stay neutral. An option's own `toneScope` wins.
91
+ * @defaultValue 'all' */
92
+ toneScope?: ToneScope;
93
93
  /** Size applied to every option (an option's own `size` wins).
94
94
  * @defaultValue 'medium' */
95
95
  size?: "small" | "medium" | "large";
@@ -116,5 +116,5 @@ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"
116
116
  *
117
117
  * Requires `@antadesign/anta/elements` (client-side only).
118
118
  */
119
- export declare const RadioGroup: ({ options, value, defaultValue, onStateChange, onChange, onValueChange, onFocus, onBlur, name, label, hint, status, tone, toneSelected, size, disabled, orientation, className, style, ...rest }: RadioGroupProps) => any;
119
+ export declare const RadioGroup: ({ options, value, defaultValue, onStateChange, onChange, onValueChange, onFocus, onBlur, name, label, hint, status, tone, toneScope, size, disabled, orientation, className, style, ...rest }: RadioGroupProps) => any;
120
120
  export {};
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
2
  import { useId, useState } from "../jsx-runtime";
3
- import { nativeStateChange, optionPresentationAttrs, toneStyle } from "../anta_helpers";
3
+ import { nativeStateChange, neutralToneAttr, optionPresentationAttrs, toneStyle } from "../anta_helpers";
4
4
  const radioAttrsOf = (el) => ({
5
5
  value: el?.value ?? null,
6
6
  name: el?.getAttribute?.("name") ?? void 0
@@ -19,7 +19,7 @@ const RadioGroup = ({
19
19
  hint,
20
20
  status,
21
21
  tone,
22
- toneSelected,
22
+ toneScope,
23
23
  size,
24
24
  disabled,
25
25
  orientation,
@@ -63,8 +63,8 @@ const RadioGroup = ({
63
63
  "default-state": !controlled ? defaultValue : void 0,
64
64
  name,
65
65
  status: status && status !== "neutral" ? status : void 0,
66
- tone: tone && tone !== "neutral" ? tone : void 0,
67
- "tone-selected": toneSelected || void 0,
66
+ tone: neutralToneAttr(tone),
67
+ "tone-scope": toneScope && toneScope !== "all" ? toneScope : void 0,
68
68
  size: size && size !== "medium" ? size : void 0,
69
69
  disabled: disabled ? "" : void 0,
70
70
  orientation: orientation && orientation !== "vertical" ? orientation : void 0,
@@ -73,15 +73,7 @@ const RadioGroup = ({
73
73
  onfocusin: onFocus,
74
74
  onfocusout: onBlur,
75
75
  class: className,
76
- style: toneStyle(
77
- toneSelected,
78
- "--radio-tone-source",
79
- toneStyle(
80
- tone,
81
- "--radio-off-tone-source",
82
- toneSelected == null ? toneStyle(tone, "--radio-tone-source", style) : style
83
- )
84
- ),
76
+ style: toneStyle(tone, "--radio-tone-source", toneStyle(tone, "--radio-off-tone-source", style)),
85
77
  children: [
86
78
  label && /* @__PURE__ */ jsx("a-radio-group-label", { id: labelId, children: label }),
87
79
  hint && /* @__PURE__ */ jsx("a-radio-group-hint", { id: hintId, children: hint }),
@@ -97,19 +89,11 @@ const RadioGroup = ({
97
89
  "aria-disabled": optDisabled ? "true" : void 0,
98
90
  tabIndex: o.value === tabStopValue ? 0 : -1,
99
91
  tone: o.tone || void 0,
100
- "tone-selected": o.toneSelected || void 0,
92
+ "tone-scope": o.toneScope ?? (o.tone ? toneScope : void 0),
101
93
  size: o.size && o.size !== "medium" ? o.size : void 0,
102
94
  disabled: o.disabled ? "" : void 0,
103
95
  class: optionClassName,
104
- style: toneStyle(
105
- o.toneSelected,
106
- "--radio-tone-source",
107
- toneStyle(
108
- o.tone,
109
- "--radio-off-tone-source",
110
- o.toneSelected == null ? toneStyle(o.tone, "--radio-tone-source", optionStyle) : optionStyle
111
- )
112
- ),
96
+ style: toneStyle(o.tone, "--radio-tone-source", toneStyle(o.tone, "--radio-off-tone-source", optionStyle)),
113
97
  children: [
114
98
  /* @__PURE__ */ jsx("a-radio-label", { children: o.label }),
115
99
  o.hint != null && /* @__PURE__ */ jsx("a-radio-hint", { children: o.hint })
@@ -1,4 +1,4 @@
1
- import type { BaseProps, OptionPresentationProps } from '../general_types';
1
+ import type { BaseProps, OptionPresentationProps, ToneScope } from '../general_types';
2
2
  import type { IconShape } from '../elements/a-icon.shapes';
3
3
  import { type MenuProps } from './Menu';
4
4
  import './select-parts.css';
@@ -30,6 +30,9 @@ export interface SelectOption<V extends OptionValue = string> extends OptionPres
30
30
  /** Tone for this option's row (label, icon, hint, selected tint, and the
31
31
  * checkbox/radio indicator). A named tone or a custom CSS color. */
32
32
  tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
33
+ /** Override where this option applies its tone. The Select scope is inherited
34
+ * when omitted. */
35
+ toneScope?: ToneScope;
33
36
  /** Tooltip for this option's row — a string or any node. In a `multiple`
34
37
  * select with `selectAll`, a row with no `tooltip` falls back to a default
35
38
  * hint for the Alt/Option-click "select only this" accelerator; set `tooltip`
@@ -160,37 +163,39 @@ export interface SelectCommonProps<V extends OptionValue = string> extends Omit<
160
163
  indicator?: 'none' | 'check' | 'radio';
161
164
  /** Text shown when nothing is selected. */
162
165
  placeholder?: string;
163
- /** Leading icon shown at the left of the field (the default trigger's `Input`
164
- * `leading` slot). With a custom `renderTrigger`, it's passed through as
166
+ /** Leading icon shown at the left of the field. With a custom
167
+ * `renderTrigger`, it's passed through as
165
168
  * `state.icon` instead — the consumer places it. */
166
169
  icon?: IconShape;
167
- /** Content for the default trigger's `leading` slot, such as a key prefix
170
+ /** Content before the default trigger's value, such as a key prefix
168
171
  * before the value. It replaces the icon derived from `icon`. Include an
169
172
  * `<Icon>` in this content when both are needed. Ignored by `renderTrigger`. */
170
173
  leading?: React.ReactNode;
171
- /** Field label, above the trigger (Input's `label`). */
174
+ /** Field label, above the trigger. */
172
175
  label?: string;
173
- /** Helper text under the field (Input's `hint`). */
176
+ /** Helper text under the field. */
174
177
  hint?: string;
175
178
  /** Field size.
176
179
  * @defaultValue medium */
177
180
  size?: 'small' | 'medium' | 'large';
178
- /** Validation/feedback tone for the field (Input's `status`).
181
+ /** Validation/feedback tone for the field.
179
182
  * @defaultValue neutral */
180
183
  status?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical';
181
- /** Glyph shown before the `hint` when `status` is set (Input's `statusIcon`).
184
+ /** Glyph shown before the `hint` when `status` is set.
182
185
  * Each status has a default; pass a shape to override, or `false` to drop it. */
183
186
  statusIcon?: IconShape | (string & {}) | false;
184
187
  /** Round the field corners — `true` for fully round, or a number / CSS length. */
185
188
  round?: boolean | number | string;
186
189
  /** Disable the whole select. */
187
190
  disabled?: boolean;
188
- /** Tone applied to the **selected** row(s) — the whole row takes this tone
189
- * (label, icon, indicator, and the background tint), like passing `tone` to just
190
- * the chosen option. A named tone or a custom CSS color. Most visible with the
191
- * tint-based marks (`indicator` `'none'` / `'check'`); with `'radio'` /
192
- * `'checkbox'` it tones the label + indicator (those modes have no row tint). */
193
- toneSelected?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
191
+ /** Default option-row tone. An option's own `tone` wins. A named tone or a
192
+ * custom CSS color. Most visible with tint-based marks (`indicator` `'none'` /
193
+ * `'check'`); with `'radio'` / `'checkbox'` it also tones the indicator. */
194
+ tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
195
+ /** Apply the default row tone in every state, or only to selected rows. An
196
+ * option's own `toneScope` wins.
197
+ * @defaultValue 'all' */
198
+ toneScope?: ToneScope;
194
199
  /** Add a search field at the top of the menu that filters the options as you
195
200
  * type. `true` uses the built-in matcher — a case-insensitive substring of the
196
201
  * option's **value / label / hint**. Pass a **function** `(option, query) =>
@@ -229,7 +234,7 @@ export interface SelectCommonProps<V extends OptionValue = string> extends Omit<
229
234
  * A, B, C` (labels comma-joined) in place of the bare `3 selected`. Applies
230
235
  * to the multi-count case only: `All` stays `All`, a single pick stays its
231
236
  * own label, and an empty selection stays the `placeholder`. The list flows
232
- * into the read-only field, so it ellipsizes at the field's width when long
237
+ * into the Button label, so it ellipsizes at the field's width when long
233
238
  * (`3 selected: Engineering, Des… `). `renderSummary` overrides this. */
234
239
  verbose?: boolean;
235
240
  /** `multiple` only: build the trigger's selection summary text yourself,
@@ -237,7 +242,7 @@ export interface SelectCommonProps<V extends OptionValue = string> extends Omit<
237
242
  * the resolved selected options (`selected.length` is the count) and runs only
238
243
  * while something is selected — an empty selection still shows the
239
244
  * `placeholder`. Return a **string**: it flows into the default trigger's
240
- * read-only field, so a long summary ellipsizes at the field's width just
245
+ * Button label, so a long summary ellipsizes at the field's width just
241
246
  * like a long value (`Engineering, Design, … `). Return `undefined` to fall
242
247
  * back to the default for that case (e.g. customize only the count, keeping
243
248
  * the single-label case built-in). For rich content (chips, multiple nodes)
@@ -248,9 +253,9 @@ export interface SelectCommonProps<V extends OptionValue = string> extends Omit<
248
253
  * one focusable element, such as an Anta `Button`. The menu is positioned
249
254
  * relative to that element and opens when it is clicked. Do not return a
250
255
  * fragment, multiple siblings, or a non-focusable wrapper. Add
251
- * `aria-haspopup="menu"` and `aria-expanded={state.open}` to the element, on a
252
- * role that supports them (an Anta `Button` already carries `role="button"`;
253
- * otherwise add `role="combobox"`).
256
+ * `aria-haspopup={filter ? 'dialog' : 'menu'}` and
257
+ * `aria-expanded={state.open}` to the returned button. An Anta `Button`
258
+ * already carries the correct role.
254
259
  * Field props (`label`, `hint`, `size`, `status`, `placeholder`, and `round`) and
255
260
  * `className` / `style` apply only to the default field. Add styling and
256
261
  * attributes to the returned element instead. */
@@ -347,8 +352,8 @@ export type SelectedItem<V extends OptionValue = string> = SelectedOption<V> | S
347
352
  */
348
353
  export declare function optionsWithSelection<V extends OptionValue = string>(options: SelectItem<V>[], values: V | V[] | undefined): SelectedItem<V>[];
349
354
  /**
350
- * `<Select>` lets people choose one or more options from a dropdown. It uses an
351
- * `<Input>` as its read-only trigger and a `<Menu>` for its options. `selection` sets behavior:
355
+ * `<Select>` lets people choose one or more options from a dropdown. It uses a
356
+ * `<Button>` as its trigger and a `<Menu>` for its options. `selection` sets behavior:
352
357
  * `'single'` (default; `value` is a string, menu closes on pick) or `'multiple'`
353
358
  * (checkboxes, `value` is a string array, menu stays open while toggling, the
354
359
  * field shows an "N selected" count). For single-select, `indicator` picks the
@@ -1,8 +1,9 @@
1
1
  import { Fragment, jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
- import { useState, useId } from "../jsx-runtime";
3
- import { ISOLATE_HINT, optionPresentationAttrs } from "../anta_helpers";
2
+ import { useState } from "../jsx-runtime";
3
+ import { ISOLATE_HINT, ISOLATE_HINT_DELAY, optionPresentationAttrs } from "../anta_helpers";
4
4
  import { normalizeOpt, matchQueryRegex, matchesQuery, highlight } from "./select-options";
5
5
  import { Input } from "./Input";
6
+ import { Button } from "./Button";
6
7
  import { Icon } from "./Icon";
7
8
  import { Menu } from "./Menu";
8
9
  import { MenuItem } from "./MenuItem";
@@ -54,7 +55,8 @@ const Select = (props) => {
54
55
  statusIcon,
55
56
  round,
56
57
  disabled,
57
- toneSelected,
58
+ tone,
59
+ toneScope,
58
60
  filter,
59
61
  selectAll = true,
60
62
  selectAllLabel = "Select all",
@@ -80,8 +82,7 @@ const Select = (props) => {
80
82
  const currentRaw = controlled ? value : internal;
81
83
  const [open, setOpen] = useState(false);
82
84
  const [query, setQuery] = useState("");
83
- const [activeId, setActiveId] = useState(null);
84
- const uid = useId();
85
+ const popupLabel = `${label ?? rest["aria-label"] ?? "Select"} options`;
85
86
  const isSubmenu = (it) => typeof it === "object" && Array.isArray(it.submenu);
86
87
  const isGroup = (it) => typeof it === "object" && Array.isArray(it.options);
87
88
  const collectLeaves = (items, group, disabled2, out) => {
@@ -176,15 +177,14 @@ const Select = (props) => {
176
177
  MenuItem,
177
178
  {
178
179
  ...optionAttrs,
179
- id: `${uid}-opt-${o.value}`,
180
180
  selectionIndicator: menuItemIndicator,
181
181
  ...ariaSelectable,
182
182
  indicator: customMark ?? void 0,
183
183
  label: custom ? void 0 : highlight(o.label ?? String(o.value), queryRe),
184
184
  hint: custom ? void 0 : o.hint ? highlight(o.hint, queryRe) : o.hint,
185
185
  icon: custom ? void 0 : o.icon,
186
- tone: o.tone,
187
- toneSelected,
186
+ tone: o.tone ?? tone,
187
+ toneScope: o.toneScope ?? toneScope,
188
188
  selected: isSelected(o.value),
189
189
  disabled: disabled2 || void 0,
190
190
  "data-menu-open": multiple ? "" : void 0,
@@ -193,7 +193,7 @@ const Select = (props) => {
193
193
  style: optionStyle,
194
194
  children: [
195
195
  custom,
196
- tip && /* @__PURE__ */ jsx(Tooltip, { follow: true, ...hintOnly ? { delay: 700 } : {}, children: tip })
196
+ tip && /* @__PURE__ */ jsx(Tooltip, { ...hintOnly ? { delay: ISOLATE_HINT_DELAY, placement: "left" } : { follow: true }, children: tip })
197
197
  ]
198
198
  },
199
199
  String(o.value)
@@ -254,48 +254,36 @@ const Select = (props) => {
254
254
  }
255
255
  return out;
256
256
  };
257
- return /* @__PURE__ */ jsxs(Fragment, { children: [
258
- renderTrigger ? renderTrigger({ open, value: currentRaw, selected: selectedOptions, disabled: !!disabled, icon }) : /* @__PURE__ */ jsx(
259
- Input,
257
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
258
+ renderTrigger ? renderTrigger({ open, value: currentRaw, selected: selectedOptions, disabled: !!disabled, icon }) : /* @__PURE__ */ jsxs(
259
+ Button,
260
260
  {
261
- label,
262
- hint,
263
- placeholder,
264
- value: display,
265
- readOnly: true,
266
- dimActions: true,
267
261
  disabled,
268
- leading: leading ?? (icon ? /* @__PURE__ */ jsx(Icon, { shape: icon }) : void 0),
269
262
  size,
270
- status,
271
- statusIcon,
272
263
  round,
273
- role: "combobox",
274
- "aria-haspopup": "menu",
264
+ "aria-label": typeof label === "string" || typeof label === "number" ? String(label) : void 0,
265
+ "aria-invalid": status === "critical" ? "true" : void 0,
266
+ "aria-haspopup": filtering ? "dialog" : "menu",
275
267
  "aria-expanded": open ? "true" : "false",
276
- trailing: (
277
- // The named tag applies the Select-specific rotation while the icon remains
278
- // a normal currentColor glyph.
279
- /* @__PURE__ */ jsx("a-select-chevron", { open: open ? "" : void 0, style: statusColor ? { color: statusColor } : void 0, children: /* @__PURE__ */ jsx(Icon, { shape: "chevron-down" }) })
280
- ),
281
- className,
282
- style,
283
- ...rest
268
+ ...rest,
269
+ children: [
270
+ (leading ?? icon) && /* @__PURE__ */ jsx("a-select-leading", { "aria-hidden": "true", children: leading ?? /* @__PURE__ */ jsx(Icon, { shape: icon }) }),
271
+ /* @__PURE__ */ jsx("a-button-label", { "data-placeholder": !display ? "" : void 0, children: display || placeholder }),
272
+ /* @__PURE__ */ jsx("a-select-chevron", { open: open ? "" : void 0, "aria-hidden": "true", style: statusColor ? { color: statusColor } : void 0, children: /* @__PURE__ */ jsx(Icon, { shape: "chevron-down" }) })
273
+ ]
284
274
  }
285
275
  ),
286
276
  /* @__PURE__ */ jsxs(
287
277
  Menu,
288
278
  {
279
+ role: filtering ? "dialog" : void 0,
280
+ "aria-label": filtering ? popupLabel : void 0,
289
281
  placement,
290
282
  offset,
291
283
  onStateChange: (_e, { next }) => {
292
284
  setOpen(next);
293
- if (!next) {
294
- setQuery("");
295
- setActiveId(null);
296
- }
285
+ if (!next) setQuery("");
297
286
  },
298
- onactivedescendant: (e) => setActiveId((e.nativeEvent ?? e).detail?.id ?? null),
299
287
  children: [
300
288
  filtering && // `slot="header"` pins the field in the Menu's fixed header region (above
301
289
  // the scrolling options); `data-menu-search` puts the menu in combobox
@@ -309,7 +297,6 @@ const Select = (props) => {
309
297
  placeholder: "Filter\u2026",
310
298
  "aria-label": "Filter options",
311
299
  "aria-autocomplete": "list",
312
- "aria-activedescendant": open && activeId ? activeId : void 0,
313
300
  onInput: (e) => setQuery(e.currentTarget.value)
314
301
  }
315
302
  ) }),
@@ -332,12 +319,38 @@ const Select = (props) => {
332
319
  clearable && selectedValues.length > 0 && // Pinned in the footer so it never scrolls away in a long / filtered list.
333
320
  /* @__PURE__ */ jsxs(Fragment, { children: [
334
321
  /* @__PURE__ */ jsx(MenuSeparator, { slot: "footer" }),
335
- /* @__PURE__ */ jsx("a-select-footer", { slot: "footer", children: /* @__PURE__ */ jsx(MenuItem, { icon: "x", label: clearLabel, "data-menu-open": "", onSelect: clear }) })
322
+ /* @__PURE__ */ jsx("a-select-footer", { slot: "footer", children: /* @__PURE__ */ jsx(
323
+ MenuItem,
324
+ {
325
+ icon: "x",
326
+ label: clearLabel,
327
+ role: filtering ? "button" : void 0,
328
+ "data-menu-open": "",
329
+ onSelect: clear
330
+ }
331
+ ) })
336
332
  ] })
337
333
  ]
338
334
  }
339
335
  )
340
336
  ] });
337
+ if (renderTrigger) return content;
338
+ const statusGlyph = {
339
+ brand: "circle-small-solid",
340
+ info: "info",
341
+ success: "circle-check",
342
+ warning: "warning-triangle",
343
+ critical: "warning-diamond"
344
+ };
345
+ const glyph = statusIcon === void 0 ? status ? statusGlyph[status] : void 0 : statusIcon;
346
+ return /* @__PURE__ */ jsxs("a-select-field", { size, status, disabled: disabled ? "" : void 0, class: className, style, children: [
347
+ label != null && /* @__PURE__ */ jsx("a-select-label", { children: label }),
348
+ content,
349
+ hint != null && /* @__PURE__ */ jsxs("a-select-hint", { children: [
350
+ glyph && /* @__PURE__ */ jsx(Icon, { shape: glyph, "aria-hidden": "true" }),
351
+ hint
352
+ ] })
353
+ ] });
341
354
  };
342
355
  export {
343
356
  Select,
@@ -1,6 +1,6 @@
1
- import type { BaseProps } from '../general_types';
1
+ import type { BaseProps, ToneScope } from '../general_types';
2
2
  import type { IconShape } from '../elements/a-icon.shapes';
3
- import type { OptionValue, SelectItem, SelectOption } from './Select';
3
+ import type { OptionState, OptionValue, SelectItem, SelectOption } from './Select';
4
4
  import { type MenuProps } from './Menu';
5
5
  import './select-parts.css';
6
6
  interface FacetBase {
@@ -28,6 +28,11 @@ export interface SelectFacetSingle extends FacetBase {
28
28
  options: SelectItem<OptionValue>[];
29
29
  /** Add a search field atop this facet's flyout that filters its options. */
30
30
  filter?: FacetFilter;
31
+ /** Replace the option's label, hint, and icon layout in the flyout and global
32
+ * search results. Receives the option and its value, selected, and disabled
33
+ * state. The row retains selection handling and its indicator. Filtering and
34
+ * summaries still use the option data. Return null to use the default layout. */
35
+ renderOption?: (option: SelectOption<OptionValue>, state: OptionState<OptionValue>) => React.ReactNode;
31
36
  }
32
37
  /** Pick **any number** of options. Value: an array of the chosen `value`s
33
38
  * (empty array clears the facet). Options are the same `SelectItem`s as `single`,
@@ -38,6 +43,11 @@ export interface SelectFacetMultiple extends FacetBase {
38
43
  options: SelectItem<OptionValue>[];
39
44
  /** Add a search field atop this facet's flyout that filters its options. */
40
45
  filter?: FacetFilter;
46
+ /** Replace the option's label, hint, and icon layout in the flyout and global
47
+ * search results. Receives the option and its value, selected, and disabled
48
+ * state. The row retains selection handling and its indicator. Filtering and
49
+ * summaries still use the option data. Return null to use the default layout. */
50
+ renderOption?: (option: SelectOption<OptionValue>, state: OptionState<OptionValue>) => React.ReactNode;
41
51
  /** A "Select all" row that toggles every option. On by default — set `false`
42
52
  * to drop it.
43
53
  * @defaultValue true */
@@ -142,10 +152,12 @@ export interface SelectFacetedProps extends Omit<BaseProps, 'children'> {
142
152
  priority?: 'primary' | 'secondary';
143
153
  /** Disable the whole control. */
144
154
  disabled?: boolean;
145
- /** Tone applied to a selected option row in the facet flyouts (label, selected
146
- * tint, and the check / checkbox indicator). A named tone or a custom CSS
147
- * color, matching `Select`'s `toneSelected`. Defaults to a neutral selection. */
148
- toneSelected?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
155
+ /** Default option-row tone in facet flyouts. An option's own `tone` wins. */
156
+ tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
157
+ /** Apply the default row tone in every state, or only to selected rows. An
158
+ * option's own `toneScope` wins.
159
+ * @defaultValue 'all' */
160
+ toneScope?: ToneScope;
149
161
  /** Adds a search field at the top of the root menu. It searches the options of
150
162
  * every `single` and `multiple` facet in one list. For example, "alice" can
151
163
  * appear under application-defined Assignee and Owner facets. `text` and
@@ -164,11 +176,12 @@ export interface SelectFacetedProps extends Omit<BaseProps, 'children'> {
164
176
  /** Replaces the default `Button` with a trigger returned from this function.
165
177
  * Receives a `SelectFacetedTriggerState`. Return exactly one focusable element:
166
178
  * the menu is positioned relative to that element and opens when it is clicked.
167
- * Add `aria-haspopup="menu"` and `aria-expanded={state.open}` to the returned
168
- * element, on a role that supports them (an Anta `Button` already carries
169
- * `role="button"`; otherwise add `role="combobox"`). `className`, `style`, and
170
- * other trigger props apply only to the default Button, so add styling and
171
- * attributes to the returned element. */
179
+ * Add `aria-haspopup={searchable ? 'dialog' : 'menu'}` and
180
+ * `aria-expanded={state.open}` to the returned element, on a role that
181
+ * supports them (an Anta `Button` already carries `role="button"`; otherwise
182
+ * add `role="combobox"`). `className`, `style`, and other trigger props apply
183
+ * only to the default Button, so add styling and attributes to the returned
184
+ * element. */
172
185
  renderTrigger?: (state: SelectFacetedTriggerState) => React.ReactNode;
173
186
  }
174
187
  /**