@testgorilla/tgo-ui 7.3.0 → 7.4.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.
Files changed (40) hide show
  1. package/components/autocomplete-v2/autocomplete-overflow-detect.directive.d.ts +21 -0
  2. package/components/autocomplete-v2/autocomplete-v2-filter.service.d.ts +24 -0
  3. package/components/autocomplete-v2/autocomplete-v2-utils.d.ts +18 -0
  4. package/components/autocomplete-v2/autocomplete-v2-value-manager.d.ts +27 -0
  5. package/components/autocomplete-v2/autocomplete-v2.component.d.ts +119 -0
  6. package/components/autocomplete-v2/autocomplete-v2.model.d.ts +12 -0
  7. package/components/autocomplete-v2/index.d.ts +5 -0
  8. package/components/autocomplete-v2/infinite-scroll.directive.d.ts +21 -0
  9. package/components/autocomplete-v2/public-api.d.ts +7 -0
  10. package/components/core/directives/index.d.ts +2 -0
  11. package/components/core/directives/prevent-input.directive.d.ts +7 -0
  12. package/components/core/directives/select-text.directive.d.ts +10 -0
  13. package/components/core/pipes/includes.pipe.d.ts +7 -0
  14. package/components/core/pipes/index.d.ts +2 -0
  15. package/components/core/pipes/transform-item.pipe.d.ts +8 -0
  16. package/components/core/public-api.d.ts +2 -1
  17. package/components/validation-error/validation-error.component.d.ts +5 -1
  18. package/fesm2022/testgorilla-tgo-ui-components-autocomplete-v2.mjs +805 -0
  19. package/fesm2022/testgorilla-tgo-ui-components-autocomplete-v2.mjs.map +1 -0
  20. package/fesm2022/testgorilla-tgo-ui-components-autocomplete.mjs +1 -1
  21. package/fesm2022/testgorilla-tgo-ui-components-autocomplete.mjs.map +1 -1
  22. package/fesm2022/testgorilla-tgo-ui-components-checkbox.mjs +1 -1
  23. package/fesm2022/testgorilla-tgo-ui-components-checkbox.mjs.map +1 -1
  24. package/fesm2022/testgorilla-tgo-ui-components-core.mjs +123 -28
  25. package/fesm2022/testgorilla-tgo-ui-components-core.mjs.map +1 -1
  26. package/fesm2022/testgorilla-tgo-ui-components-datepicker.mjs +1 -1
  27. package/fesm2022/testgorilla-tgo-ui-components-datepicker.mjs.map +1 -1
  28. package/fesm2022/testgorilla-tgo-ui-components-dropdown.mjs +1 -1
  29. package/fesm2022/testgorilla-tgo-ui-components-dropdown.mjs.map +1 -1
  30. package/fesm2022/testgorilla-tgo-ui-components-field.mjs +1 -1
  31. package/fesm2022/testgorilla-tgo-ui-components-field.mjs.map +1 -1
  32. package/fesm2022/testgorilla-tgo-ui-components-multi-input.mjs +1 -1
  33. package/fesm2022/testgorilla-tgo-ui-components-multi-input.mjs.map +1 -1
  34. package/fesm2022/testgorilla-tgo-ui-components-phone-input.mjs +1 -1
  35. package/fesm2022/testgorilla-tgo-ui-components-phone-input.mjs.map +1 -1
  36. package/fesm2022/testgorilla-tgo-ui-components-validation-error.mjs +21 -3
  37. package/fesm2022/testgorilla-tgo-ui-components-validation-error.mjs.map +1 -1
  38. package/mcp/catalog.json +1 -1
  39. package/package.json +26 -22
  40. package/components/core/select-text.directive.d.ts +0 -19
