@antadesign/anta 0.3.10 → 0.3.12
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/components/Button.d.ts +4 -46
- package/dist/components/Button.js +7 -25
- package/dist/components/ButtonCopy.d.ts +45 -21
- package/dist/components/ButtonCopy.js +46 -4
- package/dist/components/Expander.js +1 -1
- package/dist/components/MenuItem.d.ts +2 -8
- package/dist/components/MenuItem.js +2 -14
- package/dist/components/MenuItemCopy.d.ts +23 -19
- package/dist/components/MenuItemCopy.js +38 -3
- package/dist/components/Select.d.ts +8 -0
- package/dist/components/Select.js +4 -0
- package/dist/components/SelectFaceted.d.ts +8 -0
- package/dist/components/SelectFaceted.js +4 -0
- package/dist/components/copy-props.d.ts +72 -0
- package/dist/components/copy-props.js +20 -0
- package/dist/elements/a-button.css +1 -1
- package/dist/elements/a-button.d.ts +0 -4
- package/dist/elements/a-button.js +7 -20
- package/dist/elements/a-copy.css +1 -0
- package/dist/elements/a-copy.d.ts +16 -0
- package/dist/elements/a-copy.js +148 -0
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.js +20 -19
- package/dist/elements/a-menu-item.d.ts +8 -1
- package/dist/elements/a-menu-item.js +7 -11
- package/dist/elements/a-menu.d.ts +6 -2
- package/dist/elements/a-menu.js +35 -5
- package/dist/elements/copy-behavior.d.ts +31 -13
- package/dist/elements/copy-behavior.js +20 -18
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/index.js +3 -0
- package/dist/elements/key-activation.d.ts +28 -0
- package/dist/elements/key-activation.js +32 -0
- package/dist/general_types.d.ts +27 -37
- package/dist/index.d.ts +2 -1
- package/dist/jsx-runtime.d.ts +2 -1
- package/package.json +1 -1
|
@@ -55,7 +55,8 @@ export type ContentMode = {
|
|
|
55
55
|
iconTrailing?: IconShape;
|
|
56
56
|
};
|
|
57
57
|
/** Submit axis — anchors (href) don't carry form-submission props; buttons
|
|
58
|
-
* don't carry anchor props.
|
|
58
|
+
* don't carry anchor props. (Copy is no longer a Button concern — `ButtonCopy`
|
|
59
|
+
* composes a `<a-copy>` child; see `copy-props.ts`.) */
|
|
59
60
|
export type SubmitMode = {
|
|
60
61
|
/** Renders as `<a role="button">` instead of `<a-button>`. */
|
|
61
62
|
href: string;
|
|
@@ -100,50 +101,7 @@ export type PriorityMode = {
|
|
|
100
101
|
/** Drops outer padding to zero. */
|
|
101
102
|
paddingless?: boolean;
|
|
102
103
|
};
|
|
103
|
-
|
|
104
|
-
* on click and flashes a success / failure state (see `<a-button>`'s copy
|
|
105
|
-
* behavior). **Exactly one** of `copy`, `copyNode`, or `copyLazy` may be set;
|
|
106
|
-
* the union makes the others `never` in each mode. For the batteries-included
|
|
107
|
-
* preset, use `ButtonCopy`. */
|
|
108
|
-
export type CopyMode = {
|
|
109
|
-
copy?: never;
|
|
110
|
-
copyNode?: never;
|
|
111
|
-
copyLazy?: never;
|
|
112
|
-
onCopied?: never;
|
|
113
|
-
onCopyRequest?: never;
|
|
114
|
-
} | {
|
|
115
|
-
/** Text copied to the clipboard on click. */
|
|
116
|
-
copy: string;
|
|
117
|
-
copyNode?: never;
|
|
118
|
-
copyLazy?: never;
|
|
119
|
-
onCopyRequest?: never;
|
|
120
|
-
/** Fires after the copy attempt with whether it succeeded. */
|
|
121
|
-
onCopied?: (ok: boolean) => void;
|
|
122
|
-
} | {
|
|
123
|
-
/** Copy a DOM node as rich text instead of a string. `true` copies the
|
|
124
|
-
* nearest ancestor marked `data-copy-source`; a string is a CSS selector
|
|
125
|
-
* for an ancestor region (`closest`). The copy control is stripped from
|
|
126
|
-
* the copied output. */
|
|
127
|
-
copyNode: boolean | string;
|
|
128
|
-
copy?: never;
|
|
129
|
-
copyLazy?: never;
|
|
130
|
-
onCopyRequest?: never;
|
|
131
|
-
/** Fires after the copy attempt with whether it succeeded. */
|
|
132
|
-
onCopied?: (ok: boolean) => void;
|
|
133
|
-
} | {
|
|
134
|
-
/** Lazy copy: the content isn't computed or held in the DOM until the
|
|
135
|
-
* click. The click fires `onCopyRequest(provide)`; call `provide(text)`
|
|
136
|
-
* with the value — synchronously, or after an `await` (the browser's
|
|
137
|
-
* transient-activation window still covers the write). */
|
|
138
|
-
copyLazy: true;
|
|
139
|
-
copy?: never;
|
|
140
|
-
copyNode?: never;
|
|
141
|
-
/** Supplies the lazily-computed content on click: call `provide(text)`. */
|
|
142
|
-
onCopyRequest: (provide: (text: string) => void) => void;
|
|
143
|
-
/** Fires after the copy attempt with whether it succeeded. */
|
|
144
|
-
onCopied?: (ok: boolean) => void;
|
|
145
|
-
};
|
|
146
|
-
export type ButtonProps = BaseButtonProps & PriorityMode & ContentMode & SubmitMode & CopyMode & BaseProps;
|
|
104
|
+
export type ButtonProps = BaseButtonProps & PriorityMode & ContentMode & SubmitMode & BaseProps;
|
|
147
105
|
/**
|
|
148
106
|
* Action button.
|
|
149
107
|
*
|
|
@@ -164,4 +122,4 @@ export type ButtonProps = BaseButtonProps & PriorityMode & ContentMode & SubmitM
|
|
|
164
122
|
* <Button href="/docs" target="_blank" label="Read the docs" />
|
|
165
123
|
* ```
|
|
166
124
|
*/
|
|
167
|
-
export declare const Button: ({ priority, tone, underline, icon, iconTrailing, paddingless, label, size, loading, disabled, selected, round, href, type, form,
|
|
125
|
+
export declare const Button: ({ priority, tone, underline, icon, iconTrailing, paddingless, label, size, loading, disabled, selected, round, href, type, form, className, style, children, ...rest }: ButtonProps) => any;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "@antadesign/anta/jsx-runtime";
|
|
2
|
-
import { toneStyle, roundStyle, roundAttr, wrapLabel
|
|
2
|
+
import { toneStyle, roundStyle, roundAttr, wrapLabel } from "../anta_helpers";
|
|
3
3
|
const Button = ({
|
|
4
4
|
priority,
|
|
5
5
|
tone,
|
|
@@ -16,21 +16,14 @@ const Button = ({
|
|
|
16
16
|
href,
|
|
17
17
|
type,
|
|
18
18
|
form,
|
|
19
|
-
copy,
|
|
20
|
-
copyNode,
|
|
21
|
-
copyLazy,
|
|
22
|
-
onCopied,
|
|
23
|
-
onCopyRequest,
|
|
24
19
|
className,
|
|
25
20
|
style,
|
|
26
21
|
children,
|
|
27
22
|
...rest
|
|
28
23
|
}) => {
|
|
29
|
-
const isCopy = copy != null || copyNode != null || copyLazy === true;
|
|
30
24
|
const toneAttr = tone || void 0;
|
|
31
25
|
const computedStyle = roundStyle(round, "--button-round", toneStyle(toneAttr, "--button-tone-source", style));
|
|
32
|
-
const
|
|
33
|
-
const isIconOnly = leadingIcon != null && label == null && children == null && iconTrailing == null;
|
|
26
|
+
const isIconOnly = icon != null && label == null && children == null && iconTrailing == null;
|
|
34
27
|
const sharedAttrs = {
|
|
35
28
|
// `<a-button>` is a custom element with no implicit ARIA role, so AT would
|
|
36
29
|
// announce it as a generic clickable — and `aria-pressed` below is only
|
|
@@ -60,26 +53,15 @@ const Button = ({
|
|
|
60
53
|
"aria-disabled": disabled || loading ? "true" : void 0,
|
|
61
54
|
"aria-busy": loading ? "true" : void 0,
|
|
62
55
|
"aria-pressed": selected ? "true" : void 0,
|
|
63
|
-
// Icon-only buttons get an accessible name
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
"aria-label": isIconOnly ?
|
|
67
|
-
// Copy behavior — the element reads these and performs the write itself.
|
|
68
|
-
copy: copy != null ? copy : void 0,
|
|
69
|
-
"copy-node": copyNode === true ? "" : typeof copyNode === "string" ? copyNode : void 0,
|
|
70
|
-
"copy-lazy": copyLazy ? "" : void 0,
|
|
71
|
-
// Marks the control so `copy-node` serialization strips it from the copied
|
|
72
|
-
// node (a copy button inside the copied region shouldn't paste itself).
|
|
73
|
-
"data-copy-node-button": copyNode != null && copyNode !== false ? "" : void 0,
|
|
74
|
-
oncopydone: onCopied ? (e) => onCopied(nativeStateChange(e).detail?.ok ?? false) : void 0,
|
|
75
|
-
// The element hands `provide` on the request event; forward it so the
|
|
76
|
-
// consumer supplies the lazily-computed content.
|
|
77
|
-
oncopyrequest: onCopyRequest ? (e) => onCopyRequest(nativeStateChange(e).detail.provide) : void 0,
|
|
56
|
+
// Icon-only buttons get an accessible name from the icon shape. Consumer's
|
|
57
|
+
// own `aria-label` (via ...rest) wins by spread order — that's the channel
|
|
58
|
+
// ButtonCopy uses to name an icon-only copy button "Copy".
|
|
59
|
+
"aria-label": isIconOnly ? icon : void 0,
|
|
78
60
|
class: className,
|
|
79
61
|
style: computedStyle
|
|
80
62
|
};
|
|
81
63
|
const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
82
|
-
|
|
64
|
+
icon && /* @__PURE__ */ jsx("a-icon", { shape: icon, "aria-hidden": "true" }),
|
|
83
65
|
label != null && /* @__PURE__ */ jsx("a-button-label", { children: label }),
|
|
84
66
|
wrapLabel(children, "a-button-label"),
|
|
85
67
|
iconTrailing && /* @__PURE__ */ jsx("a-icon", { shape: iconTrailing, "aria-hidden": "true" })
|
|
@@ -1,32 +1,56 @@
|
|
|
1
1
|
import { type ButtonProps } from './Button';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
import { type CopyTarget } from './copy-props';
|
|
3
|
+
/** A copy button is a plain action control, so `ButtonCopy` keeps the `Button`
|
|
4
|
+
* axes that fit — tone / size / priority styling, `disabled` / `loading`, a
|
|
5
|
+
* leading `icon` + `label` — and pins the ones that don't to `never`: `selected`
|
|
6
|
+
* (it isn't a toggle), the whole submit/link axis (`href` / `target` / `rel` /
|
|
7
|
+
* `download` / `ping` / `type` / `form` — a copy button neither navigates nor
|
|
8
|
+
* submits), and the public `iconTrailing` (the glyph's side is `iconPlacement`'s
|
|
9
|
+
* job). Plus a required copy target and the placement knob. (Pinning to `never`
|
|
10
|
+
* keeps the intersection expanding fully in the docs props table, which `Omit`
|
|
11
|
+
* wouldn't.) */
|
|
12
|
+
export type ButtonCopyProps = ButtonProps & {
|
|
13
|
+
selected?: never;
|
|
14
|
+
href?: never;
|
|
15
|
+
target?: never;
|
|
16
|
+
rel?: never;
|
|
17
|
+
download?: never;
|
|
18
|
+
ping?: never;
|
|
19
|
+
type?: never;
|
|
20
|
+
form?: never;
|
|
21
|
+
iconTrailing?: never;
|
|
22
|
+
} & CopyTarget & {
|
|
23
|
+
/** Where the copy glyph sits relative to the label — or `'none'` to omit it,
|
|
24
|
+
* in which case the feedback is a ghost of the label floating up (`toast`)
|
|
25
|
+
* plus a brief success / failure tone flash.
|
|
26
|
+
* @defaultValue 'leading' */
|
|
27
|
+
iconPlacement?: 'leading' | 'trailing' | 'none';
|
|
28
|
+
};
|
|
12
29
|
/**
|
|
13
30
|
* Copy button — a `Button` preset for copy-to-clipboard. Set `copy` for a literal
|
|
14
|
-
* string, `copyNode` to copy a DOM region, or `
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* ✕ (failure) and retones to `success` / `critical` for ~2s — a JSX re-render, no
|
|
18
|
-
* element state (see `useCopyFeedback`).
|
|
31
|
+
* string, `copyNode` to copy a DOM region, or `copyUrl` to copy the current page
|
|
32
|
+
* URL. For content computed on demand, keep `copy` reactive and refresh it in
|
|
33
|
+
* `onCopyRequest` (fired on pointerdown / keydown).
|
|
19
34
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* (
|
|
35
|
+
* It composes a plain `<Button>` with a slotted `<a-copy>` child that performs
|
|
36
|
+
* the write — the button itself carries no copy behavior. This wrapper flips the
|
|
37
|
+
* copy glyph to a check (success) or ✕ (failure) and retones to `success` /
|
|
38
|
+
* `critical` for ~2s (a re-render, no element state — see `useCopyFeedback`).
|
|
39
|
+
* `iconPlacement` puts that glyph leading (default), trailing, or `'none'`; with
|
|
40
|
+
* `'none'` the `<a-copy>` floats a ghost of the label upward instead.
|
|
41
|
+
*
|
|
42
|
+
* With a `label` it's a labeled button; without one it's an icon-only copy button
|
|
43
|
+
* (named "Copy" for assistive tech). Everything else is a normal `Button` prop —
|
|
44
|
+
* `tone`, `priority`, `size`, `icon` (the resting glyph), `onCopied`.
|
|
23
45
|
*
|
|
24
46
|
* @example
|
|
25
47
|
* ```tsx
|
|
26
48
|
* <ButtonCopy copy="npm i @antadesign/anta" label="Copy install" />
|
|
27
|
-
* <ButtonCopy copy="https://anta.design" />
|
|
49
|
+
* <ButtonCopy copy="https://anta.design" /> // icon-only
|
|
50
|
+
* <ButtonCopy copy={code} label="Copy" iconPlacement="trailing" />
|
|
51
|
+
* <ButtonCopy copy={code} label="Copy snippet" iconPlacement="none" /> // ghost feedback
|
|
28
52
|
* <ButtonCopy copyNode=".snippet" label="Copy block" priority="tertiary" />
|
|
29
|
-
* <ButtonCopy
|
|
53
|
+
* <ButtonCopy copyUrl label="Copy link" /> // copies location.href
|
|
30
54
|
* ```
|
|
31
55
|
*/
|
|
32
|
-
export declare const ButtonCopy: ({ icon, tone, onCopied, ...rest }: ButtonCopyProps) => any;
|
|
56
|
+
export declare const ButtonCopy: ({ icon, iconPlacement, tone, onCopied, onCopyRequest, copy, copyNode, copyUrl, copyWithUrl, label, children, "aria-label": ariaLabel, ...rest }: ButtonCopyProps) => any;
|
|
@@ -1,9 +1,51 @@
|
|
|
1
|
-
import { jsx } from "@antadesign/anta/jsx-runtime";
|
|
1
|
+
import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
|
|
2
2
|
import { Button } from "./Button";
|
|
3
3
|
import { useCopyFeedback } from "../anta_helpers";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { copyElementProps, isNodeCopy } from "./copy-props";
|
|
5
|
+
const ButtonCopy = ({
|
|
6
|
+
icon,
|
|
7
|
+
iconPlacement = "leading",
|
|
8
|
+
tone,
|
|
9
|
+
onCopied,
|
|
10
|
+
onCopyRequest,
|
|
11
|
+
copy,
|
|
12
|
+
copyNode,
|
|
13
|
+
copyUrl,
|
|
14
|
+
copyWithUrl,
|
|
15
|
+
label,
|
|
16
|
+
children,
|
|
17
|
+
"aria-label": ariaLabel,
|
|
18
|
+
...rest
|
|
19
|
+
}) => {
|
|
20
|
+
const restingIcon = iconPlacement === "none" ? void 0 : icon ?? "copy";
|
|
21
|
+
const { shownIcon, shownTone, handleCopied } = useCopyFeedback(restingIcon, tone, onCopied);
|
|
22
|
+
const iconSlot = iconPlacement === "trailing" ? { iconTrailing: shownIcon } : iconPlacement === "none" ? {} : { icon: shownIcon };
|
|
23
|
+
const hasText = label != null || children != null;
|
|
24
|
+
const copyAttrs = copyElementProps({
|
|
25
|
+
copy,
|
|
26
|
+
copyNode,
|
|
27
|
+
copyUrl,
|
|
28
|
+
copyWithUrl,
|
|
29
|
+
onCopyRequest,
|
|
30
|
+
onCopied: handleCopied,
|
|
31
|
+
// Ghost feedback only makes sense when there's no glyph to swap.
|
|
32
|
+
toast: iconPlacement === "none"
|
|
33
|
+
});
|
|
34
|
+
return /* @__PURE__ */ jsxs(
|
|
35
|
+
Button,
|
|
36
|
+
{
|
|
37
|
+
...iconSlot,
|
|
38
|
+
label,
|
|
39
|
+
tone: shownTone,
|
|
40
|
+
"aria-label": ariaLabel ?? (hasText ? void 0 : "Copy"),
|
|
41
|
+
"data-copy-node-button": isNodeCopy({ copyNode }) ? "" : void 0,
|
|
42
|
+
...rest,
|
|
43
|
+
children: [
|
|
44
|
+
children,
|
|
45
|
+
/* @__PURE__ */ jsx("a-copy", { ...copyAttrs })
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
);
|
|
7
49
|
};
|
|
8
50
|
export {
|
|
9
51
|
ButtonCopy
|
|
@@ -44,7 +44,7 @@ const Expander = ({
|
|
|
44
44
|
...rest,
|
|
45
45
|
children: [
|
|
46
46
|
titleNode,
|
|
47
|
-
actions != null && /* @__PURE__ */ jsx("span", { slot: "actions",
|
|
47
|
+
actions != null && /* @__PURE__ */ jsx("span", { slot: "actions", children: actions }),
|
|
48
48
|
/* @__PURE__ */ jsx("a-expander-details", { children })
|
|
49
49
|
]
|
|
50
50
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { BaseProps } from '../general_types';
|
|
2
2
|
import type { IconShape } from '../elements/a-icon.shapes';
|
|
3
|
-
import type { CopyMode } from './Button';
|
|
4
3
|
/** Props shared by every menu item, link or not. */
|
|
5
4
|
export interface MenuItemCommonProps extends BaseProps {
|
|
6
5
|
/** Leading icon shape. */
|
|
@@ -84,11 +83,6 @@ export type MenuItemLinkMode = {
|
|
|
84
83
|
selectionIndicator?: never;
|
|
85
84
|
indeterminate?: never;
|
|
86
85
|
indicator?: never;
|
|
87
|
-
copy?: never;
|
|
88
|
-
copyNode?: never;
|
|
89
|
-
copyLazy?: never;
|
|
90
|
-
onCopied?: never;
|
|
91
|
-
onCopyRequest?: never;
|
|
92
86
|
};
|
|
93
87
|
export type MenuItemActionMode = {
|
|
94
88
|
href?: never;
|
|
@@ -120,7 +114,7 @@ export type MenuItemActionMode = {
|
|
|
120
114
|
* passive (aria-hidden, no pointer events) so the row owns the click. */
|
|
121
115
|
indicator?: React.ReactNode;
|
|
122
116
|
};
|
|
123
|
-
export type MenuItemProps = MenuItemCommonProps & (MenuItemLinkMode |
|
|
117
|
+
export type MenuItemProps = MenuItemCommonProps & (MenuItemLinkMode | MenuItemActionMode);
|
|
124
118
|
/**
|
|
125
119
|
* MenuItem — a single selectable row inside a `Menu`. Composes a leading
|
|
126
120
|
* `icon`, a `label` (or `children`), an optional trailing `kbd` hint, and an
|
|
@@ -141,4 +135,4 @@ export type MenuItemProps = MenuItemCommonProps & (MenuItemLinkMode | (MenuItemA
|
|
|
141
135
|
* </MenuItem>
|
|
142
136
|
* ```
|
|
143
137
|
*/
|
|
144
|
-
export declare const MenuItem: ({ icon, label, hint, kbd, iconTrailing, disabled, selected, selectionIndicator, indeterminate, indicator, tone, toneSelected, submenu, value, onSelect, href, target, rel, download, ping,
|
|
138
|
+
export declare const MenuItem: ({ icon, label, hint, kbd, iconTrailing, disabled, selected, selectionIndicator, indeterminate, indicator, tone, toneSelected, submenu, value, onSelect, href, target, rel, download, ping, role: roleOverride, className, style, children, ...rest }: MenuItemProps) => any;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
|
|
2
|
-
import { toneStyle
|
|
2
|
+
import { toneStyle } from "../anta_helpers";
|
|
3
3
|
const MenuItem = ({
|
|
4
4
|
icon,
|
|
5
5
|
label,
|
|
@@ -21,19 +21,13 @@ const MenuItem = ({
|
|
|
21
21
|
rel,
|
|
22
22
|
download,
|
|
23
23
|
ping,
|
|
24
|
-
copy,
|
|
25
|
-
copyNode,
|
|
26
|
-
copyLazy,
|
|
27
|
-
onCopied,
|
|
28
|
-
onCopyRequest,
|
|
29
24
|
role: roleOverride,
|
|
30
25
|
className,
|
|
31
26
|
style,
|
|
32
27
|
children,
|
|
33
28
|
...rest
|
|
34
29
|
}) => {
|
|
35
|
-
const
|
|
36
|
-
const leadingIcon = icon ?? (isCopy ? "copy" : void 0);
|
|
30
|
+
const leadingIcon = icon;
|
|
37
31
|
const checkable = selectionIndicator === "checkbox" || selectionIndicator === "radio" || selectionIndicator === "check";
|
|
38
32
|
const role = selectionIndicator === "checkbox" ? "menuitemcheckbox" : selectionIndicator === "radio" || selectionIndicator === "check" ? "menuitemradio" : "menuitem";
|
|
39
33
|
const ariaChecked = !checkable ? void 0 : selectionIndicator === "checkbox" && indeterminate ? "mixed" : selected ? "true" : "false";
|
|
@@ -83,12 +77,6 @@ const MenuItem = ({
|
|
|
83
77
|
"aria-haspopup": submenu ? "menu" : void 0,
|
|
84
78
|
"aria-disabled": disabled ? "true" : void 0,
|
|
85
79
|
onmenuselect: onSelect ? (e) => onSelect(e, { value, label }) : void 0,
|
|
86
|
-
copy: copy != null ? copy : void 0,
|
|
87
|
-
"copy-node": copyNode === true ? "" : typeof copyNode === "string" ? copyNode : void 0,
|
|
88
|
-
"copy-lazy": copyLazy ? "" : void 0,
|
|
89
|
-
"data-copy-node-button": copyNode != null && copyNode !== false ? "" : void 0,
|
|
90
|
-
oncopydone: onCopied ? (e) => onCopied(nativeStateChange(e).detail?.ok ?? false) : void 0,
|
|
91
|
-
oncopyrequest: onCopyRequest ? (e) => onCopyRequest(nativeStateChange(e).detail.provide) : void 0,
|
|
92
80
|
class: className,
|
|
93
81
|
...rest,
|
|
94
82
|
children: [
|
|
@@ -1,33 +1,37 @@
|
|
|
1
1
|
import { type MenuItemCommonProps, type MenuItemActionMode } from './MenuItem';
|
|
2
|
-
import type
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
import { type CopyTarget } from './copy-props';
|
|
3
|
+
/** Action-mode menu-item props plus a required copy target (a copying row must
|
|
4
|
+
* copy something). The action-mode props that don't fit a copy row are pinned to
|
|
5
|
+
* `never`: `submenu` (a copy row has no flyout) and the selection-indicator axis
|
|
6
|
+
* (`selectionIndicator` / `indeterminate` / `indicator` — a copy row isn't a
|
|
7
|
+
* checkable option). Pinning (not `Omit`) keeps the intersection expanding fully
|
|
8
|
+
* in the docs props table. */
|
|
9
|
+
export type MenuItemCopyProps = MenuItemCommonProps & MenuItemActionMode & {
|
|
10
|
+
submenu?: never;
|
|
11
|
+
selectionIndicator?: never;
|
|
12
|
+
indeterminate?: never;
|
|
13
|
+
indicator?: never;
|
|
14
|
+
} & CopyTarget;
|
|
13
15
|
/**
|
|
14
16
|
* Copying menu item — a `MenuItem` preset for copy-to-clipboard rows inside a
|
|
15
17
|
* `Menu`. Set `copy` for a literal string, `copyNode` to copy a DOM region, or
|
|
16
|
-
* `
|
|
17
|
-
*
|
|
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).
|
|
20
|
+
*
|
|
21
|
+
* It composes a plain `<MenuItem>` with a slotted `<a-copy>` child that performs
|
|
22
|
+
* the write when the row is chosen — the item itself carries no copy behavior.
|
|
23
|
+
* The row is kept open (`data-menu-open`) so the feedback shows: this wrapper
|
|
18
24
|
* flips the leading icon to a check / ✕ and retones for ~2s (see `useCopyFeedback`).
|
|
19
25
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* `icon` to `copy`; override either. Other props pass through — `tone`, `kbd`,
|
|
23
|
-
* `onCopied`.
|
|
26
|
+
* Defaults `label` to "Copy" and the leading `icon` to `copy`; override either.
|
|
27
|
+
* Other props pass through — `tone`, `kbd`, `onCopied`.
|
|
24
28
|
*
|
|
25
29
|
* @example
|
|
26
30
|
* ```tsx
|
|
27
31
|
* <Menu>
|
|
28
32
|
* <MenuItemCopy copy={shareUrl} label="Copy link" kbd="⌘C" />
|
|
29
|
-
* <MenuItemCopy copyNode=".invoice" label="Copy invoice"
|
|
33
|
+
* <MenuItemCopy copyNode=".invoice" label="Copy invoice" />
|
|
30
34
|
* </Menu>
|
|
31
35
|
* ```
|
|
32
36
|
*/
|
|
33
|
-
export declare const MenuItemCopy: ({ label, icon, tone, onCopied, ...rest }: MenuItemCopyProps) => any;
|
|
37
|
+
export declare const MenuItemCopy: ({ label, icon, tone, onCopied, onCopyRequest, copy, copyNode, copyUrl, copyWithUrl, children, ...rest }: MenuItemCopyProps) => any;
|
|
@@ -1,9 +1,44 @@
|
|
|
1
|
-
import { jsx } from "@antadesign/anta/jsx-runtime";
|
|
1
|
+
import { jsx, jsxs } from "@antadesign/anta/jsx-runtime";
|
|
2
2
|
import { MenuItem } from "./MenuItem";
|
|
3
3
|
import { useCopyFeedback } from "../anta_helpers";
|
|
4
|
-
|
|
4
|
+
import { copyElementProps, isNodeCopy } from "./copy-props";
|
|
5
|
+
const MenuItemCopy = ({
|
|
6
|
+
label = "Copy",
|
|
7
|
+
icon = "copy",
|
|
8
|
+
tone,
|
|
9
|
+
onCopied,
|
|
10
|
+
onCopyRequest,
|
|
11
|
+
copy,
|
|
12
|
+
copyNode,
|
|
13
|
+
copyUrl,
|
|
14
|
+
copyWithUrl,
|
|
15
|
+
children,
|
|
16
|
+
...rest
|
|
17
|
+
}) => {
|
|
5
18
|
const { shownIcon, shownTone, handleCopied } = useCopyFeedback(icon, tone, onCopied);
|
|
6
|
-
|
|
19
|
+
const copyAttrs = copyElementProps({
|
|
20
|
+
copy,
|
|
21
|
+
copyNode,
|
|
22
|
+
copyUrl,
|
|
23
|
+
copyWithUrl,
|
|
24
|
+
onCopyRequest,
|
|
25
|
+
onCopied: handleCopied
|
|
26
|
+
});
|
|
27
|
+
return /* @__PURE__ */ jsxs(
|
|
28
|
+
MenuItem,
|
|
29
|
+
{
|
|
30
|
+
label,
|
|
31
|
+
icon: shownIcon,
|
|
32
|
+
tone: shownTone,
|
|
33
|
+
"data-menu-open": "",
|
|
34
|
+
"data-copy-node-button": isNodeCopy({ copyNode }) ? "" : void 0,
|
|
35
|
+
...rest,
|
|
36
|
+
children: [
|
|
37
|
+
children,
|
|
38
|
+
/* @__PURE__ */ jsx("a-copy", { ...copyAttrs })
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
);
|
|
7
42
|
};
|
|
8
43
|
export {
|
|
9
44
|
MenuItemCopy
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BaseProps } from '../general_types';
|
|
2
2
|
import type { IconShape } from '../elements/a-icon.shapes';
|
|
3
|
+
import { type MenuProps } from './Menu';
|
|
3
4
|
/** One option in a `<Select>`. Pass a bare string as shorthand for
|
|
4
5
|
* `{ value: s, label: s }`. Carries an index signature so you can attach
|
|
5
6
|
* arbitrary fields (a `ranAt` date, a `status`, …) and read them back in
|
|
@@ -131,6 +132,13 @@ export interface SelectCommonProps extends Omit<BaseProps, 'children'> {
|
|
|
131
132
|
* logical pick (both rows toggle together; the trigger resolves to the last). Dev
|
|
132
133
|
* builds `console.warn` on a duplicate. */
|
|
133
134
|
options: SelectItem[];
|
|
135
|
+
/** Preferred placement of the options menu relative to the trigger. The menu
|
|
136
|
+
* auto-flips vertically and clamps horizontally when needed.
|
|
137
|
+
* @defaultValue bottom-start */
|
|
138
|
+
placement?: MenuProps['placement'];
|
|
139
|
+
/** Gap in pixels between the trigger and the options menu.
|
|
140
|
+
* @defaultValue 4 */
|
|
141
|
+
offset?: number;
|
|
134
142
|
/** The per-row mark for **single**-select: `'none'` (a tint-only highlight),
|
|
135
143
|
* `'check'` (a trailing checkmark on the selected row, keeping the tint — the
|
|
136
144
|
* canonical Select look), or `'radio'` (a leading radio on every row).
|
|
@@ -37,6 +37,8 @@ function optionsWithSelection(options, values) {
|
|
|
37
37
|
const Select = (props) => {
|
|
38
38
|
const {
|
|
39
39
|
options,
|
|
40
|
+
placement,
|
|
41
|
+
offset,
|
|
40
42
|
selection,
|
|
41
43
|
indicator,
|
|
42
44
|
value,
|
|
@@ -274,6 +276,8 @@ const Select = (props) => {
|
|
|
274
276
|
/* @__PURE__ */ jsxs(
|
|
275
277
|
Menu,
|
|
276
278
|
{
|
|
279
|
+
placement,
|
|
280
|
+
offset,
|
|
277
281
|
onStateChange: (_e, { next }) => {
|
|
278
282
|
setOpen(next);
|
|
279
283
|
if (!next) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { BaseProps } from '../general_types';
|
|
2
2
|
import type { IconShape } from '../elements/a-icon.shapes';
|
|
3
3
|
import type { SelectItem, SelectOption } from './Select';
|
|
4
|
+
import { type MenuProps } from './Menu';
|
|
4
5
|
interface FacetBase {
|
|
5
6
|
/** The facet's namespace — the key its value is stored under in the value
|
|
6
7
|
* record, and what `onValueChange`'s `attrs.facet` reports. Unique across
|
|
@@ -108,6 +109,13 @@ export interface SelectFacetedTriggerState {
|
|
|
108
109
|
export interface SelectFacetedProps extends Omit<BaseProps, 'children'> {
|
|
109
110
|
/** The facets (dimensions) to filter across, each with its own editor kind. */
|
|
110
111
|
facets: SelectFacet[];
|
|
112
|
+
/** Preferred placement of the root filter menu relative to its trigger. The
|
|
113
|
+
* menu auto-flips vertically and clamps horizontally when needed.
|
|
114
|
+
* @defaultValue bottom-start */
|
|
115
|
+
placement?: MenuProps['placement'];
|
|
116
|
+
/** Gap in pixels between the trigger and the filter menu.
|
|
117
|
+
* @defaultValue 4 */
|
|
118
|
+
offset?: number;
|
|
111
119
|
/** Controlled value — the facet-keyed record. When provided, the consumer
|
|
112
120
|
* owns state: a pick only *requests* a change via `onValueChange` (reject by
|
|
113
121
|
* not updating). Leave undefined for uncontrolled. */
|
|
@@ -27,6 +27,8 @@ const defaultMatch = (o, query) => matchesQuery(o, matchQueryRegex(query));
|
|
|
27
27
|
const SelectFaceted = (props) => {
|
|
28
28
|
const {
|
|
29
29
|
facets,
|
|
30
|
+
placement,
|
|
31
|
+
offset,
|
|
30
32
|
value,
|
|
31
33
|
defaultValue,
|
|
32
34
|
onValueChange,
|
|
@@ -284,6 +286,8 @@ const SelectFaceted = (props) => {
|
|
|
284
286
|
/* @__PURE__ */ jsxs(
|
|
285
287
|
Menu,
|
|
286
288
|
{
|
|
289
|
+
placement,
|
|
290
|
+
offset,
|
|
287
291
|
open,
|
|
288
292
|
onStateChange: (_e, { next }) => {
|
|
289
293
|
setOpen(next);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The copy target for a copy preset (`ButtonCopy` / `MenuItemCopy`) — exactly
|
|
3
|
+
* one of a literal string, a DOM region, or the page URL. The write itself is
|
|
4
|
+
* performed by the slotted `<a-copy>` element; these props map to its attributes
|
|
5
|
+
* via `copyElementProps`. `copyWithUrl` / `onCopyRequest` are only meaningful for
|
|
6
|
+
* the string target, so the union pins them `never` elsewhere.
|
|
7
|
+
*/
|
|
8
|
+
export type CopyTarget = {
|
|
9
|
+
/** Text copied to the clipboard on activation. */
|
|
10
|
+
copy: string;
|
|
11
|
+
/** Prefix the copied text with `// URL: <current page URL>`. */
|
|
12
|
+
copyWithUrl?: boolean;
|
|
13
|
+
/** Compute the copy content lazily. Fires on pointerdown / keydown; update
|
|
14
|
+
* `copy` (a state change) here and the activation copies the latest value.
|
|
15
|
+
* The gap lets the update land even off the UI thread — only the
|
|
16
|
+
* serializable `copy` string crosses. */
|
|
17
|
+
onCopyRequest?: () => void;
|
|
18
|
+
/** Fires after the copy attempt with whether it succeeded. */
|
|
19
|
+
onCopied?: (ok: boolean) => void;
|
|
20
|
+
copyNode?: never;
|
|
21
|
+
copyUrl?: never;
|
|
22
|
+
} | {
|
|
23
|
+
/** Copy a DOM node as rich text (`text/html`) + plain text. `true` copies
|
|
24
|
+
* the nearest ancestor marked `data-copy-source`; a string is a CSS
|
|
25
|
+
* selector for an ancestor region (`closest`). The copy control is stripped
|
|
26
|
+
* from the copied output. */
|
|
27
|
+
copyNode: boolean | string;
|
|
28
|
+
/** Fires after the copy attempt with whether it succeeded. */
|
|
29
|
+
onCopied?: (ok: boolean) => void;
|
|
30
|
+
copy?: never;
|
|
31
|
+
copyUrl?: never;
|
|
32
|
+
copyWithUrl?: never;
|
|
33
|
+
onCopyRequest?: never;
|
|
34
|
+
} | {
|
|
35
|
+
/** Copy the current page URL (`location.href`). */
|
|
36
|
+
copyUrl: true;
|
|
37
|
+
/** Fires after the copy attempt with whether it succeeded. */
|
|
38
|
+
onCopied?: (ok: boolean) => void;
|
|
39
|
+
copy?: never;
|
|
40
|
+
copyNode?: never;
|
|
41
|
+
copyWithUrl?: never;
|
|
42
|
+
onCopyRequest?: never;
|
|
43
|
+
};
|
|
44
|
+
/** Everything `copyElementProps` reads: the target plus the resolved `onCopied`
|
|
45
|
+
* (the preset passes its feedback-wrapped handler) and the `toast` opt-in. */
|
|
46
|
+
type CopyElementInput = {
|
|
47
|
+
copy?: string;
|
|
48
|
+
copyNode?: boolean | string;
|
|
49
|
+
copyUrl?: true;
|
|
50
|
+
copyWithUrl?: boolean;
|
|
51
|
+
onCopyRequest?: () => void;
|
|
52
|
+
onCopied?: (ok: boolean) => void;
|
|
53
|
+
toast?: boolean;
|
|
54
|
+
};
|
|
55
|
+
/** Project the copy-target props onto `<a-copy>` attributes + event handlers.
|
|
56
|
+
* Shared by `ButtonCopy` / `MenuItemCopy` so the mapping (and the cross-renderer
|
|
57
|
+
* `copydone` detail unwrap) lives in one place. */
|
|
58
|
+
export declare function copyElementProps(p: CopyElementInput): {
|
|
59
|
+
readonly copy: string | undefined;
|
|
60
|
+
readonly 'copy-node': string | undefined;
|
|
61
|
+
readonly 'copy-url': "" | undefined;
|
|
62
|
+
readonly 'copy-with-url': "" | undefined;
|
|
63
|
+
readonly toast: "" | undefined;
|
|
64
|
+
readonly oncopydone: ((e: any) => void) | undefined;
|
|
65
|
+
readonly oncopyrequest: (() => void) | undefined;
|
|
66
|
+
};
|
|
67
|
+
/** True when these props copy a DOM node — the host control must then be marked
|
|
68
|
+
* `data-copy-node-button` so the serializer strips it from the copied region. */
|
|
69
|
+
export declare function isNodeCopy(p: {
|
|
70
|
+
copyNode?: boolean | string;
|
|
71
|
+
}): boolean;
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { nativeStateChange } from "../anta_helpers";
|
|
2
|
+
function copyElementProps(p) {
|
|
3
|
+
const { copy, copyNode, copyUrl, copyWithUrl, onCopyRequest, onCopied, toast } = p;
|
|
4
|
+
return {
|
|
5
|
+
copy: copy != null ? copy : void 0,
|
|
6
|
+
"copy-node": copyNode === true ? "" : typeof copyNode === "string" ? copyNode : void 0,
|
|
7
|
+
"copy-url": copyUrl ? "" : void 0,
|
|
8
|
+
"copy-with-url": copyWithUrl ? "" : void 0,
|
|
9
|
+
toast: toast ? "" : void 0,
|
|
10
|
+
oncopydone: onCopied ? (e) => onCopied(nativeStateChange(e).detail?.ok ?? false) : void 0,
|
|
11
|
+
oncopyrequest: onCopyRequest ? () => onCopyRequest() : void 0
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function isNodeCopy(p) {
|
|
15
|
+
return p.copyNode != null && p.copyNode !== false;
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
copyElementProps,
|
|
19
|
+
isNodeCopy
|
|
20
|
+
};
|