import { type PartialWithUndefined } from '@augment-vir/common'; import { ListenTarget } from 'typed-event-target'; import { type CurrentNavEntry, type NavEntry } from '../directives/nav-entry.js'; import { type NavTree } from '../nav-tree/nav-tree.js'; import { type AllNavControllerEvents } from './nav-controller-events.js'; import { NavAction, type NavigationInputs, type NavigationResult } from './navigate.js'; /** * Options for {@link NavController}. * * @category Internal */ export type NavControllerOptions = PartialWithUndefined<{ /** * Always require an element within the nav tree to be focused. * * @default false */ alwaysRequireFocused: boolean; /** * By default, element activation is triggered on mousedown. Set this to `true` to instead * activate it on `mouseup`. * * @default false */ activateOnMouseUp: boolean; }>; /** * Allows navigation around the nav tree contained within the given `rootElement`. If there is no * nav tree, all operations simply do nothing. For a full example, see * {@link https://github.com/electrovir/device-navigation/blob/dev/src/test/elements/vir-test-app.element.ts | vir-test-app.element.ts}. * * @category Main * @example * * ```ts * import {NavController, NavDirection} from 'device-navigation'; * * const navController = new NavController(host); * * window.addEventListener('keydown', (event) => { * if (event.code === 'ArrowDown') { * navController.navigate({direction: NavDirection.Down, allowWrapper: false}); * } else if (event.code === 'ArrowUp') { * navController.navigate({direction: NavDirection.Up, allowWrapper: false}); * } * // etc. all other navigation directions * }); * ``` */ export declare class NavController extends ListenTarget { readonly rootElement: HTMLElement; readonly options: NavControllerOptions; constructor(rootElement: HTMLElement, options?: NavControllerOptions); /** If `true`, the nav tree will rebuild on next operation. */ needsUpdate: boolean; /** If true, all nav is prevented. */ locked: boolean; protected navEntries: Set>; currentNavEntry: Readonly | undefined; protected cachedNavTree: Readonly | undefined; /** Gets or builds the current nav tree. */ protected getNavTree(): Readonly; /** Clears the current nav entry and disconnect listener when it matches the active entry. */ protected clearCurrentNavEntry(currentNavEntry: Readonly | undefined): void; /** Updates the current nav entry's position after the nav tree changes. */ protected syncCurrentNavEntry(navTree: Readonly): void; /** Focus the default element for the whole tree. */ focusDefaultElement(): void; /** * Schedules a post-render pass that ensures a valid nav entry is focused when * `alwaysRequireFocused` is enabled. * * This reconciles controller state after dynamic DOM updates: it keeps the current entry when * it still exists in the rebuilt nav tree, clears it when it was removed or became * non-navigable, and focuses the tree's default entry when no current entry remains. * * @internal */ queueDefaultFocus(force?: boolean): void; /** Add a new {@link NavEntry} to this controller. */ addNavEntry(navEntry: NavEntry): void; /** Remove a {@link NavEntry} from this controller. */ removeNavEntry(navEntry: NavEntry): void; /** Sets the current nav entry with the given action. */ triggerNavEntry(navEntry: Readonly | undefined, enabled: boolean, navAction: NavAction.Activate): NavigationResult; /** Sets the current nav entry with the given action. */ triggerNavEntry(navEntry: Readonly | undefined, enabled: boolean, navAction: NavAction.Focus): NavigationResult; /** Navigate around the nav tree. */ navigate({ direction, allowWrapping, shouldSkipHoles, }: Readonly): NavigationResult; /** * Enter into the currently focused node's children. Focuses the first child. Fails if there are * no children to focus. */ enterInto(params: { fallbackToActivate: true; }): NavigationResult; enterInto(params?: { fallbackToActivate?: false | undefined; } | undefined): NavigationResult; /** Activate the currently focused nav entry. */ activate(): NavigationResult; /** Deactivate the currently active nav entry. */ deactivate(): NavigationResult; /** * Shift focus from the currently focused node to its parent. If there is no parent, or rather * if the parent is the tree root, this fails. */ exitOutOf(): NavigationResult; /** Navigate to siblings of the parent of the currently focused element, if they exist. */ navigatePibling({ allowWrapping, direction, shouldSkipHoles, }: Readonly): NavigationResult; /** Builds the latest tree, sets it internally, and returns it. */ buildNavTree(): NavTree; }