@@ -0,0 +1,805 @@
1
+ import { FocusMonitor } from '@angular/cdk/a11y';
2
+ import { CdkVirtualScrollViewport, CdkVirtualForOf, CdkFixedSizeVirtualScroll } from '@angular/cdk/scrolling';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i0 from '@angular/core';
6
+ import { signal, Injectable, computed, inject, DestroyRef, input, ElementRef, NgZone, Directive, booleanAttribute, output, ChangeDetectorRef, effect, isDevMode, untracked, ViewChild, ChangeDetectionStrategy, Component } from '@angular/core';
7
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
8
+ import * as i2 from '@angular/forms';
9
+ import { NgControl, FormsModule } from '@angular/forms';
10
+ import * as i3 from '@angular/material/autocomplete';
11
+ import { MatAutocompleteModule } from '@angular/material/autocomplete';
12
+ import { MatChipsModule } from '@angular/material/chips';
13
+ import * as i4 from '@angular/material/form-field';
14
+ import { MatFormFieldModule } from '@angular/material/form-field';
15
+ import * as i5 from '@angular/material/input';
16
+ import { MatInputModule } from '@angular/material/input';
17
+ import * as i10 from '@angular/material/tooltip';
18
+ import { MatTooltipModule } from '@angular/material/tooltip';
19
+ import { IKeyboardEvent, PreventInputDirective, UiTranslatePipe, TransformItemPipe, IncludesPipe, SelectTextDirective } from '@testgorilla/tgo-ui/components/core';
20
+ import * as i7 from '@testgorilla/tgo-ui/components/icon';
21
+ import { IconComponentModule } from '@testgorilla/tgo-ui/components/icon';
22
+ import * as i8 from '@testgorilla/tgo-ui/components/spinner';
23
+ import { SpinnerComponentModule } from '@testgorilla/tgo-ui/components/spinner';
24
+ import * as i6 from '@testgorilla/tgo-ui/components/tag';
25
+ import { TagComponentModule } from '@testgorilla/tgo-ui/components/tag';
26
+ import * as i9 from '@testgorilla/tgo-ui/components/validation-error';
27
+ import { ValidationErrorModule } from '@testgorilla/tgo-ui/components/validation-error';
28
+ import { BehaviorSubject, ReplaySubject, map, startWith, filter, throttleTime } from 'rxjs';
29
+
30
+ class AutocompleteV2Utils {
31
+ static transformDisplayValue(value, textField) {
32
+ return value?.[textField] ?? '';
33
+ }
34
+ static filterItems(items, inputValue, textField) {
35
+ return items.filter(item => {
36
+ const text = item[textField];
37
+ return typeof text === 'string' && text.toLowerCase().includes(inputValue.toLowerCase());
38
+ });
39
+ }
40
+ static filterGroupedItems(groups, inputValue, textField) {
41
+ return groups
42
+ .map(group => ({
43
+ ...group,
44
+ filteredItems: AutocompleteV2Utils.filterItems(group.items, inputValue, textField),
45
+ }))
46
+ .filter(group => group.filteredItems.length > 0);
47
+ }
48
+ static excludeSuggestions(items, excludeItems, valueField) {
49
+ if (!valueField || !excludeItems.length)
50
+ return items ?? [];
51
+ return (items ?? []).filter(item => !excludeItems.find(exclude => exclude[valueField] === item[valueField]));
52
+ }
53
+ static createValueItem(value, textField, valueField) {
54
+ if (typeof value === 'string') {
55
+ return { [textField]: value, [valueField]: value };
56
+ }
57
+ return value;
58
+ }
59
+ static findDuplicate(items, selectedValue, lookupKey) {
60
+ return items.find(v => (lookupKey ? v[lookupKey] === selectedValue[lookupKey] : v === selectedValue));
61
+ }
62
+ static isArray(value) {
63
+ return Array.isArray(value);
64
+ }
65
+ }
66
+
67
+ class AutocompleteFilterService {
68
+ constructor() {
69
+ // Configuration
70
+ this.textField = signal('');
71
+ // Data sources (fed by component via effects)
72
+ this.flatItems = signal([]);
73
+ this.groupsList = signal([]);
74
+ this.suggestions = signal([]);
75
+ // Search state
76
+ this.searchText$ = new BehaviorSubject('');
77
+ this.userInput$ = new ReplaySubject(1);
78
+ this.isSearching$ = this.searchText$.pipe(map(v => !!v.trim()));
79
+ // Dynamic filtering
80
+ this.dynamicSource$ = new BehaviorSubject(null);
81
+ this.isDynamicMode = false;
82
+ // Filtered results
83
+ this.filteredItems$ = this.searchText$.pipe(startWith(''), map(inputValue => {
84
+ if (!inputValue.length)
85
+ return null;
86
+ return AutocompleteV2Utils.filterItems(this.flatItems(), inputValue, this.textField());
87
+ }));
88
+ this.filteredGroupedItems$ = this.searchText$.pipe(startWith(''), map(inputValue => {
89
+ if (!inputValue.length || !this.groupsList().length)
90
+ return null;
91
+ return AutocompleteV2Utils.filterGroupedItems(this.groupsList(), inputValue, this.textField());
92
+ }));
93
+ this.filteredSuggestions$ = this.searchText$.pipe(map(inputValue => inputValue.length ? AutocompleteV2Utils.filterItems(this.suggestions(), inputValue, this.textField()) : null));
94
+ }
95
+ search(text, minChars) {
96
+ this.userInput$.next(text);
97
+ if (text.length >= minChars) {
98
+ this.searchText$.next(text);
99
+ }
100
+ else {
101
+ this.searchText$.next('');
102
+ this.userInput$.next('');
103
+ }
104
+ }
105
+ clearSearch() {
106
+ this.searchText$.next('');
107
+ this.userInput$.next('');
108
+ }
109
+ ngOnDestroy() {
110
+ this.searchText$.complete();
111
+ this.userInput$.complete();
112
+ this.dynamicSource$.complete();
113
+ }
114
+ setDynamicResults(list, loading) {
115
+ if ((list !== null || loading) && !this.isDynamicMode) {
116
+ this.isDynamicMode = true;
117
+ this.filteredItems$ = this.dynamicSource$;
118
+ }
119
+ if (list !== null) {
120
+ this.dynamicSource$.next(list);
121
+ }
122
+ else if (loading) {
123
+ this.dynamicSource$.next([]);
124
+ }
125
+ }
126
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteFilterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
127
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteFilterService }); }
128
+ }
129
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteFilterService, decorators: [{
130
+ type: Injectable
131
+ }] });
132
+
133
+ var Autocomplete;
134
+ (function (Autocomplete) {
135
+ Autocomplete["SINGLE"] = "single";
136
+ Autocomplete["MULTI"] = "multi";
137
+ Autocomplete["LARGE"] = "large";
138
+ })(Autocomplete || (Autocomplete = {}));
139
+ var DropdownVariation;
140
+ (function (DropdownVariation) {
141
+ DropdownVariation["AUTOCOMPLETE"] = "autocomplete";
142
+ DropdownVariation["DROPDOWN"] = "dropdown";
143
+ })(DropdownVariation || (DropdownVariation = {}));
144
+
145
+ class AutocompleteValueManager {
146
+ constructor() {
147
+ // ── Configuration signals (set by the component via effects) ────────────────
148
+ this.type = signal('multi');
149
+ this.textField = signal('');
150
+ this.valueField = signal('');
151
+ this.compareWith = signal(undefined);
152
+ // ── Value signal ─────────────────────────────────────────────────────────────
153
+ this.value = signal(null);
154
+ // ── Derived ──────────────────────────────────────────────────────────────────
155
+ this.isSingle = computed(() => this.type() === Autocomplete.SINGLE);
156
+ this.displayValue = computed(() => {
157
+ const type = this.type();
158
+ const value = this.value();
159
+ const textField = this.textField();
160
+ const isSingle = type === Autocomplete.SINGLE;
161
+ const isEmpty = !value || (AutocompleteV2Utils.isArray(value) && !value.length);
162
+ if (isEmpty)
163
+ return '';
164
+ if (isSingle) {
165
+ const display = AutocompleteV2Utils.isArray(value) ? value[0] : value;
166
+ return AutocompleteV2Utils.transformDisplayValue(display, textField);
167
+ }
168
+ // Multi with values — space placeholder (tags are visible instead)
169
+ return ' ';
170
+ });
171
+ // ── CVA callbacks ────────────────────────────────────────────────────────────
172
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
173
+ this.onChangeFn = () => { };
174
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
175
+ this.onTouchedFn = () => { };
176
+ }
177
+ registerOnChange(fn) {
178
+ this.onChangeFn = fn;
179
+ }
180
+ registerOnTouched(fn) {
181
+ this.onTouchedFn = fn;
182
+ }
183
+ notifyChange() {
184
+ this.onChangeFn(this.value());
185
+ }
186
+ markAsTouched() {
187
+ this.onTouchedFn();
188
+ }
189
+ writeValue(v) {
190
+ if (v == null) {
191
+ this.value.set(this.isSingle() ? null : []);
192
+ }
193
+ else {
194
+ this.value.set(v);
195
+ }
196
+ }
197
+ // ── Selection ─────────────────────────────────────────────────────────────────
198
+ addValue(newValue) {
199
+ if (!this.isSingle() && !this.value()) {
200
+ this.value.set([]);
201
+ }
202
+ const compareWith = this.compareWith();
203
+ const currentArray = AutocompleteV2Utils.isArray(this.value()) ? this.value() : [];
204
+ const foundDuplicate = compareWith
205
+ ? currentArray.find((v) => compareWith(v, newValue))
206
+ : AutocompleteV2Utils.findDuplicate(currentArray, newValue, this.textField());
207
+ if (!this.isSingle()) {
208
+ this.value.set(foundDuplicate
209
+ ? currentArray.filter((v) => (compareWith ? !compareWith(v, foundDuplicate) : v !== foundDuplicate))
210
+ : [...currentArray, newValue]);
211
+ }
212
+ else {
213
+ this.value.set(newValue);
214
+ }
215
+ }
216
+ /**
217
+ * Removes `option` from the value array.
218
+ * Returns the found item (so the caller can deselect the mat-option), or undefined if not found.
219
+ */
220
+ removeValue(option) {
221
+ const compareWith = this.compareWith();
222
+ const currentValue = AutocompleteV2Utils.isArray(this.value()) ? this.value() : [];
223
+ const foundValue = currentValue.find((v) => (compareWith ? compareWith(v, option) : v === option));
224
+ if (foundValue) {
225
+ this.value.set(currentValue.filter((v) => (compareWith ? !compareWith(v, option) : v !== option)));
226
+ }
227
+ return foundValue;
228
+ }
229
+ clear() {
230
+ this.value.set(AutocompleteV2Utils.isArray(this.value()) ? [] : null);
231
+ }
232
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteValueManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
233
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteValueManager }); }
234
+ }
235
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteValueManager, decorators: [{
236
+ type: Injectable
237
+ }] });
238
+
239
+ class InfiniteScrollDirective {
240
+ constructor() {
241
+ this.viewport = null;
242
+ this.scrollSub = null;
243
+ this.destroyRef = inject(DestroyRef);
244
+ this.scrollListener = (event) => {
245
+ const target = event.target;
246
+ const trigger = this.panelTrigger;
247
+ if (!trigger)
248
+ return;
249
+ const isNotAutocompleteScroll = !target?.id?.includes('mat-autocomplete-') &&
250
+ !target?.parentElement?.id?.includes('mat-autocomplete-') &&
251
+ !target?.classList?.contains('mat-mdc-autocomplete-trigger');
252
+ if (trigger.panelOpen && isNotAutocompleteScroll) {
253
+ trigger.closePanel();
254
+ }
255
+ };
256
+ this.enabled = false;
257
+ this.closeOnScroll = false;
258
+ this.panelTrigger = null;
259
+ this.onBottomReached = null;
260
+ }
261
+ attachViewport(viewport) {
262
+ this.detachViewport();
263
+ if (!viewport)
264
+ return;
265
+ this.viewport = viewport;
266
+ if (this.enabled) {
267
+ this.scrollSub = viewport
268
+ .elementScrolled()
269
+ .pipe(map(() => viewport.measureScrollOffset('bottom')), filter(offset => offset < viewport.getViewportSize() * 0.2), throttleTime(200), takeUntilDestroyed(this.destroyRef))
270
+ .subscribe(() => {
271
+ this.onBottomReached?.();
272
+ });
273
+ }
274
+ }
275
+ detachViewport() {
276
+ this.scrollSub?.unsubscribe();
277
+ this.scrollSub = null;
278
+ this.viewport = null;
279
+ }
280
+ scrollToTop() {
281
+ if (this.viewport) {
282
+ this.viewport.scrollToIndex(0);
283
+ this.viewport.checkViewportSize();
284
+ }
285
+ }
286
+ startCloseOnScroll() {
287
+ if (this.closeOnScroll) {
288
+ window.addEventListener('scroll', this.scrollListener, true);
289
+ }
290
+ }
291
+ ngOnDestroy() {
292
+ this.detachViewport();
293
+ window.removeEventListener('scroll', this.scrollListener, true);
294
+ }
295
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: InfiniteScrollDirective, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
296
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: InfiniteScrollDirective }); }
297
+ }
298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: InfiniteScrollDirective, decorators: [{
299
+ type: Injectable
300
+ }] });
301
+
302
+ class AutocompleteOverflowDetectDirective {
303
+ constructor() {
304
+ this.measureContainer = input(undefined);
305
+ this.itemSelector = input('.value-tag');
306
+ this.reserveWidth = input(100);
307
+ this.visibleCount = signal(Infinity);
308
+ this.overflowCount = signal(0);
309
+ this.hasMeasured = signal(false);
310
+ this.tagMaxWidth = signal(null);
311
+ this.resizeObserver = null;
312
+ this.rafId = null;
313
+ this.el = inject(ElementRef);
314
+ this.ngZone = inject(NgZone);
315
+ }
316
+ ngAfterViewInit() {
317
+ // Self-measure when the directive enters the DOM (e.g., after @if condition becomes true)
318
+ this.measure();
319
+ }
320
+ setupObserver(containerSelector) {
321
+ const parentContainer = this.el.nativeElement.closest(containerSelector);
322
+ if (!parentContainer || typeof ResizeObserver === 'undefined')
323
+ return;
324
+ this.resizeObserver = new ResizeObserver(() => {
325
+ this.ngZone.run(() => this.measure());
326
+ });
327
+ this.resizeObserver.observe(parentContainer);
328
+ }
329
+ measure() {
330
+ const container = this.measureContainer();
331
+ if (!container)
332
+ return;
333
+ this.rafId = requestAnimationFrame(() => {
334
+ const infix = container.closest('.mat-mdc-form-field-infix');
335
+ if (!infix)
336
+ return; // Can't measure yet — stay hidden until next attempt
337
+ const tags = Array.from(container.querySelectorAll(this.itemSelector()));
338
+ if (!tags.length) {
339
+ this.visibleCount.set(Infinity);
340
+ this.hasMeasured.set(true);
341
+ this.overflowCount.set(0);
342
+ return;
343
+ }
344
+ // Measure actual icon widths (clear button + chevron) that share the form field space
345
+ const formField = container.closest('mat-form-field');
346
+ let iconsWidth = 0;
347
+ if (formField) {
348
+ formField.querySelectorAll('.remove-selected, .arrow-state').forEach((icon) => {
349
+ iconsWidth += icon.getBoundingClientRect().width;
350
+ });
351
+ }
352
+ const inputReserve = 48;
353
+ const counterWidth = 52;
354
+ const availableWidth = infix.getBoundingClientRect().width - inputReserve - iconsWidth;
355
+ let totalWidth = 0;
356
+ let visibleCount = tags.length;
357
+ for (let i = 0; i < tags.length; i++) {
358
+ totalWidth += tags[i].getBoundingClientRect().width;
359
+ const remainingTags = tags.length - (i + 1);
360
+ const spaceForCounter = remainingTags > 0 ? counterWidth : 0;
361
+ if (totalWidth + spaceForCounter > availableWidth && i > 0) {
362
+ visibleCount = i;
363
+ break;
364
+ }
365
+ }
366
+ const total = container.querySelectorAll(this.itemSelector()).length;
367
+ const visible = Math.min(visibleCount, total);
368
+ const overflow = Math.max(0, total - visible);
369
+ // Compute max width for each tag so wide tags truncate with ellipsis
370
+ // Single tag: full available width. Multiple visible: account for counter width.
371
+ const padding = overflow >= 10 ? 16 : 8;
372
+ this.tagMaxWidth.set(visible === 1 ? availableWidth - padding : availableWidth - (overflow > 0 ? counterWidth : 0) - padding);
373
+ this.visibleCount.set(visibleCount);
374
+ this.hasMeasured.set(true);
375
+ this.overflowCount.set(overflow);
376
+ });
377
+ }
378
+ ngOnDestroy() {
379
+ this.resizeObserver?.disconnect();
380
+ if (this.rafId !== null) {
381
+ cancelAnimationFrame(this.rafId);
382
+ }
383
+ }
384
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteOverflowDetectDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
385
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.20", type: AutocompleteOverflowDetectDirective, isStandalone: true, selector: "[uiAutocompleteOverflowDetect]", inputs: { measureContainer: { classPropertyName: "measureContainer", publicName: "measureContainer", isSignal: true, isRequired: false, transformFunction: null }, itemSelector: { classPropertyName: "itemSelector", publicName: "itemSelector", isSignal: true, isRequired: false, transformFunction: null }, reserveWidth: { classPropertyName: "reserveWidth", publicName: "reserveWidth", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["autocompleteOverflowDetect"], ngImport: i0 }); }
386
+ }
387
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteOverflowDetectDirective, decorators: [{
388
+ type: Directive,
389
+ args: [{
390
+ selector: '[uiAutocompleteOverflowDetect]',
391
+ standalone: true,
392
+ exportAs: 'autocompleteOverflowDetect',
393
+ }]
394
+ }] });
395
+
396
+ /* eslint-disable no-underscore-dangle */
397
+ class AutocompleteV2Component {
398
+ set cdkViewport(viewport) {
399
+ // Ensure enabled is set before attaching (ViewChild resolves before ngAfterViewInit)
400
+ this.scrollManager.enabled = this.infiniteScroll();
401
+ this.scrollManager.attachViewport(viewport);
402
+ }
403
+ constructor() {
404
+ // ── Inputs ──────────────────────────────────────────────────────────────────
405
+ this.itemsList = input([]);
406
+ this.suggestionsList = input([]);
407
+ this.groupsList = input([]);
408
+ this.disabled = input(false);
409
+ this.allowAdd = input(true);
410
+ this.textField = input('');
411
+ this.valueField = input('');
412
+ this.label = input('');
413
+ this.placeholder = input('');
414
+ this.type = input('multi');
415
+ this.minCharactersSearch = input(3);
416
+ this.variant = input.required();
417
+ this.showBottomContent = input(true);
418
+ this.required = input(undefined);
419
+ this.virtualScroll = input(false, { transform: booleanAttribute });
420
+ this.compareWith = input(undefined);
421
+ this.dropdownPanelClass = input('');
422
+ this.closeOnScroll = input(false);
423
+ this.size = input('medium');
424
+ this.allowUserInput = input(true);
425
+ this.clearable = input(true);
426
+ this.maxLength = input(undefined);
427
+ this.dynamicFilterLoading = input(false);
428
+ this.dynamicFilteredList = input(null);
429
+ this.infiniteScroll = input(false);
430
+ this.hasMoreOptionsForInfiniteScroll = input(true);
431
+ this.itemValue = input(null);
432
+ this.formErrorConfig = input({});
433
+ this.errors = input([]);
434
+ // ── Outputs ─────────────────────────────────────────────────────────────────
435
+ this.selectionChange = output();
436
+ this.searchTextChange = output();
437
+ this.blur = output();
438
+ this.focus = output();
439
+ this.scrollViewportBottomReached = output();
440
+ this.scrollViewportBottomReachedFiltered = output();
441
+ // ── Injected services ──────────────────────────────────────────────────────
442
+ this.valueManager = inject((AutocompleteValueManager));
443
+ this.filterService = inject((AutocompleteFilterService));
444
+ this.scrollManager = inject(InfiniteScrollDirective);
445
+ this.cdr = inject(ChangeDetectorRef);
446
+ this.focusMonitor = inject(FocusMonitor);
447
+ this.destroyRef = inject(DestroyRef);
448
+ this.ngZone = inject(NgZone);
449
+ this.ngControl = inject(NgControl, { optional: true, self: true });
450
+ this.applicationTheme = inject('CANOPYUI_DEFAULT_APPLICATION_THEME', { optional: true }) ?? 'light';
451
+ // ── Internal state ──────────────────────────────────────────────────────────
452
+ this.inputValue = signal('');
453
+ this.isInputFocus = signal(false);
454
+ this.autocompleteType = Autocomplete;
455
+ /** Flat list for default (ungrouped) rendering and virtual scroll */
456
+ this.flatItemsList = computed(() => {
457
+ const suggestions = this.suggestionsList();
458
+ const valField = this.valueField();
459
+ const flat = AutocompleteV2Utils.excludeSuggestions(this.itemsList(), suggestions, valField);
460
+ const grouped = this.groupsList().flatMap(g => AutocompleteV2Utils.excludeSuggestions(g.items, suggestions, valField));
461
+ return [...flat, ...grouped];
462
+ });
463
+ /** Grouped list — only used when isGrouped is true */
464
+ this.groupedItemsList = computed(() => {
465
+ const suggestions = this.suggestionsList();
466
+ const valField = this.valueField();
467
+ return this.groupsList().map(group => ({
468
+ groupName: group.groupName,
469
+ items: AutocompleteV2Utils.excludeSuggestions(group.items, suggestions, valField),
470
+ }));
471
+ });
472
+ this._isDisabled = signal(false);
473
+ this.translationContext = 'AUTOCOMPLETE.';
474
+ this.utils = AutocompleteV2Utils;
475
+ this.keyboardFocused = signal(false);
476
+ this.isAlreadyAdded = computed(() => {
477
+ const compareWith = this.compareWith();
478
+ const val = this.valueManager.value();
479
+ const input = this.inputValue();
480
+ if (!input || input === ' ')
481
+ return false;
482
+ const valArray = AutocompleteV2Utils.isArray(val) ? val : [];
483
+ return !!(compareWith
484
+ ? valArray.find((v) => compareWith(v, input))
485
+ : AutocompleteV2Utils.findDuplicate(valArray, input, this.textField()));
486
+ });
487
+ this.showClearButton = computed(() => {
488
+ const type = this.type();
489
+ const val = this.valueManager.value();
490
+ if (type === Autocomplete.SINGLE) {
491
+ return this.clearable() && (val?.length || (val ? !!Object.keys(val).length : false));
492
+ }
493
+ return val && val.length > 1;
494
+ });
495
+ this.safeErrors = computed(() => this.errors()?.filter(Boolean) ?? []);
496
+ this.controlInvalid = signal(false);
497
+ this.hasError = computed(() => {
498
+ if (this.ngControl) {
499
+ return this.controlInvalid();
500
+ }
501
+ return this.safeErrors().length > 0;
502
+ });
503
+ this.hiddenItemsTooltip = computed(() => {
504
+ const value = this.valueManager.value();
505
+ const visibleCount = this.overflowDir?.visibleCount() ?? Infinity;
506
+ if (!AutocompleteV2Utils.isArray(value))
507
+ return '';
508
+ const tf = this.textField();
509
+ return value
510
+ .slice(visibleCount)
511
+ .map(item => (tf ? item[tf] : item))
512
+ .join('\n');
513
+ });
514
+ this.trackByFn = (index, value) => value;
515
+ this.trackByItem = (_index, item) => {
516
+ const vf = this.valueField();
517
+ return vf ? item?.[vf] : item;
518
+ };
519
+ // Assign valueAccessor manually to avoid circular DI
520
+ // (providing NG_VALUE_ACCESSOR + injecting NgControl creates a cycle)
521
+ if (this.ngControl) {
522
+ this.ngControl.valueAccessor = this;
523
+ }
524
+ effect(() => {
525
+ this.filterService.setDynamicResults(this.dynamicFilteredList(), this.dynamicFilterLoading());
526
+ });
527
+ effect(() => {
528
+ this._isDisabled.set(this.disabled());
529
+ });
530
+ effect(() => this.valueManager.type.set(this.type()));
531
+ effect(() => this.valueManager.textField.set(this.textField()));
532
+ effect(() => this.valueManager.valueField.set(this.valueField()));
533
+ effect(() => this.valueManager.compareWith.set(this.compareWith()));
534
+ effect(() => this.filterService.textField.set(this.textField()));
535
+ effect(() => this.filterService.flatItems.set(this.flatItemsList()));
536
+ effect(() => this.filterService.groupsList.set(this.groupsList()));
537
+ effect(() => this.filterService.suggestions.set(this.suggestionsList()));
538
+ effect(() => {
539
+ const v = this.itemValue();
540
+ // In CVA mode, writeValue() owns the value — itemValue should not override it
541
+ if (this.ngControl) {
542
+ if (isDevMode() && v !== null) {
543
+ console.warn('[ui-autocomplete-v2] [itemValue] is set alongside a form control. ' + 'Use ngModel or formControl instead.');
544
+ }
545
+ return;
546
+ }
547
+ this.valueManager.value.set(AutocompleteV2Utils.isArray(v) ? v : v ? [v] : []);
548
+ untracked(() => {
549
+ this.inputValue.set(this.valueManager.displayValue());
550
+ });
551
+ this.cdr.markForCheck();
552
+ });
553
+ effect(() => {
554
+ this.valueManager.value(); // track value changes
555
+ untracked(() => {
556
+ if (this.type() !== Autocomplete.LARGE) {
557
+ this.overflowDir?.measure();
558
+ }
559
+ });
560
+ });
561
+ }
562
+ /**
563
+ * Used to mark component view as dirty when touched programmatically with markAsTouched/markAllAsTouched or errors
564
+ * to display validation errors that might happen (e.g. required)
565
+ */
566
+ ngDoCheck() {
567
+ if (this.ngControl) {
568
+ const invalid = !!(this.ngControl.invalid && this.ngControl.touched);
569
+ if (this.controlInvalid() !== invalid) {
570
+ this.controlInvalid.set(invalid);
571
+ }
572
+ if (this.ngControl.touched || this.ngControl.errors) {
573
+ this.cdr.markForCheck();
574
+ }
575
+ }
576
+ }
577
+ ngAfterViewInit() {
578
+ // Set default hover color for the autocomplete panel (overlay is outside component scope)
579
+ if (!document.body.style.getPropertyValue('--ui-autocomplete-option-color')) {
580
+ document.body.style.setProperty('--ui-autocomplete-option-color', '#FFF2FC');
581
+ }
582
+ if (this.type() !== Autocomplete.LARGE) {
583
+ this.overflowDir?.setupObserver('.input-container');
584
+ }
585
+ this.scrollManager.enabled = this.infiniteScroll();
586
+ this.scrollManager.closeOnScroll = this.closeOnScroll();
587
+ this.scrollManager.panelTrigger = this.autocomplete;
588
+ this.scrollManager.onBottomReached = () => this.onScrollBottom();
589
+ this.scrollManager.startCloseOnScroll();
590
+ this.focusMonitor
591
+ .monitor(this.matInput)
592
+ .pipe(takeUntilDestroyed(this.destroyRef))
593
+ .subscribe(origin => this.ngZone.run(() => {
594
+ this.keyboardFocused.set(origin === 'keyboard');
595
+ }));
596
+ this.matInput.nativeElement.onkeydown = this.onKeydown.bind(this);
597
+ }
598
+ ngOnDestroy() {
599
+ this.scrollManager.ngOnDestroy();
600
+ this.focusMonitor.stopMonitoring(this.matInput);
601
+ if (this.matInput?.nativeElement) {
602
+ this.matInput.nativeElement.onkeydown = null;
603
+ }
604
+ }
605
+ registerOnChange(fn) {
606
+ this.valueManager.registerOnChange(fn);
607
+ }
608
+ registerOnTouched(fn) {
609
+ this.valueManager.registerOnTouched(fn);
610
+ }
611
+ setDisabledState(isDisabled) {
612
+ this._isDisabled.set(isDisabled);
613
+ this.cdr.markForCheck();
614
+ }
615
+ writeValue(value) {
616
+ this.valueManager.writeValue(value);
617
+ this.inputValue.set(this.valueManager.displayValue());
618
+ this.cdr.markForCheck();
619
+ }
620
+ get isGrouped() {
621
+ return this.groupsList().length > 0;
622
+ }
623
+ onOptionSelected(event) {
624
+ const inputValue = event.option.value;
625
+ const itemValue = AutocompleteV2Utils.createValueItem(inputValue, this.textField(), this.valueField());
626
+ this.valueManager.addValue(itemValue);
627
+ queueMicrotask(() => {
628
+ if (this.type() !== this.autocompleteType.SINGLE) {
629
+ // Multi: clear input so tags are visible while focused
630
+ this.inputValue.set('');
631
+ }
632
+ else {
633
+ this.inputValue.set(this.valueManager.displayValue());
634
+ }
635
+ this.cdr.markForCheck();
636
+ });
637
+ this.onUpdate();
638
+ this.valueManager.markAsTouched();
639
+ }
640
+ onOptionRemoved(option) {
641
+ setTimeout(() => this.autocomplete.closePanel(), 0);
642
+ const foundValue = this.valueManager.removeValue(option);
643
+ if (foundValue) {
644
+ this.matAutocomplete.options.forEach(matOption => {
645
+ const vf = this.valueField();
646
+ if (vf && matOption.value?.[vf] === foundValue[vf]) {
647
+ matOption.deselect();
648
+ }
649
+ });
650
+ }
651
+ if (!this.valueManager.value()?.length) {
652
+ this.inputValue.set('');
653
+ }
654
+ this.onUpdate();
655
+ this.valueManager.markAsTouched();
656
+ }
657
+ onInputChange(event) {
658
+ const text = event.target.value;
659
+ this.filterService.search(text, this.minCharactersSearch());
660
+ if (text.length >= this.minCharactersSearch()) {
661
+ this.searchTextChange.emit(text);
662
+ }
663
+ }
664
+ onClear() {
665
+ this.inputValue.set('');
666
+ this.valueManager.clear();
667
+ this.onUpdate();
668
+ this.matAutocomplete?.options.forEach(option => option.deselect());
669
+ this.valueManager.markAsTouched();
670
+ }
671
+ onBlur() {
672
+ setTimeout(() => {
673
+ this.filterService.clearSearch();
674
+ this.isInputFocus.set(false);
675
+ this.inputValue.set(this.valueManager.displayValue());
676
+ this.valueManager.markAsTouched();
677
+ this.blur.emit();
678
+ this.cdr.markForCheck();
679
+ }, 0);
680
+ }
681
+ onPanelOpened() {
682
+ this.scrollManager.scrollToTop();
683
+ }
684
+ onScrollBottom() {
685
+ if (this.filterService.searchText$.value) {
686
+ this.scrollViewportBottomReachedFiltered.emit();
687
+ }
688
+ else {
689
+ this.scrollViewportBottomReached.emit();
690
+ }
691
+ }
692
+ onFocus() {
693
+ this.isInputFocus.set(true);
694
+ const val = this.inputValue();
695
+ if (typeof val === 'string' && val.match(/^\s+/gm)) {
696
+ this.inputValue.set(val.trimStart());
697
+ }
698
+ this.focus.emit();
699
+ }
700
+ onUpdate() {
701
+ this.filterService.clearSearch();
702
+ this.valueManager.notifyChange();
703
+ const val = this.valueManager.value();
704
+ if (val !== null) {
705
+ this.selectionChange.emit(val);
706
+ }
707
+ }
708
+ get isDropdown() {
709
+ return this.variant() === DropdownVariation.DROPDOWN;
710
+ }
711
+ onChevronClick(autocomplete) {
712
+ if (autocomplete.isOpen) {
713
+ setTimeout(() => {
714
+ this.autocomplete.closePanel();
715
+ }, 0);
716
+ }
717
+ }
718
+ onKeydown($event) {
719
+ const optionHeight = 48;
720
+ if ($event.key === IKeyboardEvent.HOME) {
721
+ this.matAutocomplete._keyManager.setFirstItemActive();
722
+ }
723
+ else if ($event.key === IKeyboardEvent.END) {
724
+ this.matAutocomplete._keyManager.setLastItemActive();
725
+ }
726
+ else if ($event.key === IKeyboardEvent.PAGE_DOWN) {
727
+ this.matAutocomplete._keyManager.setNextItemActive();
728
+ this.matAutocomplete._keyManager.setNextItemActive();
729
+ this.matAutocomplete._keyManager.setNextItemActive();
730
+ }
731
+ else if ($event.key === IKeyboardEvent.PAGE_UP) {
732
+ this.matAutocomplete._keyManager.setPreviousItemActive();
733
+ this.matAutocomplete._keyManager.setPreviousItemActive();
734
+ this.matAutocomplete._keyManager.setPreviousItemActive();
735
+ }
736
+ this.matAutocomplete._setScrollTop((this.matAutocomplete._keyManager.activeItemIndex ?? 0) * optionHeight);
737
+ }
738
+ getVirtualScrollHeight(itemCount) {
739
+ const itemHeight = 48;
740
+ const maxHeight = 200;
741
+ const minHeight = 48;
742
+ const calculatedHeight = itemCount * itemHeight;
743
+ return Math.min(Math.max(calculatedHeight, minHeight), maxHeight);
744
+ }
745
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteV2Component, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
746
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: AutocompleteV2Component, isStandalone: true, selector: "ui-autocomplete-v2", inputs: { itemsList: { classPropertyName: "itemsList", publicName: "itemsList", isSignal: true, isRequired: false, transformFunction: null }, suggestionsList: { classPropertyName: "suggestionsList", publicName: "suggestionsList", isSignal: true, isRequired: false, transformFunction: null }, groupsList: { classPropertyName: "groupsList", publicName: "groupsList", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, allowAdd: { classPropertyName: "allowAdd", publicName: "allowAdd", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, minCharactersSearch: { classPropertyName: "minCharactersSearch", publicName: "minCharactersSearch", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: true, transformFunction: null }, showBottomContent: { classPropertyName: "showBottomContent", publicName: "showBottomContent", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, dropdownPanelClass: { classPropertyName: "dropdownPanelClass", publicName: "dropdownPanelClass", isSignal: true, isRequired: false, transformFunction: null }, closeOnScroll: { classPropertyName: "closeOnScroll", publicName: "closeOnScroll", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, allowUserInput: { classPropertyName: "allowUserInput", publicName: "allowUserInput", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, dynamicFilterLoading: { classPropertyName: "dynamicFilterLoading", publicName: "dynamicFilterLoading", isSignal: true, isRequired: false, transformFunction: null }, dynamicFilteredList: { classPropertyName: "dynamicFilteredList", publicName: "dynamicFilteredList", isSignal: true, isRequired: false, transformFunction: null }, infiniteScroll: { classPropertyName: "infiniteScroll", publicName: "infiniteScroll", isSignal: true, isRequired: false, transformFunction: null }, hasMoreOptionsForInfiniteScroll: { classPropertyName: "hasMoreOptionsForInfiniteScroll", publicName: "hasMoreOptionsForInfiniteScroll", isSignal: true, isRequired: false, transformFunction: null }, itemValue: { classPropertyName: "itemValue", publicName: "itemValue", isSignal: true, isRequired: false, transformFunction: null }, formErrorConfig: { classPropertyName: "formErrorConfig", publicName: "formErrorConfig", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", searchTextChange: "searchTextChange", blur: "blur", focus: "focus", scrollViewportBottomReached: "scrollViewportBottomReached", scrollViewportBottomReachedFiltered: "scrollViewportBottomReachedFiltered" }, host: { properties: { "attr.theme": "applicationTheme" } }, providers: [AutocompleteValueManager, AutocompleteFilterService, InfiniteScrollDirective], viewQueries: [{ propertyName: "formFieldElement", first: true, predicate: ["formField"], descendants: true }, { propertyName: "tagContainer", first: true, predicate: ["tagContainer"], descendants: true }, { propertyName: "measureElRef", first: true, predicate: ["measureEl"], descendants: true }, { propertyName: "overflowDir", first: true, predicate: ["overflow"], descendants: true }, { propertyName: "autocomplete", first: true, predicate: ["trigger"], descendants: true }, { propertyName: "cdkViewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true }, { propertyName: "matAutocomplete", first: true, predicate: ["autocomplete"], descendants: true }, { propertyName: "matInput", first: true, predicate: ["matInput"], descendants: true }], ngImport: i0, template: "<ng-container>\n <div class=\"autocomplete-wrapper\" [ngClass]=\"{ disabled: _isDisabled() }\">\n <mat-form-field\n [color]=\"hasError() ? 'warn' : 'accent'\"\n [appearance]=\"'outline'\"\n [ngClass]=\"{\n 'large-size': type() === autocompleteType.LARGE,\n 'hide-bottom-content': !showBottomContent(),\n 'keyboard-focused': keyboardFocused(),\n 'has-label': !!label(),\n }\"\n >\n @if (label()) {\n <mat-label\n >{{ label() }}\n @if (required()) {\n <span>*</span>\n }\n </mat-label>\n }\n <div #formField class=\"input-container\">\n @if (textField() ? $any(valueManager.value())?.[textField()] : $any(valueManager.value()) === inputValue()) {\n <span style=\"position: absolute; left: -9999px\" aria-live=\"polite\">{{\n ('SELECTED' | uiTranslate | async) + ' ' + inputValue()\n }}</span>\n }\n\n <input\n #trigger=\"matAutocompleteTrigger\"\n #matInput\n [attr.maxlength]=\"maxLength() !== null && maxLength() !== undefined ? maxLength() : null\"\n [uiPreventInput]=\"!allowUserInput()\"\n [disabled]=\"_isDisabled()\"\n [ngClass]=\"{\n 'unset-margin': valueManager.value() && type() === autocompleteType.LARGE,\n 'no-caret': !allowUserInput(),\n }\"\n (blur)=\"onBlur()\"\n (focusin)=\"onFocus()\"\n [attr.aria-label]=\"\n (translationContext + 'SELECTED' | uiTranslate | async) +\n ' ' +\n (valueManager.value() | transformItem: textField() : true)\n \"\n matInput\n [placeholder]=\"valueManager.value() && valueManager.value()!.length ? '' : placeholder()\"\n [type]=\"'text'\"\n [matAutocomplete]=\"autocomplete\"\n (input)=\"onInputChange($event)\"\n [ngModel]=\"inputValue()\"\n (ngModelChange)=\"inputValue.set($event)\"\n />\n <!-- Hidden measurement container: always in DOM, renders ALL tags for width measurement -->\n @if (type() !== autocompleteType.SINGLE && utils.isArray(valueManager.value())) {\n <div class=\"selected-items measurement-container\" #measureEl>\n @for (valueItem of $any(valueManager.value()); track valueItem; let i = $index) {\n <ui-tag\n class=\"value-tag\"\n [id]=\"'measure-tag-' + i\"\n [label]=\"valueItem | transformItem: textField()\"\n [allowClose]=\"true\"\n [applicationTheme]=\"applicationTheme\"\n ></ui-tag>\n }\n </div>\n }\n\n @if (\n (type() === autocompleteType.LARGE && valueManager.value()) ||\n (!(inputValue() && isInputFocus()) && valueManager.value() && type() !== autocompleteType.SINGLE)\n ) {\n <!-- Visible container: only renders tags that fit. Hidden until first measurement to prevent flash. -->\n <div\n class=\"selected-items\"\n #tagContainer\n uiAutocompleteOverflowDetect\n #overflow=\"autocompleteOverflowDetect\"\n [measureContainer]=\"measureElRef?.nativeElement\"\n [class.measured]=\"\n type() === autocompleteType.LARGE || type() === autocompleteType.SINGLE || overflow.hasMeasured()\n \"\n >\n @if (size() === 'small' && valueManager.value()!.length > 1) {\n <div class=\"selected-count\">\n {{\n translationContext + 'SELECTED_AMOUNT'\n | uiTranslate: { numberSelected: valueManager.value()!.length }\n | async\n }}\n </div>\n } @else {\n @for (valueItem of $any(valueManager.value()); track valueItem; let i = $index) {\n @if (i < overflow.visibleCount()) {\n <ui-tag\n class=\"value-tag\"\n [id]=\"'ui-tag-' + i\"\n [label]=\"valueItem | transformItem: textField()\"\n [allowClose]=\"true\"\n [applicationTheme]=\"applicationTheme\"\n [ngStyle]=\"\n type() !== autocompleteType.LARGE\n ? { '--tag-max-width': overflow.tagMaxWidth() ? overflow.tagMaxWidth() + 'px' : 'fit-content' }\n : {}\n \"\n (close)=\"onOptionRemoved(valueItem)\"\n ></ui-tag>\n }\n }\n @if (overflow.overflowCount() > 0) {\n <div class=\"overlap-count\" [matTooltip]=\"hiddenItemsTooltip()\">\n <ui-tag [applicationTheme]=\"applicationTheme\" [label]=\"'+' + overflow.overflowCount()\"></ui-tag>\n </div>\n }\n }\n </div>\n }\n </div>\n\n @if (showClearButton()) {\n <ui-icon\n class=\"remove-selected\"\n [tabIndex]=\"_isDisabled() ? -1 : 0\"\n (keydown.enter)=\"onClear(); $event.preventDefault(); $event.stopPropagation()\"\n (keydown.space)=\"onClear(); $event.preventDefault(); $event.stopPropagation()\"\n [ngClass]=\"{ 'large-input-icon': type() === autocompleteType.LARGE }\"\n (click)=\"onClear(); $event.preventDefault(); $event.stopPropagation()\"\n [size]=\"'24'\"\n [color]=\"applicationTheme === 'classic' ? 'inherit' : 'rebrand-black'\"\n [attr.aria-label]=\"'COMMON.CLEAR' | uiTranslate | async\"\n [name]=\"applicationTheme === 'classic' ? 'Close' : 'Close-in-line'\"\n ></ui-icon>\n }\n\n @if (isDropdown) {\n <ui-icon\n class=\"arrow-state\"\n [ngClass]=\"{ opened: autocomplete.isOpen, 'large-input-icon': type() === autocompleteType.LARGE }\"\n [size]=\"'24'\"\n [name]=\"applicationTheme !== 'classic' ? 'Arrow-chevron-down-in-line' : 'Arrow_down'\"\n (click)=\"onChevronClick(autocomplete)\"\n ></ui-icon>\n }\n\n <mat-autocomplete\n #autocomplete\n [class]=\"applicationTheme + ' ' + dropdownPanelClass()\"\n (optionSelected)=\"onOptionSelected($event)\"\n [disableRipple]=\"applicationTheme !== 'classic'\"\n [hideSingleSelectionIndicator]=\"false\"\n (opened)=\"onPanelOpened()\"\n >\n <!-- Reusable option template \u2014 must be inside mat-autocomplete for @ContentChildren to find mat-options -->\n <ng-template #optionTpl let-item=\"item\" let-highlight=\"highlight\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n [value]=\"item\"\n >\n <span [selectText]=\"highlight ? (filterService.userInput$ | async) : null\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </ng-template>\n\n <!-- \u2500\u2500 Unfiltered \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if ((filterService.isSearching$ | async) === false) {\n @if (!isDropdown) {\n <!-- Suggestions -->\n @if (suggestionsList().length) {\n <mat-optgroup [label]=\"(translationContext + 'SUGGESTED' | uiTranslate | async)! | uppercase\">\n @for (suggested of suggestionsList(); track suggested) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: suggested, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n }\n\n <!-- Selected items (multi) -->\n @if (valueManager.value()?.length && type() !== autocompleteType.SINGLE) {\n <mat-optgroup [label]=\"(translationContext + 'SELECTED' | uiTranslate | async)! | uppercase\">\n @for (item of $any(valueManager.value()); track item) {\n <ng-container *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: false }\"></ng-container>\n }\n </mat-optgroup>\n }\n\n <!-- Main items (normalized groups) -->\n @if (virtualScroll() || infiniteScroll()) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"48\"\n [style.height.px]=\"getVirtualScrollHeight(flatItemsList().length)\"\n class=\"virtual-scroll\"\n >\n @if (!isGrouped) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of flatItemsList(); trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{ item | transformItem: textField() }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n } @else {\n @for (group of groupedItemsList(); track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n *cdkVirtualFor=\"let item of group.items; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </mat-optgroup>\n } @else {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of group.items; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n }\n }\n\n @if (infiniteScroll() && hasMoreOptionsForInfiniteScroll()) {\n <mat-option class=\"loading-option\" [style.pointer-events]=\"'none'\">\n <div class=\"loading-container\">\n <ui-spinner size=\"small\" [isLoader]=\"false\"></ui-spinner>\n </div>\n </mat-option>\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n @if (isGrouped) {\n @for (group of groupedItemsList(); track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n @for (item of group.items; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n } @else {\n @for (item of group.items; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n }\n }\n } @else {\n @for (item of flatItemsList(); track item) {\n <ng-container *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"></ng-container>\n }\n }\n }\n\n <!-- Selected item (single) -->\n @if (valueManager.value()?.length && type() === autocompleteType.SINGLE) {\n <mat-optgroup [label]=\"(translationContext + 'SELECTED' | uiTranslate | async)! | uppercase\">\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: valueManager.value(), highlight: true }\"\n ></ng-container>\n </mat-optgroup>\n }\n } @else {\n <!-- \u2500\u2500 Dropdown (unfiltered) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (virtualScroll() || infiniteScroll()) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"48\"\n [style.height.px]=\"getVirtualScrollHeight(flatItemsList().length)\"\n class=\"virtual-scroll\"\n >\n @if (!isGrouped) {\n <!-- Ungrouped: flat cdkVirtualFor directly in viewport -->\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of flatItemsList(); trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{ item | transformItem: textField() }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n } @else {\n <!-- Grouped: nested cdkVirtualFor per group -->\n @for (group of groupedItemsList(); track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n *cdkVirtualFor=\"let item of group.items; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </mat-optgroup>\n } @else {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of group.items; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n }\n }\n\n @if (infiniteScroll() && hasMoreOptionsForInfiniteScroll()) {\n <mat-option class=\"loading-option\" [style.pointer-events]=\"'none'\">\n <div class=\"loading-container\">\n <ui-spinner size=\"small\" [isLoader]=\"false\"></ui-spinner>\n </div>\n </mat-option>\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n @if (isGrouped) {\n @for (group of groupedItemsList(); track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n @for (item of group.items; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n } @else {\n @for (item of group.items; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n }\n }\n } @else {\n @for (item of flatItemsList(); track item) {\n <ng-container *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"></ng-container>\n }\n }\n }\n }\n }\n\n <!-- \u2500\u2500 Filtered \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (filterService.filteredSuggestions$ | async; as filteredSuggestionList) {\n @if (filterService.filteredItems$ | async; as filteredItemsList) {\n @if (virtualScroll() || infiniteScroll()) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"48\"\n [style.height.px]=\"getVirtualScrollHeight(filteredItemsList.length)\"\n class=\"virtual-scroll\"\n >\n <!-- Filtered suggestions -->\n @if (filteredSuggestionList.length) {\n <mat-optgroup [label]=\"(translationContext + 'SUGGESTED' | uiTranslate | async)! | uppercase\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of filteredSuggestionList; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </mat-optgroup>\n }\n\n <!-- Filtered items: grouped -->\n @if (isGrouped && (filterService.filteredGroupedItems$ | async); as filteredGroups) {\n @if (filteredGroups.length) {\n @for (group of filteredGroups; track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n *cdkVirtualFor=\"let item of group.filteredItems; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </mat-optgroup>\n } @else {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n *cdkVirtualFor=\"let item of group.filteredItems; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n }\n }\n }\n\n <!-- Filtered items: ungrouped (no suggestions) -->\n @if (!filteredSuggestionList.length && !isGrouped) {\n @for (item of filteredItemsList; let idx = $index; track item[valueField()] || idx) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n } @else {\n <!-- Filtered items: ungrouped with suggestions present (ALL_ITEMS group) -->\n @if (filteredItemsList.length && !isGrouped) {\n <mat-optgroup [label]=\"(translationContext + 'ALL_ITEMS' | uiTranslate | async)! | uppercase\">\n @for (item of filteredItemsList; let idx = $index; track item[valueField()] || idx) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n </mat-optgroup>\n }\n }\n\n @if (dynamicFilterLoading()) {\n <mat-option class=\"loading-option\" [style.pointer-events]=\"'none'\">\n <div class=\"loading-container\">\n <ui-spinner size=\"small\" [isLoader]=\"false\"></ui-spinner>\n </div>\n </mat-option>\n } @else if (inputValue()) {\n @if (allowAdd() && !isAlreadyAdded()) {\n <mat-option (mousedown)=\"$event.preventDefault()\" [value]=\"inputValue()\">\n <span>{{ 'COMMON.ADD' | uiTranslate | async }}</span>\n <span class=\"add-suggestion\">\"{{ inputValue() }}\"</span>\n </mat-option>\n } @else if (!filteredItemsList.length && !filteredSuggestionList.length) {\n <mat-option [style.pointer-events]=\"'none'\">\n <span>{{ translationContext + 'NO_RESULTS_FOUND' | uiTranslate | async }}</span>\n </mat-option>\n }\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n <!-- Filtered items: grouped -->\n @if (isGrouped && (filterService.filteredGroupedItems$ | async); as filteredGroups) {\n @if (filteredGroups.length) {\n @for (group of filteredGroups; track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n @for (item of group.filteredItems; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n } @else {\n @for (item of group.filteredItems; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n }\n }\n }\n }\n\n <!-- Filtered suggestions -->\n @if (filteredSuggestionList.length) {\n <mat-optgroup [label]=\"(translationContext + 'SUGGESTED' | uiTranslate | async)! | uppercase\">\n @for (item of filteredSuggestionList; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n }\n\n <!-- Filtered items: ungrouped (no suggestions) -->\n @if (!filteredSuggestionList.length && !isGrouped) {\n @for (item of filteredItemsList; let idx = $index; track item[valueField()] || idx) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{ item | transformItem: textField() }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n } @else {\n <!-- Filtered items: ungrouped with suggestions present (ALL_ITEMS group) -->\n @if (filteredItemsList.length && !isGrouped) {\n <mat-optgroup [label]=\"(translationContext + 'ALL_ITEMS' | uiTranslate | async)! | uppercase\">\n @for (item of filteredItemsList; let idx = $index; track item[valueField()] || idx) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n </mat-optgroup>\n }\n }\n\n @if (dynamicFilterLoading()) {\n <mat-option class=\"loading-option\" [style.pointer-events]=\"'none'\">\n <div class=\"loading-container\">\n <ui-spinner size=\"small\" [isLoader]=\"false\"></ui-spinner>\n </div>\n </mat-option>\n } @else if (inputValue()) {\n @if (allowAdd() && !isAlreadyAdded()) {\n <mat-option (mousedown)=\"$event.preventDefault()\" [value]=\"inputValue()\">\n <span>{{ 'COMMON.ADD' | uiTranslate | async }}</span>\n <span class=\"add-suggestion\">\"{{ inputValue() }}\"</span>\n </mat-option>\n } @else if (!filteredItemsList.length && !filteredSuggestionList.length) {\n <mat-option [style.pointer-events]=\"'none'\">\n <span>{{ translationContext + 'NO_RESULTS_FOUND' | uiTranslate | async }}</span>\n </mat-option>\n }\n }\n }\n }\n }\n </mat-autocomplete>\n @if (hasError()) {\n <mat-hint class=\"error\">\n @if (ngControl) {\n <ui-validation-error\n [ngControl]=\"ngControl\"\n [customErrors]=\"formErrorConfig()\"\n [label]=\"label()\"\n ></ui-validation-error>\n } @else {\n @for (error of safeErrors(); track error) {\n <div class=\"errors\">\n <ui-icon [applicationTheme]=\"applicationTheme\" [name]=\"'Error'\"></ui-icon>\n <span>{{ error }}</span>\n </div>\n }\n }\n </mat-hint>\n }\n </mat-form-field>\n </div>\n</ng-container>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{width:320px;display:block}:host.full-width{width:100%}:host ui-tag{height:32px;margin:4px}:host ui-tag ::ng-deep .tag-container{margin:0!important}:host ui-tag ::ng-deep .tag-wrapper{max-width:fit-content}.large-size input{margin:10px 0}.large-size .selected-items{margin:5px 0;flex-wrap:wrap;--tag-max-width: calc(100% - 8px) }.large-size .selected-items .value-tag ::ng-deep .tag-container{max-width:100%!important}.large-size .input-container{width:calc(100% - 52px);display:flex;flex-direction:column-reverse}.large-size ::ng-deep .mat-mdc-form-field-infix,.large-size .mat-mdc-form-field-flex{align-items:unset!important}.disabled *{pointer-events:none}.input-container{width:100%;margin:auto;display:flex;flex-direction:row-reverse}.input-container .selected-items{display:flex;padding-left:4px;visibility:hidden}.input-container .selected-items.measured{visibility:visible}.input-container .selected-items .value-tag{max-width:var(--tag-max-width, fit-content)}.input-container .selected-items .value-tag ::ng-deep .tag-container{max-width:var(--tag-max-width, fit-content)}.input-container .selected-items .selected-count{white-space:nowrap}.input-container .selected-items.measurement-container{visibility:hidden;position:absolute;height:0;overflow:hidden;pointer-events:none}.input-container .overlap-count{font-size:14px;line-height:20px}.input-container .overlap-count ui-tag{display:block}.input-container input{margin-left:6px}.input-container input.unset-margin{margin-top:unset}.input-container input.no-caret{cursor:pointer;caret-color:transparent!important}.add-suggestion{margin:0 5px;color:#000;font-weight:700}.remove-selected{cursor:pointer;margin-right:2px;border-radius:50px;height:fit-content}.remove-selected.large-input-icon{margin-top:10px}.arrow-state{height:24px;cursor:pointer}.arrow-state.large-input-icon{margin-top:10px}.arrow-state.opened{transform:rotateX(180deg)}::ng-deep .autocomplete-wrapper .mat-mdc-form-field{width:100%}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error,::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error svg{color:#cb7b7a}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error{display:flex}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error{display:flex;flex-flow:column;row-gap:4px}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error .errors{display:flex}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error .errors ui-icon{margin-right:8px}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error{color:#e02800!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error svg{color:#e02800!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-bottom-align:before{height:0}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint-wrapper{padding:0 0 12px;font-size:12px;line-height:16px;position:relative}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint-wrapper .mat-form-field-hint-spacer{display:none}::ng-deep .autocomplete-wrapper .mat-mdc-form-field.hide-bottom-content .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{top:28px!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label{top:22px!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-text-field-wrapper{padding-left:12px!important;height:unset!important;max-height:unset!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-focused .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label{color:#276678!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__notch{border-bottom:2px solid #276678!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__leading{border-left:2px solid #276678!important;border-bottom:2px solid #276678!important;border-top:2px solid #276678!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__trailing{border:2px solid #276678!important;border-left:unset!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-infix,::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-flex{min-height:48px!important;max-height:184px!important;overflow-y:auto;overflow-x:hidden;padding:0!important;display:flex;justify-content:center;text-align:center;align-items:center;flex-direction:row;width:100%}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mdc-line-ripple{display:none!important}::ng-deep .mat-mdc-autocomplete-panel{box-shadow:0 8px 24px 4px #00000014;max-height:312px!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:focus:not(.mdc-list-item--disabled),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mat-mdc-option-active,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mdc-list-item--selected:not(.mat-mdc-option-multiple):not(.mdc-list-item--disabled){background:#e9f0f1!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{padding-right:32px;padding-left:12px!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option ui-icon{display:none;position:absolute;right:0;bottom:calc(50% - 8px);margin:0 10px}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.selected-option{background:#e9f0f1}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.selected-option ui-icon{display:block}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mdc-list-item--selected .mdc-list-item__primary-text,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item--activated .mdc-list-item__primary-text{color:#000!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mat-pseudo-checkbox{display:none}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-optgroup .mat-mdc-optgroup-label{font-weight:700!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-optgroup .mdc-list-item__primary-text{color:#000;font-size:12px;line-height:16px;font-weight:700}.active-field .mdc-notched-outline__leading{border-left-width:2px;border-top-width:2px;border-bottom-width:2px}.active-field .mdc-notched-outline__notch{border-top-width:2px;border-bottom-width:2px}.active-field .mdc-notched-outline__trailing{border-top-width:2px;border-bottom-width:2px;border-right-width:2px}.loading-option{display:flex}.loading-option .loading-container{display:flex;justify-content:center;align-items:center;width:100%;height:100%;position:absolute;top:0;left:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i3.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i3.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "directive", type: i3.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: TagComponentModule }, { kind: "component", type: i6.TagComponent, selector: "ui-tag", inputs: ["label", "icon", "allowClose", "readOnly", "isSelected", "showIconWhenSelected", "isDisabled", "applicationTheme", "ariaLabel", "ariaRequired", "showBadge", "notificationsAmount"], outputs: ["close", "press"] }, { kind: "ngmodule", type: IconComponentModule }, { kind: "component", type: i7.IconComponent, selector: "ui-icon", inputs: ["size", "cssClass", "name", "color", "filled", "toggleIconStyle", "applicationTheme", "useFullIconName"] }, { kind: "ngmodule", type: SpinnerComponentModule }, { kind: "component", type: i8.SpinnerComponent, selector: "ui-spinner", inputs: ["size", "isLoader", "text", "applicationTheme", "iconName", "iconSize"] }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: PreventInputDirective, selector: "[uiPreventInput]", inputs: ["uiPreventInput"] }, { kind: "pipe", type: UiTranslatePipe, name: "uiTranslate" }, { kind: "pipe", type: TransformItemPipe, name: "transformItem" }, { kind: "pipe", type: IncludesPipe, name: "includes" }, { kind: "directive", type: SelectTextDirective, selector: "[selectText]", inputs: ["selectText"] }, { kind: "directive", type: AutocompleteOverflowDetectDirective, selector: "[uiAutocompleteOverflowDetect]", inputs: ["measureContainer", "itemSelector", "reserveWidth"], exportAs: ["autocompleteOverflowDetect"] }, { kind: "ngmodule", type: ValidationErrorModule }, { kind: "component", type: i9.ValidationErrorComponent, selector: "ui-validation-error", inputs: ["ngControl", "touchedOn", "errorMessage", "label", "applicationTheme", "customErrors"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
747
+ }
748
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: AutocompleteV2Component, decorators: [{
749
+ type: Component,
750
+ args: [{ selector: 'ui-autocomplete-v2', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
751
+ CommonModule,
752
+ FormsModule,
753
+ MatAutocompleteModule,
754
+ MatChipsModule,
755
+ MatFormFieldModule,
756
+ MatInputModule,
757
+ TagComponentModule,
758
+ IconComponentModule,
759
+ SpinnerComponentModule,
760
+ CdkVirtualScrollViewport,
761
+ CdkVirtualForOf,
762
+ CdkFixedSizeVirtualScroll,
763
+ PreventInputDirective,
764
+ UiTranslatePipe,
765
+ TransformItemPipe,
766
+ IncludesPipe,
767
+ SelectTextDirective,
768
+ AutocompleteOverflowDetectDirective,
769
+ ValidationErrorModule,
770
+ MatTooltipModule,
771
+ ], host: {
772
+ '[attr.theme]': 'applicationTheme',
773
+ }, providers: [AutocompleteValueManager, AutocompleteFilterService, InfiniteScrollDirective], template: "<ng-container>\n <div class=\"autocomplete-wrapper\" [ngClass]=\"{ disabled: _isDisabled() }\">\n <mat-form-field\n [color]=\"hasError() ? 'warn' : 'accent'\"\n [appearance]=\"'outline'\"\n [ngClass]=\"{\n 'large-size': type() === autocompleteType.LARGE,\n 'hide-bottom-content': !showBottomContent(),\n 'keyboard-focused': keyboardFocused(),\n 'has-label': !!label(),\n }\"\n >\n @if (label()) {\n <mat-label\n >{{ label() }}\n @if (required()) {\n <span>*</span>\n }\n </mat-label>\n }\n <div #formField class=\"input-container\">\n @if (textField() ? $any(valueManager.value())?.[textField()] : $any(valueManager.value()) === inputValue()) {\n <span style=\"position: absolute; left: -9999px\" aria-live=\"polite\">{{\n ('SELECTED' | uiTranslate | async) + ' ' + inputValue()\n }}</span>\n }\n\n <input\n #trigger=\"matAutocompleteTrigger\"\n #matInput\n [attr.maxlength]=\"maxLength() !== null && maxLength() !== undefined ? maxLength() : null\"\n [uiPreventInput]=\"!allowUserInput()\"\n [disabled]=\"_isDisabled()\"\n [ngClass]=\"{\n 'unset-margin': valueManager.value() && type() === autocompleteType.LARGE,\n 'no-caret': !allowUserInput(),\n }\"\n (blur)=\"onBlur()\"\n (focusin)=\"onFocus()\"\n [attr.aria-label]=\"\n (translationContext + 'SELECTED' | uiTranslate | async) +\n ' ' +\n (valueManager.value() | transformItem: textField() : true)\n \"\n matInput\n [placeholder]=\"valueManager.value() && valueManager.value()!.length ? '' : placeholder()\"\n [type]=\"'text'\"\n [matAutocomplete]=\"autocomplete\"\n (input)=\"onInputChange($event)\"\n [ngModel]=\"inputValue()\"\n (ngModelChange)=\"inputValue.set($event)\"\n />\n <!-- Hidden measurement container: always in DOM, renders ALL tags for width measurement -->\n @if (type() !== autocompleteType.SINGLE && utils.isArray(valueManager.value())) {\n <div class=\"selected-items measurement-container\" #measureEl>\n @for (valueItem of $any(valueManager.value()); track valueItem; let i = $index) {\n <ui-tag\n class=\"value-tag\"\n [id]=\"'measure-tag-' + i\"\n [label]=\"valueItem | transformItem: textField()\"\n [allowClose]=\"true\"\n [applicationTheme]=\"applicationTheme\"\n ></ui-tag>\n }\n </div>\n }\n\n @if (\n (type() === autocompleteType.LARGE && valueManager.value()) ||\n (!(inputValue() && isInputFocus()) && valueManager.value() && type() !== autocompleteType.SINGLE)\n ) {\n <!-- Visible container: only renders tags that fit. Hidden until first measurement to prevent flash. -->\n <div\n class=\"selected-items\"\n #tagContainer\n uiAutocompleteOverflowDetect\n #overflow=\"autocompleteOverflowDetect\"\n [measureContainer]=\"measureElRef?.nativeElement\"\n [class.measured]=\"\n type() === autocompleteType.LARGE || type() === autocompleteType.SINGLE || overflow.hasMeasured()\n \"\n >\n @if (size() === 'small' && valueManager.value()!.length > 1) {\n <div class=\"selected-count\">\n {{\n translationContext + 'SELECTED_AMOUNT'\n | uiTranslate: { numberSelected: valueManager.value()!.length }\n | async\n }}\n </div>\n } @else {\n @for (valueItem of $any(valueManager.value()); track valueItem; let i = $index) {\n @if (i < overflow.visibleCount()) {\n <ui-tag\n class=\"value-tag\"\n [id]=\"'ui-tag-' + i\"\n [label]=\"valueItem | transformItem: textField()\"\n [allowClose]=\"true\"\n [applicationTheme]=\"applicationTheme\"\n [ngStyle]=\"\n type() !== autocompleteType.LARGE\n ? { '--tag-max-width': overflow.tagMaxWidth() ? overflow.tagMaxWidth() + 'px' : 'fit-content' }\n : {}\n \"\n (close)=\"onOptionRemoved(valueItem)\"\n ></ui-tag>\n }\n }\n @if (overflow.overflowCount() > 0) {\n <div class=\"overlap-count\" [matTooltip]=\"hiddenItemsTooltip()\">\n <ui-tag [applicationTheme]=\"applicationTheme\" [label]=\"'+' + overflow.overflowCount()\"></ui-tag>\n </div>\n }\n }\n </div>\n }\n </div>\n\n @if (showClearButton()) {\n <ui-icon\n class=\"remove-selected\"\n [tabIndex]=\"_isDisabled() ? -1 : 0\"\n (keydown.enter)=\"onClear(); $event.preventDefault(); $event.stopPropagation()\"\n (keydown.space)=\"onClear(); $event.preventDefault(); $event.stopPropagation()\"\n [ngClass]=\"{ 'large-input-icon': type() === autocompleteType.LARGE }\"\n (click)=\"onClear(); $event.preventDefault(); $event.stopPropagation()\"\n [size]=\"'24'\"\n [color]=\"applicationTheme === 'classic' ? 'inherit' : 'rebrand-black'\"\n [attr.aria-label]=\"'COMMON.CLEAR' | uiTranslate | async\"\n [name]=\"applicationTheme === 'classic' ? 'Close' : 'Close-in-line'\"\n ></ui-icon>\n }\n\n @if (isDropdown) {\n <ui-icon\n class=\"arrow-state\"\n [ngClass]=\"{ opened: autocomplete.isOpen, 'large-input-icon': type() === autocompleteType.LARGE }\"\n [size]=\"'24'\"\n [name]=\"applicationTheme !== 'classic' ? 'Arrow-chevron-down-in-line' : 'Arrow_down'\"\n (click)=\"onChevronClick(autocomplete)\"\n ></ui-icon>\n }\n\n <mat-autocomplete\n #autocomplete\n [class]=\"applicationTheme + ' ' + dropdownPanelClass()\"\n (optionSelected)=\"onOptionSelected($event)\"\n [disableRipple]=\"applicationTheme !== 'classic'\"\n [hideSingleSelectionIndicator]=\"false\"\n (opened)=\"onPanelOpened()\"\n >\n <!-- Reusable option template \u2014 must be inside mat-autocomplete for @ContentChildren to find mat-options -->\n <ng-template #optionTpl let-item=\"item\" let-highlight=\"highlight\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n [value]=\"item\"\n >\n <span [selectText]=\"highlight ? (filterService.userInput$ | async) : null\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </ng-template>\n\n <!-- \u2500\u2500 Unfiltered \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if ((filterService.isSearching$ | async) === false) {\n @if (!isDropdown) {\n <!-- Suggestions -->\n @if (suggestionsList().length) {\n <mat-optgroup [label]=\"(translationContext + 'SUGGESTED' | uiTranslate | async)! | uppercase\">\n @for (suggested of suggestionsList(); track suggested) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: suggested, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n }\n\n <!-- Selected items (multi) -->\n @if (valueManager.value()?.length && type() !== autocompleteType.SINGLE) {\n <mat-optgroup [label]=\"(translationContext + 'SELECTED' | uiTranslate | async)! | uppercase\">\n @for (item of $any(valueManager.value()); track item) {\n <ng-container *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: false }\"></ng-container>\n }\n </mat-optgroup>\n }\n\n <!-- Main items (normalized groups) -->\n @if (virtualScroll() || infiniteScroll()) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"48\"\n [style.height.px]=\"getVirtualScrollHeight(flatItemsList().length)\"\n class=\"virtual-scroll\"\n >\n @if (!isGrouped) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of flatItemsList(); trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{ item | transformItem: textField() }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n } @else {\n @for (group of groupedItemsList(); track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n *cdkVirtualFor=\"let item of group.items; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </mat-optgroup>\n } @else {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of group.items; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n }\n }\n\n @if (infiniteScroll() && hasMoreOptionsForInfiniteScroll()) {\n <mat-option class=\"loading-option\" [style.pointer-events]=\"'none'\">\n <div class=\"loading-container\">\n <ui-spinner size=\"small\" [isLoader]=\"false\"></ui-spinner>\n </div>\n </mat-option>\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n @if (isGrouped) {\n @for (group of groupedItemsList(); track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n @for (item of group.items; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n } @else {\n @for (item of group.items; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n }\n }\n } @else {\n @for (item of flatItemsList(); track item) {\n <ng-container *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"></ng-container>\n }\n }\n }\n\n <!-- Selected item (single) -->\n @if (valueManager.value()?.length && type() === autocompleteType.SINGLE) {\n <mat-optgroup [label]=\"(translationContext + 'SELECTED' | uiTranslate | async)! | uppercase\">\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: valueManager.value(), highlight: true }\"\n ></ng-container>\n </mat-optgroup>\n }\n } @else {\n <!-- \u2500\u2500 Dropdown (unfiltered) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (virtualScroll() || infiniteScroll()) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"48\"\n [style.height.px]=\"getVirtualScrollHeight(flatItemsList().length)\"\n class=\"virtual-scroll\"\n >\n @if (!isGrouped) {\n <!-- Ungrouped: flat cdkVirtualFor directly in viewport -->\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of flatItemsList(); trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{ item | transformItem: textField() }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n } @else {\n <!-- Grouped: nested cdkVirtualFor per group -->\n @for (group of groupedItemsList(); track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n *cdkVirtualFor=\"let item of group.items; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </mat-optgroup>\n } @else {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of group.items; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n }\n }\n\n @if (infiniteScroll() && hasMoreOptionsForInfiniteScroll()) {\n <mat-option class=\"loading-option\" [style.pointer-events]=\"'none'\">\n <div class=\"loading-container\">\n <ui-spinner size=\"small\" [isLoader]=\"false\"></ui-spinner>\n </div>\n </mat-option>\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n @if (isGrouped) {\n @for (group of groupedItemsList(); track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n @for (item of group.items; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n } @else {\n @for (item of group.items; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n }\n }\n } @else {\n @for (item of flatItemsList(); track item) {\n <ng-container *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"></ng-container>\n }\n }\n }\n }\n }\n\n <!-- \u2500\u2500 Filtered \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (filterService.filteredSuggestions$ | async; as filteredSuggestionList) {\n @if (filterService.filteredItems$ | async; as filteredItemsList) {\n @if (virtualScroll() || infiniteScroll()) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"48\"\n [style.height.px]=\"getVirtualScrollHeight(filteredItemsList.length)\"\n class=\"virtual-scroll\"\n >\n <!-- Filtered suggestions -->\n @if (filteredSuggestionList.length) {\n <mat-optgroup [label]=\"(translationContext + 'SUGGESTED' | uiTranslate | async)! | uppercase\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n *cdkVirtualFor=\"let item of filteredSuggestionList; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </mat-optgroup>\n }\n\n <!-- Filtered items: grouped -->\n @if (isGrouped && (filterService.filteredGroupedItems$ | async); as filteredGroups) {\n @if (filteredGroups.length) {\n @for (group of filteredGroups; track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n *cdkVirtualFor=\"let item of group.filteredItems; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n </mat-optgroup>\n } @else {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n *cdkVirtualFor=\"let item of group.filteredItems; trackBy: trackByItem\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n }\n }\n }\n\n <!-- Filtered items: ungrouped (no suggestions) -->\n @if (!filteredSuggestionList.length && !isGrouped) {\n @for (item of filteredItemsList; let idx = $index; track item[valueField()] || idx) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n } @else {\n <!-- Filtered items: ungrouped with suggestions present (ALL_ITEMS group) -->\n @if (filteredItemsList.length && !isGrouped) {\n <mat-optgroup [label]=\"(translationContext + 'ALL_ITEMS' | uiTranslate | async)! | uppercase\">\n @for (item of filteredItemsList; let idx = $index; track item[valueField()] || idx) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{\n 'selected-option': item | includes: valueManager.value() ?? [] : valueField(),\n }\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n </mat-optgroup>\n }\n }\n\n @if (dynamicFilterLoading()) {\n <mat-option class=\"loading-option\" [style.pointer-events]=\"'none'\">\n <div class=\"loading-container\">\n <ui-spinner size=\"small\" [isLoader]=\"false\"></ui-spinner>\n </div>\n </mat-option>\n } @else if (inputValue()) {\n @if (allowAdd() && !isAlreadyAdded()) {\n <mat-option (mousedown)=\"$event.preventDefault()\" [value]=\"inputValue()\">\n <span>{{ 'COMMON.ADD' | uiTranslate | async }}</span>\n <span class=\"add-suggestion\">\"{{ inputValue() }}\"</span>\n </mat-option>\n } @else if (!filteredItemsList.length && !filteredSuggestionList.length) {\n <mat-option [style.pointer-events]=\"'none'\">\n <span>{{ translationContext + 'NO_RESULTS_FOUND' | uiTranslate | async }}</span>\n </mat-option>\n }\n }\n </cdk-virtual-scroll-viewport>\n } @else {\n <!-- Filtered items: grouped -->\n @if (isGrouped && (filterService.filteredGroupedItems$ | async); as filteredGroups) {\n @if (filteredGroups.length) {\n @for (group of filteredGroups; track group) {\n @if (group.groupName) {\n <mat-optgroup [label]=\"group.groupName\">\n @for (item of group.filteredItems; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n } @else {\n @for (item of group.filteredItems; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n }\n }\n }\n }\n\n <!-- Filtered suggestions -->\n @if (filteredSuggestionList.length) {\n <mat-optgroup [label]=\"(translationContext + 'SUGGESTED' | uiTranslate | async)! | uppercase\">\n @for (item of filteredSuggestionList; track item) {\n <ng-container\n *ngTemplateOutlet=\"optionTpl; context: { item: item, highlight: true }\"\n ></ng-container>\n }\n </mat-optgroup>\n }\n\n <!-- Filtered items: ungrouped (no suggestions) -->\n @if (!filteredSuggestionList.length && !isGrouped) {\n @for (item of filteredItemsList; let idx = $index; track item[valueField()] || idx) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{ item | transformItem: textField() }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n } @else {\n <!-- Filtered items: ungrouped with suggestions present (ALL_ITEMS group) -->\n @if (filteredItemsList.length && !isGrouped) {\n <mat-optgroup [label]=\"(translationContext + 'ALL_ITEMS' | uiTranslate | async)! | uppercase\">\n @for (item of filteredItemsList; let idx = $index; track item[valueField()] || idx) {\n <mat-option\n (mousedown)=\"$event.preventDefault()\"\n [ngClass]=\"{ 'selected-option': item | includes: valueManager.value() ?? [] : valueField() }\"\n [value]=\"item\"\n >\n <span [selectText]=\"filterService.userInput$ | async\">{{\n item | transformItem: textField()\n }}</span>\n <ui-icon\n [applicationTheme]=\"applicationTheme\"\n [name]=\"applicationTheme === 'classic' ? 'Check' : 'Check-in-line'\"\n ></ui-icon>\n </mat-option>\n }\n </mat-optgroup>\n }\n }\n\n @if (dynamicFilterLoading()) {\n <mat-option class=\"loading-option\" [style.pointer-events]=\"'none'\">\n <div class=\"loading-container\">\n <ui-spinner size=\"small\" [isLoader]=\"false\"></ui-spinner>\n </div>\n </mat-option>\n } @else if (inputValue()) {\n @if (allowAdd() && !isAlreadyAdded()) {\n <mat-option (mousedown)=\"$event.preventDefault()\" [value]=\"inputValue()\">\n <span>{{ 'COMMON.ADD' | uiTranslate | async }}</span>\n <span class=\"add-suggestion\">\"{{ inputValue() }}\"</span>\n </mat-option>\n } @else if (!filteredItemsList.length && !filteredSuggestionList.length) {\n <mat-option [style.pointer-events]=\"'none'\">\n <span>{{ translationContext + 'NO_RESULTS_FOUND' | uiTranslate | async }}</span>\n </mat-option>\n }\n }\n }\n }\n }\n </mat-autocomplete>\n @if (hasError()) {\n <mat-hint class=\"error\">\n @if (ngControl) {\n <ui-validation-error\n [ngControl]=\"ngControl\"\n [customErrors]=\"formErrorConfig()\"\n [label]=\"label()\"\n ></ui-validation-error>\n } @else {\n @for (error of safeErrors(); track error) {\n <div class=\"errors\">\n <ui-icon [applicationTheme]=\"applicationTheme\" [name]=\"'Error'\"></ui-icon>\n <span>{{ error }}</span>\n </div>\n }\n }\n </mat-hint>\n }\n </mat-form-field>\n </div>\n</ng-container>\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}:host{width:320px;display:block}:host.full-width{width:100%}:host ui-tag{height:32px;margin:4px}:host ui-tag ::ng-deep .tag-container{margin:0!important}:host ui-tag ::ng-deep .tag-wrapper{max-width:fit-content}.large-size input{margin:10px 0}.large-size .selected-items{margin:5px 0;flex-wrap:wrap;--tag-max-width: calc(100% - 8px) }.large-size .selected-items .value-tag ::ng-deep .tag-container{max-width:100%!important}.large-size .input-container{width:calc(100% - 52px);display:flex;flex-direction:column-reverse}.large-size ::ng-deep .mat-mdc-form-field-infix,.large-size .mat-mdc-form-field-flex{align-items:unset!important}.disabled *{pointer-events:none}.input-container{width:100%;margin:auto;display:flex;flex-direction:row-reverse}.input-container .selected-items{display:flex;padding-left:4px;visibility:hidden}.input-container .selected-items.measured{visibility:visible}.input-container .selected-items .value-tag{max-width:var(--tag-max-width, fit-content)}.input-container .selected-items .value-tag ::ng-deep .tag-container{max-width:var(--tag-max-width, fit-content)}.input-container .selected-items .selected-count{white-space:nowrap}.input-container .selected-items.measurement-container{visibility:hidden;position:absolute;height:0;overflow:hidden;pointer-events:none}.input-container .overlap-count{font-size:14px;line-height:20px}.input-container .overlap-count ui-tag{display:block}.input-container input{margin-left:6px}.input-container input.unset-margin{margin-top:unset}.input-container input.no-caret{cursor:pointer;caret-color:transparent!important}.add-suggestion{margin:0 5px;color:#000;font-weight:700}.remove-selected{cursor:pointer;margin-right:2px;border-radius:50px;height:fit-content}.remove-selected.large-input-icon{margin-top:10px}.arrow-state{height:24px;cursor:pointer}.arrow-state.large-input-icon{margin-top:10px}.arrow-state.opened{transform:rotateX(180deg)}::ng-deep .autocomplete-wrapper .mat-mdc-form-field{width:100%}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error,::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error svg{color:#cb7b7a}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error{display:flex}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error{display:flex;flex-flow:column;row-gap:4px}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error .errors{display:flex}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error .errors ui-icon{margin-right:8px}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error{color:#e02800!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint.error svg{color:#e02800!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-bottom-align:before{height:0}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint-wrapper{padding:0 0 12px;font-size:12px;line-height:16px;position:relative}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-hint-wrapper .mat-form-field-hint-spacer{display:none}::ng-deep .autocomplete-wrapper .mat-mdc-form-field.hide-bottom-content .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{top:28px!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label{top:22px!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-text-field-wrapper{padding-left:12px!important;height:unset!important;max-height:unset!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-focused .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label{color:#276678!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__notch{border-bottom:2px solid #276678!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__leading{border-left:2px solid #276678!important;border-bottom:2px solid #276678!important;border-top:2px solid #276678!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__trailing{border:2px solid #276678!important;border-left:unset!important}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-infix,::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mat-mdc-form-field-flex{min-height:48px!important;max-height:184px!important;overflow-y:auto;overflow-x:hidden;padding:0!important;display:flex;justify-content:center;text-align:center;align-items:center;flex-direction:row;width:100%}::ng-deep .autocomplete-wrapper .mat-mdc-form-field .mdc-line-ripple{display:none!important}::ng-deep .mat-mdc-autocomplete-panel{box-shadow:0 8px 24px 4px #00000014;max-height:312px!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mdc-list-item--disabled),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:focus:not(.mdc-list-item--disabled),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mat-mdc-option-active,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mdc-list-item--selected:not(.mat-mdc-option-multiple):not(.mdc-list-item--disabled){background:#e9f0f1!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option{padding-right:32px;padding-left:12px!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option ui-icon{display:none;position:absolute;right:0;bottom:calc(50% - 8px);margin:0 10px}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.selected-option{background:#e9f0f1}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.selected-option ui-icon{display:block}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mdc-list-item--selected .mdc-list-item__primary-text,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mdc-list-item--activated .mdc-list-item__primary-text{color:#000!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .mat-pseudo-checkbox{display:none}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-optgroup .mat-mdc-optgroup-label{font-weight:700!important}::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-optgroup .mdc-list-item__primary-text{color:#000;font-size:12px;line-height:16px;font-weight:700}.active-field .mdc-notched-outline__leading{border-left-width:2px;border-top-width:2px;border-bottom-width:2px}.active-field .mdc-notched-outline__notch{border-top-width:2px;border-bottom-width:2px}.active-field .mdc-notched-outline__trailing{border-top-width:2px;border-bottom-width:2px;border-right-width:2px}.loading-option{display:flex}.loading-option .loading-container{display:flex;justify-content:center;align-items:center;width:100%;height:100%;position:absolute;top:0;left:0}\n"] }]
774
+ }], ctorParameters: () => [], propDecorators: { formFieldElement: [{
775
+ type: ViewChild,
776
+ args: ['formField']
777
+ }], tagContainer: [{
778
+ type: ViewChild,
779
+ args: ['tagContainer']
780
+ }], measureElRef: [{
781
+ type: ViewChild,
782
+ args: ['measureEl']
783
+ }], overflowDir: [{
784
+ type: ViewChild,
785
+ args: ['overflow']
786
+ }], autocomplete: [{
787
+ type: ViewChild,
788
+ args: ['trigger']
789
+ }], cdkViewport: [{
790
+ type: ViewChild,
791
+ args: [CdkVirtualScrollViewport, { static: false }]
792
+ }], matAutocomplete: [{
793
+ type: ViewChild,
794
+ args: ['autocomplete']
795
+ }], matInput: [{
796
+ type: ViewChild,
797
+ args: ['matInput']
798
+ }] } });
799
+
800
+ /**
801
+ * Generated bundle index. Do not edit.
802
+ */
803
+
804
+ export { Autocomplete, AutocompleteFilterService, AutocompleteOverflowDetectDirective, AutocompleteV2Component, AutocompleteV2Utils, AutocompleteValueManager, DropdownVariation };
805
+ //# sourceMappingURL=testgorilla-tgo-ui-components-autocomplete-v2.mjs.map