@memberjunction/ng-search 5.25.0 → 5.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -46,6 +46,7 @@ export declare class SearchCompositeComponent implements OnInit, OnDestroy {
46
46
  RecentSearches: RecentSearch[];
47
47
  PreviewTotalCount: number;
48
48
  IsPreviewLoading: boolean;
49
+ private previewSearchVersion;
49
50
  ngOnInit(): void;
50
51
  ngOnDestroy(): void;
51
52
  OnDocumentMousedown(event: MouseEvent): void;
@@ -1 +1 @@
1
- {"version":3,"file":"search-composite.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-composite.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAGH,YAAY,EAGZ,SAAS,EACT,MAAM,EAKT,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;;AAElD,qBAMa,wBAAyB,YAAW,MAAM,EAAE,SAAS;IAC9D,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,UAAU,CAAsB;IACxC,SAAS,CAAC,aAAa,gBAAyB;IAChD,OAAO,CAAC,QAAQ,CAAuB;IAEb,cAAc,EAAG,oBAAoB,CAAC;IACpC,gBAAgB,EAAG,sBAAsB,CAAC;IAItE,4CAA4C;IACnC,WAAW,SAAe;IAEnC,0DAA0D;IACjD,gBAAgB,UAAQ;IAEjC,sDAAsD;IAC7C,UAAU,SAAO;IAE1B,8DAA8D;IACrD,cAAc,SAAK;IAE5B,gEAAgE;IACvD,iBAAiB,SAAK;IAE/B,sDAAsD;IAC7C,aAAa,UAAQ;IAE9B,gDAAgD;IACvC,YAAY,UAAQ;IAI7B,kEAAkE;IACxD,cAAc,iCAAwC;IAEhE,mFAAmF;IACzE,eAAe,uBAA8B;IAEvD,uDAAuD;IAC7C,eAAe,uBAA8B;IAIhD,KAAK,SAAM;IACX,aAAa,UAAS;IAE7B,yEAAyE;IACzE,IAAW,mBAAmB,IAAI,MAAM,CAEvC;IACM,cAAc,EAAE,gBAAgB,EAAE,CAAM;IACxC,cAAc,EAAE,YAAY,EAAE,CAAM;IACpC,iBAAiB,SAAK;IACtB,gBAAgB,UAAS;IAEhC,QAAQ,IAAI,IAAI;IAKhB,WAAW,IAAI,IAAI;IAQnB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAU5C,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAuBzC,oDAAoD;IAC7C,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAYzC,sCAAsC;IAC/B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAazC,yBAAyB;IAClB,cAAc,IAAI,IAAI;IAI7B,uCAAuC;IAChC,cAAc,IAAI,IAAI;IAM7B,2BAA2B;IACpB,cAAc,IAAI,IAAI;IAM7B,oDAAoD;IAC7C,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAKvD,qCAAqC;IAC9B,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM5C,6BAA6B;IACtB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7C,qCAAqC;IAC9B,sBAAsB,IAAI,IAAI;IAMrC,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,yBAAyB;YASnB,oBAAoB;IAoBlC,OAAO,CAAC,mBAAmB;yCAxNlB,wBAAwB;2CAAxB,wBAAwB;CA6NpC"}
1
+ {"version":3,"file":"search-composite.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-composite.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAGH,YAAY,EAGZ,SAAS,EACT,MAAM,EAKT,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;;AAElD,qBAMa,wBAAyB,YAAW,MAAM,EAAE,SAAS;IAC9D,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,UAAU,CAAsB;IACxC,SAAS,CAAC,aAAa,gBAAyB;IAChD,OAAO,CAAC,QAAQ,CAAuB;IAEb,cAAc,EAAG,oBAAoB,CAAC;IACpC,gBAAgB,EAAG,sBAAsB,CAAC;IAItE,4CAA4C;IACnC,WAAW,SAAe;IAEnC,0DAA0D;IACjD,gBAAgB,UAAQ;IAEjC,sDAAsD;IAC7C,UAAU,SAAO;IAE1B,8DAA8D;IACrD,cAAc,SAAK;IAE5B,gEAAgE;IACvD,iBAAiB,SAAK;IAE/B,sDAAsD;IAC7C,aAAa,UAAQ;IAE9B,gDAAgD;IACvC,YAAY,UAAQ;IAI7B,kEAAkE;IACxD,cAAc,iCAAwC;IAEhE,mFAAmF;IACzE,eAAe,uBAA8B;IAEvD,uDAAuD;IAC7C,eAAe,uBAA8B;IAIhD,KAAK,SAAM;IACX,aAAa,UAAS;IAE7B,yEAAyE;IACzE,IAAW,mBAAmB,IAAI,MAAM,CAEvC;IACM,cAAc,EAAE,gBAAgB,EAAE,CAAM;IACxC,cAAc,EAAE,YAAY,EAAE,CAAM;IACpC,iBAAiB,SAAK;IACtB,gBAAgB,UAAS;IAChC,OAAO,CAAC,oBAAoB,CAAK;IAEjC,QAAQ,IAAI,IAAI;IAKhB,WAAW,IAAI,IAAI;IAQnB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAU5C,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAuBzC,oDAAoD;IAC7C,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAYzC,sCAAsC;IAC/B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAazC,yBAAyB;IAClB,cAAc,IAAI,IAAI;IAI7B,uCAAuC;IAChC,cAAc,IAAI,IAAI;IAM7B,2BAA2B;IACpB,cAAc,IAAI,IAAI;IAM7B,oDAAoD;IAC7C,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAKvD,qCAAqC;IAC9B,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM5C,6BAA6B;IACtB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7C,qCAAqC;IAC9B,sBAAsB,IAAI,IAAI;IAMrC,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,yBAAyB;YASnB,oBAAoB;IAyBlC,OAAO,CAAC,mBAAmB;yCA9NlB,wBAAwB;2CAAxB,wBAAwB;CAmOpC"}
@@ -27,7 +27,7 @@ export class SearchCompositeComponent {
27
27
  /** Whether to show keyboard shortcut hint on the input */
28
28
  ShowShortcutHint = true;
29
29
  /** Debounce time in milliseconds for query changes */
30
- DebounceMs = 200;
30
+ DebounceMs = 400;
31
31
  /** Minimum query length before preview results are fetched */
32
32
  MinQueryLength = 2;
33
33
  /** Maximum number of preview results to show in the dropdown */
@@ -54,6 +54,7 @@ export class SearchCompositeComponent {
54
54
  RecentSearches = [];
55
55
  PreviewTotalCount = 0;
56
56
  IsPreviewLoading = false;
57
+ previewSearchVersion = 0;
57
58
  ngOnInit() {
58
59
  this.subscribeToRecentSearches();
59
60
  this.searchService.LoadRecentSearches(); // fire-and-forget — loads from UserInfoEngine
@@ -170,23 +171,28 @@ export class SearchCompositeComponent {
170
171
  });
171
172
  }
172
173
  async executePreviewSearch(query) {
174
+ const version = ++this.previewSearchVersion;
173
175
  this.IsPreviewLoading = true;
174
176
  this.cdr.detectChanges();
175
177
  try {
176
178
  const response = await this.searchService.PreviewSearch(query, this.MaxPreviewResults);
177
- // Only apply if query hasn't changed since we started
178
- if (this.Query === query) {
179
+ // Only apply if this is still the latest request and query hasn't changed
180
+ if (version === this.previewSearchVersion && this.Query === query) {
179
181
  this.PreviewResults = response.Results;
180
182
  this.PreviewTotalCount = response.TotalCount;
181
183
  }
182
184
  }
183
185
  catch {
184
- this.PreviewResults = [];
185
- this.PreviewTotalCount = 0;
186
+ if (version === this.previewSearchVersion) {
187
+ this.PreviewResults = [];
188
+ this.PreviewTotalCount = 0;
189
+ }
186
190
  }
187
191
  finally {
188
- this.IsPreviewLoading = false;
189
- this.cdr.detectChanges();
192
+ if (version === this.previewSearchVersion) {
193
+ this.IsPreviewLoading = false;
194
+ this.cdr.detectChanges();
195
+ }
190
196
  }
191
197
  }
192
198
  clearPreviewResults() {
@@ -1 +1 @@
1
- {"version":3,"file":"search-composite.component.js","sourceRoot":"","sources":["../../src/lib/search-composite.component.ts","../../src/lib/search-composite.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Composite Component\n *\n * Drop-in widget combining SearchInputComponent + SearchSuggestComponent.\n * Handles query debouncing, preview search calls, recent searches,\n * keyboard navigation delegation, and click-outside-to-close.\n */\n\nimport {\n Component,\n ElementRef,\n EventEmitter,\n HostListener,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ViewChild,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { SearchService, RecentSearch } from './search.service';\nimport { SearchInputComponent } from './search-input.component';\nimport { SearchSuggestComponent } from './search-suggest.component';\nimport { SearchResultItem } from './search-types';\n\n@Component({\n standalone: false,\n selector: 'mj-search-composite',\n templateUrl: './search-composite.component.html',\n styleUrls: ['./search-composite.component.css']\n})\nexport class SearchCompositeComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private elementRef = inject(ElementRef);\n protected searchService = inject(SearchService);\n private destroy$ = new Subject<void>();\n\n @ViewChild('searchInput') searchInputRef!: SearchInputComponent;\n @ViewChild('searchSuggest') searchSuggestRef!: SearchSuggestComponent;\n\n // --- Configuration Inputs ---\n\n /** Placeholder text for the search input */\n @Input() Placeholder = 'Search...';\n\n /** Whether to show keyboard shortcut hint on the input */\n @Input() ShowShortcutHint = true;\n\n /** Debounce time in milliseconds for query changes */\n @Input() DebounceMs = 200;\n\n /** Minimum query length before preview results are fetched */\n @Input() MinQueryLength = 2;\n\n /** Maximum number of preview results to show in the dropdown */\n @Input() MaxPreviewResults = 8;\n\n /** Whether to enable live preview search on typing */\n @Input() EnablePreview = true;\n\n /** Whether to enable recent searches display */\n @Input() EnableRecent = true;\n\n // --- Outputs ---\n\n /** Emitted when a result is selected from the preview dropdown */\n @Output() ResultSelected = new EventEmitter<SearchResultItem>();\n\n /** Emitted when the user presses Enter or selects a recent search (full search) */\n @Output() SearchSubmitted = new EventEmitter<string>();\n\n /** Emitted when the user clicks \"See all N results\" */\n @Output() SeeAllRequested = new EventEmitter<string>();\n\n // --- Internal state ---\n\n public Query = '';\n public IsSuggestOpen = false;\n\n /** The current min relevance percent from the suggest dropdown filter */\n public get MinRelevancePercent(): number {\n return this.searchSuggestRef?.MinRelevancePercent ?? 0;\n }\n public PreviewResults: SearchResultItem[] = [];\n public RecentSearches: RecentSearch[] = [];\n public PreviewTotalCount = 0;\n public IsPreviewLoading = false;\n\n ngOnInit(): void {\n this.subscribeToRecentSearches();\n this.searchService.LoadRecentSearches(); // fire-and-forget — loads from UserInfoEngine\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // --- Click outside to close ---\n\n @HostListener('document:mousedown', ['$event'])\n OnDocumentMousedown(event: MouseEvent): void {\n const target = event.target as Node | null;\n if (target && !this.elementRef.nativeElement.contains(target)) {\n this.closeSuggest();\n }\n }\n\n // --- Keyboard navigation delegation ---\n\n @HostListener('keydown', ['$event'])\n OnHostKeydown(event: KeyboardEvent): void {\n if (!this.IsSuggestOpen) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.searchSuggestRef?.NavigateDown();\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.searchSuggestRef?.NavigateUp();\n break;\n case 'Enter':\n if (this.searchSuggestRef?.HighlightedIndex >= 0) {\n event.preventDefault();\n this.searchSuggestRef.SelectHighlighted();\n }\n break;\n }\n }\n\n // --- Event handlers from child components ---\n\n /** Handle debounced query changes from the input */\n public OnQueryChange(query: string): void {\n this.Query = query;\n\n if (query.length >= this.MinQueryLength && this.EnablePreview) {\n this.executePreviewSearch(query);\n } else {\n this.clearPreviewResults();\n }\n\n this.openSuggest();\n }\n\n /** Handle Enter press in the input */\n public OnQuerySubmit(query: string): void {\n // If a suggestion is highlighted, select it instead of searching\n if (this.IsSuggestOpen && this.searchSuggestRef && this.searchSuggestRef.HighlightedIndex >= 0) {\n this.searchSuggestRef.SelectHighlighted();\n return;\n }\n\n if (query.trim().length > 0) {\n this.SearchSubmitted.emit(query.trim());\n this.closeSuggest();\n }\n }\n\n /** Handle input focus */\n public OnInputFocused(): void {\n this.openSuggest();\n }\n\n /** Handle Escape press in the input */\n public OnInputEscaped(): void {\n if (this.IsSuggestOpen) {\n this.closeSuggest();\n }\n }\n\n /** Handle input cleared */\n public OnInputCleared(): void {\n this.Query = '';\n this.clearPreviewResults();\n this.openSuggest();\n }\n\n /** Handle result selection from suggest dropdown */\n public OnResultSelected(result: SearchResultItem): void {\n this.ResultSelected.emit(result);\n this.closeSuggest();\n }\n\n /** Handle recent search selection */\n public OnRecentSelected(query: string): void {\n this.Query = query;\n this.SearchSubmitted.emit(query);\n this.closeSuggest();\n }\n\n /** Handle \"See all\" click */\n public OnSeeAllRequested(query: string): void {\n this.SeeAllRequested.emit(query);\n this.closeSuggest();\n }\n\n /** Handle \"Clear\" recent searches */\n public OnClearRecentRequested(): void {\n this.searchService.ClearRecentSearches();\n }\n\n // --- Private ---\n\n private openSuggest(): void {\n this.IsSuggestOpen = true;\n this.searchSuggestRef?.ResetHighlight();\n this.cdr.detectChanges();\n }\n\n private closeSuggest(): void {\n this.IsSuggestOpen = false;\n this.searchSuggestRef?.ResetHighlight();\n this.cdr.detectChanges();\n }\n\n private subscribeToRecentSearches(): void {\n this.searchService.RecentSearches$\n .pipe(takeUntil(this.destroy$))\n .subscribe(recents => {\n this.RecentSearches = recents;\n this.cdr.detectChanges();\n });\n }\n\n private async executePreviewSearch(query: string): Promise<void> {\n this.IsPreviewLoading = true;\n this.cdr.detectChanges();\n\n try {\n const response = await this.searchService.PreviewSearch(query, this.MaxPreviewResults);\n // Only apply if query hasn't changed since we started\n if (this.Query === query) {\n this.PreviewResults = response.Results;\n this.PreviewTotalCount = response.TotalCount;\n }\n } catch {\n this.PreviewResults = [];\n this.PreviewTotalCount = 0;\n } finally {\n this.IsPreviewLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n private clearPreviewResults(): void {\n this.PreviewResults = [];\n this.PreviewTotalCount = 0;\n this.cdr.detectChanges();\n }\n}\n","<div class=\"search-composite-wrap\">\n <mj-search-input\n #searchInput\n [Placeholder]=\"Placeholder\"\n [Query]=\"Query\"\n [ShowShortcutHint]=\"ShowShortcutHint\"\n [DebounceMs]=\"DebounceMs\"\n (QueryChange)=\"OnQueryChange($any($event))\"\n (QuerySubmit)=\"OnQuerySubmit($any($event))\"\n (InputFocused)=\"OnInputFocused()\"\n (InputEscaped)=\"OnInputEscaped()\"\n (InputCleared)=\"OnInputCleared()\"\n ></mj-search-input>\n\n <mj-search-suggest\n #searchSuggest\n [IsOpen]=\"IsSuggestOpen\"\n [PreviewResults]=\"PreviewResults\"\n [RecentSearches]=\"RecentSearches\"\n [TotalCount]=\"PreviewTotalCount\"\n [IsLoading]=\"IsPreviewLoading\"\n [Query]=\"Query\"\n [MinQueryLength]=\"MinQueryLength\"\n [MaxPreviewResults]=\"MaxPreviewResults\"\n [ShowRecent]=\"EnableRecent\"\n (ResultSelected)=\"OnResultSelected($any($event))\"\n (RecentSelected)=\"OnRecentSelected($any($event))\"\n (SeeAllRequested)=\"OnSeeAllRequested($any($event))\"\n (ClearRecentRequested)=\"OnClearRecentRequested()\"\n ></mj-search-suggest>\n</div>\n"]}
1
+ {"version":3,"file":"search-composite.component.js","sourceRoot":"","sources":["../../src/lib/search-composite.component.ts","../../src/lib/search-composite.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Composite Component\n *\n * Drop-in widget combining SearchInputComponent + SearchSuggestComponent.\n * Handles query debouncing, preview search calls, recent searches,\n * keyboard navigation delegation, and click-outside-to-close.\n */\n\nimport {\n Component,\n ElementRef,\n EventEmitter,\n HostListener,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ViewChild,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { SearchService, RecentSearch } from './search.service';\nimport { SearchInputComponent } from './search-input.component';\nimport { SearchSuggestComponent } from './search-suggest.component';\nimport { SearchResultItem } from './search-types';\n\n@Component({\n standalone: false,\n selector: 'mj-search-composite',\n templateUrl: './search-composite.component.html',\n styleUrls: ['./search-composite.component.css']\n})\nexport class SearchCompositeComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private elementRef = inject(ElementRef);\n protected searchService = inject(SearchService);\n private destroy$ = new Subject<void>();\n\n @ViewChild('searchInput') searchInputRef!: SearchInputComponent;\n @ViewChild('searchSuggest') searchSuggestRef!: SearchSuggestComponent;\n\n // --- Configuration Inputs ---\n\n /** Placeholder text for the search input */\n @Input() Placeholder = 'Search...';\n\n /** Whether to show keyboard shortcut hint on the input */\n @Input() ShowShortcutHint = true;\n\n /** Debounce time in milliseconds for query changes */\n @Input() DebounceMs = 400;\n\n /** Minimum query length before preview results are fetched */\n @Input() MinQueryLength = 2;\n\n /** Maximum number of preview results to show in the dropdown */\n @Input() MaxPreviewResults = 8;\n\n /** Whether to enable live preview search on typing */\n @Input() EnablePreview = true;\n\n /** Whether to enable recent searches display */\n @Input() EnableRecent = true;\n\n // --- Outputs ---\n\n /** Emitted when a result is selected from the preview dropdown */\n @Output() ResultSelected = new EventEmitter<SearchResultItem>();\n\n /** Emitted when the user presses Enter or selects a recent search (full search) */\n @Output() SearchSubmitted = new EventEmitter<string>();\n\n /** Emitted when the user clicks \"See all N results\" */\n @Output() SeeAllRequested = new EventEmitter<string>();\n\n // --- Internal state ---\n\n public Query = '';\n public IsSuggestOpen = false;\n\n /** The current min relevance percent from the suggest dropdown filter */\n public get MinRelevancePercent(): number {\n return this.searchSuggestRef?.MinRelevancePercent ?? 0;\n }\n public PreviewResults: SearchResultItem[] = [];\n public RecentSearches: RecentSearch[] = [];\n public PreviewTotalCount = 0;\n public IsPreviewLoading = false;\n private previewSearchVersion = 0;\n\n ngOnInit(): void {\n this.subscribeToRecentSearches();\n this.searchService.LoadRecentSearches(); // fire-and-forget — loads from UserInfoEngine\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // --- Click outside to close ---\n\n @HostListener('document:mousedown', ['$event'])\n OnDocumentMousedown(event: MouseEvent): void {\n const target = event.target as Node | null;\n if (target && !this.elementRef.nativeElement.contains(target)) {\n this.closeSuggest();\n }\n }\n\n // --- Keyboard navigation delegation ---\n\n @HostListener('keydown', ['$event'])\n OnHostKeydown(event: KeyboardEvent): void {\n if (!this.IsSuggestOpen) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.searchSuggestRef?.NavigateDown();\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.searchSuggestRef?.NavigateUp();\n break;\n case 'Enter':\n if (this.searchSuggestRef?.HighlightedIndex >= 0) {\n event.preventDefault();\n this.searchSuggestRef.SelectHighlighted();\n }\n break;\n }\n }\n\n // --- Event handlers from child components ---\n\n /** Handle debounced query changes from the input */\n public OnQueryChange(query: string): void {\n this.Query = query;\n\n if (query.length >= this.MinQueryLength && this.EnablePreview) {\n this.executePreviewSearch(query);\n } else {\n this.clearPreviewResults();\n }\n\n this.openSuggest();\n }\n\n /** Handle Enter press in the input */\n public OnQuerySubmit(query: string): void {\n // If a suggestion is highlighted, select it instead of searching\n if (this.IsSuggestOpen && this.searchSuggestRef && this.searchSuggestRef.HighlightedIndex >= 0) {\n this.searchSuggestRef.SelectHighlighted();\n return;\n }\n\n if (query.trim().length > 0) {\n this.SearchSubmitted.emit(query.trim());\n this.closeSuggest();\n }\n }\n\n /** Handle input focus */\n public OnInputFocused(): void {\n this.openSuggest();\n }\n\n /** Handle Escape press in the input */\n public OnInputEscaped(): void {\n if (this.IsSuggestOpen) {\n this.closeSuggest();\n }\n }\n\n /** Handle input cleared */\n public OnInputCleared(): void {\n this.Query = '';\n this.clearPreviewResults();\n this.openSuggest();\n }\n\n /** Handle result selection from suggest dropdown */\n public OnResultSelected(result: SearchResultItem): void {\n this.ResultSelected.emit(result);\n this.closeSuggest();\n }\n\n /** Handle recent search selection */\n public OnRecentSelected(query: string): void {\n this.Query = query;\n this.SearchSubmitted.emit(query);\n this.closeSuggest();\n }\n\n /** Handle \"See all\" click */\n public OnSeeAllRequested(query: string): void {\n this.SeeAllRequested.emit(query);\n this.closeSuggest();\n }\n\n /** Handle \"Clear\" recent searches */\n public OnClearRecentRequested(): void {\n this.searchService.ClearRecentSearches();\n }\n\n // --- Private ---\n\n private openSuggest(): void {\n this.IsSuggestOpen = true;\n this.searchSuggestRef?.ResetHighlight();\n this.cdr.detectChanges();\n }\n\n private closeSuggest(): void {\n this.IsSuggestOpen = false;\n this.searchSuggestRef?.ResetHighlight();\n this.cdr.detectChanges();\n }\n\n private subscribeToRecentSearches(): void {\n this.searchService.RecentSearches$\n .pipe(takeUntil(this.destroy$))\n .subscribe(recents => {\n this.RecentSearches = recents;\n this.cdr.detectChanges();\n });\n }\n\n private async executePreviewSearch(query: string): Promise<void> {\n const version = ++this.previewSearchVersion;\n this.IsPreviewLoading = true;\n this.cdr.detectChanges();\n\n try {\n const response = await this.searchService.PreviewSearch(query, this.MaxPreviewResults);\n // Only apply if this is still the latest request and query hasn't changed\n if (version === this.previewSearchVersion && this.Query === query) {\n this.PreviewResults = response.Results;\n this.PreviewTotalCount = response.TotalCount;\n }\n } catch {\n if (version === this.previewSearchVersion) {\n this.PreviewResults = [];\n this.PreviewTotalCount = 0;\n }\n } finally {\n if (version === this.previewSearchVersion) {\n this.IsPreviewLoading = false;\n this.cdr.detectChanges();\n }\n }\n }\n\n private clearPreviewResults(): void {\n this.PreviewResults = [];\n this.PreviewTotalCount = 0;\n this.cdr.detectChanges();\n }\n}\n","<div class=\"search-composite-wrap\">\n <mj-search-input\n #searchInput\n [Placeholder]=\"Placeholder\"\n [Query]=\"Query\"\n [ShowShortcutHint]=\"ShowShortcutHint\"\n [DebounceMs]=\"DebounceMs\"\n (QueryChange)=\"OnQueryChange($any($event))\"\n (QuerySubmit)=\"OnQuerySubmit($any($event))\"\n (InputFocused)=\"OnInputFocused()\"\n (InputEscaped)=\"OnInputEscaped()\"\n (InputCleared)=\"OnInputCleared()\"\n ></mj-search-input>\n\n <mj-search-suggest\n #searchSuggest\n [IsOpen]=\"IsSuggestOpen\"\n [PreviewResults]=\"PreviewResults\"\n [RecentSearches]=\"RecentSearches\"\n [TotalCount]=\"PreviewTotalCount\"\n [IsLoading]=\"IsPreviewLoading\"\n [Query]=\"Query\"\n [MinQueryLength]=\"MinQueryLength\"\n [MaxPreviewResults]=\"MaxPreviewResults\"\n [ShowRecent]=\"EnableRecent\"\n (ResultSelected)=\"OnResultSelected($any($event))\"\n (RecentSelected)=\"OnRecentSelected($any($event))\"\n (SeeAllRequested)=\"OnSeeAllRequested($any($event))\"\n (ClearRecentRequested)=\"OnClearRecentRequested()\"\n ></mj-search-suggest>\n</div>\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"search-input.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-input.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAEH,UAAU,EACV,YAAY,EAEZ,SAAS,EACT,MAAM,EAKT,MAAM,eAAe,CAAC;;AAIvB,qBAMa,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAC1D,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,WAAW,CAAyB;IAEtB,QAAQ,EAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAI9D,0CAA0C;IACjC,WAAW,SAAe;IAEnC,6DAA6D;IAC7D,OAAO,CAAC,MAAM,CAAM;IAEpB,IACI,KAAK,CAAC,KAAK,EAAE,MAAM,EAKtB;IACD,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,uDAAuD;IAC9C,gBAAgB,UAAQ;IAEjC,iDAAiD;IACxC,YAAY,SAAY;IAEjC,6DAA6D;IACpD,UAAU,SAAO;IAI1B,qDAAqD;IAC3C,WAAW,uBAA8B;IAEnD,sDAAsD;IAC5C,WAAW,uBAA8B;IAEnD,4CAA4C;IAClC,YAAY,qBAA4B;IAElD,yCAAyC;IAC/B,YAAY,qBAA4B;IAElD,wDAAwD;IAC9C,YAAY,qBAA4B;IAElD,kEAAkE;IACxD,YAAY,qBAA4B;IAIlD,4CAA4C;IACrC,SAAS,UAAS;IAEzB,QAAQ,IAAI,IAAI;IAIhB,WAAW,IAAI,IAAI;IAOnB,+CAA+C;IACxC,KAAK,IAAI,IAAI;IAIpB,4CAA4C;IACrC,KAAK,IAAI,IAAI;IAWpB,gCAAgC;IACzB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKnC,yCAAyC;IAClC,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAa5C,yBAAyB;IAClB,OAAO,IAAI,IAAI;IAMtB,mEAAmE;IAC5D,OAAO,IAAI,IAAI;IAMtB,wBAAwB;IACjB,MAAM,IAAI,IAAI;IAQrB,OAAO,CAAC,aAAa;yCAnIZ,oBAAoB;2CAApB,oBAAoB;CA6IhC"}
1
+ {"version":3,"file":"search-input.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-input.component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAEH,UAAU,EACV,YAAY,EAEZ,SAAS,EACT,MAAM,EAKT,MAAM,eAAe,CAAC;;AAIvB,qBAMa,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAC1D,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,WAAW,CAAyB;IAEtB,QAAQ,EAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAI9D,0CAA0C;IACjC,WAAW,SAAe;IAEnC,6DAA6D;IAC7D,OAAO,CAAC,MAAM,CAAM;IAEpB,IACI,KAAK,CAAC,KAAK,EAAE,MAAM,EAKtB;IACD,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,uDAAuD;IAC9C,gBAAgB,UAAQ;IAEjC,iDAAiD;IACxC,YAAY,SAAY;IAEjC,6DAA6D;IACpD,UAAU,SAAO;IAI1B,qDAAqD;IAC3C,WAAW,uBAA8B;IAEnD,sDAAsD;IAC5C,WAAW,uBAA8B;IAEnD,4CAA4C;IAClC,YAAY,qBAA4B;IAElD,yCAAyC;IAC/B,YAAY,qBAA4B;IAElD,wDAAwD;IAC9C,YAAY,qBAA4B;IAElD,kEAAkE;IACxD,YAAY,qBAA4B;IAIlD,4CAA4C;IACrC,SAAS,UAAS;IAEzB,QAAQ,IAAI,IAAI;IAIhB,WAAW,IAAI,IAAI;IAOnB,+CAA+C;IACxC,KAAK,IAAI,IAAI;IAIpB,4CAA4C;IACrC,KAAK,IAAI,IAAI;IAWpB,gCAAgC;IACzB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKnC,yCAAyC;IAClC,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAa5C,yBAAyB;IAClB,OAAO,IAAI,IAAI;IAMtB,mEAAmE;IAC5D,OAAO,IAAI,IAAI;IAMtB,wBAAwB;IACjB,MAAM,IAAI,IAAI;IAQrB,OAAO,CAAC,aAAa;yCAnIZ,oBAAoB;2CAApB,oBAAoB;CA8IhC"}
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { Component, EventEmitter, Input, Output, ViewChild, ChangeDetectorRef, inject } from '@angular/core';
9
9
  import { Subject } from 'rxjs';
10
- import { debounceTime, takeUntil } from 'rxjs/operators';
10
+ import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
11
11
  import * as i0 from "@angular/core";
12
12
  const _c0 = ["inputEl"];
13
13
  function SearchInputComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
@@ -50,7 +50,7 @@ export class SearchInputComponent {
50
50
  /** Text to display in the shortcut hint badge */
51
51
  ShortcutHint = 'Ctrl+K';
52
52
  /** Debounce time in milliseconds before QueryChange emits */
53
- DebounceMs = 200;
53
+ DebounceMs = 400;
54
54
  // --- Outputs ---
55
55
  /** Emitted after debounce when query text changes */
56
56
  QueryChange = new EventEmitter();
@@ -128,7 +128,7 @@ export class SearchInputComponent {
128
128
  // --- Private ---
129
129
  setupDebounce() {
130
130
  this.queryInput$
131
- .pipe(debounceTime(this.DebounceMs), takeUntil(this.destroy$))
131
+ .pipe(debounceTime(this.DebounceMs), distinctUntilChanged(), takeUntil(this.destroy$))
132
132
  .subscribe(value => {
133
133
  this.QueryChange.emit(value);
134
134
  });
@@ -1 +1 @@
1
- {"version":3,"file":"search-input.component.js","sourceRoot":"","sources":["../../src/lib/search-input.component.ts","../../src/lib/search-input.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Input Component\n *\n * A reusable search text input for navbar/hero placement.\n * Features debounced query emission, keyboard shortcut hint,\n * clear button, and focus management.\n */\n\nimport {\n Component,\n ElementRef,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ViewChild,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\n\n@Component({\n standalone: false,\n selector: 'mj-search-input',\n templateUrl: './search-input.component.html',\n styleUrls: ['./search-input.component.css']\n})\nexport class SearchInputComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private destroy$ = new Subject<void>();\n private queryInput$ = new Subject<string>();\n\n @ViewChild('inputEl') inputRef!: ElementRef<HTMLInputElement>;\n\n // --- Configuration Inputs ---\n\n /** Placeholder text shown in the input */\n @Input() Placeholder = 'Search...';\n\n /** Current query value (two-way bindable via QueryChange) */\n private _Query = '';\n\n @Input()\n set Query(value: string) {\n if (value !== this._Query) {\n this._Query = value;\n this.cdr.detectChanges();\n }\n }\n get Query(): string {\n return this._Query;\n }\n\n /** Whether to show the keyboard shortcut hint badge */\n @Input() ShowShortcutHint = true;\n\n /** Text to display in the shortcut hint badge */\n @Input() ShortcutHint = 'Ctrl+K';\n\n /** Debounce time in milliseconds before QueryChange emits */\n @Input() DebounceMs = 200;\n\n // --- Outputs ---\n\n /** Emitted after debounce when query text changes */\n @Output() QueryChange = new EventEmitter<string>();\n\n /** Emitted immediately when the user presses Enter */\n @Output() QuerySubmit = new EventEmitter<string>();\n\n /** Emitted when the input receives focus */\n @Output() InputFocused = new EventEmitter<void>();\n\n /** Emitted when the input loses focus */\n @Output() InputBlurred = new EventEmitter<void>();\n\n /** Emitted when the user presses Escape in the input */\n @Output() InputEscaped = new EventEmitter<void>();\n\n /** Emitted when the user clears the input via the clear button */\n @Output() InputCleared = new EventEmitter<void>();\n\n // --- Internal state ---\n\n /** Whether the input currently has focus */\n public IsFocused = false;\n\n ngOnInit(): void {\n this.setupDebounce();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // --- Public Methods ---\n\n /** Programmatically focus the input element */\n public Focus(): void {\n this.inputRef?.nativeElement?.focus();\n }\n\n /** Clear the query and emit InputCleared */\n public Clear(): void {\n this._Query = '';\n this.queryInput$.next('');\n this.QueryChange.emit('');\n this.InputCleared.emit();\n this.Focus();\n this.cdr.detectChanges();\n }\n\n // --- Template event handlers ---\n\n /** Handle native input event */\n public OnInput(value: string): void {\n this._Query = value;\n this.queryInput$.next(value);\n }\n\n /** Handle keydown events on the input */\n public OnKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Enter':\n event.preventDefault();\n this.QuerySubmit.emit(this._Query);\n break;\n case 'Escape':\n event.preventDefault();\n this.InputEscaped.emit();\n break;\n }\n }\n\n /** Handle focus event */\n public OnFocus(): void {\n this.IsFocused = true;\n this.InputFocused.emit();\n this.cdr.detectChanges();\n }\n\n /** Handle click — re-opens suggest when input already has focus */\n public OnClick(): void {\n if (this.IsFocused) {\n this.InputFocused.emit();\n }\n }\n\n /** Handle blur event */\n public OnBlur(): void {\n this.IsFocused = false;\n this.InputBlurred.emit();\n this.cdr.detectChanges();\n }\n\n // --- Private ---\n\n private setupDebounce(): void {\n this.queryInput$\n .pipe(\n debounceTime(this.DebounceMs),\n takeUntil(this.destroy$)\n )\n .subscribe(value => {\n this.QueryChange.emit(value);\n });\n }\n}\n","<div class=\"search-input-container\" [class.search-input-focused]=\"IsFocused\">\n <i class=\"fa-solid fa-magnifying-glass search-input-icon\"></i>\n <input\n #inputEl\n type=\"text\"\n class=\"mj-input search-input-field\"\n [placeholder]=\"Placeholder\"\n [value]=\"Query\"\n (input)=\"OnInput($any($event.target).value)\"\n (keydown)=\"OnKeydown($event)\"\n (focus)=\"OnFocus()\"\n (blur)=\"OnBlur()\"\n (click)=\"OnClick()\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (Query.length > 0) {\n <button\n class=\"search-input-clear\"\n (click)=\"Clear()\"\n title=\"Clear search\"\n type=\"button\"\n >\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n @if (ShowShortcutHint && !IsFocused && Query.length === 0) {\n <kbd class=\"search-input-shortcut\">{{ ShortcutHint }}</kbd>\n }\n</div>\n"]}
1
+ {"version":3,"file":"search-input.component.js","sourceRoot":"","sources":["../../src/lib/search-input.component.ts","../../src/lib/search-input.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Input Component\n *\n * A reusable search text input for navbar/hero placement.\n * Features debounced query emission, keyboard shortcut hint,\n * clear button, and focus management.\n */\n\nimport {\n Component,\n ElementRef,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ViewChild,\n ChangeDetectorRef,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';\n\n@Component({\n standalone: false,\n selector: 'mj-search-input',\n templateUrl: './search-input.component.html',\n styleUrls: ['./search-input.component.css']\n})\nexport class SearchInputComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private destroy$ = new Subject<void>();\n private queryInput$ = new Subject<string>();\n\n @ViewChild('inputEl') inputRef!: ElementRef<HTMLInputElement>;\n\n // --- Configuration Inputs ---\n\n /** Placeholder text shown in the input */\n @Input() Placeholder = 'Search...';\n\n /** Current query value (two-way bindable via QueryChange) */\n private _Query = '';\n\n @Input()\n set Query(value: string) {\n if (value !== this._Query) {\n this._Query = value;\n this.cdr.detectChanges();\n }\n }\n get Query(): string {\n return this._Query;\n }\n\n /** Whether to show the keyboard shortcut hint badge */\n @Input() ShowShortcutHint = true;\n\n /** Text to display in the shortcut hint badge */\n @Input() ShortcutHint = 'Ctrl+K';\n\n /** Debounce time in milliseconds before QueryChange emits */\n @Input() DebounceMs = 400;\n\n // --- Outputs ---\n\n /** Emitted after debounce when query text changes */\n @Output() QueryChange = new EventEmitter<string>();\n\n /** Emitted immediately when the user presses Enter */\n @Output() QuerySubmit = new EventEmitter<string>();\n\n /** Emitted when the input receives focus */\n @Output() InputFocused = new EventEmitter<void>();\n\n /** Emitted when the input loses focus */\n @Output() InputBlurred = new EventEmitter<void>();\n\n /** Emitted when the user presses Escape in the input */\n @Output() InputEscaped = new EventEmitter<void>();\n\n /** Emitted when the user clears the input via the clear button */\n @Output() InputCleared = new EventEmitter<void>();\n\n // --- Internal state ---\n\n /** Whether the input currently has focus */\n public IsFocused = false;\n\n ngOnInit(): void {\n this.setupDebounce();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // --- Public Methods ---\n\n /** Programmatically focus the input element */\n public Focus(): void {\n this.inputRef?.nativeElement?.focus();\n }\n\n /** Clear the query and emit InputCleared */\n public Clear(): void {\n this._Query = '';\n this.queryInput$.next('');\n this.QueryChange.emit('');\n this.InputCleared.emit();\n this.Focus();\n this.cdr.detectChanges();\n }\n\n // --- Template event handlers ---\n\n /** Handle native input event */\n public OnInput(value: string): void {\n this._Query = value;\n this.queryInput$.next(value);\n }\n\n /** Handle keydown events on the input */\n public OnKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Enter':\n event.preventDefault();\n this.QuerySubmit.emit(this._Query);\n break;\n case 'Escape':\n event.preventDefault();\n this.InputEscaped.emit();\n break;\n }\n }\n\n /** Handle focus event */\n public OnFocus(): void {\n this.IsFocused = true;\n this.InputFocused.emit();\n this.cdr.detectChanges();\n }\n\n /** Handle click — re-opens suggest when input already has focus */\n public OnClick(): void {\n if (this.IsFocused) {\n this.InputFocused.emit();\n }\n }\n\n /** Handle blur event */\n public OnBlur(): void {\n this.IsFocused = false;\n this.InputBlurred.emit();\n this.cdr.detectChanges();\n }\n\n // --- Private ---\n\n private setupDebounce(): void {\n this.queryInput$\n .pipe(\n debounceTime(this.DebounceMs),\n distinctUntilChanged(),\n takeUntil(this.destroy$)\n )\n .subscribe(value => {\n this.QueryChange.emit(value);\n });\n }\n}\n","<div class=\"search-input-container\" [class.search-input-focused]=\"IsFocused\">\n <i class=\"fa-solid fa-magnifying-glass search-input-icon\"></i>\n <input\n #inputEl\n type=\"text\"\n class=\"mj-input search-input-field\"\n [placeholder]=\"Placeholder\"\n [value]=\"Query\"\n (input)=\"OnInput($any($event.target).value)\"\n (keydown)=\"OnKeydown($event)\"\n (focus)=\"OnFocus()\"\n (blur)=\"OnBlur()\"\n (click)=\"OnClick()\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (Query.length > 0) {\n <button\n class=\"search-input-clear\"\n (click)=\"Clear()\"\n title=\"Clear search\"\n type=\"button\"\n >\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n @if (ShowShortcutHint && !IsFocused && Query.length === 0) {\n <kbd class=\"search-input-shortcut\">{{ ShortcutHint }}</kbd>\n }\n</div>\n"]}
@@ -51,6 +51,7 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
51
51
  ElapsedMs: number;
52
52
  HighlightedIndex: number;
53
53
  HasSearched: boolean;
54
+ private searchVersion;
54
55
  /** All results flattened for keyboard navigation */
55
56
  get FlatResults(): SearchResultItem[];
56
57
  ngOnInit(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"search-overlay.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-overlay.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAEH,YAAY,EAGZ,SAAS,EACT,MAAM,EAGN,UAAU,EAGb,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EAEZ,yBAAyB,EACzB,uBAAuB,EACvB,mBAAmB,EACtB,MAAM,gBAAgB,CAAC;;AAExB,qBAMa,sBAAuB,YAAW,MAAM,EAAE,SAAS;IAC5D,OAAO,CAAC,GAAG,CAA6B;IACxC,SAAS,CAAC,aAAa,gBAAyB;IAChD,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,YAAY,CAAyB;IAEnB,cAAc,EAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAIxE,4CAA4C;IACnC,WAAW,SAAyC;IAE7D,yCAAyC;IAChC,UAAU,SAAM;IAEzB,+CAA+C;IAC/C,OAAO,CAAC,OAAO,CAAS;IAExB,IACI,MAAM,CAAC,KAAK,EAAE,OAAO,EASxB;IACD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,8CAA8C;IACrC,UAAU,SAAO;IAE1B,sCAAsC;IAC7B,cAAc,EAAE,CAAC,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC,EAAE,CAAoC;IAEjG,oCAAoC;IAC3B,WAAW,UAAQ;IAE5B,oCAAoC;IAC3B,YAAY,SAAyB;IAE9C,oCAAoC;IAC3B,YAAY,UAAQ;IAInB,YAAY,wBAA+B;IAC3C,cAAc,0CAAiD;IAC/D,aAAa,wCAA+C;IAC5D,cAAc,oCAA2C;IACzD,eAAe,uBAA8B;IAIhD,KAAK,SAAM;IACX,WAAW,UAAS;IACpB,YAAY,EAAE,iBAAiB,EAAE,CAAM;IACvC,UAAU,EAAE,gBAAgB,EAAE,CAAM;IACpC,OAAO,EAAE,YAAY,EAAE,CAAM;IAC7B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAM;IAC7C,UAAU,SAAK;IACf,SAAS,SAAK;IACd,gBAAgB,SAAM;IACtB,WAAW,UAAS;IAE3B,oDAAoD;IACpD,IAAW,WAAW,IAAI,gBAAgB,EAAE,CAE3C;IAED,QAAQ,IAAI,IAAI;IAKhB,WAAW,IAAI,IAAI;IAQnB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAW/C,qCAAqC;IAC9B,aAAa,IAAI,IAAI;IAK5B,uBAAuB;IAChB,IAAI,IAAI,IAAI;IAOnB,wBAAwB;IACjB,KAAK,IAAI,IAAI;IAOpB,iCAAiC;IAC1B,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKxC,+BAA+B;IACxB,aAAa,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IAQvE,8CAA8C;IACvC,iBAAiB,IAAI,IAAI;IAUhC,kCAAkC;IAC3B,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAa5D,+BAA+B;IACxB,eAAe,IAAI,IAAI;IAK9B,oCAAoC;IAC7B,eAAe,IAAI,IAAI;IAK9B,4CAA4C;IACrC,eAAe,IAAI,IAAI;IAI9B,yCAAyC;IAClC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAI/D,6CAA6C;IACtC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIzC,kCAAkC;IAC3B,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAS5C,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,sBAAsB;YAShB,aAAa;IAiC3B,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,eAAe;IAIvB,yDAAyD;IAClD,gBAAgB,IAAI,OAAO;IAIlC,0DAA0D;IACnD,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO;IAK7D,6DAA6D;IACtD,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM;yCAlU5C,sBAAsB;2CAAtB,sBAAsB;CAqUlC"}
1
+ {"version":3,"file":"search-overlay.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-overlay.component.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import { Component, EventEmitter, HostListener, Input, Output, ChangeDetectorRef, ViewChild, inject } from '@angular/core';
12
12
  import { Subject } from 'rxjs';
13
- import { debounceTime, takeUntil } from 'rxjs/operators';
13
+ import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
14
14
  import { SearchService } from './search.service';
15
15
  import * as i0 from "@angular/core";
16
16
  const _c0 = ["searchInput"];
@@ -327,7 +327,7 @@ export class SearchOverlayComponent {
327
327
  return this._IsOpen;
328
328
  }
329
329
  /** Debounce time in ms before search fires */
330
- DebounceMs = 250;
330
+ DebounceMs = 400;
331
331
  /** Which search sources to include */
332
332
  IncludeSources = ['vector', 'fulltext', 'entity'];
333
333
  /** Whether to show filter facets */
@@ -353,6 +353,7 @@ export class SearchOverlayComponent {
353
353
  ElapsedMs = 0;
354
354
  HighlightedIndex = -1;
355
355
  HasSearched = false;
356
+ searchVersion = 0;
356
357
  /** All results flattened for keyboard navigation */
357
358
  get FlatResults() {
358
359
  return this.AllResults;
@@ -500,7 +501,7 @@ export class SearchOverlayComponent {
500
501
  }
501
502
  setupSearchDebounce() {
502
503
  this.searchInput$
503
- .pipe(debounceTime(this.DebounceMs), takeUntil(this.destroy$))
504
+ .pipe(debounceTime(this.DebounceMs), distinctUntilChanged(), takeUntil(this.destroy$))
504
505
  .subscribe(() => this.executeSearch());
505
506
  }
506
507
  subscribeToSearchState() {
@@ -517,6 +518,7 @@ export class SearchOverlayComponent {
517
518
  this.clearResults();
518
519
  return;
519
520
  }
521
+ const version = ++this.searchVersion;
520
522
  const request = {
521
523
  Query: query,
522
524
  MaxResults: this.MaxResults,
@@ -524,6 +526,10 @@ export class SearchOverlayComponent {
524
526
  IncludeSources: this.IncludeSources,
525
527
  };
526
528
  const response = await this.searchService.ExecuteSearch(request);
529
+ // Discard results if a newer search was triggered while this one was in-flight
530
+ if (version !== this.searchVersion) {
531
+ return;
532
+ }
527
533
  this.AllResults = response.Results;
528
534
  this.ResultGroups = response.Groups;
529
535
  this.Filters = response.Filters;
@@ -1 +1 @@
1
- {"version":3,"file":"search-overlay.component.js","sourceRoot":"","sources":["../../src/lib/search-overlay.component.ts","../../src/lib/search-overlay.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Overlay Component\n *\n * A floating search overlay inspired by command palette / Spotlight style.\n * Triggered by Cmd+K (Mac) or Ctrl+K (Windows), appears as a centered\n * floating panel with backdrop blur, search input, and grouped results.\n *\n * Supports keyboard navigation (up/down/enter/escape), filter facets,\n * and responsive mobile layout.\n */\n\nimport {\n Component,\n EventEmitter,\n HostListener,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n ElementRef,\n ViewChild,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\nimport { SearchService } from './search.service';\nimport {\n SearchResultItem,\n SearchResultGroup,\n SearchFilter,\n SearchRequest,\n SearchResultSelectedEvent,\n SearchFilterChangeEvent,\n SearchExecutedEvent,\n} from './search-types';\n\n@Component({\n standalone: false,\n selector: 'mj-search-overlay',\n templateUrl: './search-overlay.component.html',\n styleUrls: ['./search-overlay.component.css']\n})\nexport class SearchOverlayComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n protected searchService = inject(SearchService);\n private destroy$ = new Subject<void>();\n private searchInput$ = new Subject<string>();\n\n @ViewChild('searchInput') searchInputRef!: ElementRef<HTMLInputElement>;\n\n // --- Configuration Inputs ---\n\n /** Placeholder text for the search input */\n @Input() Placeholder = 'Search across all your knowledge...';\n\n /** Maximum number of results to fetch */\n @Input() MaxResults = 25;\n\n /** Whether the overlay is currently visible */\n private _IsOpen = false;\n\n @Input()\n set IsOpen(value: boolean) {\n const prev = this._IsOpen;\n this._IsOpen = value;\n if (value && !prev) {\n this.onOverlayOpened();\n }\n if (!value && prev) {\n this.onOverlayClosed();\n }\n }\n get IsOpen(): boolean {\n return this._IsOpen;\n }\n\n /** Debounce time in ms before search fires */\n @Input() DebounceMs = 250;\n\n /** Which search sources to include */\n @Input() IncludeSources: ('vector' | 'fulltext' | 'entity')[] = ['vector', 'fulltext', 'entity'];\n\n /** Whether to show filter facets */\n @Input() ShowFilters = true;\n\n /** Text for the agent CTA button */\n @Input() AgentCtaText = 'Ask Knowledge Agent';\n\n /** Whether to show the agent CTA */\n @Input() ShowAgentCta = true;\n\n // --- Outputs ---\n\n @Output() IsOpenChange = new EventEmitter<boolean>();\n @Output() ResultSelected = new EventEmitter<SearchResultSelectedEvent>();\n @Output() FilterChanged = new EventEmitter<SearchFilterChangeEvent>();\n @Output() SearchExecuted = new EventEmitter<SearchExecutedEvent>();\n @Output() AgentCtaClicked = new EventEmitter<string>();\n\n // --- Component State ---\n\n public Query = '';\n public IsSearching = false;\n public ResultGroups: SearchResultGroup[] = [];\n public AllResults: SearchResultItem[] = [];\n public Filters: SearchFilter[] = [];\n public ActiveFilters: Record<string, string[]> = {};\n public TotalCount = 0;\n public ElapsedMs = 0;\n public HighlightedIndex = -1;\n public HasSearched = false;\n\n /** All results flattened for keyboard navigation */\n public get FlatResults(): SearchResultItem[] {\n return this.AllResults;\n }\n\n ngOnInit(): void {\n this.setupSearchDebounce();\n this.subscribeToSearchState();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // --- Keyboard shortcuts ---\n\n @HostListener('document:keydown', ['$event'])\n HandleGlobalKeydown(event: KeyboardEvent): void {\n if (this.isToggleShortcut(event)) {\n event.preventDefault();\n this.ToggleOverlay();\n return;\n }\n if (this._IsOpen) {\n this.handleOverlayKeydown(event);\n }\n }\n\n /** Toggle the overlay open/closed */\n public ToggleOverlay(): void {\n this.IsOpen = !this._IsOpen;\n this.IsOpenChange.emit(this._IsOpen);\n }\n\n /** Open the overlay */\n public Open(): void {\n if (!this._IsOpen) {\n this.IsOpen = true;\n this.IsOpenChange.emit(true);\n }\n }\n\n /** Close the overlay */\n public Close(): void {\n if (this._IsOpen) {\n this.IsOpen = false;\n this.IsOpenChange.emit(false);\n }\n }\n\n /** Handle query input changes */\n public OnQueryInput(value: string): void {\n this.Query = value;\n this.searchInput$.next(value);\n }\n\n /** Handle clicking a result */\n public OnResultClick(result: SearchResultItem, event: MouseEvent): void {\n this.ResultSelected.emit({\n Result: result,\n OpenInNewTab: event.metaKey || event.ctrlKey\n });\n this.Close();\n }\n\n /** Handle selecting the highlighted result */\n public SelectHighlighted(): void {\n if (this.HighlightedIndex >= 0 && this.HighlightedIndex < this.FlatResults.length) {\n this.ResultSelected.emit({\n Result: this.FlatResults[this.HighlightedIndex],\n OpenInNewTab: false\n });\n this.Close();\n }\n }\n\n /** Handle filter option toggle */\n public OnFilterToggle(category: string, value: string): void {\n const current = this.ActiveFilters[category] ?? [];\n const index = current.indexOf(value);\n if (index >= 0) {\n current.splice(index, 1);\n } else {\n current.push(value);\n }\n this.ActiveFilters[category] = current;\n this.FilterChanged.emit({ Category: category, SelectedValues: current });\n this.executeSearch();\n }\n\n /** Clear all active filters */\n public ClearAllFilters(): void {\n this.ActiveFilters = {};\n this.executeSearch();\n }\n\n /** Handle clicking the agent CTA */\n public OnAgentCtaClick(): void {\n this.AgentCtaClicked.emit(this.Query);\n this.Close();\n }\n\n /** Handle clicking the backdrop to close */\n public OnBackdropClick(): void {\n this.Close();\n }\n\n /** Check if a filter option is active */\n public IsFilterActive(category: string, value: string): boolean {\n return (this.ActiveFilters[category] ?? []).includes(value);\n }\n\n /** Get a score display value (percentage) */\n public FormatScore(score: number): string {\n return `${Math.round(score * 100)}%`;\n }\n\n /** Format elapsed time display */\n public FormatElapsedTime(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n return `${(ms / 1000).toFixed(1)}s`;\n }\n\n // --- Private Methods ---\n\n private isToggleShortcut(event: KeyboardEvent): boolean {\n return (event.metaKey || event.ctrlKey) && event.key === 'k';\n }\n\n private handleOverlayKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Escape':\n event.preventDefault();\n this.Close();\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.moveHighlight(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveHighlight(-1);\n break;\n case 'Enter':\n event.preventDefault();\n this.SelectHighlighted();\n break;\n }\n }\n\n private moveHighlight(direction: number): void {\n const maxIndex = this.FlatResults.length - 1;\n if (maxIndex < 0) return;\n\n this.HighlightedIndex += direction;\n if (this.HighlightedIndex < 0) {\n this.HighlightedIndex = maxIndex;\n } else if (this.HighlightedIndex > maxIndex) {\n this.HighlightedIndex = 0;\n }\n this.cdr.detectChanges();\n }\n\n private setupSearchDebounce(): void {\n this.searchInput$\n .pipe(\n debounceTime(this.DebounceMs),\n takeUntil(this.destroy$)\n )\n .subscribe(() => this.executeSearch());\n }\n\n private subscribeToSearchState(): void {\n this.searchService.IsSearching$\n .pipe(takeUntil(this.destroy$))\n .subscribe(val => {\n this.IsSearching = val;\n this.cdr.detectChanges();\n });\n }\n\n private async executeSearch(): Promise<void> {\n const query = this.Query.trim();\n if (!query) {\n this.clearResults();\n return;\n }\n\n const request: SearchRequest = {\n Query: query,\n MaxResults: this.MaxResults,\n ActiveFilters: this.ActiveFilters,\n IncludeSources: this.IncludeSources,\n };\n\n const response = await this.searchService.ExecuteSearch(request);\n this.AllResults = response.Results;\n this.ResultGroups = response.Groups;\n this.Filters = response.Filters;\n this.TotalCount = response.TotalCount;\n this.ElapsedMs = response.ElapsedMs;\n this.HasSearched = true;\n this.HighlightedIndex = response.Results.length > 0 ? 0 : -1;\n\n this.SearchExecuted.emit({\n Query: query,\n Filters: this.ActiveFilters,\n ResultCount: response.TotalCount,\n ElapsedMs: response.ElapsedMs,\n });\n\n this.cdr.detectChanges();\n }\n\n private clearResults(): void {\n this.AllResults = [];\n this.ResultGroups = [];\n this.Filters = [];\n this.TotalCount = 0;\n this.ElapsedMs = 0;\n this.HasSearched = false;\n this.HighlightedIndex = -1;\n this.cdr.detectChanges();\n }\n\n private onOverlayOpened(): void {\n // Focus input after view updates\n Promise.resolve().then(() => {\n this.searchInputRef?.nativeElement?.focus();\n this.cdr.detectChanges();\n });\n }\n\n private onOverlayClosed(): void {\n this.HighlightedIndex = -1;\n }\n\n /** Check if any filters are active (used by template) */\n public hasActiveFilters(): boolean {\n return Object.values(this.ActiveFilters).some(v => v.length > 0);\n }\n\n /** Check if a result is currently keyboard-highlighted */\n public isResultHighlighted(result: SearchResultItem): boolean {\n const flatIndex = this.getFlatIndex(result);\n return flatIndex === this.HighlightedIndex;\n }\n\n /** Get the flat index of a result for keyboard navigation */\n public getFlatIndex(result: SearchResultItem): number {\n return this.FlatResults.indexOf(result);\n }\n}\n","@if (IsOpen) {\n <!-- Backdrop -->\n <div class=\"search-backdrop\" (click)=\"OnBackdropClick()\"></div>\n\n <!-- Spotlight container -->\n <div class=\"search-spotlight\" (click)=\"$event.stopPropagation()\">\n <!-- Search input area -->\n <div class=\"search-input-wrap\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\"></i>\n <input\n #searchInput\n type=\"text\"\n class=\"search-input\"\n [placeholder]=\"Placeholder\"\n [value]=\"Query\"\n (input)=\"OnQueryInput($any($event.target).value)\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (IsSearching) {\n <div class=\"search-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n </div>\n }\n <div class=\"search-shortcut-hint\">\n <kbd>ESC</kbd>\n </div>\n </div>\n\n <!-- Results area -->\n <div class=\"search-results-area\">\n @if (ShowFilters && Filters.length > 0) {\n <!-- Filter chips -->\n <div class=\"search-filter-bar\">\n @for (filter of Filters; track filter.Category) {\n @for (option of filter.Options; track option.Value) {\n <button\n class=\"filter-chip\"\n [class.filter-chip-active]=\"IsFilterActive(filter.Category, option.Value)\"\n (click)=\"OnFilterToggle(filter.Category, option.Value)\"\n >\n @if (option.Icon) {\n <i [class]=\"option.Icon\"></i>\n }\n <span>{{ option.Label }}</span>\n <span class=\"filter-chip-count\">{{ option.Count }}</span>\n </button>\n }\n }\n @if (hasActiveFilters()) {\n <button class=\"filter-clear-btn\" (click)=\"ClearAllFilters()\">\n <i class=\"fa-solid fa-times\"></i> Clear\n </button>\n }\n </div>\n }\n\n @if (HasSearched && AllResults.length === 0 && !IsSearching) {\n <!-- No results -->\n <div class=\"search-empty-state\">\n <i class=\"fa-solid fa-search search-empty-icon\"></i>\n <p class=\"search-empty-title\">No results found</p>\n <p class=\"search-empty-text\">Try different keywords or remove some filters</p>\n @if (ShowAgentCta) {\n <button class=\"agent-cta-btn\" (click)=\"OnAgentCtaClick()\">\n <i class=\"fa-solid fa-robot\"></i>\n {{ AgentCtaText }}\n </button>\n }\n </div>\n }\n\n @if (!HasSearched && !IsSearching) {\n <!-- Recent searches -->\n <div class=\"search-recent\">\n @if (searchService.RecentSearches$.value.length > 0) {\n <div class=\"search-recent-header\">\n <span class=\"search-recent-title\">Recent Searches</span>\n </div>\n @for (recent of searchService.RecentSearches$.value; track recent.Query; let i = $index) {\n @if (i < 5) {\n <div class=\"search-recent-item\" (click)=\"OnQueryInput(recent.Query)\">\n <i class=\"fa-solid fa-clock search-recent-icon\"></i>\n <span>{{ recent.Query }}</span>\n <span class=\"search-recent-count\">{{ recent.ResultCount }} results</span>\n </div>\n }\n }\n } @else {\n <div class=\"search-empty-state search-empty-state-compact\">\n <i class=\"fa-solid fa-magnifying-glass search-empty-icon\"></i>\n <p class=\"search-empty-text\">Start typing to search across all your knowledge</p>\n </div>\n }\n </div>\n }\n\n @if (AllResults.length > 0) {\n <!-- Grouped results -->\n @for (group of ResultGroups; track group.SourceType) {\n <div class=\"result-group\">\n <div class=\"result-group-header\">\n <i [class]=\"group.Icon\"></i>\n <span class=\"result-group-label\">{{ group.Label }}</span>\n <span class=\"result-group-count\">{{ group.TotalCount }}</span>\n </div>\n @for (result of group.Results; track result.ID; let ri = $index) {\n <div\n class=\"result-item\"\n [class.result-item-highlighted]=\"isResultHighlighted(result)\"\n (click)=\"OnResultClick(result, $event)\"\n (mouseenter)=\"HighlightedIndex = getFlatIndex(result)\"\n >\n <div class=\"result-item-icon\">\n <i [class]=\"result.SourceIcon\"></i>\n </div>\n <div class=\"result-item-content\">\n <div class=\"result-item-title\">{{ result.Title }}</div>\n <div class=\"result-item-snippet\">{{ result.Snippet }}</div>\n @if (result.Tags.length > 0) {\n <div class=\"result-item-tags\">\n @for (tag of result.Tags; track tag; let ti = $index) {\n @if (ti < 3) {\n <span class=\"result-tag\">{{ tag }}</span>\n }\n }\n </div>\n }\n </div>\n <div class=\"result-item-score\">\n <span class=\"score-badge\">{{ FormatScore(result.Score) }}</span>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Footer -->\n <div class=\"search-footer\">\n <span class=\"search-footer-count\">\n {{ TotalCount }} results in {{ FormatElapsedTime(ElapsedMs) }}\n </span>\n @if (ShowAgentCta) {\n <button class=\"agent-cta-btn agent-cta-btn-small\" (click)=\"OnAgentCtaClick()\">\n <i class=\"fa-solid fa-robot\"></i>\n {{ AgentCtaText }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n}\n"]}
1
+ {"version":3,"file":"search-overlay.component.js","sourceRoot":"","sources":["../../src/lib/search-overlay.component.ts","../../src/lib/search-overlay.component.html"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Search Overlay Component\n *\n * A floating search overlay inspired by command palette / Spotlight style.\n * Triggered by Cmd+K (Mac) or Ctrl+K (Windows), appears as a centered\n * floating panel with backdrop blur, search input, and grouped results.\n *\n * Supports keyboard navigation (up/down/enter/escape), filter facets,\n * and responsive mobile layout.\n */\n\nimport {\n Component,\n EventEmitter,\n HostListener,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n ElementRef,\n ViewChild,\n inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';\nimport { SearchService } from './search.service';\nimport {\n SearchResultItem,\n SearchResultGroup,\n SearchFilter,\n SearchRequest,\n SearchResultSelectedEvent,\n SearchFilterChangeEvent,\n SearchExecutedEvent,\n} from './search-types';\n\n@Component({\n standalone: false,\n selector: 'mj-search-overlay',\n templateUrl: './search-overlay.component.html',\n styleUrls: ['./search-overlay.component.css']\n})\nexport class SearchOverlayComponent implements OnInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n protected searchService = inject(SearchService);\n private destroy$ = new Subject<void>();\n private searchInput$ = new Subject<string>();\n\n @ViewChild('searchInput') searchInputRef!: ElementRef<HTMLInputElement>;\n\n // --- Configuration Inputs ---\n\n /** Placeholder text for the search input */\n @Input() Placeholder = 'Search across all your knowledge...';\n\n /** Maximum number of results to fetch */\n @Input() MaxResults = 25;\n\n /** Whether the overlay is currently visible */\n private _IsOpen = false;\n\n @Input()\n set IsOpen(value: boolean) {\n const prev = this._IsOpen;\n this._IsOpen = value;\n if (value && !prev) {\n this.onOverlayOpened();\n }\n if (!value && prev) {\n this.onOverlayClosed();\n }\n }\n get IsOpen(): boolean {\n return this._IsOpen;\n }\n\n /** Debounce time in ms before search fires */\n @Input() DebounceMs = 400;\n\n /** Which search sources to include */\n @Input() IncludeSources: ('vector' | 'fulltext' | 'entity')[] = ['vector', 'fulltext', 'entity'];\n\n /** Whether to show filter facets */\n @Input() ShowFilters = true;\n\n /** Text for the agent CTA button */\n @Input() AgentCtaText = 'Ask Knowledge Agent';\n\n /** Whether to show the agent CTA */\n @Input() ShowAgentCta = true;\n\n // --- Outputs ---\n\n @Output() IsOpenChange = new EventEmitter<boolean>();\n @Output() ResultSelected = new EventEmitter<SearchResultSelectedEvent>();\n @Output() FilterChanged = new EventEmitter<SearchFilterChangeEvent>();\n @Output() SearchExecuted = new EventEmitter<SearchExecutedEvent>();\n @Output() AgentCtaClicked = new EventEmitter<string>();\n\n // --- Component State ---\n\n public Query = '';\n public IsSearching = false;\n public ResultGroups: SearchResultGroup[] = [];\n public AllResults: SearchResultItem[] = [];\n public Filters: SearchFilter[] = [];\n public ActiveFilters: Record<string, string[]> = {};\n public TotalCount = 0;\n public ElapsedMs = 0;\n public HighlightedIndex = -1;\n public HasSearched = false;\n private searchVersion = 0;\n\n /** All results flattened for keyboard navigation */\n public get FlatResults(): SearchResultItem[] {\n return this.AllResults;\n }\n\n ngOnInit(): void {\n this.setupSearchDebounce();\n this.subscribeToSearchState();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // --- Keyboard shortcuts ---\n\n @HostListener('document:keydown', ['$event'])\n HandleGlobalKeydown(event: KeyboardEvent): void {\n if (this.isToggleShortcut(event)) {\n event.preventDefault();\n this.ToggleOverlay();\n return;\n }\n if (this._IsOpen) {\n this.handleOverlayKeydown(event);\n }\n }\n\n /** Toggle the overlay open/closed */\n public ToggleOverlay(): void {\n this.IsOpen = !this._IsOpen;\n this.IsOpenChange.emit(this._IsOpen);\n }\n\n /** Open the overlay */\n public Open(): void {\n if (!this._IsOpen) {\n this.IsOpen = true;\n this.IsOpenChange.emit(true);\n }\n }\n\n /** Close the overlay */\n public Close(): void {\n if (this._IsOpen) {\n this.IsOpen = false;\n this.IsOpenChange.emit(false);\n }\n }\n\n /** Handle query input changes */\n public OnQueryInput(value: string): void {\n this.Query = value;\n this.searchInput$.next(value);\n }\n\n /** Handle clicking a result */\n public OnResultClick(result: SearchResultItem, event: MouseEvent): void {\n this.ResultSelected.emit({\n Result: result,\n OpenInNewTab: event.metaKey || event.ctrlKey\n });\n this.Close();\n }\n\n /** Handle selecting the highlighted result */\n public SelectHighlighted(): void {\n if (this.HighlightedIndex >= 0 && this.HighlightedIndex < this.FlatResults.length) {\n this.ResultSelected.emit({\n Result: this.FlatResults[this.HighlightedIndex],\n OpenInNewTab: false\n });\n this.Close();\n }\n }\n\n /** Handle filter option toggle */\n public OnFilterToggle(category: string, value: string): void {\n const current = this.ActiveFilters[category] ?? [];\n const index = current.indexOf(value);\n if (index >= 0) {\n current.splice(index, 1);\n } else {\n current.push(value);\n }\n this.ActiveFilters[category] = current;\n this.FilterChanged.emit({ Category: category, SelectedValues: current });\n this.executeSearch();\n }\n\n /** Clear all active filters */\n public ClearAllFilters(): void {\n this.ActiveFilters = {};\n this.executeSearch();\n }\n\n /** Handle clicking the agent CTA */\n public OnAgentCtaClick(): void {\n this.AgentCtaClicked.emit(this.Query);\n this.Close();\n }\n\n /** Handle clicking the backdrop to close */\n public OnBackdropClick(): void {\n this.Close();\n }\n\n /** Check if a filter option is active */\n public IsFilterActive(category: string, value: string): boolean {\n return (this.ActiveFilters[category] ?? []).includes(value);\n }\n\n /** Get a score display value (percentage) */\n public FormatScore(score: number): string {\n return `${Math.round(score * 100)}%`;\n }\n\n /** Format elapsed time display */\n public FormatElapsedTime(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n return `${(ms / 1000).toFixed(1)}s`;\n }\n\n // --- Private Methods ---\n\n private isToggleShortcut(event: KeyboardEvent): boolean {\n return (event.metaKey || event.ctrlKey) && event.key === 'k';\n }\n\n private handleOverlayKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Escape':\n event.preventDefault();\n this.Close();\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.moveHighlight(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveHighlight(-1);\n break;\n case 'Enter':\n event.preventDefault();\n this.SelectHighlighted();\n break;\n }\n }\n\n private moveHighlight(direction: number): void {\n const maxIndex = this.FlatResults.length - 1;\n if (maxIndex < 0) return;\n\n this.HighlightedIndex += direction;\n if (this.HighlightedIndex < 0) {\n this.HighlightedIndex = maxIndex;\n } else if (this.HighlightedIndex > maxIndex) {\n this.HighlightedIndex = 0;\n }\n this.cdr.detectChanges();\n }\n\n private setupSearchDebounce(): void {\n this.searchInput$\n .pipe(\n debounceTime(this.DebounceMs),\n distinctUntilChanged(),\n takeUntil(this.destroy$)\n )\n .subscribe(() => this.executeSearch());\n }\n\n private subscribeToSearchState(): void {\n this.searchService.IsSearching$\n .pipe(takeUntil(this.destroy$))\n .subscribe(val => {\n this.IsSearching = val;\n this.cdr.detectChanges();\n });\n }\n\n private async executeSearch(): Promise<void> {\n const query = this.Query.trim();\n if (!query) {\n this.clearResults();\n return;\n }\n\n const version = ++this.searchVersion;\n\n const request: SearchRequest = {\n Query: query,\n MaxResults: this.MaxResults,\n ActiveFilters: this.ActiveFilters,\n IncludeSources: this.IncludeSources,\n };\n\n const response = await this.searchService.ExecuteSearch(request);\n\n // Discard results if a newer search was triggered while this one was in-flight\n if (version !== this.searchVersion) {\n return;\n }\n\n this.AllResults = response.Results;\n this.ResultGroups = response.Groups;\n this.Filters = response.Filters;\n this.TotalCount = response.TotalCount;\n this.ElapsedMs = response.ElapsedMs;\n this.HasSearched = true;\n this.HighlightedIndex = response.Results.length > 0 ? 0 : -1;\n\n this.SearchExecuted.emit({\n Query: query,\n Filters: this.ActiveFilters,\n ResultCount: response.TotalCount,\n ElapsedMs: response.ElapsedMs,\n });\n\n this.cdr.detectChanges();\n }\n\n private clearResults(): void {\n this.AllResults = [];\n this.ResultGroups = [];\n this.Filters = [];\n this.TotalCount = 0;\n this.ElapsedMs = 0;\n this.HasSearched = false;\n this.HighlightedIndex = -1;\n this.cdr.detectChanges();\n }\n\n private onOverlayOpened(): void {\n // Focus input after view updates\n Promise.resolve().then(() => {\n this.searchInputRef?.nativeElement?.focus();\n this.cdr.detectChanges();\n });\n }\n\n private onOverlayClosed(): void {\n this.HighlightedIndex = -1;\n }\n\n /** Check if any filters are active (used by template) */\n public hasActiveFilters(): boolean {\n return Object.values(this.ActiveFilters).some(v => v.length > 0);\n }\n\n /** Check if a result is currently keyboard-highlighted */\n public isResultHighlighted(result: SearchResultItem): boolean {\n const flatIndex = this.getFlatIndex(result);\n return flatIndex === this.HighlightedIndex;\n }\n\n /** Get the flat index of a result for keyboard navigation */\n public getFlatIndex(result: SearchResultItem): number {\n return this.FlatResults.indexOf(result);\n }\n}\n","@if (IsOpen) {\n <!-- Backdrop -->\n <div class=\"search-backdrop\" (click)=\"OnBackdropClick()\"></div>\n\n <!-- Spotlight container -->\n <div class=\"search-spotlight\" (click)=\"$event.stopPropagation()\">\n <!-- Search input area -->\n <div class=\"search-input-wrap\">\n <i class=\"fa-solid fa-magnifying-glass search-icon\"></i>\n <input\n #searchInput\n type=\"text\"\n class=\"search-input\"\n [placeholder]=\"Placeholder\"\n [value]=\"Query\"\n (input)=\"OnQueryInput($any($event.target).value)\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (IsSearching) {\n <div class=\"search-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n </div>\n }\n <div class=\"search-shortcut-hint\">\n <kbd>ESC</kbd>\n </div>\n </div>\n\n <!-- Results area -->\n <div class=\"search-results-area\">\n @if (ShowFilters && Filters.length > 0) {\n <!-- Filter chips -->\n <div class=\"search-filter-bar\">\n @for (filter of Filters; track filter.Category) {\n @for (option of filter.Options; track option.Value) {\n <button\n class=\"filter-chip\"\n [class.filter-chip-active]=\"IsFilterActive(filter.Category, option.Value)\"\n (click)=\"OnFilterToggle(filter.Category, option.Value)\"\n >\n @if (option.Icon) {\n <i [class]=\"option.Icon\"></i>\n }\n <span>{{ option.Label }}</span>\n <span class=\"filter-chip-count\">{{ option.Count }}</span>\n </button>\n }\n }\n @if (hasActiveFilters()) {\n <button class=\"filter-clear-btn\" (click)=\"ClearAllFilters()\">\n <i class=\"fa-solid fa-times\"></i> Clear\n </button>\n }\n </div>\n }\n\n @if (HasSearched && AllResults.length === 0 && !IsSearching) {\n <!-- No results -->\n <div class=\"search-empty-state\">\n <i class=\"fa-solid fa-search search-empty-icon\"></i>\n <p class=\"search-empty-title\">No results found</p>\n <p class=\"search-empty-text\">Try different keywords or remove some filters</p>\n @if (ShowAgentCta) {\n <button class=\"agent-cta-btn\" (click)=\"OnAgentCtaClick()\">\n <i class=\"fa-solid fa-robot\"></i>\n {{ AgentCtaText }}\n </button>\n }\n </div>\n }\n\n @if (!HasSearched && !IsSearching) {\n <!-- Recent searches -->\n <div class=\"search-recent\">\n @if (searchService.RecentSearches$.value.length > 0) {\n <div class=\"search-recent-header\">\n <span class=\"search-recent-title\">Recent Searches</span>\n </div>\n @for (recent of searchService.RecentSearches$.value; track recent.Query; let i = $index) {\n @if (i < 5) {\n <div class=\"search-recent-item\" (click)=\"OnQueryInput(recent.Query)\">\n <i class=\"fa-solid fa-clock search-recent-icon\"></i>\n <span>{{ recent.Query }}</span>\n <span class=\"search-recent-count\">{{ recent.ResultCount }} results</span>\n </div>\n }\n }\n } @else {\n <div class=\"search-empty-state search-empty-state-compact\">\n <i class=\"fa-solid fa-magnifying-glass search-empty-icon\"></i>\n <p class=\"search-empty-text\">Start typing to search across all your knowledge</p>\n </div>\n }\n </div>\n }\n\n @if (AllResults.length > 0) {\n <!-- Grouped results -->\n @for (group of ResultGroups; track group.SourceType) {\n <div class=\"result-group\">\n <div class=\"result-group-header\">\n <i [class]=\"group.Icon\"></i>\n <span class=\"result-group-label\">{{ group.Label }}</span>\n <span class=\"result-group-count\">{{ group.TotalCount }}</span>\n </div>\n @for (result of group.Results; track result.ID; let ri = $index) {\n <div\n class=\"result-item\"\n [class.result-item-highlighted]=\"isResultHighlighted(result)\"\n (click)=\"OnResultClick(result, $event)\"\n (mouseenter)=\"HighlightedIndex = getFlatIndex(result)\"\n >\n <div class=\"result-item-icon\">\n <i [class]=\"result.SourceIcon\"></i>\n </div>\n <div class=\"result-item-content\">\n <div class=\"result-item-title\">{{ result.Title }}</div>\n <div class=\"result-item-snippet\">{{ result.Snippet }}</div>\n @if (result.Tags.length > 0) {\n <div class=\"result-item-tags\">\n @for (tag of result.Tags; track tag; let ti = $index) {\n @if (ti < 3) {\n <span class=\"result-tag\">{{ tag }}</span>\n }\n }\n </div>\n }\n </div>\n <div class=\"result-item-score\">\n <span class=\"score-badge\">{{ FormatScore(result.Score) }}</span>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Footer -->\n <div class=\"search-footer\">\n <span class=\"search-footer-count\">\n {{ TotalCount }} results in {{ FormatElapsedTime(ElapsedMs) }}\n </span>\n @if (ShowAgentCta) {\n <button class=\"agent-cta-btn agent-cta-btn-small\" (click)=\"OnAgentCtaClick()\">\n <i class=\"fa-solid fa-robot\"></i>\n {{ AgentCtaText }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-search",
3
- "version": "5.25.0",
3
+ "version": "5.27.0",
4
4
  "description": "MemberJunction: Reusable search overlay and results components - command palette / Spotlight style search",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -27,11 +27,11 @@
27
27
  "@angular/forms": "21.1.3"
28
28
  },
29
29
  "dependencies": {
30
- "@memberjunction/core": "5.25.0",
31
- "@memberjunction/global": "5.25.0",
32
- "@memberjunction/graphql-dataprovider": "5.25.0",
33
- "@memberjunction/core-entities": "5.25.0",
34
- "@memberjunction/ng-shared-generic": "5.25.0",
30
+ "@memberjunction/core": "5.27.0",
31
+ "@memberjunction/global": "5.27.0",
32
+ "@memberjunction/graphql-dataprovider": "5.27.0",
33
+ "@memberjunction/core-entities": "5.27.0",
34
+ "@memberjunction/ng-shared-generic": "5.27.0",
35
35
  "rxjs": "^7.8.2",
36
36
  "tslib": "^2.8.1"
37
37
  },