@rio-m3e/core 0.2.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 +535 -21
- package/dist/index.js +1757 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,4 +4,6 @@ Framework-agnostic logic for [Rio](https://github.com/LegenLee/rio), a Material
|
|
|
4
4
|
|
|
5
5
|
Framework adapters such as [`@rio-m3e/vue`](https://www.npmjs.com/package/@rio-m3e/vue) are built on it, and install it for you. Install it directly only to build components of your own.
|
|
6
6
|
|
|
7
|
+
You can see the document page in [here](https://legenlee.github.io/rio/).
|
|
8
|
+
|
|
7
9
|
Licensed under the Apache License 2.0.
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
* `docs/conventions.md`.
|
|
6
6
|
*/
|
|
7
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
|
+
}
|
|
8
16
|
/**
|
|
9
17
|
* One node of a component's skeleton: the markup an adapter renders, part by part. Adapters
|
|
10
18
|
* render it their own way; contract tests check what they rendered against it. Each component
|
|
@@ -82,13 +90,13 @@ export interface ButtonContent {
|
|
|
82
90
|
/** Whether there is a leading icon. */
|
|
83
91
|
icon: boolean;
|
|
84
92
|
}
|
|
85
|
-
export interface ButtonOptions {
|
|
93
|
+
export interface ButtonOptions<E extends CancelableEvent = MouseEvent> {
|
|
86
94
|
/** Returns the current prop values. The adapter owns the state. */
|
|
87
95
|
props: () => ButtonProps;
|
|
88
96
|
/** Returns what content the adapter has. Without it, the button has no icon. */
|
|
89
97
|
content?: () => ButtonContent;
|
|
90
|
-
/** Called for a click that isn't blocked. */
|
|
91
|
-
onClick: (event:
|
|
98
|
+
/** Called for a click that isn't blocked, with the event `handleClick` got. */
|
|
99
|
+
onClick: (event: E) => void;
|
|
92
100
|
/** Called after an unblocked click on a toggle button, with the requested value. */
|
|
93
101
|
onChange: (selected: boolean) => void;
|
|
94
102
|
}
|
|
@@ -104,14 +112,14 @@ export interface ButtonParts {
|
|
|
104
112
|
}
|
|
105
113
|
/** How the adapter renders the button's parts. The icon holds the leading icon. */
|
|
106
114
|
export declare const buttonSkeleton: PartNode<keyof ButtonParts, 'showsIcon'>;
|
|
107
|
-
export interface ButtonApi {
|
|
115
|
+
export interface ButtonApi<E extends CancelableEvent = MouseEvent> {
|
|
108
116
|
parts: ButtonParts;
|
|
109
117
|
/** Whether to render the icon part. */
|
|
110
118
|
showsIcon: () => boolean;
|
|
111
119
|
/** Attach to the root element's `click`. */
|
|
112
|
-
handleClick: (event:
|
|
120
|
+
handleClick: (event: E) => void;
|
|
113
121
|
}
|
|
114
|
-
export declare function createButton(options: ButtonOptions): ButtonApi
|
|
122
|
+
export declare function createButton<E extends CancelableEvent = MouseEvent>(options: ButtonOptions<E>): ButtonApi<E>;
|
|
115
123
|
/**
|
|
116
124
|
* M3E button group variants. A standard group spaces its buttons and lets a pressed button push
|
|
117
125
|
* its neighbors; a connected group joins them with 2px gaps and shared corners, and fills the
|
|
@@ -192,6 +200,87 @@ export interface ButtonGroupHandle {
|
|
|
192
200
|
detach(): void;
|
|
193
201
|
}
|
|
194
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
|
+
};
|
|
236
|
+
}
|
|
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;
|
|
195
284
|
export declare const ICON_BUTTON_VARIANTS: readonly ["filled", "tonal", "outlined", "standard"];
|
|
196
285
|
export type IconButtonVariant = (typeof ICON_BUTTON_VARIANTS)[number];
|
|
197
286
|
/** M3E icon button widths. `default` makes a square (or circle) as wide as it is tall. */
|
|
@@ -240,13 +329,13 @@ export interface IconButtonContent {
|
|
|
240
329
|
/** Whether there is an icon for the selected state. */
|
|
241
330
|
selectedIcon: boolean;
|
|
242
331
|
}
|
|
243
|
-
export interface IconButtonOptions {
|
|
332
|
+
export interface IconButtonOptions<E extends CancelableEvent = MouseEvent> {
|
|
244
333
|
/** Returns the current prop values. The adapter owns the state. */
|
|
245
334
|
props: () => IconButtonProps;
|
|
246
335
|
/** Returns what content the adapter has. Without it, there is no selected icon. */
|
|
247
336
|
content?: () => IconButtonContent;
|
|
248
|
-
/** Called for a click that isn't blocked. */
|
|
249
|
-
onClick: (event:
|
|
337
|
+
/** Called for a click that isn't blocked, with the event `handleClick` got. */
|
|
338
|
+
onClick: (event: E) => void;
|
|
250
339
|
/** Called after an unblocked click on a toggle button, with the requested value. */
|
|
251
340
|
onChange: (selected: boolean) => void;
|
|
252
341
|
}
|
|
@@ -264,14 +353,298 @@ export interface IconButtonParts {
|
|
|
264
353
|
* `showsSelectedIcon()`, otherwise the default one.
|
|
265
354
|
*/
|
|
266
355
|
export declare const iconButtonSkeleton: PartNode<keyof IconButtonParts>;
|
|
267
|
-
export interface IconButtonApi {
|
|
356
|
+
export interface IconButtonApi<E extends CancelableEvent = MouseEvent> {
|
|
268
357
|
parts: IconButtonParts;
|
|
269
358
|
/** Whether the icon part shows the selected icon instead of the default one. */
|
|
270
359
|
showsSelectedIcon: () => boolean;
|
|
271
360
|
/** Attach to the root element's `click`. */
|
|
272
|
-
handleClick: (event:
|
|
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;
|
|
273
535
|
}
|
|
274
|
-
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;
|
|
275
648
|
export interface DragInfo {
|
|
276
649
|
/** Distance from where the press started, in px. */
|
|
277
650
|
dx: number;
|
|
@@ -295,6 +668,41 @@ export interface DragHandle {
|
|
|
295
668
|
detach(): void;
|
|
296
669
|
}
|
|
297
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;
|
|
298
706
|
export interface RippleHandle {
|
|
299
707
|
/** Removes the listeners and the `data-ripple` marker. */
|
|
300
708
|
detach(): void;
|
|
@@ -450,13 +858,16 @@ export interface SplitButtonContent {
|
|
|
450
858
|
/** Whether there is label text. */
|
|
451
859
|
label: boolean;
|
|
452
860
|
}
|
|
453
|
-
export interface SplitButtonOptions {
|
|
861
|
+
export interface SplitButtonOptions<E extends CancelableEvent = MouseEvent> {
|
|
454
862
|
/** Returns the current prop values. The adapter owns the state. */
|
|
455
863
|
props: () => SplitButtonProps;
|
|
456
864
|
/** Returns what content the adapter has. Without it, the leading button has only a label. */
|
|
457
865
|
content?: () => SplitButtonContent;
|
|
458
|
-
/**
|
|
459
|
-
|
|
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;
|
|
460
871
|
/** Called with the requested `open` when the trailing button is clicked and isn't blocked. */
|
|
461
872
|
onChange: (open: boolean) => void;
|
|
462
873
|
}
|
|
@@ -479,18 +890,18 @@ export interface SplitButtonParts {
|
|
|
479
890
|
* button's content; the menu icon holds the expand icon the app provides.
|
|
480
891
|
*/
|
|
481
892
|
export declare const splitButtonSkeleton: PartNode<keyof SplitButtonParts, 'showsIcon' | 'showsLabel'>;
|
|
482
|
-
export interface SplitButtonApi {
|
|
893
|
+
export interface SplitButtonApi<E extends CancelableEvent = MouseEvent> {
|
|
483
894
|
parts: SplitButtonParts;
|
|
484
895
|
/** Whether to render the icon part. */
|
|
485
896
|
showsIcon: () => boolean;
|
|
486
897
|
/** Whether to render the label part. */
|
|
487
898
|
showsLabel: () => boolean;
|
|
488
899
|
/** Attach to the leading button's `click`. */
|
|
489
|
-
handleLeadingClick: (event:
|
|
900
|
+
handleLeadingClick: (event: E) => void;
|
|
490
901
|
/** Attach to the trailing button's `click`. */
|
|
491
|
-
handleTrailingClick: (event:
|
|
902
|
+
handleTrailingClick: (event: E) => void;
|
|
492
903
|
}
|
|
493
|
-
export declare function createSplitButton(options: SplitButtonOptions): SplitButtonApi
|
|
904
|
+
export declare function createSplitButton<E extends CancelableEvent = MouseEvent>(options: SplitButtonOptions<E>): SplitButtonApi<E>;
|
|
494
905
|
export interface SwitchHandleOptions {
|
|
495
906
|
/** Returns whether the switch is on. */
|
|
496
907
|
selected: () => boolean;
|
|
@@ -557,6 +968,109 @@ export interface SwitchApi {
|
|
|
557
968
|
/** Whether the icon part shows the selected icon: the switch is on and has one. */
|
|
558
969
|
showsSelectedIcon: () => boolean;
|
|
559
970
|
/** Attach to the root element's `click`. */
|
|
560
|
-
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;
|
|
561
1074
|
}
|
|
562
|
-
export declare function
|
|
1075
|
+
export declare function attachTooltip(trigger: HTMLElement, root: HTMLElement, options: TooltipDomOptions): TooltipDomHandle;
|
|
1076
|
+
export {};
|