@antadesign/anta 0.3.34 → 0.3.35
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/LICENSE.md +14 -1
- package/README.md +9 -0
- package/dist/anta_helpers.d.ts +46 -30
- package/dist/anta_helpers.js +66 -25
- package/dist/bundle.css +1 -1
- package/dist/bundle.js +2 -1333
- package/dist/components/Banner.d.ts +25 -40
- package/dist/components/Banner.js +15 -17
- package/dist/components/Button.js +1 -0
- package/dist/components/ButtonCopy.js +3 -2
- package/dist/components/Calendar.js +13 -13
- package/dist/components/Card.d.ts +9 -17
- package/dist/components/Card.js +50 -46
- package/dist/components/Dialog.d.ts +1 -0
- package/dist/components/Dialog.js +16 -10
- package/dist/components/Expander.d.ts +6 -21
- package/dist/components/Expander.js +24 -23
- package/dist/components/Icon.d.ts +8 -14
- package/dist/components/Input.d.ts +77 -96
- package/dist/components/Input.js +23 -27
- package/dist/components/InputAutocomplete.d.ts +29 -10
- package/dist/components/InputAutocomplete.js +25 -8
- package/dist/components/InputDate.js +2 -2
- package/dist/components/InputTime.d.ts +10 -4
- package/dist/components/InputTime.js +20 -16
- package/dist/components/Loader.d.ts +2 -2
- package/dist/components/Menu.d.ts +5 -4
- package/dist/components/Menu.js +13 -8
- package/dist/components/MenuItem.js +1 -14
- package/dist/components/MenuItemCopy.js +2 -2
- package/dist/components/Panel.d.ts +3 -1
- package/dist/components/Panel.js +17 -11
- package/dist/components/Progress.d.ts +21 -23
- package/dist/components/Progress.js +13 -9
- package/dist/components/RadioGroup.js +6 -8
- package/dist/components/{select-parts.css → Select.css} +1 -1
- package/dist/components/Select.d.ts +53 -35
- package/dist/components/Select.js +53 -97
- package/dist/components/SelectFaceted.d.ts +7 -3
- package/dist/components/SelectFaceted.js +21 -9
- package/dist/components/Slider.d.ts +28 -11
- package/dist/components/Slider.js +20 -20
- package/dist/components/Steps.css +1 -1
- package/dist/components/Steps.js +1 -11
- package/dist/components/Tabs.d.ts +17 -20
- package/dist/components/Tabs.js +5 -8
- package/dist/components/Text.d.ts +55 -36
- package/dist/components/Text.js +35 -22
- package/dist/components/Title.d.ts +16 -26
- package/dist/components/Title.js +2 -1
- package/dist/components/Toaster.js +9 -2
- package/dist/components/Tooltip.d.ts +10 -15
- package/dist/components/copy-props.d.ts +14 -3
- package/dist/components/copy-props.js +14 -3
- package/dist/components/select-tree.d.ts +24 -0
- package/dist/components/select-tree.js +35 -0
- package/dist/element-base.d.ts +10 -0
- package/dist/element-base.js +15 -0
- package/dist/elements/a-banner.css +1 -1
- package/dist/elements/a-banner.d.ts +4 -1
- package/dist/elements/a-banner.js +22 -112
- package/dist/elements/a-button.d.ts +2 -1
- package/dist/elements/a-button.js +18 -1
- package/dist/elements/a-calendar.d.ts +14 -13
- package/dist/elements/a-calendar.js +29 -24
- package/dist/elements/a-card.css +1 -1
- package/dist/elements/a-card.d.ts +0 -9
- package/dist/elements/a-card.js +0 -184
- package/dist/elements/a-checkbox.css +1 -1
- package/dist/elements/a-copy.css +1 -1
- package/dist/elements/a-copy.d.ts +1 -5
- package/dist/elements/a-copy.js +129 -108
- package/dist/elements/a-dialog.css +1 -1
- package/dist/elements/a-dialog.d.ts +1 -1
- package/dist/elements/a-dialog.js +66 -194
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.d.ts +4 -30
- package/dist/elements/a-expander.js +85 -344
- package/dist/elements/a-icon.d.ts +5 -23
- package/dist/elements/a-icon.js +1 -2
- package/dist/elements/a-input-time.css +1 -1
- package/dist/elements/a-input-time.d.ts +2 -1
- package/dist/elements/a-input-time.js +101 -168
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-input.d.ts +10 -8
- package/dist/elements/a-input.js +155 -230
- package/dist/elements/a-loader.d.ts +5 -8
- package/dist/elements/a-loader.js +1 -2
- package/dist/elements/a-menu-item.css +1 -1
- package/dist/elements/a-menu-item.d.ts +5 -3
- package/dist/elements/a-menu-item.js +5 -1
- package/dist/elements/a-menu.css +1 -1
- package/dist/elements/a-menu.d.ts +5 -7
- package/dist/elements/a-menu.js +383 -299
- package/dist/elements/a-panel.css +1 -1
- package/dist/elements/a-panel.js +19 -37
- package/dist/elements/a-progress.css +1 -1
- package/dist/elements/a-progress.d.ts +0 -22
- package/dist/elements/a-progress.js +0 -100
- package/dist/elements/a-radio-group.d.ts +1 -1
- package/dist/elements/a-radio-group.js +6 -4
- package/dist/elements/a-select-faceted.d.ts +1 -1
- package/dist/elements/a-select-faceted.js +1 -1
- package/dist/elements/a-select.d.ts +1 -1
- package/dist/elements/a-select.js +1 -1
- package/dist/elements/a-slider.css +1 -1
- package/dist/elements/a-slider.d.ts +11 -3
- package/dist/elements/a-slider.js +244 -242
- package/dist/elements/a-switch.css +1 -1
- package/dist/elements/a-tab.css +1 -1
- package/dist/elements/a-tabs.css +1 -1
- package/dist/elements/a-tabs.d.ts +1 -1
- package/dist/elements/a-tabs.js +6 -4
- package/dist/elements/a-tag.css +1 -1
- package/dist/elements/a-text.css +1 -1
- package/dist/elements/a-text.d.ts +6 -43
- package/dist/elements/a-text.js +110 -193
- package/dist/elements/a-title.css +1 -1
- package/dist/elements/a-toast.css +1 -1
- package/dist/elements/a-toast.d.ts +10 -45
- package/dist/elements/a-toast.js +80 -66
- package/dist/elements/a-toaster.css +1 -1
- package/dist/elements/a-toaster.js +9 -44
- package/dist/elements/a-tooltip.css +1 -1
- package/dist/elements/a-tooltip.d.ts +1 -1
- package/dist/elements/a-tooltip.js +142 -136
- package/dist/elements/copy-behavior.d.ts +1 -1
- package/dist/elements/copy-behavior.js +21 -21
- package/dist/elements/index.d.ts +3 -3
- package/dist/elements/index.js +3 -7
- package/dist/elements/input-focus-modality.d.ts +15 -0
- package/dist/elements/input-focus-modality.js +44 -0
- package/dist/elements/input-trailing-actions.d.ts +5 -0
- package/dist/elements/input-trailing-actions.js +38 -0
- package/dist/elements/shadow-aria.d.ts +2 -0
- package/dist/elements/shadow-aria.js +2 -1
- package/dist/elements/value-input.d.ts +3 -0
- package/dist/elements/value-input.js +12 -0
- package/dist/general_types.d.ts +103 -96
- package/dist/index.d.ts +1 -1
- package/dist/input-events.d.ts +4 -0
- package/dist/input-events.js +15 -0
- package/dist/jsx-runtime.d.ts +70 -23
- package/dist/jsx-runtime.js +26 -19
- package/dist/native-event-props.d.ts +2 -0
- package/dist/native-event-props.js +10 -0
- package/dist/reset.css +1 -1
- package/dist/theme-antithesis.css +10 -1
- package/dist/theme-antune.css +1 -1
- package/docs/accessibility.md +17 -3
- package/docs/changelog.md +348 -2
- package/docs/comparison.md +2 -2
- package/docs/components/avatar.md +5 -0
- package/docs/components/banner.md +117 -187
- package/docs/components/button.md +22 -0
- package/docs/components/card.md +74 -28
- package/docs/components/checkbox.md +9 -10
- package/docs/components/dialog.md +83 -32
- package/docs/components/expander.md +198 -435
- package/docs/components/icon.md +11 -17
- package/docs/components/input-autocomplete.md +152 -52
- package/docs/components/input-date.md +175 -148
- package/docs/components/input-time.md +81 -38
- package/docs/components/input.md +343 -349
- package/docs/components/loader.md +2 -1
- package/docs/components/menu.md +35 -6
- package/docs/components/panel.md +18 -0
- package/docs/components/progress.md +83 -49
- package/docs/components/radio.md +39 -43
- package/docs/components/select-faceted.md +54 -7
- package/docs/components/select.md +390 -386
- package/docs/components/slider.md +136 -19
- package/docs/components/steps.md +2 -1
- package/docs/components/switch.md +8 -9
- package/docs/components/tabs.md +110 -104
- package/docs/components/text.md +110 -86
- package/docs/components/title.md +47 -33
- package/docs/components/toaster.md +242 -84
- package/docs/components/tooltip.md +204 -113
- package/docs/install-config.md +183 -26
- package/docs/packages/plot.md +170 -148
- package/docs/theming.md +7 -0
- package/package.json +41 -3
- package/theme-antithesis-license.md +66 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { nativeStateChange, neutralToneAttr, toneStyle, roundStyle, roundAttr } from "../anta_helpers";
|
|
1
|
+
import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
|
|
2
|
+
import { hasChildren, nativeStateChange, neutralToneAttr, toneStyle, roundStyle, roundAttr } from "../anta_helpers";
|
|
3
|
+
import { useNativeEventProps } from "../native-event-props";
|
|
3
4
|
const Expander = ({
|
|
4
5
|
title,
|
|
5
6
|
level,
|
|
@@ -20,44 +21,44 @@ const Expander = ({
|
|
|
20
21
|
...rest
|
|
21
22
|
}) => {
|
|
22
23
|
const controlled = open !== void 0;
|
|
23
|
-
const
|
|
24
|
+
const eventProps = useNativeEventProps({
|
|
25
|
+
onstatechange: onStateChange ? (e) => {
|
|
26
|
+
const { event, detail, isOwn } = nativeStateChange(e);
|
|
27
|
+
if (isOwn && detail)
|
|
28
|
+
onStateChange(event, {
|
|
29
|
+
next: detail.next === "open",
|
|
30
|
+
prev: detail.prev === "open"
|
|
31
|
+
});
|
|
32
|
+
} : void 0
|
|
33
|
+
});
|
|
34
|
+
const hasActions = hasChildren(actions) && typeof actions !== "boolean" && (typeof actions !== "string" || Boolean(actions.trim()));
|
|
35
|
+
const presetIndicator = indicator == null ? "chevron" : typeof indicator === "string" && (indicator === "chevron" || indicator === "triangle" || indicator === "plus") ? indicator : void 0;
|
|
24
36
|
const pairedIndicator = indicator != null && typeof indicator === "object" && "closed" in indicator && "open" in indicator ? indicator : void 0;
|
|
25
|
-
const
|
|
37
|
+
const useCustomIndicator = indicator != null && !presetIndicator && !pairedIndicator;
|
|
26
38
|
const customIndicator = typeof indicator === "object" ? indicator : null;
|
|
39
|
+
const indicatorNodes = pairedIndicator ? [
|
|
40
|
+
/* @__PURE__ */ jsx("a-expander-indicator", { "data-when": "closed", "aria-hidden": "true", inert: true, children: pairedIndicator.closed }, "indicator-closed"),
|
|
41
|
+
/* @__PURE__ */ jsx("a-expander-indicator", { "data-when": "open", "aria-hidden": "true", inert: true, children: pairedIndicator.open }, "indicator-open")
|
|
42
|
+
] : [/* @__PURE__ */ jsx("a-expander-indicator", { shape: presetIndicator, "aria-hidden": "true", inert: true, children: useCustomIndicator ? customIndicator : null }, "indicator")];
|
|
27
43
|
const computedStyle = roundStyle(round, "--expander-round", toneStyle(tone, "--expander-tone-source", style));
|
|
28
|
-
const titleNode = typeof title === "object" && title !== null ? /* @__PURE__ */ jsx("
|
|
44
|
+
const titleNode = typeof title === "object" && title !== null ? /* @__PURE__ */ jsx("a-expander-title", { children: title }, "title") : /* @__PURE__ */ jsx("a-expander-summary", { level: level != null ? String(level) : void 0, children: title }, "title");
|
|
45
|
+
const actionsNode = hasActions ? /* @__PURE__ */ jsx("a-expander-actions", { children: actions }, "actions") : null;
|
|
29
46
|
return /* @__PURE__ */ jsxs(
|
|
30
47
|
"a-expander",
|
|
31
48
|
{
|
|
32
49
|
state: controlled ? open ? "open" : "closed" : void 0,
|
|
33
50
|
"default-state": !controlled && defaultOpen ? "open" : void 0,
|
|
34
|
-
level: level != null ? String(level) : void 0,
|
|
35
51
|
tone: neutralToneAttr(tone),
|
|
36
52
|
priority: priority && priority !== "secondary" ? priority : void 0,
|
|
37
53
|
outdent: outdent ? "" : void 0,
|
|
38
54
|
round: roundAttr(round),
|
|
39
55
|
disabled: disabled ? "" : void 0,
|
|
40
|
-
|
|
41
|
-
"indicator-placement": indicatorPlacement && indicatorPlacement !== "start" ? indicatorPlacement : void 0,
|
|
42
|
-
onstatechange: onStateChange ? (e) => {
|
|
43
|
-
const { event, detail, isOwn } = nativeStateChange(e);
|
|
44
|
-
if (isOwn && detail)
|
|
45
|
-
onStateChange(event, {
|
|
46
|
-
next: detail.next === "open",
|
|
47
|
-
prev: detail.prev === "open"
|
|
48
|
-
});
|
|
49
|
-
} : void 0,
|
|
56
|
+
...eventProps,
|
|
50
57
|
class: className,
|
|
51
58
|
style: computedStyle,
|
|
52
59
|
...rest,
|
|
53
60
|
children: [
|
|
54
|
-
titleNode,
|
|
55
|
-
actions != null && /* @__PURE__ */ jsx("span", { slot: "actions", children: actions }),
|
|
56
|
-
pairedIndicator && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
57
|
-
/* @__PURE__ */ jsx("span", { slot: "indicator", "data-when": "closed", "aria-hidden": "true", inert: true, children: pairedIndicator.closed }),
|
|
58
|
-
/* @__PURE__ */ jsx("span", { slot: "indicator", "data-when": "open", "aria-hidden": "true", inert: true, children: pairedIndicator.open })
|
|
59
|
-
] }),
|
|
60
|
-
useCustomSlot && /* @__PURE__ */ jsx("span", { slot: "indicator", "aria-hidden": "true", inert: true, children: customIndicator }),
|
|
61
|
+
indicatorPlacement === "end" ? [titleNode, actionsNode, ...indicatorNodes] : [...indicatorNodes, titleNode, actionsNode],
|
|
61
62
|
/* @__PURE__ */ jsx("a-expander-details", { children })
|
|
62
63
|
]
|
|
63
64
|
}
|
|
@@ -16,26 +16,20 @@ export interface IconProps extends BaseProps {
|
|
|
16
16
|
label?: string;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* Displays an icon in the current text color. Pass `size` for custom dimensions
|
|
20
|
+
* and `label` when the icon conveys meaning without accompanying text.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* stylesheets.
|
|
22
|
+
* Icon needs CSS without element registration. See
|
|
23
|
+
* [Install and configure](https://anta.design/install/) for stylesheet setup.
|
|
25
24
|
*
|
|
26
|
-
* @example Decorative icon
|
|
25
|
+
* @example Decorative icon beside status text
|
|
27
26
|
* ```tsx
|
|
28
|
-
* <
|
|
29
|
-
* <Icon shape="trash" />
|
|
30
|
-
* Delete
|
|
31
|
-
* </button>
|
|
27
|
+
* <Text><Icon shape="check" /> Saved</Text>
|
|
32
28
|
* ```
|
|
33
29
|
*
|
|
34
|
-
* @example
|
|
30
|
+
* @example Standalone icon with an accessible name
|
|
35
31
|
* ```tsx
|
|
36
|
-
* <
|
|
37
|
-
* <Icon shape="trash" label="Delete" />
|
|
38
|
-
* </button>
|
|
32
|
+
* <Icon shape="warning-triangle" label="Warning" />
|
|
39
33
|
* ```
|
|
40
34
|
*/
|
|
41
35
|
export declare const Icon: ({ shape, size, label, className, style, ...rest }: IconProps) => any;
|
|
@@ -10,40 +10,33 @@ export interface InputChangeAttrs {
|
|
|
10
10
|
name?: string;
|
|
11
11
|
/** `true` when the value is empty. */
|
|
12
12
|
empty: boolean;
|
|
13
|
-
/** Whether the field currently passes validation (native
|
|
13
|
+
/** Whether the field currently passes validation (native constraints and `status`). `undefined`
|
|
14
14
|
* where `ElementInternals` is unsupported. */
|
|
15
15
|
valid?: boolean;
|
|
16
16
|
/** Current validation message (`''` when valid). */
|
|
17
17
|
validationMessage: string;
|
|
18
18
|
}
|
|
19
19
|
export interface InputProps extends BaseProps, DOMEventHandlers {
|
|
20
|
-
/** Extra content
|
|
21
|
-
*
|
|
22
|
-
* space and anchors to the field — consistent with how tooltips attach
|
|
23
|
-
* to any other element. Use the named `leading` / `trailing` props for
|
|
24
|
-
* in-field content. */
|
|
20
|
+
/** Extra content between the field and hint. A `Tooltip` child anchors to the
|
|
21
|
+
* field. Use `leading` and `trailing` for content inside the field. */
|
|
25
22
|
children?: React.ReactNode;
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
* control as its accessible name (the element mirrors the label text to
|
|
29
|
-
* `aria-label`, since `<label for>` can't cross the shadow boundary). */
|
|
23
|
+
/** Explain what to enter. Accepts text or JSX and also names the field for
|
|
24
|
+
* screen readers. */
|
|
30
25
|
label?: React.ReactNode;
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
26
|
+
/** Persistent help or feedback below the field. `status` colors the message and
|
|
27
|
+
* adds a status icon. */
|
|
33
28
|
hint?: React.ReactNode;
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* are advisory and stay valid. Omit (or `neutral`) for a plain field. */
|
|
29
|
+
/** Feedback for the field and hint. Use `critical` for an error that must be
|
|
30
|
+
* fixed before submission. Other statuses provide feedback without adding a
|
|
31
|
+
* validation error. Required fields and other validation rules still apply. */
|
|
38
32
|
status?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical';
|
|
39
|
-
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
33
|
+
/** Icon before the hint. The defaults are `warning-diamond` for critical,
|
|
34
|
+
* `warning-triangle` for warning, `circle-check` for success, `info` for info,
|
|
35
|
+
* and `circle-small-solid` for brand. Pass a shape to replace it or `false` to
|
|
36
|
+
* hide it. Neutral has no default icon. */
|
|
43
37
|
statusIcon?: IconShape | (string & {}) | false;
|
|
44
|
-
/** Custom
|
|
45
|
-
*
|
|
46
|
-
* other controls' custom-tone knob; a `status` still overrides for validation. */
|
|
38
|
+
/** Custom CSS border color. A non-neutral `status` takes precedence. The focus
|
|
39
|
+
* ring uses the global `--focus-ring`. */
|
|
47
40
|
tone?: string;
|
|
48
41
|
/** Field emphasis. `primary` has a fill and border, `secondary` keeps the
|
|
49
42
|
* border without a fill, and `tertiary` makes the border transparent until
|
|
@@ -51,52 +44,49 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
|
|
|
51
44
|
* Status borders remain visible at rest.
|
|
52
45
|
* @defaultValue primary */
|
|
53
46
|
priority?: 'primary' | 'secondary' | 'tertiary';
|
|
54
|
-
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* @defaultValue medium */
|
|
47
|
+
/** Adjust the field, text, icons, and action buttons together to suit the
|
|
48
|
+
* surrounding interface.
|
|
49
|
+
* @defaultValue medium */
|
|
58
50
|
size?: 'small' | 'medium' | 'large';
|
|
59
|
-
/** Controlled value.
|
|
51
|
+
/** Controlled value. Update it with `onInput` or `onValueChange` for live
|
|
52
|
+
* editing. */
|
|
60
53
|
value?: string;
|
|
61
|
-
/** Initial value for
|
|
54
|
+
/** Initial value for an uncontrolled field, restored on form reset. */
|
|
62
55
|
defaultValue?: string;
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
* CSS `field-sizing` where supported (Chrome/Edge, Safari ≥ 26.2) and falls
|
|
66
|
-
* back to a built-in JS resize elsewhere (Firefox, older Safari), so it grows
|
|
67
|
-
* in every browser. */
|
|
56
|
+
/** Allow longer text and grow the field as someone types. Use `maxRows` to
|
|
57
|
+
* limit growth or `rows` to keep a fixed height. */
|
|
68
58
|
multiline?: boolean;
|
|
69
|
-
/** Fixed visible row count
|
|
70
|
-
* `multiline`). */
|
|
59
|
+
/** Fixed visible row count. Also enables `multiline`. */
|
|
71
60
|
rows?: number;
|
|
72
|
-
/**
|
|
73
|
-
*
|
|
61
|
+
/** Maximum row count for autogrow when `rows` is unset. Omit for unlimited
|
|
62
|
+
* growth. */
|
|
74
63
|
maxRows?: number;
|
|
75
|
-
/** Show a clear button
|
|
76
|
-
*
|
|
64
|
+
/** Show a clear button before trailing content when an editable field has a
|
|
65
|
+
* value. */
|
|
77
66
|
clearable?: boolean;
|
|
78
|
-
/** Content
|
|
67
|
+
/** Content at the start of the field, such as an icon or text. */
|
|
79
68
|
leading?: React.ReactNode;
|
|
80
|
-
/** Content
|
|
81
|
-
*
|
|
69
|
+
/** Content at the end of the field, after the clear button. Anta buttons fit
|
|
70
|
+
* the field height and keep their padding. Icon-only Buttons are square; text
|
|
71
|
+
* buttons keep their natural width. Pass buttons directly or in
|
|
72
|
+
* a fragment for compact spacing. Other wrapping elements keep the text inset.
|
|
73
|
+
* Override either inset with the `--input-trailing-inset` CSS property. */
|
|
82
74
|
trailing?: React.ReactNode;
|
|
83
|
-
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* native `search` type never reaches the element, so the browser's own
|
|
88
|
-
* clear/search affordances never appear — Anta owns that chrome.
|
|
89
|
-
* @defaultValue text */
|
|
75
|
+
/** Choose the kind of information to enter. Ignored for multiline fields.
|
|
76
|
+
* `search` adds a search icon and clear button. Replace the icon with
|
|
77
|
+
* `leading` or hide the button with `clearable={false}`.
|
|
78
|
+
* @defaultValue text */
|
|
90
79
|
type?: 'text' | 'search' | 'email' | 'password' | 'tel' | 'url' | 'number';
|
|
91
|
-
/** Native autocomplete token
|
|
92
|
-
*
|
|
93
|
-
*
|
|
80
|
+
/** Native autocomplete token describing the field purpose. Overrides the token
|
|
81
|
+
* derived from the email, tel, or url type. Set an explicit token for other
|
|
82
|
+
* purposes, such as `username`, `current-password`, or `one-time-code`. */
|
|
94
83
|
autoComplete?: 'off' | 'on' | 'name' | 'username' | 'email' | 'current-password' | 'new-password' | 'one-time-code' | 'tel' | 'url' | (string & {});
|
|
95
|
-
/** Virtual
|
|
84
|
+
/** Virtual keyboard hint. Overrides the value derived from `type` without
|
|
85
|
+
* changing validation. */
|
|
96
86
|
inputMode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';
|
|
97
87
|
/** Focus this field when its containing `Dialog` opens. */
|
|
98
88
|
autoFocus?: boolean;
|
|
99
|
-
/** Form field name
|
|
89
|
+
/** Form field name for submission, named form lookup, and attribute selectors. */
|
|
100
90
|
name?: string;
|
|
101
91
|
/** Placeholder shown when empty. */
|
|
102
92
|
placeholder?: string;
|
|
@@ -114,71 +104,62 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
|
|
|
114
104
|
button?: boolean;
|
|
115
105
|
/** Mark the field required (drives native validity). */
|
|
116
106
|
required?: boolean;
|
|
117
|
-
/**
|
|
118
|
-
*
|
|
119
|
-
* trailing actions). */
|
|
107
|
+
/** Keep leading, trailing, and clear content subtle until someone hovers over
|
|
108
|
+
* or focuses the field. */
|
|
120
109
|
dimActions?: boolean;
|
|
121
|
-
/**
|
|
122
|
-
*
|
|
123
|
-
* a circle to match (it isn't sized by a custom field value). */
|
|
110
|
+
/** Give the field fully rounded corners. Pass a number in pixels or a CSS
|
|
111
|
+
* length for a custom radius. The clear button stays circular. */
|
|
124
112
|
round?: boolean | number | string;
|
|
125
113
|
/** Toggle native spell-checking. */
|
|
126
114
|
spellCheck?: boolean;
|
|
127
|
-
/**
|
|
115
|
+
/** Maximum text length for native types that support it. */
|
|
128
116
|
maxLength?: number;
|
|
129
|
-
/**
|
|
117
|
+
/** Minimum text length for native types that support it. */
|
|
130
118
|
minLength?: number;
|
|
131
|
-
/** Validation pattern
|
|
119
|
+
/** Validation pattern for supported single-line types. Checks validity without
|
|
120
|
+
* preventing typing. */
|
|
132
121
|
pattern?: string;
|
|
133
|
-
/**
|
|
122
|
+
/** Minimum value for `type="number"`. */
|
|
134
123
|
min?: number | string;
|
|
124
|
+
/** Maximum value for `type="number"`. */
|
|
135
125
|
max?: number | string;
|
|
126
|
+
/** Allowed increment for `type="number"`. */
|
|
136
127
|
step?: number | string;
|
|
137
|
-
/** Fires
|
|
128
|
+
/** Fires when editing changes the value or the field is cleared. Read
|
|
129
|
+
* `e.target.value`. */
|
|
138
130
|
onInput?: (e: any) => void;
|
|
139
|
-
/** Fires on
|
|
140
|
-
*
|
|
141
|
-
* the native meaning; reach for `onInput` (every keystroke) or `onValueChange`
|
|
142
|
-
* (both) for live updates. Read `e.target.value`. */
|
|
131
|
+
/** Fires on native commit, such as blur or Enter, and on clear. Use `onInput` or
|
|
132
|
+
* `onValueChange` for live edits. Read `e.target.value`. */
|
|
143
133
|
onChange?: (e: any) => void;
|
|
144
|
-
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* you can do `setForm(s => ({ ...s, [attrs.name]: attrs.value }))` without
|
|
148
|
-
* digging into the event. Use `event.type` to tell a live edit (`input`) from
|
|
149
|
-
* a commit (`change`); read `id` / `type` / `className` off `event.target`. */
|
|
134
|
+
/** Receive the current text, field name, and validation result while editing
|
|
135
|
+
* and when an edit is committed, including clear. Can run more than once for
|
|
136
|
+
* the same value. Use `event.type` to distinguish the events. */
|
|
150
137
|
onValueChange?: (event: any, attrs: InputChangeAttrs) => void;
|
|
151
|
-
/** Fires
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* element's cancelable, bubbling `clearclick` event. */
|
|
138
|
+
/** Fires before the built-in clear action. Call `e.preventDefault()`
|
|
139
|
+
* synchronously to keep the value and cancel `onClearInput`. Corresponds to the
|
|
140
|
+
* cancelable, bubbling `clearclick` event. */
|
|
155
141
|
onClearClick?: (e: CustomEvent) => void;
|
|
156
|
-
/** Fires after
|
|
157
|
-
*
|
|
158
|
-
* specifically to a clear. Doesn't fire if `onClearClick` cancelled the
|
|
159
|
-
* clear. Backed by the element's bubbling `clearinput` event. */
|
|
142
|
+
/** Fires after clearing, following `onInput` and `onChange`. Does not fire when
|
|
143
|
+
* clearing is canceled. Corresponds to the bubbling `clearinput` event. */
|
|
160
144
|
onClearInput?: (e: CustomEvent) => void;
|
|
161
145
|
/** Fires when the field gains focus. */
|
|
162
146
|
onFocus?: (e: any) => void;
|
|
163
147
|
/** Fires when the field loses focus. */
|
|
164
148
|
onBlur?: (e: any) => void;
|
|
165
|
-
/** ARIA
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* shadow control. Left unset by default. */
|
|
149
|
+
/** ARIA role for the native control, such as `combobox` for an InputAutocomplete
|
|
150
|
+
* trigger. The element delegates this and standard `aria-*` props to its native
|
|
151
|
+
* shadow control. */
|
|
169
152
|
role?: string;
|
|
170
153
|
}
|
|
171
154
|
/**
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* control is reachable for styling through `::part(input)`.
|
|
155
|
+
* Text field for single-line or multiline input, with labels, hints, and actions.
|
|
156
|
+
* Supports native form submission, validation, autofill, and input methods.
|
|
157
|
+
* Pass `multiline` for a textarea and `clearable` to offer a clear action.
|
|
176
158
|
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
* `clear()`, and its visibility is CSS off the element's `:state(filled)`.
|
|
159
|
+
* Use `leading` and `trailing` for content inside the field. Style the editable
|
|
160
|
+
* control through `::part(input)`.
|
|
180
161
|
*
|
|
181
|
-
*
|
|
162
|
+
* See [Install and configure](https://anta.design/install/) for runtime setup.
|
|
182
163
|
*
|
|
183
164
|
* @example
|
|
184
165
|
* ```tsx
|
package/dist/components/Input.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
|
|
2
|
+
import { CLEAR_TRIGGER } from "../input-events";
|
|
2
3
|
import { nativeStateChange, neutralToneAttr, toneStyle, roundStyle, roundAttr } from "../anta_helpers";
|
|
3
4
|
import { Button } from "./Button";
|
|
4
5
|
import { Icon } from "./Icon";
|
|
6
|
+
import { useNativeEventProps } from "../native-event-props";
|
|
5
7
|
const presence = (on) => on ? "" : void 0;
|
|
6
|
-
const isStringish = (n) => typeof n === "string" || typeof n === "number";
|
|
7
8
|
const attrsOf = (e) => {
|
|
8
9
|
const el = e?.target ?? {};
|
|
9
10
|
const value = el.value ?? "";
|
|
10
11
|
return {
|
|
11
12
|
value,
|
|
12
|
-
name: el.
|
|
13
|
+
name: el.name || void 0,
|
|
13
14
|
empty: !value,
|
|
14
15
|
valid: el.validity ? el.validity.valid : void 0,
|
|
15
16
|
validationMessage: el.validationMessage ?? ""
|
|
@@ -77,6 +78,18 @@ const Input = ({
|
|
|
77
78
|
style,
|
|
78
79
|
...rest
|
|
79
80
|
}) => {
|
|
81
|
+
const eventProps = useNativeEventProps({
|
|
82
|
+
oninput: onInput || onValueChange ? (e) => {
|
|
83
|
+
onInput?.(e);
|
|
84
|
+
onValueChange?.(e, attrsOf(e));
|
|
85
|
+
} : void 0,
|
|
86
|
+
onchange: onChange || onValueChange ? (e) => {
|
|
87
|
+
onChange?.(e);
|
|
88
|
+
onValueChange?.(e, attrsOf(e));
|
|
89
|
+
} : void 0,
|
|
90
|
+
onclearclick: onClearClick ? (e) => onClearClick(nativeStateChange(e).event) : void 0,
|
|
91
|
+
onclearinput: onClearInput ? (e) => onClearInput(nativeStateChange(e).event) : void 0
|
|
92
|
+
});
|
|
80
93
|
const statusTone = status && status !== "neutral" ? status : void 0;
|
|
81
94
|
const glyph = statusIcon === void 0 ? statusTone ? STATUS_ICON[statusTone] : void 0 : statusIcon;
|
|
82
95
|
const isSearch = type === "search";
|
|
@@ -117,32 +130,15 @@ const Input = ({
|
|
|
117
130
|
step,
|
|
118
131
|
"aria-invalid": status === "critical" ? "true" : void 0,
|
|
119
132
|
role: role ?? (isSearch ? "searchbox" : void 0),
|
|
120
|
-
|
|
121
|
-
onInput?.(e);
|
|
122
|
-
onValueChange?.(e, attrsOf(e));
|
|
123
|
-
} : void 0,
|
|
124
|
-
onchange: onChange || onValueChange ? (e) => {
|
|
125
|
-
onChange?.(e);
|
|
126
|
-
onValueChange?.(e, attrsOf(e));
|
|
127
|
-
} : void 0,
|
|
128
|
-
onclearclick: onClearClick ? (e) => onClearClick(nativeStateChange(e).event) : void 0,
|
|
129
|
-
onclearinput: onClearInput ? (e) => onClearInput(nativeStateChange(e).event) : void 0,
|
|
133
|
+
...eventProps,
|
|
130
134
|
class: className,
|
|
131
135
|
style: roundStyle(round, "--input-round", toneStyle(tone, "--input-tone-source", style)),
|
|
132
136
|
...rest,
|
|
133
137
|
children: [
|
|
134
|
-
label != null &&
|
|
135
|
-
resolvedLeading != null && /* @__PURE__ */ jsx("
|
|
136
|
-
resolvedClearable && //
|
|
137
|
-
|
|
138
|
-
// only when filled + editable). It fires the bubbling `clearrequest`
|
|
139
|
-
// event via a-button's global listener, so clearing works even without
|
|
140
|
-
// framework hydration; the element turns that into clearclick→clear().
|
|
141
|
-
// CONTRACT: the `data-custom-event` value below MUST match `CLEAR_TRIGGER`
|
|
142
|
-
// in the element (src/elements/a-input.ts). The string is duplicated, not
|
|
143
|
-
// shared — importing the element module here would self-register it and
|
|
144
|
-
// break the wrapper/element decoupling. Rename in both places.
|
|
145
|
-
/* @__PURE__ */ jsx("span", { slot: "clear", style: { display: "contents" }, children: /* @__PURE__ */ jsx(
|
|
138
|
+
label != null && /* @__PURE__ */ jsx("a-input-label", { slot: "label", children: label }),
|
|
139
|
+
resolvedLeading != null && /* @__PURE__ */ jsx("a-input-leading", { slot: "leading", children: resolvedLeading }),
|
|
140
|
+
resolvedClearable && // The UI element handles the clear lifecycle before framework hydration.
|
|
141
|
+
/* @__PURE__ */ jsx("a-input-clear", { slot: "clear", children: /* @__PURE__ */ jsx(
|
|
146
142
|
Button,
|
|
147
143
|
{
|
|
148
144
|
priority: "tertiary",
|
|
@@ -150,11 +146,11 @@ const Input = ({
|
|
|
150
146
|
round: !!round,
|
|
151
147
|
icon: "x",
|
|
152
148
|
"aria-label": "Clear",
|
|
153
|
-
"data-custom-event":
|
|
149
|
+
"data-custom-event": CLEAR_TRIGGER
|
|
154
150
|
}
|
|
155
151
|
) }),
|
|
156
|
-
trailing != null && /* @__PURE__ */ jsx("
|
|
157
|
-
hint != null && /* @__PURE__ */ jsxs("
|
|
152
|
+
trailing != null && /* @__PURE__ */ jsx("a-input-trailing", { slot: "trailing", children: trailing }),
|
|
153
|
+
hint != null && /* @__PURE__ */ jsxs("a-input-hint", { slot: "hint", children: [
|
|
158
154
|
glyph && /* @__PURE__ */ jsx(Icon, { shape: glyph, "aria-hidden": "true" }),
|
|
159
155
|
/* @__PURE__ */ jsx("span", { children: hint })
|
|
160
156
|
] }),
|
|
@@ -1,24 +1,31 @@
|
|
|
1
|
-
import type { BaseProps } from '../general_types';
|
|
1
|
+
import type { BaseProps, DOMEventHandlers } from '../general_types';
|
|
2
2
|
import type { IconShape } from '../elements/a-icon.shapes';
|
|
3
3
|
import type { SelectOption } from './Select';
|
|
4
|
-
export interface InputAutocompleteProps extends Omit<BaseProps, 'children'> {
|
|
4
|
+
export interface InputAutocompleteProps extends Omit<BaseProps, 'children'>, Omit<DOMEventHandlers, 'onSelect'> {
|
|
5
5
|
/** The suggestions: bare strings or `SelectOption`s (`value` / `label` / `hint` /
|
|
6
6
|
* `icon` / `tone` / `disabled`). A flat list; picking one fills the field. */
|
|
7
7
|
suggestions: (string | SelectOption)[];
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
8
|
+
/** The controlled field text. Any string is valid, including `''` for an empty
|
|
9
|
+
* field. Omit or pass `undefined` for uncontrolled use. Parent updates do not
|
|
10
|
+
* call `onValueChange`. Releasing control retains the latest controlled text. */
|
|
10
11
|
value?: string;
|
|
11
|
-
/** Initial value
|
|
12
|
+
/** Initial uncontrolled text and the value restored by a form reset. Resetting
|
|
13
|
+
* an unfocused field does not open suggestions or move focus. */
|
|
12
14
|
defaultValue?: string;
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
+
/** Reports text changes from typing, picking a suggestion, clearing, or form
|
|
16
|
+
* reset. */
|
|
15
17
|
onValueChange?: (value: string) => void;
|
|
16
|
-
/** Fires
|
|
18
|
+
/** Fires after `onValueChange` when a suggestion is chosen, with the normalized
|
|
19
|
+
* option. This reports the choice even if a controlled parent rejects the value.
|
|
20
|
+
* Typing and clearing do not call it. */
|
|
17
21
|
onSelect?: (option: SelectOption) => void;
|
|
18
22
|
/** How suggestions match the text. `true` uses the built-in case-insensitive
|
|
19
23
|
* substring match on `value` / `label` / `hint`; a function `(option, query) =>
|
|
20
|
-
* boolean`
|
|
21
|
-
*
|
|
24
|
+
* boolean` receives the original field text, including whitespace, once per
|
|
25
|
+
* option on each render, including when empty. Custom matching has no automatic
|
|
26
|
+
* highlighting. `false` shows `suggestions` unchanged for application-provided
|
|
27
|
+
* async or remote filtering, without automatic highlighting. Replacing results
|
|
28
|
+
* updates an open list but does not reopen a dismissed list.
|
|
22
29
|
* @defaultValue true */
|
|
23
30
|
filter?: boolean | ((option: SelectOption, query: string) => boolean);
|
|
24
31
|
/** Placeholder text. */
|
|
@@ -46,6 +53,18 @@ export interface InputAutocompleteProps extends Omit<BaseProps, 'children'> {
|
|
|
46
53
|
leading?: React.ReactNode;
|
|
47
54
|
/** Trailing adornment inside the field. */
|
|
48
55
|
trailing?: React.ReactNode;
|
|
56
|
+
/** Observe focus before the suggestion list opens. */
|
|
57
|
+
onFocus?: (event: any) => void;
|
|
58
|
+
/** Observe focus loss. The suggestion list closes without changing the text. */
|
|
59
|
+
onBlur?: (event: any) => void;
|
|
60
|
+
/** Observe editing before `onValueChange`. The input event reports text that
|
|
61
|
+
* has already changed; `preventDefault()` does not reject that text. */
|
|
62
|
+
onInput?: (event: any) => void;
|
|
63
|
+
/** Observe keys before the wrapper's plain-Enter dismissal. `preventDefault()`
|
|
64
|
+
* keeps that dismissal from running. Menu handles navigation and active-option
|
|
65
|
+
* activation earlier, in document capture; this callback cannot veto those
|
|
66
|
+
* actions. Composing keys remain with the input method. */
|
|
67
|
+
onKeyDown?: (event: any) => void;
|
|
49
68
|
}
|
|
50
69
|
/**
|
|
51
70
|
* `<InputAutocomplete>` is a text field with a suggestion dropdown. Its value is
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "@antadesign/anta/jsx-runtime";
|
|
2
2
|
import { useState, useMemo } from "../jsx-runtime";
|
|
3
|
-
import { optionPresentationAttrs } from "../anta_helpers";
|
|
3
|
+
import { isComposingKey, optionPresentationAttrs, useSelectionMirror } from "../anta_helpers";
|
|
4
4
|
import { normalizeOpt, matchQueryRegex, matchesQuery, highlight } from "./select-options";
|
|
5
5
|
import { Input } from "./Input";
|
|
6
6
|
import { Menu } from "./Menu";
|
|
@@ -12,13 +12,18 @@ const InputAutocomplete = (props) => {
|
|
|
12
12
|
defaultValue,
|
|
13
13
|
onValueChange,
|
|
14
14
|
onSelect,
|
|
15
|
+
onFocus,
|
|
16
|
+
onBlur,
|
|
17
|
+
onInput,
|
|
18
|
+
onKeyDown,
|
|
15
19
|
filter = true,
|
|
16
20
|
...rest
|
|
17
21
|
} = props;
|
|
18
22
|
const controlled = value !== void 0;
|
|
19
|
-
const [
|
|
20
|
-
const text =
|
|
21
|
-
const [open,
|
|
23
|
+
const [mirroredText, setInternal] = useSelectionMirror(value, defaultValue ?? "");
|
|
24
|
+
const text = mirroredText ?? "";
|
|
25
|
+
const [{ open }, setPopup] = useState({ open: false, focused: false });
|
|
26
|
+
const setOpen = (next) => setPopup((prev) => ({ ...prev, open: next }));
|
|
22
27
|
const options = useMemo(() => suggestions.map(normalizeOpt), [suggestions]);
|
|
23
28
|
const custom = typeof filter === "function";
|
|
24
29
|
const queryRe = filter !== false && !custom ? matchQueryRegex(text) : null;
|
|
@@ -39,18 +44,29 @@ const InputAutocomplete = (props) => {
|
|
|
39
44
|
{
|
|
40
45
|
...rest,
|
|
41
46
|
value: text,
|
|
47
|
+
defaultValue,
|
|
42
48
|
"data-menu-search": "",
|
|
43
49
|
role: "combobox",
|
|
44
50
|
"aria-haspopup": "listbox",
|
|
45
51
|
"aria-expanded": menuOpen ? "true" : "false",
|
|
46
52
|
"aria-autocomplete": "list",
|
|
47
|
-
onFocus: () =>
|
|
53
|
+
onFocus: (e) => {
|
|
54
|
+
onFocus?.(e);
|
|
55
|
+
setPopup({ open: true, focused: true });
|
|
56
|
+
},
|
|
57
|
+
onBlur: (e) => {
|
|
58
|
+
onBlur?.(e);
|
|
59
|
+
setPopup({ open: false, focused: false });
|
|
60
|
+
},
|
|
48
61
|
onInput: (e) => {
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
const next = e.currentTarget.value;
|
|
63
|
+
onInput?.(e);
|
|
64
|
+
setText(next);
|
|
65
|
+
setPopup((prev) => ({ ...prev, open: prev.focused }));
|
|
51
66
|
},
|
|
52
67
|
onKeyDown: (e) => {
|
|
53
|
-
|
|
68
|
+
onKeyDown?.(e);
|
|
69
|
+
if (e.key === "Enter" && !e.defaultPrevented && !isComposingKey(e)) setOpen(false);
|
|
54
70
|
}
|
|
55
71
|
}
|
|
56
72
|
),
|
|
@@ -69,6 +85,7 @@ const InputAutocomplete = (props) => {
|
|
|
69
85
|
{
|
|
70
86
|
...optionAttrs,
|
|
71
87
|
role: "option",
|
|
88
|
+
tabIndex: -1,
|
|
72
89
|
icon: opt.icon,
|
|
73
90
|
label: highlight(opt.label ?? opt.value, queryRe),
|
|
74
91
|
hint: opt.hint ? highlight(opt.hint, queryRe) : opt.hint,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "@antadesign/anta/jsx-runtime";
|
|
2
2
|
import { useMemo, useState } from "../jsx-runtime";
|
|
3
|
-
import { isModifiedNavigationKey } from "../anta_helpers";
|
|
3
|
+
import { isModifiedNavigationKey, unwrapNativeEvent } from "../anta_helpers";
|
|
4
4
|
import { Temporal } from "temporal-polyfill";
|
|
5
5
|
import {
|
|
6
6
|
parseISODate,
|
|
@@ -195,7 +195,7 @@ const InputDate = ({
|
|
|
195
195
|
"aria-label": "Time",
|
|
196
196
|
value: hasTime ? `${String(h24).padStart(2, "0")}:${curM}` : "",
|
|
197
197
|
onValueChange: (e, { value: t }) => {
|
|
198
|
-
const ev =
|
|
198
|
+
const ev = unwrapNativeEvent(e);
|
|
199
199
|
if (ev?.type !== "change") return;
|
|
200
200
|
const base = dateISO || Temporal.Now.plainDateISO().toString();
|
|
201
201
|
commit(t ? `${base}T${t}` : base);
|