import { Component, Input, Output, EventEmitter, signal, ViewChild, ElementRef, ChangeDetectionStrategy, AfterViewInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { SearchQueryAssistantComponent } from '../search-query-assistant/search-query-assistant.component'; import { inject } from '@angular/core'; import { SearchHistoryService } from '../../core/search/search-history.service'; /** * Search input with integrated query assistant * Wraps a text input and manages the search assistant popover */ @Component({ selector: 'app-search-input-with-assistant', standalone: true, imports: [CommonModule, FormsModule, SearchQueryAssistantComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
`, styles: [` :host { display: block; } `] }) export class SearchInputWithAssistantComponent implements AfterViewInit { @Input() placeholder: string = 'Search...'; @Input() value: string = ''; @Input() context: string = 'default'; @Input() showSearchIcon: boolean = true; @Input() inputClass: string = 'w-full px-3 py-2 text-sm border border-border rounded-md bg-bg-primary text-text-main placeholder-text-muted focus:outline-none focus:ring-2 focus:ring-accent'; @Output() valueChange = new EventEmitter(); @Output() submit = new EventEmitter(); @ViewChild('searchInput') searchInputRef?: ElementRef; @ViewChild('assistant') assistantRef?: SearchQueryAssistantComponent; anchorElement: HTMLElement | null = null; private historyService = inject(SearchHistoryService); constructor(private hostElement: ElementRef) {} ngAfterViewInit(): void { this.anchorElement = this.hostElement.nativeElement; } /** * Handle input changes */ onInputChange(event: Event): void { const target = event.target as HTMLInputElement; this.value = target.value; this.valueChange.emit(this.value); // Update suggestions in assistant if (this.assistantRef) { this.assistantRef.currentQuery = this.value; this.assistantRef.updateOptions(); this.assistantRef.updateSuggestions(); } } /** * Handle focus event - open assistant */ onFocus(): void { if (this.assistantRef) { this.assistantRef.open(); } } /** * Handle blur event */ onBlur(): void { // Delay close to allow clicking on popover items setTimeout(() => { if (this.assistantRef && !this.assistantRef.popoverRef) { // Only close if not interacting with popover } }, 200); } /** * Handle Enter key */ onEnter(): void { // Save to history and submit if (this.value.trim()) { this.historyService.add(this.context, this.value); } this.submit.emit(this.value); if (this.assistantRef) { this.assistantRef.refreshHistoryView(); this.assistantRef.close(); } } /** * Handle query change from assistant */ onQueryChange(query: string): void { this.value = query; this.valueChange.emit(query); if (this.searchInputRef) { this.searchInputRef.nativeElement.value = query; } if (this.assistantRef) { this.assistantRef.currentQuery = query; this.assistantRef.updateOptions(); this.assistantRef.updateSuggestions(); } } /** * Handle query submit from assistant */ onQuerySubmit(query: string): void { this.value = query; if (query.trim()) { this.historyService.add(this.context, query); } this.submit.emit(query); if (this.searchInputRef) { this.searchInputRef.nativeElement.value = query; this.searchInputRef.nativeElement.focus(); } if (this.assistantRef) { this.assistantRef.currentQuery = query; this.assistantRef.refreshHistoryView(); this.assistantRef.close(); } } /** * Clear the input */ clear(): void { this.value = ''; this.valueChange.emit(''); if (this.searchInputRef) { this.searchInputRef.nativeElement.value = ''; this.searchInputRef.nativeElement.focus(); } } /** * Focus the input */ focus(): void { if (this.searchInputRef) { this.searchInputRef.nativeElement.focus(); } } }