@antadesign/anta 0.3.23 → 0.3.25

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 (89) hide show
  1. package/dist/bundle.css +1 -1
  2. package/dist/bundle.js +32 -25
  3. package/dist/components/Banner.d.ts +10 -10
  4. package/dist/components/Banner.js +3 -1
  5. package/dist/components/Breadcrumbs.css +1 -0
  6. package/dist/components/Breadcrumbs.d.ts +127 -0
  7. package/dist/components/Breadcrumbs.js +145 -0
  8. package/dist/components/Button.d.ts +14 -7
  9. package/dist/components/Button.js +2 -0
  10. package/dist/components/ButtonCopy.d.ts +2 -2
  11. package/dist/components/Input.d.ts +3 -1
  12. package/dist/components/Input.js +2 -0
  13. package/dist/components/InputDate.css +1 -1
  14. package/dist/components/InputTime.d.ts +3 -1
  15. package/dist/components/InputTime.js +2 -0
  16. package/dist/components/MenuItem.d.ts +5 -1
  17. package/dist/components/MenuItem.js +72 -2
  18. package/dist/components/MenuItemCopy.d.ts +16 -5
  19. package/dist/components/MenuItemCopy.js +9 -3
  20. package/dist/components/Steps.css +1 -1
  21. package/dist/components/copy-props.d.ts +3 -4
  22. package/dist/components/select-parts.css +1 -1
  23. package/dist/elements/a-avatar.css +1 -1
  24. package/dist/elements/a-banner.css +1 -1
  25. package/dist/elements/a-banner.js +12 -0
  26. package/dist/elements/a-button.css +1 -1
  27. package/dist/elements/a-calendar.css +1 -1
  28. package/dist/elements/a-card.css +1 -1
  29. package/dist/elements/a-checkbox.css +1 -1
  30. package/dist/elements/a-copy.css +1 -1
  31. package/dist/elements/a-dialog.css +1 -1
  32. package/dist/elements/a-dialog.js +3 -1
  33. package/dist/elements/a-expander.css +1 -1
  34. package/dist/elements/a-icon.css +1 -1
  35. package/dist/elements/a-icon.shapes.css +1 -1
  36. package/dist/elements/a-icon.shapes.d.ts +2 -2
  37. package/dist/elements/a-icon.shapes.js +2 -2
  38. package/dist/elements/a-input-time.css +1 -1
  39. package/dist/elements/a-input-time.d.ts +2 -0
  40. package/dist/elements/a-input-time.js +7 -0
  41. package/dist/elements/a-input.css +1 -1
  42. package/dist/elements/a-input.d.ts +4 -0
  43. package/dist/elements/a-input.js +17 -0
  44. package/dist/elements/a-loader.css +1 -1
  45. package/dist/elements/a-menu-group.css +1 -1
  46. package/dist/elements/a-menu-item.css +1 -1
  47. package/dist/elements/a-menu-separator.css +1 -1
  48. package/dist/elements/a-menu.css +1 -1
  49. package/dist/elements/a-menu.d.ts +4 -4
  50. package/dist/elements/a-menu.js +6 -4
  51. package/dist/elements/a-progress.css +1 -1
  52. package/dist/elements/a-radio-group.css +1 -1
  53. package/dist/elements/a-radio.css +1 -1
  54. package/dist/elements/a-slider.css +1 -1
  55. package/dist/elements/a-switch.css +1 -1
  56. package/dist/elements/a-tab.css +1 -1
  57. package/dist/elements/a-tabpanel.css +1 -1
  58. package/dist/elements/a-tabs.css +1 -1
  59. package/dist/elements/a-tag.css +1 -1
  60. package/dist/elements/a-text.css +1 -1
  61. package/dist/elements/a-title.css +1 -1
  62. package/dist/elements/a-toast.css +1 -1
  63. package/dist/elements/a-toaster.css +1 -1
  64. package/dist/elements/a-tooltip.css +1 -1
  65. package/dist/elements/copy-behavior.d.ts +13 -15
  66. package/dist/general_types.d.ts +12 -4
  67. package/dist/generate-icons.mjs +3 -3
  68. package/dist/index.d.ts +3 -1
  69. package/dist/index.js +2 -0
  70. package/dist/jsx-runtime.d.ts +2 -0
  71. package/dist/reset.css +1 -1
  72. package/dist/search-index.json +0 -0
  73. package/dist/theme-anta.css +1 -1
  74. package/dist/tokens.css +1 -1
  75. package/docs/changelog.md +43 -2
  76. package/docs/comparison.md +8 -3
  77. package/docs/components/banner.md +26 -15
  78. package/docs/components/breadcrumbs.md +177 -0
  79. package/docs/components/button.md +30 -16
  80. package/docs/components/dialog.md +4 -4
  81. package/docs/components/input-time.md +1 -0
  82. package/docs/components/input.md +6 -0
  83. package/docs/components/menu.md +18 -10
  84. package/docs/components/tag.md +47 -0
  85. package/docs/index.md +1 -0
  86. package/docs/install-config.md +58 -13
  87. package/docs/normalization.md +37 -28
  88. package/docs/theming.md +4 -1
  89. package/package.json +2 -2
@@ -1,9 +1,8 @@
1
1
  import type { BaseProps } from "../general_types";
