@antadesign/anta 0.3.18 → 0.3.20

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 (92) hide show
  1. package/README.md +38 -242
  2. package/dist/anta_helpers.d.ts +2 -2
  3. package/dist/components/Banner.d.ts +3 -3
  4. package/dist/components/Button.d.ts +1 -1
  5. package/dist/components/Calendar.d.ts +11 -12
  6. package/dist/components/Card.d.ts +1 -1
  7. package/dist/components/Card.js +1 -1
  8. package/dist/components/Checkbox.d.ts +8 -9
  9. package/dist/components/Dialog.d.ts +1 -1
  10. package/dist/components/Expander.d.ts +5 -6
  11. package/dist/components/Input.d.ts +6 -3
  12. package/dist/components/Input.js +3 -1
  13. package/dist/components/InputAutocomplete.d.ts +8 -8
  14. package/dist/components/InputDate.css +1 -0
  15. package/dist/components/InputDate.d.ts +1 -0
  16. package/dist/components/InputDate.js +5 -5
  17. package/dist/components/InputTime.d.ts +3 -3
  18. package/dist/components/InputTime.js +1 -1
  19. package/dist/components/Menu.d.ts +7 -3
  20. package/dist/components/Menu.js +3 -2
  21. package/dist/components/MenuItem.d.ts +1 -1
  22. package/dist/components/MenuItem.js +1 -1
  23. package/dist/components/Progress.d.ts +1 -1
  24. package/dist/components/RadioGroup.d.ts +12 -13
  25. package/dist/components/Select.d.ts +32 -38
  26. package/dist/components/Select.js +9 -13
  27. package/dist/components/SelectFaceted.d.ts +28 -33
  28. package/dist/components/SelectFaceted.js +29 -23
  29. package/dist/components/Slider.d.ts +5 -5
  30. package/dist/components/Switch.d.ts +4 -4
  31. package/dist/components/Tabs.d.ts +7 -7
  32. package/dist/components/Title.d.ts +1 -1
  33. package/dist/components/Toaster.d.ts +1 -1
  34. package/dist/components/Tooltip.d.ts +1 -1
  35. package/dist/components/select-parts.css +1 -0
  36. package/dist/elements/a-card.css +1 -1
  37. package/dist/elements/a-dialog.css +1 -1
  38. package/dist/elements/a-expander.css +1 -1
  39. package/dist/elements/a-expander.d.ts +1 -0
  40. package/dist/elements/a-expander.js +12 -2
  41. package/dist/elements/a-input.css +1 -1
  42. package/dist/elements/a-menu.js +12 -0
  43. package/dist/elements/a-progress.css +1 -1
  44. package/dist/elements/a-slider.css +1 -1
  45. package/dist/elements/a-tabs.css +1 -1
  46. package/dist/elements/a-tabs.d.ts +3 -0
  47. package/dist/elements/a-tabs.js +40 -1
  48. package/dist/elements/a-tooltip.css +1 -1
  49. package/dist/elements/a-tooltip.d.ts +1 -1
  50. package/dist/elements/a-tooltip.js +1 -1
  51. package/dist/elements/index.d.ts +1 -1
  52. package/dist/general_types.d.ts +24 -22
  53. package/dist/index.d.ts +3 -3
  54. package/dist/jsx-runtime.d.ts +9 -0
  55. package/docs/accessibility.md +34 -0
  56. package/docs/changelog.md +561 -0
  57. package/docs/colors.md +42 -0
  58. package/docs/comparison.md +28 -0
  59. package/docs/components/banner.md +267 -0
  60. package/docs/components/button.md +603 -0
  61. package/docs/components/card.md +321 -0
  62. package/docs/components/checkbox.md +296 -0
  63. package/docs/components/dialog.md +314 -0
  64. package/docs/components/expander.md +526 -0
  65. package/docs/components/icon.md +155 -0
  66. package/docs/components/input-autocomplete.md +100 -0
  67. package/docs/components/input-date.md +401 -0
  68. package/docs/components/input-time.md +174 -0
  69. package/docs/components/input.md +610 -0
  70. package/docs/components/loader.md +139 -0
  71. package/docs/components/menu.md +511 -0
  72. package/docs/components/progress.md +182 -0
  73. package/docs/components/radio.md +368 -0
  74. package/docs/components/select-faceted.md +451 -0
  75. package/docs/components/select.md +926 -0
  76. package/docs/components/slider.md +147 -0
  77. package/docs/components/switch.md +198 -0
  78. package/docs/components/tabs.md +471 -0
  79. package/docs/components/tag.md +185 -0
  80. package/docs/components/text.md +148 -0
  81. package/docs/components/title.md +146 -0
  82. package/docs/components/toaster.md +313 -0
  83. package/docs/components/tooltip.md +177 -0
  84. package/docs/credits.md +18 -0
  85. package/docs/index.md +52 -0
  86. package/docs/install-config.md +240 -0
  87. package/docs/normalization.md +102 -0
  88. package/docs/overview.md +10 -0
  89. package/docs/packages/stickers.md +187 -0
  90. package/docs/packages/table.md +153 -0
  91. package/docs/theming.md +13 -0
  92. package/package.json +10 -6
