@memberjunction/ng-search 5.47.0 → 5.49.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.
- package/dist/lib/search-composite.component.d.ts +19 -2
- package/dist/lib/search-composite.component.d.ts.map +1 -1
- package/dist/lib/search-composite.component.js +79 -4
- package/dist/lib/search-composite.component.js.map +1 -1
- package/dist/lib/search-input.component.d.ts +9 -1
- package/dist/lib/search-input.component.d.ts.map +1 -1
- package/dist/lib/search-input.component.js +13 -2
- package/dist/lib/search-input.component.js.map +1 -1
- package/dist/lib/search-overlay.component.d.ts +65 -2
- package/dist/lib/search-overlay.component.d.ts.map +1 -1
- package/dist/lib/search-overlay.component.js +344 -135
- package/dist/lib/search-overlay.component.js.map +1 -1
- package/dist/lib/search-suggest.component.d.ts +43 -3
- package/dist/lib/search-suggest.component.d.ts.map +1 -1
- package/dist/lib/search-suggest.component.js +216 -75
- package/dist/lib/search-suggest.component.js.map +1 -1
- package/dist/lib/search-types.d.ts +9 -0
- package/dist/lib/search-types.d.ts.map +1 -1
- package/dist/lib/search-types.js.map +1 -1
- package/dist/lib/search.service.d.ts +20 -1
- package/dist/lib/search.service.d.ts.map +1 -1
- package/dist/lib/search.service.js +58 -1
- package/dist/lib/search.service.js.map +1 -1
- package/package.json +9 -9
|
@@ -9,7 +9,7 @@ import { EventEmitter, OnDestroy, OnInit } from '@angular/core';
|
|
|
9
9
|
import { SearchService, RecentSearch } from './search.service';
|
|
10
10
|
import { SearchInputComponent } from './search-input.component';
|
|
11
11
|
import { SearchSuggestComponent } from './search-suggest.component';
|
|
12
|
-
import { SearchResultItem, SearchScopeInfo } from './search-types';
|
|
12
|
+
import { SearchResultItem, SearchScopeInfo, RecentRecordItem } from './search-types';
|
|
13
13
|
import * as i0 from "@angular/core";
|
|
14
14
|
export declare class SearchCompositeComponent implements OnInit, OnDestroy {
|
|
15
15
|
private cdr;
|
|
@@ -39,18 +39,31 @@ export declare class SearchCompositeComponent implements OnInit, OnDestroy {
|
|
|
39
39
|
* stays hidden and the UX is identical to the pre-scope unscoped behavior.
|
|
40
40
|
*/
|
|
41
41
|
EnableScopeSelector: boolean;
|
|
42
|
+
/** Promo row pass-throughs — see SearchSuggestComponent for semantics. */
|
|
43
|
+
ShowPromo: boolean;
|
|
44
|
+
PromoText: string;
|
|
45
|
+
PromoActionLabel: string;
|
|
42
46
|
/** Emitted when a result is selected from the preview dropdown */
|
|
43
47
|
ResultSelected: EventEmitter<SearchResultItem>;
|
|
44
48
|
/** Emitted when the user presses Enter or selects a recent search (full search) */
|
|
45
49
|
SearchSubmitted: EventEmitter<string>;
|
|
46
50
|
/** Emitted when the user clicks "See all N results" */
|
|
47
51
|
SeeAllRequested: EventEmitter<string>;
|
|
52
|
+
/** Promo pass-throughs (accept carries the current query). */
|
|
53
|
+
PromoAccepted: EventEmitter<string>;
|
|
54
|
+
PromoDismissed: EventEmitter<void>;
|
|
55
|
+
/** Emitted when the user selects a recently opened record from the dropdown */
|
|
56
|
+
RecentRecordSelected: EventEmitter<RecentRecordItem>;
|
|
48
57
|
Query: string;
|
|
49
58
|
IsSuggestOpen: boolean;
|
|
50
59
|
/** The current min relevance percent from the suggest dropdown filter */
|
|
60
|
+
/** Programmatically focus the search input (e.g. a host-owned Ctrl/Cmd+K chord). */
|
|
61
|
+
Focus(): void;
|
|
51
62
|
get MinRelevancePercent(): number;
|
|
52
63
|
PreviewResults: SearchResultItem[];
|
|
53
64
|
RecentSearches: RecentSearch[];
|
|
65
|
+
/** Recently opened records for the dropdown's idle state (max 3 shown). */
|
|
66
|
+
RecentRecords: RecentRecordItem[];
|
|
54
67
|
PreviewTotalCount: number;
|
|
55
68
|
IsPreviewLoading: boolean;
|
|
56
69
|
private previewSearchVersion;
|
|
@@ -96,12 +109,16 @@ export declare class SearchCompositeComponent implements OnInit, OnDestroy {
|
|
|
96
109
|
*/
|
|
97
110
|
OnScopeSelectionChange(scopeIDs: string[]): void;
|
|
98
111
|
private openSuggest;
|
|
112
|
+
/** Load/refresh the recently-opened-records list (fail-soft, fire-and-forget). */
|
|
113
|
+
private refreshRecentRecords;
|
|
114
|
+
/** Recently-opened-record selection from the dropdown → bubble to the host. */
|
|
115
|
+
OnRecentRecordSelected(record: RecentRecordItem): void;
|
|
99
116
|
private closeSuggest;
|
|
100
117
|
private subscribeToRecentSearches;
|
|
101
118
|
private subscribeToScopes;
|
|
102
119
|
private executePreviewSearch;
|
|
103
120
|
private clearPreviewResults;
|
|
104
121
|
static ɵfac: i0.ɵɵFactoryDeclaration<SearchCompositeComponent, never>;
|
|
105
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<SearchCompositeComponent, "mj-search-composite", never, { "Placeholder": { "alias": "Placeholder"; "required": false; }; "ShowShortcutHint": { "alias": "ShowShortcutHint"; "required": false; }; "DebounceMs": { "alias": "DebounceMs"; "required": false; }; "MinQueryLength": { "alias": "MinQueryLength"; "required": false; }; "MaxPreviewResults": { "alias": "MaxPreviewResults"; "required": false; }; "EnablePreview": { "alias": "EnablePreview"; "required": false; }; "EnableRecent": { "alias": "EnableRecent"; "required": false; }; "EnableScopeSelector": { "alias": "EnableScopeSelector"; "required": false; }; }, { "ResultSelected": "ResultSelected"; "SearchSubmitted": "SearchSubmitted"; "SeeAllRequested": "SeeAllRequested"; }, never, never, false, never>;
|
|
122
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SearchCompositeComponent, "mj-search-composite", never, { "Placeholder": { "alias": "Placeholder"; "required": false; }; "ShowShortcutHint": { "alias": "ShowShortcutHint"; "required": false; }; "DebounceMs": { "alias": "DebounceMs"; "required": false; }; "MinQueryLength": { "alias": "MinQueryLength"; "required": false; }; "MaxPreviewResults": { "alias": "MaxPreviewResults"; "required": false; }; "EnablePreview": { "alias": "EnablePreview"; "required": false; }; "EnableRecent": { "alias": "EnableRecent"; "required": false; }; "EnableScopeSelector": { "alias": "EnableScopeSelector"; "required": false; }; "ShowPromo": { "alias": "ShowPromo"; "required": false; }; "PromoText": { "alias": "PromoText"; "required": false; }; "PromoActionLabel": { "alias": "PromoActionLabel"; "required": false; }; }, { "ResultSelected": "ResultSelected"; "SearchSubmitted": "SearchSubmitted"; "SeeAllRequested": "SeeAllRequested"; "PromoAccepted": "PromoAccepted"; "PromoDismissed": "PromoDismissed"; "RecentRecordSelected": "RecentRecordSelected"; }, never, never, false, never>;
|
|
106
123
|
}
|
|
107
124
|
//# sourceMappingURL=search-composite.component.d.ts.map
|
|
@@ -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,eAAe,EAAE,MAAM,gBAAgB,CAAC;;
|
|
1
|
+
{"version":3,"file":"search-composite.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-composite.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,6 +53,10 @@ export class SearchCompositeComponent {
|
|
|
53
53
|
* stays hidden and the UX is identical to the pre-scope unscoped behavior.
|
|
54
54
|
*/
|
|
55
55
|
EnableScopeSelector = true;
|
|
56
|
+
/** Promo row pass-throughs — see SearchSuggestComponent for semantics. */
|
|
57
|
+
ShowPromo = false;
|
|
58
|
+
PromoText = '';
|
|
59
|
+
PromoActionLabel = 'Turn on';
|
|
56
60
|
// --- Outputs ---
|
|
57
61
|
/** Emitted when a result is selected from the preview dropdown */
|
|
58
62
|
ResultSelected = new EventEmitter();
|
|
@@ -60,15 +64,26 @@ export class SearchCompositeComponent {
|
|
|
60
64
|
SearchSubmitted = new EventEmitter();
|
|
61
65
|
/** Emitted when the user clicks "See all N results" */
|
|
62
66
|
SeeAllRequested = new EventEmitter();
|
|
67
|
+
/** Promo pass-throughs (accept carries the current query). */
|
|
68
|
+
PromoAccepted = new EventEmitter();
|
|
69
|
+
PromoDismissed = new EventEmitter();
|
|
70
|
+
/** Emitted when the user selects a recently opened record from the dropdown */
|
|
71
|
+
RecentRecordSelected = new EventEmitter();
|
|
63
72
|
// --- Internal state ---
|
|
64
73
|
Query = '';
|
|
65
74
|
IsSuggestOpen = false;
|
|
66
75
|
/** The current min relevance percent from the suggest dropdown filter */
|
|
76
|
+
/** Programmatically focus the search input (e.g. a host-owned Ctrl/Cmd+K chord). */
|
|
77
|
+
Focus() {
|
|
78
|
+
this.searchInputRef?.Focus();
|
|
79
|
+
}
|
|
67
80
|
get MinRelevancePercent() {
|
|
68
81
|
return this.searchSuggestRef?.MinRelevancePercent ?? 0;
|
|
69
82
|
}
|
|
70
83
|
PreviewResults = [];
|
|
71
84
|
RecentSearches = [];
|
|
85
|
+
/** Recently opened records for the dropdown's idle state (max 3 shown). */
|
|
86
|
+
RecentRecords = [];
|
|
72
87
|
PreviewTotalCount = 0;
|
|
73
88
|
IsPreviewLoading = false;
|
|
74
89
|
previewSearchVersion = 0;
|
|
@@ -88,6 +103,7 @@ export class SearchCompositeComponent {
|
|
|
88
103
|
ngOnInit() {
|
|
89
104
|
this.subscribeToRecentSearches();
|
|
90
105
|
this.searchService.LoadRecentSearches(); // fire-and-forget — loads from UserInfoEngine
|
|
106
|
+
this.refreshRecentRecords(); // fire-and-forget — recently opened records
|
|
91
107
|
if (this.EnableScopeSelector) {
|
|
92
108
|
this.subscribeToScopes();
|
|
93
109
|
this.searchService.LoadScopes(); // fire-and-forget — populates Scopes$
|
|
@@ -123,6 +139,28 @@ export class SearchCompositeComponent {
|
|
|
123
139
|
this.searchSuggestRef.SelectHighlighted();
|
|
124
140
|
}
|
|
125
141
|
break;
|
|
142
|
+
case 'Tab': {
|
|
143
|
+
// Tab walks the dropdown suggestions (mirrors ArrowDown/Up) before
|
|
144
|
+
// leaving the widget — same model as the palette and overlay. DOM
|
|
145
|
+
// focus stays in the input (combobox pattern); only the highlight
|
|
146
|
+
// moves. Once the highlight walks off either end, Tab proceeds
|
|
147
|
+
// naturally (forward → the promo row / next control; backward →
|
|
148
|
+
// out of the bar).
|
|
149
|
+
const suggest = this.searchSuggestRef;
|
|
150
|
+
const count = suggest?.NavigableItemCount ?? 0;
|
|
151
|
+
if (!suggest || count === 0) {
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
if (!event.shiftKey && suggest.HighlightedIndex < count - 1) {
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
suggest.NavigateDown();
|
|
157
|
+
}
|
|
158
|
+
else if (event.shiftKey && suggest.HighlightedIndex > 0) {
|
|
159
|
+
event.preventDefault();
|
|
160
|
+
suggest.NavigateUp();
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
126
164
|
}
|
|
127
165
|
}
|
|
128
166
|
// --- Event handlers from child components ---
|
|
@@ -167,6 +205,15 @@ export class SearchCompositeComponent {
|
|
|
167
205
|
}
|
|
168
206
|
/** Handle result selection from suggest dropdown */
|
|
169
207
|
OnResultSelected(result) {
|
|
208
|
+
// Direct navigation bypasses ExecuteSearch (which is what normally records
|
|
209
|
+
// recents), so record the query here — the same compensation the omnibar
|
|
210
|
+
// palette applies in its Execute(). Enter/see-all paths don't need this:
|
|
211
|
+
// they land on the results page, whose full search records with the real
|
|
212
|
+
// count (addToRecentSearches dedups by query, so no double entries).
|
|
213
|
+
const typed = this.Query.trim();
|
|
214
|
+
if (typed.length > 0) {
|
|
215
|
+
this.searchService.RecordRecentSearch(typed, this.PreviewTotalCount);
|
|
216
|
+
}
|
|
170
217
|
this.ResultSelected.emit(result);
|
|
171
218
|
this.closeSuggest();
|
|
172
219
|
}
|
|
@@ -197,8 +244,24 @@ export class SearchCompositeComponent {
|
|
|
197
244
|
openSuggest() {
|
|
198
245
|
this.IsSuggestOpen = true;
|
|
199
246
|
this.searchSuggestRef?.ResetHighlight();
|
|
247
|
+
// Refresh in the background so a record opened since the last dropdown
|
|
248
|
+
// appears; name resolution is memoized in the service, so repeat opens
|
|
249
|
+
// are cheap.
|
|
250
|
+
this.refreshRecentRecords();
|
|
200
251
|
this.cdr.detectChanges();
|
|
201
252
|
}
|
|
253
|
+
/** Load/refresh the recently-opened-records list (fail-soft, fire-and-forget). */
|
|
254
|
+
refreshRecentRecords() {
|
|
255
|
+
void this.searchService.GetRecentlyOpenedRecords(3).then((records) => {
|
|
256
|
+
this.RecentRecords = records;
|
|
257
|
+
this.cdr.detectChanges();
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/** Recently-opened-record selection from the dropdown → bubble to the host. */
|
|
261
|
+
OnRecentRecordSelected(record) {
|
|
262
|
+
this.RecentRecordSelected.emit(record);
|
|
263
|
+
this.closeSuggest();
|
|
264
|
+
}
|
|
202
265
|
closeSuggest() {
|
|
203
266
|
this.IsSuggestOpen = false;
|
|
204
267
|
this.searchSuggestRef?.ResetHighlight();
|
|
@@ -268,7 +331,7 @@ export class SearchCompositeComponent {
|
|
|
268
331
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.searchSuggestRef = _t.first);
|
|
269
332
|
} }, hostBindings: function SearchCompositeComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
270
333
|
i0.ɵɵlistener("mousedown", function SearchCompositeComponent_mousedown_HostBindingHandler($event) { return ctx.OnDocumentMousedown($event); }, i0.ɵɵresolveDocument)("keydown", function SearchCompositeComponent_keydown_HostBindingHandler($event) { return ctx.OnHostKeydown($event); });
|
|
271
|
-
} }, inputs: { Placeholder: "Placeholder", ShowShortcutHint: "ShowShortcutHint", DebounceMs: "DebounceMs", MinQueryLength: "MinQueryLength", MaxPreviewResults: "MaxPreviewResults", EnablePreview: "EnablePreview", EnableRecent: "EnableRecent", EnableScopeSelector: "EnableScopeSelector" }, outputs: { ResultSelected: "ResultSelected", SearchSubmitted: "SearchSubmitted", SeeAllRequested: "SeeAllRequested" }, standalone: false, decls: 6, vars:
|
|
334
|
+
} }, inputs: { Placeholder: "Placeholder", ShowShortcutHint: "ShowShortcutHint", DebounceMs: "DebounceMs", MinQueryLength: "MinQueryLength", MaxPreviewResults: "MaxPreviewResults", EnablePreview: "EnablePreview", EnableRecent: "EnableRecent", EnableScopeSelector: "EnableScopeSelector", ShowPromo: "ShowPromo", PromoText: "PromoText", PromoActionLabel: "PromoActionLabel" }, outputs: { ResultSelected: "ResultSelected", SearchSubmitted: "SearchSubmitted", SeeAllRequested: "SeeAllRequested", PromoAccepted: "PromoAccepted", PromoDismissed: "PromoDismissed", RecentRecordSelected: "RecentRecordSelected" }, standalone: false, decls: 6, vars: 18, consts: [["searchInput", ""], ["searchSuggest", ""], [1, "search-composite-wrap"], [1, "search-composite-scope", 3, "SelectedScopeIDs"], [3, "QueryChange", "QuerySubmit", "InputFocused", "InputEscaped", "InputCleared", "Placeholder", "Query", "ShowShortcutHint", "DebounceMs"], [3, "ResultSelected", "RecentSelected", "SeeAllRequested", "ClearRecentRequested", "RecentRecordSelected", "PromoAccepted", "PromoDismissed", "IsOpen", "PreviewResults", "RecentSearches", "TotalCount", "IsLoading", "Query", "MinQueryLength", "MaxPreviewResults", "ShowRecent", "RecentRecords", "ShowPromo", "PromoText", "PromoActionLabel"], [1, "search-composite-scope", 3, "SelectionChange", "SelectedScopeIDs"]], template: function SearchCompositeComponent_Template(rf, ctx) { if (rf & 1) {
|
|
272
335
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
273
336
|
i0.ɵɵelementStart(0, "div", 2);
|
|
274
337
|
i0.ɵɵconditionalCreate(1, SearchCompositeComponent_Conditional_1_Template, 1, 1, "mj-search-scope-selector", 3);
|
|
@@ -276,7 +339,7 @@ export class SearchCompositeComponent {
|
|
|
276
339
|
i0.ɵɵlistener("QueryChange", function SearchCompositeComponent_Template_mj_search_input_QueryChange_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnQueryChange($event)); })("QuerySubmit", function SearchCompositeComponent_Template_mj_search_input_QuerySubmit_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnQuerySubmit($event)); })("InputFocused", function SearchCompositeComponent_Template_mj_search_input_InputFocused_2_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnInputFocused()); })("InputEscaped", function SearchCompositeComponent_Template_mj_search_input_InputEscaped_2_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnInputEscaped()); })("InputCleared", function SearchCompositeComponent_Template_mj_search_input_InputCleared_2_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnInputCleared()); });
|
|
277
340
|
i0.ɵɵelementEnd();
|
|
278
341
|
i0.ɵɵelementStart(4, "mj-search-suggest", 5, 1);
|
|
279
|
-
i0.ɵɵlistener("ResultSelected", function SearchCompositeComponent_Template_mj_search_suggest_ResultSelected_4_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnResultSelected($event)); })("RecentSelected", function SearchCompositeComponent_Template_mj_search_suggest_RecentSelected_4_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnRecentSelected($event)); })("SeeAllRequested", function SearchCompositeComponent_Template_mj_search_suggest_SeeAllRequested_4_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnSeeAllRequested($event)); })("ClearRecentRequested", function SearchCompositeComponent_Template_mj_search_suggest_ClearRecentRequested_4_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnClearRecentRequested()); });
|
|
342
|
+
i0.ɵɵlistener("ResultSelected", function SearchCompositeComponent_Template_mj_search_suggest_ResultSelected_4_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnResultSelected($event)); })("RecentSelected", function SearchCompositeComponent_Template_mj_search_suggest_RecentSelected_4_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnRecentSelected($event)); })("SeeAllRequested", function SearchCompositeComponent_Template_mj_search_suggest_SeeAllRequested_4_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnSeeAllRequested($event)); })("ClearRecentRequested", function SearchCompositeComponent_Template_mj_search_suggest_ClearRecentRequested_4_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnClearRecentRequested()); })("RecentRecordSelected", function SearchCompositeComponent_Template_mj_search_suggest_RecentRecordSelected_4_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnRecentRecordSelected($event)); })("PromoAccepted", function SearchCompositeComponent_Template_mj_search_suggest_PromoAccepted_4_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.PromoAccepted.emit($event)); })("PromoDismissed", function SearchCompositeComponent_Template_mj_search_suggest_PromoDismissed_4_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.PromoDismissed.emit()); });
|
|
280
343
|
i0.ɵɵelementEnd()();
|
|
281
344
|
} if (rf & 2) {
|
|
282
345
|
i0.ɵɵadvance();
|
|
@@ -284,12 +347,12 @@ export class SearchCompositeComponent {
|
|
|
284
347
|
i0.ɵɵadvance();
|
|
285
348
|
i0.ɵɵproperty("Placeholder", ctx.Placeholder)("Query", ctx.Query)("ShowShortcutHint", ctx.ShowShortcutHint)("DebounceMs", ctx.DebounceMs);
|
|
286
349
|
i0.ɵɵadvance(2);
|
|
287
|
-
i0.ɵɵproperty("IsOpen", ctx.IsSuggestOpen)("PreviewResults", ctx.PreviewResults)("RecentSearches", ctx.RecentSearches)("TotalCount", ctx.PreviewTotalCount)("IsLoading", ctx.IsPreviewLoading)("Query", ctx.Query)("MinQueryLength", ctx.MinQueryLength)("MaxPreviewResults", ctx.MaxPreviewResults)("ShowRecent", ctx.EnableRecent);
|
|
350
|
+
i0.ɵɵproperty("IsOpen", ctx.IsSuggestOpen)("PreviewResults", ctx.PreviewResults)("RecentSearches", ctx.RecentSearches)("TotalCount", ctx.PreviewTotalCount)("IsLoading", ctx.IsPreviewLoading)("Query", ctx.Query)("MinQueryLength", ctx.MinQueryLength)("MaxPreviewResults", ctx.MaxPreviewResults)("ShowRecent", ctx.EnableRecent)("RecentRecords", ctx.RecentRecords)("ShowPromo", ctx.ShowPromo)("PromoText", ctx.PromoText)("PromoActionLabel", ctx.PromoActionLabel);
|
|
288
351
|
} }, dependencies: [i1.SearchInputComponent, i2.SearchSuggestComponent, i3.SearchScopeSelectorComponent], styles: ["\n\n\n.search-composite-wrap[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: stretch;\n gap: 8px;\n width: 100%;\n}\n\n.search-composite-scope[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: inline-flex;\n align-items: stretch;\n}\n\n.search-composite-wrap[_ngcontent-%COMP%] > mj-search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.search-composite-wrap[_ngcontent-%COMP%] > mj-search-suggest[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n}"] });
|
|
289
352
|
}
|
|
290
353
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SearchCompositeComponent, [{
|
|
291
354
|
type: Component,
|
|
292
|
-
args: [{ standalone: false, selector: 'mj-search-composite', template: "<div class=\"search-composite-wrap\">\n @if (EnableScopeSelector && HasScopes) {\n <mj-search-scope-selector\n class=\"search-composite-scope\"\n [SelectedScopeIDs]=\"SelectedScopeIDs\"\n (SelectionChange)=\"OnScopeSelectionChange($any($event))\">\n </mj-search-scope-selector>\n }\n\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", styles: ["/* Search Composite Component */\n\n.search-composite-wrap {\n position: relative;\n display: flex;\n align-items: stretch;\n gap: 8px;\n width: 100%;\n}\n\n.search-composite-scope {\n flex-shrink: 0;\n display: inline-flex;\n align-items: stretch;\n}\n\n.search-composite-wrap > mj-search-input {\n flex: 1;\n min-width: 0;\n}\n\n.search-composite-wrap > mj-search-suggest {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n}\n"] }]
|
|
355
|
+
args: [{ standalone: false, selector: 'mj-search-composite', template: "<div class=\"search-composite-wrap\">\n @if (EnableScopeSelector && HasScopes) {\n <mj-search-scope-selector\n class=\"search-composite-scope\"\n [SelectedScopeIDs]=\"SelectedScopeIDs\"\n (SelectionChange)=\"OnScopeSelectionChange($any($event))\">\n </mj-search-scope-selector>\n }\n\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 [RecentRecords]=\"RecentRecords\"\n [ShowPromo]=\"ShowPromo\"\n [PromoText]=\"PromoText\"\n [PromoActionLabel]=\"PromoActionLabel\"\n (ResultSelected)=\"OnResultSelected($any($event))\"\n (RecentSelected)=\"OnRecentSelected($any($event))\"\n (SeeAllRequested)=\"OnSeeAllRequested($any($event))\"\n (ClearRecentRequested)=\"OnClearRecentRequested()\"\n (RecentRecordSelected)=\"OnRecentRecordSelected($event)\"\n (PromoAccepted)=\"PromoAccepted.emit($event)\"\n (PromoDismissed)=\"PromoDismissed.emit()\"\n ></mj-search-suggest>\n</div>\n", styles: ["/* Search Composite Component */\n\n.search-composite-wrap {\n position: relative;\n display: flex;\n align-items: stretch;\n gap: 8px;\n width: 100%;\n}\n\n.search-composite-scope {\n flex-shrink: 0;\n display: inline-flex;\n align-items: stretch;\n}\n\n.search-composite-wrap > mj-search-input {\n flex: 1;\n min-width: 0;\n}\n\n.search-composite-wrap > mj-search-suggest {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n}\n"] }]
|
|
293
356
|
}], null, { searchInputRef: [{
|
|
294
357
|
type: ViewChild,
|
|
295
358
|
args: ['searchInput']
|
|
@@ -312,12 +375,24 @@ export class SearchCompositeComponent {
|
|
|
312
375
|
type: Input
|
|
313
376
|
}], EnableScopeSelector: [{
|
|
314
377
|
type: Input
|
|
378
|
+
}], ShowPromo: [{
|
|
379
|
+
type: Input
|
|
380
|
+
}], PromoText: [{
|
|
381
|
+
type: Input
|
|
382
|
+
}], PromoActionLabel: [{
|
|
383
|
+
type: Input
|
|
315
384
|
}], ResultSelected: [{
|
|
316
385
|
type: Output
|
|
317
386
|
}], SearchSubmitted: [{
|
|
318
387
|
type: Output
|
|
319
388
|
}], SeeAllRequested: [{
|
|
320
389
|
type: Output
|
|
390
|
+
}], PromoAccepted: [{
|
|
391
|
+
type: Output
|
|
392
|
+
}], PromoDismissed: [{
|
|
393
|
+
type: Output
|
|
394
|
+
}], RecentRecordSelected: [{
|
|
395
|
+
type: Output
|
|
321
396
|
}], OnDocumentMousedown: [{
|
|
322
397
|
type: HostListener,
|
|
323
398
|
args: ['document:mousedown', ['$event']]
|
|
@@ -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, SearchScopeInfo } 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 /**\n * Whether to show the scope selector inline with the search input. When true (default),\n * the composite lazy-loads the list of scopes the current user can see and renders the\n * selector only if at least one scope exists. When zero scopes are visible the selector\n * stays hidden and the UX is identical to the pre-scope unscoped behavior.\n */\n @Input() EnableScopeSelector = 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 /**\n * Scopes the current user can see. Populated by `SearchService.LoadScopes()` on init.\n * When empty, the scope selector is not rendered (unscoped-as-before UX).\n */\n public AvailableScopes: SearchScopeInfo[] = [];\n\n /** Whether any scope is visible to the current user — drives selector visibility. */\n public HasScopes: boolean = false;\n\n /**\n * Currently selected scope IDs. Empty array means \"Global\" / unscoped. Read by the\n * shell (or any parent) on submit via the exposed getter, and mirrored to the server\n * through `SearchRequest.ScopeIDs` on the full submitted search.\n */\n public SelectedScopeIDs: string[] = [];\n\n ngOnInit(): void {\n this.subscribeToRecentSearches();\n this.searchService.LoadRecentSearches(); // fire-and-forget — loads from UserInfoEngine\n if (this.EnableScopeSelector) {\n this.subscribeToScopes();\n this.searchService.LoadScopes(); // fire-and-forget — populates Scopes$\n }\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 /**\n * Relay a selection change from the embedded scope selector to local state. Parents\n * read `SelectedScopeIDs` directly on submit; no output event is needed because\n * scope selection doesn't alter the inline preview (preview stays global for speed).\n */\n public OnScopeSelectionChange(scopeIDs: string[]): void {\n this.SelectedScopeIDs = scopeIDs;\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 subscribeToScopes(): void {\n this.searchService.Scopes$\n .pipe(takeUntil(this.destroy$))\n .subscribe(scopes => {\n this.AvailableScopes = scopes;\n this.HasScopes = scopes.length > 0;\n // Drop any previously-selected scope IDs the user can no longer see.\n if (this.SelectedScopeIDs.length > 0) {\n const visible = new Set(scopes.map(s => s.ID));\n const next = this.SelectedScopeIDs.filter(id => visible.has(id));\n if (next.length !== this.SelectedScopeIDs.length) {\n this.SelectedScopeIDs = next;\n }\n }\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 @if (EnableScopeSelector && HasScopes) {\n <mj-search-scope-selector\n class=\"search-composite-scope\"\n [SelectedScopeIDs]=\"SelectedScopeIDs\"\n (SelectionChange)=\"OnScopeSelectionChange($any($event))\">\n </mj-search-scope-selector>\n }\n\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, SearchScopeInfo, RecentRecordItem } 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 /**\n * Whether to show the scope selector inline with the search input. When true (default),\n * the composite lazy-loads the list of scopes the current user can see and renders the\n * selector only if at least one scope exists. When zero scopes are visible the selector\n * stays hidden and the UX is identical to the pre-scope unscoped behavior.\n */\n @Input() EnableScopeSelector = true;\n\n /** Promo row pass-throughs — see SearchSuggestComponent for semantics. */\n @Input() ShowPromo = false;\n @Input() PromoText = '';\n @Input() PromoActionLabel = 'Turn on';\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 /** Promo pass-throughs (accept carries the current query). */\n @Output() PromoAccepted = new EventEmitter<string>();\n @Output() PromoDismissed = new EventEmitter<void>();\n\n /** Emitted when the user selects a recently opened record from the dropdown */\n @Output() RecentRecordSelected = new EventEmitter<RecentRecordItem>();\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 /** Programmatically focus the search input (e.g. a host-owned Ctrl/Cmd+K chord). */\n public Focus(): void {\n this.searchInputRef?.Focus();\n }\n\n public get MinRelevancePercent(): number {\n return this.searchSuggestRef?.MinRelevancePercent ?? 0;\n }\n public PreviewResults: SearchResultItem[] = [];\n public RecentSearches: RecentSearch[] = [];\n /** Recently opened records for the dropdown's idle state (max 3 shown). */\n public RecentRecords: RecentRecordItem[] = [];\n public PreviewTotalCount = 0;\n public IsPreviewLoading = false;\n private previewSearchVersion = 0;\n\n /**\n * Scopes the current user can see. Populated by `SearchService.LoadScopes()` on init.\n * When empty, the scope selector is not rendered (unscoped-as-before UX).\n */\n public AvailableScopes: SearchScopeInfo[] = [];\n\n /** Whether any scope is visible to the current user — drives selector visibility. */\n public HasScopes: boolean = false;\n\n /**\n * Currently selected scope IDs. Empty array means \"Global\" / unscoped. Read by the\n * shell (or any parent) on submit via the exposed getter, and mirrored to the server\n * through `SearchRequest.ScopeIDs` on the full submitted search.\n */\n public SelectedScopeIDs: string[] = [];\n\n ngOnInit(): void {\n this.subscribeToRecentSearches();\n this.searchService.LoadRecentSearches(); // fire-and-forget — loads from UserInfoEngine\n this.refreshRecentRecords(); // fire-and-forget — recently opened records\n if (this.EnableScopeSelector) {\n this.subscribeToScopes();\n this.searchService.LoadScopes(); // fire-and-forget — populates Scopes$\n }\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 case 'Tab': {\n // Tab walks the dropdown suggestions (mirrors ArrowDown/Up) before\n // leaving the widget — same model as the palette and overlay. DOM\n // focus stays in the input (combobox pattern); only the highlight\n // moves. Once the highlight walks off either end, Tab proceeds\n // naturally (forward → the promo row / next control; backward →\n // out of the bar).\n const suggest = this.searchSuggestRef;\n const count = suggest?.NavigableItemCount ?? 0;\n if (!suggest || count === 0) {\n break;\n }\n if (!event.shiftKey && suggest.HighlightedIndex < count - 1) {\n event.preventDefault();\n suggest.NavigateDown();\n } else if (event.shiftKey && suggest.HighlightedIndex > 0) {\n event.preventDefault();\n suggest.NavigateUp();\n }\n break;\n }\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 // Direct navigation bypasses ExecuteSearch (which is what normally records\n // recents), so record the query here — the same compensation the omnibar\n // palette applies in its Execute(). Enter/see-all paths don't need this:\n // they land on the results page, whose full search records with the real\n // count (addToRecentSearches dedups by query, so no double entries).\n const typed = this.Query.trim();\n if (typed.length > 0) {\n this.searchService.RecordRecentSearch(typed, this.PreviewTotalCount);\n }\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 /**\n * Relay a selection change from the embedded scope selector to local state. Parents\n * read `SelectedScopeIDs` directly on submit; no output event is needed because\n * scope selection doesn't alter the inline preview (preview stays global for speed).\n */\n public OnScopeSelectionChange(scopeIDs: string[]): void {\n this.SelectedScopeIDs = scopeIDs;\n }\n\n // --- Private ---\n\n private openSuggest(): void {\n this.IsSuggestOpen = true;\n this.searchSuggestRef?.ResetHighlight();\n // Refresh in the background so a record opened since the last dropdown\n // appears; name resolution is memoized in the service, so repeat opens\n // are cheap.\n this.refreshRecentRecords();\n this.cdr.detectChanges();\n }\n\n /** Load/refresh the recently-opened-records list (fail-soft, fire-and-forget). */\n private refreshRecentRecords(): void {\n void this.searchService.GetRecentlyOpenedRecords(3).then((records) => {\n this.RecentRecords = records;\n this.cdr.detectChanges();\n });\n }\n\n /** Recently-opened-record selection from the dropdown → bubble to the host. */\n public OnRecentRecordSelected(record: RecentRecordItem): void {\n this.RecentRecordSelected.emit(record);\n this.closeSuggest();\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 subscribeToScopes(): void {\n this.searchService.Scopes$\n .pipe(takeUntil(this.destroy$))\n .subscribe(scopes => {\n this.AvailableScopes = scopes;\n this.HasScopes = scopes.length > 0;\n // Drop any previously-selected scope IDs the user can no longer see.\n if (this.SelectedScopeIDs.length > 0) {\n const visible = new Set(scopes.map(s => s.ID));\n const next = this.SelectedScopeIDs.filter(id => visible.has(id));\n if (next.length !== this.SelectedScopeIDs.length) {\n this.SelectedScopeIDs = next;\n }\n }\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 @if (EnableScopeSelector && HasScopes) {\n <mj-search-scope-selector\n class=\"search-composite-scope\"\n [SelectedScopeIDs]=\"SelectedScopeIDs\"\n (SelectionChange)=\"OnScopeSelectionChange($any($event))\">\n </mj-search-scope-selector>\n }\n\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 [RecentRecords]=\"RecentRecords\"\n [ShowPromo]=\"ShowPromo\"\n [PromoText]=\"PromoText\"\n [PromoActionLabel]=\"PromoActionLabel\"\n (ResultSelected)=\"OnResultSelected($any($event))\"\n (RecentSelected)=\"OnRecentSelected($any($event))\"\n (SeeAllRequested)=\"OnSeeAllRequested($any($event))\"\n (ClearRecentRequested)=\"OnClearRecentRequested()\"\n (RecentRecordSelected)=\"OnRecentRecordSelected($event)\"\n (PromoAccepted)=\"PromoAccepted.emit($event)\"\n (PromoDismissed)=\"PromoDismissed.emit()\"\n ></mj-search-suggest>\n</div>\n"]}
|
|
@@ -20,7 +20,12 @@ export declare class SearchInputComponent implements OnInit, OnDestroy {
|
|
|
20
20
|
get Query(): string;
|
|
21
21
|
/** Whether to show the keyboard shortcut hint badge */
|
|
22
22
|
ShowShortcutHint: boolean;
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Text to display in the shortcut hint badge. Defaults platform-aware:
|
|
25
|
+
* "⌘K" on macOS, "Ctrl+K" elsewhere (matching the actual chord, which hosts
|
|
26
|
+
* bind with metaKey on Mac). Set explicitly only to advertise a different
|
|
27
|
+
* chord.
|
|
28
|
+
*/
|
|
24
29
|
ShortcutHint: string;
|
|
25
30
|
/** Debounce time in milliseconds before QueryChange emits */
|
|
26
31
|
DebounceMs: number;
|
|
@@ -54,6 +59,9 @@ export declare class SearchInputComponent implements OnInit, OnDestroy {
|
|
|
54
59
|
OnClick(): void;
|
|
55
60
|
/** Handle blur event */
|
|
56
61
|
OnBlur(): void;
|
|
62
|
+
/** Platform-correct default for the shortcut badge (same detection idiom as
|
|
63
|
+
the Ctrl/Cmd+K keydown handlers that actually bind the chord). */
|
|
64
|
+
private static defaultShortcutHint;
|
|
57
65
|
private setupDebounce;
|
|
58
66
|
static ɵfac: i0.ɵɵFactoryDeclaration<SearchInputComponent, never>;
|
|
59
67
|
static ɵcmp: i0.ɵɵComponentDeclaration<SearchInputComponent, "mj-search-input", never, { "Placeholder": { "alias": "Placeholder"; "required": false; }; "Query": { "alias": "Query"; "required": false; }; "ShowShortcutHint": { "alias": "ShowShortcutHint"; "required": false; }; "ShortcutHint": { "alias": "ShortcutHint"; "required": false; }; "DebounceMs": { "alias": "DebounceMs"; "required": false; }; }, { "QueryChange": "QueryChange"; "QuerySubmit": "QuerySubmit"; "InputFocused": "InputFocused"; "InputBlurred": "InputBlurred"; "InputEscaped": "InputEscaped"; "InputCleared": "InputCleared"; }, never, never, false, never>;
|
|
@@ -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
|
|
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;;;;;OAKG;IACM,YAAY,SAA8C;IAEnE,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;yEACqE;IACrE,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAKlC,OAAO,CAAC,aAAa;yCA/IZ,oBAAoB;2CAApB,oBAAoB;CA0JhC"}
|
|
@@ -47,8 +47,13 @@ export class SearchInputComponent {
|
|
|
47
47
|
}
|
|
48
48
|
/** Whether to show the keyboard shortcut hint badge */
|
|
49
49
|
ShowShortcutHint = true;
|
|
50
|
-
/**
|
|
51
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Text to display in the shortcut hint badge. Defaults platform-aware:
|
|
52
|
+
* "⌘K" on macOS, "Ctrl+K" elsewhere (matching the actual chord, which hosts
|
|
53
|
+
* bind with metaKey on Mac). Set explicitly only to advertise a different
|
|
54
|
+
* chord.
|
|
55
|
+
*/
|
|
56
|
+
ShortcutHint = SearchInputComponent.defaultShortcutHint();
|
|
52
57
|
/** Debounce time in milliseconds before QueryChange emits */
|
|
53
58
|
DebounceMs = 400;
|
|
54
59
|
// --- Outputs ---
|
|
@@ -126,6 +131,12 @@ export class SearchInputComponent {
|
|
|
126
131
|
this.cdr.detectChanges();
|
|
127
132
|
}
|
|
128
133
|
// --- Private ---
|
|
134
|
+
/** Platform-correct default for the shortcut badge (same detection idiom as
|
|
135
|
+
the Ctrl/Cmd+K keydown handlers that actually bind the chord). */
|
|
136
|
+
static defaultShortcutHint() {
|
|
137
|
+
const isMac = typeof navigator !== 'undefined' && navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
|
138
|
+
return isMac ? '⌘K' : 'Ctrl+K';
|
|
139
|
+
}
|
|
129
140
|
setupDebounce() {
|
|
130
141
|
this.queryInput$
|
|
131
142
|
.pipe(debounceTime(this.DebounceMs), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
@@ -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":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,SAAS,EAET,YAAY,EACZ,KAAK,EAGL,MAAM,EACN,SAAS,EACT,iBAAiB,EACjB,MAAM,EACT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;;;;;ICJvE,iCAMC;IAJG,wLAAS,cAAO,KAAC;IAKjB,uBAAiC;IACrC,iBAAS;;;IAGT,8BAAmC;IAAA,YAAkB;IAAA,iBAAM;;;IAAxB,cAAkB;IAAlB,yCAAkB;;ADC7D,MAAM,OAAO,oBAAoB;IACrB,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAChC,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;IAC/B,WAAW,GAAG,IAAI,OAAO,EAAU,CAAC;IAEtB,QAAQ,CAAgC;IAE9D,+BAA+B;IAE/B,0CAA0C;IACjC,WAAW,GAAG,WAAW,CAAC;IAEnC,6DAA6D;IACrD,MAAM,GAAG,EAAE,CAAC;IAEpB,IACI,KAAK,CAAC,KAAa;QACnB,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC7B,CAAC;IACL,CAAC;IACD,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,uDAAuD;IAC9C,gBAAgB,GAAG,IAAI,CAAC;IAEjC,iDAAiD;IACxC,YAAY,GAAG,QAAQ,CAAC;IAEjC,6DAA6D;IACpD,UAAU,GAAG,GAAG,CAAC;IAE1B,kBAAkB;IAElB,qDAAqD;IAC3C,WAAW,GAAG,IAAI,YAAY,EAAU,CAAC;IAEnD,sDAAsD;IAC5C,WAAW,GAAG,IAAI,YAAY,EAAU,CAAC;IAEnD,4CAA4C;IAClC,YAAY,GAAG,IAAI,YAAY,EAAQ,CAAC;IAElD,yCAAyC;IAC/B,YAAY,GAAG,IAAI,YAAY,EAAQ,CAAC;IAElD,wDAAwD;IAC9C,YAAY,GAAG,IAAI,YAAY,EAAQ,CAAC;IAElD,kEAAkE;IACxD,YAAY,GAAG,IAAI,YAAY,EAAQ,CAAC;IAElD,yBAAyB;IAEzB,4CAA4C;IACrC,SAAS,GAAG,KAAK,CAAC;IAEzB,QAAQ;QACJ,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,WAAW;QACP,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAED,yBAAyB;IAEzB,+CAA+C;IACxC,KAAK;QACR,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,4CAA4C;IACrC,KAAK;QACR,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,kCAAkC;IAElC,gCAAgC;IACzB,OAAO,CAAC,KAAa;QACxB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,yCAAyC;IAClC,SAAS,CAAC,KAAoB;QACjC,QAAQ,KAAK,CAAC,GAAG,EAAE,CAAC;YAChB,KAAK,OAAO;gBACR,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACnC,MAAM;YACV,KAAK,QAAQ;gBACT,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;gBACzB,MAAM;QACd,CAAC;IACL,CAAC;IAED,yBAAyB;IAClB,OAAO;QACV,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,mEAAmE;IAC5D,OAAO;QACV,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QAC7B,CAAC;IACL,CAAC;IAED,wBAAwB;IACjB,MAAM;QACT,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,kBAAkB;IAEV,aAAa;QACjB,IAAI,CAAC,WAAW;aACX,IAAI,CACD,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,EAC7B,oBAAoB,EAAE,EACtB,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAC3B;aACA,SAAS,CAAC,KAAK,CAAC,EAAE;YACf,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACX,CAAC;8GA7IQ,oBAAoB;6DAApB,oBAAoB;;;;;;;YC7BjC,8BAA6E;YACzE,uBAA8D;YAC9D,mCAaE;YAHE,AADA,AADA,AADA,AADA,4IAAS,gCAAkC,KAAC,mIACjC,qBAAiB,KAAC,yHACpB,aAAS,KAAC,uHACX,YAAQ,KAAC,yHACR,aAAS,KAAC;YAVvB,iBAaE;YACF,yFAAwB;YAWxB,sFAA4D;YAGhE,iBAAM;;YA9B8B,qDAAwC;YAMpE,eAA2B;YAC3B,AADA,6CAA2B,oBACZ;YASnB,eAUC;YAVD,+CAUC;YACD,cAEC;YAFD,2FAEC;;;iFDAQ,oBAAoB;cANhC,SAAS;6BACM,KAAK,YACP,iBAAiB;;kBAS1B,SAAS;mBAAC,SAAS;;kBAKnB,KAAK;;kBAKL,KAAK;;kBAYL,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAKL,MAAM;;kBAGN,MAAM;;kBAGN,MAAM;;kBAGN,MAAM;;kBAGN,MAAM;;kBAGN,MAAM;;kFArDE,oBAAoB","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 aria-label=\"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 /**\n * Text to display in the shortcut hint badge. Defaults platform-aware:\n * \"⌘K\" on macOS, \"Ctrl+K\" elsewhere (matching the actual chord, which hosts\n * bind with metaKey on Mac). Set explicitly only to advertise a different\n * chord.\n */\n @Input() ShortcutHint = SearchInputComponent.defaultShortcutHint();\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 /** Platform-correct default for the shortcut badge (same detection idiom as\n the Ctrl/Cmd+K keydown handlers that actually bind the chord). */\n private static defaultShortcutHint(): string {\n const isMac = typeof navigator !== 'undefined' && navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n return isMac ? '⌘K' : 'Ctrl+K';\n }\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 aria-label=\"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"]}
|
|
@@ -37,7 +37,13 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
37
37
|
searchInputRef: ElementRef<HTMLInputElement>;
|
|
38
38
|
/** Placeholder text for the search input */
|
|
39
39
|
Placeholder: string;
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Maximum number of results to fetch and display. Deliberately small — the
|
|
42
|
+
* overlay is a quick-jump surface; "See all results" hands off to the full
|
|
43
|
+
* Search Results workspace for anything deeper. 8 matches the omnibar
|
|
44
|
+
* palette's RESULT count (it fetches 9 rows = 8 results + its see-all row;
|
|
45
|
+
* this overlay's see-all is a footer button, not a row).
|
|
46
|
+
*/
|
|
41
47
|
MaxResults: number;
|
|
42
48
|
/** Whether the overlay is currently visible */
|
|
43
49
|
private _IsOpen;
|
|
@@ -60,11 +66,40 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
60
66
|
* Defaults to false to preserve the request-response UX that shipped in Phase 1.
|
|
61
67
|
*/
|
|
62
68
|
EnableStreaming: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* When false, the overlay does NOT claim the global Ctrl/Cmd+K chord. For hosts
|
|
71
|
+
* (e.g. the Explorer shell) that own that shortcut themselves and open the
|
|
72
|
+
* overlay programmatically — two listeners on the same chord would double-toggle.
|
|
73
|
+
* Escape/arrow handling while open is unaffected.
|
|
74
|
+
*/
|
|
75
|
+
EnableGlobalShortcut: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Optional promo strip pinned to the overlay's bottom edge — a host-supplied
|
|
78
|
+
* nudge (e.g. Explorer advertising its command palette). The component is
|
|
79
|
+
* deliberately ignorant of WHAT is being promoted; the host provides the
|
|
80
|
+
* copy and handles both outcomes.
|
|
81
|
+
*/
|
|
82
|
+
ShowPromo: boolean;
|
|
83
|
+
/** Promo copy (one sentence). Required when ShowPromo is true. */
|
|
84
|
+
PromoText: string;
|
|
85
|
+
/** Label for the promo's accept action. */
|
|
86
|
+
PromoActionLabel: string;
|
|
63
87
|
IsOpenChange: EventEmitter<boolean>;
|
|
64
88
|
ResultSelected: EventEmitter<SearchResultSelectedEvent>;
|
|
65
89
|
FilterChanged: EventEmitter<SearchFilterChangeEvent>;
|
|
66
90
|
SearchExecuted: EventEmitter<SearchExecutedEvent>;
|
|
67
91
|
AgentCtaClicked: EventEmitter<string>;
|
|
92
|
+
/**
|
|
93
|
+
* Emitted when the user clicks "See all results" — carries the current query.
|
|
94
|
+
* Hosts (e.g. the Explorer shell) open the full Search Results workspace,
|
|
95
|
+
* which has scopes, relevance controls, and richer result actions than this
|
|
96
|
+
* capped quick-jump overlay. The overlay closes itself after emitting.
|
|
97
|
+
*/
|
|
98
|
+
SeeAllRequested: EventEmitter<string>;
|
|
99
|
+
/** Promo accept — carries the current query so the host can hand it off. */
|
|
100
|
+
PromoAccepted: EventEmitter<string>;
|
|
101
|
+
/** Promo dismissed — the host should persist this and stop showing it. */
|
|
102
|
+
PromoDismissed: EventEmitter<void>;
|
|
68
103
|
Query: string;
|
|
69
104
|
IsSearching: boolean;
|
|
70
105
|
ResultGroups: SearchResultGroup[];
|
|
@@ -84,8 +119,12 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
84
119
|
StreamingProviders: StreamingProviderStatus[];
|
|
85
120
|
/** Active stream subscription so we can cancel on a new search or destroy. */
|
|
86
121
|
private currentStream;
|
|
122
|
+
/** Element focused before the overlay opened — restored on close (a11y). */
|
|
123
|
+
private previousFocus;
|
|
87
124
|
/** All results flattened for keyboard navigation */
|
|
88
125
|
get FlatResults(): SearchResultItem[];
|
|
126
|
+
/** id of the highlighted option, announced via aria-activedescendant. */
|
|
127
|
+
get ActiveDescendantId(): string | null;
|
|
89
128
|
ngOnInit(): void;
|
|
90
129
|
ngOnDestroy(): void;
|
|
91
130
|
HandleGlobalKeydown(event: KeyboardEvent): void;
|
|
@@ -107,6 +146,12 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
107
146
|
ClearAllFilters(): void;
|
|
108
147
|
/** Handle clicking the agent CTA */
|
|
109
148
|
OnAgentCtaClick(): void;
|
|
149
|
+
/** Promo accept: emit the current query and close — the host takes over. */
|
|
150
|
+
OnPromoAccept(): void;
|
|
151
|
+
/** Promo dismiss: the host persists the dismissal; hide it immediately. */
|
|
152
|
+
OnPromoDismiss(): void;
|
|
153
|
+
/** Handle clicking "See all results" — hand off to the full Search workspace */
|
|
154
|
+
OnSeeAllClick(): void;
|
|
110
155
|
/** Handle clicking the backdrop to close */
|
|
111
156
|
OnBackdropClick(): void;
|
|
112
157
|
/** Check if a filter option is active */
|
|
@@ -118,6 +163,24 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
118
163
|
private isToggleShortcut;
|
|
119
164
|
private handleOverlayKeydown;
|
|
120
165
|
private moveHighlight;
|
|
166
|
+
/**
|
|
167
|
+
* Tab behavior inside the dialog:
|
|
168
|
+
* - On a result row, Tab / Shift+Tab step through the RESULTS themselves
|
|
169
|
+
* (mirrors ArrowDown/Up) until walking off either end of the list — then
|
|
170
|
+
* focus continues to the footer actions / back to the earlier controls.
|
|
171
|
+
* - Everywhere else, Tab wraps within the dialog (focus trap): input → close
|
|
172
|
+
* → filter chips → results → footer actions → back to the input.
|
|
173
|
+
* Escape is handled by the document-level keydown.
|
|
174
|
+
*/
|
|
175
|
+
OnSpotlightKeydown(event: KeyboardEvent): void;
|
|
176
|
+
/**
|
|
177
|
+
* Recent-search row activated (click or Enter/Space). Re-runs the search AND
|
|
178
|
+
* refocuses the input — the activated row leaves the DOM when recents are
|
|
179
|
+
* replaced by results, which would otherwise drop focus to <body>.
|
|
180
|
+
*/
|
|
181
|
+
OnRecentSelect(query: string): void;
|
|
182
|
+
/** Recent-search rows are keyboard-activatable (Enter/Space = click). */
|
|
183
|
+
OnRecentKeydown(event: KeyboardEvent, query: string): void;
|
|
121
184
|
private setupSearchDebounce;
|
|
122
185
|
private subscribeToSearchState;
|
|
123
186
|
private executeSearch;
|
|
@@ -140,6 +203,6 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
140
203
|
/** Get the flat index of a result for keyboard navigation */
|
|
141
204
|
getFlatIndex(result: SearchResultItem): number;
|
|
142
205
|
static ɵfac: i0.ɵɵFactoryDeclaration<SearchOverlayComponent, never>;
|
|
143
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<SearchOverlayComponent, "mj-search-overlay", never, { "Placeholder": { "alias": "Placeholder"; "required": false; }; "MaxResults": { "alias": "MaxResults"; "required": false; }; "IsOpen": { "alias": "IsOpen"; "required": false; }; "DebounceMs": { "alias": "DebounceMs"; "required": false; }; "IncludeSources": { "alias": "IncludeSources"; "required": false; }; "ShowFilters": { "alias": "ShowFilters"; "required": false; }; "AgentCtaText": { "alias": "AgentCtaText"; "required": false; }; "ShowAgentCta": { "alias": "ShowAgentCta"; "required": false; }; "EnableStreaming": { "alias": "EnableStreaming"; "required": false; }; }, { "IsOpenChange": "IsOpenChange"; "ResultSelected": "ResultSelected"; "FilterChanged": "FilterChanged"; "SearchExecuted": "SearchExecuted"; "AgentCtaClicked": "AgentCtaClicked"; }, never, never, false, never>;
|
|
206
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SearchOverlayComponent, "mj-search-overlay", never, { "Placeholder": { "alias": "Placeholder"; "required": false; }; "MaxResults": { "alias": "MaxResults"; "required": false; }; "IsOpen": { "alias": "IsOpen"; "required": false; }; "DebounceMs": { "alias": "DebounceMs"; "required": false; }; "IncludeSources": { "alias": "IncludeSources"; "required": false; }; "ShowFilters": { "alias": "ShowFilters"; "required": false; }; "AgentCtaText": { "alias": "AgentCtaText"; "required": false; }; "ShowAgentCta": { "alias": "ShowAgentCta"; "required": false; }; "EnableStreaming": { "alias": "EnableStreaming"; "required": false; }; "EnableGlobalShortcut": { "alias": "EnableGlobalShortcut"; "required": false; }; "ShowPromo": { "alias": "ShowPromo"; "required": false; }; "PromoText": { "alias": "PromoText"; "required": false; }; "PromoActionLabel": { "alias": "PromoActionLabel"; "required": false; }; }, { "IsOpenChange": "IsOpenChange"; "ResultSelected": "ResultSelected"; "FilterChanged": "FilterChanged"; "SearchExecuted": "SearchExecuted"; "AgentCtaClicked": "AgentCtaClicked"; "SeeAllRequested": "SeeAllRequested"; "PromoAccepted": "PromoAccepted"; "PromoDismissed": "PromoDismissed"; }, never, never, false, never>;
|
|
144
207
|
}
|
|
145
208
|
//# sourceMappingURL=search-overlay.component.d.ts.map
|