2
- /** Public props for the `<Banner>` message strip. `message` is the leading
3
- * content, `children` sit between it and `actions`, all centered in one row. */
2
+ /** Props for the `<Banner>` message strip. `message` leads, `children` precede
3
+ * `actions`, and `align` places the row. */
4
4
  export interface BannerProps extends BaseProps {
5
- /** Leading message — a string (rendered at the banner type scale) or any node.
6
- * Centered in the bar, followed by `children` and then `actions`. */
5
+ /** Leading message: a string at the banner type scale or any node. */
7
6
  message?: React.ReactNode;
8
7
  /** Trailing controls (buttons, links) rendered as a compact row after the
9
8
  * message and `children`. */
@@ -16,6 +15,10 @@ export interface BannerProps extends BaseProps {
16
15
  * lightness/chroma are pinned. `'neutral'` (the default) is the same as omitting it.
17
16
  * @defaultValue 'neutral' */
18
17
  tone?: "neutral" | "brand" | "info" | "success" | "warning" | "critical" | (string & {});
18
+ /** Positions the content row. `'start'` aligns it to the inline edge; `'center'`
19
+ * centers it. Wrapped message text follows the selected alignment.
20
+ * @defaultValue 'start' */
21
+ align?: "start" | "center";
19
22
  /** Rounded corners for a standalone, floating banner (`border-radius: 999px`,
20
23
  * which clamps to a stadium) instead of the edge-to-edge strip. Still borderless
21
24
  * by default. Pass a `number` (px) or a CSS length string for a custom radius. */
@@ -45,11 +48,8 @@ export interface BannerProps extends BaseProps {
45
48
  onDismiss?: () => void;
46
49
  }
47
50
  /**
48
- * `<Banner>` — a full-width, dismissible message strip with a bottom border.
49
- *
50
- * A close cousin of `<Card>` with a small, centered horizontal payload:
51
- * `message` leads, `children` sit in the middle, `actions` trail, and (when
52
- * `closable`) a 40px-wide, full-height ✕ fills the right edge without shifting the centered group.
51
+ * `<Banner>` — a full-width, dismissible message strip. `message`, `children`, and
52
+ * `actions` form a row at the inline start by default; `align="center"` centers it.
53
53
  *
54
54
  * A pure, stateless pass-through to `<a-banner>`: the element owns dismissal and
55
55
  * visibility, so the wrapper holds no state and grabs no ref — it maps props to
@@ -76,4 +76,4 @@ export interface BannerProps extends BaseProps {
76
76
  * <Banner message="Saved." dismissed={hidden} onDismiss={() => setHidden(true)} />
77
77
  * ```
78
78
  */
79
- export declare const Banner: ({ message, actions, tone, round, closable, role, dismissed, defaultDismissed, onDismiss, className, style, children, ...rest }: BannerProps) => any;
79
+ export declare const Banner: ({ message, actions, tone, align, round, closable, role, dismissed, defaultDismissed, onDismiss, className, style, children, ...rest }: BannerProps) => any;
@@ -5,6 +5,7 @@ const Banner = ({
5
5
  message,
6
6
  actions,
7
7
  tone,
8
+ align,
8
9
  round,
9
10
  closable,
10
11
  role = "status",
@@ -29,6 +30,7 @@ const Banner = ({
29
30
  state: controlled ? dismissed ? "closed" : "open" : void 0,
30
31
  "default-state": !controlled ? defaultDismissed ? "closed" : "open" : void 0,
31
32
  tone: tone && tone !== "neutral" ? tone : void 0,
33
+ align: align === "center" ? "center" : void 0,
32
34
  round: roundAttr(round),
33
35
  role,
34
36
  onstatechange: onDismiss ? (e) => {
@@ -41,7 +43,7 @@ const Banner = ({
41
43
  children: [
42
44
  messageNode,
43
45
  children,
44
- actions != null && /* @__PURE__ */ jsx("span", { slot: "actions", style: { display: "contents" }, children: actions }),
46
+ actions != null && /* @__PURE__ */ jsx("span", { "data-anta-banner-actions-wrapper": "", slot: "actions", style: { display: "contents" }, children: actions }),
45
47
  closable !== false && // A real <a-button> (light DOM → fully styled, keyboard-focusable) in the
46
48
  // element's `close` slot. It fires the bubbling `dismissrequest` event via
47
49
  // a-button's global listener, so dismissing works even without framework
@@ -0,0 +1 @@
1
+ @layer anta.components{a-breadcrumbs{--breadcrumb-gap: 1px;--breadcrumb-separator-color: var(--text-5);--breadcrumb-separator-icon-size: 16px;--breadcrumb-separator-font-size: 15px;display:flex;align-items:center;gap:var(--breadcrumb-gap);width:max-content;min-width:100%;max-width:100%;overflow-x:auto}a-breadcrumbs[data-size=small]{--breadcrumb-separator-icon-size: 14px;--breadcrumb-separator-font-size: 13px}a-breadcrumbs[data-size=large]{--breadcrumb-separator-icon-size: 18px;--breadcrumb-separator-font-size: 17px}a-breadcrumbs[data-paddingless]{--breadcrumb-gap: .75ch}a-breadcrumbs[data-separator-icon]{--breadcrumb-gap: 0}a-breadcrumbs>*{flex:none}a-breadcrumb-separator{display:inline-flex;flex:none;align-items:center;justify-content:center;color:var(--breadcrumb-separator-color);font-family:var(--sans-serif);font-size:var(--breadcrumb-separator-font-size);line-height:1;user-select:none}a-breadcrumb-separator>a-icon{--icon-size: var(--breadcrumb-separator-icon-size)}}
@@ -0,0 +1,127 @@
1
+ import type { IconShape } from '../elements/a-icon.shapes';
2
+ import type { BaseProps } from '../general_types';
3
+ import type { BaseButtonProps } from './Button';
4
+ import type { CopyTarget } from './copy-props';
5
+ import './Breadcrumbs.css';
6
+ /** The text separators built into `<Breadcrumbs>`. Pass an `IconShape` for a
7
+ * graphic separator instead. */
8
+ export type BreadcrumbTextSeparator = '→' | '/' | '•' | '▸';
9
+ /** A built-in text separator or any registered Anta icon shape. */
10
+ export type BreadcrumbSeparator = BreadcrumbTextSeparator | IconShape;
11
+ /** Props shared by every breadcrumb item. They land on the visible `Button`
12
+ * and, when the item is folded, on the corresponding `MenuItem`. */
13
+ type BreadcrumbItemBase = Omit<BaseProps, 'children' | 'key' | 'slot' | 'tabIndex'> & {
14
+ /** Visible item content. It is reused as the folded menu row's label. */
15
+ label: React.ReactNode;
16
+ /** Leading icon shape. */
17
+ icon?: IconShape;
18
+ /** Trailing icon shape. Copy items reserve the trailing icon for their copy
19
+ * feedback and therefore do not accept this prop. */
20
+ iconTrailing?: IconShape;
21
+ /** Semantic tone or a literal CSS color. */
22
+ tone?: BaseButtonProps['tone'];
23
+ /** Disable the item. */
24
+ disabled?: boolean;
25
+ /** Mark this item as the current page. The wrapper passes
26
+ * `aria-current="page"` through to its button or link. */
27
+ current?: boolean;
28
+ /** Runs when an action item is activated. A folded item calls it from the
29
+ * corresponding `MenuItem` selection. */
30
+ onClick?: (event: any) => void;
31
+ };
32
+ /** A breadcrumb that navigates to an href. */
33
+ export type BreadcrumbLinkItem = BreadcrumbItemBase & {
34
+ /** Destination URL. */
35
+ href: string;
36
+ /** Where to open the destination. */
37
+ target?: string;
38
+ copy?: never;
39
+ copyNode?: never;
40
+ copyUrl?: never;
41
+ };
42
+ /** A non-navigating breadcrumb action. */
43
+ export type BreadcrumbActionItem = BreadcrumbItemBase & {
44
+ href?: never;
45
+ target?: never;
46
+ copy?: never;
47
+ copyNode?: never;
48
+ copyUrl?: never;
49
+ };
50
+ /** A breadcrumb that copies a literal value, a marked DOM region, or the page
51
+ * URL. It uses `ButtonCopy` when visible and `MenuItemCopy` when folded. */
52
+ export type BreadcrumbCopyItem = Omit<BreadcrumbItemBase, 'iconTrailing'> & CopyTarget & {
53
+ href?: never;
54
+ target?: never;
55
+ iconTrailing?: never;
56
+ /** Where the copy glyph sits relative to the label — or `'none'` to omit it.
57
+ * @defaultValue 'leading' */
58
+ iconPlacement?: 'leading' | 'trailing' | 'none';
59
+ /** Text in the successful no-icon confirmation.
60
+ * @defaultValue Copied */
61
+ copiedLabel?: string;
62
+ };
63
+ /** One item in a `<Breadcrumbs>` trail. Link, action, and copy items share
64
+ * presentation props while keeping incompatible behaviours type-safe. */
65
+ export type BreadcrumbItem = BreadcrumbLinkItem | BreadcrumbActionItem | BreadcrumbCopyItem;
66
+ /** Public props for `<Breadcrumbs>`. */
67
+ export type BreadcrumbsProps = BaseProps & {
68
+ children?: never;
69
+ } & {
70
+ /** Ordered breadcrumb entries. */
71
+ items: BreadcrumbItem[];
72
+ /** Button size applied to every visible item and the More control.
73
+ * @defaultValue 'medium' */
74
+ size?: 'small' | 'medium' | 'large';
75
+ /** Separator between visible entries.
76
+ * @defaultValue 'chevron-right' */
77
+ separator?: BreadcrumbSeparator;
78
+ /** Maximum number of original breadcrumb items left visible. The More
79
+ * control does not count. Omit to keep every item visible. */
80
+ maxItems?: number;
81
+ /** Number of original items kept before the More control when `maxItems`
82
+ * collapses the trail. The rest of the visible-item budget is kept from the
83
+ * end, so `0` puts More first.
84
+ * @defaultValue 0 */
85
+ itemsBeforeCollapse?: number;
86
+ /** Accessible name for the More control.
87
+ * @defaultValue 'Show more breadcrumbs' */
88
+ moreLabel?: string;
89
+ } & ({
90
+ /** Button priority applied to every visible item and the More control.
91
+ * @defaultValue quaternary */
92
+ priority?: 'quaternary';
93
+ /** Remove horizontal padding from every visible breadcrumb control. */
94
+ paddingless?: boolean;
95
+ } | {
96
+ /** Button priority applied to every visible item and the More control. */
97
+ priority: 'tertiary';
98
+ paddingless?: never;
99
+ }) & ({
100
+ underline?: never;
101
+ underlineOnHover?: never;
102
+ } | {
103
+ /** Underline style applied to every visible breadcrumb control. */
104
+ underline: 'solid' | 'dashed' | 'dotted';
105
+ /** Hide the underline at rest and reveal it on hover. */
106
+ underlineOnHover?: boolean;
107
+ });
108
+ /**
109
+ * Breadcrumbs — hierarchy navigation assembled from Anta Buttons. Entries can
110
+ * be links, actions, or copy controls; an optional `maxItems` replaces one
111
+ * contiguous range with a More menu without measuring the available width.
112
+ *
113
+ * @example
114
+ * ```tsx
115
+ * <Breadcrumbs
116
+ * maxItems={3}
117
+ * items={[
118
+ * { label: 'Home', href: '/' },
119
+ * { label: 'Projects', href: '/projects' },
120
+ * { label: 'Anta', href: '/projects/anta' },
121
+ * { label: 'Button.tsx', current: true, copy: 'src/components/Button.tsx' },
122
+ * ]}
123
+ * />
124
+ * ```
125
+ */
126
+ export declare const Breadcrumbs: ({ items, priority, size, separator, maxItems, itemsBeforeCollapse, moreLabel, underline, underlineOnHover, paddingless, className, style, "aria-label": ariaLabel, ...rest }: BreadcrumbsProps) => any;
127
+ export {};
@@ -0,0 +1,145 @@
1
+ import { jsx } from "@antadesign/anta/jsx-runtime";
2
+ import { Button } from "./Button";
3
+ import { ButtonCopy } from "./ButtonCopy";
4
+ import { Icon } from "./Icon";
5
+ import { Menu } from "./Menu";
6
+ import { MenuItem } from "./MenuItem";
7
+ import { MenuItemCopy } from "./MenuItemCopy";
8
+ import "./Breadcrumbs.css";
9
+ const TEXT_SEPARATORS = /* @__PURE__ */ new Set(["\u2192", "/", "\u2022", "\u25B8"]);
10
+ function isCopyItem(item) {
11
+ return "copy" in item || "copyNode" in item || "copyUrl" in item;
12
+ }
13
+ function buildEntries(items, maxItems, itemsBeforeCollapse) {
14
+ if (maxItems == null || !Number.isFinite(maxItems))
15
+ return items.map((item) => ({ kind: "item", item }));
16
+ const visibleCount = Math.max(1, Math.floor(maxItems));
17
+ if (items.length <= visibleCount) return items.map((item) => ({ kind: "item", item }));
18
+ const beforeCount = Math.min(
19
+ Math.max(0, Number.isFinite(itemsBeforeCollapse) ? Math.floor(itemsBeforeCollapse) : 0),
20
+ visibleCount - 1
21
+ );
22
+ const afterCount = visibleCount - beforeCount;
23
+ const hidden = items.slice(beforeCount, items.length - afterCount);
24
+ return [
25
+ ...items.slice(0, beforeCount).map((item) => ({ kind: "item", item })),
26
+ { kind: "overflow", items: hidden },
27
+ ...items.slice(items.length - afterCount).map((item) => ({ kind: "item", item }))
28
+ ];
29
+ }
30
+ function currentAttrs(item) {
31
+ return item.current ? { "aria-current": "page" } : {};
32
+ }
33
+ function renderButtonItem(item, priority, size, underline, underlineOnHover, paddingless, key) {
34
+ const { label, current, ...props } = item;
35
+ const a11y = currentAttrs(item);
36
+ if (isCopyItem(item)) {
37
+ const copyProps = {
38
+ ...props,
39
+ priority,
40
+ size,
41
+ underline,
42
+ underlineOnHover,
43
+ paddingless,
44
+ ...a11y
45
+ };
46
+ return /* @__PURE__ */ jsx(ButtonCopy, { ...copyProps, children: label }, key);
47
+ }
48
+ const buttonProps = {
49
+ ...props,
50
+ priority,
51
+ size,
52
+ underline,
53
+ underlineOnHover,
54
+ paddingless,
55
+ ...a11y
56
+ };
57
+ return /* @__PURE__ */ jsx(Button, { ...buttonProps, children: label }, key);
58
+ }
59
+ function renderMenuItem(item, key) {
60
+ const { label, current, onClick, ...props } = item;
61
+ const a11y = currentAttrs(item);
62
+ if (isCopyItem(item)) {
63
+ return /* @__PURE__ */ jsx(
64
+ MenuItemCopy,
65
+ {
66
+ ...props,
67
+ label,
68
+ onSelect: onClick,
69
+ ...a11y
70
+ },
71
+ key
72
+ );
73
+ }
74
+ return /* @__PURE__ */ jsx(
75
+ MenuItem,
76
+ {
77
+ ...props,
78
+ label,
79
+ onSelect: onClick,
80
+ ...a11y
81
+ },
82
+ key
83
+ );
84
+ }
85
+ const Breadcrumbs = ({
86
+ items,
87
+ priority = "quaternary",
88
+ size = "medium",
89
+ separator = "chevron-right",
90
+ maxItems,
91
+ itemsBeforeCollapse = 0,
92
+ moreLabel = "Show more breadcrumbs",
93
+ underline,
94
+ underlineOnHover,
95
+ paddingless,
96
+ className,
97
+ style,
98
+ "aria-label": ariaLabel,
99
+ ...rest
100
+ }) => {
101
+ const entries = buildEntries(items, maxItems, itemsBeforeCollapse);
102
+ const textSeparator = TEXT_SEPARATORS.has(separator);
103
+ const separatorNode = textSeparator ? separator : /* @__PURE__ */ jsx(Icon, { shape: separator });
104
+ return /* @__PURE__ */ jsx(
105
+ "a-breadcrumbs",
106
+ {
107
+ role: "navigation",
108
+ "aria-label": ariaLabel ?? "Breadcrumb",
109
+ "data-size": size === "medium" ? void 0 : size,
110
+ "data-paddingless": paddingless ? "" : void 0,
111
+ "data-separator-icon": textSeparator ? void 0 : "",
112
+ class: className,
113
+ style,
114
+ ...rest,
115
+ children: entries.flatMap((entry, index) => {
116
+ const nodes = entry.kind === "overflow" ? [
117
+ /* @__PURE__ */ jsx(
118
+ Button,
119
+ {
120
+ ...{
121
+ priority,
122
+ size,
123
+ paddingless,
124
+ icon: "more",
125
+ "aria-label": moreLabel,
126
+ "aria-haspopup": "menu"
127
+ }
128
+ },
129
+ `more-${index}`
130
+ ),
131
+ /* @__PURE__ */ jsx(Menu, { autoWidth: true, children: entry.items.map((item, hiddenIndex) => renderMenuItem(item, hiddenIndex)) }, `menu-${index}`)
132
+ ] : [renderButtonItem(entry.item, priority, size, underline, underlineOnHover, paddingless, index)];
133
+ if (index < entries.length - 1) {
134
+ nodes.push(
135
+ /* @__PURE__ */ jsx("a-breadcrumb-separator", { "aria-hidden": "true", children: separatorNode }, `separator-${index}`)
136
+ );
137
+ }
138
+ return nodes;
139
+ })
140
+ }
141
+ );
142
+ };
143
+ export {
144
+ Breadcrumbs
145
+ };
@@ -94,6 +94,16 @@ export type SubmitMode = {
94
94
  /** Form id when the button isn't a descendant of its form. */
95
95
  form?: string;
96
96
  };
97
+ /** Underline options shared by tertiary and quaternary buttons. */
98
+ export type UnderlineMode = {
99
+ underline?: never;
100
+ underlineOnHover?: never;
101
+ } | {
102
+ /** Underline style. */
103
+ underline: 'solid' | 'dashed' | 'dotted';
104
+ /** Hide the underline at rest and reveal it on hover. */
105
+ underlineOnHover?: boolean;
106
+ };
97
107
  /** Priority axis — `underline` only on `tertiary` / `quaternary`,
98
108
  * `paddingless` only on `quaternary`. */
99
109
  export type PriorityMode = {
@@ -101,16 +111,13 @@ export type PriorityMode = {
101
111
  * @defaultValue secondary */
102
112
  priority?: 'primary' | 'secondary';
103
113
  underline?: never;
114
+ underlineOnHover?: never;
104
115
  paddingless?: never;
105
- } | {
116
+ } | UnderlineMode & {
106
117
  priority: 'tertiary';
107
- /** Underline style. */
108
- underline?: 'solid' | 'dashed' | 'dotted';
109
118
  paddingless?: never;
110
- } | {
119
+ } | UnderlineMode & {
111
120
  priority: 'quaternary';
112
- /** Underline style. */
113
- underline?: 'solid' | 'dashed' | 'dotted';
114
121
  /** Drops outer padding to zero. */
115
122
  paddingless?: boolean;
116
123
  };
@@ -135,4 +142,4 @@ export type ButtonProps = BaseButtonProps & PriorityMode & ContentMode & SubmitM
135
142
  * <Button href="/docs" target="_blank" label="Read the docs" />
136
143
  * ```
137
144
  */
138
- export declare const Button: ({ priority, tone, underline, icon, iconTrailing, paddingless, label, size, loading, disabled, selected, round, onClick, href, target, rel, download, ping, type, form, className, style, children, ...rest }: ButtonProps) => any;
145
+ export declare const Button: ({ priority, tone, underline, underlineOnHover, icon, iconTrailing, paddingless, label, size, loading, disabled, selected, round, onClick, href, target, rel, download, ping, type, form, className, style, children, ...rest }: ButtonProps) => any;
@@ -4,6 +4,7 @@ const Button = ({
4
4
  priority,
5
5
  tone,
6
6
  underline,
7
+ underlineOnHover,
7
8
  icon,
8
9
  iconTrailing,
9
10
  paddingless,
@@ -40,6 +41,7 @@ const Button = ({
40
41
  priority,
41
42
  tone: toneAttr,
42
43
  underline,
44
+ "underline-on-hover": underlineOnHover ? "" : void 0,
43
45
  // 'medium' (and unset) is the implicit default — emit no DOM attr.
44
46
  size: size && size !== "medium" ? size : void 0,
45
47
  // Boolean attributes: emit a presence attribute (empty string) when on,
@@ -32,8 +32,8 @@ export type ButtonCopyProps = ButtonProps & {
32
32
  /**
33
33
  * Copy button — a `Button` preset for copy-to-clipboard. Set `copy` for a literal
34
34
  * string, `copyNode` to copy a DOM region, or `copyUrl` to copy the current page
35
- * URL. For content computed on demand, keep `copy` reactive and refresh it in
36
- * `onCopyRequest` (fired on pointerdown / keydown).
35
+ * URL. For dynamic text, pass a controlled `copy` string and set it in
36
+ * `onCopyRequest` before activation.
37
37
  *
38
38
  * It composes a plain `<Button>` with a slotted `<a-copy>` child that performs
39
39
  * the write — the button itself carries no copy behavior. This wrapper flips the
@@ -88,6 +88,8 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
88
88
  autoComplete?: 'off' | 'on' | 'name' | 'username' | 'email' | 'current-password' | 'new-password' | 'one-time-code' | 'tel' | 'url' | (string & {});
89
89
  /** Virtual-keyboard hint. Overrides the value derived from `type`. */
90
90
  inputMode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';
91
+ /** Focus this field when its containing `Dialog` opens. */
92
+ autoFocus?: boolean;
91
93
  /** Form field name — submitted with the form via ElementInternals. */
92
94
  name?: string;
93
95
  /** Placeholder shown when empty. */
@@ -171,4 +173,4 @@ export interface InputProps extends BaseProps, DOMEventHandlers {
171
173
  * <Input label="Email" type="email" placeholder="you@example.com" clearable />
172
174
  * ```
173
175
  */
174
- export declare const Input: ({ label, hint, status, statusIcon, tone, size, round, value, defaultValue, multiline, rows, maxRows, clearable, leading, trailing, type, autoComplete, inputMode, name, placeholder, truncate, disabled, readOnly, required, dimActions, spellCheck, maxLength, minLength, pattern, min, max, step, onInput, onChange, onValueChange, onClearClick, onClearInput, children, className, style, ...rest }: InputProps) => any;
176
+ export declare const Input: ({ label, hint, status, statusIcon, tone, size, round, value, defaultValue, multiline, rows, maxRows, clearable, leading, trailing, type, autoComplete, inputMode, autoFocus, name, placeholder, truncate, disabled, readOnly, required, dimActions, spellCheck, maxLength, minLength, pattern, min, max, step, onInput, onChange, onValueChange, onClearClick, onClearInput, children, className, style, ...rest }: InputProps) => any;
@@ -49,6 +49,7 @@ const Input = ({
49
49
  type,
50
50
  autoComplete,
51
51
  inputMode,
52
+ autoFocus,
52
53
  name,
53
54
  placeholder,
54
55
  truncate = true,
@@ -101,6 +102,7 @@ const Input = ({
101
102
  "dim-actions": presence(dimActions),
102
103
  autocomplete: autoComplete ?? (!multiline && rows == null && type ? AUTOCOMPLETE_BY_TYPE[type] : void 0),
103
104
  inputmode: inputMode ?? (!multiline && rows == null && type ? INPUTMODE_BY_TYPE[type] : void 0),
105
+ autofocus: autoFocus ? true : void 0,
104
106
  spellcheck: spellCheck != null ? spellCheck ? "true" : "false" : void 0,
105
107
  maxlength: maxLength != null ? String(maxLength) : void 0,
106
108
  minlength: minLength != null ? String(minLength) : void 0,
@@ -1 +1 @@
1
- @layer anta{a-input-date-time-container{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:6px;padding-top:8px;border-top:1px solid var(--border-3)}}
1
+ @layer anta.components{a-input-date-time-container{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:6px;padding-top:8px;border-top:1px solid var(--border-3)}}
@@ -70,6 +70,8 @@ export interface InputTimeProps extends BaseProps, DOMEventHandlers {
70
70
  trailing?: React.ReactNode;
71
71
  /** Fully-round the field, or a custom radius (`number` px / CSS length). */
72
72
  round?: boolean | number | string;
73
+ /** Focus this field when its containing `Dialog` opens. */
74
+ autoFocus?: boolean;
73
75
  /** Fires on every edit (`input`), with the native event + an `attrs` snapshot
74
76
  * (`value`, `name`, `empty`, `valid`, `validationMessage`). Also fires on
75
77
  * `change` (blur) and on clear. */
@@ -103,4 +105,4 @@ export interface InputTimeProps extends BaseProps, DOMEventHandlers {
103
105
  * <InputTime label="Start" defaultValue="09:30" onValueChange={(_, { value }) => save(value)} />
104
106
  * ```
105
107
  */
106
- export declare const InputTime: ({ label, hint, status, statusIcon, tone, size, round, value, defaultValue, locale, hour12, min, max, name, disabled, required, icon, clearable, dimActions, trailing, onValueChange, onClearInput, children, className, style, ...rest }: InputTimeProps) => any;
108
+ export declare const InputTime: ({ label, hint, status, statusIcon, tone, size, round, value, defaultValue, locale, hour12, min, max, name, disabled, required, icon, clearable, dimActions, trailing, autoFocus, onValueChange, onClearInput, children, className, style, ...rest }: InputTimeProps) => any;
@@ -43,6 +43,7 @@ const InputTime = ({
43
43
  clearable,
44
44
  dimActions,
45
45
  trailing,
46
+ autoFocus,
46
47
  onValueChange,
47
48
  onClearInput,
48
49
  children,
@@ -69,6 +70,7 @@ const InputTime = ({
69
70
  disabled: presence(disabled),
70
71
  required: presence(required),
71
72
  "dim-actions": presence(dimActions),
73
+ autofocus: autoFocus ? true : void 0,
72
74
  "aria-invalid": status === "critical" ? "true" : void 0,
73
75
  oninput: onValueChange ? (e) => onValueChange(e, attrsOf(e)) : void 0,
74
76
  onchange: onValueChange ? (e) => onValueChange(e, attrsOf(e)) : void 0,
@@ -12,7 +12,11 @@ export interface MenuItemCommonProps extends BaseProps {
12
12
  * option `hint`. Requires `label` (it stacks in a column beneath it). Muted
13
13
  * (`--text-3`) and tracks the row's `tone`. A string, or any node. */
14
14
  hint?: React.ReactNode;
15
- /** A trailing keyboard-shortcut hint, e.g. `"⌘E"`. */
15
+ /** Trailing shortcut hint, e.g. `"⌘E"`. Anta translates it to
16
+ * `aria-keyshortcuts` and hides the visual glyphs from assistive technology.
17
+ * Use `+` within a chord and spaces between shortcuts (`"⌘K ⌘S"` becomes
18
+ * `"Meta+K Meta+S"`). Pass `aria-keyshortcuts` to override the translation.
19
+ * This does not bind the shortcut. */
16
20
  kbd?: string;
17
21
  /** A trailing icon. On a `submenu` item this **overrides** the default
18
22
  * chevron (omit it to keep the chevron); on a normal item it's the trailing
@@ -1,5 +1,70 @@
1
1
  import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
2
2
  import { toneStyle } from "../anta_helpers";
3
+ const SHORTCUT_KEYS = {
4
+ "\u2318": "Meta",
5
+ cmd: "Meta",
6
+ command: "Meta",
7
+ win: "Meta",
8
+ super: "Meta",
9
+ "\u2303": "Control",
10
+ ctrl: "Control",
11
+ control: "Control",
12
+ "\u2325": "Alt",
13
+ alt: "Alt",
14
+ opt: "Alt",
15
+ option: "Alt",
16
+ "\u21E7": "Shift",
17
+ shift: "Shift",
18
+ "\u21B5": "Enter",
19
+ "\u23CE": "Enter",
20
+ enter: "Enter",
21
+ return: "Enter",
22
+ "\u232B": "Backspace",
23
+ backspace: "Backspace",
24
+ "\u2326": "Delete",
25
+ del: "Delete",
26
+ delete: "Delete",
27
+ "\u238B": "Escape",
28
+ esc: "Escape",
29
+ escape: "Escape",
30
+ "\u21E5": "Tab",
31
+ tab: "Tab",
32
+ "\u2423": "Space",
33
+ space: "Space",
34
+ "\u2191": "ArrowUp",
35
+ "\u2193": "ArrowDown",
36
+ "\u2190": "ArrowLeft",
37
+ "\u2192": "ArrowRight",
38
+ "\u21DE": "PageUp",
39
+ "\u21DF": "PageDown",
40
+ "\u2196": "Home",
41
+ "\u2198": "End"
42
+ };
43
+ function shortcutChordLabel(kbd) {
44
+ const parts = [];
45
+ let word = "";
46
+ const flush = () => {
47
+ if (!word) return;
48
+ parts.push(SHORTCUT_KEYS[word.toLowerCase()] ?? (word.length === 1 ? word.toUpperCase() : word));
49
+ word = "";
50
+ };
51
+ for (const char of kbd) {
52
+ if (SHORTCUT_KEYS[char]) {
53
+ flush();
54
+ parts.push(SHORTCUT_KEYS[char]);
55
+ } else if (char === "+") {
56
+ flush();
57
+ } else {
58
+ word += char;
59
+ }
60
+ }
61
+ flush();
62
+ return parts.length ? parts.join("+") : void 0;
63
+ }
64
+ function shortcutLabel(kbd) {
65
+ const shortcuts = kbd.trim().replace(/\s*\+\s*/g, "+").split(/\s+/).map(shortcutChordLabel).filter((shortcut) => shortcut !== void 0);
66
+ return shortcuts.length ? shortcuts.join(" ") : void 0;
67
+ }
3
68
  const MenuItem = ({
4
69
  icon,
5
70
  label,
@@ -34,6 +99,9 @@ const MenuItem = ({
34
99
  const keepTint = selected && (selectionIndicator === void 0 || selectionIndicator === "check");
35
100
  const effectiveTone = selected && toneSelected || tone;
36
101
  const toneAttr = effectiveTone && effectiveTone !== "neutral" ? effectiveTone : void 0;
102
+ const declaredShortcuts = rest["aria-keyshortcuts"];
103
+ const keyShortcuts = kbd ? shortcutLabel(kbd) : void 0;
104
+ const kbdNode = kbd ? /* @__PURE__ */ jsx("kbd", { "aria-hidden": declaredShortcuts ?? keyShortcuts ? "true" : void 0, children: kbd }) : null;
37
105
  const labelNode = label != null && (hint != null ? /* @__PURE__ */ jsxs("a-menu-item-text", { children: [
38
106
  /* @__PURE__ */ jsx("a-menu-item-label", { children: label }),
39
107
  /* @__PURE__ */ jsx("a-menu-item-hint", { children: hint })
@@ -50,6 +118,7 @@ const MenuItem = ({
50
118
  tabIndex: disabled ? -1 : 0,
51
119
  "aria-disabled": disabled ? "true" : void 0,
52
120
  "aria-current": selected ? "true" : void 0,
121
+ "aria-keyshortcuts": keyShortcuts,
53
122
  tone: toneAttr,
54
123
  style: toneStyle(effectiveTone, "--menu-item-tone-source", style),
55
124
  onClick: onSelect && !disabled ? (e) => onSelect(e, { value, label }) : void 0,
@@ -59,7 +128,7 @@ const MenuItem = ({
59
128
  icon && /* @__PURE__ */ jsx("a-icon", { shape: icon, "aria-hidden": "true" }),
60
129
  labelNode,
61
130
  children,
62
- kbd && /* @__PURE__ */ jsx("kbd", { children: kbd }),
131
+ kbdNode,
63
132
  iconTrailing && /* @__PURE__ */ jsx("a-icon", { shape: iconTrailing, "aria-hidden": "true" })
64
133
  ] });
65
134
  }
@@ -76,6 +145,7 @@ const MenuItem = ({
76
145
  submenu: submenu ? "" : void 0,
77
146
  "aria-haspopup": submenu ? "menu" : void 0,
78
147
  "aria-disabled": disabled ? "true" : void 0,
148
+ "aria-keyshortcuts": keyShortcuts,
79
149
  onmenuselect: onSelect ? (e) => onSelect(e, { value, label }) : void 0,
80
150
  class: className,
81
151
  ...rest,
@@ -120,7 +190,7 @@ const MenuItem = ({
120
190
  leadingIcon && /* @__PURE__ */ jsx("a-icon", { shape: leadingIcon, "aria-hidden": "true" }),
121
191
  labelNode,
122
192
  children,
123
- kbd && /* @__PURE__ */ jsx("kbd", { children: kbd }),
193
+ kbdNode,
124
194
  (() => {
125
195
  let trailing = submenu ? iconTrailing ?? "chevron-right" : iconTrailing;
126
196
  if (!submenu && !iconTrailing && selectionIndicator === "check" && indicator == null)
@@ -11,12 +11,22 @@ export type MenuItemCopyProps = MenuItemCommonProps & MenuItemActionMode & {
11
11
  selectionIndicator?: never;
12
12
  indeterminate?: never;
13
13
  indicator?: never;
14
- } & CopyTarget;
14
+ iconTrailing?: never;
15
+ } & CopyTarget & {
16
+ /** Where the copy glyph sits relative to the label — or `'none'` to omit it.
17
+ * Without a glyph, a successful copy shows a confirmation label near the
18
+ * pointer and leaves the row unchanged.
19
+ * @defaultValue 'leading' */
20
+ iconPlacement?: 'leading' | 'trailing' | 'none';
21
+ /** Text in the successful no-icon confirmation.
22
+ * @defaultValue Copied */
23
+ copiedLabel?: string;
24
+ };
15
25
  /**
16
26
  * Copying menu item — a `MenuItem` preset for copy-to-clipboard rows inside a
17
27
  * `Menu`. Set `copy` for a literal string, `copyNode` to copy a DOM region, or
18
- * `copyUrl` to copy the current page URL. For content computed on demand, keep
19
- * `copy` reactive and refresh it in `onCopyRequest` (fired on pointerdown / keydown).
28
+ * `copyUrl` to copy the current page URL. For dynamic text, pass a controlled
29
+ * `copy` string and set it in `onCopyRequest` before activation.
20
30
  *
21
31
  * It composes a plain `<MenuItem>` with a slotted `<a-copy>` child that performs
22
32
  * the write when the row is chosen — the item itself carries no copy behavior.
@@ -24,7 +34,8 @@ export type MenuItemCopyProps = MenuItemCommonProps & MenuItemActionMode & {
24
34
  * flips the leading icon to a check / ✕ and retones for ~2s (see `useCopyFeedback`).
25
35
  *
26
36
  * Defaults `label` to "Copy" and the leading `icon` to `copy`; override either.
27
- * Other props pass through — `tone`, `kbd`, `onCopied`.
37
+ * `iconPlacement` moves that glyph to the trailing edge or omits it. Other props
38
+ * pass through — `tone`, `kbd`, `onCopied`.
28
39
  *
29
40
  * @example
30
41
  * ```tsx
@@ -34,4 +45,4 @@ export type MenuItemCopyProps = MenuItemCommonProps & MenuItemActionMode & {
34
45
  * </Menu>
35
46
  * ```
36
47
  */
37
- export declare const MenuItemCopy: ({ label, icon, tone, onCopied, onCopyRequest, copy, copyNode, copyUrl, copyWithUrl, children, ...rest }: MenuItemCopyProps) => any;
48
+ export declare const MenuItemCopy: ({ label, icon, iconPlacement, copiedLabel, tone, onCopied, onCopyRequest, copy, copyNode, copyUrl, copyWithUrl, children, ...rest }: MenuItemCopyProps) => any;