@antadesign/anta 0.3.2 → 0.3.4

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 (96) hide show
  1. package/dist/anta_helpers.d.ts +97 -0
  2. package/dist/anta_helpers.js +70 -0
  3. package/dist/calendar-core.d.ts +126 -0
  4. package/dist/calendar-core.js +289 -0
  5. package/dist/components/Button.d.ts +9 -1
  6. package/dist/components/Button.js +5 -2
  7. package/dist/components/Calendar.d.ts +85 -0
  8. package/dist/components/Calendar.js +226 -0
  9. package/dist/components/Checkbox.d.ts +16 -11
  10. package/dist/components/Checkbox.js +13 -7
  11. package/dist/components/Expander.d.ts +7 -1
  12. package/dist/components/Expander.js +4 -2
  13. package/dist/components/Input.d.ts +13 -5
  14. package/dist/components/Input.js +14 -6
  15. package/dist/components/InputDate.d.ts +89 -0
  16. package/dist/components/InputDate.js +273 -0
  17. package/dist/components/InputDate.module.css +1 -0
  18. package/dist/components/Menu.d.ts +14 -1
  19. package/dist/components/Menu.js +6 -2
  20. package/dist/components/MenuItem.d.ts +48 -7
  21. package/dist/components/MenuItem.js +72 -14
  22. package/dist/components/MenuSeparator.d.ts +13 -2
  23. package/dist/components/MenuSeparator.js +12 -2
  24. package/dist/components/Progress.d.ts +4 -1
  25. package/dist/components/Progress.js +4 -3
  26. package/dist/components/RadioGroup.d.ts +12 -10
  27. package/dist/components/RadioGroup.js +5 -5
  28. package/dist/components/Select.d.ts +319 -0
  29. package/dist/components/Select.js +341 -0
  30. package/dist/components/Select.module.css +1 -0
  31. package/dist/components/Tab.d.ts +3 -0
  32. package/dist/components/Tab.js +2 -1
  33. package/dist/components/TabPanel.d.ts +21 -13
  34. package/dist/components/TabPanel.js +13 -1
  35. package/dist/components/Tabs.d.ts +75 -40
  36. package/dist/components/Tabs.js +20 -88
  37. package/dist/components/Tag.d.ts +10 -9
  38. package/dist/components/Tag.js +2 -2
  39. package/dist/components/Text.d.ts +6 -5
  40. package/dist/components/Title.d.ts +4 -2
  41. package/dist/components/Tooltip.d.ts +4 -1
  42. package/dist/components/Tooltip.js +5 -0
  43. package/dist/elements/a-button.css +1 -1
  44. package/dist/elements/a-calendar.css +1 -0
  45. package/dist/elements/a-calendar.d.ts +76 -0
  46. package/dist/elements/a-calendar.js +190 -0
  47. package/dist/elements/a-checkbox.css +1 -1
  48. package/dist/elements/a-checkbox.d.ts +1 -2
  49. package/dist/elements/a-checkbox.js +5 -5
  50. package/dist/elements/a-expander.css +1 -1
  51. package/dist/elements/a-expander.d.ts +16 -5
  52. package/dist/elements/a-expander.js +59 -8
  53. package/dist/elements/a-icon.shapes.css +1 -1
  54. package/dist/elements/a-icon.shapes.d.ts +6 -1
  55. package/dist/elements/a-icon.shapes.js +9 -0
  56. package/dist/elements/a-input.css +1 -1
  57. package/dist/elements/a-input.d.ts +6 -0
  58. package/dist/elements/a-input.js +28 -8
  59. package/dist/elements/a-menu-group.css +1 -1
  60. package/dist/elements/a-menu-item.css +1 -1
  61. package/dist/elements/a-menu-item.d.ts +22 -10
  62. package/dist/elements/a-menu-item.js +17 -0
  63. package/dist/elements/a-menu-separator.css +1 -1
  64. package/dist/elements/a-menu.css +1 -1
  65. package/dist/elements/a-menu.d.ts +61 -20
  66. package/dist/elements/a-menu.js +337 -58
  67. package/dist/elements/a-progress.css +1 -1
  68. package/dist/elements/a-radio-group.d.ts +1 -3
  69. package/dist/elements/a-radio-group.js +13 -13
  70. package/dist/elements/a-radio.css +1 -1
  71. package/dist/elements/a-radio.d.ts +3 -11
  72. package/dist/elements/a-radio.js +3 -34
  73. package/dist/elements/a-tab.css +1 -1
  74. package/dist/elements/a-tab.d.ts +3 -11
  75. package/dist/elements/a-tab.js +3 -34
  76. package/dist/elements/a-tabpanel.css +1 -1
  77. package/dist/elements/a-tabpanel.d.ts +17 -0
  78. package/dist/elements/a-tabpanel.js +66 -0
  79. package/dist/elements/a-tabs.css +1 -1
  80. package/dist/elements/a-tabs.d.ts +1 -4
  81. package/dist/elements/a-tabs.js +14 -14
  82. package/dist/elements/a-tag.css +1 -1
  83. package/dist/elements/a-text.d.ts +14 -13
  84. package/dist/elements/a-text.js +53 -23
  85. package/dist/elements/a-tooltip.css +1 -1
  86. package/dist/elements/a-tooltip.d.ts +1 -11
  87. package/dist/elements/a-tooltip.js +20 -19
  88. package/dist/elements/index.d.ts +2 -1
  89. package/dist/elements/index.js +6 -1
  90. package/dist/general_types.d.ts +158 -42
  91. package/dist/index.d.ts +10 -4
  92. package/dist/index.js +38 -3
  93. package/dist/jsx-runtime.d.ts +16 -7
  94. package/dist/jsx-runtime.js +6 -0
  95. package/dist/reset.css +1 -1
  96. package/package.json +4 -2
