/** * Bridge between a menu widget and the shared {@link MenuKeyboardController}. * * The controller is intentionally decoupled from any specific menu's internals: * it drives navigation purely through this host, so both {@link import('./column-menu').ColumnMenu} * (with fly-out submenus) and {@link import('./group-context-menu').GroupContextMenu} * (flat) can share one implementation. */ export interface MenuKeyboardHost { /** The menu's root `[role="menu"]` element, or `null` when the menu is closed. */ getRootEl(): HTMLElement | null; /** * The currently-open fly-out submenu (portaled to `document.body`), or `null`. * Menus without submenus always return `null`. */ getActiveSubmenuEl(): HTMLElement | null; /** * Open the submenu owned by `parentItem` (portals + positions it) and return * it, or `null` when the item has no submenu. */ openSubmenu(parentItem: HTMLElement): HTMLElement | null; /** Close a submenu previously returned by {@link openSubmenu}. */ closeSubmenu(submenuEl: HTMLElement): void; /** Resolve the parent item that owns `submenuEl`, or `null`. */ getSubmenuParent(submenuEl: HTMLElement): HTMLElement | null; /** * Close the entire menu. When `restoreFocus` is `true`, focus is returned to * the element that opened the menu (the header cell or trigger button). */ closeAll(restoreFocus: boolean): void; } /** * Reusable keyboard-navigation controller implementing the WAI-ARIA * *menu / menubar* pattern for Photon Grid's portaled context menus. * * ### Behaviour * - **ArrowDown / ArrowUp** — move focus between enabled items (skipping * separators and disabled items), wrapping at the ends. * - **Home / End** — focus the first / last enabled item. * - **ArrowRight / Enter / Space** on a submenu parent — open its fly-out and * focus the first child. * - **ArrowLeft** — close the current submenu and return focus to its parent. * - **Enter / Space** on a leaf — activate it (dispatches a synthetic click, so * the item's existing handler runs and the menu closes). * - **Escape** — close the current submenu, or the whole menu (restoring focus * to the opener) at the root level. * - **Printable keys** — type-ahead: focus the first enabled item whose label * starts with the buffered characters. * * ### Focus model * Items are `tabindex="-1"` and moved with `.focus()` (not * `aria-activedescendant`). Fly-out submenus are portaled to `document.body`, so * the active item is not a DOM descendant of the root menu — `.focus()` crosses * that boundary correctly where `aria-activedescendant` would not. * * ### Lifecycle * A single capture-phase `keydown` listener is added in {@link attach} and * removed in {@link destroy}; no per-item listeners are created. The type-ahead * timer is always cleared on {@link destroy}. Safe to attach/detach on every * menu open/close with no listener accumulation. */ export declare class MenuKeyboardController { private readonly host; private readonly boundKeydown; private typeaheadBuffer; private typeaheadTimer; private attached; constructor(host: MenuKeyboardHost); /** * Begin handling keyboard navigation and move focus to the first enabled item * of the root menu. Call once, immediately after the menu DOM is shown. */ attach(): void; /** Stop handling keyboard navigation and release the type-ahead timer. */ destroy(): void; private onKeydown; /** Prevent scrolling / other handlers from also acting on a handled key. */ private consume; /** The menu level (root or open submenu) that currently owns focus. */ private currentLevel; /** Enabled, focusable items within a menu level, in DOM order. */ private getItems; private move; private focusEdge; private focusFirst; private focusAt; /** `true` when the focused item opens a submenu. */ private isParent; private openActiveSubmenu; private closeCurrentSubmenu; private activate; private onEscape; private isPrintable; private typeahead; private clearTypeahead; } //# sourceMappingURL=menu-keyboard-controller.d.ts.map