@material/web
Version:
Material web components
267 lines (266 loc) • 9.31 kB
TypeScript
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import '../../focus/md-focus-ring.js';
import '../../elevation/elevation.js';
import { LitElement, PropertyValues } from 'lit';
import { MenuItem } from './controllers/menuItemController.js';
import { FocusState } from './controllers/shared.js';
import { Corner, SurfacePositionTarget } from './controllers/surfacePositionController.js';
import { TypeaheadController } from './controllers/typeaheadController.js';
export { Corner } from './controllers/surfacePositionController.js';
/**
* The default value for the typeahead buffer time in Milliseconds.
*/
export declare const DEFAULT_TYPEAHEAD_BUFFER_TIME = 200;
/**
* @fires opening Fired before the opening animation begins
* @fires opened Fired once the menu is open, after any animations
* @fires closing Fired before the closing animation begins
* @fires closed Fired once the menu is closed, after any animations
*/
export declare abstract class Menu extends LitElement {
private readonly surfaceEl;
private readonly slotEl;
/**
* The ID of the element in the same root node in which the menu should align
* to. Overrides setting `anchorElement = elementReference`.
*
* __NOTE__: anchor or anchorElement must either be an HTMLElement or resolve
* to an HTMLElement in order for menu to open.
*/
anchor: string;
/**
* Whether the positioning algorithim should calculate relative to the parent
* of the anchor element (absolute) or relative to the window (fixed).
*
* Examples for `position = 'fixed'`:
*
* - If there is no `position:relative` in the given parent tree and the
* surface is `position:absolute`
* - If the surface is `position:fixed`
* - If the surface is in the "top layer"
* - The anchor and the surface do not share a common `position:relative`
* ancestor
*
* When using positioning = fixed, in most cases, the menu should position
* itself above most other `position:absolute` or `position:fixed` elements
* when placed inside of them. e.g. using a menu inside of an `md-dialog`.
*
* __NOTE__: Fixed menus will not scroll with the page and will be fixed to
* the window instead.
*/
positioning: 'absolute' | 'fixed';
/**
* Skips the opening and closing animations.
*/
quick: boolean;
/**
* Displays overflow content like a submenu.
*
* __NOTE__: This may cause adverse effects if you set
* `md-menu {max-height:...}`
* and have items overflowing items in the "y" direction.
*/
hasOverflow: boolean;
/**
* Opens the menu and makes it visible. Alternative to the `.show()` and
* `.close()` methods
*/
open: boolean;
/**
* Offsets the menu's inline alignment from the anchor by the given number in
* pixels. This value is direction aware and will follow the LTR / RTL
* direction.
*
* e.g. LTR: positive -> right, negative -> left
* RTL: positive -> left, negative -> right
*/
xOffset: number;
/**
* Offsets the menu's block alignment from the anchor by the given number in
* pixels.
*
* e.g. positive -> down, negative -> up
*/
yOffset: number;
/**
* The max time between the keystrokes of the typeahead menu behavior before
* it clears the typeahead buffer.
*/
typeaheadDelay: number;
/**
* The corner of the anchor which to align the menu in the standard logical
* property style of <block>-<inline> e.g. `'end-start'`.
*
* NOTE: This value may not be respected by the menu positioning algorithm
* if the menu would render outisde the viewport.
*/
anchorCorner: Corner;
/**
* The corner of the menu which to align the anchor in the standard logical
* property style of <block>-<inline> e.g. `'start-start'`.
*
* NOTE: This value may not be respected by the menu positioning algorithm
* if the menu would render outisde the viewport.
*/
menuCorner: Corner;
/**
* Keeps the user clicks outside the menu.
*
* NOTE: clicking outside may still cause focusout to close the menu so see
* `stayOpenOnFocusout`.
*/
stayOpenOnOutsideClick: boolean;
/**
* Keeps the menu open when focus leaves the menu's composed subtree.
*
* NOTE: Focusout behavior will stop propagation of the focusout event. Set
* this property to true to opt-out of menu's focuout handling altogether.
*/
stayOpenOnFocusout: boolean;
/**
* After closing, does not restore focus to the last focused element before
* the menu was opened.
*/
skipRestoreFocus: boolean;
/**
* The element that should be focused by default once opened.
*
* NOTE: When setting default focus to 'LIST_ROOT', remember to change
* `tabindex` to `0` and change md-menu's display to something other than
* `display: contents` when necessary.
*/
defaultFocus: FocusState;
protected slotItems: HTMLElement[];
private typeaheadActive;
/**
* Whether or not the current menu is a submenu and should not handle specific
* navigation keys.
*
* @exports
*/
isSubmenu: boolean;
/**
* The event path of the last window pointerdown event.
*/
private pointerPath;
private readonly openCloseAnimationSignal;
private readonly listController;
/**
* Whether the menu is animating upwards or downwards when opening. This is
* helpful for calculating some animation calculations.
*/
private get openDirection();
/**
* The element that was focused before the menu opened.
*/
private lastFocusedElement;
/**
* Handles typeahead navigation through the menu.
*/
typeaheadController: TypeaheadController;
private currentAnchorElement;
/**
* The element which the menu should align to. If `anchor` is set to a
* non-empty idref string, then `anchorEl` will resolve to the element with
* the given id in the same root node. Otherwise, `null`.
*/
get anchorElement(): HTMLElement & Partial<SurfacePositionTarget> | null;
set anchorElement(element: HTMLElement & Partial<SurfacePositionTarget> | null);
private readonly internals;
constructor();
/**
* Handles positioning the surface and aligning it to the anchor as well as
* keeping it in the viewport.
*/
private readonly menuPositionController;
/**
* The menu items associated with this menu. The items must be `MenuItem`s and
* have both the `md-menu-item` and `md-list-item` attributes.
*/
get items(): MenuItem[];
protected willUpdate(changed: PropertyValues<Menu>): void;
update(changed: PropertyValues<Menu>): void;
connectedCallback(): void;
disconnectedCallback(): void;
protected render(): import("lit-html").TemplateResult<1>;
/**
* Renders the positionable surface element and its contents.
*/
private renderSurface;
/**
* Renders the menu items' slot
*/
private renderMenuItems;
/**
* Renders the elevation component.
*/
private renderElevation;
private getSurfaceClasses;
private readonly handleFocusout;
private captureKeydown;
/**
* Saves the last focused element focuses the new element based on
* `defaultFocus`, and animates open.
*/
private readonly onOpened;
/**
* Animates closed.
*/
private readonly beforeClose;
/**
* Focuses the last focused element.
*/
private readonly onClosed;
/**
* Performs the opening animation:
*
* https://direct.googleplex.com/#/spec/295000003+271060003
*
* @return A promise that resolve to `true` if the animation was aborted,
* `false` if it was not aborted.
*/
private animateOpen;
/**
* Performs the closing animation:
*
* https://direct.googleplex.com/#/spec/295000003+271060003
*/
private animateClose;
private handleKeydown;
private setUpGlobalEventListeners;
private cleanUpGlobalEventListeners;
private readonly onWindowPointerdown;
/**
* We cannot listen to window click because Safari on iOS will not bubble a
* click event on window if the item clicked is not a "clickable" item such as
* <body>
*/
private readonly onDocumentClick;
private onCloseMenu;
private onDeactivateItems;
private onRequestActivation;
private handleDeactivateTypeahead;
private handleActivateTypeahead;
private handleStayOpenOnFocusout;
private handleCloseOnFocusout;
close(): void;
show(): void;
/**
* Activates the next item in the menu. If at the end of the menu, the first
* item will be activated.
*
* @return The activated menu item or `null` if there are no items.
*/
activateNextItem(): MenuItem;
/**
* Activates the previous item in the menu. If at the start of the menu, the
* last item will be activated.
*
* @return The activated menu item or `null` if there are no items.
*/
activatePreviousItem(): MenuItem;
}