@@ -1,5 +1,4 @@
1
1
  import { Fragment, jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
- import cn from "clsx";
3
2
  import { useMemo, useState } from "../jsx-runtime";
4
3
  import { Temporal } from "temporal-polyfill";
5
4
  import {
@@ -18,7 +17,7 @@ import { Calendar } from "./Calendar";
18
17
  import { Button } from "./Button";
19
18
  import { Icon } from "./Icon";
20
19
  import { InputTime } from "./InputTime";
21
- import styles from "./InputDate.module.css";
20
+ import "./InputDate.css";
22
21
  const InputDate = ({
23
22
  value,
24
23
  defaultValue,
@@ -147,7 +146,8 @@ const InputDate = ({
147
146
  if (resolve(e.currentTarget.value)) setOpen(false);
148
147
  }
149
148
  },
150
- className: cn(styles.dateField, className),
149
+ truncate: true,
150
+ className,
151
151
  style,
152
152
  ...rest
153
153
  }
@@ -159,7 +159,7 @@ const InputDate = ({
159
159
  placement: placement ?? "bottom-start",
160
160
  offset,
161
161
  autoWidth: true,
162
- className: styles.calendarMenu,
162
+ inset: 8,
163
163
  onStateChange: (_e, { next }) => setOpen(next),
164
164
  children: /* @__PURE__ */ jsxs("div", { "data-menu-open": "", children: [
165
165
  /* @__PURE__ */ jsx(
@@ -180,7 +180,7 @@ const InputDate = ({
180
180
  }
181
181
  }
182
182
  ),
183
- time && /* @__PURE__ */ jsxs("div", { className: styles.timeRow, children: [
183
+ time && /* @__PURE__ */ jsxs("a-input-date-time-container", { children: [
184
184
  /* @__PURE__ */ jsx(
185
185
  InputTime,
186
186
  {
@@ -16,7 +16,7 @@ export interface InputTimeChangeAttrs {
16
16
  }
17
17
  export interface InputTimeProps extends BaseProps, DOMEventHandlers {
18
18
  /** Extra content rendered under the field, above the hint (a no-box child like
19
- * a `<Tooltip>` takes no space and just anchors to the field). */
19
+ * a `<Tooltip>` takes no space and anchors to the field). */
20
20
  children?: React.ReactNode;
21
21
  /** Field label, shown above the control and used as the segment group's
22
22
  * accessible name. */
@@ -29,7 +29,7 @@ export interface InputTimeProps extends BaseProps, DOMEventHandlers {
29
29
  /** Glyph before the `hint` when `status` is set (per-status default; pass a
30
30
  * shape to override, or `false` to drop it). */
31
31
  statusIcon?: IconShape | (string & {}) | false;
32
- /** Custom accent colour — any literal CSS colour tints the resting + hover
32
+ /** Custom accent color — any literal CSS color tints the resting + hover
33
33
  * border (focus ring stays `--focus-ring`); `status` overrides for validation. */
34
34
  tone?: string;
35
35
  /** Size variant. small=24px, medium=28px, large=32px tall.
@@ -87,7 +87,7 @@ export interface InputTimeProps extends BaseProps, DOMEventHandlers {
87
87
  * behave as one control: each is a native text input — ↑/↓ steps with wrap,
88
88
  * ←/→ crosses segments at caret boundaries, typing digits auto-advances, and
89
89
  * AM/PM accepts its locale text or `a`/`p`. Renders an `<a-input-time>` web
90
- * component that owns the segments, navigation, and form value (via
90
+ * component that manages the segments, navigation, and form value (via
91
91
  * `ElementInternals`).
92
92
  *
93
93
  * The clock and layout follow the locale (`en-US` → 12-hour, most others 24),
@@ -79,7 +79,7 @@ const InputTime = ({
79
79
  children: [
80
80
  label != null && (isStringish(label) ? /* @__PURE__ */ jsx("span", { slot: "label", children: label }) : /* @__PURE__ */ jsx("span", { slot: "label", style: { display: "contents" }, children: label })),
81
81
  icon !== false && /* @__PURE__ */ jsx("span", { slot: "leading", style: { display: "contents" }, children: /* @__PURE__ */ jsx(Icon, { shape: icon ?? "clock" }) }),
82
- clearable && // Real <a-button> in the element's `clear` slot; the element owns its
82
+ clearable && // Real <a-button> in the element's `clear` slot; the element controls its
83
83
  // visibility (shown only when filled). It fires `clearrequest`, which the
84
84
  // element turns into clear(). CONTRACT: `data-custom-event` MUST match
85
85
  // CLEAR_TRIGGER in src/elements/a-input-time.ts (string duplicated, not
@@ -28,6 +28,10 @@ export interface MenuProps extends BaseProps {
28
28
  * content menu under a wide trigger (e.g. a calendar below a full-width field)
29
29
  * so it wraps its content and left-aligns under the trigger. */
30
30
  autoWidth?: boolean;
31
+ /** Inner inset for the scroll body and named header/footer content. A number is
32
+ * pixels; a CSS length string is used as written.
33
+ * @defaultValue 4 */
34
+ inset?: number | string;
31
35
  /** Controlled open state. Omit for the default **uncontrolled** menu (it
32
36
  * opens/closes itself via its triggers). Pass a boolean to **control** it:
33
37
  * the menu's visibility follows `open`, and user dismiss (Esc, outside-click,
@@ -53,7 +57,7 @@ export interface MenuProps extends BaseProps {
53
57
  /** Combobox-mode cursor report (raw element event). Fires when the active
54
58
  * option changes as arrow keys move the cursor while focus stays in a
55
59
  * `[data-menu-search]` filter field; `detail.id` is the active option's `id`
56
- * (`null` when none). The reactive layer that owns the field reflects this
60
+ * (`null` when none). The reactive layer that renders the field reflects this
57
61
  * onto its `aria-activedescendant` — the element can't write that light-DOM
58
62
  * attribute itself. Passed straight through to the element. */
59
63
  onactivedescendant?: (e: CustomEvent<{
@@ -74,7 +78,7 @@ export interface MenuProps extends BaseProps {
74
78
  *
75
79
  * Open state is uncontrolled by default — listen for `onStateChange`
76
80
  * (`detail: { next, prev }`) to observe it, or pass `open` to control it. You
77
- * can also grab a `ref` and call `.open()` / `.close()` / `.toggle()`.
81
+ * can also keep a `ref` and call `.open()` / `.close()` / `.toggle()`.
78
82
  * Selecting a `MenuItem` closes the menu;
79
83
  * arbitrary injected content does not. Add `data-menu-open` to any item /
80
84
  * container to keep it open, or `data-menu-close` to a custom element to let it
@@ -92,4 +96,4 @@ export interface MenuProps extends BaseProps {
92
96
  * </Menu>
93
97
  * ```
94
98
  */
95
- export declare const Menu: ({ placement, context, coord, nohover, offset, autoWidth, open, onStateChange, round, role, className, style, children, ...rest }: MenuProps) => any;
99
+ export declare const Menu: ({ placement, context, coord, nohover, offset, autoWidth, inset, open, onStateChange, round, role, className, style, children, ...rest }: MenuProps) => any;
@@ -1,5 +1,5 @@
1
1
  import { jsx } from "@antadesign/anta/jsx-runtime";
2
- import { nativeStateChange, roundStyle, roundAttr } from "../anta_helpers";
2
+ import { nativeStateChange, lengthStyle, roundStyle, roundAttr } from "../anta_helpers";
3
3
  const Menu = ({
4
4
  placement,
5
5
  context,
@@ -7,6 +7,7 @@ const Menu = ({
7
7
  nohover,
8
8
  offset,
9
9
  autoWidth,
10
+ inset,
10
11
  open,
11
12
  onStateChange,
12
13
  round,
@@ -38,7 +39,7 @@ const Menu = ({
38
39
  role,
39
40
  "aria-orientation": "vertical",
40
41
  class: className,
41
- style: roundStyle(round, "--menu-round", style),
42
+ style: lengthStyle(inset, "--menu-padding", roundStyle(round, "--menu-round", style)),
42
43
  ...rest,
43
44
  children
44
45
  }
@@ -111,7 +111,7 @@ export type MenuItemActionMode = {
111
111
  * `selectionIndicator` to keep the semantics — the row stays the control and
112
112
  * carries `role` + `aria-checked`; only the drawn mark changes. Suppresses the
113
113
  * built-in checkbox / radio and the trailing `check` glyph. The node is made
114
- * passive (aria-hidden, no pointer events) so the row owns the click. */
114
+ * passive (aria-hidden, no pointer events) so the row receives the click. */
115
115
  indicator?: React.ReactNode;
116
116
  };
117
117
  export type MenuItemProps = MenuItemCommonProps & (MenuItemLinkMode | MenuItemActionMode);
@@ -81,7 +81,7 @@ const MenuItem = ({
81
81
  ...rest,
82
82
  children: [
83
83
  indicator != null ? (
84
- // `min-height: 1lh` makes the wrapper one text line tall and centres the node
84
+ // `min-height: 1lh` makes the wrapper one text line tall and centers the node
85
85
  // in it, so a small indicator aligns with the label's first line in a hinted
86
86
  // (top-aligned) row instead of riding at the top.
87
87
  /* @__PURE__ */ jsx(
@@ -6,7 +6,7 @@ export interface ProgressProps extends BaseProps {
6
6
  /** Upper bound of the range.
7
7
  * @defaultValue 100 */
8
8
  max?: number;
9
- /** Colour variant, or any literal CSS colour for a one-off custom tone (the
9
+ /** Color variant, or any literal CSS color for a one-off custom tone (the
10
10
  * surface / indicator / text are derived from it in oklch). Named tones track
11
11
  * light/dark automatically.
12
12
  * @defaultValue 'neutral' */
@@ -37,12 +37,11 @@ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"
37
37
  /** The options. The wrapper renders one `<a-radio>` per entry and computes its
38
38
  * `selected` / roving `tabindex` / `role` declaratively. */
39
39
  options: RadioOption[];
40
- /** Controlled selected value. When provided, the consumer owns selection: the
41
- * group follows this prop and a pick only *requests* a change via
42
- * `onStateChange` (reject by not updating). Leave undefined for uncontrolled. */
40
+ /** Controlled selected value. The group follows this prop and reports a
41
+ * requested change through `onStateChange`. Leave it undefined for
42
+ * uncontrolled use. */
43
43
  value?: string;
44
- /** Initial selected value for the uncontrolled case (the wrapper then owns the
45
- * selection in local state). */
44
+ /** Initial selected value for uncontrolled use. */
46
45
  defaultValue?: string;
47
46
  /** Fired whenever selection changes — event-first. `detail` is
48
47
  * `{ next, prev, reason }`: `next`/`prev` are values (`null` = nothing selected);
@@ -56,8 +55,8 @@ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"
56
55
  * counterpart to `onStateChange`). Not cancelable; for a controlled group it
57
56
  * fires once you've updated `value`. */
58
57
  onChange?: (event: Event) => void;
59
- /** Like `onChange`, but with a `{ value, name }` snapshot as the 2nd argument —
60
- * the ergonomic "just give me the new value" callback (mirrors `Input`). */
58
+ /** Like `onChange`, but with a `{ value, name }` snapshot as the second argument,
59
+ * matching `Input`. */
61
60
  onValueChange?: (event: Event, attrs: RadioChangeAttrs) => void;
62
61
  /** Fired when focus enters the group (any option) — wired to `focusin`, since
63
62
  * focus lands on an individual option, not the group element itself. */
@@ -73,19 +72,19 @@ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"
73
72
  * the options) — typically instructional copy. Per-option helper text goes on
74
73
  * the option's own `hint` instead. */
75
74
  hint?: string;
76
- /** Validation/feedback tone for the group `hint` — recolours it (same tone set
75
+ /** Validation/feedback tone for the group `hint` — recolors it (same tone set
77
76
  * as `Input`'s `status`). Use `critical` for an error message, etc.; omit for
78
77
  * the neutral default.
79
78
  * @defaultValue 'neutral' */
80
79
  status?: "neutral" | "brand" | "info" | "success" | "warning" | "critical";
81
80
  /** 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*
81
+ * CSS color for a one-off custom tone. Colors the selected-ring fill + dot *and*
83
82
  * the unselected ring border. Named tones track light/dark mode. Use `toneSelected`
84
83
  * instead to tone only the selected option and leave the rest neutral. The option
85
- * text stays neutral — recolour it in plain CSS via the `--text-N-{tone}` tokens.
84
+ * text stays neutral — recolor it in plain CSS via the `--text-N-{tone}` tokens.
86
85
  * @defaultValue 'neutral' */
87
86
  tone?: "brand" | "neutral" | "info" | "success" | "warning" | "critical" | (string & {});
88
- /** Like `tone`, but coloured onto the **selected option only** — every unselected
87
+ /** Like `tone`, but colored onto the **selected option only** — every unselected
89
88
  * ring stays neutral grey. Applied to every option (an option's own `toneSelected`
90
89
  * wins). Prefer this over `tone` when a resting tinted border would read as a
91
90
  * validation state.
@@ -104,8 +103,8 @@ export interface RadioGroupProps extends Omit<BaseProps, "children" | "onChange"
104
103
  * `<RadioGroup>` — a single-select radio control, rendered from `options`.
105
104
  *
106
105
  * This wrapper is convenience over the web components: it renders an `<a-radio>`
107
- * per option and, crucially, owns the two **declarative** DOM concerns the
108
- * elements deliberately don't touch — the roving **`tabindex`** (so keyboard Tab
106
+ * per option and manages the two **declarative** DOM concerns the elements
107
+ * deliberately do not touch: the roving **`tabindex`** (so keyboard Tab
109
108
  * lands on the right option) and each radio's **`role`**. Selection itself lives
110
109
  * in `<a-radio-group>` off-DOM (it sets each radio's `selected` property), so the
111
110
  * elements never mutate the DOM; this wrapper just reflects the current value into
@@ -1,6 +1,7 @@
1
1
  import type { BaseProps } from '../general_types';
2
2
  import type { IconShape } from '../elements/a-icon.shapes';
3
3
  import { type MenuProps } from './Menu';
4
+ import './select-parts.css';
4
5
  /** The type an option `value` may take: `string`, `number`, or `boolean`. Selection
5
6
  * compares values with `===`. Object-shaped values are out of scope; give the option a
6
7
  * stable primitive `value` and read the object back off `attrs.option` (or, in
@@ -34,7 +35,7 @@ export interface SelectOption<V extends OptionValue = string> {
34
35
  * hint for the Alt/Option-click "select only this" accelerator; set `tooltip`
35
36
  * to override that, or `''` to suppress it. */
36
37
  tooltip?: React.ReactNode;
37
- /** Your own data — attach anything and read it in `renderOption`. */
38
+ /** Additional application data. Read it in `renderOption`. */
38
39
  [key: string]: unknown;
39
40
  }
40
41
  /** A titled group of options rendered **inline** under a heading (like `MenuGroup`).
@@ -163,10 +164,9 @@ export interface SelectCommonProps<V extends OptionValue = string> extends Omit<
163
164
  * `leading` slot). With a custom `renderTrigger`, it's passed through as
164
165
  * `state.icon` instead — the consumer places it. */
165
166
  icon?: IconShape;
166
- /** Arbitrary content for the default trigger's leading slot (piped straight to
167
- * `Input`'s `leading`) — e.g. a key prefix before the value. Overrides the
168
- * `icon`-derived glyph when both are set; include your own `<Icon>` if you want
169
- * one alongside. Ignored with a custom `renderTrigger`. */
167
+ /** Content for the default trigger's `leading` slot, such as a key prefix
168
+ * before the value. It replaces the icon derived from `icon`. Include an
169
+ * `<Icon>` in this content when both are needed. Ignored by `renderTrigger`. */
170
170
  leading?: React.ReactNode;
171
171
  /** Field label, above the trigger (Input's `label`). */
172
172
  label?: string;
@@ -196,11 +196,10 @@ export interface SelectCommonProps<V extends OptionValue = string> extends Omit<
196
196
  * option's **value / label / hint**. Pass a **function** `(option, query) =>
197
197
  * boolean` for custom matching (called per option; return `true` to keep it). */
198
198
  filter?: boolean | ((option: SelectOption<V>, query: string) => boolean);
199
- /** `multiple` only: a "Select all" row at the top that toggles every enabled
200
- * option (the currently-visible ones when a `filter` query is active); its box
201
- * shows the mixed state when only some are selected. On by default in
202
- * `multiple` mode — set `false` to drop the row (and with it the Alt/⌥-click
203
- * isolate accelerator it gates).
199
+ /** `multiple` only: shows a "Select all" row that toggles every enabled option,
200
+ * or only the visible options when a filter query is active. Its checkbox is
201
+ * mixed when some options are selected. It is on by default. Set it to `false`
202
+ * to remove the row and the Alt/Option-click shortcut that selects only one row.
204
203
  * @defaultValue true */
205
204
  selectAll?: boolean;
206
205
  /** Label for the `selectAll` row.
@@ -213,13 +212,12 @@ export interface SelectCommonProps<V extends OptionValue = string> extends Omit<
213
212
  /** Label for the `clearable` footer row.
214
213
  * @defaultValue Clear */
215
214
  clearLabel?: string;
216
- /** Render the **content** of each option row yourself, replacing the built-in
217
- * `label`/`hint`/`icon` layout. Select still supplies the row box, click, ARIA,
218
- * and the selection indicator — you return only what goes *inside*. Read extra
219
- * fields off the option (see `SelectOption`'s index signature) plus an
220
- * `OptionState` (`value`/`selected`/`disabled`). Filtering still works (it
221
- * matches the option's `value`/`label`/`hint`), but match-highlighting is
222
- * skipped — your content owns its own display. */
215
+ /** Replaces the built-in `label`, `hint`, and `icon` layout for each option row.
216
+ * Select still supplies the row container, click handling, ARIA attributes, and
217
+ * selection indicator. Read extra option fields through `SelectOption`'s index
218
+ * signature. `state` contains `value`, `selected`, and `disabled`. Filtering
219
+ * still matches the option's `value`, `label`, and `hint`, but Select cannot
220
+ * highlight matches within the returned content. */
223
221
  renderOption?: (option: SelectOption<V>, state: OptionState<V>) => React.ReactNode;
224
222
  /** Replace each row's selection **mark** with your own node, drawn at the
225
223
  * leading edge. The row stays the control (`role` + `aria-checked` from
@@ -245,16 +243,15 @@ export interface SelectCommonProps<V extends OptionValue = string> extends Omit<
245
243
  * the single-label case built-in). For rich content (chips, multiple nodes)
246
244
  * use `renderTrigger`, which replaces the whole field. */
247
245
  renderSummary?: (selected: SelectOption<V>[]) => string | undefined;
248
- /** Render your own trigger in place of the default field. Receives a
249
- * `TriggerState` (`open` / `value` / `selected` / `disabled` / `icon`) to drive
250
- * its look. **Return exactly one focusable element** (an Anta `Button`, say) —
251
- * the menu anchors to it (its own previous DOM sibling) and opens it on click,
252
- * so a fragment, multiple siblings, or a non-focusable wrapper will misanchor
253
- * (the menu warns in the console if the trigger has no focusable element). Give
254
- * the element `aria-haspopup="menu"` plus `aria-expanded={state.open}`. The custom
255
- * trigger owns its own styling: the field props (`label`, `hint`, `size`, `status`,
256
- * `placeholder`, `round`) and `className` / `style` apply to the *default* trigger
257
- * only — put your own on the element you return. */
246
+ /** Replaces the default field with a trigger returned from this function.
247
+ * Receives `open`, `value`, `selected`, `disabled`, and `icon`. Return exactly
248
+ * one focusable element, such as an Anta `Button`. The menu is positioned
249
+ * relative to that element and opens when it is clicked. Do not return a
250
+ * fragment, multiple siblings, or a non-focusable wrapper. Add
251
+ * `aria-haspopup="menu"` and `aria-expanded={state.open}` to the element.
252
+ * Field props (`label`, `hint`, `size`, `status`, `placeholder`, and `round`) and
253
+ * `className` / `style` apply only to the default field. Add styling and
254
+ * attributes to the returned element instead. */
258
255
  renderTrigger?: (state: TriggerState<V>) => React.ReactNode;
259
256
  /** Render content in the menu body when the (filtered) option list is empty —
260
257
  * a "no results" message, a loading indicator (gated on your own external
@@ -275,13 +272,10 @@ export type SelectProps<V extends OptionValue = string> = SelectCommonProps<V> &
275
272
  * array value.
276
273
  * @defaultValue single */
277
274
  selection?: 'single';
278
- /** Controlled value — the `value` of the selected option. When provided, the
279
- * consumer owns selection: the field follows this prop and a pick only
280
- * *requests* a change via `onValueChange` (reject by not updating). Leave
281
- * undefined for uncontrolled. */
275
+ /** Controlled value: the selected option's `value`. Update it through
276
+ * `onValueChange`. Leave it undefined for uncontrolled use. */
282
277
  value?: V;
283
- /** Initial value (an option's `value`) for the uncontrolled case — the
284
- * wrapper then owns it. */
278
+ /** Initial selected option value for uncontrolled use. */
285
279
  defaultValue?: V;
286
280
  /** Fires after the selection changes, with the new value and a
287
281
  * `{ value, option }` snapshot. Select has no discrete element state, so
@@ -351,17 +345,17 @@ export type SelectedItem<V extends OptionValue = string> = SelectedOption<V> | S
351
345
  */
352
346
  export declare function optionsWithSelection<V extends OptionValue = string>(options: SelectItem<V>[], values: V | V[] | undefined): SelectedItem<V>[];
353
347
  /**
354
- * `<Select>` — a single- or multi-select dropdown, composed from `<Input>` (a
355
- * read-only trigger) and `<Menu>` (the options). `selection` sets behaviour:
348
+ * `<Select>` lets people choose one or more options from a dropdown. It uses an
349
+ * `<Input>` as its read-only trigger and a `<Menu>` for its options. `selection` sets behavior:
356
350
  * `'single'` (default; `value` is a string, menu closes on pick) or `'multiple'`
357
351
  * (checkboxes, `value` is a string array, menu stays open while toggling, the
358
352
  * field shows an "N selected" count). For single-select, `indicator` picks the
359
353
  * per-row mark: `'none'` (tint only, default), `'check'` (trailing checkmark), or
360
354
  * `'radio'` (leading radio).
361
355
  *
362
- * Controlled (`value` + `onValueChange`) or uncontrolled (`defaultValue`). There
363
- * is no `a-select` element — this wrapper is the coordinator; for a non-React
364
- * equivalent, hand-compose the same pieces (see the docs).
356
+ * Use `value` with `onValueChange` to control the selection, or use
357
+ * `defaultValue` for uncontrolled use. There is no `a-select` element. See the
358
+ * docs for the equivalent markup without React or Preact.
365
359
  *
366
360
  * Requires `@antadesign/anta/elements` (client-side only).
367
361
  *
@@ -9,7 +9,7 @@ import { MenuItem } from "./MenuItem";
9
9
  import { MenuGroup } from "./MenuGroup";
10
10
  import { MenuSeparator } from "./MenuSeparator";
11
11
  import { Tooltip } from "./Tooltip";
12
- import styles from "./Select.module.css";
12
+ import "./select-parts.css";
13
13
  function optionsWithSelection(options, values) {
14
14
  const set = new Set(values == null ? [] : Array.isArray(values) ? values : [values]);
15
15
  const state = (on, total) => on === 0 ? "none" : on === total ? "all" : "some";
@@ -269,16 +269,9 @@ const Select = (props) => {
269
269
  "aria-haspopup": "menu",
270
270
  "aria-expanded": open ? "true" : "false",
271
271
  trailing: (
272
- // Chevron rotates down → up when open (spacing + rotation in the CSS
273
- // module, matching the Input "Select dropdown" example).
274
- /* @__PURE__ */ jsx(
275
- Icon,
276
- {
277
- shape: "chevron-down",
278
- className: open ? `${styles.chevron} ${styles.open}` : styles.chevron,
279
- style: statusColor ? { color: statusColor } : void 0
280
- }
281
- )
272
+ // The named tag applies the Select-specific rotation while the icon remains
273
+ // a normal currentColor glyph.
274
+ /* @__PURE__ */ jsx("a-select-chevron", { open: open ? "" : void 0, style: statusColor ? { color: statusColor } : void 0, children: /* @__PURE__ */ jsx(Icon, { shape: "chevron-down" }) })
282
275
  ),
283
276
  className,
284
277
  style,
@@ -302,7 +295,7 @@ const Select = (props) => {
302
295
  filtering && // `slot="header"` pins the field in the Menu's fixed header region (above
303
296
  // the scrolling options); `data-menu-search` puts the menu in combobox
304
297
  // mode — it focuses this field on open and drives an active-option cursor.
305
- /* @__PURE__ */ jsx("div", { className: styles.filter, slot: "header", "data-menu-open": "", children: /* @__PURE__ */ jsx(
298
+ /* @__PURE__ */ jsx("a-select-header", { slot: "header", "data-menu-open": "", children: /* @__PURE__ */ jsx(
306
299
  Input,
307
300
  {
308
301
  "data-menu-search": "",
@@ -332,7 +325,10 @@ const Select = (props) => {
332
325
  ] }),
333
326
  visibleLeaves.length === 0 ? renderEmpty?.({ query: q }) : flattening ? renderFlat() : renderTree(options, false),
334
327
  clearable && selectedValues.length > 0 && // Pinned in the footer so it never scrolls away in a long / filtered list.
335
- /* @__PURE__ */ jsx("div", { slot: "footer", className: styles.footer, children: /* @__PURE__ */ jsx(MenuItem, { icon: "x", label: clearLabel, "data-menu-open": "", onSelect: clear }) })
328
+ /* @__PURE__ */ jsxs(Fragment, { children: [
329
+ /* @__PURE__ */ jsx(MenuSeparator, { slot: "footer" }),
330
+ /* @__PURE__ */ jsx("a-select-footer", { slot: "footer", children: /* @__PURE__ */ jsx(MenuItem, { icon: "x", label: clearLabel, "data-menu-open": "", onSelect: clear }) })
331
+ ] })
336
332
  ]
337
333
  }
338
334
  )
@@ -2,10 +2,10 @@ import type { BaseProps } from '../general_types';
2
2
  import type { IconShape } from '../elements/a-icon.shapes';
3
3
  import type { OptionValue, SelectItem, SelectOption } from './Select';
4
4
  import { type MenuProps } from './Menu';
5
+ import './select-parts.css';
5
6
  interface FacetBase {
6
- /** The facet's namespace — the key its value is stored under in the value
7
- * record, and what `onValueChange`'s `attrs.facet` reports. Unique across
8
- * `facets`. */
7
+ /** The key for this facet's value in the record. `onValueChange` reports it as
8
+ * `attrs.facet`. It must be unique across `facets`. */
9
9
  key: string;
10
10
  /** The facet's row label in the menu. */
11
11
  label: string;
@@ -62,9 +62,8 @@ export interface SelectFacetCustomContext<V> {
62
62
  /** Close the whole filter menu (e.g. after applying from a custom editor). */
63
63
  close: () => void;
64
64
  }
65
- /** Bring your own editor and value type — the escape hatch for anything the
66
- * built-in kinds don't cover, including object-shaped values (a date range, a
67
- * numeric comparator, …). */
65
+ /** A custom editor and value type for values the built-in kinds do not cover,
66
+ * including objects such as date ranges and numeric comparisons. */
68
67
  export interface SelectFacetCustom<V = unknown> extends FacetBase {
69
68
  kind: 'custom';
70
69
  /** Render the facet's editor inside its flyout. The returned node stays
@@ -74,11 +73,11 @@ export interface SelectFacetCustom<V = unknown> extends FacetBase {
74
73
  * string or any node). Called only when the value is set. */
75
74
  summary: (value: V) => React.ReactNode;
76
75
  }
77
- /** One facet (dimension) of the filter, discriminated by `kind`. */
76
+ /** One filter category, discriminated by `kind`. */
78
77
  export type SelectFacet = SelectFacetSingle | SelectFacetMultiple | SelectFacetText | SelectFacetCustom;
79
78
  /** The filter value: a facet key → that facet's value. Per kind: an option value
80
79
  * (`string` / `number` / `boolean`) for `single`, a `string` for `text`, an array for
81
- * `multiple`, or your own `V` for `custom`. Values are stored and reported unchanged.
80
+ * `multiple`, or a `V` value for `custom`. Values are stored and reported unchanged.
82
81
  * Typed loosely as `unknown` since facets in one control can hold different value
83
82
  * types; narrow per facet when you read it. A cleared facet is absent from the record. */
84
83
  export type SelectFacetedValue = Record<string, unknown>;
@@ -110,7 +109,7 @@ export interface SelectFacetedTriggerState {
110
109
  disabled: boolean;
111
110
  }
112
111
  export interface SelectFacetedProps extends Omit<BaseProps, 'children'> {
113
- /** The facets (dimensions) to filter across, each with its own editor kind. */
112
+ /** Categories to filter by. Each facet has a `kind` that determines its editor. */
114
113
  facets: SelectFacet[];
115
114
  /** Preferred placement of the root filter menu relative to its trigger. The
116
115
  * menu auto-flips vertically and clamps horizontally when needed.
@@ -119,11 +118,10 @@ export interface SelectFacetedProps extends Omit<BaseProps, 'children'> {
119
118
  /** Gap in pixels between the trigger and the filter menu.
120
119
  * @defaultValue 4 */
121
120
  offset?: number;
122
- /** Controlled value — the facet-keyed record. When provided, the consumer
123
- * owns state: a pick only *requests* a change via `onValueChange` (reject by
124
- * not updating). Leave undefined for uncontrolled. */
121
+ /** Controlled value record, keyed by facet. When provided, update it through
122
+ * `onValueChange`. Leave it undefined for uncontrolled use. */
125
123
  value?: SelectFacetedValue;
126
- /** Initial value for the uncontrolled case (the wrapper then owns it). */
124
+ /** Initial value for uncontrolled use. */
127
125
  defaultValue?: SelectFacetedValue;
128
126
  /** Fires after any facet changes. `value` is the whole new record (a facet key →
129
127
  * that facet's value; a cleared facet is absent). `attrs` says what changed:
@@ -146,14 +144,13 @@ export interface SelectFacetedProps extends Omit<BaseProps, 'children'> {
146
144
  disabled?: boolean;
147
145
  /** Tone applied to a selected option row in the facet flyouts (label, selected
148
146
  * tint, and the check / checkbox indicator). A named tone or a custom CSS
149
- * colour, matching `Select`'s `toneSelected`. Defaults to a neutral selection. */
147
+ * color, matching `Select`'s `toneSelected`. Defaults to a neutral selection. */
150
148
  toneSelected?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
151
- /** Add a single search field to the top of the root menu that flattens every
152
- * `single` / `multiple` facet's options into one list and searches across them
153
- * — typing "alice" surfaces it under both an Assignee and an Owner facet, each
154
- * selectable in place. `text` / `custom` facets are reachable when the search is
155
- * empty. Matching uses each facet's `filter` function if it has one, else the
156
- * built-in substring match. */
149
+ /** Adds a search field at the top of the root menu. It searches the options of
150
+ * every `single` and `multiple` facet in one list. For example, "alice" can
151
+ * appear under application-defined Assignee and Owner facets. `text` and
152
+ * `custom` facets remain available when the search is empty. Each facet uses
153
+ * its `filter` function when supplied, or the built-in substring match. */
157
154
  searchable?: boolean;
158
155
  /** Placeholder for the global search field.
159
156
  * @defaultValue Filter… */
@@ -164,22 +161,20 @@ export interface SelectFacetedProps extends Omit<BaseProps, 'children'> {
164
161
  /** Label for the "Clear all" row.
165
162
  * @defaultValue Clear all */
166
163
  clearAllLabel?: string;
167
- /** Render your own trigger in place of the default `Button`. Receives a
168
- * `SelectFacetedTriggerState`; **return exactly one focusable element** (the
169
- * menu anchors to it as its previous sibling and opens it on click). Give it
170
- * `aria-haspopup="menu"` plus `aria-expanded={state.open}`. The custom trigger
171
- * owns its own styling — `className` / `style` / other props apply to the
172
- * *default* trigger only, so put your own on the element you return. */
164
+ /** Replaces the default `Button` with a trigger returned from this function.
165
+ * Receives a `SelectFacetedTriggerState`. Return exactly one focusable element:
166
+ * 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. `className`, `style`, and other trigger props apply only to the
169
+ * default Button, so add styling and attributes to the returned element. */
173
170
  renderTrigger?: (state: SelectFacetedTriggerState) => React.ReactNode;
174
171
  }
175
172
  /**
176
- * `<SelectFaceted>` — a faceted filter: one trigger opens a menu of facets
177
- * (dimensions), each a submenu flyout with its own editor. Facet kinds:
178
- * `'single'` (pick one), `'multiple'` (pick many), `'text'` (free-form
179
- * substring, applied on Enter / blur), and `'custom'` (bring your own editor +
180
- * value, including object-shaped values). The value is a
181
- * `Record<facetKey, value>`, so the same option value under two facets stays
182
- * distinct.
173
+ * `<SelectFaceted>` filters a result set by categories called facets. Its
174
+ * trigger opens a facet menu, and each facet opens a control for its value.
175
+ * The available kinds are `'single'`, `'multiple'`, `'text'`, and `'custom'`.
176
+ * The value is a `Record<facetKey, value>`, so values under different facet
177
+ * keys stay distinct.
183
178
  *
184
179
  * Controlled (`value` + `onValueChange`) or uncontrolled (`defaultValue`).
185
180
  * There is no `a-select-faceted` element — this wrapper is the coordinator.