UNPKG

@universal-material/web

Version:
82 lines 3.24 kB
import { normalizedStartsWith } from '../shared/compare-text.js'; import { MenuFieldNavigationController } from '../shared/menu-field/menu-field-navigation-controller.js'; const getCleanTypeaheadStatus = () => ({ typing: false, repeating: false, buffer: '', timeoutId: 0, }); export class SelectNavigationController extends MenuFieldNavigationController { #typeaheadStatus = getCleanTypeaheadStatus(); handleKeyDown(event) { if (this.host._menu.open) { const handled = super.handleKeyDown(event); return handled || this.handleType(event); } const isDown = event.key === 'ArrowDown'; const isUp = event.key === 'ArrowUp'; if (!isDown && !isUp) { return this.handleType(event); } event.preventDefault(); this.host._menu.show(); if (!this.host.selectedOptions.length) { return true; } const option = this.host.selectedOptions[0]; this.navigateTo(event, option, this.host._menuItems.indexOf(option)); return true; } attach(element) { super.attach(element); this.host._menu.addEventListener('menu-item-mouseenter', this.#handleMouseFocus); } detach() { super.detach(); this.host._menu.removeEventListener('menu-item-mouseenter', this.#handleMouseFocus); } #handleMouseFocus = (e) => { this.blurMenu(); const option = e.target; this.focusMenu(option, this.host._menuItems.indexOf(option), false, false); }; afterFocus(_, index) { this.host._button.setAttribute('aria-activedescendant', `item-${index + 1}`); } afterBlur() { this.host._button.removeAttribute('aria-activedescendant'); } handleType(event) { if (event.key.length > 1) { return false; } if (this.#typeaheadStatus.timeoutId) { clearTimeout(this.#typeaheadStatus.timeoutId); } const lastFocusedMenu = this.focusedMenu; this.#typeaheadStatus.buffer += event.key; this.#typeaheadStatus.timeoutId = setTimeout(() => this.#typeaheadStatus = getCleanTypeaheadStatus(), 1000); const term = this.#typeaheadStatus.buffer.replaceAll(event.key, '') === '' ? event.key : this.#typeaheadStatus.buffer; this.findNextElementByTerm(term, lastFocusedMenu); return true; } findNextElementByTerm(term, lastFocusedMenu) { const options = this.host._options; const lastFocusedMenuIndex = lastFocusedMenu ? options.indexOf(lastFocusedMenu) : -1; let nextMenu = lastFocusedMenuIndex > -1 ? this.host._options[lastFocusedMenuIndex + 1] : null; if (!nextMenu || !normalizedStartsWith(nextMenu.textContent, term)) { nextMenu = options.find(o => normalizedStartsWith(o.textContent, term)); } if (!nextMenu) { return; } const nextMenuIndex = options.indexOf(nextMenu); if (this.host._menu.open) { this.blurMenu(); this.focusMenu(nextMenu, nextMenuIndex); return; } nextMenu.setSelectedByUser(); } } //# sourceMappingURL=select-navigation-controller.js.map