UNPKG

@material/web

Version:
107 lines 3.67 kB
/** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { CloseReason, createDefaultCloseMenuEvent, isClosableKey } from './shared.js'; /** * A controller that provides most functionality of an element that implements * the MenuItem interface. */ export class MenuItemController { /** * @param host The MenuItem in which to attach this controller to. * @param config The object that configures this controller's behavior. */ constructor(host, config) { this.host = host; this.internalTypeaheadText = null; /** * Bind this click listener to the interactive element. Handles closing the * menu. */ this.onClick = () => { if (this.host.keepOpen) return; this.host.dispatchEvent(createDefaultCloseMenuEvent(this.host, { kind: CloseReason.CLICK_SELECTION })); }; /** * Bind this click listener to the interactive element. Handles closing the * menu. */ this.onKeydown = (event) => { // Check if the interactive element is an anchor tag. If so, click it. if (this.host.href && event.code === 'Enter') { const interactiveElement = this.getInteractiveElement(); if (interactiveElement instanceof HTMLAnchorElement) { interactiveElement.click(); } } if (this.host.keepOpen || event.defaultPrevented) return; const keyCode = event.code; if (!event.defaultPrevented && isClosableKey(keyCode)) { event.preventDefault(); this.host.dispatchEvent(createDefaultCloseMenuEvent(this.host, { kind: CloseReason.KEYDOWN, key: keyCode })); } }; const { getHeadlineElements, getInteractiveElement, } = config; this.getHeadlineElements = getHeadlineElements; this.getInteractiveElement = getInteractiveElement; this.host.addController(this); } /** * The text that is selectable via typeahead. If not set, defaults to the * innerText of the item slotted into the `"headline"` slot. */ get typeaheadText() { if (this.internalTypeaheadText !== null) { return this.internalTypeaheadText; } const headlineElements = this.getHeadlineElements(); const textParts = []; headlineElements.forEach((headlineElement) => { if (headlineElement.textContent && headlineElement.textContent.trim()) { textParts.push(headlineElement.textContent.trim()); } }); return textParts.join(' '); } /** * The recommended tag name to render as the list item. */ get tagName() { const type = this.host.type; switch (type) { case 'link': return 'a'; case 'button': return 'button'; default: case 'menuitem': case 'option': return 'li'; } } /** * The recommended role of the menu item. */ get role() { return this.host.type === 'option' ? 'option' : 'menuitem'; } hostConnected() { this.host.toggleAttribute('md-menu-item', true); } hostUpdate() { if (this.host.href) { this.host.type = 'link'; } } /** * Use to set the typeaheadText when it changes. */ setTypeaheadText(text) { this.internalTypeaheadText = text; } } //# sourceMappingURL=menuItemController.js.map