@rio-m3e/core 0.1.0 → 0.3.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/README.md +2 -0
- package/dist/index.d.ts +837 -29
- package/dist/index.js +2378 -185
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The attributes of one part of a component's markup, in HTML form: names as HTML spells them
|
|
3
|
+
* (`class`, `aria-pressed`, `data-size`) and string values, with `undefined` leaving an attribute
|
|
4
|
+
* out. Each component's `parts` returns one of these per part. See "Core output" in
|
|
5
|
+
* `docs/conventions.md`.
|
|
6
|
+
*/
|
|
7
|
+
export type PartAttrs = Record<string, string | undefined>;
|
|
8
|
+
/**
|
|
9
|
+
* An event a component's handler (`handleClick`) takes: a DOM event, or a framework's own, such
|
|
10
|
+
* as React's synthetic events. Core only cancels it, and hands the same event back to the adapter
|
|
11
|
+
* (`onClick`), so components are generic over its type, with `MouseEvent` as the default.
|
|
12
|
+
*/
|
|
13
|
+
export interface CancelableEvent {
|
|
14
|
+
preventDefault(): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* One node of a component's skeleton: the markup an adapter renders, part by part. Adapters
|
|
18
|
+
* render it their own way; contract tests check what they rendered against it. Each component
|
|
19
|
+
* exports its skeleton (`buttonSkeleton`, `switchSkeleton`, ...).
|
|
20
|
+
*
|
|
21
|
+
* `Part` narrows the names to the component's parts, so a typo fails the build. `When` lists the
|
|
22
|
+
* decisions the skeleton may use; leave it out when every part always renders. Skeletons are
|
|
23
|
+
* shared objects, so everything is read-only.
|
|
24
|
+
*/
|
|
25
|
+
export interface PartNode<Part extends string = string, When extends string = never> {
|
|
26
|
+
/** The part, named as in the component's `parts`. */
|
|
27
|
+
readonly part: Part;
|
|
28
|
+
/** The element the part is, as `tagName` in lower case. */
|
|
29
|
+
readonly tag: keyof HTMLElementTagNameMap;
|
|
30
|
+
/**
|
|
31
|
+
* The component API's decision that says whether the part renders, such as `'showsIcon'`.
|
|
32
|
+
* Without it, the part always renders.
|
|
33
|
+
*/
|
|
34
|
+
readonly when?: When;
|
|
35
|
+
/**
|
|
36
|
+
* Content from the app (slots, children) goes inside. The content itself isn't checked against
|
|
37
|
+
* the skeleton; where a component picks between contents, its contract test checks the pick.
|
|
38
|
+
*/
|
|
39
|
+
readonly content?: true;
|
|
40
|
+
readonly children?: readonly PartNode<Part, When>[];
|
|
41
|
+
}
|
|
1
42
|
export declare const BUTTON_VARIANTS: readonly ["filled", "tonal", "outlined", "elevated", "text"];
|
|
2
43
|
export type ButtonVariant = (typeof BUTTON_VARIANTS)[number];
|
|
3
44
|
/** M3E button sizes. `small` is the default. */
|
|
@@ -28,6 +69,11 @@ export interface ButtonProps {
|
|
|
28
69
|
softDisabled?: boolean;
|
|
29
70
|
/** Defaults to `'button'`, so a button inside a form doesn't submit it by accident. */
|
|
30
71
|
type?: 'button' | 'submit' | 'reset';
|
|
72
|
+
/**
|
|
73
|
+
* Identifies the button inside a button group that keeps a selection. Such a group makes the
|
|
74
|
+
* button a toggle and decides whether it is selected.
|
|
75
|
+
*/
|
|
76
|
+
value?: ButtonGroupValue;
|
|
31
77
|
}
|
|
32
78
|
export declare const buttonDefaults: {
|
|
33
79
|
variant: "filled";
|
|
@@ -39,20 +85,202 @@ export declare const buttonDefaults: {
|
|
|
39
85
|
softDisabled: false;
|
|
40
86
|
type: "button";
|
|
41
87
|
};
|
|
42
|
-
|
|
88
|
+
/** What the adapter has to put in the button, which only the adapter can see. */
|
|
89
|
+
export interface ButtonContent {
|
|
90
|
+
/** Whether there is a leading icon. */
|
|
91
|
+
icon: boolean;
|
|
92
|
+
}
|
|
93
|
+
export interface ButtonOptions<E extends CancelableEvent = MouseEvent> {
|
|
43
94
|
/** Returns the current prop values. The adapter owns the state. */
|
|
44
95
|
props: () => ButtonProps;
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
/** Called
|
|
48
|
-
|
|
96
|
+
/** Returns what content the adapter has. Without it, the button has no icon. */
|
|
97
|
+
content?: () => ButtonContent;
|
|
98
|
+
/** Called for a click that isn't blocked, with the event `handleClick` got. */
|
|
99
|
+
onClick: (event: E) => void;
|
|
100
|
+
/** Called after an unblocked click on a toggle button, with the requested value. */
|
|
101
|
+
onChange: (selected: boolean) => void;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The button's markup, part by part. `buttonSkeleton` says how the adapter nests them.
|
|
105
|
+
*/
|
|
106
|
+
export interface ButtonParts {
|
|
107
|
+
root: () => PartAttrs;
|
|
108
|
+
/** Extends small buttons to the 48px target. */
|
|
109
|
+
touch: () => PartAttrs;
|
|
110
|
+
icon: () => PartAttrs;
|
|
111
|
+
label: () => PartAttrs;
|
|
49
112
|
}
|
|
50
|
-
|
|
51
|
-
|
|
113
|
+
/** How the adapter renders the button's parts. The icon holds the leading icon. */
|
|
114
|
+
export declare const buttonSkeleton: PartNode<keyof ButtonParts, 'showsIcon'>;
|
|
115
|
+
export interface ButtonApi<E extends CancelableEvent = MouseEvent> {
|
|
116
|
+
parts: ButtonParts;
|
|
117
|
+
/** Whether to render the icon part. */
|
|
118
|
+
showsIcon: () => boolean;
|
|
52
119
|
/** Attach to the root element's `click`. */
|
|
53
|
-
handleClick: (event:
|
|
120
|
+
handleClick: (event: E) => void;
|
|
121
|
+
}
|
|
122
|
+
export declare function createButton<E extends CancelableEvent = MouseEvent>(options: ButtonOptions<E>): ButtonApi<E>;
|
|
123
|
+
/**
|
|
124
|
+
* M3E button group variants. A standard group spaces its buttons and lets a pressed button push
|
|
125
|
+
* its neighbors; a connected group joins them with 2px gaps and shared corners, and fills the
|
|
126
|
+
* width it is given.
|
|
127
|
+
*/
|
|
128
|
+
export declare const BUTTON_GROUP_VARIANTS: readonly ["standard", "connected"];
|
|
129
|
+
export type ButtonGroupVariant = (typeof BUTTON_GROUP_VARIANTS)[number];
|
|
130
|
+
/** Whether the group's buttons can be selected: none, one at a time, or any number. */
|
|
131
|
+
export declare const BUTTON_GROUP_SELECTIONS: readonly ["none", "single", "multiple"];
|
|
132
|
+
export type ButtonGroupSelection = (typeof BUTTON_GROUP_SELECTIONS)[number];
|
|
133
|
+
/** Identifies a button inside a selecting group, through its `value` prop. */
|
|
134
|
+
export type ButtonGroupValue = string | number;
|
|
135
|
+
/** The selected value for `single` (or `undefined`), or the selected values for `multiple`. */
|
|
136
|
+
export type ButtonGroupSelected = ButtonGroupValue | ButtonGroupValue[] | undefined;
|
|
137
|
+
export interface ButtonGroupProps {
|
|
138
|
+
/** Defaults to `'standard'`. */
|
|
139
|
+
variant?: ButtonGroupVariant;
|
|
140
|
+
/** The size of every button in the group that doesn't set its own. Defaults to `'small'`. */
|
|
141
|
+
size?: ButtonSize;
|
|
142
|
+
/** The shape of every button in the group that doesn't set its own. Defaults to `'round'`. */
|
|
143
|
+
shape?: ButtonShape;
|
|
144
|
+
/**
|
|
145
|
+
* Turns buttons that have a `value` into toggle buttons whose selection the group keeps.
|
|
146
|
+
* Defaults to `'none'`, where every button acts on its own.
|
|
147
|
+
*/
|
|
148
|
+
selection?: ButtonGroupSelection;
|
|
149
|
+
/** With a selection, keeps at least one button selected: the last one can't be turned off. */
|
|
150
|
+
required?: boolean;
|
|
151
|
+
/** The selected value (`single`) or values (`multiple`). */
|
|
152
|
+
selected?: ButtonGroupSelected;
|
|
153
|
+
}
|
|
154
|
+
export declare const buttonGroupDefaults: {
|
|
155
|
+
variant: "standard";
|
|
156
|
+
size: "small";
|
|
157
|
+
shape: "round";
|
|
158
|
+
selection: "none";
|
|
159
|
+
required: false;
|
|
160
|
+
};
|
|
161
|
+
export interface ButtonGroupOptions {
|
|
162
|
+
/** Returns the current prop values. The adapter owns the state. */
|
|
163
|
+
props: () => ButtonGroupProps;
|
|
164
|
+
/** Called with the requested selection. Adapters wire it to v-model, a callback prop, and so on. */
|
|
165
|
+
onChange: (selected: ButtonGroupSelected) => void;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The button group's markup. `buttonGroupSkeleton` says how the adapter renders it.
|
|
169
|
+
*/
|
|
170
|
+
export interface ButtonGroupParts {
|
|
171
|
+
root: () => PartAttrs;
|
|
172
|
+
}
|
|
173
|
+
/** How the adapter renders the button group: one root, with the buttons as its direct children. */
|
|
174
|
+
export declare const buttonGroupSkeleton: PartNode<keyof ButtonGroupParts>;
|
|
175
|
+
export interface ButtonGroupApi {
|
|
176
|
+
parts: ButtonGroupParts;
|
|
177
|
+
/** The size for buttons that don't set their own, with the default filled in. */
|
|
178
|
+
size: () => ButtonSize;
|
|
179
|
+
/** The shape for buttons that don't set their own, with the default filled in. */
|
|
180
|
+
shape: () => ButtonShape;
|
|
181
|
+
/** The selection mode, with the default filled in. */
|
|
182
|
+
selection: () => ButtonGroupSelection;
|
|
183
|
+
/** Whether the button with this value is selected. */
|
|
184
|
+
isSelected: (value: ButtonGroupValue) => boolean;
|
|
185
|
+
/**
|
|
186
|
+
* Requests turning the button with this value on or off. The group applies its selection rules:
|
|
187
|
+
* a single selection turns the previous button off, and `required` keeps the last one on.
|
|
188
|
+
*/
|
|
189
|
+
select: (value: ButtonGroupValue, selected: boolean) => void;
|
|
190
|
+
}
|
|
191
|
+
export declare function createButtonGroup(options: ButtonGroupOptions): ButtonGroupApi;
|
|
192
|
+
export interface ButtonGroupInteractionOptions {
|
|
193
|
+
/**
|
|
194
|
+
* How much wider a pressed button gets, as a share of its width. Each neighbor gives up at most
|
|
195
|
+
* the same share of its own width. Defaults to 0.15, the spec's 15%.
|
|
196
|
+
*/
|
|
197
|
+
pressedWidthRatio?: number;
|
|
198
|
+
}
|
|
199
|
+
export interface ButtonGroupHandle {
|
|
200
|
+
detach(): void;
|
|
201
|
+
}
|
|
202
|
+
export declare function attachButtonGroup(root: HTMLElement, options?: ButtonGroupInteractionOptions): ButtonGroupHandle;
|
|
203
|
+
/**
|
|
204
|
+
* The dialog's ARIA role: `alertdialog` for a prompt that asks for a response, such as a
|
|
205
|
+
* confirmation, and `dialog` for one that holds a list or a form.
|
|
206
|
+
*/
|
|
207
|
+
export declare const DIALOG_ROLES: readonly ["alertdialog", "dialog"];
|
|
208
|
+
export type DialogRole = (typeof DIALOG_ROLES)[number];
|
|
209
|
+
export interface DialogProps {
|
|
210
|
+
/** Whether the dialog is shown. */
|
|
211
|
+
open?: boolean;
|
|
212
|
+
/** Defaults to `'alertdialog'`. */
|
|
213
|
+
role?: DialogRole;
|
|
214
|
+
}
|
|
215
|
+
export declare const dialogDefaults: {
|
|
216
|
+
open: false;
|
|
217
|
+
role: "alertdialog";
|
|
218
|
+
};
|
|
219
|
+
/** What the adapter has to put in the dialog, which only the adapter can see. */
|
|
220
|
+
export interface DialogContent {
|
|
221
|
+
/** An icon above the headline */
|
|
222
|
+
icon: boolean;
|
|
223
|
+
headline: boolean;
|
|
224
|
+
/** Buttons below the content */
|
|
225
|
+
actions: boolean;
|
|
226
|
+
}
|
|
227
|
+
export interface DialogOptions {
|
|
228
|
+
props: () => DialogProps;
|
|
229
|
+
/** Without it, the dialog has only its content. */
|
|
230
|
+
content?: () => DialogContent;
|
|
231
|
+
/** Ids for the parts the dialog refers to, unique in the document. The adapter makes them. */
|
|
232
|
+
ids: {
|
|
233
|
+
headline: string;
|
|
234
|
+
content: string;
|
|
235
|
+
};
|
|
54
236
|
}
|
|
55
|
-
export
|
|
237
|
+
export interface DialogParts {
|
|
238
|
+
/** The `<dialog>`, shown in the top layer */
|
|
239
|
+
root: () => PartAttrs;
|
|
240
|
+
/** Holds the icon, which only decorates: the headline says what the dialog is for. */
|
|
241
|
+
icon: () => PartAttrs;
|
|
242
|
+
headline: () => PartAttrs;
|
|
243
|
+
/** Holds the supporting text, or a list or a form. It scrolls when it doesn't fit. */
|
|
244
|
+
content: () => PartAttrs;
|
|
245
|
+
/** Holds the buttons. */
|
|
246
|
+
actions: () => PartAttrs;
|
|
247
|
+
}
|
|
248
|
+
type DialogPart = keyof DialogParts;
|
|
249
|
+
type DialogWhen = 'showsIcon' | 'showsHeadline' | 'showsActions';
|
|
250
|
+
/**
|
|
251
|
+
* The markup of an open dialog. The parts inside render from opening until `attachDialog`'s
|
|
252
|
+
* `onClosed`; a closed dialog is the empty `<dialog>`.
|
|
253
|
+
*/
|
|
254
|
+
export declare const dialogSkeleton: PartNode<DialogPart, DialogWhen>;
|
|
255
|
+
export interface DialogApi extends Record<DialogWhen, () => boolean> {
|
|
256
|
+
parts: DialogParts;
|
|
257
|
+
}
|
|
258
|
+
export declare function createDialog(options: DialogOptions): DialogApi;
|
|
259
|
+
/** What asks the dialog to close: Escape (or the back gesture), or a click on the scrim */
|
|
260
|
+
export type DialogCancelReason = 'escape' | 'scrim';
|
|
261
|
+
export interface DialogCancelEvent extends CancelableEvent {
|
|
262
|
+
readonly reason: DialogCancelReason;
|
|
263
|
+
readonly defaultPrevented: boolean;
|
|
264
|
+
}
|
|
265
|
+
export interface DialogDomOptions {
|
|
266
|
+
/** Escape or a click on the scrim asks to close. Canceling the event keeps the dialog open. */
|
|
267
|
+
onCancel?: (event: DialogCancelEvent) => void;
|
|
268
|
+
/** The dialog closes on its own, or is asked to and isn't kept open. The adapter sets `open`. */
|
|
269
|
+
onOpenChange: (open: boolean) => void;
|
|
270
|
+
/**
|
|
271
|
+
* The dialog finished closing, its motion included, and hasn't opened again since. The adapter
|
|
272
|
+
* renders the content from opening until then.
|
|
273
|
+
*/
|
|
274
|
+
onClosed?: () => void;
|
|
275
|
+
}
|
|
276
|
+
export interface DialogDomHandle {
|
|
277
|
+
/** Brings the dialog in line with `open`. Call it once attached, and whenever `open` changes. */
|
|
278
|
+
sync(open: boolean): void;
|
|
279
|
+
/** Call it after the content changed, to update the dividers. */
|
|
280
|
+
update(): void;
|
|
281
|
+
detach(): void;
|
|
282
|
+
}
|
|
283
|
+
export declare function attachDialog(root: HTMLDialogElement, options: DialogDomOptions): DialogDomHandle;
|
|
56
284
|
export declare const ICON_BUTTON_VARIANTS: readonly ["filled", "tonal", "outlined", "standard"];
|
|
57
285
|
export type IconButtonVariant = (typeof ICON_BUTTON_VARIANTS)[number];
|
|
58
286
|
/** M3E icon button widths. `default` makes a square (or circle) as wide as it is tall. */
|
|
@@ -82,6 +310,8 @@ export interface IconButtonProps {
|
|
|
82
310
|
softDisabled?: boolean;
|
|
83
311
|
/** Defaults to `'button'`, so it doesn't submit a form by accident. */
|
|
84
312
|
type?: 'button' | 'submit' | 'reset';
|
|
313
|
+
/** Identifies the button inside a button group that keeps a selection, as on the button. */
|
|
314
|
+
value?: ButtonGroupValue;
|
|
85
315
|
}
|
|
86
316
|
export declare const iconButtonDefaults: {
|
|
87
317
|
variant: "filled";
|
|
@@ -94,15 +324,327 @@ export declare const iconButtonDefaults: {
|
|
|
94
324
|
softDisabled: false;
|
|
95
325
|
type: "button";
|
|
96
326
|
};
|
|
97
|
-
|
|
327
|
+
/** What the adapter has to put in the icon button, which only the adapter can see. */
|
|
328
|
+
export interface IconButtonContent {
|
|
329
|
+
/** Whether there is an icon for the selected state. */
|
|
330
|
+
selectedIcon: boolean;
|
|
331
|
+
}
|
|
332
|
+
export interface IconButtonOptions<E extends CancelableEvent = MouseEvent> {
|
|
98
333
|
/** Returns the current prop values. The adapter owns the state. */
|
|
99
334
|
props: () => IconButtonProps;
|
|
100
|
-
/**
|
|
101
|
-
|
|
102
|
-
/** Called
|
|
103
|
-
|
|
335
|
+
/** Returns what content the adapter has. Without it, there is no selected icon. */
|
|
336
|
+
content?: () => IconButtonContent;
|
|
337
|
+
/** Called for a click that isn't blocked, with the event `handleClick` got. */
|
|
338
|
+
onClick: (event: E) => void;
|
|
339
|
+
/** Called after an unblocked click on a toggle button, with the requested value. */
|
|
340
|
+
onChange: (selected: boolean) => void;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* The icon button's markup, part by part. `iconButtonSkeleton` says how the adapter nests them.
|
|
344
|
+
*/
|
|
345
|
+
export interface IconButtonParts {
|
|
346
|
+
root: () => PartAttrs;
|
|
347
|
+
/** Extends small icon buttons to the 48px target. */
|
|
348
|
+
touch: () => PartAttrs;
|
|
349
|
+
icon: () => PartAttrs;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* How the adapter renders the icon button's parts. The icon holds the selected icon when
|
|
353
|
+
* `showsSelectedIcon()`, otherwise the default one.
|
|
354
|
+
*/
|
|
355
|
+
export declare const iconButtonSkeleton: PartNode<keyof IconButtonParts>;
|
|
356
|
+
export interface IconButtonApi<E extends CancelableEvent = MouseEvent> {
|
|
357
|
+
parts: IconButtonParts;
|
|
358
|
+
/** Whether the icon part shows the selected icon instead of the default one. */
|
|
359
|
+
showsSelectedIcon: () => boolean;
|
|
360
|
+
/** Attach to the root element's `click`. */
|
|
361
|
+
handleClick: (event: E) => void;
|
|
362
|
+
}
|
|
363
|
+
export declare function createIconButton<E extends CancelableEvent = MouseEvent>(options: IconButtonOptions<E>): IconButtonApi<E>;
|
|
364
|
+
export type AnchoredSide = 'top' | 'bottom' | 'start' | 'end';
|
|
365
|
+
export type AnchoredAlign = 'start' | 'center' | 'end';
|
|
366
|
+
/** A point in viewport coordinates, such as a pointer event's `clientX` and `clientY`. */
|
|
367
|
+
export interface AnchorPoint {
|
|
368
|
+
x: number;
|
|
369
|
+
y: number;
|
|
370
|
+
}
|
|
371
|
+
export interface AnchoredPositionOptions {
|
|
372
|
+
/** Returns the anchor. Placing is skipped while it returns nothing. */
|
|
373
|
+
anchor: () => Element | AnchorPoint | null | undefined;
|
|
374
|
+
/** The preferred side of the anchor. Defaults to `'bottom'`. */
|
|
375
|
+
side?: AnchoredSide;
|
|
376
|
+
/** Which edges line up along that side. Defaults to `'start'`. */
|
|
377
|
+
align?: AnchoredAlign;
|
|
378
|
+
/** Space between the anchor and the element, in px. Defaults to 0. */
|
|
379
|
+
offset?: number;
|
|
380
|
+
/**
|
|
381
|
+
* Moves the element along the anchor, in px, once lined up: down beside the anchor, toward the
|
|
382
|
+
* end of the line above or below it. Defaults to 0. A submenu uses it to line its first item up
|
|
383
|
+
* with the item that opened it.
|
|
384
|
+
*/
|
|
385
|
+
alignOffset?: number;
|
|
386
|
+
/** Sides to try, in order, when the preferred one has no room. Defaults to the opposite side. */
|
|
387
|
+
fallbacks?: readonly AnchoredSide[];
|
|
388
|
+
/** Space kept from the edges of the window, in px. Defaults to 8. */
|
|
389
|
+
padding?: number;
|
|
390
|
+
}
|
|
391
|
+
export interface AnchoredPositionHandle {
|
|
392
|
+
/** Places the element now, for example after the anchor point moved. */
|
|
393
|
+
update(): void;
|
|
394
|
+
detach(): void;
|
|
395
|
+
}
|
|
396
|
+
export declare function attachAnchoredPosition(floating: HTMLElement, options: AnchoredPositionOptions): AnchoredPositionHandle;
|
|
397
|
+
/** M3E vertical menu color styles: surface-based, or tertiary-based for more emphasis. */
|
|
398
|
+
export declare const MENU_VARIANTS: readonly ["standard", "vibrant"];
|
|
399
|
+
export type MenuVariant = (typeof MENU_VARIANTS)[number];
|
|
400
|
+
/** Whether the menu's items can be selected: none, one at a time, or any number. */
|
|
401
|
+
export declare const MENU_SELECTIONS: readonly ["none", "single", "multiple"];
|
|
402
|
+
export type MenuSelection = (typeof MENU_SELECTIONS)[number];
|
|
403
|
+
/** Identifies an item in a selecting menu, through its `value` prop. */
|
|
404
|
+
export type MenuValue = string | number;
|
|
405
|
+
/** The selected value for `single` (or `undefined`), or the selected values for `multiple`. */
|
|
406
|
+
export type MenuSelected = MenuValue | MenuValue[] | undefined;
|
|
407
|
+
export interface MenuProps {
|
|
408
|
+
/** Whether the menu is shown. */
|
|
409
|
+
open?: boolean;
|
|
410
|
+
/** Defaults to `'standard'`. */
|
|
411
|
+
variant?: MenuVariant;
|
|
412
|
+
/**
|
|
413
|
+
* Makes items with a `value` selectable, and keeps the selection. Defaults to `'none'`, where
|
|
414
|
+
* choosing an item only runs its action.
|
|
415
|
+
*/
|
|
416
|
+
selection?: MenuSelection;
|
|
417
|
+
/** The selected value (`single`) or values (`multiple`). */
|
|
418
|
+
selected?: MenuSelected;
|
|
419
|
+
/** Names the menu for assistive technology, such as the label of the button that opens it. */
|
|
420
|
+
label?: string;
|
|
421
|
+
/** The side of the anchor it opens on, when there is room. Defaults to `'bottom'`. */
|
|
422
|
+
side?: AnchoredSide;
|
|
423
|
+
/** Which edges line up with the anchor's. Defaults to `'start'`. */
|
|
424
|
+
align?: AnchoredAlign;
|
|
425
|
+
/** Space between the anchor and the menu, in px. Defaults to 0; a split button's menu uses 4. */
|
|
426
|
+
offset?: number;
|
|
427
|
+
/** Opens and closes without the expanding motion, as dense desktop products may. */
|
|
428
|
+
instant?: boolean;
|
|
429
|
+
}
|
|
430
|
+
export declare const menuDefaults: {
|
|
431
|
+
open: false;
|
|
432
|
+
variant: "standard";
|
|
433
|
+
selection: "none";
|
|
434
|
+
side: "bottom";
|
|
435
|
+
align: "start";
|
|
436
|
+
offset: number;
|
|
437
|
+
instant: false;
|
|
438
|
+
};
|
|
439
|
+
export interface MenuOptions {
|
|
440
|
+
/** Returns the current prop values. The adapter owns the state. */
|
|
441
|
+
props: () => MenuProps;
|
|
442
|
+
/** Called with the requested selection. */
|
|
443
|
+
onChange: (selected: MenuSelected) => void;
|
|
444
|
+
/** Called with the requested `open`, such as `false` once an item is chosen. */
|
|
445
|
+
onOpenChange: (open: boolean) => void;
|
|
446
|
+
}
|
|
447
|
+
export interface MenuParts {
|
|
448
|
+
/** The surface, shown in the top layer. Its children are items, dividers, and groups. */
|
|
449
|
+
root: () => PartAttrs;
|
|
450
|
+
}
|
|
451
|
+
export declare const menuSkeleton: PartNode<keyof MenuParts>;
|
|
452
|
+
export interface MenuApi {
|
|
453
|
+
parts: MenuParts;
|
|
454
|
+
/** The selection mode, with the default filled in. */
|
|
455
|
+
selection: () => MenuSelection;
|
|
456
|
+
/** Whether the item with this value is selected. */
|
|
457
|
+
isSelected: (value: MenuValue) => boolean;
|
|
458
|
+
/**
|
|
459
|
+
* An item was chosen. With a `value` in a selecting menu, the selection rules apply: `single`
|
|
460
|
+
* selects it, `multiple` toggles it. Then the menu asks to close, except for `multiple`, which
|
|
461
|
+
* stays open until dismissed.
|
|
462
|
+
*/
|
|
463
|
+
choose: (value?: MenuValue) => void;
|
|
464
|
+
/** Asks the menu to close. In a submenu, the whole menu closes, as after a choice. */
|
|
465
|
+
close: () => void;
|
|
466
|
+
/** The color style, with the default filled in, which submenus take on. */
|
|
467
|
+
variant: () => MenuVariant;
|
|
468
|
+
/** Whether the menu opens without its motion, which submenus take on. */
|
|
469
|
+
instant: () => boolean;
|
|
470
|
+
}
|
|
471
|
+
export declare function createMenu(options: MenuOptions): MenuApi;
|
|
472
|
+
export interface MenuItemProps {
|
|
473
|
+
/** Makes the item selectable in a menu that keeps a selection. */
|
|
474
|
+
value?: MenuValue;
|
|
475
|
+
/** Still focusable, but can't be chosen. */
|
|
476
|
+
disabled?: boolean;
|
|
477
|
+
}
|
|
478
|
+
export declare const menuItemDefaults: {
|
|
479
|
+
disabled: false;
|
|
480
|
+
};
|
|
481
|
+
/** What the adapter has to put in the item, which only the adapter can see. */
|
|
482
|
+
export interface MenuItemContent {
|
|
483
|
+
/** A leading icon */
|
|
484
|
+
icon: boolean;
|
|
485
|
+
/** Supporting text under the label */
|
|
486
|
+
supportingText: boolean;
|
|
487
|
+
/** Trailing text, such as a keyboard shortcut */
|
|
488
|
+
trailingText: boolean;
|
|
489
|
+
/** A trailing icon */
|
|
490
|
+
trailingIcon: boolean;
|
|
491
|
+
}
|
|
492
|
+
export interface MenuItemOptions<E extends CancelableEvent = MouseEvent> {
|
|
493
|
+
props: () => MenuItemProps;
|
|
494
|
+
/** Without it, the item has only a label. */
|
|
495
|
+
content?: () => MenuItemContent;
|
|
496
|
+
/** The menu around the item. Without one, the item acts as in a menu without a selection. */
|
|
497
|
+
menu?: () => Pick<MenuApi, 'selection' | 'isSelected' | 'choose'> | undefined;
|
|
498
|
+
/**
|
|
499
|
+
* Called for a click on the item that isn't blocked, before the menu is told, with the event
|
|
500
|
+
* `handleClick` got.
|
|
501
|
+
*/
|
|
502
|
+
onClick: (event: E) => void;
|
|
503
|
+
/**
|
|
504
|
+
* Makes it the item that opens a submenu (see `createSubMenu`): a click opens the submenu rather
|
|
505
|
+
* than choosing the item.
|
|
506
|
+
*/
|
|
507
|
+
submenu?: {
|
|
508
|
+
/** Whether the submenu is open */
|
|
509
|
+
open: () => boolean;
|
|
510
|
+
/** Asks for the submenu to open. */
|
|
511
|
+
onOpen: () => void;
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
export interface MenuItemParts {
|
|
515
|
+
/** A `<button>` with the item's role */
|
|
516
|
+
root: () => PartAttrs;
|
|
517
|
+
/** Extends the 44px item to a 48px target, over the space between items. */
|
|
518
|
+
touch: () => PartAttrs;
|
|
519
|
+
icon: () => PartAttrs;
|
|
520
|
+
/** Holds the label and the supporting text, one above the other */
|
|
521
|
+
text: () => PartAttrs;
|
|
522
|
+
label: () => PartAttrs;
|
|
523
|
+
supportingText: () => PartAttrs;
|
|
524
|
+
trailingText: () => PartAttrs;
|
|
525
|
+
trailingIcon: () => PartAttrs;
|
|
526
|
+
}
|
|
527
|
+
type MenuItemWhen = 'showsIcon' | 'showsSupportingText' | 'showsTrailingText' | 'showsTrailingIcon';
|
|
528
|
+
export declare const menuItemSkeleton: PartNode<keyof MenuItemParts, MenuItemWhen>;
|
|
529
|
+
export interface MenuItemApi<E extends CancelableEvent = MouseEvent> extends Record<MenuItemWhen, () => boolean> {
|
|
530
|
+
parts: MenuItemParts;
|
|
531
|
+
/** Whether the item is selected, in a menu that keeps a selection. */
|
|
532
|
+
selected: () => boolean;
|
|
533
|
+
/** Attach to the item's `click`. */
|
|
534
|
+
handleClick: (event: E) => void;
|
|
104
535
|
}
|
|
105
|
-
export declare function
|
|
536
|
+
export declare function createMenuItem<E extends CancelableEvent = MouseEvent>(options: MenuItemOptions<E>): MenuItemApi<E>;
|
|
537
|
+
export interface SubMenuProps {
|
|
538
|
+
/** The label of the item that opens the submenu, which also names the submenu. */
|
|
539
|
+
label?: string;
|
|
540
|
+
/** The item stays focusable but doesn't open the submenu. */
|
|
541
|
+
disabled?: boolean;
|
|
542
|
+
/** As a menu's: a submenu keeps its own selection, such as a sort order. */
|
|
543
|
+
selection?: MenuSelection;
|
|
544
|
+
/** The selected value (`single`) or values (`multiple`). */
|
|
545
|
+
selected?: MenuSelected;
|
|
546
|
+
}
|
|
547
|
+
export interface SubMenuOptions {
|
|
548
|
+
props: () => SubMenuProps;
|
|
549
|
+
/** What the adapter put in the item that opens it. Without it, the item has only a label. */
|
|
550
|
+
content?: () => MenuItemContent;
|
|
551
|
+
/** The menu the submenu is in. Its color style and motion carry over, and choosing closes it. */
|
|
552
|
+
menu?: () => Pick<MenuApi, 'variant' | 'instant' | 'close'> | undefined;
|
|
553
|
+
/** Whether the submenu is open: the adapter owns it. */
|
|
554
|
+
open: () => boolean;
|
|
555
|
+
/** Called with the requested selection. */
|
|
556
|
+
onChange: (selected: MenuSelected) => void;
|
|
557
|
+
/** Called with the requested `open`: `true` for a click on its item. */
|
|
558
|
+
onOpenChange: (open: boolean) => void;
|
|
559
|
+
}
|
|
560
|
+
export interface SubMenuApi {
|
|
561
|
+
/**
|
|
562
|
+
* The item that opens the submenu, with the parts of a menu item (`menuItemSkeleton`). A click on
|
|
563
|
+
* it reports no event, so its `handleClick` takes any event it can cancel.
|
|
564
|
+
*/
|
|
565
|
+
item: MenuItemApi<CancelableEvent>;
|
|
566
|
+
/** The submenu, with the parts of a menu (`menuSkeleton`). Its items take it as their menu. */
|
|
567
|
+
menu: MenuApi;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* A submenu and the item that opens it. The two render side by side in the menu, the item where it
|
|
571
|
+
* sits and the submenu after it; the submenu shows in the top layer next to the item.
|
|
572
|
+
*/
|
|
573
|
+
export declare function createSubMenu(options: SubMenuOptions): SubMenuApi;
|
|
574
|
+
export interface MenuGroupProps {
|
|
575
|
+
/** A label shown above the group's items, which also names the group. */
|
|
576
|
+
label?: string;
|
|
577
|
+
}
|
|
578
|
+
export interface MenuGroupParts {
|
|
579
|
+
root: () => PartAttrs;
|
|
580
|
+
/** The visible label. Assistive technology reads the name from the root instead. */
|
|
581
|
+
label: () => PartAttrs;
|
|
582
|
+
/** Holds the group's items. */
|
|
583
|
+
items: () => PartAttrs;
|
|
584
|
+
}
|
|
585
|
+
export declare const menuGroupSkeleton: PartNode<keyof MenuGroupParts, 'showsLabel'>;
|
|
586
|
+
export interface MenuGroupApi {
|
|
587
|
+
parts: MenuGroupParts;
|
|
588
|
+
showsLabel: () => boolean;
|
|
589
|
+
}
|
|
590
|
+
export declare function createMenuGroup(options: {
|
|
591
|
+
props: () => MenuGroupProps;
|
|
592
|
+
}): MenuGroupApi;
|
|
593
|
+
export interface MenuDividerParts {
|
|
594
|
+
root: () => PartAttrs;
|
|
595
|
+
}
|
|
596
|
+
export declare const menuDividerSkeleton: PartNode<keyof MenuDividerParts>;
|
|
597
|
+
export declare function createMenuDivider(): {
|
|
598
|
+
parts: MenuDividerParts;
|
|
599
|
+
};
|
|
600
|
+
/**
|
|
601
|
+
* A point a menu opens at, such as where a context menu was asked for, in viewport coordinates.
|
|
602
|
+
* With `element`, what the point is on, the menu keeps to that spot on it as it scrolls, as it
|
|
603
|
+
* follows an element anchor. Without, it stays where the point is on the screen.
|
|
604
|
+
*/
|
|
605
|
+
export interface MenuAnchorPoint extends AnchorPoint {
|
|
606
|
+
element?: Element;
|
|
607
|
+
}
|
|
608
|
+
export interface MenuDomOptions {
|
|
609
|
+
/** What the menu opens from: an element, such as a button, or a point, for a context menu. */
|
|
610
|
+
anchor: () => HTMLElement | MenuAnchorPoint | null | undefined;
|
|
611
|
+
/** The placement props, read when the menu opens. */
|
|
612
|
+
props: () => Pick<MenuProps, 'side' | 'align' | 'offset'>;
|
|
613
|
+
/**
|
|
614
|
+
* The menu closed, or asks to close, on its own: Escape, a click outside, Tab, or another
|
|
615
|
+
* overlay opening. The adapter sets `open` to false.
|
|
616
|
+
*/
|
|
617
|
+
onClose: () => void;
|
|
618
|
+
}
|
|
619
|
+
export interface MenuDomHandle {
|
|
620
|
+
/** Brings the menu in line with `open`. Call it once attached, and whenever `open` changes. */
|
|
621
|
+
sync(open: boolean): void;
|
|
622
|
+
/**
|
|
623
|
+
* Call it when the anchor changes. An anchor other than the one the menu opened at is a new
|
|
624
|
+
* request, as from another right-click: an open menu opens afresh there, with its opening motion.
|
|
625
|
+
* One that fills in where there was none, such as a template ref, only places it.
|
|
626
|
+
*/
|
|
627
|
+
update(): void;
|
|
628
|
+
detach(): void;
|
|
629
|
+
}
|
|
630
|
+
export interface SubMenuDomOptions {
|
|
631
|
+
/**
|
|
632
|
+
* The submenu opens or closes on its own: the pointer, the arrow keys, Escape, or a click
|
|
633
|
+
* elsewhere. The adapter sets its `open` to match.
|
|
634
|
+
*/
|
|
635
|
+
onOpenChange: (open: boolean) => void;
|
|
636
|
+
}
|
|
637
|
+
export interface SubMenuDomHandle {
|
|
638
|
+
/** Brings the submenu in line with `open`. Call it once attached, and whenever `open` changes. */
|
|
639
|
+
sync(open: boolean): void;
|
|
640
|
+
detach(): void;
|
|
641
|
+
}
|
|
642
|
+
export declare function attachMenu(root: HTMLElement, options: MenuDomOptions): MenuDomHandle;
|
|
643
|
+
/**
|
|
644
|
+
* A submenu's behavior in the DOM: a menu (see `attachMenu`) that `item` opens, shown beside it.
|
|
645
|
+
* `item` sits in a menu that `attachMenu` or this function runs, and `root` follows it.
|
|
646
|
+
*/
|
|
647
|
+
export declare function attachSubMenu(item: HTMLElement, root: HTMLElement, options: SubMenuDomOptions): SubMenuDomHandle;
|
|
106
648
|
export interface DragInfo {
|
|
107
649
|
/** Distance from where the press started, in px. */
|
|
108
650
|
dx: number;
|
|
@@ -126,6 +668,41 @@ export interface DragHandle {
|
|
|
126
668
|
detach(): void;
|
|
127
669
|
}
|
|
128
670
|
export declare function attachDrag(element: HTMLElement, options: DragOptions): DragHandle;
|
|
671
|
+
export type OverlayMode = 'auto' | 'manual' | 'modal';
|
|
672
|
+
/**
|
|
673
|
+
* Why an overlay closed, or asks to close, without the adapter asking:
|
|
674
|
+
* - `'escape'`: Escape, or the back gesture on a dialog. The overlay is still open, and the adapter
|
|
675
|
+
* can turn the request down, as a dialog with unsaved changes might.
|
|
676
|
+
* - `'dismiss'`: the browser closed it: a click outside, or another popover or a modal dialog
|
|
677
|
+
* opening.
|
|
678
|
+
* - `'parent'`: the overlay it was opened from closed.
|
|
679
|
+
* - `'replaced'`: another overlay opened, and this transient one gave way.
|
|
680
|
+
*
|
|
681
|
+
* All but `'escape'` arrive after the overlay closed, so the adapter has to follow them.
|
|
682
|
+
*/
|
|
683
|
+
export type OverlayCloseReason = 'escape' | 'dismiss' | 'parent' | 'replaced';
|
|
684
|
+
export interface OverlayOptions {
|
|
685
|
+
mode: OverlayMode;
|
|
686
|
+
/** Closes when any other overlay opens, as a tooltip does. */
|
|
687
|
+
transient?: boolean;
|
|
688
|
+
/** Keeps clicks and presses in the element from bubbling past it, as a tooltip and a dialog do. */
|
|
689
|
+
contain?: boolean;
|
|
690
|
+
/** The overlay closed, or asks to close, without the adapter asking. */
|
|
691
|
+
onClose: (reason: OverlayCloseReason) => void;
|
|
692
|
+
}
|
|
693
|
+
export interface OverlayHandle {
|
|
694
|
+
/**
|
|
695
|
+
* Shows the element. `source` is what opened it, such as a menu item: a popover shown from
|
|
696
|
+
* inside an auto popover keeps that one open, and closes with it.
|
|
697
|
+
*/
|
|
698
|
+
show(source?: HTMLElement): void;
|
|
699
|
+
/** Closes the element, without calling `onClose`. */
|
|
700
|
+
hide(): void;
|
|
701
|
+
/** Whether an overlay that opened after this one is still open, other than a transient one. */
|
|
702
|
+
covered(): boolean;
|
|
703
|
+
detach(): void;
|
|
704
|
+
}
|
|
705
|
+
export declare function attachOverlay(element: HTMLElement, options: OverlayOptions): OverlayHandle;
|
|
129
706
|
export interface RippleHandle {
|
|
130
707
|
/** Removes the listeners and the `data-ripple` marker. */
|
|
131
708
|
detach(): void;
|
|
@@ -147,22 +724,21 @@ export declare function attachRipple(element: HTMLElement, options?: RippleOptio
|
|
|
147
724
|
export interface ShapeMorphOptions {
|
|
148
725
|
/** The motion token whose spring drives the morph. Defaults to `'fast-spatial'`. */
|
|
149
726
|
token?: string;
|
|
150
|
-
/** Attributes whose changes can move the target. Defaults to Rio's state attributes. */
|
|
151
|
-
watch?: string[];
|
|
152
727
|
}
|
|
153
728
|
export interface ShapeMorphHandle {
|
|
154
729
|
detach(): void;
|
|
155
730
|
}
|
|
156
731
|
export declare function attachShapeMorph(element: HTMLElement, options?: ShapeMorphOptions): ShapeMorphHandle;
|
|
157
732
|
export interface SpringPropertyOptions {
|
|
158
|
-
/**
|
|
733
|
+
/**
|
|
734
|
+
* A registered custom property that holds the target for the current state: a <length>, read
|
|
735
|
+
* in px, or an <angle>, read in deg. The stylesheet has to transition it (see above).
|
|
736
|
+
*/
|
|
159
737
|
target: string;
|
|
160
|
-
/** Writes the animated value
|
|
738
|
+
/** Writes the animated value (px or deg), or clears it with `undefined` at rest. */
|
|
161
739
|
apply: (value: number | undefined) => void;
|
|
162
740
|
/** The motion token whose spring drives the value. Defaults to `'fast-spatial'`. */
|
|
163
741
|
token?: string;
|
|
164
|
-
/** Attributes whose changes can move the target. Defaults to Rio's state attributes. */
|
|
165
|
-
watch?: string[];
|
|
166
742
|
}
|
|
167
743
|
export interface SpringPropertyHandle {
|
|
168
744
|
/** The current animated value. */
|
|
@@ -173,8 +749,6 @@ export interface SpringPropertyHandle {
|
|
|
173
749
|
release(velocity?: number): void;
|
|
174
750
|
detach(): void;
|
|
175
751
|
}
|
|
176
|
-
/** The data attributes Rio's components use for state. */
|
|
177
|
-
export declare const STATE_ATTRIBUTES: string[];
|
|
178
752
|
export declare function attachSpringProperty(element: HTMLElement, options: SpringPropertyOptions): SpringPropertyHandle;
|
|
179
753
|
export interface SpringParams {
|
|
180
754
|
/** 1 settles without overshoot; lower values bounce, higher values approach more slowly. */
|
|
@@ -220,6 +794,11 @@ export interface Spring {
|
|
|
220
794
|
}
|
|
221
795
|
/** A spring that animates a single number with `requestAnimationFrame`. */
|
|
222
796
|
export declare function createSpring(options: SpringOptions): Spring;
|
|
797
|
+
/**
|
|
798
|
+
* Whether the user asked for reduced motion. Spatial springs should jump straight to their target
|
|
799
|
+
* (or be skipped) when it is on; see `docs/foundations.md`, section 3.
|
|
800
|
+
*/
|
|
801
|
+
export declare function prefersReducedMotion(): boolean;
|
|
223
802
|
/**
|
|
224
803
|
* Reads a motion token's spring from CSS variables on an element, for example
|
|
225
804
|
* `--rio-motion-fast-spatial-damping` and `-stiffness`. Reading them from the element, rather than
|
|
@@ -227,11 +806,107 @@ export declare function createSpring(options: SpringOptions): Spring;
|
|
|
227
806
|
* Returns `undefined` when the theme doesn't define them.
|
|
228
807
|
*/
|
|
229
808
|
export declare function readSpringParams(element: Element, token: string): SpringParams | undefined;
|
|
809
|
+
export interface SplitButtonMenuIconHandle {
|
|
810
|
+
detach(): void;
|
|
811
|
+
}
|
|
812
|
+
/** Attach to the trailing button. */
|
|
813
|
+
export declare function attachSplitButtonMenuIcon(trailing: HTMLElement): SplitButtonMenuIconHandle;
|
|
814
|
+
/** Split button colors: the button's, without text. */
|
|
815
|
+
export declare const SPLIT_BUTTON_VARIANTS: readonly ["filled", "tonal", "outlined", "elevated"];
|
|
816
|
+
export type SplitButtonVariant = (typeof SPLIT_BUTTON_VARIANTS)[number];
|
|
817
|
+
/** What the trailing button opens, for `aria-haspopup`. */
|
|
818
|
+
export type SplitButtonPopup = 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';
|
|
819
|
+
export interface SplitButtonProps {
|
|
820
|
+
/**
|
|
821
|
+
* Names the trailing button. It should say that more choices for the leading action are there,
|
|
822
|
+
* such as "More watch options" next to "Watch later".
|
|
823
|
+
*/
|
|
824
|
+
menuLabel: string;
|
|
825
|
+
/**
|
|
826
|
+
* Names the leading button when it has no label text, only an icon. Ignored when there is label
|
|
827
|
+
* text, so the visible label stays the name (WCAG 2.5.3).
|
|
828
|
+
*/
|
|
829
|
+
label?: string;
|
|
830
|
+
/** Defaults to `'filled'`. */
|
|
831
|
+
variant?: SplitButtonVariant;
|
|
832
|
+
/** Defaults to `'small'`. */
|
|
833
|
+
size?: ButtonSize;
|
|
834
|
+
/** Whether what the trailing button opens is open. */
|
|
835
|
+
open?: boolean;
|
|
836
|
+
/** What the trailing button opens. Defaults to `'menu'`. */
|
|
837
|
+
popup?: SplitButtonPopup;
|
|
838
|
+
/** Native disabled, on both buttons: not focusable and not pressable. The spec's behavior. */
|
|
839
|
+
disabled?: boolean;
|
|
840
|
+
/** Disabled but still focusable, on both buttons, as on the button. Deviates from the spec. */
|
|
841
|
+
softDisabled?: boolean;
|
|
842
|
+
/** The leading button's type. Defaults to `'button'`; the trailing button is always `'button'`. */
|
|
843
|
+
type?: 'button' | 'submit' | 'reset';
|
|
844
|
+
}
|
|
845
|
+
export declare const splitButtonDefaults: {
|
|
846
|
+
variant: "filled";
|
|
847
|
+
size: "small";
|
|
848
|
+
open: false;
|
|
849
|
+
popup: "menu";
|
|
850
|
+
disabled: false;
|
|
851
|
+
softDisabled: false;
|
|
852
|
+
type: "button";
|
|
853
|
+
};
|
|
854
|
+
/** What the adapter has to put in the leading button, which only the adapter can see. */
|
|
855
|
+
export interface SplitButtonContent {
|
|
856
|
+
/** Whether there is a leading icon. */
|
|
857
|
+
icon: boolean;
|
|
858
|
+
/** Whether there is label text. */
|
|
859
|
+
label: boolean;
|
|
860
|
+
}
|
|
861
|
+
export interface SplitButtonOptions<E extends CancelableEvent = MouseEvent> {
|
|
862
|
+
/** Returns the current prop values. The adapter owns the state. */
|
|
863
|
+
props: () => SplitButtonProps;
|
|
864
|
+
/** Returns what content the adapter has. Without it, the leading button has only a label. */
|
|
865
|
+
content?: () => SplitButtonContent;
|
|
866
|
+
/**
|
|
867
|
+
* Called for a click on the leading button that isn't blocked, with the event
|
|
868
|
+
* `handleLeadingClick` got.
|
|
869
|
+
*/
|
|
870
|
+
onClick: (event: E) => void;
|
|
871
|
+
/** Called with the requested `open` when the trailing button is clicked and isn't blocked. */
|
|
872
|
+
onChange: (open: boolean) => void;
|
|
873
|
+
}
|
|
874
|
+
/** The split button's markup, part by part. `splitButtonSkeleton` says how the adapter nests them. */
|
|
875
|
+
export interface SplitButtonParts {
|
|
876
|
+
root: () => PartAttrs;
|
|
877
|
+
/** The main action, a button with an icon, label text, or both. */
|
|
878
|
+
leading: () => PartAttrs;
|
|
879
|
+
/** The button that opens the menu. */
|
|
880
|
+
trailing: () => PartAttrs;
|
|
881
|
+
/** Extends each button to the 48px target. Both buttons have one. */
|
|
882
|
+
touch: () => PartAttrs;
|
|
883
|
+
icon: () => PartAttrs;
|
|
884
|
+
label: () => PartAttrs;
|
|
885
|
+
/** Holds the expand icon, which turns when the menu opens. */
|
|
886
|
+
menuIcon: () => PartAttrs;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* How the adapter renders the split button's parts. The icon and the label hold the leading
|
|
890
|
+
* button's content; the menu icon holds the expand icon the app provides.
|
|
891
|
+
*/
|
|
892
|
+
export declare const splitButtonSkeleton: PartNode<keyof SplitButtonParts, 'showsIcon' | 'showsLabel'>;
|
|
893
|
+
export interface SplitButtonApi<E extends CancelableEvent = MouseEvent> {
|
|
894
|
+
parts: SplitButtonParts;
|
|
895
|
+
/** Whether to render the icon part. */
|
|
896
|
+
showsIcon: () => boolean;
|
|
897
|
+
/** Whether to render the label part. */
|
|
898
|
+
showsLabel: () => boolean;
|
|
899
|
+
/** Attach to the leading button's `click`. */
|
|
900
|
+
handleLeadingClick: (event: E) => void;
|
|
901
|
+
/** Attach to the trailing button's `click`. */
|
|
902
|
+
handleTrailingClick: (event: E) => void;
|
|
903
|
+
}
|
|
904
|
+
export declare function createSplitButton<E extends CancelableEvent = MouseEvent>(options: SplitButtonOptions<E>): SplitButtonApi<E>;
|
|
230
905
|
export interface SwitchHandleOptions {
|
|
231
906
|
/** Returns whether the switch is on. */
|
|
232
907
|
selected: () => boolean;
|
|
233
908
|
/** Called when a drag ends on the other side. */
|
|
234
|
-
|
|
909
|
+
onChange: (selected: boolean) => void;
|
|
235
910
|
}
|
|
236
911
|
export interface SwitchHandleHandle {
|
|
237
912
|
detach(): void;
|
|
@@ -254,15 +929,148 @@ export declare const switchDefaults: {
|
|
|
254
929
|
disabled: false;
|
|
255
930
|
softDisabled: false;
|
|
256
931
|
};
|
|
932
|
+
/** What the adapter has to put in the switch, which only the adapter can see. */
|
|
933
|
+
export interface SwitchContent {
|
|
934
|
+
/** Whether there is an icon for the handle while the switch is on. */
|
|
935
|
+
selectedIcon: boolean;
|
|
936
|
+
/** Whether there is an icon for the handle while the switch is off. */
|
|
937
|
+
unselectedIcon: boolean;
|
|
938
|
+
}
|
|
257
939
|
export interface SwitchOptions {
|
|
258
940
|
/** Returns the current prop values. The adapter owns the state. */
|
|
259
941
|
props: () => SwitchProps;
|
|
260
|
-
/**
|
|
261
|
-
|
|
942
|
+
/** Returns what content the adapter has. Without it, the handle has no icons. */
|
|
943
|
+
content?: () => SwitchContent;
|
|
944
|
+
/** Called with the requested value. Adapters wire it to v-model, a callback prop, and so on. */
|
|
945
|
+
onChange: (selected: boolean) => void;
|
|
262
946
|
}
|
|
947
|
+
/**
|
|
948
|
+
* The switch's markup, part by part. `switchSkeleton` says how the adapter nests them.
|
|
949
|
+
*/
|
|
950
|
+
export interface SwitchParts {
|
|
951
|
+
root: () => PartAttrs;
|
|
952
|
+
/** Extends the 32px track to the 48px target. */
|
|
953
|
+
touch: () => PartAttrs;
|
|
954
|
+
state: () => PartAttrs;
|
|
955
|
+
handle: () => PartAttrs;
|
|
956
|
+
icon: () => PartAttrs;
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* How the adapter renders the switch's parts. The state part is the circle where the state layer
|
|
960
|
+
* and the ripple draw. The icon holds the selected icon when `showsSelectedIcon()`, otherwise the
|
|
961
|
+
* unselected one.
|
|
962
|
+
*/
|
|
963
|
+
export declare const switchSkeleton: PartNode<keyof SwitchParts, 'showsIcon'>;
|
|
263
964
|
export interface SwitchApi {
|
|
264
|
-
|
|
965
|
+
parts: SwitchParts;
|
|
966
|
+
/** Whether the handle shows an icon in the current state, which also makes it bigger. */
|
|
967
|
+
showsIcon: () => boolean;
|
|
968
|
+
/** Whether the icon part shows the selected icon: the switch is on and has one. */
|
|
969
|
+
showsSelectedIcon: () => boolean;
|
|
265
970
|
/** Attach to the root element's `click`. */
|
|
266
|
-
handleClick: (event:
|
|
971
|
+
handleClick: (event: CancelableEvent) => void;
|
|
972
|
+
}
|
|
973
|
+
export declare function createSwitch(options: SwitchOptions): SwitchApi;
|
|
974
|
+
/** M3 tooltip variants: a brief label, or a card with a subhead, text, and actions. */
|
|
975
|
+
export declare const TOOLTIP_VARIANTS: readonly ["plain", "rich"];
|
|
976
|
+
export type TooltipVariant = (typeof TOOLTIP_VARIANTS)[number];
|
|
977
|
+
export interface TooltipProps {
|
|
978
|
+
/** Defaults to `'plain'`. */
|
|
979
|
+
variant?: TooltipVariant;
|
|
980
|
+
/**
|
|
981
|
+
* Rich only: opens on a click on its element rather than on hover or focus, and stays open
|
|
982
|
+
* until the person interacts with something else.
|
|
983
|
+
*/
|
|
984
|
+
persistent?: boolean;
|
|
985
|
+
/** Whether the tooltip is shown. */
|
|
986
|
+
open?: boolean;
|
|
987
|
+
/** The side of its element it shows on. Defaults to `'top'` for plain, `'bottom'` for rich. */
|
|
988
|
+
side?: AnchoredSide;
|
|
989
|
+
/** Which edges line up with the element's. Defaults to `'center'` for plain, `'start'` for rich. */
|
|
990
|
+
align?: AnchoredAlign;
|
|
991
|
+
/**
|
|
992
|
+
* Space between the element and the tooltip, in px. Defaults to 4, for an element with a visible
|
|
993
|
+
* edge, such as a button; 8 suits one without, such as text.
|
|
994
|
+
*/
|
|
995
|
+
offset?: number;
|
|
996
|
+
}
|
|
997
|
+
export declare const tooltipDefaults: {
|
|
998
|
+
variant: "plain";
|
|
999
|
+
persistent: false;
|
|
1000
|
+
open: false;
|
|
1001
|
+
offset: number;
|
|
1002
|
+
};
|
|
1003
|
+
/** What the adapter has to put in the tooltip, which only the adapter can see. */
|
|
1004
|
+
export interface TooltipContent {
|
|
1005
|
+
/** A subhead above the text (rich only) */
|
|
1006
|
+
subhead: boolean;
|
|
1007
|
+
/** Text buttons below the text (rich only) */
|
|
1008
|
+
actions: boolean;
|
|
1009
|
+
}
|
|
1010
|
+
export interface TooltipOptions {
|
|
1011
|
+
props: () => TooltipProps;
|
|
1012
|
+
/** Without it, the tooltip has only its text. */
|
|
1013
|
+
content?: () => TooltipContent;
|
|
1014
|
+
/** Ids for the parts that others refer to, unique in the document. The adapter makes them. */
|
|
1015
|
+
ids: {
|
|
1016
|
+
root: string;
|
|
1017
|
+
subhead: string;
|
|
1018
|
+
supportingText: string;
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
export interface TooltipParts {
|
|
1022
|
+
/**
|
|
1023
|
+
* Wraps the element the tooltip is for, then the tooltip itself, without a box of its own. The
|
|
1024
|
+
* tooltip shows in the top layer, but comes right after its element in the focus order.
|
|
1025
|
+
*/
|
|
1026
|
+
trigger: () => PartAttrs;
|
|
1027
|
+
/** The tooltip, shown in the top layer */
|
|
1028
|
+
root: () => PartAttrs;
|
|
1029
|
+
subhead: () => PartAttrs;
|
|
1030
|
+
supportingText: () => PartAttrs;
|
|
1031
|
+
/** Holds the text buttons. */
|
|
1032
|
+
actions: () => PartAttrs;
|
|
1033
|
+
}
|
|
1034
|
+
/** The trigger holds the app's element first, then the tooltip (`tooltipSkeleton`). */
|
|
1035
|
+
export declare const tooltipTriggerSkeleton: PartNode<'trigger'>;
|
|
1036
|
+
type TooltipPart = Exclude<keyof TooltipParts, 'trigger'>;
|
|
1037
|
+
type TooltipWhen = 'showsSubhead' | 'showsActions';
|
|
1038
|
+
/** Spans throughout, so a tooltip may sit inside a paragraph. */
|
|
1039
|
+
export declare const tooltipSkeleton: PartNode<TooltipPart, TooltipWhen>;
|
|
1040
|
+
export interface TooltipPlacement {
|
|
1041
|
+
side: AnchoredSide;
|
|
1042
|
+
align: AnchoredAlign;
|
|
1043
|
+
offset: number;
|
|
1044
|
+
}
|
|
1045
|
+
export interface TooltipApi extends Record<TooltipWhen, () => boolean> {
|
|
1046
|
+
parts: TooltipParts;
|
|
1047
|
+
/**
|
|
1048
|
+
* Whether it holds actions, which take the focus: a rich tooltip with actions is a non-modal
|
|
1049
|
+
* dialog rather than a tooltip.
|
|
1050
|
+
*/
|
|
1051
|
+
interactive: () => boolean;
|
|
1052
|
+
/** Whether it opens on a click and stays open (rich only). */
|
|
1053
|
+
persistent: () => boolean;
|
|
1054
|
+
/** Where it shows, with the defaults of its variant filled in. */
|
|
1055
|
+
placement: () => TooltipPlacement;
|
|
1056
|
+
}
|
|
1057
|
+
export declare function createTooltip(options: TooltipOptions): TooltipApi;
|
|
1058
|
+
export interface TooltipDomOptions {
|
|
1059
|
+
/** Where the tooltip shows, read when it opens. */
|
|
1060
|
+
placement: () => TooltipPlacement;
|
|
1061
|
+
/** Whether it opens on a click and stays open. */
|
|
1062
|
+
persistent: () => boolean;
|
|
1063
|
+
/** Whether it holds actions, and so is a dialog whose text describes the element. */
|
|
1064
|
+
interactive: () => boolean;
|
|
1065
|
+
/** The tooltip opens or closes on its own. The adapter sets `open` to match. */
|
|
1066
|
+
onOpenChange: (open: boolean) => void;
|
|
1067
|
+
}
|
|
1068
|
+
export interface TooltipDomHandle {
|
|
1069
|
+
/** Brings the tooltip in line with `open`. Call it once attached, and whenever `open` changes. */
|
|
1070
|
+
sync(open: boolean): void;
|
|
1071
|
+
/** Call it after the element or the tooltip's content changed, to update the element's ARIA. */
|
|
1072
|
+
update(): void;
|
|
1073
|
+
detach(): void;
|
|
267
1074
|
}
|
|
268
|
-
export declare function
|
|
1075
|
+
export declare function attachTooltip(trigger: HTMLElement, root: HTMLElement, options: TooltipDomOptions): TooltipDomHandle;
|
|
1076
|
+
export {};
|