UNPKG

asciitorium

Version:
81 lines (80 loc) 2.64 kB
import { Component } from '../core/Component.js'; import { State } from '../core/State.js'; export class Keybind extends Component { constructor(options) { super({ ...options, width: 0, // Non-visual component height: 0, border: false, visible: new State(false) // Explicitly invisible - not a visual component }); this.registrationAttempted = false; this.destroyed = false; this.keyBinding = options.keyBinding; this.action = options.action; this.description = options.description; this.priority = options.priority ?? 0; // Handle disabled state (reactive or static) if (options.disabled instanceof State) { this.disabledState = options.disabled; this.staticDisabled = false; } else { this.staticDisabled = options.disabled ?? false; } } get disabled() { return this.disabledState?.value ?? this.staticDisabled; } // Override setParent to register with App when added setParent(parent) { super.setParent(parent); this.registerWithApp(); } registerWithApp() { if (this.registrationAttempted || this.destroyed) { return; // Prevent infinite loops and registration after destruction } // Walk up parent chain to find App let current = this.parent; while (current && !current.isApp) { current = current.parent; } if (current && current.registerKeybind) { current.registerKeybind(this); this.registrationAttempted = true; } else { // Try again after a short delay in case the parent tree isn't fully built yet this.timeoutId = setTimeout(() => { if (!this.destroyed) { this.registerWithApp(); } }, 0); } } // Called when component is removed destroy() { this.destroyed = true; // Clear any pending registration timeout if (this.timeoutId !== undefined) { clearTimeout(this.timeoutId); this.timeoutId = undefined; } this.unregisterWithApp(); super.destroy(); } unregisterWithApp() { let current = this.parent; while (current && !current.isApp) { current = current.parent; } if (current && current.unregisterKeybind) { current.unregisterKeybind(this); } } draw() { return []; // Never renders } }