@memberjunction/ng-search 6.2.0-edge.0 → 6.2.0-edge.1
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 +10 -2
- package/dist/lib/search-composite.component.d.ts.map +1 -1
- package/dist/lib/search-composite.component.js +33 -17
- package/dist/lib/search-composite.component.js.map +1 -1
- package/dist/lib/search-input.component.d.ts +6 -2
- package/dist/lib/search-input.component.d.ts.map +1 -1
- package/dist/lib/search-input.component.js +19 -11
- package/dist/lib/search-input.component.js.map +1 -1
- package/dist/lib/search-overlay.component.d.ts +12 -2
- package/dist/lib/search-overlay.component.d.ts.map +1 -1
- package/dist/lib/search-overlay.component.js +39 -19
- package/dist/lib/search-overlay.component.js.map +1 -1
- package/dist/lib/search-suggest.component.d.ts +8 -0
- package/dist/lib/search-suggest.component.d.ts.map +1 -1
- package/dist/lib/search-suggest.component.js +30 -14
- package/dist/lib/search-suggest.component.js.map +1 -1
- package/package.json +9 -9
|
@@ -16,8 +16,16 @@ export declare class SearchCompositeComponent implements OnInit, OnDestroy {
|
|
|
16
16
|
private elementRef;
|
|
17
17
|
protected searchService: SearchService;
|
|
18
18
|
private destroy$;
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
SearchInputRef: SearchInputComponent;
|
|
20
|
+
/** @deprecated Use {@link SearchInputRef}. */
|
|
21
|
+
get searchInputRef(): SearchInputComponent;
|
|
22
|
+
/** @deprecated Use {@link SearchInputRef}. */
|
|
23
|
+
set searchInputRef(value: SearchInputComponent);
|
|
24
|
+
SearchSuggestRef: SearchSuggestComponent;
|
|
25
|
+
/** @deprecated Use {@link SearchSuggestRef}. */
|
|
26
|
+
get searchSuggestRef(): SearchSuggestComponent;
|
|
27
|
+
/** @deprecated Use {@link SearchSuggestRef}. */
|
|
28
|
+
set searchSuggestRef(value: SearchSuggestComponent);
|
|
21
29
|
/** Placeholder text for the search input */
|
|
22
30
|
Placeholder: string;
|
|
23
31
|
/** Whether to show keyboard shortcut hint on the input */
|
|
@@ -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,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;;AAErF,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;
|
|
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,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;;AAErF,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;IAEhE,8CAA8C;IAC9C,IAAI,cAAc,IAAI,oBAAoB,CAEzC;IACD,8CAA8C;IAC9C,IAAI,cAAc,CAAC,KAAK,EAAE,oBAAoB,EAE7C;IAC2B,gBAAgB,EAAG,sBAAsB,CAAC;IAEtE,gDAAgD;IAChD,IAAI,gBAAgB,IAAI,sBAAsB,CAE7C;IACD,gDAAgD;IAChD,IAAI,gBAAgB,CAAC,KAAK,EAAE,sBAAsB,EAEjD;IAID,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;IAE7B;;;;;OAKG;IACM,mBAAmB,UAAQ;IAEpC,0EAA0E;IACjE,SAAS,UAAS;IAClB,SAAS,SAAM;IACf,gBAAgB,SAAa;IAItC,kEAAkE;IACxD,cAAc,iCAAwC;IAEhE,mFAAmF;IACzE,eAAe,uBAA8B;IAEvD,uDAAuD;IAC7C,eAAe,uBAA8B;IAEvD,8DAA8D;IACpD,aAAa,uBAA8B;IAC3C,cAAc,qBAA4B;IAEpD,+EAA+E;IACrE,oBAAoB,iCAAwC;IAI/D,KAAK,SAAM;IACX,aAAa,UAAS;IAE7B,yEAAyE;IACzE,oFAAoF;IAC7E,KAAK,IAAI,IAAI;IAIpB,IAAW,mBAAmB,IAAI,MAAM,CAEvC;IACM,cAAc,EAAE,gBAAgB,EAAE,CAAM;IACxC,cAAc,EAAE,YAAY,EAAE,CAAM;IAC3C,2EAA2E;IACpE,aAAa,EAAE,gBAAgB,EAAE,CAAM;IACvC,iBAAiB,SAAK;IACtB,gBAAgB,UAAS;IAChC,OAAO,CAAC,oBAAoB,CAAK;IAEjC;;;OAGG;IACI,eAAe,EAAE,eAAe,EAAE,CAAM;IAE/C,qFAAqF;IAC9E,SAAS,EAAE,OAAO,CAAS;IAElC;;;;OAIG;IACI,gBAAgB,EAAE,MAAM,EAAE,CAAM;IAEvC,QAAQ,IAAI,IAAI;IAUhB,WAAW,IAAI,IAAI;IAQnB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAU5C,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IA4CzC,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;IAcvD,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;IAIrC;;;;OAIG;IACI,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAMvD,OAAO,CAAC,WAAW;IAUnB,kFAAkF;IAClF,OAAO,CAAC,oBAAoB;IAO5B,+EAA+E;IACxE,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAK7D,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,yBAAyB;IASjC,OAAO,CAAC,iBAAiB;YAkBX,oBAAoB;IAyBlC,OAAO,CAAC,mBAAmB;yCA3WlB,wBAAwB;2CAAxB,wBAAwB;CAgXpC"}
|
|
@@ -29,8 +29,24 @@ export class SearchCompositeComponent {
|
|
|
29
29
|
elementRef = inject(ElementRef);
|
|
30
30
|
searchService = inject(SearchService);
|
|
31
31
|
destroy$ = new Subject();
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
SearchInputRef;
|
|
33
|
+
/** @deprecated Use {@link SearchInputRef}. */
|
|
34
|
+
get searchInputRef() {
|
|
35
|
+
return this.SearchInputRef;
|
|
36
|
+
}
|
|
37
|
+
/** @deprecated Use {@link SearchInputRef}. */
|
|
38
|
+
set searchInputRef(value) {
|
|
39
|
+
this.SearchInputRef = value;
|
|
40
|
+
}
|
|
41
|
+
SearchSuggestRef;
|
|
42
|
+
/** @deprecated Use {@link SearchSuggestRef}. */
|
|
43
|
+
get searchSuggestRef() {
|
|
44
|
+
return this.SearchSuggestRef;
|
|
45
|
+
}
|
|
46
|
+
/** @deprecated Use {@link SearchSuggestRef}. */
|
|
47
|
+
set searchSuggestRef(value) {
|
|
48
|
+
this.SearchSuggestRef = value;
|
|
49
|
+
}
|
|
34
50
|
// --- Configuration Inputs ---
|
|
35
51
|
/** Placeholder text for the search input */
|
|
36
52
|
Placeholder = 'Search...';
|
|
@@ -75,10 +91,10 @@ export class SearchCompositeComponent {
|
|
|
75
91
|
/** The current min relevance percent from the suggest dropdown filter */
|
|
76
92
|
/** Programmatically focus the search input (e.g. a host-owned Ctrl/Cmd+K chord). */
|
|
77
93
|
Focus() {
|
|
78
|
-
this.
|
|
94
|
+
this.SearchInputRef?.Focus();
|
|
79
95
|
}
|
|
80
96
|
get MinRelevancePercent() {
|
|
81
|
-
return this.
|
|
97
|
+
return this.SearchSuggestRef?.MinRelevancePercent ?? 0;
|
|
82
98
|
}
|
|
83
99
|
PreviewResults = [];
|
|
84
100
|
RecentSearches = [];
|
|
@@ -127,16 +143,16 @@ export class SearchCompositeComponent {
|
|
|
127
143
|
switch (event.key) {
|
|
128
144
|
case 'ArrowDown':
|
|
129
145
|
event.preventDefault();
|
|
130
|
-
this.
|
|
146
|
+
this.SearchSuggestRef?.NavigateDown();
|
|
131
147
|
break;
|
|
132
148
|
case 'ArrowUp':
|
|
133
149
|
event.preventDefault();
|
|
134
|
-
this.
|
|
150
|
+
this.SearchSuggestRef?.NavigateUp();
|
|
135
151
|
break;
|
|
136
152
|
case 'Enter':
|
|
137
|
-
if (this.
|
|
153
|
+
if (this.SearchSuggestRef?.HighlightedIndex >= 0) {
|
|
138
154
|
event.preventDefault();
|
|
139
|
-
this.
|
|
155
|
+
this.SearchSuggestRef.SelectHighlighted();
|
|
140
156
|
}
|
|
141
157
|
break;
|
|
142
158
|
case 'Tab': {
|
|
@@ -146,7 +162,7 @@ export class SearchCompositeComponent {
|
|
|
146
162
|
// moves. Once the highlight walks off either end, Tab proceeds
|
|
147
163
|
// naturally (forward → the promo row / next control; backward →
|
|
148
164
|
// out of the bar).
|
|
149
|
-
const suggest = this.
|
|
165
|
+
const suggest = this.SearchSuggestRef;
|
|
150
166
|
const count = suggest?.NavigableItemCount ?? 0;
|
|
151
167
|
if (!suggest || count === 0) {
|
|
152
168
|
break;
|
|
@@ -178,8 +194,8 @@ export class SearchCompositeComponent {
|
|
|
178
194
|
/** Handle Enter press in the input */
|
|
179
195
|
OnQuerySubmit(query) {
|
|
180
196
|
// If a suggestion is highlighted, select it instead of searching
|
|
181
|
-
if (this.IsSuggestOpen && this.
|
|
182
|
-
this.
|
|
197
|
+
if (this.IsSuggestOpen && this.SearchSuggestRef && this.SearchSuggestRef.HighlightedIndex >= 0) {
|
|
198
|
+
this.SearchSuggestRef.SelectHighlighted();
|
|
183
199
|
return;
|
|
184
200
|
}
|
|
185
201
|
if (query.trim().length > 0) {
|
|
@@ -243,7 +259,7 @@ export class SearchCompositeComponent {
|
|
|
243
259
|
// --- Private ---
|
|
244
260
|
openSuggest() {
|
|
245
261
|
this.IsSuggestOpen = true;
|
|
246
|
-
this.
|
|
262
|
+
this.SearchSuggestRef?.ResetHighlight();
|
|
247
263
|
// Refresh in the background so a record opened since the last dropdown
|
|
248
264
|
// appears; name resolution is memoized in the service, so repeat opens
|
|
249
265
|
// are cheap.
|
|
@@ -264,7 +280,7 @@ export class SearchCompositeComponent {
|
|
|
264
280
|
}
|
|
265
281
|
closeSuggest() {
|
|
266
282
|
this.IsSuggestOpen = false;
|
|
267
|
-
this.
|
|
283
|
+
this.SearchSuggestRef?.ResetHighlight();
|
|
268
284
|
this.cdr.detectChanges();
|
|
269
285
|
}
|
|
270
286
|
subscribeToRecentSearches() {
|
|
@@ -327,8 +343,8 @@ export class SearchCompositeComponent {
|
|
|
327
343
|
i0.ɵɵviewQuery(_c0, 5)(_c1, 5);
|
|
328
344
|
} if (rf & 2) {
|
|
329
345
|
let _t;
|
|
330
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.
|
|
331
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.
|
|
346
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.SearchInputRef = _t.first);
|
|
347
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.SearchSuggestRef = _t.first);
|
|
332
348
|
} }, hostBindings: function SearchCompositeComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
333
349
|
i0.ɵɵlistener("mousedown", function SearchCompositeComponent_mousedown_HostBindingHandler($event) { return ctx.OnDocumentMousedown($event); }, i0.ɵɵresolveDocument)("keydown", function SearchCompositeComponent_keydown_HostBindingHandler($event) { return ctx.OnHostKeydown($event); });
|
|
334
350
|
} }, 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) {
|
|
@@ -352,10 +368,10 @@ export class SearchCompositeComponent {
|
|
|
352
368
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SearchCompositeComponent, [{
|
|
353
369
|
type: Component,
|
|
354
370
|
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"] }]
|
|
355
|
-
}], null, {
|
|
371
|
+
}], null, { SearchInputRef: [{
|
|
356
372
|
type: ViewChild,
|
|
357
373
|
args: ['searchInput']
|
|
358
|
-
}],
|
|
374
|
+
}], SearchSuggestRef: [{
|
|
359
375
|
type: ViewChild,
|
|
360
376
|
args: ['searchSuggest']
|
|
361
377
|
}], Placeholder: [{
|
|
@@ -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, 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"]}
|
|
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\n /** @deprecated Use {@link SearchInputRef}. */\n get searchInputRef(): SearchInputComponent {\n return this.SearchInputRef;\n }\n /** @deprecated Use {@link SearchInputRef}. */\n set searchInputRef(value: SearchInputComponent) {\n this.SearchInputRef = value;\n }\n @ViewChild('searchSuggest') SearchSuggestRef!: SearchSuggestComponent;\n\n /** @deprecated Use {@link SearchSuggestRef}. */\n get searchSuggestRef(): SearchSuggestComponent {\n return this.SearchSuggestRef;\n }\n /** @deprecated Use {@link SearchSuggestRef}. */\n set searchSuggestRef(value: SearchSuggestComponent) {\n this.SearchSuggestRef = value;\n }\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"]}
|
|
@@ -11,11 +11,15 @@ export declare class SearchInputComponent implements OnInit, OnDestroy {
|
|
|
11
11
|
private cdr;
|
|
12
12
|
private destroy$;
|
|
13
13
|
private queryInput$;
|
|
14
|
-
|
|
14
|
+
InputRef: ElementRef<HTMLInputElement>;
|
|
15
|
+
/** @deprecated Use {@link InputRef}. */
|
|
16
|
+
get inputRef(): ElementRef<HTMLInputElement>;
|
|
17
|
+
/** @deprecated Use {@link InputRef}. */
|
|
18
|
+
set inputRef(value: ElementRef<HTMLInputElement>);
|
|
15
19
|
/** Placeholder text shown in the input */
|
|
16
20
|
Placeholder: string;
|
|
17
21
|
/** Current query value (two-way bindable via QueryChange) */
|
|
18
|
-
private
|
|
22
|
+
private _query;
|
|
19
23
|
set Query(value: string);
|
|
20
24
|
get Query(): string;
|
|
21
25
|
/** Whether to show the keyboard shortcut hint badge */
|
|
@@ -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;
|
|
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;IAE9D,wCAAwC;IACxC,IAAI,QAAQ,IAAI,UAAU,CAAC,gBAAgB,CAAC,CAE3C;IACD,wCAAwC;IACxC,IAAI,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC,EAE/C;IAID,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;yCAxJZ,oBAAoB;2CAApB,oBAAoB;CAmKhC"}
|
|
@@ -30,20 +30,28 @@ export class SearchInputComponent {
|
|
|
30
30
|
cdr = inject(ChangeDetectorRef);
|
|
31
31
|
destroy$ = new Subject();
|
|
32
32
|
queryInput$ = new Subject();
|
|
33
|
-
|
|
33
|
+
InputRef;
|
|
34
|
+
/** @deprecated Use {@link InputRef}. */
|
|
35
|
+
get inputRef() {
|
|
36
|
+
return this.InputRef;
|
|
37
|
+
}
|
|
38
|
+
/** @deprecated Use {@link InputRef}. */
|
|
39
|
+
set inputRef(value) {
|
|
40
|
+
this.InputRef = value;
|
|
41
|
+
}
|
|
34
42
|
// --- Configuration Inputs ---
|
|
35
43
|
/** Placeholder text shown in the input */
|
|
36
44
|
Placeholder = 'Search...';
|
|
37
45
|
/** Current query value (two-way bindable via QueryChange) */
|
|
38
|
-
|
|
46
|
+
_query = '';
|
|
39
47
|
set Query(value) {
|
|
40
|
-
if (value !== this.
|
|
41
|
-
this.
|
|
48
|
+
if (value !== this._query) {
|
|
49
|
+
this._query = value;
|
|
42
50
|
this.cdr.detectChanges();
|
|
43
51
|
}
|
|
44
52
|
}
|
|
45
53
|
get Query() {
|
|
46
|
-
return this.
|
|
54
|
+
return this._query;
|
|
47
55
|
}
|
|
48
56
|
/** Whether to show the keyboard shortcut hint badge */
|
|
49
57
|
ShowShortcutHint = true;
|
|
@@ -82,11 +90,11 @@ export class SearchInputComponent {
|
|
|
82
90
|
// --- Public Methods ---
|
|
83
91
|
/** Programmatically focus the input element */
|
|
84
92
|
Focus() {
|
|
85
|
-
this.
|
|
93
|
+
this.InputRef?.nativeElement?.focus();
|
|
86
94
|
}
|
|
87
95
|
/** Clear the query and emit InputCleared */
|
|
88
96
|
Clear() {
|
|
89
|
-
this.
|
|
97
|
+
this._query = '';
|
|
90
98
|
this.queryInput$.next('');
|
|
91
99
|
this.QueryChange.emit('');
|
|
92
100
|
this.InputCleared.emit();
|
|
@@ -96,7 +104,7 @@ export class SearchInputComponent {
|
|
|
96
104
|
// --- Template event handlers ---
|
|
97
105
|
/** Handle native input event */
|
|
98
106
|
OnInput(value) {
|
|
99
|
-
this.
|
|
107
|
+
this._query = value;
|
|
100
108
|
this.queryInput$.next(value);
|
|
101
109
|
}
|
|
102
110
|
/** Handle keydown events on the input */
|
|
@@ -104,7 +112,7 @@ export class SearchInputComponent {
|
|
|
104
112
|
switch (event.key) {
|
|
105
113
|
case 'Enter':
|
|
106
114
|
event.preventDefault();
|
|
107
|
-
this.QuerySubmit.emit(this.
|
|
115
|
+
this.QuerySubmit.emit(this._query);
|
|
108
116
|
break;
|
|
109
117
|
case 'Escape':
|
|
110
118
|
event.preventDefault();
|
|
@@ -149,7 +157,7 @@ export class SearchInputComponent {
|
|
|
149
157
|
i0.ɵɵviewQuery(_c0, 5);
|
|
150
158
|
} if (rf & 2) {
|
|
151
159
|
let _t;
|
|
152
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.
|
|
160
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.InputRef = _t.first);
|
|
153
161
|
} }, inputs: { Placeholder: "Placeholder", Query: "Query", ShowShortcutHint: "ShowShortcutHint", ShortcutHint: "ShortcutHint", DebounceMs: "DebounceMs" }, outputs: { QueryChange: "QueryChange", QuerySubmit: "QuerySubmit", InputFocused: "InputFocused", InputBlurred: "InputBlurred", InputEscaped: "InputEscaped", InputCleared: "InputCleared" }, standalone: false, decls: 6, vars: 6, consts: [["inputEl", ""], [1, "search-input-container"], [1, "fa-solid", "fa-magnifying-glass", "search-input-icon"], ["type", "text", "autocomplete", "off", "spellcheck", "false", 1, "mj-input", "search-input-field", 3, "input", "keydown", "focus", "blur", "click", "placeholder", "value"], ["title", "Clear search", "aria-label", "Clear search", "type", "button", 1, "search-input-clear"], [1, "search-input-shortcut"], ["title", "Clear search", "aria-label", "Clear search", "type", "button", 1, "search-input-clear", 3, "click"], [1, "fa-solid", "fa-times"]], template: function SearchInputComponent_Template(rf, ctx) { if (rf & 1) {
|
|
154
162
|
i0.ɵɵelementStart(0, "div", 1);
|
|
155
163
|
i0.ɵɵelement(1, "i", 2);
|
|
@@ -172,7 +180,7 @@ export class SearchInputComponent {
|
|
|
172
180
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SearchInputComponent, [{
|
|
173
181
|
type: Component,
|
|
174
182
|
args: [{ standalone: false, selector: 'mj-search-input', template: "<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", styles: ["/* Search Input Component */\n\n.search-input-container {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.1rem 0.75rem;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n}\n\n.search-input-focused {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.search-input-icon {\n color: var(--mj-text-muted);\n font-size: 0.85rem;\n flex-shrink: 0;\n transition: color 0.15s ease;\n}\n\n.search-input-focused .search-input-icon {\n color: var(--mj-brand-primary);\n}\n\n.search-input-field {\n flex: 1;\n border: none !important;\n background: transparent !important;\n padding: 0.2rem 0 !important;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n outline: none !important;\n box-shadow: none !important;\n min-width: 0;\n}\n\n.search-input-field::placeholder {\n color: var(--mj-text-muted);\n}\n\n.search-input-clear {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 0.7rem;\n cursor: pointer;\n flex-shrink: 0;\n transition: background 0.1s ease, color 0.1s ease;\n}\n\n.search-input-clear:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.search-input-shortcut {\n display: inline-block;\n padding: 0.12rem 0.45rem;\n border-radius: 4px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n font-size: 0.7rem;\n font-family: inherit;\n flex-shrink: 0;\n line-height: 1.4;\n white-space: nowrap;\n}\n"] }]
|
|
175
|
-
}], null, {
|
|
183
|
+
}], null, { InputRef: [{
|
|
176
184
|
type: ViewChild,
|
|
177
185
|
args: ['inputEl']
|
|
178
186
|
}], Placeholder: [{
|
|
@@ -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, 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"]}
|
|
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 /** @deprecated Use {@link InputRef}. */\n get inputRef(): ElementRef<HTMLInputElement> {\n return this.InputRef;\n }\n /** @deprecated Use {@link InputRef}. */\n set inputRef(value: ElementRef<HTMLInputElement>) {\n this.InputRef = value;\n }\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"]}
|
|
@@ -34,7 +34,11 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
34
34
|
protected searchService: SearchService;
|
|
35
35
|
private destroy$;
|
|
36
36
|
private searchInput$;
|
|
37
|
-
|
|
37
|
+
SearchInputRef: ElementRef<HTMLInputElement>;
|
|
38
|
+
/** @deprecated Use {@link SearchInputRef}. */
|
|
39
|
+
get searchInputRef(): ElementRef<HTMLInputElement>;
|
|
40
|
+
/** @deprecated Use {@link SearchInputRef}. */
|
|
41
|
+
set searchInputRef(value: ElementRef<HTMLInputElement>);
|
|
38
42
|
/** Placeholder text for the search input */
|
|
39
43
|
Placeholder: string;
|
|
40
44
|
/**
|
|
@@ -46,7 +50,7 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
46
50
|
*/
|
|
47
51
|
MaxResults: number;
|
|
48
52
|
/** Whether the overlay is currently visible */
|
|
49
|
-
private
|
|
53
|
+
private _isOpen;
|
|
50
54
|
set IsOpen(value: boolean);
|
|
51
55
|
get IsOpen(): boolean;
|
|
52
56
|
/** Debounce time in ms before search fires */
|
|
@@ -197,10 +201,16 @@ export declare class SearchOverlayComponent implements OnInit, OnDestroy {
|
|
|
197
201
|
private onOverlayOpened;
|
|
198
202
|
private onOverlayClosed;
|
|
199
203
|
/** Check if any filters are active (used by template) */
|
|
204
|
+
HasActiveFilters(): boolean;
|
|
205
|
+
/** @deprecated Use {@link HasActiveFilters}. */
|
|
200
206
|
hasActiveFilters(): boolean;
|
|
201
207
|
/** Check if a result is currently keyboard-highlighted */
|
|
208
|
+
IsResultHighlighted(result: SearchResultItem): boolean;
|
|
209
|
+
/** @deprecated Use {@link IsResultHighlighted}. */
|
|
202
210
|
isResultHighlighted(result: SearchResultItem): boolean;
|
|
203
211
|
/** Get the flat index of a result for keyboard navigation */
|
|
212
|
+
GetFlatIndex(result: SearchResultItem): number;
|
|
213
|
+
/** @deprecated Use {@link GetFlatIndex}. */
|
|
204
214
|
getFlatIndex(result: SearchResultItem): number;
|
|
205
215
|
static ɵfac: i0.ɵɵFactoryDeclaration<SearchOverlayComponent, never>;
|
|
206
216
|
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>;
|
|
@@ -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;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACpC,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC;IAC7B,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,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;
|
|
1
|
+
{"version":3,"file":"search-overlay.component.d.ts","sourceRoot":"","sources":["../../src/lib/search-overlay.component.ts"],"names":[],"mappings":"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"}
|