/** * Search Controller * * Handles global search functionality and keyboard shortcuts */ export class SearchController { private input: HTMLInputElement | null = null; private container: HTMLElement | null = null; constructor() { this.input = document.getElementById('globalSearch') as HTMLInputElement | null; this.container = document.querySelector('swp-topbar-search'); this.setupListeners(); } /** * Get current search value */ get value(): string { return this.input?.value ?? ''; } /** * Set search value */ set value(val: string) { if (this.input) { this.input.value = val; } } /** * Focus the search input */ focus(): void { this.input?.focus(); } /** * Blur the search input */ blur(): void { this.input?.blur(); } /** * Clear the search input */ clear(): void { this.value = ''; } private setupListeners(): void { // Keyboard shortcuts document.addEventListener('keydown', (e) => this.handleKeyboard(e)); // Input handlers if (this.input) { this.input.addEventListener('input', (e) => this.handleInput(e)); // Prevent form submission if wrapped in form const form = this.input.closest('form'); form?.addEventListener('submit', (e) => this.handleSubmit(e)); } } private handleKeyboard(e: KeyboardEvent): void { // Cmd/Ctrl + K to focus search if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); this.focus(); return; } // Escape to blur search when focused if (e.key === 'Escape' && document.activeElement === this.input) { this.blur(); } } private handleInput(e: Event): void { const target = e.target as HTMLInputElement; const query = target.value.trim(); // Emit custom event for search document.dispatchEvent(new CustomEvent('app:search', { detail: { query }, bubbles: true })); } private handleSubmit(e: Event): void { e.preventDefault(); const query = this.value.trim(); if (!query) return; // Emit custom event for search submit document.dispatchEvent(new CustomEvent('app:search-submit', { detail: { query }, bubbles: true })); } }