@antadesign/anta 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/anta_helpers.d.ts +101 -0
- package/dist/anta_helpers.js +77 -0
- package/dist/calendar-core.d.ts +126 -0
- package/dist/calendar-core.js +289 -0
- package/dist/components/Button.d.ts +9 -1
- package/dist/components/Button.js +5 -2
- package/dist/components/Calendar.d.ts +80 -0
- package/dist/components/Calendar.js +220 -0
- package/dist/components/Checkbox.d.ts +16 -11
- package/dist/components/Checkbox.js +13 -7
- package/dist/components/Expander.d.ts +7 -1
- package/dist/components/Expander.js +4 -2
- package/dist/components/Input.d.ts +13 -5
- package/dist/components/Input.js +14 -6
- package/dist/components/InputDate.d.ts +87 -0
- package/dist/components/InputDate.js +278 -0
- package/dist/components/InputDate.module.css +1 -0
- package/dist/components/Menu.d.ts +5 -1
- package/dist/components/Menu.js +6 -2
- package/dist/components/MenuItem.d.ts +48 -7
- package/dist/components/MenuItem.js +71 -7
- package/dist/components/MenuSeparator.d.ts +13 -2
- package/dist/components/MenuSeparator.js +12 -2
- package/dist/components/Progress.d.ts +4 -1
- package/dist/components/Progress.js +4 -3
- package/dist/components/RadioGroup.d.ts +12 -10
- package/dist/components/RadioGroup.js +5 -5
- package/dist/components/Select.d.ts +255 -0
- package/dist/components/Select.js +290 -0
- package/dist/components/Select.module.css +1 -0
- package/dist/components/Tab.d.ts +3 -0
- package/dist/components/Tab.js +2 -1
- package/dist/components/TabPanel.js +2 -1
- package/dist/components/Tabs.d.ts +18 -1
- package/dist/components/Tabs.js +8 -6
- package/dist/components/Tag.d.ts +10 -9
- package/dist/components/Tag.js +2 -2
- package/dist/components/Text.d.ts +6 -5
- package/dist/components/Title.d.ts +4 -2
- package/dist/components/Tooltip.d.ts +4 -1
- package/dist/components/Tooltip.js +5 -0
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-calendar.css +1 -0
- package/dist/elements/a-calendar.d.ts +76 -0
- package/dist/elements/a-calendar.js +190 -0
- package/dist/elements/a-checkbox.css +1 -1
- package/dist/elements/a-checkbox.d.ts +1 -2
- package/dist/elements/a-checkbox.js +5 -5
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.d.ts +16 -5
- package/dist/elements/a-expander.js +59 -8
- package/dist/elements/a-icon.shapes.css +1 -1
- package/dist/elements/a-icon.shapes.d.ts +6 -1
- package/dist/elements/a-icon.shapes.js +9 -0
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-input.d.ts +6 -0
- package/dist/elements/a-input.js +27 -8
- package/dist/elements/a-menu-group.css +1 -1
- package/dist/elements/a-menu-item.css +1 -1
- package/dist/elements/a-menu-item.d.ts +14 -4
- package/dist/elements/a-menu-item.js +17 -0
- package/dist/elements/a-menu-separator.css +1 -1
- package/dist/elements/a-menu.css +1 -1
- package/dist/elements/a-menu.d.ts +51 -8
- package/dist/elements/a-menu.js +285 -42
- package/dist/elements/a-progress.css +1 -1
- package/dist/elements/a-radio-group.d.ts +1 -3
- package/dist/elements/a-radio-group.js +13 -13
- package/dist/elements/a-radio.css +1 -1
- package/dist/elements/a-radio.d.ts +3 -11
- package/dist/elements/a-radio.js +3 -34
- package/dist/elements/a-tab.css +1 -1
- package/dist/elements/a-tab.d.ts +3 -11
- package/dist/elements/a-tab.js +3 -34
- package/dist/elements/a-tabs.css +1 -1
- package/dist/elements/a-tabs.d.ts +1 -4
- package/dist/elements/a-tabs.js +14 -14
- package/dist/elements/a-tag.css +1 -1
- package/dist/elements/a-text.d.ts +14 -13
- package/dist/elements/a-text.js +53 -23
- package/dist/elements/a-tooltip.css +1 -1
- package/dist/elements/a-tooltip.d.ts +1 -11
- package/dist/elements/a-tooltip.js +20 -19
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/index.js +3 -0
- package/dist/general_types.d.ts +127 -31
- package/dist/index.d.ts +9 -1
- package/dist/index.js +37 -1
- package/dist/jsx-runtime.d.ts +16 -7
- package/dist/jsx-runtime.js +6 -0
- package/dist/reset.css +1 -1
- package/package.json +4 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "@antadesign/anta/jsx-runtime";
|
|
2
|
-
import { toneStyle, wrapLabel } from "../anta_helpers";
|
|
2
|
+
import { toneStyle, roundStyle, wrapLabel } from "../anta_helpers";
|
|
3
3
|
const Button = ({
|
|
4
4
|
priority,
|
|
5
5
|
tone,
|
|
@@ -12,6 +12,7 @@ const Button = ({
|
|
|
12
12
|
loading,
|
|
13
13
|
disabled,
|
|
14
14
|
selected,
|
|
15
|
+
round,
|
|
15
16
|
href,
|
|
16
17
|
type,
|
|
17
18
|
form,
|
|
@@ -21,7 +22,7 @@ const Button = ({
|
|
|
21
22
|
...rest
|
|
22
23
|
}) => {
|
|
23
24
|
const toneAttr = tone || void 0;
|
|
24
|
-
const computedStyle = toneStyle(toneAttr, "--button-tone-source", style);
|
|
25
|
+
const computedStyle = roundStyle(round, "--button-round", toneStyle(toneAttr, "--button-tone-source", style));
|
|
25
26
|
const isIconOnly = icon != null && label == null && children == null && iconTrailing == null;
|
|
26
27
|
const sharedAttrs = {
|
|
27
28
|
// `<a-button>` is a custom element with no implicit ARIA role, so AT would
|
|
@@ -41,6 +42,7 @@ const Button = ({
|
|
|
41
42
|
// presence (`[disabled]`, not `[disabled="true"]`), so any present form
|
|
42
43
|
// works. (ARIA attributes below stay string-valued — ARIA needs "true".)
|
|
43
44
|
paddingless: paddingless ? "" : void 0,
|
|
45
|
+
round: round ? "" : void 0,
|
|
44
46
|
loading: loading ? "" : void 0,
|
|
45
47
|
disabled: disabled ? "" : void 0,
|
|
46
48
|
selected: selected ? "" : void 0,
|
|
@@ -68,6 +70,7 @@ const Button = ({
|
|
|
68
70
|
"a",
|
|
69
71
|
{
|
|
70
72
|
href,
|
|
73
|
+
"data-anta": "",
|
|
71
74
|
...sharedAttrs,
|
|
72
75
|
...rest,
|
|
73
76
|
children: inner
|
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
/** Accessible name for the grid (defaults to the visible month heading). */
|
|
40
|
+
"aria-label"?: string;
|
|
41
|
+
/** Fired whenever the selection changes — event-first. `detail` is
|
|
42
|
+
* `{ next, prev, reason }`: `next` / `prev` are ISO date strings (`null` = none);
|
|
43
|
+
* `reason` is `'user'` | `'reset'` | `'restore'`. A `'user'` pick fires *before*
|
|
44
|
+
* applying and is **cancelable** — `event.preventDefault()` vetoes it
|
|
45
|
+
* (uncontrolled), or in controlled mode answer by updating `value`. `'reset'` /
|
|
46
|
+
* `'restore'` are not cancelable. */
|
|
47
|
+
onStateChange?: (event: StateChangeEvent, detail: StateDetail) => void;
|
|
48
|
+
/** Fired *after* the selection changes (post-apply). Not cancelable; for a
|
|
49
|
+
* controlled calendar it fires once you've updated `value`. */
|
|
50
|
+
onChange?: (event: Event) => void;
|
|
51
|
+
/** Like `onChange`, but with a `{ value, name }` snapshot — the ergonomic
|
|
52
|
+
* "just give me the new date" callback (mirrors `Input`). */
|
|
53
|
+
onValueChange?: (event: Event, attrs: CalendarChangeAttrs) => void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* `<Calendar>` — a single-date month grid you pick a day from, **composed from
|
|
57
|
+
* Anta components in light DOM** (nothing is hidden in a shadow root): days and
|
|
58
|
+
* the prev/next chevrons are `<Button>`s, so they inherit the design system's
|
|
59
|
+
* states for free — a selected day is literally a `secondary` Button in its
|
|
60
|
+
* `selected` state. All date math runs on the Temporal engine
|
|
61
|
+
* (`@antadesign/anta` exports `buildMonth` & friends), and the value is an ISO
|
|
62
|
+
* `YYYY-MM-DD` string.
|
|
63
|
+
*
|
|
64
|
+
* The grid lives in a form-associated `<a-calendar>` element (which owns the
|
|
65
|
+
* submitted value + reset/restore); the wrapper owns view-month, selection,
|
|
66
|
+
* keyboard, and roving `tabindex` — the `RadioGroup` model. The month switcher
|
|
67
|
+
* is a sibling rendered *outside* the grid, so it can be extended (month/year
|
|
68
|
+
* pickers) independently.
|
|
69
|
+
*
|
|
70
|
+
* Controlled (`value` + `onStateChange`) or uncontrolled (`defaultValue`).
|
|
71
|
+
* Requires `@antadesign/anta/elements` (client-side only).
|
|
72
|
+
*
|
|
73
|
+
* @remarks Not SSR-safe. It reads the current date (`Temporal.Now`) and locale
|
|
74
|
+
* (`navigator.language`) at render, so a server render and the client render
|
|
75
|
+
* disagree on the highlighted "today" and on localized labels, causing a
|
|
76
|
+
* hydration mismatch. Render it client-side only (Astro `client:only`, or a
|
|
77
|
+
* dynamic import inside `useEffect`).
|
|
78
|
+
*/
|
|
79
|
+
export declare const Calendar: ({ value, defaultValue, min, max, locale, name, size, disabled, onStateChange, onChange, onValueChange, className, style, "aria-label": ariaLabel, ...rest }: CalendarProps) => any;
|
|
80
|
+
export {};
|
|
@@ -0,0 +1,220 @@
|
|
|
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
|
+
onStateChange,
|
|
21
|
+
onChange,
|
|
22
|
+
onValueChange,
|
|
23
|
+
className,
|
|
24
|
+
style,
|
|
25
|
+
"aria-label": ariaLabel,
|
|
26
|
+
...rest
|
|
27
|
+
}) => {
|
|
28
|
+
const controlled = value !== void 0;
|
|
29
|
+
const resolvedLocale = locale || (typeof navigator !== "undefined" ? navigator.language : "en-US");
|
|
30
|
+
const minD = parseISODate(min);
|
|
31
|
+
const maxD = parseISODate(max);
|
|
32
|
+
const today = Temporal.Now.plainDateISO();
|
|
33
|
+
const [internalSelected, setInternalSelected] = useState(
|
|
34
|
+
() => parseISODate(defaultValue)
|
|
35
|
+
);
|
|
36
|
+
const selected = controlled ? parseISODate(value) : internalSelected;
|
|
37
|
+
const [cursor, setCursor] = useState(
|
|
38
|
+
() => clampDate(parseISODate(value ?? defaultValue) ?? today, minD, maxD)
|
|
39
|
+
);
|
|
40
|
+
const [focusReq, setFocusReq] = useState(null);
|
|
41
|
+
const [jumpOpen, setJumpOpen] = useState(false);
|
|
42
|
+
const headingId = useId();
|
|
43
|
+
const month = buildMonth({ anchor: cursor, locale: resolvedLocale, min: minD, max: maxD, selected, today });
|
|
44
|
+
const cursorIso = cursor.toString();
|
|
45
|
+
const minYear = minD ? minD.year : today.year - 3;
|
|
46
|
+
const maxYear = maxD ? maxD.year : today.year + 3;
|
|
47
|
+
const years = [];
|
|
48
|
+
for (let y = minYear; y <= maxYear; y++) years.push(y);
|
|
49
|
+
const monthNames = useMemo(
|
|
50
|
+
() => Array.from(
|
|
51
|
+
{ length: 12 },
|
|
52
|
+
(_, i) => Temporal.PlainDate.from({ year: 2e3, month: i + 1, day: 1 }).toLocaleString(resolvedLocale, {
|
|
53
|
+
month: "long"
|
|
54
|
+
})
|
|
55
|
+
),
|
|
56
|
+
[resolvedLocale]
|
|
57
|
+
);
|
|
58
|
+
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);
|
|
59
|
+
const moveCursorByMonth = (delta) => {
|
|
60
|
+
if (disabled) return;
|
|
61
|
+
setCursor((c) => clampDate(c.add({ months: delta }), minD, maxD));
|
|
62
|
+
};
|
|
63
|
+
const pickMonth = (y, m) => {
|
|
64
|
+
if (disabled) return;
|
|
65
|
+
setCursor((c) => clampDate(c.with({ year: y, month: m }), minD, maxD));
|
|
66
|
+
};
|
|
67
|
+
const jumpItems = useMemo(() => {
|
|
68
|
+
const monthItem = (y, i) => {
|
|
69
|
+
const m = i + 1;
|
|
70
|
+
return /* @__PURE__ */ jsx(
|
|
71
|
+
MenuItem,
|
|
72
|
+
{
|
|
73
|
+
label: monthNames[i],
|
|
74
|
+
selectionIndicator: "check",
|
|
75
|
+
selected: y === cursor.year && m === cursor.month,
|
|
76
|
+
disabled: monthOutOfRange(y, m) || void 0,
|
|
77
|
+
"data-menu-open": "",
|
|
78
|
+
onSelect: () => {
|
|
79
|
+
pickMonth(y, m);
|
|
80
|
+
setJumpOpen(false);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
`${y}-${m}`
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
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: [
|
|
87
|
+
y === cursor.year && /* @__PURE__ */ jsx("span", { className: "year-dot", "aria-hidden": "true" }),
|
|
88
|
+
/* @__PURE__ */ jsx(Menu, { children: monthNames.map((_, i) => monthItem(y, i)) })
|
|
89
|
+
] }, y));
|
|
90
|
+
}, [monthNames, cursor.year, cursor.month, minYear, maxYear, min, max, disabled]);
|
|
91
|
+
const onElementStateChange = (raw) => {
|
|
92
|
+
const { event, detail } = nativeStateChange(raw);
|
|
93
|
+
if (!detail) return;
|
|
94
|
+
onStateChange?.(event, detail);
|
|
95
|
+
if (detail.reason === "user" && (controlled || event.defaultPrevented)) return;
|
|
96
|
+
const next = parseISODate(detail.next);
|
|
97
|
+
if (!controlled) setInternalSelected(next);
|
|
98
|
+
setCursor(clampDate(next ?? cursor, minD, maxD));
|
|
99
|
+
};
|
|
100
|
+
const onElementChange = (raw) => {
|
|
101
|
+
const e = "nativeEvent" in raw ? raw.nativeEvent : raw;
|
|
102
|
+
onChange?.(e);
|
|
103
|
+
onValueChange?.(e, { value: e?.target?.value || null, name });
|
|
104
|
+
};
|
|
105
|
+
const onNavigate = (raw) => {
|
|
106
|
+
if (disabled) return;
|
|
107
|
+
const { detail } = nativeStateChange(raw);
|
|
108
|
+
const next = parseISODate(detail?.date ?? null);
|
|
109
|
+
if (!next) return;
|
|
110
|
+
const clamped = clampDate(next, minD, maxD);
|
|
111
|
+
setCursor(clamped);
|
|
112
|
+
setFocusReq((p) => ({ iso: clamped.toString(), n: (p?.n ?? 0) + 1 }));
|
|
113
|
+
};
|
|
114
|
+
const prevDisabled = disabled || minD != null && Temporal.PlainDate.compare(cursor.with({ day: 1 }).subtract({ days: 1 }), minD) < 0;
|
|
115
|
+
const nextDisabled = disabled || maxD != null && Temporal.PlainDate.compare(cursor.with({ day: 1 }).add({ months: 1 }), maxD) > 0;
|
|
116
|
+
return /* @__PURE__ */ jsxs(
|
|
117
|
+
"div",
|
|
118
|
+
{
|
|
119
|
+
className: cn("anta-calendar", className),
|
|
120
|
+
"data-size": size && size !== "medium" ? size : void 0,
|
|
121
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
122
|
+
style,
|
|
123
|
+
...rest,
|
|
124
|
+
children: [
|
|
125
|
+
/* @__PURE__ */ jsxs("div", { "data-part": "header", children: [
|
|
126
|
+
/* @__PURE__ */ jsx(
|
|
127
|
+
Button,
|
|
128
|
+
{
|
|
129
|
+
priority: "tertiary",
|
|
130
|
+
icon: "chevron-left",
|
|
131
|
+
size,
|
|
132
|
+
"aria-label": "Previous month",
|
|
133
|
+
disabled: prevDisabled,
|
|
134
|
+
onClick: () => moveCursorByMonth(-1)
|
|
135
|
+
}
|
|
136
|
+
),
|
|
137
|
+
/* @__PURE__ */ jsx(
|
|
138
|
+
Button,
|
|
139
|
+
{
|
|
140
|
+
id: headingId,
|
|
141
|
+
"data-part": "heading",
|
|
142
|
+
priority: "tertiary",
|
|
143
|
+
size,
|
|
144
|
+
"aria-live": "polite",
|
|
145
|
+
"aria-label": `${month.heading} \u2014 choose month and year`,
|
|
146
|
+
disabled: disabled || prevDisabled && nextDisabled,
|
|
147
|
+
children: month.heading
|
|
148
|
+
}
|
|
149
|
+
),
|
|
150
|
+
/* @__PURE__ */ jsx(Menu, { placement: "bottom", open: jumpOpen, onStateChange: (_e, { next }) => setJumpOpen(next), children: jumpItems }),
|
|
151
|
+
/* @__PURE__ */ jsx(
|
|
152
|
+
Button,
|
|
153
|
+
{
|
|
154
|
+
priority: "tertiary",
|
|
155
|
+
icon: "chevron-right",
|
|
156
|
+
size,
|
|
157
|
+
"aria-label": "Next month",
|
|
158
|
+
disabled: nextDisabled,
|
|
159
|
+
onClick: () => moveCursorByMonth(1)
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
] }),
|
|
163
|
+
/* @__PURE__ */ jsxs(
|
|
164
|
+
"a-calendar",
|
|
165
|
+
{
|
|
166
|
+
role: "group",
|
|
167
|
+
"aria-labelledby": headingId,
|
|
168
|
+
"aria-label": ariaLabel,
|
|
169
|
+
name,
|
|
170
|
+
value: controlled ? value : void 0,
|
|
171
|
+
defaultvalue: !controlled ? defaultValue : void 0,
|
|
172
|
+
disabled: disabled ? "" : void 0,
|
|
173
|
+
"data-focus": focusReq ? `${focusReq.iso}#${focusReq.n}` : void 0,
|
|
174
|
+
onstatechange: onElementStateChange,
|
|
175
|
+
onchange: onElementChange,
|
|
176
|
+
onnavigate: onNavigate,
|
|
177
|
+
children: [
|
|
178
|
+
month.weekdays.map((w, i) => /* @__PURE__ */ jsx(
|
|
179
|
+
"span",
|
|
180
|
+
{
|
|
181
|
+
"data-part": "weekday",
|
|
182
|
+
"data-weekend": w.weekend ? "" : void 0,
|
|
183
|
+
"aria-hidden": "true",
|
|
184
|
+
children: w.narrow
|
|
185
|
+
},
|
|
186
|
+
`wd${i}`
|
|
187
|
+
)),
|
|
188
|
+
month.weeks.flat().map((d) => {
|
|
189
|
+
const variant = d.today && !d.selected ? { priority: "secondary" } : { priority: "tertiary", selected: d.selected };
|
|
190
|
+
return /* @__PURE__ */ jsxs(
|
|
191
|
+
Button,
|
|
192
|
+
{
|
|
193
|
+
...variant,
|
|
194
|
+
size,
|
|
195
|
+
disabled: disabled || d.disabled,
|
|
196
|
+
tabIndex: d.iso === cursorIso ? 0 : -1,
|
|
197
|
+
"aria-label": d.label,
|
|
198
|
+
"aria-current": d.today ? "date" : void 0,
|
|
199
|
+
"data-part": "day-cell",
|
|
200
|
+
"data-date": d.iso,
|
|
201
|
+
"data-today": d.today ? "" : void 0,
|
|
202
|
+
"data-outside": d.outside ? "" : void 0,
|
|
203
|
+
children: [
|
|
204
|
+
d.day,
|
|
205
|
+
d.today && /* @__PURE__ */ jsx(Tooltip, { children: "Today" })
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
d.iso
|
|
209
|
+
);
|
|
210
|
+
})
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
};
|
|
218
|
+
export {
|
|
219
|
+
Calendar
|
|
220
|
+
};
|
|
@@ -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
|
|
52
|
-
* A named tone or any literal CSS color (`'#ff1493'`,
|
|
53
|
-
* one-off custom tone. Named tones track light/dark mode
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
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
|
-
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
30
|
-
|
|
31
|
-
"--checkbox-
|
|
32
|
-
toneStyle(
|
|
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-
|
|
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/
|
|
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`.
|
|
78
|
-
*
|
|
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;
|
package/dist/components/Input.js
CHANGED
|
@@ -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 ?
|
|
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
|
-
|
|
119
|
-
|
|
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"
|