Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...

    Manages context-aware keyboard input routing to prevent conflicts.

    Provides a hierarchical context system where different parts of the UI can register key bindings without conflicting. FLY_CONTROLS derives its allowlist from its own registrations and falls back to NAVIGATION, while NAVIGATION reserves no chords globally.

    Key features:

    • Priority-based context system (higher priority contexts take precedence)
    • Context stack for nested contexts (modal over main view)
    • Automatic typing detection (blocks shortcuts when typing in inputs)
    • Explicit fallback routes between compatible contexts
    const manager = new InputContextManager();

    // Register a key binding for navigation context
    manager.registerBinding(InputContext.NAVIGATION, {
    actionId: 'dimension.navigate',
    actionParameter: -1,
    key: '[',
    handler: () => navigateBackward(),
    preventDefault: true,
    description: 'Step along the selected dimension',
    help: false
    });

    // Switch to fly controls context
    manager.setContext(InputContext.FLY_CONTROLS);
    // Now WASD keys are enabled, [ ] keys still work via passthrough
    Index
    currentContext: string = InputContext.NAVIGATION
    contextStack: string[] = []
    bindings: Map<string, Map<string, KeyBinding>> = ...
    actionBindings: Map<string, Map<string, string>> = ...
    contextConfigs: Map<string, ContextConfig> = ...
    builtInContexts: Set<string> = ...
    enabled: boolean = true
    keyEventDepth: number = 0

    Re-entrance depth for handleKeyEvent. A binding handler that (mis)configured itself to dispatch keyboard events back through the context manager could otherwise recurse infinitely; cap at MAX_KEY_EVENT_DEPTH and bail with a single error log.

    • Private

      Initialize default context configurations with priorities and key filters.

      Sets up four predefined contexts:

      • NAVIGATION (priority 0): Default orbit-navigation mode
      • FLY_CONTROLS (priority 1): Enables WASD + arrow keys for fly mode
      • TYPING (priority 10): Highest priority, blocks all shortcuts
      • UI_INTERACTION (priority 5): For UI panels

      Returns void

    • Push a new context onto the stack, saving current context.

      Used for nested contexts like modal dialogs over main view. The previous context is saved and will be restored when popContext() is called. If the new context is the same as current, does nothing.

      Parameters

      Returns void

      // Open modal dialog
      contextManager.pushContext(InputContext.UI_INTERACTION);
      // Now UI has higher priority

      // Close modal dialog
      contextManager.popContext();
      // Back to previous context
    • Pop the current context and restore the previous one from stack.

      Used to return to previous context after closing modal/dialog. If stack is empty, does nothing (stays in current context).

      Returns void

      // Open settings dialog
      contextManager.pushContext(InputContext.UI_INTERACTION);
      // ... user interacts with settings ...
      contextManager.popContext(); // Back to NAVIGATION
    • Set the current context, replacing current without saving to stack.

      Use this for mode switches (navigation → fly controls) rather than nested contexts. The previous context is NOT saved - use pushContext() if you need to restore the previous context later.

      Logs context change for debugging.

      Parameters

      Returns void

      // Switch to fly control mode
      contextManager.setContext(InputContext.FLY_CONTROLS);
      // WASD keys now enabled, can't go back with popContext()

      // Switch back to navigation
      contextManager.setContext(InputContext.NAVIGATION);
    • Register a key binding for a specific context.

      Associates a key (with optional modifiers) to a handler function within a specific context. The binding will only be active when that context is current. Warns if the binding conflicts with an existing binding.

      Parameters

      • context: InputContextId

        Context where this binding should be active

      • binding: KeyBinding

        Key binding configuration with key, modifiers, and handler

        Key binding configuration

        • actionId: string

          Stable action identity, independent of the registered chord.

        • OptionalactionParameter?: string | number

          Optional discriminator for parameterized actions sharing one identity.

        • key: string
        • Optionalmodifiers?: { ctrl?: boolean; shift?: boolean; alt?: boolean; meta?: boolean }
        • handler: (event: KeyboardEvent) => boolean | void | Promise<void>

          Return false synchronously to leave the event available to lower-priority contexts.

        • OptionalkeyupHandler?: (event: KeyboardEvent) => boolean | void | Promise<void>

          Modifier-aware bindings match keyup only while those modifiers remain held. Async handlers are always handled; only a synchronous false can decline.

        • OptionalpreventDefault?: boolean
        • description: string
        • help: false | ShortcutHelpMetadata

          Shortcut-overlay metadata, or an explicit opt-out.

      Returns void

      // Register [ key for backward navigation
      manager.registerBinding(InputContext.NAVIGATION, {
      actionId: 'dimension.navigate',
      actionParameter: -1,
      key: '[',
      handler: () => navigateBackward(),
      preventDefault: true,
      description: 'Step along the selected dimension',
      help: false
      });

      // Register Ctrl+S for save (with modifier)
      manager.registerBinding(InputContext.UI_INTERACTION, {
      actionId: 'document.save',
      key: 's',
      modifiers: { ctrl: true },
      handler: () => save(),
      preventDefault: true,
      description: 'Save document',
      help: false
      });
    • Unregister a previously registered key binding.

      Removes the binding for the specified key and modifiers in the given context. Has no effect if the context or binding doesn't exist, which keeps teardown idempotent after context removal.

      Parameters

      • context: InputContextId

        Context containing the binding to remove

      • key: string

        Key that was bound

      • Optionalmodifiers: { ctrl?: boolean; shift?: boolean; alt?: boolean; meta?: boolean }

        Optional modifiers that were bound

      Returns void

      // Remove [ key binding
      manager.unregisterBinding(InputContext.NAVIGATION, '[');

      // Remove Ctrl+S binding
      manager.unregisterBinding(
      InputContext.UI_INTERACTION,
      's',
      { ctrl: true }
      );
    • Handle a keyboard event with context-aware routing.

      Routes the event through the context system to find and execute the appropriate handler. Processing order:

      1. Check if manager is enabled (keydown only)
      2. Check if in typing context (blocks most keydown events)
      3. Check if key is allowed in current context
      4. Look for registered binding in current context
      5. If passthrough is enabled, try the declared fallback contexts

      Parameters

      • event: KeyboardEvent

        Keyboard event to handle

      • type: "up" | "down"

        Event type ('down' for keydown, 'up' for keyup)

      Returns boolean

      true if event was handled by a binding, false if not handled (return value indicates whether to prevent default behavior)

      // In event listener
      document.addEventListener('keydown', (event) => {
      const handled = contextManager.handleKeyEvent(event, 'down');
      if (handled) {
      // Event was handled by context system
      console.log('Key handled by context manager');
      } else {
      // No handler found, let it propagate
      console.log('Key not handled, continuing...');
      }
      });
    • Private

      Check if a binding is allowed in the given context based on filters.

      Checks both blockedKeys and allowedKeys filters:

      • If the canonical binding key is in blockedKeys: returns false
      • If allowedKeys contains neither the base key nor canonical binding key: returns false
      • Otherwise: returns true

      Parameters

      • key: string

        Base key to check

      • bindingKey: string

        Canonical modifier-aware binding key

      • config: ContextConfig

        Context configuration with key filters

      Returns boolean

      true if key is allowed in this context, false if blocked

    • Dispatch Escape from a typing context.

      Walks built-in contexts plus the active context in priority order and fires the first matching Escape binding. Mirrors the dispatch shape of tryLowerContexts but does not exclude the current context — Escape is most often registered in NAVIGATION (the default current context), so excluding the current context like tryLowerContexts does would skip it.

      Parameters

      • event: KeyboardEvent
      • type: "up" | "down"

      Returns boolean

    • Private

      Try to handle an event in the active context's declared fallbacks.

      When current context doesn't handle a key and has passthrough enabled, this method tries its declared fallback contexts in descending priority order. For example, navigation shortcuts work in FLY_CONTROLS because that context explicitly falls back to NAVIGATION.

      Parameters

      • event: KeyboardEvent

        Keyboard event to handle

      • type: "up" | "down"

        Event type ('down' or 'up')

      Returns boolean

      true if a declared fallback handled the event, false otherwise

    • Private

      Check if currently in a typing context (should block shortcuts).

      Returns true if:

      • Current context is explicitly set to TYPING
      • Focus is in a text input, textarea, select, or contenteditable element

      Used to prevent keyboard shortcuts from interfering with text entry. For example, prevents 'p' key from toggling performance stats while user is typing "apple" in a search box.

      Returns boolean

      true if in typing context, false otherwise

    • Private

      Generate unique string key for a key binding (for Map storage).

      Combines key and modifiers into a sorted string representation. Format: "key+mod1+mod2" (alphabetically sorted modifiers). Used as key in Map to store and lookup bindings.

      Parameters

      • binding: Pick<KeyBinding, "key" | "modifiers">

        Key binding configuration

      Returns string

      Unique string key (e.g., "w", "[", "s+ctrl", "z+ctrl+shift")

      // Simple key
      const key1 = getBindingKey({ key: '[', handler: () => {} });
      console.log(key1); // "["

      // Key with modifiers (always sorted)
      const key2 = getBindingKey({
      key: 's',
      modifiers: { ctrl: true, shift: true },
      handler: () => {}
      });
      console.log(key2); // "ctrl+s+shift" (sorted alphabetically)
    • Private

      Generate binding key from keyboard event for lookup.

      Converts KeyboardEvent to the same string format as getBindingKey() for Map lookup. Checks modifier properties (ctrlKey, shiftKey, etc.) and combines with key in sorted format.

      Parameters

      • event: KeyboardEvent

        Keyboard event to convert

      Returns string

      Unique string key matching getBindingKey() format

      // Event with Ctrl+S
      const event = new KeyboardEvent('keydown', {
      key: 's',
      ctrlKey: true
      });
      const key = getBindingKeyFromEvent(event);
      console.log(key); // "ctrl+s"
    • Enable or disable the entire context manager.

      When disabled, keydown events return false without processing. Keyup handlers still run so stateful bindings can release held input. Useful for temporarily suspending context-based input handling without leaving movement or modifier state latched.

      Parameters

      • enabled: boolean

        true to enable context management, false to disable

      Returns void

    • Get debug information about current context manager state.

      Returns snapshot of current state for debugging and diagnostics. Useful for understanding why a key isn't working or what context is active.

      Returns {
          currentContext: string;
          contextStack: string[];
          registeredBindings: Map<string, RegisteredShortcutBinding[]>;
      }

      Object containing: - currentContext: Active context - contextStack: Stack of pushed contexts - registeredBindings: Map of context → binding keys

      const debug = contextManager.getDebugInfo();
      console.log('Current context:', debug.currentContext);
      console.log('Context stack:', debug.contextStack);
      console.log('Bindings in NAVIGATION:', debug.registeredBindings.get(InputContext.NAVIGATION));
      // Output:
      // Current context: navigation
      // Context stack: []
      // Bindings in NAVIGATION: [{ actionId: 'help.toggle', key: 'h', ... }]
    • Resolve an action label in the active context, then its explicit fallbacks.

      Parameters

      • actionId: string

      Returns string | undefined

    • Clear all registered key bindings for a specific context.

      Removes all bindings associated with the specified context. Useful when dynamically changing context configuration or cleaning up temporary bindings.

      Parameters

      Returns void

    • Reset context manager to initial state.

      Clears all registered bindings, empties context stack, and returns to NAVIGATION context. Useful when reinitializing the application or cleaning up for testing.

      Restores the built-in context configurations and removes custom contexts.

      Returns void