import { CommonModule } from '@angular/common';
import { Component, Input, Output, EventEmitter, HostListener, signal, computed, ViewChild, } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { searchOutline, closeOutline } from 'ionicons/icons';
import { Subject } from 'rxjs';
import { debounceTime, takeUntil } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@angular/router";
import * as i2 from "@angular/forms";
addIcons({ searchOutline, closeOutline });
/**
 * val-docs-search
 *
 * A search component for documentation with keyboard navigation support.
 * Supports Cmd+K / Ctrl+K shortcut to open.
 *
 * @example
 * ```html
 * <val-docs-search
 *   [props]="{
 *     placeholder: 'Search docs...',
 *     sections: sidebarSections,
 *     showShortcut: true
 *   }"
 *   (navigate)="onNavigate($event)"
 * ></val-docs-search>
 * ```
 */
export class DocsSearchComponent {
    constructor(router) {
        this.router = router;
        this.props = {};
        this.navigate = new EventEmitter();
        this.search = new EventEmitter();
        this.searchQuery = signal('');
        this.showResults = signal(false);
        this.selectedIndex = signal(0);
        this.searchSubject = new Subject();
        this.destroy$ = new Subject();
        this.isMac = typeof navigator !== 'undefined' && navigator.platform.toLowerCase().includes('mac');
        this.results = computed(() => {
            const query = this.searchQuery().toLowerCase().trim();
            if (!query || !this.props.sections)
                return [];
            const results = [];
            this.props.sections.forEach((section) => {
                section.items.forEach((item) => {
                    // Match label
                    if (item.label.toLowerCase().includes(query)) {
                        results.push({ section: section.title, item, matchType: 'label' });
                        return;
                    }
                    // Match description
                    if (item.description?.toLowerCase().includes(query)) {
                        results.push({ section: section.title, item, matchType: 'description' });
                        return;
                    }
                    // Match keywords
                    if (item.keywords?.some((kw) => kw.toLowerCase().includes(query))) {
                        results.push({ section: section.title, item, matchType: 'keyword' });
                    }
                });
            });
            return results.slice(0, 10); // Limit results
        });
        this.searchSubject
            .pipe(debounceTime(this.props.debounceMs || 150), takeUntil(this.destroy$))
            .subscribe((query) => {
            this.search.emit(query);
        });
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
    }
    onGlobalKeydown(event) {
        // Cmd+K or Ctrl+K to focus search
        if ((event.metaKey || event.ctrlKey) && event.key === 'k') {
            event.preventDefault();
            this.searchInputEl?.nativeElement.focus();
        }
    }
    onQueryChange(query) {
        this.searchQuery.set(query);
        this.selectedIndex.set(0);
        this.searchSubject.next(query);
    }
    onFocus() {
        this.showResults.set(true);
    }
    onBlur() {
        // Delay to allow click on results
        setTimeout(() => this.showResults.set(false), 200);
    }
    onInputKeydown(event) {
        const resultsArray = this.results();
        switch (event.key) {
            case 'ArrowDown':
                event.preventDefault();
                this.selectedIndex.update((i) => Math.min(i + 1, resultsArray.length - 1));
                break;
            case 'ArrowUp':
                event.preventDefault();
                this.selectedIndex.update((i) => Math.max(i - 1, 0));
                break;
            case 'Enter':
                event.preventDefault();
                if (resultsArray[this.selectedIndex()]) {
                    this.selectResult(resultsArray[this.selectedIndex()]);
                }
                break;
            case 'Escape':
                event.preventDefault();
                this.clearSearch();
                this.searchInputEl?.nativeElement.blur();
                break;
        }
    }
    selectResult(result) {
        this.navigate.emit(result.item.route);
        this.router.navigate(result.item.route);
        this.clearSearch();
    }
    clearSearch() {
        this.searchQuery.set('');
        this.selectedIndex.set(0);
        this.showResults.set(false);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DocsSearchComponent, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: DocsSearchComponent, isStandalone: true, selector: "val-docs-search", inputs: { props: "props" }, outputs: { navigate: "navigate", search: "search" }, host: { listeners: { "document:keydown": "onGlobalKeydown($event)" } }, viewQueries: [{ propertyName: "searchInputEl", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: `
    <div class="docs-search" [class]="props.cssClass">
      <div class="docs-search__input-wrapper">
        <ion-icon name="search-outline" class="docs-search__icon"></ion-icon>
        <input
          #searchInput
          type="text"
          class="docs-search__input"
          [placeholder]="props.placeholder || 'Search...'"
          [(ngModel)]="searchQuery"
          (ngModelChange)="onQueryChange($event)"
          (keydown)="onInputKeydown($event)"
          (focus)="onFocus()"
          (blur)="onBlur()"
          aria-label="Search documentation"
          autocomplete="off"
        />
        @if (searchQuery()) {
          <button
            type="button"
            class="docs-search__clear"
            (click)="clearSearch()"
            aria-label="Clear search"
          >
            <ion-icon name="close-outline"></ion-icon>
          </button>
        } @else if (props.showShortcut) {
          <span class="docs-search__shortcut">{{ isMac ? '⌘' : 'Ctrl' }}+K</span>
        }
      </div>

      @if (showResults() && results().length > 0) {
        <div class="docs-search__results" role="listbox">
          @for (result of results(); track result.item.label; let i = $index) {
            <button
              type="button"
              class="docs-search__result"
              [class.docs-search__result--active]="selectedIndex() === i"
              role="option"
              [attr.aria-selected]="selectedIndex() === i"
              (click)="selectResult(result)"
              (mouseenter)="selectedIndex.set(i)"
            >
              <span class="docs-search__result-section">{{ result.section }}</span>
              <span class="docs-search__result-label">{{ result.item.label }}</span>
              @if (result.item.description) {
                <span class="docs-search__result-description">{{ result.item.description }}</span>
              }
            </button>
          }
        </div>
      }

      @if (showResults() && searchQuery() && results().length === 0) {
        <div class="docs-search__no-results">
          No results found for "{{ searchQuery() }}"
        </div>
      }
    </div>
  `, isInline: true, styles: [".docs-search{--search-bg: var(--ion-background-color, #fff);--search-border: var(--ion-border-color, #e0e0e0);--search-text: var(--ion-text-color, #1a1a1a);--search-placeholder: var(--ion-color-medium, #666);--search-hover-bg: rgba(0, 0, 0, .03);--search-active-bg: rgba(0, 0, 0, .05);position:relative;font-family:var(--ion-font-family, system-ui, sans-serif)}.docs-search__input-wrapper{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:var(--search-bg);border:1px solid var(--search-border);border-radius:8px;transition:all .15s ease}.docs-search__input-wrapper:focus-within{border-color:#1a1a1a;box-shadow:0 0 0 3px #0000000d}.docs-search__icon{font-size:1rem;color:var(--search-placeholder);flex-shrink:0}.docs-search__input{flex:1;border:none;outline:none;background:transparent;font-size:.875rem;color:var(--search-text);min-width:0}.docs-search__input::placeholder{color:var(--search-placeholder)}.docs-search__clear{display:flex;align-items:center;justify-content:center;padding:.25rem;border:none;background:transparent;color:var(--search-placeholder);cursor:pointer;border-radius:4px;transition:all .15s ease}.docs-search__clear:hover{background:var(--search-hover-bg);color:var(--search-text)}.docs-search__clear:focus-visible{outline:2px solid #1a1a1a;outline-offset:2px}.docs-search__clear ion-icon{font-size:.875rem}.docs-search__shortcut{font-size:.6875rem;font-weight:500;color:var(--search-placeholder);background:var(--search-hover-bg);padding:.125rem .375rem;border-radius:4px;white-space:nowrap}.docs-search__results{position:absolute;top:calc(100% + 4px);left:0;right:0;max-height:400px;overflow-y:auto;background:var(--search-bg);border:1px solid var(--search-border);border-radius:8px;box-shadow:0 4px 16px #0000001a;z-index:100}.docs-search__result{display:flex;flex-direction:column;gap:.125rem;width:100%;padding:.75rem 1rem;border:none;background:transparent;text-align:left;cursor:pointer;transition:background .15s ease;border-bottom:1px solid var(--search-border)}.docs-search__result:last-child{border-bottom:none}.docs-search__result:hover,.docs-search__result--active{background:var(--search-hover-bg)}.docs-search__result:focus-visible{outline:2px solid #1a1a1a;outline-offset:-2px}.docs-search__result-section{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--search-placeholder)}.docs-search__result-label{font-size:.875rem;font-weight:500;color:var(--search-text)}.docs-search__result-description{font-size:.75rem;color:var(--search-placeholder);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.docs-search__no-results{padding:1.5rem 1rem;text-align:center;font-size:.875rem;color:var(--search-placeholder);background:var(--search-bg);border:1px solid var(--search-border);border-radius:8px;box-shadow:0 4px 16px #0000001a;position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:100}:host-context(.dark) .docs-search,:host-context([color-scheme=dark]) .docs-search{--search-bg: #1e1e1e;--search-border: #3a3a3a;--search-text: #f4f5f8;--search-placeholder: #a0a0a0;--search-hover-bg: rgba(255, 255, 255, .05);--search-active-bg: rgba(255, 255, 255, .08)}:host-context(.dark) .docs-search__input-wrapper:focus-within,:host-context([color-scheme=dark]) .docs-search__input-wrapper:focus-within{border-color:#f4f5f8;box-shadow:0 0 0 3px #ffffff0d}:host-context(.dark) .docs-search__results,:host-context(.dark) .docs-search__no-results,:host-context([color-scheme=dark]) .docs-search__results,:host-context([color-scheme=dark]) .docs-search__no-results{box-shadow:0 4px 16px #0000004d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DocsSearchComponent, decorators: [{
            type: Component,
            args: [{ selector: 'val-docs-search', standalone: true, imports: [CommonModule, FormsModule, IonIcon], template: `
    <div class="docs-search" [class]="props.cssClass">
      <div class="docs-search__input-wrapper">
        <ion-icon name="search-outline" class="docs-search__icon"></ion-icon>
        <input
          #searchInput
          type="text"
          class="docs-search__input"
          [placeholder]="props.placeholder || 'Search...'"
          [(ngModel)]="searchQuery"
          (ngModelChange)="onQueryChange($event)"
          (keydown)="onInputKeydown($event)"
          (focus)="onFocus()"
          (blur)="onBlur()"
          aria-label="Search documentation"
          autocomplete="off"
        />
        @if (searchQuery()) {
          <button
            type="button"
            class="docs-search__clear"
            (click)="clearSearch()"
            aria-label="Clear search"
          >
            <ion-icon name="close-outline"></ion-icon>
          </button>
        } @else if (props.showShortcut) {
          <span class="docs-search__shortcut">{{ isMac ? '⌘' : 'Ctrl' }}+K</span>
        }
      </div>

      @if (showResults() && results().length > 0) {
        <div class="docs-search__results" role="listbox">
          @for (result of results(); track result.item.label; let i = $index) {
            <button
              type="button"
              class="docs-search__result"
              [class.docs-search__result--active]="selectedIndex() === i"
              role="option"
              [attr.aria-selected]="selectedIndex() === i"
              (click)="selectResult(result)"
              (mouseenter)="selectedIndex.set(i)"
            >
              <span class="docs-search__result-section">{{ result.section }}</span>
              <span class="docs-search__result-label">{{ result.item.label }}</span>
              @if (result.item.description) {
                <span class="docs-search__result-description">{{ result.item.description }}</span>
              }
            </button>
          }
        </div>
      }

      @if (showResults() && searchQuery() && results().length === 0) {
        <div class="docs-search__no-results">
          No results found for "{{ searchQuery() }}"
        </div>
      }
    </div>
  `, styles: [".docs-search{--search-bg: var(--ion-background-color, #fff);--search-border: var(--ion-border-color, #e0e0e0);--search-text: var(--ion-text-color, #1a1a1a);--search-placeholder: var(--ion-color-medium, #666);--search-hover-bg: rgba(0, 0, 0, .03);--search-active-bg: rgba(0, 0, 0, .05);position:relative;font-family:var(--ion-font-family, system-ui, sans-serif)}.docs-search__input-wrapper{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;background:var(--search-bg);border:1px solid var(--search-border);border-radius:8px;transition:all .15s ease}.docs-search__input-wrapper:focus-within{border-color:#1a1a1a;box-shadow:0 0 0 3px #0000000d}.docs-search__icon{font-size:1rem;color:var(--search-placeholder);flex-shrink:0}.docs-search__input{flex:1;border:none;outline:none;background:transparent;font-size:.875rem;color:var(--search-text);min-width:0}.docs-search__input::placeholder{color:var(--search-placeholder)}.docs-search__clear{display:flex;align-items:center;justify-content:center;padding:.25rem;border:none;background:transparent;color:var(--search-placeholder);cursor:pointer;border-radius:4px;transition:all .15s ease}.docs-search__clear:hover{background:var(--search-hover-bg);color:var(--search-text)}.docs-search__clear:focus-visible{outline:2px solid #1a1a1a;outline-offset:2px}.docs-search__clear ion-icon{font-size:.875rem}.docs-search__shortcut{font-size:.6875rem;font-weight:500;color:var(--search-placeholder);background:var(--search-hover-bg);padding:.125rem .375rem;border-radius:4px;white-space:nowrap}.docs-search__results{position:absolute;top:calc(100% + 4px);left:0;right:0;max-height:400px;overflow-y:auto;background:var(--search-bg);border:1px solid var(--search-border);border-radius:8px;box-shadow:0 4px 16px #0000001a;z-index:100}.docs-search__result{display:flex;flex-direction:column;gap:.125rem;width:100%;padding:.75rem 1rem;border:none;background:transparent;text-align:left;cursor:pointer;transition:background .15s ease;border-bottom:1px solid var(--search-border)}.docs-search__result:last-child{border-bottom:none}.docs-search__result:hover,.docs-search__result--active{background:var(--search-hover-bg)}.docs-search__result:focus-visible{outline:2px solid #1a1a1a;outline-offset:-2px}.docs-search__result-section{font-size:.625rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--search-placeholder)}.docs-search__result-label{font-size:.875rem;font-weight:500;color:var(--search-text)}.docs-search__result-description{font-size:.75rem;color:var(--search-placeholder);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.docs-search__no-results{padding:1.5rem 1rem;text-align:center;font-size:.875rem;color:var(--search-placeholder);background:var(--search-bg);border:1px solid var(--search-border);border-radius:8px;box-shadow:0 4px 16px #0000001a;position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:100}:host-context(.dark) .docs-search,:host-context([color-scheme=dark]) .docs-search{--search-bg: #1e1e1e;--search-border: #3a3a3a;--search-text: #f4f5f8;--search-placeholder: #a0a0a0;--search-hover-bg: rgba(255, 255, 255, .05);--search-active-bg: rgba(255, 255, 255, .08)}:host-context(.dark) .docs-search__input-wrapper:focus-within,:host-context([color-scheme=dark]) .docs-search__input-wrapper:focus-within{border-color:#f4f5f8;box-shadow:0 0 0 3px #ffffff0d}:host-context(.dark) .docs-search__results,:host-context(.dark) .docs-search__no-results,:host-context([color-scheme=dark]) .docs-search__results,:host-context([color-scheme=dark]) .docs-search__no-results{box-shadow:0 4px 16px #0000004d}\n"] }]
        }], ctorParameters: () => [{ type: i1.Router }], propDecorators: { props: [{
                type: Input
            }], navigate: [{
                type: Output
            }], search: [{
                type: Output
            }], searchInputEl: [{
                type: ViewChild,
                args: ['searchInput']
            }], onGlobalKeydown: [{
                type: HostListener,
                args: ['document:keydown', ['$event']]
            }] } });
//# sourceMappingURL=data:application/json;base64, 