@ansh-ui/react 0.2.0
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 +21 -0
- package/dist/chunk-5CFQFMP5.js +178 -0
- package/dist/chunk-5CFQFMP5.js.map +1 -0
- package/dist/chunk-6VRF7X5C.cjs +164 -0
- package/dist/chunk-6VRF7X5C.cjs.map +1 -0
- package/dist/chunk-AVPEA5PB.cjs +718 -0
- package/dist/chunk-AVPEA5PB.cjs.map +1 -0
- package/dist/chunk-C32LKF23.cjs +198 -0
- package/dist/chunk-C32LKF23.cjs.map +1 -0
- package/dist/chunk-C5JG6TMM.cjs +1200 -0
- package/dist/chunk-C5JG6TMM.cjs.map +1 -0
- package/dist/chunk-DATBU46V.cjs +614 -0
- package/dist/chunk-DATBU46V.cjs.map +1 -0
- package/dist/chunk-EGG4CP7C.js +320 -0
- package/dist/chunk-EGG4CP7C.js.map +1 -0
- package/dist/chunk-H34OXXJU.js +55 -0
- package/dist/chunk-H34OXXJU.js.map +1 -0
- package/dist/chunk-HO2YSF5O.js +187 -0
- package/dist/chunk-HO2YSF5O.js.map +1 -0
- package/dist/chunk-HPGCILO4.js +760 -0
- package/dist/chunk-HPGCILO4.js.map +1 -0
- package/dist/chunk-IBXLC5IE.js +154 -0
- package/dist/chunk-IBXLC5IE.js.map +1 -0
- package/dist/chunk-LDCZQP3R.js +1185 -0
- package/dist/chunk-LDCZQP3R.js.map +1 -0
- package/dist/chunk-LXCIXR5T.js +27 -0
- package/dist/chunk-LXCIXR5T.js.map +1 -0
- package/dist/chunk-O2PX54KX.js +94 -0
- package/dist/chunk-O2PX54KX.js.map +1 -0
- package/dist/chunk-OHBWBXLO.cjs +101 -0
- package/dist/chunk-OHBWBXLO.cjs.map +1 -0
- package/dist/chunk-OJN5JBNP.cjs +776 -0
- package/dist/chunk-OJN5JBNP.cjs.map +1 -0
- package/dist/chunk-OLTS6G5M.js +606 -0
- package/dist/chunk-OLTS6G5M.js.map +1 -0
- package/dist/chunk-PO5DU3FU.cjs +29 -0
- package/dist/chunk-PO5DU3FU.cjs.map +1 -0
- package/dist/chunk-QO3E7TJS.js +2940 -0
- package/dist/chunk-QO3E7TJS.js.map +1 -0
- package/dist/chunk-RHTLNSVW.cjs +2976 -0
- package/dist/chunk-RHTLNSVW.cjs.map +1 -0
- package/dist/chunk-SFU5EPSN.cjs +61 -0
- package/dist/chunk-SFU5EPSN.cjs.map +1 -0
- package/dist/chunk-T4AK2KLM.js +699 -0
- package/dist/chunk-T4AK2KLM.js.map +1 -0
- package/dist/chunk-WGYNCSTP.cjs +333 -0
- package/dist/chunk-WGYNCSTP.cjs.map +1 -0
- package/dist/chunk-XEP6P7E6.js +279 -0
- package/dist/chunk-XEP6P7E6.js.map +1 -0
- package/dist/chunk-XMXECSQO.cjs +286 -0
- package/dist/chunk-XMXECSQO.cjs.map +1 -0
- package/dist/chunk-ZWAFLHC2.cjs +181 -0
- package/dist/chunk-ZWAFLHC2.cjs.map +1 -0
- package/dist/data.cjs +71 -0
- package/dist/data.cjs.map +1 -0
- package/dist/data.d.cts +316 -0
- package/dist/data.d.ts +316 -0
- package/dist/data.js +6 -0
- package/dist/data.js.map +1 -0
- package/dist/form.cjs +153 -0
- package/dist/form.cjs.map +1 -0
- package/dist/form.d.cts +660 -0
- package/dist/form.d.ts +660 -0
- package/dist/form.js +8 -0
- package/dist/form.js.map +1 -0
- package/dist/index.cjs +1641 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +552 -0
- package/dist/index.d.ts +552 -0
- package/dist/index.js +956 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.cjs +68 -0
- package/dist/layout.cjs.map +1 -0
- package/dist/layout.d.cts +169 -0
- package/dist/layout.d.ts +169 -0
- package/dist/layout.js +7 -0
- package/dist/layout.js.map +1 -0
- package/dist/motion-CQmCq6_k.d.ts +395 -0
- package/dist/motion-CSX4g2N8.d.cts +395 -0
- package/dist/motion.cjs +79 -0
- package/dist/motion.cjs.map +1 -0
- package/dist/motion.d.cts +4 -0
- package/dist/motion.d.ts +4 -0
- package/dist/motion.js +6 -0
- package/dist/motion.js.map +1 -0
- package/dist/navigation.cjs +48 -0
- package/dist/navigation.cjs.map +1 -0
- package/dist/navigation.d.cts +210 -0
- package/dist/navigation.d.ts +210 -0
- package/dist/navigation.js +7 -0
- package/dist/navigation.js.map +1 -0
- package/dist/overlay.cjs +69 -0
- package/dist/overlay.cjs.map +1 -0
- package/dist/overlay.d.cts +330 -0
- package/dist/overlay.d.ts +330 -0
- package/dist/overlay.js +8 -0
- package/dist/overlay.js.map +1 -0
- package/dist/position-DVScKcaa.d.cts +66 -0
- package/dist/position-DVScKcaa.d.ts +66 -0
- package/dist/primitives.cjs +162 -0
- package/dist/primitives.cjs.map +1 -0
- package/dist/primitives.d.cts +294 -0
- package/dist/primitives.d.ts +294 -0
- package/dist/primitives.js +9 -0
- package/dist/primitives.js.map +1 -0
- package/dist/sidebar-D-PafAXw.d.cts +71 -0
- package/dist/sidebar-D-PafAXw.d.ts +71 -0
- package/dist/styles.css +5575 -0
- package/dist/use-observers-B9qtimrk.d.cts +99 -0
- package/dist/use-observers-B9qtimrk.d.ts +99 -0
- package/package.json +92 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { P as Placement } from './position-DVScKcaa.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A command palette.
|
|
7
|
+
*
|
|
8
|
+
* The interaction is easy; the accessibility is where these usually go wrong. This one implements
|
|
9
|
+
* the combobox pattern properly:
|
|
10
|
+
*
|
|
11
|
+
* - Focus stays in the input the whole time. Arrow keys move a *virtual* selection, announced via
|
|
12
|
+
* `aria-activedescendant`, rather than moving DOM focus — so the user can keep typing.
|
|
13
|
+
* - The list is `role="listbox"` with `role="option"` children and correct `aria-selected`.
|
|
14
|
+
* - Focus is restored to whatever was focused before opening, so keyboard users aren't dumped at
|
|
15
|
+
* the top of the document on close.
|
|
16
|
+
* - Focus is trapped while open, so Tab can't escape to the page behind the scrim.
|
|
17
|
+
*
|
|
18
|
+
* Filtering is a subsequence match rather than a substring one: typing `nds` should find
|
|
19
|
+
* "**N**ew **D**ata**s**ource", which is what anyone who has used a palette expects.
|
|
20
|
+
*/
|
|
21
|
+
interface CommandItem {
|
|
22
|
+
id: string;
|
|
23
|
+
label: string;
|
|
24
|
+
/** Optional grouping heading. Items with the same group render together. */
|
|
25
|
+
group?: string;
|
|
26
|
+
/** Leading icon. */
|
|
27
|
+
icon?: ReactNode;
|
|
28
|
+
/** Shortcut hint shown on the right, e.g. `'⌘K'`. Display only. */
|
|
29
|
+
shortcut?: string;
|
|
30
|
+
/** Extra text matched against the query but not displayed. */
|
|
31
|
+
keywords?: string;
|
|
32
|
+
onSelect?: () => void;
|
|
33
|
+
}
|
|
34
|
+
interface CommandPaletteProps {
|
|
35
|
+
items: readonly CommandItem[];
|
|
36
|
+
open: boolean;
|
|
37
|
+
onOpenChange: (open: boolean) => void;
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
emptyMessage?: string;
|
|
40
|
+
}
|
|
41
|
+
declare function CommandPalette({ items, open, onOpenChange, placeholder, emptyMessage, }: CommandPaletteProps): react.JSX.Element | null;
|
|
42
|
+
/**
|
|
43
|
+
* Bind a keyboard shortcut that toggles state — `⌘K` by default.
|
|
44
|
+
*
|
|
45
|
+
* ```tsx
|
|
46
|
+
* const [open, setOpen] = useState(false)
|
|
47
|
+
* useCommandShortcut(() => setOpen((v) => !v))
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
declare function useCommandShortcut(toggle: () => void, key?: string): void;
|
|
51
|
+
|
|
52
|
+
interface PopoverProps {
|
|
53
|
+
open?: boolean;
|
|
54
|
+
defaultOpen?: boolean;
|
|
55
|
+
onOpenChange?: (open: boolean) => void;
|
|
56
|
+
placement?: Placement;
|
|
57
|
+
/** Gap from the trigger, in px. Default `8`. */
|
|
58
|
+
offset?: number;
|
|
59
|
+
/** Trap focus and block interaction behind. Default `false` — most popovers are non-modal. */
|
|
60
|
+
modal?: boolean;
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
}
|
|
63
|
+
declare function Popover({ open, defaultOpen, onOpenChange, placement, offset, modal, children, }: PopoverProps): react.JSX.Element;
|
|
64
|
+
interface PopoverTriggerProps extends React.HTMLAttributes<HTMLElement> {
|
|
65
|
+
/** Render into the child element rather than emitting a `<button>`. */
|
|
66
|
+
asChild?: boolean;
|
|
67
|
+
children: ReactNode;
|
|
68
|
+
}
|
|
69
|
+
declare function PopoverTrigger({ asChild, children, ...rest }: PopoverTriggerProps): react.JSX.Element;
|
|
70
|
+
interface PopoverContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
71
|
+
/** Draw an arrow pointing at the trigger. Default `false`. */
|
|
72
|
+
arrow?: boolean;
|
|
73
|
+
/** Match the trigger's width — for a popover acting as a dropdown panel. */
|
|
74
|
+
matchWidth?: boolean;
|
|
75
|
+
/** Accessible name. Required unless the content contains its own heading. */
|
|
76
|
+
label?: string;
|
|
77
|
+
children: ReactNode;
|
|
78
|
+
}
|
|
79
|
+
declare function PopoverContent({ arrow, matchWidth, label, className, style, children, ...rest }: PopoverContentProps): react.JSX.Element | null;
|
|
80
|
+
interface HoverCardProps {
|
|
81
|
+
/** The card's contents. */
|
|
82
|
+
content: ReactNode;
|
|
83
|
+
/** Delay before opening, in ms. Default `500`. */
|
|
84
|
+
openDelay?: number;
|
|
85
|
+
/** Delay before closing, in ms. Default `200`. */
|
|
86
|
+
closeDelay?: number;
|
|
87
|
+
placement?: Placement;
|
|
88
|
+
className?: string;
|
|
89
|
+
children: ReactNode;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A rich preview shown on hover — a user card on an @mention, a link preview.
|
|
93
|
+
*
|
|
94
|
+
* Two delays, not one. The open delay stops cards firing as the pointer sweeps across a paragraph
|
|
95
|
+
* of links. The close delay is what lets the pointer travel from the trigger to the card without it
|
|
96
|
+
* vanishing en route, which is the failure that makes hover cards feel broken.
|
|
97
|
+
*
|
|
98
|
+
* Hover-only content is invisible to keyboard and touch users, so this also opens on focus. It is
|
|
99
|
+
* strictly for *supplementary* information — anything essential belongs in a click-opened popover.
|
|
100
|
+
*/
|
|
101
|
+
declare function HoverCard({ content, openDelay, closeDelay, placement, className, children, }: HoverCardProps): react.JSX.Element;
|
|
102
|
+
|
|
103
|
+
interface TooltipProviderProps {
|
|
104
|
+
/** Delay before the first tooltip in a group opens, in ms. Default `600`. */
|
|
105
|
+
delay?: number;
|
|
106
|
+
children: ReactNode;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Share a delay across a set of tooltips.
|
|
110
|
+
*
|
|
111
|
+
* Once one is open, moving to a neighbour shows its tooltip immediately. Without this, scanning a
|
|
112
|
+
* toolbar means waiting out the delay on every single button — the behaviour every desktop OS gets
|
|
113
|
+
* right and most web implementations miss.
|
|
114
|
+
*/
|
|
115
|
+
declare function TooltipProvider({ delay, children }: TooltipProviderProps): react.JSX.Element;
|
|
116
|
+
interface TooltipProps {
|
|
117
|
+
/** The tooltip text. Keep it short — it is read as one description. */
|
|
118
|
+
content: ReactNode;
|
|
119
|
+
placement?: Placement;
|
|
120
|
+
/** Override the group delay, in ms. */
|
|
121
|
+
delay?: number;
|
|
122
|
+
/** Draw an arrow. Default `true`. */
|
|
123
|
+
arrow?: boolean;
|
|
124
|
+
disabled?: boolean;
|
|
125
|
+
className?: string;
|
|
126
|
+
children: ReactNode;
|
|
127
|
+
}
|
|
128
|
+
declare function Tooltip({ content, placement, delay, arrow, disabled, className, children, }: TooltipProps): react.JSX.Element;
|
|
129
|
+
|
|
130
|
+
type DialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
131
|
+
interface DialogProps {
|
|
132
|
+
open: boolean;
|
|
133
|
+
onOpenChange: (open: boolean) => void;
|
|
134
|
+
/** The dialog's accessible name. Required — a dialog announced as just "dialog" is useless. */
|
|
135
|
+
title: ReactNode;
|
|
136
|
+
/** Supporting text, wired to `aria-describedby`. */
|
|
137
|
+
description?: ReactNode;
|
|
138
|
+
size?: DialogSize;
|
|
139
|
+
/** Actions row, pinned below the scrollable body. */
|
|
140
|
+
footer?: ReactNode;
|
|
141
|
+
/** Show the ✕ button. Default `true`. */
|
|
142
|
+
showClose?: boolean;
|
|
143
|
+
/** Allow closing via scrim click and Escape. Default `true`. */
|
|
144
|
+
dismissable?: boolean;
|
|
145
|
+
/** Element to focus on open. Defaults to the first tabbable one. */
|
|
146
|
+
initialFocus?: React.RefObject<HTMLElement | null>;
|
|
147
|
+
className?: string;
|
|
148
|
+
children?: ReactNode;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* A modal dialog.
|
|
152
|
+
*
|
|
153
|
+
* Not `<dialog showModal>`: the native element's top-layer behaviour is genuinely better, but its
|
|
154
|
+
* backdrop cannot be animated consistently, `::backdrop` inherits nothing, and closing behaviour
|
|
155
|
+
* differs enough across browsers to need working around anyway. The pieces the native element gives
|
|
156
|
+
* for free — focus trap, scroll lock, inert background, focus restore — are all here explicitly.
|
|
157
|
+
*
|
|
158
|
+
* `title` is a required prop rather than an optional slot. Every accessibility audit of a component
|
|
159
|
+
* library turns up unnamed dialogs, and the reliable fix is to make the name impossible to omit.
|
|
160
|
+
*/
|
|
161
|
+
declare function Dialog({ open, onOpenChange, title, description, size, footer, showClose, dismissable, initialFocus, className, children, }: DialogProps): react.JSX.Element | null;
|
|
162
|
+
interface AlertDialogProps {
|
|
163
|
+
open: boolean;
|
|
164
|
+
onOpenChange: (open: boolean) => void;
|
|
165
|
+
title: ReactNode;
|
|
166
|
+
description: ReactNode;
|
|
167
|
+
/** Confirm button text. Default `'Confirm'`. */
|
|
168
|
+
confirmLabel?: string;
|
|
169
|
+
cancelLabel?: string;
|
|
170
|
+
/** Style the confirm action as destructive. */
|
|
171
|
+
destructive?: boolean;
|
|
172
|
+
onConfirm: () => void | Promise<void>;
|
|
173
|
+
onCancel?: () => void;
|
|
174
|
+
/** Disable the buttons while an async confirm runs. */
|
|
175
|
+
busy?: boolean;
|
|
176
|
+
className?: string;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A confirmation dialog.
|
|
180
|
+
*
|
|
181
|
+
* `role="alertdialog"` and `aria-describedby` on the message, which makes a screen reader read the
|
|
182
|
+
* consequence immediately on open rather than waiting for the user to navigate to it. That is the
|
|
183
|
+
* entire difference from a regular dialog, and it matters precisely because these appear before
|
|
184
|
+
* irreversible actions.
|
|
185
|
+
*
|
|
186
|
+
* It is deliberately **not** dismissable by clicking the scrim: an accidental click outside should
|
|
187
|
+
* not silently cancel a decision the user was asked to make. Escape still works, because trapping
|
|
188
|
+
* someone in a dialog is worse.
|
|
189
|
+
*
|
|
190
|
+
* Focus starts on **Cancel**, not Confirm. A keyboard user who hits Enter reflexively should not
|
|
191
|
+
* delete their account.
|
|
192
|
+
*/
|
|
193
|
+
declare function AlertDialog({ open, onOpenChange, title, description, confirmLabel, cancelLabel, destructive, onConfirm, onCancel, busy, className, }: AlertDialogProps): react.JSX.Element | null;
|
|
194
|
+
/** Layout helper for a dialog's action row. Right-aligned, reversed on narrow screens. */
|
|
195
|
+
declare function DialogFooter({ children, className }: {
|
|
196
|
+
children: ReactNode;
|
|
197
|
+
className?: string;
|
|
198
|
+
}): react.JSX.Element;
|
|
199
|
+
|
|
200
|
+
type DrawerSide = 'left' | 'right' | 'top' | 'bottom';
|
|
201
|
+
interface DrawerProps {
|
|
202
|
+
open: boolean;
|
|
203
|
+
onOpenChange: (open: boolean) => void;
|
|
204
|
+
/** Which edge it slides from. Default `'right'`. */
|
|
205
|
+
side?: DrawerSide;
|
|
206
|
+
title: ReactNode;
|
|
207
|
+
description?: ReactNode;
|
|
208
|
+
/** Width for left/right, height for top/bottom. Default `'22rem'`. */
|
|
209
|
+
size?: string;
|
|
210
|
+
footer?: ReactNode;
|
|
211
|
+
showClose?: boolean;
|
|
212
|
+
/** Block interaction behind and lock scroll. Default `true`. */
|
|
213
|
+
modal?: boolean;
|
|
214
|
+
dismissable?: boolean;
|
|
215
|
+
className?: string;
|
|
216
|
+
children?: ReactNode;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* A panel that slides in from an edge.
|
|
220
|
+
*
|
|
221
|
+
* Same accessibility contract as `Dialog` — it is a dialog, just positioned differently. The reason
|
|
222
|
+
* it exists separately is that the *content* pattern differs: drawers hold navigation, filters and
|
|
223
|
+
* detail views that stay open while the user works, so they support a non-modal mode where the page
|
|
224
|
+
* behind stays usable.
|
|
225
|
+
*
|
|
226
|
+
* On a phone a bottom drawer is the right shape for what would be a dialog on a desktop; that's a
|
|
227
|
+
* layout decision for the consumer, which is why `side` is a plain prop rather than a breakpoint
|
|
228
|
+
* rule baked in here.
|
|
229
|
+
*/
|
|
230
|
+
declare function Drawer({ open, onOpenChange, side, title, description, size, footer, showClose, modal, dismissable, className, children, }: DrawerProps): react.JSX.Element | null;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Menus — dropdown and context.
|
|
234
|
+
*
|
|
235
|
+
* Data-driven (`items={[…]}`) rather than compound. Menus are almost always built from a
|
|
236
|
+
* configuration array anyway — permissions filter entries, a selection decides what's enabled — and
|
|
237
|
+
* expressing that as JSX children means `{canDelete && <MenuItem …/>}` scattered through the tree,
|
|
238
|
+
* which breaks keyboard navigation indices in ways that are painful to debug.
|
|
239
|
+
*
|
|
240
|
+
* Follows the ARIA menu pattern, where **DOM focus moves to the item** (unlike a listbox, which
|
|
241
|
+
* keeps focus on the container). That's what makes Right/Left arrow submenu traversal work the way
|
|
242
|
+
* it does in every desktop application.
|
|
243
|
+
*/
|
|
244
|
+
interface MenuItemBase {
|
|
245
|
+
id?: string;
|
|
246
|
+
disabled?: boolean;
|
|
247
|
+
}
|
|
248
|
+
interface MenuAction extends MenuItemBase {
|
|
249
|
+
type?: 'item';
|
|
250
|
+
label: ReactNode;
|
|
251
|
+
icon?: ReactNode;
|
|
252
|
+
/** Display-only shortcut hint, e.g. `'⌘S'`. */
|
|
253
|
+
shortcut?: string;
|
|
254
|
+
/** Style as destructive, and mark it in the accessible name. */
|
|
255
|
+
danger?: boolean;
|
|
256
|
+
onSelect?: () => void;
|
|
257
|
+
}
|
|
258
|
+
interface MenuCheckbox extends MenuItemBase {
|
|
259
|
+
type: 'checkbox';
|
|
260
|
+
label: ReactNode;
|
|
261
|
+
checked: boolean;
|
|
262
|
+
onChange: (checked: boolean) => void;
|
|
263
|
+
shortcut?: string;
|
|
264
|
+
}
|
|
265
|
+
interface MenuRadioGroup {
|
|
266
|
+
type: 'radio';
|
|
267
|
+
value: string;
|
|
268
|
+
onChange: (value: string) => void;
|
|
269
|
+
options: ReadonlyArray<{
|
|
270
|
+
value: string;
|
|
271
|
+
label: ReactNode;
|
|
272
|
+
disabled?: boolean;
|
|
273
|
+
}>;
|
|
274
|
+
}
|
|
275
|
+
interface MenuSubmenu extends MenuItemBase {
|
|
276
|
+
type: 'submenu';
|
|
277
|
+
label: ReactNode;
|
|
278
|
+
icon?: ReactNode;
|
|
279
|
+
items: readonly MenuEntry[];
|
|
280
|
+
}
|
|
281
|
+
type MenuEntry = MenuAction | MenuCheckbox | MenuRadioGroup | MenuSubmenu | {
|
|
282
|
+
type: 'separator';
|
|
283
|
+
} | {
|
|
284
|
+
type: 'label';
|
|
285
|
+
label: ReactNode;
|
|
286
|
+
};
|
|
287
|
+
interface MenuProps {
|
|
288
|
+
items: readonly MenuEntry[];
|
|
289
|
+
placement?: Placement;
|
|
290
|
+
/** Accessible name for the menu itself. */
|
|
291
|
+
label?: string;
|
|
292
|
+
className?: string;
|
|
293
|
+
/** The control that opens the menu. */
|
|
294
|
+
children: ReactNode;
|
|
295
|
+
open?: boolean;
|
|
296
|
+
onOpenChange?: (open: boolean) => void;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* A dropdown menu.
|
|
300
|
+
*
|
|
301
|
+
* ```tsx
|
|
302
|
+
* <DropdownMenu items={[
|
|
303
|
+
* { label: 'Edit', shortcut: '⌘E', onSelect: edit },
|
|
304
|
+
* { type: 'separator' },
|
|
305
|
+
* { label: 'Delete', danger: true, onSelect: remove },
|
|
306
|
+
* ]}>
|
|
307
|
+
* <IconButton label="Actions" />
|
|
308
|
+
* </DropdownMenu>
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
declare function DropdownMenu({ items, placement, label, className, children, open: controlledOpen, onOpenChange, }: MenuProps): react.JSX.Element;
|
|
312
|
+
interface ContextMenuProps {
|
|
313
|
+
items: readonly MenuEntry[];
|
|
314
|
+
label?: string;
|
|
315
|
+
className?: string;
|
|
316
|
+
children: ReactNode;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* A right-click menu.
|
|
320
|
+
*
|
|
321
|
+
* Also opens on the **context-menu key** and on Shift+F10, which is how keyboard users reach one —
|
|
322
|
+
* a right-click-only implementation is inaccessible, and it is the most commonly missed keyboard
|
|
323
|
+
* binding in the whole component set.
|
|
324
|
+
*
|
|
325
|
+
* Anchored to the pointer via a zero-size virtual rect, so the existing positioning code flips and
|
|
326
|
+
* shifts it near the viewport edges without needing a separate path.
|
|
327
|
+
*/
|
|
328
|
+
declare function ContextMenu({ items, label, className, children, }: ContextMenuProps): react.JSX.Element;
|
|
329
|
+
|
|
330
|
+
export { AlertDialog, type AlertDialogProps, type CommandItem, CommandPalette, type CommandPaletteProps, ContextMenu, type ContextMenuProps, Dialog, DialogFooter, type DialogProps, type DialogSize, Drawer, type DrawerProps, type DrawerSide, DropdownMenu, HoverCard, type HoverCardProps, type MenuAction, type MenuCheckbox, type MenuEntry, type MenuProps, type MenuRadioGroup, type MenuSubmenu, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type PopoverTriggerProps, Tooltip, type TooltipProps, TooltipProvider, type TooltipProviderProps, useCommandShortcut };
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { P as Placement } from './position-DVScKcaa.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A command palette.
|
|
7
|
+
*
|
|
8
|
+
* The interaction is easy; the accessibility is where these usually go wrong. This one implements
|
|
9
|
+
* the combobox pattern properly:
|
|
10
|
+
*
|
|
11
|
+
* - Focus stays in the input the whole time. Arrow keys move a *virtual* selection, announced via
|
|
12
|
+
* `aria-activedescendant`, rather than moving DOM focus — so the user can keep typing.
|
|
13
|
+
* - The list is `role="listbox"` with `role="option"` children and correct `aria-selected`.
|
|
14
|
+
* - Focus is restored to whatever was focused before opening, so keyboard users aren't dumped at
|
|
15
|
+
* the top of the document on close.
|
|
16
|
+
* - Focus is trapped while open, so Tab can't escape to the page behind the scrim.
|
|
17
|
+
*
|
|
18
|
+
* Filtering is a subsequence match rather than a substring one: typing `nds` should find
|
|
19
|
+
* "**N**ew **D**ata**s**ource", which is what anyone who has used a palette expects.
|
|
20
|
+
*/
|
|
21
|
+
interface CommandItem {
|
|
22
|
+
id: string;
|
|
23
|
+
label: string;
|
|
24
|
+
/** Optional grouping heading. Items with the same group render together. */
|
|
25
|
+
group?: string;
|
|
26
|
+
/** Leading icon. */
|
|
27
|
+
icon?: ReactNode;
|
|
28
|
+
/** Shortcut hint shown on the right, e.g. `'⌘K'`. Display only. */
|
|
29
|
+
shortcut?: string;
|
|
30
|
+
/** Extra text matched against the query but not displayed. */
|
|
31
|
+
keywords?: string;
|
|
32
|
+
onSelect?: () => void;
|
|
33
|
+
}
|
|
34
|
+
interface CommandPaletteProps {
|
|
35
|
+
items: readonly CommandItem[];
|
|
36
|
+
open: boolean;
|
|
37
|
+
onOpenChange: (open: boolean) => void;
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
emptyMessage?: string;
|
|
40
|
+
}
|
|
41
|
+
declare function CommandPalette({ items, open, onOpenChange, placeholder, emptyMessage, }: CommandPaletteProps): react.JSX.Element | null;
|
|
42
|
+
/**
|
|
43
|
+
* Bind a keyboard shortcut that toggles state — `⌘K` by default.
|
|
44
|
+
*
|
|
45
|
+
* ```tsx
|
|
46
|
+
* const [open, setOpen] = useState(false)
|
|
47
|
+
* useCommandShortcut(() => setOpen((v) => !v))
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
declare function useCommandShortcut(toggle: () => void, key?: string): void;
|
|
51
|
+
|
|
52
|
+
interface PopoverProps {
|
|
53
|
+
open?: boolean;
|
|
54
|
+
defaultOpen?: boolean;
|
|
55
|
+
onOpenChange?: (open: boolean) => void;
|
|
56
|
+
placement?: Placement;
|
|
57
|
+
/** Gap from the trigger, in px. Default `8`. */
|
|
58
|
+
offset?: number;
|
|
59
|
+
/** Trap focus and block interaction behind. Default `false` — most popovers are non-modal. */
|
|
60
|
+
modal?: boolean;
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
}
|
|
63
|
+
declare function Popover({ open, defaultOpen, onOpenChange, placement, offset, modal, children, }: PopoverProps): react.JSX.Element;
|
|
64
|
+
interface PopoverTriggerProps extends React.HTMLAttributes<HTMLElement> {
|
|
65
|
+
/** Render into the child element rather than emitting a `<button>`. */
|
|
66
|
+
asChild?: boolean;
|
|
67
|
+
children: ReactNode;
|
|
68
|
+
}
|
|
69
|
+
declare function PopoverTrigger({ asChild, children, ...rest }: PopoverTriggerProps): react.JSX.Element;
|
|
70
|
+
interface PopoverContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
71
|
+
/** Draw an arrow pointing at the trigger. Default `false`. */
|
|
72
|
+
arrow?: boolean;
|
|
73
|
+
/** Match the trigger's width — for a popover acting as a dropdown panel. */
|
|
74
|
+
matchWidth?: boolean;
|
|
75
|
+
/** Accessible name. Required unless the content contains its own heading. */
|
|
76
|
+
label?: string;
|
|
77
|
+
children: ReactNode;
|
|
78
|
+
}
|
|
79
|
+
declare function PopoverContent({ arrow, matchWidth, label, className, style, children, ...rest }: PopoverContentProps): react.JSX.Element | null;
|
|
80
|
+
interface HoverCardProps {
|
|
81
|
+
/** The card's contents. */
|
|
82
|
+
content: ReactNode;
|
|
83
|
+
/** Delay before opening, in ms. Default `500`. */
|
|
84
|
+
openDelay?: number;
|
|
85
|
+
/** Delay before closing, in ms. Default `200`. */
|
|
86
|
+
closeDelay?: number;
|
|
87
|
+
placement?: Placement;
|
|
88
|
+
className?: string;
|
|
89
|
+
children: ReactNode;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A rich preview shown on hover — a user card on an @mention, a link preview.
|
|
93
|
+
*
|
|
94
|
+
* Two delays, not one. The open delay stops cards firing as the pointer sweeps across a paragraph
|
|
95
|
+
* of links. The close delay is what lets the pointer travel from the trigger to the card without it
|
|
96
|
+
* vanishing en route, which is the failure that makes hover cards feel broken.
|
|
97
|
+
*
|
|
98
|
+
* Hover-only content is invisible to keyboard and touch users, so this also opens on focus. It is
|
|
99
|
+
* strictly for *supplementary* information — anything essential belongs in a click-opened popover.
|
|
100
|
+
*/
|
|
101
|
+
declare function HoverCard({ content, openDelay, closeDelay, placement, className, children, }: HoverCardProps): react.JSX.Element;
|
|
102
|
+
|
|
103
|
+
interface TooltipProviderProps {
|
|
104
|
+
/** Delay before the first tooltip in a group opens, in ms. Default `600`. */
|
|
105
|
+
delay?: number;
|
|
106
|
+
children: ReactNode;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Share a delay across a set of tooltips.
|
|
110
|
+
*
|
|
111
|
+
* Once one is open, moving to a neighbour shows its tooltip immediately. Without this, scanning a
|
|
112
|
+
* toolbar means waiting out the delay on every single button — the behaviour every desktop OS gets
|
|
113
|
+
* right and most web implementations miss.
|
|
114
|
+
*/
|
|
115
|
+
declare function TooltipProvider({ delay, children }: TooltipProviderProps): react.JSX.Element;
|
|
116
|
+
interface TooltipProps {
|
|
117
|
+
/** The tooltip text. Keep it short — it is read as one description. */
|
|
118
|
+
content: ReactNode;
|
|
119
|
+
placement?: Placement;
|
|
120
|
+
/** Override the group delay, in ms. */
|
|
121
|
+
delay?: number;
|
|
122
|
+
/** Draw an arrow. Default `true`. */
|
|
123
|
+
arrow?: boolean;
|
|
124
|
+
disabled?: boolean;
|
|
125
|
+
className?: string;
|
|
126
|
+
children: ReactNode;
|
|
127
|
+
}
|
|
128
|
+
declare function Tooltip({ content, placement, delay, arrow, disabled, className, children, }: TooltipProps): react.JSX.Element;
|
|
129
|
+
|
|
130
|
+
type DialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
131
|
+
interface DialogProps {
|
|
132
|
+
open: boolean;
|
|
133
|
+
onOpenChange: (open: boolean) => void;
|
|
134
|
+
/** The dialog's accessible name. Required — a dialog announced as just "dialog" is useless. */
|
|
135
|
+
title: ReactNode;
|
|
136
|
+
/** Supporting text, wired to `aria-describedby`. */
|
|
137
|
+
description?: ReactNode;
|
|
138
|
+
size?: DialogSize;
|
|
139
|
+
/** Actions row, pinned below the scrollable body. */
|
|
140
|
+
footer?: ReactNode;
|
|
141
|
+
/** Show the ✕ button. Default `true`. */
|
|
142
|
+
showClose?: boolean;
|
|
143
|
+
/** Allow closing via scrim click and Escape. Default `true`. */
|
|
144
|
+
dismissable?: boolean;
|
|
145
|
+
/** Element to focus on open. Defaults to the first tabbable one. */
|
|
146
|
+
initialFocus?: React.RefObject<HTMLElement | null>;
|
|
147
|
+
className?: string;
|
|
148
|
+
children?: ReactNode;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* A modal dialog.
|
|
152
|
+
*
|
|
153
|
+
* Not `<dialog showModal>`: the native element's top-layer behaviour is genuinely better, but its
|
|
154
|
+
* backdrop cannot be animated consistently, `::backdrop` inherits nothing, and closing behaviour
|
|
155
|
+
* differs enough across browsers to need working around anyway. The pieces the native element gives
|
|
156
|
+
* for free — focus trap, scroll lock, inert background, focus restore — are all here explicitly.
|
|
157
|
+
*
|
|
158
|
+
* `title` is a required prop rather than an optional slot. Every accessibility audit of a component
|
|
159
|
+
* library turns up unnamed dialogs, and the reliable fix is to make the name impossible to omit.
|
|
160
|
+
*/
|
|
161
|
+
declare function Dialog({ open, onOpenChange, title, description, size, footer, showClose, dismissable, initialFocus, className, children, }: DialogProps): react.JSX.Element | null;
|
|
162
|
+
interface AlertDialogProps {
|
|
163
|
+
open: boolean;
|
|
164
|
+
onOpenChange: (open: boolean) => void;
|
|
165
|
+
title: ReactNode;
|
|
166
|
+
description: ReactNode;
|
|
167
|
+
/** Confirm button text. Default `'Confirm'`. */
|
|
168
|
+
confirmLabel?: string;
|
|
169
|
+
cancelLabel?: string;
|
|
170
|
+
/** Style the confirm action as destructive. */
|
|
171
|
+
destructive?: boolean;
|
|
172
|
+
onConfirm: () => void | Promise<void>;
|
|
173
|
+
onCancel?: () => void;
|
|
174
|
+
/** Disable the buttons while an async confirm runs. */
|
|
175
|
+
busy?: boolean;
|
|
176
|
+
className?: string;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A confirmation dialog.
|
|
180
|
+
*
|
|
181
|
+
* `role="alertdialog"` and `aria-describedby` on the message, which makes a screen reader read the
|
|
182
|
+
* consequence immediately on open rather than waiting for the user to navigate to it. That is the
|
|
183
|
+
* entire difference from a regular dialog, and it matters precisely because these appear before
|
|
184
|
+
* irreversible actions.
|
|
185
|
+
*
|
|
186
|
+
* It is deliberately **not** dismissable by clicking the scrim: an accidental click outside should
|
|
187
|
+
* not silently cancel a decision the user was asked to make. Escape still works, because trapping
|
|
188
|
+
* someone in a dialog is worse.
|
|
189
|
+
*
|
|
190
|
+
* Focus starts on **Cancel**, not Confirm. A keyboard user who hits Enter reflexively should not
|
|
191
|
+
* delete their account.
|
|
192
|
+
*/
|
|
193
|
+
declare function AlertDialog({ open, onOpenChange, title, description, confirmLabel, cancelLabel, destructive, onConfirm, onCancel, busy, className, }: AlertDialogProps): react.JSX.Element | null;
|
|
194
|
+
/** Layout helper for a dialog's action row. Right-aligned, reversed on narrow screens. */
|
|
195
|
+
declare function DialogFooter({ children, className }: {
|
|
196
|
+
children: ReactNode;
|
|
197
|
+
className?: string;
|
|
198
|
+
}): react.JSX.Element;
|
|
199
|
+
|
|
200
|
+
type DrawerSide = 'left' | 'right' | 'top' | 'bottom';
|
|
201
|
+
interface DrawerProps {
|
|
202
|
+
open: boolean;
|
|
203
|
+
onOpenChange: (open: boolean) => void;
|
|
204
|
+
/** Which edge it slides from. Default `'right'`. */
|
|
205
|
+
side?: DrawerSide;
|
|
206
|
+
title: ReactNode;
|
|
207
|
+
description?: ReactNode;
|
|
208
|
+
/** Width for left/right, height for top/bottom. Default `'22rem'`. */
|
|
209
|
+
size?: string;
|
|
210
|
+
footer?: ReactNode;
|
|
211
|
+
showClose?: boolean;
|
|
212
|
+
/** Block interaction behind and lock scroll. Default `true`. */
|
|
213
|
+
modal?: boolean;
|
|
214
|
+
dismissable?: boolean;
|
|
215
|
+
className?: string;
|
|
216
|
+
children?: ReactNode;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* A panel that slides in from an edge.
|
|
220
|
+
*
|
|
221
|
+
* Same accessibility contract as `Dialog` — it is a dialog, just positioned differently. The reason
|
|
222
|
+
* it exists separately is that the *content* pattern differs: drawers hold navigation, filters and
|
|
223
|
+
* detail views that stay open while the user works, so they support a non-modal mode where the page
|
|
224
|
+
* behind stays usable.
|
|
225
|
+
*
|
|
226
|
+
* On a phone a bottom drawer is the right shape for what would be a dialog on a desktop; that's a
|
|
227
|
+
* layout decision for the consumer, which is why `side` is a plain prop rather than a breakpoint
|
|
228
|
+
* rule baked in here.
|
|
229
|
+
*/
|
|
230
|
+
declare function Drawer({ open, onOpenChange, side, title, description, size, footer, showClose, modal, dismissable, className, children, }: DrawerProps): react.JSX.Element | null;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Menus — dropdown and context.
|
|
234
|
+
*
|
|
235
|
+
* Data-driven (`items={[…]}`) rather than compound. Menus are almost always built from a
|
|
236
|
+
* configuration array anyway — permissions filter entries, a selection decides what's enabled — and
|
|
237
|
+
* expressing that as JSX children means `{canDelete && <MenuItem …/>}` scattered through the tree,
|
|
238
|
+
* which breaks keyboard navigation indices in ways that are painful to debug.
|
|
239
|
+
*
|
|
240
|
+
* Follows the ARIA menu pattern, where **DOM focus moves to the item** (unlike a listbox, which
|
|
241
|
+
* keeps focus on the container). That's what makes Right/Left arrow submenu traversal work the way
|
|
242
|
+
* it does in every desktop application.
|
|
243
|
+
*/
|
|
244
|
+
interface MenuItemBase {
|
|
245
|
+
id?: string;
|
|
246
|
+
disabled?: boolean;
|
|
247
|
+
}
|
|
248
|
+
interface MenuAction extends MenuItemBase {
|
|
249
|
+
type?: 'item';
|
|
250
|
+
label: ReactNode;
|
|
251
|
+
icon?: ReactNode;
|
|
252
|
+
/** Display-only shortcut hint, e.g. `'⌘S'`. */
|
|
253
|
+
shortcut?: string;
|
|
254
|
+
/** Style as destructive, and mark it in the accessible name. */
|
|
255
|
+
danger?: boolean;
|
|
256
|
+
onSelect?: () => void;
|
|
257
|
+
}
|
|
258
|
+
interface MenuCheckbox extends MenuItemBase {
|
|
259
|
+
type: 'checkbox';
|
|
260
|
+
label: ReactNode;
|
|
261
|
+
checked: boolean;
|
|
262
|
+
onChange: (checked: boolean) => void;
|
|
263
|
+
shortcut?: string;
|
|
264
|
+
}
|
|
265
|
+
interface MenuRadioGroup {
|
|
266
|
+
type: 'radio';
|
|
267
|
+
value: string;
|
|
268
|
+
onChange: (value: string) => void;
|
|
269
|
+
options: ReadonlyArray<{
|
|
270
|
+
value: string;
|
|
271
|
+
label: ReactNode;
|
|
272
|
+
disabled?: boolean;
|
|
273
|
+
}>;
|
|
274
|
+
}
|
|
275
|
+
interface MenuSubmenu extends MenuItemBase {
|
|
276
|
+
type: 'submenu';
|
|
277
|
+
label: ReactNode;
|
|
278
|
+
icon?: ReactNode;
|
|
279
|
+
items: readonly MenuEntry[];
|
|
280
|
+
}
|
|
281
|
+
type MenuEntry = MenuAction | MenuCheckbox | MenuRadioGroup | MenuSubmenu | {
|
|
282
|
+
type: 'separator';
|
|
283
|
+
} | {
|
|
284
|
+
type: 'label';
|
|
285
|
+
label: ReactNode;
|
|
286
|
+
};
|
|
287
|
+
interface MenuProps {
|
|
288
|
+
items: readonly MenuEntry[];
|
|
289
|
+
placement?: Placement;
|
|
290
|
+
/** Accessible name for the menu itself. */
|
|
291
|
+
label?: string;
|
|
292
|
+
className?: string;
|
|
293
|
+
/** The control that opens the menu. */
|
|
294
|
+
children: ReactNode;
|
|
295
|
+
open?: boolean;
|
|
296
|
+
onOpenChange?: (open: boolean) => void;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* A dropdown menu.
|
|
300
|
+
*
|
|
301
|
+
* ```tsx
|
|
302
|
+
* <DropdownMenu items={[
|
|
303
|
+
* { label: 'Edit', shortcut: '⌘E', onSelect: edit },
|
|
304
|
+
* { type: 'separator' },
|
|
305
|
+
* { label: 'Delete', danger: true, onSelect: remove },
|
|
306
|
+
* ]}>
|
|
307
|
+
* <IconButton label="Actions" />
|
|
308
|
+
* </DropdownMenu>
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
declare function DropdownMenu({ items, placement, label, className, children, open: controlledOpen, onOpenChange, }: MenuProps): react.JSX.Element;
|
|
312
|
+
interface ContextMenuProps {
|
|
313
|
+
items: readonly MenuEntry[];
|
|
314
|
+
label?: string;
|
|
315
|
+
className?: string;
|
|
316
|
+
children: ReactNode;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* A right-click menu.
|
|
320
|
+
*
|
|
321
|
+
* Also opens on the **context-menu key** and on Shift+F10, which is how keyboard users reach one —
|
|
322
|
+
* a right-click-only implementation is inaccessible, and it is the most commonly missed keyboard
|
|
323
|
+
* binding in the whole component set.
|
|
324
|
+
*
|
|
325
|
+
* Anchored to the pointer via a zero-size virtual rect, so the existing positioning code flips and
|
|
326
|
+
* shifts it near the viewport edges without needing a separate path.
|
|
327
|
+
*/
|
|
328
|
+
declare function ContextMenu({ items, label, className, children, }: ContextMenuProps): react.JSX.Element;
|
|
329
|
+
|
|
330
|
+
export { AlertDialog, type AlertDialogProps, type CommandItem, CommandPalette, type CommandPaletteProps, ContextMenu, type ContextMenuProps, Dialog, DialogFooter, type DialogProps, type DialogSize, Drawer, type DrawerProps, type DrawerSide, DropdownMenu, HoverCard, type HoverCardProps, type MenuAction, type MenuCheckbox, type MenuEntry, type MenuProps, type MenuRadioGroup, type MenuSubmenu, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type PopoverTriggerProps, Tooltip, type TooltipProps, TooltipProvider, type TooltipProviderProps, useCommandShortcut };
|
package/dist/overlay.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
export { AlertDialog, CommandPalette, ContextMenu, Dialog, DialogFooter, Drawer, DropdownMenu, HoverCard, Popover, PopoverContent, PopoverTrigger, Tooltip, TooltipProvider, useCommandShortcut } from './chunk-LDCZQP3R.js';
|
|
3
|
+
import './chunk-HO2YSF5O.js';
|
|
4
|
+
import './chunk-XEP6P7E6.js';
|
|
5
|
+
import './chunk-LXCIXR5T.js';
|
|
6
|
+
import './chunk-H34OXXJU.js';
|
|
7
|
+
//# sourceMappingURL=overlay.js.map
|
|
8
|
+
//# sourceMappingURL=overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"overlay.js"}
|