@@ -0,0 +1,85 @@
1
+ import type { BaseProps } from "../general_types";
2
+ type StateReason = "user" | "reset" | "restore";
3
+ type StateDetail = {
4
+ next: string | null;
5
+ prev: string | null;
6
+ reason: StateReason;
7
+ };
8
+ type StateChangeEvent = CustomEvent<StateDetail>;
9
+ /** Snapshot passed as the 2nd argument to `onValueChange` — the new ISO date plus
10
+ * the field name (mirrors `Input` / `RadioGroup`). */
11
+ export interface CalendarChangeAttrs {
12
+ value: string | null;
13
+ name?: string;
14
+ }
15
+ /** Public props for `<Calendar>` — the single-date month grid. */
16
+ export interface CalendarProps extends Omit<BaseProps, "children" | "onChange"> {
17
+ /** Controlled selected date — ISO `YYYY-MM-DD`. When provided, the consumer owns
18
+ * selection: the grid follows this prop and a pick only *requests* a change via
19
+ * `onStateChange`. Leave undefined for uncontrolled. */
20
+ value?: string;
21
+ /** Initial selected date for the uncontrolled case (ISO `YYYY-MM-DD`). */
22
+ defaultValue?: string;
23
+ /** Earliest selectable date (ISO `YYYY-MM-DD`) — earlier days render disabled. */
24
+ min?: string;
25
+ /** Latest selectable date (ISO `YYYY-MM-DD`) — later days render disabled. */
26
+ max?: string;
27
+ /** BCP-47 locale tag driving first-day-of-week, weekday, and month names.
28
+ * @defaultValue navigator.language */
29
+ locale?: string;
30
+ /** Form field name — the selected ISO date submits under this key. */
31
+ name?: string;
32
+ /** Size of the whole calendar — scales the day cells, the chevrons, and the
33
+ * weekday / month-heading type together (uses Button's `small` / `medium` /
34
+ * `large` scale).
35
+ * @defaultValue 'medium' */
36
+ size?: "small" | "medium" | "large";
37
+ /** Disable the whole calendar (not focusable or selectable). */
38
+ disabled?: boolean;
39
+ /** Move keyboard focus onto the active day. Change this to a new value (e.g.
40
+ * increment a counter) to focus the cursor cell — `InputDate` bumps it when
41
+ * the calendar is opened from the field by keyboard (ArrowDown), so focus
42
+ * lands in the grid. The initial value never focuses; only a change does. */
43
+ focusSignal?: number;
44
+ /** Accessible name for the grid (defaults to the visible month heading). */
45
+ "aria-label"?: string;
46
+ /** Fired whenever the selection changes — event-first. `detail` is
47
+ * `{ next, prev, reason }`: `next` / `prev` are ISO date strings (`null` = none);
48
+ * `reason` is `'user'` | `'reset'` | `'restore'`. A `'user'` pick fires *before*
49
+ * applying and is **cancelable** — `event.preventDefault()` vetoes it
50
+ * (uncontrolled), or in controlled mode answer by updating `value`. `'reset'` /
51
+ * `'restore'` are not cancelable. */
52
+ onStateChange?: (event: StateChangeEvent, detail: StateDetail) => void;
53
+ /** Fired *after* the selection changes (post-apply). Not cancelable; for a
54
+ * controlled calendar it fires once you've updated `value`. */
55
+ onChange?: (event: Event) => void;
56
+ /** Like `onChange`, but with a `{ value, name }` snapshot — the ergonomic
57
+ * "just give me the new date" callback (mirrors `Input`). */
58
+ onValueChange?: (event: Event, attrs: CalendarChangeAttrs) => void;
59
+ }
60
+ /**
61
+ * `<Calendar>` — a single-date month grid you pick a day from, **composed from
62
+ * Anta components in light DOM** (nothing is hidden in a shadow root): days and
63
+ * the prev/next chevrons are `<Button>`s, so they inherit the design system's
64
+ * states for free — a selected day is literally a `secondary` Button in its
65
+ * `selected` state. All date math runs on the Temporal engine
66
+ * (`@antadesign/anta` exports `buildMonth` & friends), and the value is an ISO
67
+ * `YYYY-MM-DD` string.
68
+ *
69
+ * The grid lives in a form-associated `<a-calendar>` element (which owns the
70
+ * submitted value + reset/restore); the wrapper owns view-month, selection,
71
+ * keyboard, and roving `tabindex` — the `RadioGroup` model. The month switcher
72
+ * is a sibling rendered *outside* the grid, so it can be extended (month/year
73
+ * pickers) independently.
74
+ *
75
+ * Controlled (`value` + `onStateChange`) or uncontrolled (`defaultValue`).
76
+ * Requires `@antadesign/anta/elements` (client-side only).
77
+ *
78
+ * @remarks Not SSR-safe. It reads the current date (`Temporal.Now`) and locale
79
+ * (`navigator.language`) at render, so a server render and the client render
80
+ * disagree on the highlighted "today" and on localized labels, causing a
81
+ * hydration mismatch. Render it client-side only (Astro `client:only`, or a
82
+ * dynamic import inside `useEffect`).
83
+ */
84
+ export declare const Calendar: ({ value, defaultValue, min, max, locale, name, size, disabled, focusSignal, onStateChange, onChange, onValueChange, className, style, "aria-label": ariaLabel, ...rest }: CalendarProps) => any;
85
+ export {};
@@ -0,0 +1,226 @@
1
+ import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
+ import cn from "clsx";
3
+ import { Temporal } from "temporal-polyfill";
4
+ import { useId, useMemo, useState } from "../jsx-runtime";
5
+ import { nativeStateChange } from "../anta_helpers";
6
+ import { Button } from "./Button";
7
+ import { Menu } from "./Menu";
8
+ import { MenuItem } from "./MenuItem";
9
+ import { Tooltip } from "./Tooltip";
10
+ import { buildMonth, clampDate, parseISODate } from "../calendar-core";
11
+ const Calendar = ({
12
+ value,
13
+ defaultValue,
14
+ min,
15
+ max,
16
+ locale,
17
+ name,
18
+ size,
19
+ disabled,
20
+ focusSignal,
21
+ onStateChange,
22
+ onChange,
23
+ onValueChange,
24
+ className,
25
+ style,
26
+ "aria-label": ariaLabel,
27
+ ...rest
28
+ }) => {
29
+ const controlled = value !== void 0;
30
+ const resolvedLocale = locale || (typeof navigator !== "undefined" ? navigator.language : "en-US");
31
+ const minD = parseISODate(min);
32
+ const maxD = parseISODate(max);
33
+ const today = Temporal.Now.plainDateISO();
34
+ const [internalSelected, setInternalSelected] = useState(
35
+ () => parseISODate(defaultValue)
36
+ );
37
+ const selected = controlled ? parseISODate(value) : internalSelected;
38
+ const [cursor, setCursor] = useState(
39
+ () => clampDate(parseISODate(value ?? defaultValue) ?? today, minD, maxD)
40
+ );
41
+ const [focusReq, setFocusReq] = useState(null);
42
+ const [jumpOpen, setJumpOpen] = useState(false);
43
+ const headingId = useId();
44
+ const month = buildMonth({ anchor: cursor, locale: resolvedLocale, min: minD, max: maxD, selected, today });
45
+ const cursorIso = cursor.toString();
46
+ const [lastFocusSignal, setLastFocusSignal] = useState(focusSignal);
47
+ if (focusSignal !== lastFocusSignal) {
48
+ setLastFocusSignal(focusSignal);
49
+ if (focusSignal !== void 0) setFocusReq({ iso: cursorIso, n: focusSignal });
50
+ }
51
+ const minYear = minD ? minD.year : today.year - 3;
52
+ const maxYear = maxD ? maxD.year : today.year + 3;
53
+ const years = [];
54
+ for (let y = minYear; y <= maxYear; y++) years.push(y);
55
+ const monthNames = useMemo(
56
+ () => Array.from(
57
+ { length: 12 },
58
+ (_, i) => Temporal.PlainDate.from({ year: 2e3, month: i + 1, day: 1 }).toLocaleString(resolvedLocale, {
59
+ month: "long"
60
+ })
61
+ ),
62
+ [resolvedLocale]
63
+ );
64
+ const monthOutOfRange = (y, m) => minD != null && (y < minD.year || y === minD.year && m < minD.month) || maxD != null && (y > maxD.year || y === maxD.year && m > maxD.month);
65
+ const moveCursorByMonth = (delta) => {
66
+ if (disabled) return;
67
+ setCursor((c) => clampDate(c.add({ months: delta }), minD, maxD));
68
+ };
69
+ const pickMonth = (y, m) => {
70
+ if (disabled) return;
71
+ setCursor((c) => clampDate(c.with({ year: y, month: m }), minD, maxD));
72
+ };
73
+ const jumpItems = useMemo(() => {
74
+ const monthItem = (y, i) => {
75
+ const m = i + 1;
76
+ return /* @__PURE__ */ jsx(
77
+ MenuItem,
78
+ {
79
+ label: monthNames[i],
80
+ selectionIndicator: "check",
81
+ selected: y === cursor.year && m === cursor.month,
82
+ disabled: monthOutOfRange(y, m) || void 0,
83
+ "data-menu-open": "",
84
+ onSelect: () => {
85
+ pickMonth(y, m);
86
+ setJumpOpen(false);
87
+ }
88
+ },
89
+ `${y}-${m}`
90
+ );
91
+ };
92
+ return years.length === 1 ? monthNames.map((_, i) => monthItem(years[0], i)) : years.map((y) => /* @__PURE__ */ jsxs(MenuItem, { submenu: true, label: String(y), selected: y === cursor.year, children: [
93
+ y === cursor.year && /* @__PURE__ */ jsx("span", { className: "year-dot", "aria-hidden": "true" }),
94
+ /* @__PURE__ */ jsx(Menu, { children: monthNames.map((_, i) => monthItem(y, i)) })
95
+ ] }, y));
96
+ }, [monthNames, cursor.year, cursor.month, minYear, maxYear, min, max, disabled]);
97
+ const onElementStateChange = (raw) => {
98
+ const { event, detail } = nativeStateChange(raw);
99
+ if (!detail) return;
100
+ onStateChange?.(event, detail);
101
+ if (detail.reason === "user" && (controlled || event.defaultPrevented)) return;
102
+ const next = parseISODate(detail.next);
103
+ if (!controlled) setInternalSelected(next);
104
+ setCursor(clampDate(next ?? cursor, minD, maxD));
105
+ };
106
+ const onElementChange = (raw) => {
107
+ const e = "nativeEvent" in raw ? raw.nativeEvent : raw;
108
+ onChange?.(e);
109
+ onValueChange?.(e, { value: e?.target?.value || null, name });
110
+ };
111
+ const onNavigate = (raw) => {
112
+ if (disabled) return;
113
+ const { detail } = nativeStateChange(raw);
114
+ const next = parseISODate(detail?.date ?? null);
115
+ if (!next) return;
116
+ const clamped = clampDate(next, minD, maxD);
117
+ setCursor(clamped);
118
+ setFocusReq((p) => ({ iso: clamped.toString(), n: (p?.n ?? 0) + 1 }));
119
+ };
120
+ const prevDisabled = disabled || minD != null && Temporal.PlainDate.compare(cursor.with({ day: 1 }).subtract({ days: 1 }), minD) < 0;
121
+ const nextDisabled = disabled || maxD != null && Temporal.PlainDate.compare(cursor.with({ day: 1 }).add({ months: 1 }), maxD) > 0;
122
+ return /* @__PURE__ */ jsxs(
123
+ "div",
124
+ {
125
+ className: cn("anta-calendar", className),
126
+ "data-size": size && size !== "medium" ? size : void 0,
127
+ "aria-disabled": disabled ? "true" : void 0,
128
+ style,
129
+ ...rest,
130
+ children: [
131
+ /* @__PURE__ */ jsxs("div", { "data-part": "header", children: [
132
+ /* @__PURE__ */ jsx(
133
+ Button,
134
+ {
135
+ priority: "tertiary",
136
+ icon: "chevron-left",
137
+ size,
138
+ "aria-label": "Previous month",
139
+ disabled: prevDisabled,
140
+ onClick: () => moveCursorByMonth(-1)
141
+ }
142
+ ),
143
+ /* @__PURE__ */ jsx(
144
+ Button,
145
+ {
146
+ id: headingId,
147
+ "data-part": "heading",
148
+ priority: "tertiary",
149
+ size,
150
+ "aria-live": "polite",
151
+ "aria-label": `${month.heading} \u2014 choose month and year`,
152
+ disabled: disabled || prevDisabled && nextDisabled,
153
+ children: month.heading
154
+ }
155
+ ),
156
+ /* @__PURE__ */ jsx(Menu, { placement: "bottom", open: jumpOpen, onStateChange: (_e, { next }) => setJumpOpen(next), children: jumpItems }),
157
+ /* @__PURE__ */ jsx(
158
+ Button,
159
+ {
160
+ priority: "tertiary",
161
+ icon: "chevron-right",
162
+ size,
163
+ "aria-label": "Next month",
164
+ disabled: nextDisabled,
165
+ onClick: () => moveCursorByMonth(1)
166
+ }
167
+ )
168
+ ] }),
169
+ /* @__PURE__ */ jsxs(
170
+ "a-calendar",
171
+ {
172
+ role: "group",
173
+ "aria-labelledby": headingId,
174
+ "aria-label": ariaLabel,
175
+ name,
176
+ value: controlled ? value : void 0,
177
+ defaultvalue: !controlled ? defaultValue : void 0,
178
+ disabled: disabled ? "" : void 0,
179
+ "data-focus": focusReq ? `${focusReq.iso}#${focusReq.n}` : void 0,
180
+ onstatechange: onElementStateChange,
181
+ onchange: onElementChange,
182
+ onnavigate: onNavigate,
183
+ children: [
184
+ month.weekdays.map((w, i) => /* @__PURE__ */ jsx(
185
+ "span",
186
+ {
187
+ "data-part": "weekday",
188
+ "data-weekend": w.weekend ? "" : void 0,
189
+ "aria-hidden": "true",
190
+ children: w.narrow
191
+ },
192
+ `wd${i}`
193
+ )),
194
+ month.weeks.flat().map((d) => {
195
+ const variant = d.today && !d.selected ? { priority: "secondary" } : { priority: "tertiary", selected: d.selected };
196
+ return /* @__PURE__ */ jsxs(
197
+ Button,
198
+ {
199
+ ...variant,
200
+ size,
201
+ disabled: disabled || d.disabled,
202
+ tabIndex: d.iso === cursorIso ? 0 : -1,
203
+ "aria-label": d.label,
204
+ "aria-current": d.today ? "date" : void 0,
205
+ "data-part": "day-cell",
206
+ "data-date": d.iso,
207
+ "data-today": d.today ? "" : void 0,
208
+ "data-outside": d.outside ? "" : void 0,
209
+ children: [
210
+ d.day,
211
+ d.today && /* @__PURE__ */ jsx(Tooltip, { children: "Today" })
212
+ ]
213
+ },
214
+ d.iso
215
+ );
216
+ })
217
+ ]
218
+ }
219
+ )
220
+ ]
221
+ }
222
+ );
223
+ };
224
+ export {
225
+ Calendar
226
+ };
@@ -42,25 +42,30 @@ export interface CheckboxProps extends BaseProps {
42
42
  defaultChecked?: CheckboxValue;
43
43
  /** Disable the checkbox (no interaction, dropped from the tab order). */
44
44
  disabled?: boolean;
45
+ /** Round the checkbox mark to a circle (`border-radius: 999px` on the box). Pass
46
+ * a `number` (px) or a CSS length string for a rounded-square mark instead. */
47
+ round?: boolean | number | string;
45
48
  /** Form field name. Inside a `<form>` the checkbox submits under this name,
46
49
  * contributing `value` when checked — like a native checkbox. */
47
50
  name?: string;
48
51
  /** Value submitted with the form when checked — like a native checkbox.
49
52
  * @defaultValue "on" */
50
53
  value?: string;
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.
54
+ /** Colour of the **mark** in every state — the checked-box fill *and* the
55
+ * unselected box border. A named tone or any literal CSS color (`'#ff1493'`,
56
+ * `'rebeccapurple'`) for a one-off custom tone. Named tones track light/dark mode
57
+ * automatically; a custom colour keeps its hue + chroma and pins lightness to the
58
+ * fill curve. Use `toneSelected` instead to tone only the checked mark and leave
59
+ * the empty box neutral. The label + hint stay neutral — recolour them in plain
60
+ * CSS via the theme-aware `--text-N-{tone}` tokens.
57
61
  * @defaultValue 'neutral' */
58
62
  tone?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
59
- /** Colour of the **text** the label and hintindependent 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.
63
+ /** Like `tone`, but coloured onto the **checked mark only**the empty box stays
64
+ * neutral grey until it's checked. Prefer this over `tone` when a resting tinted
65
+ * border would read as a validation state. Same value set as `tone`; if both are
66
+ * set, `tone` governs the off-state border and `toneSelected` the checked fill.
62
67
  * @defaultValue 'neutral' */
63
- toneText?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
68
+ toneSelected?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
64
69
  /** Size variant. small=14px, medium=16px, large=18px box.
65
70
  * @defaultValue 'medium' */
66
71
  size?: 'small' | 'medium' | 'large';
@@ -94,5 +99,5 @@ export interface CheckboxProps extends BaseProps {
94
99
  * <Checkbox defaultChecked label="Remember me" hint="On this device" />
95
100
  * ```
96
101
  */
97
- export declare const Checkbox: ({ checked, defaultChecked, disabled, tone, toneText, size, onStateChange, onChange, onValueChange, label, hint, className, style, children, tabIndex, ...rest }: CheckboxProps) => any;
102
+ export declare const Checkbox: ({ checked, defaultChecked, disabled, tone, toneSelected, size, round, onStateChange, onChange, onValueChange, label, hint, className, style, children, tabIndex, ...rest }: CheckboxProps) => any;
98
103
  export {};
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
- import { nativeStateChange, toneStyle } from "../anta_helpers";
2
+ import { nativeStateChange, toneStyle, roundStyle } from "../anta_helpers";
3
3
  const valueToState = (v) => v === "indeterminate" ? "indeterminate" : v ? "checked" : "unchecked";
4
4
  const stateToValue = (s) => s === "indeterminate" ? "indeterminate" : s === "checked";
5
5
  const checkboxAttrsOf = (el) => ({
@@ -13,8 +13,9 @@ const Checkbox = ({
13
13
  defaultChecked,
14
14
  disabled,
15
15
  tone,
16
- toneText,
16
+ toneSelected,
17
17
  size,
18
+ round,
18
19
  onStateChange,
19
20
  onChange,
20
21
  onValueChange,
@@ -26,10 +27,14 @@ const Checkbox = ({
26
27
  tabIndex,
27
28
  ...rest
28
29
  }) => {
29
- const computedStyle = toneStyle(
30
- toneText,
31
- "--checkbox-tone-text-source",
32
- toneStyle(tone, "--checkbox-tone-source", style)
30
+ const computedStyle = roundStyle(
31
+ round,
32
+ "--checkbox-round",
33
+ toneStyle(
34
+ toneSelected,
35
+ "--checkbox-tone-source",
36
+ toneStyle(tone, "--checkbox-tone-source", style)
37
+ )
33
38
  );
34
39
  const explicitAriaLabel = rest["aria-label"];
35
40
  const ariaLabel = (typeof explicitAriaLabel === "string" ? explicitAriaLabel : void 0) ?? label ?? (typeof children === "string" ? children : void 0);
@@ -59,8 +64,9 @@ const Checkbox = ({
59
64
  "default-state": defaultStateAttr,
60
65
  disabled: disabled ? "" : void 0,
61
66
  tone: tone && tone !== "neutral" ? tone : void 0,
62
- "tone-text": toneText && toneText !== "neutral" ? toneText : void 0,
67
+ "tone-selected": toneSelected && toneSelected !== "neutral" ? toneSelected : void 0,
63
68
  size: size && size !== "medium" ? size : void 0,
69
+ round: round ? "" : void 0,
64
70
  tabIndex: disabled ? -1 : tabIndex ?? 0,
65
71
  onstatechange,
66
72
  onchange,
@@ -38,6 +38,12 @@ export interface ExpanderProps extends Omit<BaseProps, "title"> {
38
38
  * expander keeps it open. `actions` stay live; disable them
39
39
  * separately if needed. */
40
40
  disabled?: boolean;
41
+ /** Round corners sized to half the folded (header) height: a pill when folded,
42
+ * and — when expanded — the same corner radius rather than a bigger stadium.
43
+ * The element measures the header, so it tracks custom header content. Pass a
44
+ * `number` (px) or CSS length string for a *fixed* radius that overrides the
45
+ * measurement (and skips it) in both states. */
46
+ round?: boolean | number | string;
41
47
  /** Controlled open state. When provided, the consumer owns open/close:
42
48
  * the expander only follows this prop, and clicking the summary just
43
49
  * requests a change via `onStateChange` (so a toggle can be rejected by
@@ -71,4 +77,4 @@ export interface ExpanderProps extends Omit<BaseProps, "title"> {
71
77
  * giving real controlled semantics (a consumer can reject a toggle). See
72
78
  * STATEFUL-COMPONENTS.md.
73
79
  */
74
- export declare const Expander: ({ title, level, tone, priority, outdent, actions, disabled, open, defaultOpen, onStateChange, className, style, children, ...rest }: ExpanderProps) => any;
80
+ export declare const Expander: ({ title, level, tone, priority, outdent, actions, disabled, round, open, defaultOpen, onStateChange, className, style, children, ...rest }: ExpanderProps) => any;
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
- import { nativeStateChange, toneStyle } from "../anta_helpers";
2
+ import { nativeStateChange, toneStyle, roundStyle } from "../anta_helpers";
3
3
  const Expander = ({
4
4
  title,
5
5
  level,
@@ -8,6 +8,7 @@ const Expander = ({
8
8
  outdent,
9
9
  actions,
10
10
  disabled,
11
+ round,
11
12
  open,
12
13
  defaultOpen,
13
14
  onStateChange,
@@ -17,7 +18,7 @@ const Expander = ({
17
18
  ...rest
18
19
  }) => {
19
20
  const controlled = open !== void 0;
20
- const computedStyle = toneStyle(tone, "--expander-tone-source", style);
21
+ const computedStyle = roundStyle(round, "--expander-round", toneStyle(tone, "--expander-tone-source", style));
21
22
  const titleNode = typeof title === "object" && title !== null ? /* @__PURE__ */ jsx("span", { slot: "title", style: { display: "contents" }, children: title }) : /* @__PURE__ */ jsx("a-expander-summary", { slot: "title", children: title });
22
23
  return /* @__PURE__ */ jsxs(
23
24
  "a-expander",
@@ -28,6 +29,7 @@ const Expander = ({
28
29
  tone: tone && tone !== "neutral" ? tone : void 0,
29
30
  priority: priority && priority !== "secondary" ? priority : void 0,
30
31
  outdent: outdent ? "" : void 0,
32
+ round: round ? "" : void 0,
31
33
  disabled: disabled ? "" : void 0,
32
34
  onstatechange: onStateChange ? (e) => {
33
35
  const { event, detail } = nativeStateChange(e);
@@ -47,7 +47,7 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
47
47
  tone?: string;
48
48
  /** Size variant. small=24px, medium=28px, large=32px tall; the type scale and
49
49
  * icon track the size (small 13/16 + 14px icon · medium 15/20 + 16px ·
50
- * large 17/24 + 18px).
50
+ * large 17/22 + 18px).
51
51
  * @defaultValue medium */
52
52
  size?: 'small' | 'medium' | 'large';
53
53
  /** Controlled value. Pair with `onChange` / `onInput`. */
@@ -74,10 +74,14 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
74
74
  /** Content pinned to the end of the field (e.g. icons, buttons), after the
75
75
  * clear button when `clearable`. */
76
76
  trailing?: React.ReactNode;
77
- /** Single-line input type. Ignored when `multiline`. (`search` is omitted
78
- * deliberately it triggers browser-injected clear/search affordances.)
77
+ /** Single-line input type. Ignored when `multiline`. `search` is a
78
+ * **wrapper-only** shorthand: it defaults a leading search icon and a clear
79
+ * button (both overridable — pass your own `leading`, or `clearable={false}`)
80
+ * and sets `inputmode="search"`, but the DOM input stays `type="text"`. The
81
+ * native `search` type never reaches the element, so the browser's own
82
+ * clear/search affordances never appear — Anta owns that chrome.
79
83
  * @defaultValue text */
80
- type?: 'text' | 'email' | 'password' | 'tel' | 'url' | 'number';
84
+ type?: 'text' | 'search' | 'email' | 'password' | 'tel' | 'url' | 'number';
81
85
  /** Native autocomplete token. Overrides the value derived from `type`
82
86
  * (`email` / `tel` / `url`) — set it for the cases `type` can't express, e.g.
83
87
  * `username`, `current-password`, `new-password`, `one-time-code`, or `off`. */
@@ -98,6 +102,10 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
98
102
  * when the field is hovered or focused (a quiet-until-engaged affordance for
99
103
  * trailing actions). */
100
104
  dimActions?: boolean;
105
+ /** Fully-round the field (`border-radius: 999px`). Pass a `number` (px) or a CSS
106
+ * length string for a custom radius. The `clearable` × button always rounds to
107
+ * a circle to match (it isn't sized by a custom field value). */
108
+ round?: boolean | number | string;
101
109
  /** Toggle native spell-checking. */
102
110
  spellCheck?: boolean;
103
111
  /** Max input length. */
@@ -156,4 +164,4 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
156
164
  * <Input label="Email" type="email" placeholder="you@example.com" clearable />
157
165
  * ```
158
166
  */
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;
167
+ export declare const Input: ({ label, hint, status, statusIcon, tone, size, round, 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;
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
- import { nativeStateChange, toneStyle } from "../anta_helpers";
2
+ import { nativeStateChange, toneStyle, roundStyle } from "../anta_helpers";
3
3
  import { Button } from "./Button";
4
4
  import { Icon } from "./Icon";
5
5
  const presence = (on) => on ? "" : void 0;
@@ -20,7 +20,8 @@ const INPUTMODE_BY_TYPE = {
20
20
  email: "email",
21
21
  tel: "tel",
22
22
  url: "url",
23
- number: "numeric"
23
+ number: "numeric",
24
+ search: "search"
24
25
  };
25
26
  const STATUS_ICON = {
26
27
  critical: "warning-diamond",
@@ -36,6 +37,7 @@ const Input = ({
36
37
  statusIcon,
37
38
  tone,
38
39
  size,
40
+ round,
39
41
  value,
40
42
  defaultValue,
41
43
  multiline,
@@ -72,10 +74,15 @@ const Input = ({
72
74
  }) => {
73
75
  const statusTone = status && status !== "neutral" ? status : void 0;
74
76
  const glyph = statusIcon === void 0 ? statusTone ? STATUS_ICON[statusTone] : void 0 : statusIcon;
77
+ const isSearch = type === "search";
78
+ const nativeType = isSearch ? void 0 : type;
79
+ const resolvedLeading = leading ?? (isSearch ? /* @__PURE__ */ jsx(Icon, { shape: "search" }) : void 0);
80
+ const resolvedClearable = isSearch ? clearable ?? true : clearable;
75
81
  return /* @__PURE__ */ jsxs(
76
82
  "a-input",
77
83
  {
78
84
  size: size && size !== "medium" ? size : void 0,
85
+ round: round ? "" : void 0,
79
86
  value,
80
87
  defaultvalue: defaultValue,
81
88
  multiline: presence(multiline || rows != null),
@@ -83,7 +90,7 @@ const Input = ({
83
90
  maxrows: maxRows != null ? String(maxRows) : void 0,
84
91
  status: statusTone,
85
92
  tone: tone || void 0,
86
- type: !multiline && rows == null ? type : void 0,
93
+ type: !multiline && rows == null ? nativeType : void 0,
87
94
  name,
88
95
  placeholder,
89
96
  disabled: presence(disabled),
@@ -111,12 +118,12 @@ const Input = ({
111
118
  onclearclick: onClearClick ? (e) => onClearClick(nativeStateChange(e).event) : void 0,
112
119
  onclearinput: onClearInput ? (e) => onClearInput(nativeStateChange(e).event) : void 0,
113
120
  class: className,
114
- style: toneStyle(tone, "--input-tone-source", style),
121
+ style: roundStyle(round, "--input-round", toneStyle(tone, "--input-tone-source", style)),
115
122
  ...rest,
116
123
  children: [
117
124
  label != null && (isStringish(label) ? /* @__PURE__ */ jsx("span", { slot: "label", children: label }) : /* @__PURE__ */ jsx("span", { slot: "label", style: { display: "contents" }, children: label })),
118
- leading != null && /* @__PURE__ */ jsx("span", { slot: "leading", style: { display: "contents" }, children: leading }),
119
- clearable && // A real <a-button> (light DOM → fully styled, keyboard-focusable) in
125
+ resolvedLeading != null && /* @__PURE__ */ jsx("span", { slot: "leading", style: { display: "contents" }, children: resolvedLeading }),
126
+ resolvedClearable && // A real <a-button> (light DOM → fully styled, keyboard-focusable) in
120
127
  // the element's `clear` slot — the element owns its visibility (shown
121
128
  // only when filled + editable). It fires the bubbling `clearrequest`
122
129
  // event via a-button's global listener, so clearing works even without
@@ -130,6 +137,7 @@ const Input = ({
130
137
  {
131
138
  priority: "tertiary",
132
139
  size,
140
+ round: !!round,
133
141
  icon: "x",
134
142
  "aria-label": "Clear",
135
143
  "data-custom-event": "clearrequest"