UNPKG

@universal-material/web

Version:
108 lines 3.41 kB
export class MenuFieldNavigationController { #element; constructor(host) { this.#element = null; this.focusedMenu = null; this.#handleMenuClose = () => this.blurMenu(); this.host = host; this._bindHandleKeyDown = this.handleKeyDown.bind(this); } attach(element) { this.detach(); element?.addEventListener('keydown', this._bindHandleKeyDown, { capture: true }); this.host._menu?.addEventListener('close', this.#handleMenuClose); this.#element = element; } detach() { this.#element?.removeEventListener('keydown', this._bindHandleKeyDown); this.host._menu?.removeEventListener('close', this.#handleMenuClose); this.#element = null; } #handleMenuClose; handleKeyDown(event) { if (this.host._menu?.open !== true) { return false; } const isEscape = event.key === 'Escape'; if (isEscape) { this.host._menu.close(); } if (event.key === 'Home') { this.navigateTo(event, this.host._menuItems[0], 0); return true; } if (event.key === 'End') { this.navigateTo(event, this.host._menuItems[this.host._menuItems.length - 1], this.host._menuItems.length - 1); return true; } const isDown = event.key === 'ArrowDown'; const isUp = event.key === 'ArrowUp'; if (isDown || isUp) { this.navigate(event, isDown); return true; } const isEnter = event.key === 'Enter'; const isTab = event.key === 'Tab'; if (isEnter || isTab) { this.selectActiveItem(event); return true; } return false; } navigate(event, forwards) { const menuItems = this.host._menuItems; if (!menuItems.length) { return; } event.preventDefault(); const activeMenu = this.focusedMenu; const activeMenuIndex = activeMenu ? menuItems.indexOf(activeMenu) : -1; const nextMenu = forwards ? menuItems[activeMenuIndex + 1] ?? menuItems[0] : menuItems[activeMenuIndex - 1] ?? menuItems[menuItems.length - 1]; if (!nextMenu) { return; } this.navigateTo(event, nextMenu, menuItems.indexOf(nextMenu)); } navigateTo(event, menu, index) { event.preventDefault(); this.blurMenu(); if (!menu) { return; } this.focusMenu(menu, index); } focusMenu(menu, index, active = true, scroll = true) { if (this.focusedMenu) { this.focusedMenu.active = false; } this.focusedMenu = menu; menu.active = active; if (scroll) { menu.scrollIntoView({ block: 'nearest' }); } this.afterFocus(menu, index); } blurMenu() { if (!this.focusedMenu) { return; } this.focusedMenu.active = false; this.focusedMenu = null; this.afterBlur(); } selectActiveItem(event) { if (!this.focusedMenu) { return; } event.preventDefault(); this.focusedMenu.click(); this.host._menu.open = false; } afterFocus(_, __) { } afterBlur() { } } //# sourceMappingURL=menu-field-navigation-controller.js.map