@raintonic/formaui 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -7
- package/LICENSE +21 -0
- package/README.md +199 -145
- package/fesm2022/raintonic-formaui-cdk-drag-drop.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-cdk-form-field.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-cdk-overlay.mjs +0 -26
- package/fesm2022/raintonic-formaui-cdk-overlay.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs +2 -2
- package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-accordion.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-accordion.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-alert.mjs +24 -5
- package/fesm2022/raintonic-formaui-components-alert.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-autocomplete.mjs +38 -9
- package/fesm2022/raintonic-formaui-components-autocomplete.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-avatar.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-badge.mjs +45 -31
- package/fesm2022/raintonic-formaui-components-badge.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-big-menu.mjs +23 -5
- package/fesm2022/raintonic-formaui-components-big-menu.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-breadcrumb.mjs +24 -7
- package/fesm2022/raintonic-formaui-components-breadcrumb.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-button-group.mjs +6 -6
- package/fesm2022/raintonic-formaui-components-button-group.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-button.mjs +63 -17
- package/fesm2022/raintonic-formaui-components-button.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-card.mjs +8 -8
- package/fesm2022/raintonic-formaui-components-card.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-checkbox.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-checkbox.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-data-table.mjs +67 -9
- package/fesm2022/raintonic-formaui-components-data-table.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-date-picker.mjs +63 -16
- package/fesm2022/raintonic-formaui-components-date-picker.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-divider.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-divider.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-drawer.mjs +19 -4
- package/fesm2022/raintonic-formaui-components-drawer.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-empty-state.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-empty-state.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-file-upload.mjs +25 -5
- package/fesm2022/raintonic-formaui-components-file-upload.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-form-field.mjs +21 -6
- package/fesm2022/raintonic-formaui-components-form-field.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-icon.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-icon.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-input.mjs +1 -1
- package/fesm2022/raintonic-formaui-components-input.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-list.mjs +4 -4
- package/fesm2022/raintonic-formaui-components-list.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-menu.mjs +4 -4
- package/fesm2022/raintonic-formaui-components-menu.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-number-input.mjs +20 -5
- package/fesm2022/raintonic-formaui-components-number-input.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-paginator.mjs +27 -7
- package/fesm2022/raintonic-formaui-components-paginator.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-password-input.mjs +23 -5
- package/fesm2022/raintonic-formaui-components-password-input.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-popover.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-popover.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-progressbar.mjs +32 -7
- package/fesm2022/raintonic-formaui-components-progressbar.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-radio.mjs +4 -4
- package/fesm2022/raintonic-formaui-components-radio.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-select.mjs +41 -26
- package/fesm2022/raintonic-formaui-components-select.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-side-panel.mjs +19 -4
- package/fesm2022/raintonic-formaui-components-side-panel.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-sidebar.mjs +23 -5
- package/fesm2022/raintonic-formaui-components-sidebar.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-skeleton.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-skeleton.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-slider.mjs +23 -5
- package/fesm2022/raintonic-formaui-components-slider.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-spinner.mjs +24 -7
- package/fesm2022/raintonic-formaui-components-spinner.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-stepper.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-stepper.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tab.mjs +10 -10
- package/fesm2022/raintonic-formaui-components-tab.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tag.mjs +21 -4
- package/fesm2022/raintonic-formaui-components-tag.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-time-picker.mjs +26 -7
- package/fesm2022/raintonic-formaui-components-time-picker.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-toggle.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-toggle.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-toolbar.mjs +41 -7
- package/fesm2022/raintonic-formaui-components-toolbar.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tooltip.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-tooltip.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tree-select.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-tree-select.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tree-table.mjs +35 -6
- package/fesm2022/raintonic-formaui-components-tree-table.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tree.mjs +25 -7
- package/fesm2022/raintonic-formaui-components-tree.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-core.mjs +25 -1
- package/fesm2022/raintonic-formaui-core.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-services-dialog.mjs +37 -37
- package/fesm2022/raintonic-formaui-services-dialog.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-services-notification.mjs +2 -2
- package/fesm2022/raintonic-formaui-services-notification.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-services-theme.mjs +3 -3
- package/fesm2022/raintonic-formaui-services-theme.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-test-utils.mjs +21 -16
- package/fesm2022/raintonic-formaui-test-utils.mjs.map +1 -1
- package/fesm2022/raintonic-formaui.mjs +1 -1
- package/fesm2022/raintonic-formaui.mjs.map +1 -1
- package/llms-full.txt +36 -122
- package/llms.txt +4 -5
- package/package.json +1 -5
- package/styles/index.scss +5 -5
- package/styles/partials/_motion.scss +25 -0
- package/styles/partials/_theme.scss +6 -5
- package/styles/partials/components/_button.scss +361 -0
- package/styles/partials/components/_dialog.scss +180 -0
- package/styles/partials/components/_overlay.scss +87 -0
- package/styles/partials/themes/_dark.scss +14 -0
- package/styles/partials/themes/_light.scss +14 -0
- package/types/raintonic-formaui-cdk-overlay.d.ts +0 -1
- package/types/raintonic-formaui-cdk-overlay.d.ts.map +1 -1
- package/types/raintonic-formaui-components-alert.d.ts +11 -1
- package/types/raintonic-formaui-components-alert.d.ts.map +1 -1
- package/types/raintonic-formaui-components-autocomplete.d.ts +25 -7
- package/types/raintonic-formaui-components-autocomplete.d.ts.map +1 -1
- package/types/raintonic-formaui-components-badge.d.ts +20 -9
- package/types/raintonic-formaui-components-badge.d.ts.map +1 -1
- package/types/raintonic-formaui-components-big-menu.d.ts +12 -1
- package/types/raintonic-formaui-components-big-menu.d.ts.map +1 -1
- package/types/raintonic-formaui-components-breadcrumb.d.ts +11 -2
- package/types/raintonic-formaui-components-breadcrumb.d.ts.map +1 -1
- package/types/raintonic-formaui-components-button-group.d.ts +6 -6
- package/types/raintonic-formaui-components-button.d.ts +9 -7
- package/types/raintonic-formaui-components-button.d.ts.map +1 -1
- package/types/raintonic-formaui-components-card.d.ts +4 -4
- package/types/raintonic-formaui-components-checkbox.d.ts +1 -1
- package/types/raintonic-formaui-components-data-table.d.ts +56 -16
- package/types/raintonic-formaui-components-data-table.d.ts.map +1 -1
- package/types/raintonic-formaui-components-date-picker.d.ts +32 -4
- package/types/raintonic-formaui-components-date-picker.d.ts.map +1 -1
- package/types/raintonic-formaui-components-drawer.d.ts +10 -1
- package/types/raintonic-formaui-components-drawer.d.ts.map +1 -1
- package/types/raintonic-formaui-components-file-upload.d.ts +12 -1
- package/types/raintonic-formaui-components-file-upload.d.ts.map +1 -1
- package/types/raintonic-formaui-components-form-field.d.ts +12 -2
- package/types/raintonic-formaui-components-form-field.d.ts.map +1 -1
- package/types/raintonic-formaui-components-input.d.ts +1 -1
- package/types/raintonic-formaui-components-number-input.d.ts +11 -2
- package/types/raintonic-formaui-components-number-input.d.ts.map +1 -1
- package/types/raintonic-formaui-components-paginator.d.ts +13 -1
- package/types/raintonic-formaui-components-paginator.d.ts.map +1 -1
- package/types/raintonic-formaui-components-password-input.d.ts +12 -2
- package/types/raintonic-formaui-components-password-input.d.ts.map +1 -1
- package/types/raintonic-formaui-components-progressbar.d.ts +14 -1
- package/types/raintonic-formaui-components-progressbar.d.ts.map +1 -1
- package/types/raintonic-formaui-components-select.d.ts.map +1 -1
- package/types/raintonic-formaui-components-side-panel.d.ts +10 -1
- package/types/raintonic-formaui-components-side-panel.d.ts.map +1 -1
- package/types/raintonic-formaui-components-sidebar.d.ts +12 -1
- package/types/raintonic-formaui-components-sidebar.d.ts.map +1 -1
- package/types/raintonic-formaui-components-slider.d.ts +12 -1
- package/types/raintonic-formaui-components-slider.d.ts.map +1 -1
- package/types/raintonic-formaui-components-spinner.d.ts +12 -2
- package/types/raintonic-formaui-components-spinner.d.ts.map +1 -1
- package/types/raintonic-formaui-components-tag.d.ts +10 -1
- package/types/raintonic-formaui-components-tag.d.ts.map +1 -1
- package/types/raintonic-formaui-components-time-picker.d.ts +14 -2
- package/types/raintonic-formaui-components-time-picker.d.ts.map +1 -1
- package/types/raintonic-formaui-components-toggle.d.ts +1 -1
- package/types/raintonic-formaui-components-toolbar.d.ts +22 -4
- package/types/raintonic-formaui-components-toolbar.d.ts.map +1 -1
- package/types/raintonic-formaui-components-tree-table.d.ts +29 -4
- package/types/raintonic-formaui-components-tree-table.d.ts.map +1 -1
- package/types/raintonic-formaui-components-tree.d.ts +12 -1
- package/types/raintonic-formaui-components-tree.d.ts.map +1 -1
- package/types/raintonic-formaui-core.d.ts +19 -2
- package/types/raintonic-formaui-core.d.ts.map +1 -1
- package/types/raintonic-formaui-services-dialog.d.ts +1 -1
- package/types/raintonic-formaui-services-theme.d.ts +3 -3
- package/types/raintonic-formaui-test-utils.d.ts +15 -2
- package/types/raintonic-formaui-test-utils.d.ts.map +1 -1
- package/types/raintonic-formaui.d.ts +1 -1
- package/fesm2022/raintonic-formaui-components-dynamic-form.mjs +0 -266
- package/fesm2022/raintonic-formaui-components-dynamic-form.mjs.map +0 -1
- package/types/raintonic-formaui-components-dynamic-form.d.ts +0 -412
- package/types/raintonic-formaui-components-dynamic-form.d.ts.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { Injectable, InjectionToken, inject, ChangeDetectorRef, input, computed, output, signal, contentChildren, ElementRef, NgZone, effect, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
3
4
|
import { NgForm, FormGroupDirective, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
5
|
import { DOCUMENT } from '@angular/common';
|
|
5
6
|
import { Subject, Subscription, fromEvent } from 'rxjs';
|
|
@@ -7,10 +8,28 @@ import { filter } from 'rxjs/operators';
|
|
|
7
8
|
import { injectNgControl, updateErrorState, syncRequiredState, syncNgControlDisabled } from '@raintonic/formaui/cdk/form-field';
|
|
8
9
|
import { FuiIconComponent } from '@raintonic/formaui/components/icon';
|
|
9
10
|
import { FuiButtonDirective } from '@raintonic/formaui/components/button';
|
|
10
|
-
import { DefaultErrorStateMatcher, FUI_FORM_FIELD_CONTROL } from '@raintonic/formaui/core';
|
|
11
|
+
import { FuiIntlBase, DefaultErrorStateMatcher, FUI_FORM_FIELD_CONTROL } from '@raintonic/formaui/core';
|
|
11
12
|
import { FuiOptionComponent } from '@raintonic/formaui/components/select';
|
|
12
13
|
import { FuiOverlayService } from '@raintonic/formaui/cdk/overlay';
|
|
13
14
|
|
|
15
|
+
class FuiAutocompleteIntl extends FuiIntlBase {
|
|
16
|
+
addButtonLabel = 'Add New';
|
|
17
|
+
refreshButtonLabel = 'Refresh';
|
|
18
|
+
noOptionsText = 'No options found';
|
|
19
|
+
searchPlaceholder = 'Search...';
|
|
20
|
+
clearSelectionAriaLabel = 'Clear selection';
|
|
21
|
+
noResultsAvailableText = 'No results available.';
|
|
22
|
+
resultsAvailableText(count) {
|
|
23
|
+
return `${count} results available.`;
|
|
24
|
+
}
|
|
25
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiAutocompleteIntl, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
26
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiAutocompleteIntl, providedIn: 'root' });
|
|
27
|
+
}
|
|
28
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiAutocompleteIntl, decorators: [{
|
|
29
|
+
type: Injectable,
|
|
30
|
+
args: [{ providedIn: 'root' }]
|
|
31
|
+
}] });
|
|
32
|
+
|
|
14
33
|
/**
|
|
15
34
|
* Injection token used to provide the parent autocomplete to options
|
|
16
35
|
*/
|
|
@@ -85,17 +104,25 @@ class FuiAutocompleteComponent {
|
|
|
85
104
|
// Static properties
|
|
86
105
|
static nextId = 0;
|
|
87
106
|
controlType = 'fui-autocomplete';
|
|
107
|
+
// Injected dependencies required by input resolvers (must be declared before computed fields below)
|
|
108
|
+
intl = inject(FuiAutocompleteIntl);
|
|
109
|
+
_cdr = inject(ChangeDetectorRef);
|
|
88
110
|
// Inputs using signal-based API
|
|
89
111
|
placeholderInput = input('', { ...(ngDevMode ? { debugName: "placeholderInput" } : /* istanbul ignore next */ {}), alias: 'placeholder' });
|
|
90
112
|
disabledInput = input(false, { ...(ngDevMode ? { debugName: "disabledInput" } : /* istanbul ignore next */ {}), alias: 'disabled' });
|
|
91
113
|
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
92
114
|
showAddButton = input(false, ...(ngDevMode ? [{ debugName: "showAddButton" }] : /* istanbul ignore next */ []));
|
|
93
115
|
showRefreshButton = input(false, ...(ngDevMode ? [{ debugName: "showRefreshButton" }] : /* istanbul ignore next */ []));
|
|
94
|
-
addButtonLabel = input(
|
|
95
|
-
refreshButtonLabel = input(
|
|
96
|
-
noOptionsText = input(
|
|
97
|
-
searchPlaceholder = input(
|
|
116
|
+
addButtonLabel = input(undefined, ...(ngDevMode ? [{ debugName: "addButtonLabel" }] : /* istanbul ignore next */ []));
|
|
117
|
+
refreshButtonLabel = input(undefined, ...(ngDevMode ? [{ debugName: "refreshButtonLabel" }] : /* istanbul ignore next */ []));
|
|
118
|
+
noOptionsText = input(undefined, ...(ngDevMode ? [{ debugName: "noOptionsText" }] : /* istanbul ignore next */ []));
|
|
119
|
+
searchPlaceholder = input(undefined, ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
|
|
98
120
|
errorStateMatcher = input(null, ...(ngDevMode ? [{ debugName: "errorStateMatcher" }] : /* istanbul ignore next */ []));
|
|
121
|
+
// Resolved i18n labels: per-instance input wins, Intl service is fallback
|
|
122
|
+
resolvedAddButtonLabel = computed(() => this.addButtonLabel() ?? this.intl.addButtonLabel, ...(ngDevMode ? [{ debugName: "resolvedAddButtonLabel" }] : /* istanbul ignore next */ []));
|
|
123
|
+
resolvedRefreshButtonLabel = computed(() => this.refreshButtonLabel() ?? this.intl.refreshButtonLabel, ...(ngDevMode ? [{ debugName: "resolvedRefreshButtonLabel" }] : /* istanbul ignore next */ []));
|
|
124
|
+
resolvedNoOptionsText = computed(() => this.noOptionsText() ?? this.intl.noOptionsText, ...(ngDevMode ? [{ debugName: "resolvedNoOptionsText" }] : /* istanbul ignore next */ []));
|
|
125
|
+
resolvedSearchPlaceholder = computed(() => this.searchPlaceholder() ?? this.intl.searchPlaceholder, ...(ngDevMode ? [{ debugName: "resolvedSearchPlaceholder" }] : /* istanbul ignore next */ []));
|
|
99
126
|
/**
|
|
100
127
|
* Whether to compare option values using object identity or deep equality
|
|
101
128
|
*/
|
|
@@ -205,6 +232,8 @@ class FuiAutocompleteComponent {
|
|
|
205
232
|
this._ngControlRef.ngControl.valueAccessor = this;
|
|
206
233
|
}
|
|
207
234
|
});
|
|
235
|
+
// Subscribe to Intl changes to trigger re-render when labels mutate at runtime
|
|
236
|
+
this.intl.changes.pipe(takeUntilDestroyed()).subscribe(() => { this._cdr.markForCheck(); });
|
|
208
237
|
// Effect to emit state changes
|
|
209
238
|
effect(() => {
|
|
210
239
|
// Track all reactive inputs and internal signals
|
|
@@ -680,7 +709,7 @@ class FuiAutocompleteComponent {
|
|
|
680
709
|
provide: FUI_AUTOCOMPLETE,
|
|
681
710
|
useExisting: FuiAutocompleteComponent,
|
|
682
711
|
},
|
|
683
|
-
], queries: [{ propertyName: "options", predicate: FuiOptionComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "<!-- Autocomplete Trigger -->\r\n<div\r\n #trigger\r\n [id]=\"id\"\r\n class=\"fui-autocomplete__trigger\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n [attr.role]=\"'combobox'\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-expanded]=\"panelOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-invalid]=\"errorState()\"\r\n [attr.aria-describedby]=\"_ariaDescribedby\"\r\n [attr.aria-required]=\"required()\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-activedescendant]=\"panelOpen() ? _getActiveDescendant() : null\"\r\n [attr.aria-controls]=\"panelOpen() ? id + '-panel' : null\"\r\n (keydown)=\"_handleKeydown($event)\"\r\n>\r\n <span class=\"fui-autocomplete__value\">\r\n @if (empty()) {\r\n <span class=\"fui-autocomplete__placeholder\">{{ placeholder() }}</span>\r\n } @else {\r\n <span class=\"fui-autocomplete__value-text\">{{ _getDisplayValue() }}</span>\r\n }\r\n </span>\r\n\r\n @if (!_readOnly()) {\r\n <!-- Clear button \u2014 visible only when a value is selected and not disabled -->\r\n @if (!empty() && !disabled()) {\r\n <span class=\"fui-autocomplete__clear\" role=\"button\" aria-label=\"Clear selection\" (click)=\"clear($event)\">\r\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\r\n <path\r\n d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\"\r\n />\r\n </svg>\r\n </span>\r\n }\r\n\r\n <!-- Dropdown arrow icon -->\r\n <svg\r\n class=\"fui-autocomplete__arrow\"\r\n [class.fui-autocomplete__arrow--open]=\"panelOpen()\"\r\n viewBox=\"0 0 16 16\"\r\n fill=\"currentColor\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M8 11L3 6l.7-.7L8 9.6l4.3-4.3L13 6z\" />\r\n </svg>\r\n }\r\n</div>\r\n\r\n<!-- Hidden container for projected options (used for data binding) -->\r\n<div class=\"fui-autocomplete__options-source\">\r\n <ng-content></ng-content>\r\n</div>\r\n\r\n<!-- Dropdown Panel -->\r\n@if (panelOpen()) {\r\n <div #panel [id]=\"id + '-panel'\" class=\"fui-autocomplete__panel\" [attr.aria-label]=\"placeholder()\">\r\n <!-- Search Input -->\r\n <div class=\"fui-autocomplete__search\">\r\n <fui-icon name=\"magnifying-glass\" size=\"sm\" class=\"fui-autocomplete__search-icon\"> </fui-icon>\r\n <input\r\n #searchInput\r\n type=\"text\"\r\n class=\"fui-autocomplete__search-input\"\r\n [placeholder]=\"searchPlaceholder()\"\r\n [value]=\"searchTerm()\"\r\n autocomplete=\"off\"\r\n role=\"searchbox\"\r\n [attr.aria-label]=\"searchPlaceholder()\"\r\n [attr.aria-controls]=\"id + '-panel-listbox'\"\r\n [attr.aria-activedescendant]=\"_getActiveDescendant()\"\r\n (input)=\"onSearchInput($event)\"\r\n (keydown)=\"_handlePanelKeydown($event)\"\r\n />\r\n </div>\r\n <!-- Live region for announcing result count to screen readers -->\r\n <div class=\"fui-visually-hidden\" aria-live=\"assertive\" aria-atomic=\"true\">\r\n @if (_liveAnnouncement()) {\r\n {{ _liveAnnouncement() }}\r\n } @else if (hasFilteredOptions()) {\r\n {{ filteredOptions().length }} results available.\r\n } @else {\r\n No results available.\r\n }\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n @if (showAddButton() || showRefreshButton()) {\r\n <div class=\"fui-autocomplete__actions\">\r\n @if (showAddButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onAddNew()\"\r\n >\r\n <fui-icon name=\"plus\" size=\"sm\"></fui-icon>\r\n {{ addButtonLabel() }}\r\n </button>\r\n }\r\n @if (showRefreshButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onRefresh()\"\r\n >\r\n <fui-icon name=\"refresh-cw\" size=\"sm\"></fui-icon>\r\n {{ refreshButtonLabel() }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Options List -->\r\n <div\r\n class=\"fui-autocomplete__options\"\r\n [id]=\"id + '-panel-listbox'\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"placeholder()\"\r\n >\r\n @if (hasFilteredOptions()) {\r\n @for (option of filteredOptions(); track option.id; let i = $index) {\r\n <div\r\n class=\"fui-autocomplete__option\"\r\n [class.fui-autocomplete__option--active]=\"activeOptionIndex() === i\"\r\n [class.fui-autocomplete__option--selected]=\"option._selected()\"\r\n role=\"option\"\r\n [attr.id]=\"option.id\"\r\n [attr.aria-selected]=\"option._selected()\"\r\n (click)=\"_onOptionSelected(option)\"\r\n (mouseenter)=\"setActiveOption(i, option)\"\r\n (mouseleave)=\"option.setInactive()\"\r\n >\r\n <span class=\"fui-autocomplete__option-text\">{{ option.getLabel() }}</span>\r\n @if (option._selected()) {\r\n <fui-icon name=\"check\" size=\"sm\" class=\"fui-autocomplete__option-check\"></fui-icon>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"fui-autocomplete__no-options\">\r\n {{ noOptionsText() }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}.fui-autocomplete{--fui-autocomplete-font-size: var(--fui-font-size-02);--fui-autocomplete-panel-max-height: 24rem;--fui-autocomplete-panel-border-radius: var(--fui-border-radius-sm);--fui-autocomplete-panel-shadow: var(--fui-shadow-03);--fui-autocomplete-panel-bg: var(--fui-surface-00);--fui-autocomplete-option-padding: .5rem .75rem;--fui-autocomplete-search-padding: .75rem;position:relative;display:inline-block;width:100%}.fui-autocomplete__options-source{display:none}.fui-autocomplete__trigger{display:flex;align-items:center;width:100%;border:none;color:var(--fui-text-primary);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;cursor:pointer;outline:none;transition:border-color var(--fui-duration-fast-01) var(--fui-ease-standard),background-color var(--fui-duration-fast-01) var(--fui-ease-standard);gap:.25rem}.fui-autocomplete__trigger:hover:not([aria-disabled=true]){background-color:var(--fui-field-background-hover)}.fui-autocomplete__trigger[aria-disabled=true]{background-color:var(--fui-field-background-disabled);color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.fui-autocomplete__placeholder{color:var(--fui-text-secondary)}.fui-autocomplete__value-text{color:var(--fui-text-primary)}.fui-autocomplete__clear{display:flex;align-items:center;justify-content:center;width:1rem;height:1rem;cursor:pointer;color:var(--fui-icon-secondary);flex-shrink:0;border-radius:50%;transition:color var(--fui-duration-fast-01) var(--fui-ease-standard),background-color var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__clear svg{width:.75rem;height:.75rem}.fui-autocomplete__clear:hover{color:var(--fui-text-primary);background-color:var(--fui-background-hover)}.fui-autocomplete__arrow{width:1rem;height:1rem;flex-shrink:0;color:var(--fui-icon-primary);pointer-events:none;transition:transform var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__arrow--open{transform:rotate(180deg)}.fui-autocomplete__panel{position:absolute;width:100%;background-color:var(--fui-autocomplete-panel-bg);border:1px solid var(--fui-border-color);border-radius:var(--fui-autocomplete-panel-border-radius);box-shadow:var(--fui-autocomplete-panel-shadow);max-height:var(--fui-autocomplete-panel-max-height);overflow:hidden;display:flex;flex-direction:column}.fui-autocomplete__search{position:relative;padding:.75rem;border-bottom:1px solid var(--fui-border-color);background-color:var(--fui-field-background)}.fui-autocomplete__search-icon{position:absolute;left:1.5rem;top:50%;transform:translateY(-50%);color:var(--fui-icon-secondary);pointer-events:none}.fui-autocomplete__search-input{width:100%;padding:.5rem .75rem .5rem 2.5rem;border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);background-color:var(--fui-background-primary);color:var(--fui-text-primary);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;transition:border-color var(--fui-duration-fast-01) var(--fui-ease-standard),outline var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__search-input:focus{outline:2px solid var(--fui-primary);outline-offset:-2px;border-color:var(--fui-primary)}.fui-autocomplete__search-input::placeholder{color:var(--fui-text-secondary)}.fui-autocomplete__actions{display:flex;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid var(--fui-border-color);background-color:var(--fui-field-background)}.fui-autocomplete__action-button{display:flex;align-items:center;gap:.25rem;font-size:var(--fui-font-size-01)}.fui-autocomplete__action-button fui-icon{flex-shrink:0}.fui-autocomplete__options{max-height:16rem;overflow-y:auto;padding:.25rem 0;background-color:var(--fui-surface-01);scrollbar-width:thin;scrollbar-color:var(--fui-border-color) transparent}.fui-autocomplete__options::-webkit-scrollbar{width:6px}.fui-autocomplete__options::-webkit-scrollbar-track{background:transparent}.fui-autocomplete__options::-webkit-scrollbar-thumb{background-color:var(--fui-border-color);border-radius:3px}.fui-autocomplete__options::-webkit-scrollbar-thumb:hover{background-color:var(--fui-text-secondary)}.fui-autocomplete__option{display:flex;align-items:center;justify-content:space-between;padding:.5rem .75rem;cursor:pointer;color:var(--fui-text-primary);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;transition:background-color var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__option:hover:not(.fui-autocomplete__option--disabled){background-color:var(--fui-background-hover)}.fui-autocomplete__option--active{background-color:var(--fui-surface-05)}.fui-autocomplete__option--selected{background-color:var(--fui-surface-05);font-weight:600}.fui-autocomplete__option--disabled{color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete__option-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-autocomplete__option-check{color:var(--fui-icon-primary);flex-shrink:0;margin-left:.5rem}.fui-autocomplete__no-options{padding:1rem .75rem;text-align:center;color:var(--fui-text-secondary);font-size:var(--fui-font-size-02);font-style:italic}.fui-autocomplete--disabled .fui-autocomplete__trigger{background-color:var(--fui-field-background-disabled);color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete--disabled .fui-autocomplete__arrow{color:var(--fui-text-primary-disabled)}.fui-autocomplete--readonly .fui-autocomplete__trigger{background-color:transparent;min-height:unset;cursor:default;color:var(--fui-text-primary)}.fui-autocomplete--readonly .fui-autocomplete__trigger[aria-disabled=true]{background-color:transparent;color:var(--fui-text-primary);cursor:default}.fui-autocomplete--readonly .fui-autocomplete__value-text{color:var(--fui-text-primary)}.fui-autocomplete--error .fui-autocomplete__trigger{border-bottom-color:var(--fui-error)}.fui-autocomplete--error .fui-autocomplete__trigger:focus{outline-color:var(--fui-error)}.fui-autocomplete-overlay-panel .fui-autocomplete__panel{border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);box-shadow:var(--fui-shadow-03)}.fui-autocomplete-backdrop{background:transparent}@media(prefers-contrast:high){.fui-autocomplete__trigger,.fui-autocomplete__panel{border-width:2px}.fui-autocomplete__trigger:focus,.fui-autocomplete__search-input:focus{outline-width:3px}.fui-autocomplete__option--active,.fui-autocomplete__option--selected{outline:2px solid var(--fui-primary);outline-offset:-2px}}@media(prefers-reduced-motion:reduce){.fui-autocomplete__trigger,.fui-autocomplete__arrow,.fui-autocomplete__option,.fui-autocomplete__search-input{transition:none}}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: FuiButtonDirective, selector: "button[fuiButton], a[fuiButton]", inputs: ["variant", "size", "disabled", "fullWidth", "loading", "iconOnly", "aria-label", "type"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
712
|
+
], queries: [{ propertyName: "options", predicate: FuiOptionComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "<!-- Autocomplete Trigger -->\r\n<div\r\n #trigger\r\n [id]=\"id\"\r\n class=\"fui-autocomplete__trigger\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n [attr.role]=\"'combobox'\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-expanded]=\"panelOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-invalid]=\"errorState()\"\r\n [attr.aria-describedby]=\"_ariaDescribedby\"\r\n [attr.aria-required]=\"required()\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-activedescendant]=\"panelOpen() ? _getActiveDescendant() : null\"\r\n [attr.aria-controls]=\"panelOpen() ? id + '-panel' : null\"\r\n (keydown)=\"_handleKeydown($event)\"\r\n>\r\n <span class=\"fui-autocomplete__value\">\r\n @if (empty()) {\r\n <span class=\"fui-autocomplete__placeholder\">{{ placeholder() }}</span>\r\n } @else {\r\n <span class=\"fui-autocomplete__value-text\">{{ _getDisplayValue() }}</span>\r\n }\r\n </span>\r\n\r\n @if (!_readOnly()) {\r\n <!-- Clear button \u2014 visible only when a value is selected and not disabled -->\r\n @if (!empty() && !disabled()) {\r\n <span class=\"fui-autocomplete__clear\" role=\"button\" [attr.aria-label]=\"intl.clearSelectionAriaLabel\" (click)=\"clear($event)\">\r\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\r\n <path\r\n d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\"\r\n />\r\n </svg>\r\n </span>\r\n }\r\n\r\n <!-- Dropdown arrow icon -->\r\n <svg\r\n class=\"fui-autocomplete__arrow\"\r\n [class.fui-autocomplete__arrow--open]=\"panelOpen()\"\r\n viewBox=\"0 0 16 16\"\r\n fill=\"currentColor\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M8 11L3 6l.7-.7L8 9.6l4.3-4.3L13 6z\" />\r\n </svg>\r\n }\r\n</div>\r\n\r\n<!-- Hidden container for projected options (used for data binding) -->\r\n<div class=\"fui-autocomplete__options-source\">\r\n <ng-content></ng-content>\r\n</div>\r\n\r\n<!-- Dropdown Panel -->\r\n@if (panelOpen()) {\r\n <div #panel [id]=\"id + '-panel'\" class=\"fui-autocomplete__panel\" [attr.aria-label]=\"placeholder()\">\r\n <!-- Search Input -->\r\n <div class=\"fui-autocomplete__search\">\r\n <fui-icon name=\"magnifying-glass\" size=\"sm\" class=\"fui-autocomplete__search-icon\"> </fui-icon>\r\n <input\r\n #searchInput\r\n type=\"text\"\r\n class=\"fui-autocomplete__search-input\"\r\n [placeholder]=\"resolvedSearchPlaceholder()\"\r\n [value]=\"searchTerm()\"\r\n autocomplete=\"off\"\r\n role=\"searchbox\"\r\n [attr.aria-label]=\"resolvedSearchPlaceholder()\"\r\n [attr.aria-controls]=\"id + '-panel-listbox'\"\r\n [attr.aria-activedescendant]=\"_getActiveDescendant()\"\r\n (input)=\"onSearchInput($event)\"\r\n (keydown)=\"_handlePanelKeydown($event)\"\r\n />\r\n </div>\r\n <!-- Live region for announcing result count to screen readers -->\r\n <div class=\"fui-sr-only\" aria-live=\"assertive\" aria-atomic=\"true\">\r\n @if (_liveAnnouncement()) {\r\n {{ _liveAnnouncement() }}\r\n } @else if (hasFilteredOptions()) {\r\n {{ intl.resultsAvailableText(filteredOptions().length) }}\r\n } @else {\r\n {{ intl.noResultsAvailableText }}\r\n }\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n @if (showAddButton() || showRefreshButton()) {\r\n <div class=\"fui-autocomplete__actions\">\r\n @if (showAddButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"tertiary\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onAddNew()\"\r\n >\r\n <fui-icon name=\"plus\" size=\"sm\"></fui-icon>\r\n {{ resolvedAddButtonLabel() }}\r\n </button>\r\n }\r\n @if (showRefreshButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"tertiary\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onRefresh()\"\r\n >\r\n <fui-icon name=\"refresh-cw\" size=\"sm\"></fui-icon>\r\n {{ resolvedRefreshButtonLabel() }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Options List -->\r\n <div\r\n class=\"fui-autocomplete__options\"\r\n [id]=\"id + '-panel-listbox'\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"placeholder()\"\r\n >\r\n @if (hasFilteredOptions()) {\r\n @for (option of filteredOptions(); track option.id; let i = $index) {\r\n <div\r\n class=\"fui-autocomplete__option\"\r\n [class.fui-autocomplete__option--active]=\"activeOptionIndex() === i\"\r\n [class.fui-autocomplete__option--selected]=\"option._selected()\"\r\n role=\"option\"\r\n [attr.id]=\"option.id\"\r\n [attr.aria-selected]=\"option._selected()\"\r\n (click)=\"_onOptionSelected(option)\"\r\n (mouseenter)=\"setActiveOption(i, option)\"\r\n (mouseleave)=\"option.setInactive()\"\r\n >\r\n <span class=\"fui-autocomplete__option-text\">{{ option.getLabel() }}</span>\r\n @if (option._selected()) {\r\n <fui-icon name=\"check\" size=\"sm\" class=\"fui-autocomplete__option-check\"></fui-icon>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"fui-autocomplete__no-options\">\r\n {{ resolvedNoOptionsText() }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-autocomplete{--fui-autocomplete-font-size: var(--fui-font-size-02);--fui-autocomplete-panel-max-height: 24rem;--fui-autocomplete-panel-border-radius: var(--fui-border-radius-sm);--fui-autocomplete-panel-shadow: var(--fui-shadow-04);--fui-autocomplete-panel-bg: var(--fui-surface-00);--fui-autocomplete-option-padding: .5rem .75rem;--fui-autocomplete-search-padding: .75rem;position:relative;display:inline-block;width:100%}.fui-autocomplete__options-source{display:none}.fui-autocomplete__trigger{display:flex;align-items:center;width:100%;border:none;color:var(--fui-text-primary);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;cursor:pointer;outline:none;transition:border-color var(--fui-duration-fast-01) var(--fui-ease-standard),background-color var(--fui-duration-fast-01) var(--fui-ease-standard);gap:.25rem}.fui-autocomplete__trigger:hover:not([aria-disabled=true]){background-color:var(--fui-field-background-hover)}.fui-autocomplete__trigger[aria-disabled=true]{background-color:var(--fui-field-background-disabled);color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.fui-autocomplete__placeholder{color:var(--fui-text-secondary)}.fui-autocomplete__value-text{color:var(--fui-text-primary)}.fui-autocomplete__clear{display:flex;align-items:center;justify-content:center;width:1rem;height:1rem;cursor:pointer;color:var(--fui-icon-secondary);flex-shrink:0;border-radius:50%;transition:color var(--fui-duration-fast-01) var(--fui-ease-standard),background-color var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__clear svg{width:.75rem;height:.75rem}.fui-autocomplete__clear:hover{color:var(--fui-text-primary);background-color:var(--fui-background-hover)}.fui-autocomplete__arrow{width:1rem;height:1rem;flex-shrink:0;color:var(--fui-icon-primary);pointer-events:none;transition:transform var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__arrow--open{transform:rotate(180deg)}.fui-autocomplete__panel{position:absolute;width:100%;background-color:var(--fui-autocomplete-panel-bg);border:1px solid var(--fui-border-color);border-radius:var(--fui-autocomplete-panel-border-radius);box-shadow:var(--fui-autocomplete-panel-shadow);max-height:var(--fui-autocomplete-panel-max-height);overflow:hidden;display:flex;flex-direction:column}.fui-autocomplete__search{position:relative;padding:.75rem;border-bottom:1px solid var(--fui-border-color);background-color:var(--fui-field-background)}.fui-autocomplete__search-icon{position:absolute;left:1.5rem;top:50%;transform:translateY(-50%);color:var(--fui-icon-secondary);pointer-events:none}.fui-autocomplete__search-input{width:100%;padding:.5rem .75rem .5rem 2.5rem;border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);background-color:var(--fui-background-primary);color:var(--fui-text-primary);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;transition:border-color var(--fui-duration-fast-01) var(--fui-ease-standard),outline var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__search-input:focus{outline:2px solid var(--fui-primary);outline-offset:-2px;border-color:var(--fui-primary)}.fui-autocomplete__search-input::placeholder{color:var(--fui-text-secondary)}.fui-autocomplete__actions{display:flex;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid var(--fui-border-color);background-color:var(--fui-field-background)}.fui-autocomplete__action-button{display:flex;align-items:center;gap:.25rem;font-size:var(--fui-font-size-01)}.fui-autocomplete__action-button fui-icon{flex-shrink:0}.fui-autocomplete__options{max-height:16rem;overflow-y:auto;padding:.25rem 0;background-color:var(--fui-surface-01);scrollbar-width:thin;scrollbar-color:var(--fui-border-color) transparent}.fui-autocomplete__options::-webkit-scrollbar{width:6px}.fui-autocomplete__options::-webkit-scrollbar-track{background:transparent}.fui-autocomplete__options::-webkit-scrollbar-thumb{background-color:var(--fui-border-color);border-radius:3px}.fui-autocomplete__options::-webkit-scrollbar-thumb:hover{background-color:var(--fui-text-secondary)}.fui-autocomplete__option{display:flex;align-items:center;justify-content:space-between;padding:.5rem .75rem;cursor:pointer;color:var(--fui-text-primary);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;transition:background-color var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__option:hover:not(.fui-autocomplete__option--disabled){background-color:var(--fui-background-hover)}.fui-autocomplete__option--active{background-color:var(--fui-surface-05)}.fui-autocomplete__option--selected{background-color:var(--fui-surface-05);font-weight:600}.fui-autocomplete__option--disabled{color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete__option-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-autocomplete__option-check{color:var(--fui-icon-primary);flex-shrink:0;margin-left:.5rem}.fui-autocomplete__no-options{padding:1rem .75rem;text-align:center;color:var(--fui-text-secondary);font-size:var(--fui-font-size-02);font-style:italic}.fui-autocomplete--disabled .fui-autocomplete__trigger{background-color:var(--fui-field-background-disabled);color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete--disabled .fui-autocomplete__arrow{color:var(--fui-text-primary-disabled)}.fui-autocomplete--readonly .fui-autocomplete__trigger{background-color:transparent;min-height:unset;cursor:default;color:var(--fui-text-primary)}.fui-autocomplete--readonly .fui-autocomplete__trigger[aria-disabled=true]{background-color:transparent;color:var(--fui-text-primary);cursor:default}.fui-autocomplete--readonly .fui-autocomplete__value-text{color:var(--fui-text-primary)}.fui-autocomplete--error .fui-autocomplete__trigger{border-bottom-color:var(--fui-error)}.fui-autocomplete--error .fui-autocomplete__trigger:focus{outline-color:var(--fui-error)}.fui-autocomplete-overlay-panel .fui-autocomplete__panel{border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);box-shadow:var(--fui-shadow-04);transform-origin:top center;animation:fui-popover-enter var(--fui-duration-moderate-01) var(--fui-ease-entrance) both;will-change:transform,opacity}.fui-autocomplete-backdrop{background:transparent}@media(prefers-contrast:high){.fui-autocomplete__trigger,.fui-autocomplete__panel{border-width:2px}.fui-autocomplete__trigger:focus,.fui-autocomplete__search-input:focus{outline-width:3px}.fui-autocomplete__option--active,.fui-autocomplete__option--selected{outline:2px solid var(--fui-primary);outline-offset:-2px}}@media(prefers-reduced-motion:reduce){.fui-autocomplete__trigger,.fui-autocomplete__arrow,.fui-autocomplete__option,.fui-autocomplete__search-input{transition:none}.fui-autocomplete-overlay-panel .fui-autocomplete__panel{animation:none}}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: FuiButtonDirective, selector: "button[fuiButton], a[fuiButton]", inputs: ["variant", "size", "disabled", "fullWidth", "loading", "iconOnly", "aria-label", "type"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
684
713
|
}
|
|
685
714
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiAutocompleteComponent, decorators: [{
|
|
686
715
|
type: Component,
|
|
@@ -706,7 +735,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
|
|
|
706
735
|
provide: FUI_AUTOCOMPLETE,
|
|
707
736
|
useExisting: FuiAutocompleteComponent,
|
|
708
737
|
},
|
|
709
|
-
], template: "<!-- Autocomplete Trigger -->\r\n<div\r\n #trigger\r\n [id]=\"id\"\r\n class=\"fui-autocomplete__trigger\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n [attr.role]=\"'combobox'\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-expanded]=\"panelOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-invalid]=\"errorState()\"\r\n [attr.aria-describedby]=\"_ariaDescribedby\"\r\n [attr.aria-required]=\"required()\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-activedescendant]=\"panelOpen() ? _getActiveDescendant() : null\"\r\n [attr.aria-controls]=\"panelOpen() ? id + '-panel' : null\"\r\n (keydown)=\"_handleKeydown($event)\"\r\n>\r\n <span class=\"fui-autocomplete__value\">\r\n @if (empty()) {\r\n <span class=\"fui-autocomplete__placeholder\">{{ placeholder() }}</span>\r\n } @else {\r\n <span class=\"fui-autocomplete__value-text\">{{ _getDisplayValue() }}</span>\r\n }\r\n </span>\r\n\r\n @if (!_readOnly()) {\r\n <!-- Clear button \u2014 visible only when a value is selected and not disabled -->\r\n @if (!empty() && !disabled()) {\r\n <span class=\"fui-autocomplete__clear\" role=\"button\" aria-label=\"Clear selection\" (click)=\"clear($event)\">\r\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\r\n <path\r\n d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\"\r\n />\r\n </svg>\r\n </span>\r\n }\r\n\r\n <!-- Dropdown arrow icon -->\r\n <svg\r\n class=\"fui-autocomplete__arrow\"\r\n [class.fui-autocomplete__arrow--open]=\"panelOpen()\"\r\n viewBox=\"0 0 16 16\"\r\n fill=\"currentColor\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M8 11L3 6l.7-.7L8 9.6l4.3-4.3L13 6z\" />\r\n </svg>\r\n }\r\n</div>\r\n\r\n<!-- Hidden container for projected options (used for data binding) -->\r\n<div class=\"fui-autocomplete__options-source\">\r\n <ng-content></ng-content>\r\n</div>\r\n\r\n<!-- Dropdown Panel -->\r\n@if (panelOpen()) {\r\n <div #panel [id]=\"id + '-panel'\" class=\"fui-autocomplete__panel\" [attr.aria-label]=\"placeholder()\">\r\n <!-- Search Input -->\r\n <div class=\"fui-autocomplete__search\">\r\n <fui-icon name=\"magnifying-glass\" size=\"sm\" class=\"fui-autocomplete__search-icon\"> </fui-icon>\r\n <input\r\n #searchInput\r\n type=\"text\"\r\n class=\"fui-autocomplete__search-input\"\r\n [placeholder]=\"searchPlaceholder()\"\r\n [value]=\"searchTerm()\"\r\n autocomplete=\"off\"\r\n role=\"searchbox\"\r\n [attr.aria-label]=\"searchPlaceholder()\"\r\n [attr.aria-controls]=\"id + '-panel-listbox'\"\r\n [attr.aria-activedescendant]=\"_getActiveDescendant()\"\r\n (input)=\"onSearchInput($event)\"\r\n (keydown)=\"_handlePanelKeydown($event)\"\r\n />\r\n </div>\r\n <!-- Live region for announcing result count to screen readers -->\r\n <div class=\"fui-visually-hidden\" aria-live=\"assertive\" aria-atomic=\"true\">\r\n @if (_liveAnnouncement()) {\r\n {{ _liveAnnouncement() }}\r\n } @else if (hasFilteredOptions()) {\r\n {{ filteredOptions().length }} results available.\r\n } @else {\r\n No results available.\r\n }\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n @if (showAddButton() || showRefreshButton()) {\r\n <div class=\"fui-autocomplete__actions\">\r\n @if (showAddButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onAddNew()\"\r\n >\r\n <fui-icon name=\"plus\" size=\"sm\"></fui-icon>\r\n {{ addButtonLabel() }}\r\n </button>\r\n }\r\n @if (showRefreshButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onRefresh()\"\r\n >\r\n <fui-icon name=\"refresh-cw\" size=\"sm\"></fui-icon>\r\n {{ refreshButtonLabel() }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Options List -->\r\n <div\r\n class=\"fui-autocomplete__options\"\r\n [id]=\"id + '-panel-listbox'\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"placeholder()\"\r\n >\r\n @if (hasFilteredOptions()) {\r\n @for (option of filteredOptions(); track option.id; let i = $index) {\r\n <div\r\n class=\"fui-autocomplete__option\"\r\n [class.fui-autocomplete__option--active]=\"activeOptionIndex() === i\"\r\n [class.fui-autocomplete__option--selected]=\"option._selected()\"\r\n role=\"option\"\r\n [attr.id]=\"option.id\"\r\n [attr.aria-selected]=\"option._selected()\"\r\n (click)=\"_onOptionSelected(option)\"\r\n (mouseenter)=\"setActiveOption(i, option)\"\r\n (mouseleave)=\"option.setInactive()\"\r\n >\r\n <span class=\"fui-autocomplete__option-text\">{{ option.getLabel() }}</span>\r\n @if (option._selected()) {\r\n <fui-icon name=\"check\" size=\"sm\" class=\"fui-autocomplete__option-check\"></fui-icon>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"fui-autocomplete__no-options\">\r\n {{ noOptionsText() }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}.fui-autocomplete{--fui-autocomplete-font-size: var(--fui-font-size-02);--fui-autocomplete-panel-max-height: 24rem;--fui-autocomplete-panel-border-radius: var(--fui-border-radius-sm);--fui-autocomplete-panel-shadow: var(--fui-shadow-03);--fui-autocomplete-panel-bg: var(--fui-surface-00);--fui-autocomplete-option-padding: .5rem .75rem;--fui-autocomplete-search-padding: .75rem;position:relative;display:inline-block;width:100%}.fui-autocomplete__options-source{display:none}.fui-autocomplete__trigger{display:flex;align-items:center;width:100%;border:none;color:var(--fui-text-primary);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;cursor:pointer;outline:none;transition:border-color var(--fui-duration-fast-01) var(--fui-ease-standard),background-color var(--fui-duration-fast-01) var(--fui-ease-standard);gap:.25rem}.fui-autocomplete__trigger:hover:not([aria-disabled=true]){background-color:var(--fui-field-background-hover)}.fui-autocomplete__trigger[aria-disabled=true]{background-color:var(--fui-field-background-disabled);color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.fui-autocomplete__placeholder{color:var(--fui-text-secondary)}.fui-autocomplete__value-text{color:var(--fui-text-primary)}.fui-autocomplete__clear{display:flex;align-items:center;justify-content:center;width:1rem;height:1rem;cursor:pointer;color:var(--fui-icon-secondary);flex-shrink:0;border-radius:50%;transition:color var(--fui-duration-fast-01) var(--fui-ease-standard),background-color var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__clear svg{width:.75rem;height:.75rem}.fui-autocomplete__clear:hover{color:var(--fui-text-primary);background-color:var(--fui-background-hover)}.fui-autocomplete__arrow{width:1rem;height:1rem;flex-shrink:0;color:var(--fui-icon-primary);pointer-events:none;transition:transform var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__arrow--open{transform:rotate(180deg)}.fui-autocomplete__panel{position:absolute;width:100%;background-color:var(--fui-autocomplete-panel-bg);border:1px solid var(--fui-border-color);border-radius:var(--fui-autocomplete-panel-border-radius);box-shadow:var(--fui-autocomplete-panel-shadow);max-height:var(--fui-autocomplete-panel-max-height);overflow:hidden;display:flex;flex-direction:column}.fui-autocomplete__search{position:relative;padding:.75rem;border-bottom:1px solid var(--fui-border-color);background-color:var(--fui-field-background)}.fui-autocomplete__search-icon{position:absolute;left:1.5rem;top:50%;transform:translateY(-50%);color:var(--fui-icon-secondary);pointer-events:none}.fui-autocomplete__search-input{width:100%;padding:.5rem .75rem .5rem 2.5rem;border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);background-color:var(--fui-background-primary);color:var(--fui-text-primary);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;transition:border-color var(--fui-duration-fast-01) var(--fui-ease-standard),outline var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__search-input:focus{outline:2px solid var(--fui-primary);outline-offset:-2px;border-color:var(--fui-primary)}.fui-autocomplete__search-input::placeholder{color:var(--fui-text-secondary)}.fui-autocomplete__actions{display:flex;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid var(--fui-border-color);background-color:var(--fui-field-background)}.fui-autocomplete__action-button{display:flex;align-items:center;gap:.25rem;font-size:var(--fui-font-size-01)}.fui-autocomplete__action-button fui-icon{flex-shrink:0}.fui-autocomplete__options{max-height:16rem;overflow-y:auto;padding:.25rem 0;background-color:var(--fui-surface-01);scrollbar-width:thin;scrollbar-color:var(--fui-border-color) transparent}.fui-autocomplete__options::-webkit-scrollbar{width:6px}.fui-autocomplete__options::-webkit-scrollbar-track{background:transparent}.fui-autocomplete__options::-webkit-scrollbar-thumb{background-color:var(--fui-border-color);border-radius:3px}.fui-autocomplete__options::-webkit-scrollbar-thumb:hover{background-color:var(--fui-text-secondary)}.fui-autocomplete__option{display:flex;align-items:center;justify-content:space-between;padding:.5rem .75rem;cursor:pointer;color:var(--fui-text-primary);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;transition:background-color var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__option:hover:not(.fui-autocomplete__option--disabled){background-color:var(--fui-background-hover)}.fui-autocomplete__option--active{background-color:var(--fui-surface-05)}.fui-autocomplete__option--selected{background-color:var(--fui-surface-05);font-weight:600}.fui-autocomplete__option--disabled{color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete__option-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-autocomplete__option-check{color:var(--fui-icon-primary);flex-shrink:0;margin-left:.5rem}.fui-autocomplete__no-options{padding:1rem .75rem;text-align:center;color:var(--fui-text-secondary);font-size:var(--fui-font-size-02);font-style:italic}.fui-autocomplete--disabled .fui-autocomplete__trigger{background-color:var(--fui-field-background-disabled);color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete--disabled .fui-autocomplete__arrow{color:var(--fui-text-primary-disabled)}.fui-autocomplete--readonly .fui-autocomplete__trigger{background-color:transparent;min-height:unset;cursor:default;color:var(--fui-text-primary)}.fui-autocomplete--readonly .fui-autocomplete__trigger[aria-disabled=true]{background-color:transparent;color:var(--fui-text-primary);cursor:default}.fui-autocomplete--readonly .fui-autocomplete__value-text{color:var(--fui-text-primary)}.fui-autocomplete--error .fui-autocomplete__trigger{border-bottom-color:var(--fui-error)}.fui-autocomplete--error .fui-autocomplete__trigger:focus{outline-color:var(--fui-error)}.fui-autocomplete-overlay-panel .fui-autocomplete__panel{border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);box-shadow:var(--fui-shadow-03)}.fui-autocomplete-backdrop{background:transparent}@media(prefers-contrast:high){.fui-autocomplete__trigger,.fui-autocomplete__panel{border-width:2px}.fui-autocomplete__trigger:focus,.fui-autocomplete__search-input:focus{outline-width:3px}.fui-autocomplete__option--active,.fui-autocomplete__option--selected{outline:2px solid var(--fui-primary);outline-offset:-2px}}@media(prefers-reduced-motion:reduce){.fui-autocomplete__trigger,.fui-autocomplete__arrow,.fui-autocomplete__option,.fui-autocomplete__search-input{transition:none}}\n"] }]
|
|
738
|
+
], template: "<!-- Autocomplete Trigger -->\r\n<div\r\n #trigger\r\n [id]=\"id\"\r\n class=\"fui-autocomplete__trigger\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n [attr.role]=\"'combobox'\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-expanded]=\"panelOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-invalid]=\"errorState()\"\r\n [attr.aria-describedby]=\"_ariaDescribedby\"\r\n [attr.aria-required]=\"required()\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-activedescendant]=\"panelOpen() ? _getActiveDescendant() : null\"\r\n [attr.aria-controls]=\"panelOpen() ? id + '-panel' : null\"\r\n (keydown)=\"_handleKeydown($event)\"\r\n>\r\n <span class=\"fui-autocomplete__value\">\r\n @if (empty()) {\r\n <span class=\"fui-autocomplete__placeholder\">{{ placeholder() }}</span>\r\n } @else {\r\n <span class=\"fui-autocomplete__value-text\">{{ _getDisplayValue() }}</span>\r\n }\r\n </span>\r\n\r\n @if (!_readOnly()) {\r\n <!-- Clear button \u2014 visible only when a value is selected and not disabled -->\r\n @if (!empty() && !disabled()) {\r\n <span class=\"fui-autocomplete__clear\" role=\"button\" [attr.aria-label]=\"intl.clearSelectionAriaLabel\" (click)=\"clear($event)\">\r\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\r\n <path\r\n d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\"\r\n />\r\n </svg>\r\n </span>\r\n }\r\n\r\n <!-- Dropdown arrow icon -->\r\n <svg\r\n class=\"fui-autocomplete__arrow\"\r\n [class.fui-autocomplete__arrow--open]=\"panelOpen()\"\r\n viewBox=\"0 0 16 16\"\r\n fill=\"currentColor\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M8 11L3 6l.7-.7L8 9.6l4.3-4.3L13 6z\" />\r\n </svg>\r\n }\r\n</div>\r\n\r\n<!-- Hidden container for projected options (used for data binding) -->\r\n<div class=\"fui-autocomplete__options-source\">\r\n <ng-content></ng-content>\r\n</div>\r\n\r\n<!-- Dropdown Panel -->\r\n@if (panelOpen()) {\r\n <div #panel [id]=\"id + '-panel'\" class=\"fui-autocomplete__panel\" [attr.aria-label]=\"placeholder()\">\r\n <!-- Search Input -->\r\n <div class=\"fui-autocomplete__search\">\r\n <fui-icon name=\"magnifying-glass\" size=\"sm\" class=\"fui-autocomplete__search-icon\"> </fui-icon>\r\n <input\r\n #searchInput\r\n type=\"text\"\r\n class=\"fui-autocomplete__search-input\"\r\n [placeholder]=\"resolvedSearchPlaceholder()\"\r\n [value]=\"searchTerm()\"\r\n autocomplete=\"off\"\r\n role=\"searchbox\"\r\n [attr.aria-label]=\"resolvedSearchPlaceholder()\"\r\n [attr.aria-controls]=\"id + '-panel-listbox'\"\r\n [attr.aria-activedescendant]=\"_getActiveDescendant()\"\r\n (input)=\"onSearchInput($event)\"\r\n (keydown)=\"_handlePanelKeydown($event)\"\r\n />\r\n </div>\r\n <!-- Live region for announcing result count to screen readers -->\r\n <div class=\"fui-sr-only\" aria-live=\"assertive\" aria-atomic=\"true\">\r\n @if (_liveAnnouncement()) {\r\n {{ _liveAnnouncement() }}\r\n } @else if (hasFilteredOptions()) {\r\n {{ intl.resultsAvailableText(filteredOptions().length) }}\r\n } @else {\r\n {{ intl.noResultsAvailableText }}\r\n }\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n @if (showAddButton() || showRefreshButton()) {\r\n <div class=\"fui-autocomplete__actions\">\r\n @if (showAddButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"tertiary\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onAddNew()\"\r\n >\r\n <fui-icon name=\"plus\" size=\"sm\"></fui-icon>\r\n {{ resolvedAddButtonLabel() }}\r\n </button>\r\n }\r\n @if (showRefreshButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"tertiary\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onRefresh()\"\r\n >\r\n <fui-icon name=\"refresh-cw\" size=\"sm\"></fui-icon>\r\n {{ resolvedRefreshButtonLabel() }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Options List -->\r\n <div\r\n class=\"fui-autocomplete__options\"\r\n [id]=\"id + '-panel-listbox'\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"placeholder()\"\r\n >\r\n @if (hasFilteredOptions()) {\r\n @for (option of filteredOptions(); track option.id; let i = $index) {\r\n <div\r\n class=\"fui-autocomplete__option\"\r\n [class.fui-autocomplete__option--active]=\"activeOptionIndex() === i\"\r\n [class.fui-autocomplete__option--selected]=\"option._selected()\"\r\n role=\"option\"\r\n [attr.id]=\"option.id\"\r\n [attr.aria-selected]=\"option._selected()\"\r\n (click)=\"_onOptionSelected(option)\"\r\n (mouseenter)=\"setActiveOption(i, option)\"\r\n (mouseleave)=\"option.setInactive()\"\r\n >\r\n <span class=\"fui-autocomplete__option-text\">{{ option.getLabel() }}</span>\r\n @if (option._selected()) {\r\n <fui-icon name=\"check\" size=\"sm\" class=\"fui-autocomplete__option-check\"></fui-icon>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"fui-autocomplete__no-options\">\r\n {{ resolvedNoOptionsText() }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-autocomplete{--fui-autocomplete-font-size: var(--fui-font-size-02);--fui-autocomplete-panel-max-height: 24rem;--fui-autocomplete-panel-border-radius: var(--fui-border-radius-sm);--fui-autocomplete-panel-shadow: var(--fui-shadow-04);--fui-autocomplete-panel-bg: var(--fui-surface-00);--fui-autocomplete-option-padding: .5rem .75rem;--fui-autocomplete-search-padding: .75rem;position:relative;display:inline-block;width:100%}.fui-autocomplete__options-source{display:none}.fui-autocomplete__trigger{display:flex;align-items:center;width:100%;border:none;color:var(--fui-text-primary);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;cursor:pointer;outline:none;transition:border-color var(--fui-duration-fast-01) var(--fui-ease-standard),background-color var(--fui-duration-fast-01) var(--fui-ease-standard);gap:.25rem}.fui-autocomplete__trigger:hover:not([aria-disabled=true]){background-color:var(--fui-field-background-hover)}.fui-autocomplete__trigger[aria-disabled=true]{background-color:var(--fui-field-background-disabled);color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.fui-autocomplete__placeholder{color:var(--fui-text-secondary)}.fui-autocomplete__value-text{color:var(--fui-text-primary)}.fui-autocomplete__clear{display:flex;align-items:center;justify-content:center;width:1rem;height:1rem;cursor:pointer;color:var(--fui-icon-secondary);flex-shrink:0;border-radius:50%;transition:color var(--fui-duration-fast-01) var(--fui-ease-standard),background-color var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__clear svg{width:.75rem;height:.75rem}.fui-autocomplete__clear:hover{color:var(--fui-text-primary);background-color:var(--fui-background-hover)}.fui-autocomplete__arrow{width:1rem;height:1rem;flex-shrink:0;color:var(--fui-icon-primary);pointer-events:none;transition:transform var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__arrow--open{transform:rotate(180deg)}.fui-autocomplete__panel{position:absolute;width:100%;background-color:var(--fui-autocomplete-panel-bg);border:1px solid var(--fui-border-color);border-radius:var(--fui-autocomplete-panel-border-radius);box-shadow:var(--fui-autocomplete-panel-shadow);max-height:var(--fui-autocomplete-panel-max-height);overflow:hidden;display:flex;flex-direction:column}.fui-autocomplete__search{position:relative;padding:.75rem;border-bottom:1px solid var(--fui-border-color);background-color:var(--fui-field-background)}.fui-autocomplete__search-icon{position:absolute;left:1.5rem;top:50%;transform:translateY(-50%);color:var(--fui-icon-secondary);pointer-events:none}.fui-autocomplete__search-input{width:100%;padding:.5rem .75rem .5rem 2.5rem;border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);background-color:var(--fui-background-primary);color:var(--fui-text-primary);font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;transition:border-color var(--fui-duration-fast-01) var(--fui-ease-standard),outline var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__search-input:focus{outline:2px solid var(--fui-primary);outline-offset:-2px;border-color:var(--fui-primary)}.fui-autocomplete__search-input::placeholder{color:var(--fui-text-secondary)}.fui-autocomplete__actions{display:flex;gap:.5rem;padding:.5rem .75rem;border-bottom:1px solid var(--fui-border-color);background-color:var(--fui-field-background)}.fui-autocomplete__action-button{display:flex;align-items:center;gap:.25rem;font-size:var(--fui-font-size-01)}.fui-autocomplete__action-button fui-icon{flex-shrink:0}.fui-autocomplete__options{max-height:16rem;overflow-y:auto;padding:.25rem 0;background-color:var(--fui-surface-01);scrollbar-width:thin;scrollbar-color:var(--fui-border-color) transparent}.fui-autocomplete__options::-webkit-scrollbar{width:6px}.fui-autocomplete__options::-webkit-scrollbar-track{background:transparent}.fui-autocomplete__options::-webkit-scrollbar-thumb{background-color:var(--fui-border-color);border-radius:3px}.fui-autocomplete__options::-webkit-scrollbar-thumb:hover{background-color:var(--fui-text-secondary)}.fui-autocomplete__option{display:flex;align-items:center;justify-content:space-between;padding:.5rem .75rem;cursor:pointer;color:var(--fui-text-primary);font-size:var(--fui-font-size-02);line-height:1.29;letter-spacing:.16px;transition:background-color var(--fui-duration-fast-01) var(--fui-ease-standard)}.fui-autocomplete__option:hover:not(.fui-autocomplete__option--disabled){background-color:var(--fui-background-hover)}.fui-autocomplete__option--active{background-color:var(--fui-surface-05)}.fui-autocomplete__option--selected{background-color:var(--fui-surface-05);font-weight:600}.fui-autocomplete__option--disabled{color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete__option-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-autocomplete__option-check{color:var(--fui-icon-primary);flex-shrink:0;margin-left:.5rem}.fui-autocomplete__no-options{padding:1rem .75rem;text-align:center;color:var(--fui-text-secondary);font-size:var(--fui-font-size-02);font-style:italic}.fui-autocomplete--disabled .fui-autocomplete__trigger{background-color:var(--fui-field-background-disabled);color:var(--fui-text-primary-disabled);cursor:not-allowed}.fui-autocomplete--disabled .fui-autocomplete__arrow{color:var(--fui-text-primary-disabled)}.fui-autocomplete--readonly .fui-autocomplete__trigger{background-color:transparent;min-height:unset;cursor:default;color:var(--fui-text-primary)}.fui-autocomplete--readonly .fui-autocomplete__trigger[aria-disabled=true]{background-color:transparent;color:var(--fui-text-primary);cursor:default}.fui-autocomplete--readonly .fui-autocomplete__value-text{color:var(--fui-text-primary)}.fui-autocomplete--error .fui-autocomplete__trigger{border-bottom-color:var(--fui-error)}.fui-autocomplete--error .fui-autocomplete__trigger:focus{outline-color:var(--fui-error)}.fui-autocomplete-overlay-panel .fui-autocomplete__panel{border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);box-shadow:var(--fui-shadow-04);transform-origin:top center;animation:fui-popover-enter var(--fui-duration-moderate-01) var(--fui-ease-entrance) both;will-change:transform,opacity}.fui-autocomplete-backdrop{background:transparent}@media(prefers-contrast:high){.fui-autocomplete__trigger,.fui-autocomplete__panel{border-width:2px}.fui-autocomplete__trigger:focus,.fui-autocomplete__search-input:focus{outline-width:3px}.fui-autocomplete__option--active,.fui-autocomplete__option--selected{outline:2px solid var(--fui-primary);outline-offset:-2px}}@media(prefers-reduced-motion:reduce){.fui-autocomplete__trigger,.fui-autocomplete__arrow,.fui-autocomplete__option,.fui-autocomplete__search-input{transition:none}.fui-autocomplete-overlay-panel .fui-autocomplete__panel{animation:none}}\n"] }]
|
|
710
739
|
}], ctorParameters: () => [], propDecorators: { placeholderInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabledInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], showAddButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAddButton", required: false }] }], showRefreshButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRefreshButton", required: false }] }], addButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "addButtonLabel", required: false }] }], refreshButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "refreshButtonLabel", required: false }] }], noOptionsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noOptionsText", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], errorStateMatcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStateMatcher", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], openedChange: [{ type: i0.Output, args: ["openedChange"] }], addNew: [{ type: i0.Output, args: ["addNew"] }], refresh: [{ type: i0.Output, args: ["refresh"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], trigger: [{
|
|
711
740
|
type: ViewChild,
|
|
712
741
|
args: ['trigger', { static: false }]
|
|
@@ -722,5 +751,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
|
|
|
722
751
|
* Generated bundle index. Do not edit.
|
|
723
752
|
*/
|
|
724
753
|
|
|
725
|
-
export { FUI_AUTOCOMPLETE, FuiAutocompleteComponent };
|
|
754
|
+
export { FUI_AUTOCOMPLETE, FuiAutocompleteComponent, FuiAutocompleteIntl };
|
|
726
755
|
//# sourceMappingURL=raintonic-formaui-components-autocomplete.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raintonic-formaui-components-autocomplete.mjs","sources":["../../../lib/components/autocomplete/autocomplete.component.ts","../../../lib/components/autocomplete/autocomplete.component.html","../../../lib/components/autocomplete/raintonic-formaui-components-autocomplete.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChildren,\n DoCheck,\n effect,\n ElementRef,\n inject,\n InjectionToken,\n NgZone,\n input,\n InputSignal,\n OnDestroy,\n output,\n OutputEmitterRef,\n signal,\n Signal,\n ViewChild,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport {\n ControlValueAccessor,\n FormGroupDirective,\n NG_VALUE_ACCESSOR,\n NgControl,\n NgForm,\n ReactiveFormsModule,\n} from '@angular/forms';\nimport { DOCUMENT } from '@angular/common';\nimport { fromEvent, Subject, Subscription } from 'rxjs';\nimport { filter } from 'rxjs/operators';\nimport { injectNgControl, updateErrorState, syncRequiredState, syncNgControlDisabled } from '@raintonic/formaui/cdk/form-field';\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\nimport { FuiButtonDirective } from '@raintonic/formaui/components/button';\nimport { FUI_FORM_FIELD_CONTROL, FuiFormFieldControl } from '@raintonic/formaui/core';\nimport { DefaultErrorStateMatcher, ErrorStateMatcher } from '@raintonic/formaui/core';\nimport { FuiOptionComponent } from '@raintonic/formaui/components/select';\nimport { FuiOverlayService, FuiOverlayRef, FuiConnectedPosition } from '@raintonic/formaui/cdk/overlay';\n\n/**\n * Injection token used to provide the parent autocomplete to options\n */\nexport const FUI_AUTOCOMPLETE = new InjectionToken<FuiAutocompleteComponent>('FUI_AUTOCOMPLETE');\n\n/**\n * Selection change event object emitted when the autocomplete's selection changes\n */\nexport interface FuiAutocompleteChange {\n source: FuiAutocompleteComponent;\n value: unknown;\n}\n\n/**\n * # fui-autocomplete Component\n *\n * An autocomplete component designed to work seamlessly with fui-form-field.\n * Similar to Angular Material's mat-autocomplete integration with mat-form-field.\n * Provides full Reactive Forms support with validation, filtering, and optional\n * add/refresh actions.\n *\n * ## Features\n * - Works inside fui-form-field like mat-autocomplete\n * - Full Reactive Forms integration (ControlValueAccessor)\n * - Options via projected content (fui-option)\n * - Built-in search/filter input in the panel\n * - Optional \"Add New\" and \"Refresh\" action buttons\n * - Disabled and readonly states\n * - Full accessibility support\n * - Full keyboard navigation (Arrow keys, Enter, Escape, Home, End, PageUp, PageDown)\n * - Uses overlay service for proper positioning\n *\n * ## Usage\n *\n * ### Basic Autocomplete with Form Field\n * ```html\n * <fui-form-field>\n * <label>Country</label>\n * <fui-autocomplete placeholder=\"Search countries...\">\n * <fui-option value=\"us\">United States</fui-option>\n * <fui-option value=\"ca\">Canada</fui-option>\n * <fui-option value=\"mx\">Mexico</fui-option>\n * </fui-autocomplete>\n * </fui-form-field>\n * ```\n *\n * ### With Reactive Forms and Validation\n * ```html\n * <form [formGroup]=\"form\">\n * <fui-form-field>\n * <label>Country</label>\n * <fui-autocomplete formControlName=\"country\" placeholder=\"Select a country\">\n * <fui-option value=\"us\">United States</fui-option>\n * <fui-option value=\"ca\">Canada</fui-option>\n * </fui-autocomplete>\n * <fui-error *ngIf=\"form.get('country')?.hasError('required')\">\n * Country is required\n * </fui-error>\n * </fui-form-field>\n * </form>\n * ```\n *\n * ### With Add/Refresh Buttons\n * ```html\n * <fui-form-field>\n * <label>Category</label>\n * <fui-autocomplete\n * placeholder=\"Search categories...\"\n * [showAddButton]=\"true\"\n * [showRefreshButton]=\"true\"\n * (addNew)=\"openAddCategoryDialog()\"\n * (refresh)=\"refreshCategories()\">\n * @for (category of categories; track category.id) {\n * <fui-option [value]=\"category.id\">{{ category.name }}</fui-option>\n * }\n * </fui-autocomplete>\n * </fui-form-field>\n * ```\n */\n@Component({\n selector: 'fui-autocomplete',\n standalone: true,\n imports: [FuiIconComponent, ReactiveFormsModule, FuiButtonDirective],\n templateUrl: './autocomplete.component.html',\n styleUrls: ['./autocomplete.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'fui-autocomplete',\n '[attr.id]': 'id',\n '[class.fui-autocomplete--open]': 'panelOpen()',\n '[class.fui-autocomplete--disabled]': 'disabled()',\n '[class.fui-autocomplete--focused]': 'focused()',\n '[class.fui-autocomplete--error]': 'errorState()',\n '[class.fui-autocomplete--readonly]': '_readOnly()',\n },\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: FuiAutocompleteComponent,\n multi: true,\n },\n {\n provide: FUI_FORM_FIELD_CONTROL,\n useExisting: FuiAutocompleteComponent,\n },\n {\n provide: FUI_AUTOCOMPLETE,\n useExisting: FuiAutocompleteComponent,\n },\n ],\n})\nexport class FuiAutocompleteComponent implements ControlValueAccessor, FuiFormFieldControl, DoCheck, OnDestroy {\n // Static properties\n static nextId = 0;\n readonly controlType = 'fui-autocomplete';\n\n // Inputs using signal-based API\n readonly placeholderInput: InputSignal<string> = input('', {\n alias: 'placeholder',\n });\n readonly disabledInput: InputSignal<boolean> = input(false, {\n alias: 'disabled',\n });\n readonly readonly: InputSignal<boolean> = input(false);\n readonly showAddButton: InputSignal<boolean> = input(false);\n readonly showRefreshButton: InputSignal<boolean> = input(false);\n readonly addButtonLabel: InputSignal<string> = input('Add New');\n readonly refreshButtonLabel: InputSignal<string> = input('Refresh');\n readonly noOptionsText: InputSignal<string> = input('No options found');\n readonly searchPlaceholder: InputSignal<string> = input('Search...');\n readonly errorStateMatcher: InputSignal<ErrorStateMatcher | null> = input<ErrorStateMatcher | null>(null);\n\n /**\n * Whether to compare option values using object identity or deep equality\n */\n readonly compareWith: InputSignal<(o1: unknown, o2: unknown) => boolean> = input<\n (o1: unknown, o2: unknown) => boolean\n >((o1, o2) => o1 === o2);\n\n // Outputs\n readonly valueChange: OutputEmitterRef<unknown> = output<unknown>();\n readonly selectionChange: OutputEmitterRef<FuiAutocompleteChange> = output<FuiAutocompleteChange>();\n readonly openedChange: OutputEmitterRef<boolean> = output<boolean>();\n readonly addNew: OutputEmitterRef<void> = output();\n readonly refresh: OutputEmitterRef<void> = output();\n readonly searchChange: OutputEmitterRef<string> = output<string>();\n\n // Internal state signals\n private readonly _value: WritableSignal<unknown> = signal(null);\n private readonly _focused: WritableSignal<boolean> = signal(false);\n private readonly _disabled: WritableSignal<boolean> = signal(false);\n readonly _readOnly: WritableSignal<boolean> = signal(false);\n\n // FuiFormFieldControl implementation\n readonly stateChanges = new Subject<void>();\n private _uid = `fui-autocomplete-${FuiAutocompleteComponent.nextId++}`;\n _ariaDescribedby: string | null = null;\n\n // Error state\n private readonly _errorState: WritableSignal<boolean> = signal(false);\n readonly errorState = this._errorState;\n\n // Form control references\n private _parentForm = inject(NgForm, { optional: true });\n private _parentFormGroup = inject(FormGroupDirective, { optional: true });\n private _defaultErrorStateMatcher = inject(DefaultErrorStateMatcher);\n private readonly _ngControlRef = injectNgControl();\n get ngControl(): NgControl | null {\n return this._ngControlRef.ngControl;\n }\n\n // Interface implementation\n readonly placeholder = computed(() => this.placeholderInput());\n private readonly _required: WritableSignal<boolean> = signal(false);\n readonly required = this._required;\n\n readonly value = this._value;\n readonly focused = this._focused;\n\n private readonly _ngControlDisabled: WritableSignal<boolean> = signal(false);\n readonly disabled = computed(() => this._disabled() || this.disabledInput() || this._ngControlDisabled());\n\n readonly empty = computed(() => {\n const val = this._value();\n return val === null || val === undefined;\n });\n\n readonly id = this._uid;\n\n // ViewChild for trigger and panel\n @ViewChild('trigger', { static: false }) trigger?: ElementRef<HTMLDivElement>;\n @ViewChild('panel', { static: false }) panel?: ElementRef<HTMLDivElement>;\n @ViewChild('searchInput', { static: false })\n searchInput?: ElementRef<HTMLInputElement>;\n\n // ContentChildren for options\n readonly options = contentChildren(FuiOptionComponent, { descendants: true });\n\n // Panel open/close state\n readonly panelOpen = signal(false);\n\n // Search term for filtering\n readonly searchTerm: WritableSignal<string> = signal('');\n\n // Active option index for keyboard navigation\n readonly activeOptionIndex: WritableSignal<number> = signal(-1);\n\n // Live announcement for screen readers\n readonly _liveAnnouncement = signal('');\n\n _announce(message: string): void {\n this._liveAnnouncement.set('');\n setTimeout(() => {\n this._liveAnnouncement.set(message);\n }, 50);\n }\n\n // Overlay reference\n private _overlayRef: FuiOverlayRef | null = null;\n private _overlaySubscriptions = new Subscription();\n\n // Services\n private readonly _overlayService = inject(FuiOverlayService);\n private readonly _elementRef = inject(ElementRef);\n private readonly _document = inject(DOCUMENT);\n private readonly _ngZone = inject(NgZone);\n private _outsideClickSub?: Subscription;\n\n // ControlValueAccessor callbacks\n private _onChange: (value: unknown) => void = () => {\n // Intentionally empty: will be replaced by Angular forms\n };\n private _onTouched: () => void = () => {\n // Intentionally empty: will be replaced by Angular forms\n };\n\n // Computed properties\n readonly displayValue: Signal<string> = computed(() => {\n const currentValue = this.value();\n const opts = this.options();\n\n if (currentValue === null || currentValue === undefined) {\n return '';\n }\n\n const selectedOption = opts.find((opt) => this.compareWith()(opt.value(), currentValue));\n return selectedOption ? selectedOption.getLabel() : String(currentValue);\n });\n\n // Filtered options based on search term\n readonly filteredOptions: Signal<FuiOptionComponent[]> = computed(() => {\n const opts = this.options();\n const term = this.searchTerm().toLowerCase().trim();\n\n if (!term) {\n return opts.filter((opt) => !opt.disabled());\n }\n\n return opts.filter((opt) => !opt.disabled() && opt.getLabel().toLowerCase().includes(term));\n });\n\n readonly hasFilteredOptions: Signal<boolean> = computed(() => {\n return this.filteredOptions().length > 0;\n });\n\n constructor() {\n // Set valueAccessor after NgControl is resolved\n void Promise.resolve().then(() => {\n if (this._ngControlRef.ngControl) {\n this._ngControlRef.ngControl.valueAccessor = this;\n }\n });\n\n // Effect to emit state changes\n effect(() => {\n // Track all reactive inputs and internal signals\n this.placeholderInput();\n this.readonly();\n this.disabledInput();\n this.errorStateMatcher();\n this._focused();\n this._disabled();\n this._value();\n this._ngControlDisabled();\n this._required();\n this._errorState();\n\n // Emit state change\n this.stateChanges.next();\n });\n\n // Effect to update options selected state when value changes\n effect(() => {\n const currentValue = this._value();\n const opts = this.options();\n const compareFn = this.compareWith();\n\n opts.forEach((option) => {\n const optValue = option.value();\n const isSelected = compareFn(currentValue, optValue);\n\n if (isSelected) {\n option.select();\n } else {\n option.deselect();\n }\n });\n\n // Notify form-field that state may have changed\n this.stateChanges.next();\n });\n }\n\n ngDoCheck(): void {\n if (this.ngControl) {\n updateErrorState(\n this.ngControl,\n this._errorState,\n this.errorStateMatcher(),\n this._defaultErrorStateMatcher,\n this._parentForm,\n this._parentFormGroup,\n this.stateChanges,\n );\n syncRequiredState(this.ngControl, this._required, this.stateChanges);\n syncNgControlDisabled(this.ngControl, this._ngControlDisabled, this.stateChanges);\n }\n }\n\n ngOnDestroy(): void {\n this.stateChanges.complete();\n this._outsideClickSub?.unsubscribe();\n this._disposeOverlay();\n }\n\n // ControlValueAccessor implementation\n writeValue(value: unknown): void {\n this._value.set(value ?? null);\n this.stateChanges.next();\n }\n\n registerOnChange(fn: (value: unknown) => void): void {\n this._onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this._onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this._disabled.set(isDisabled);\n this.stateChanges.next();\n }\n\n // FuiFormFieldControl implementation\n onContainerClick(_event: MouseEvent): void {\n if (!this.disabled()) {\n this.toggle();\n }\n }\n\n setDescribedByIds(ids: string[]): void {\n this._ariaDescribedby = ids.length ? ids.join(' ') : null;\n }\n\n setReadOnly(readOnly: boolean): void {\n this._readOnly.set(readOnly);\n }\n\n // Public methods\n clear(event: Event): void {\n event.stopPropagation();\n this._value.set(null);\n this._onChange(null);\n this.valueChange.emit(null);\n this.selectionChange.emit({ source: this, value: null });\n this.stateChanges.next();\n }\n\n focus(): void {\n this.trigger?.nativeElement.focus();\n }\n\n blur(): void {\n this.trigger?.nativeElement.blur();\n }\n\n // Toggle panel open/close\n toggle(): void {\n if (this.disabled()) return;\n if (this.panelOpen()) {\n this.close();\n } else {\n this.open();\n }\n }\n\n // Open the dropdown panel\n open(): void {\n if (this.disabled() || this.readonly() || this.panelOpen()) return;\n\n this.panelOpen.set(true);\n this._focused.set(true);\n this.searchTerm.set('');\n this.openedChange.emit(true);\n\n // Set active option to currently selected or first option\n this._setInitialActiveOption();\n\n // Create overlay after the view updates\n setTimeout(() => {\n this._createOverlay();\n this._scrollToActiveOption();\n this._listenForOutsideClicks();\n // Focus the search input\n this.searchInput?.nativeElement.focus();\n }, 0);\n }\n\n // Close the dropdown panel\n close(): void {\n if (!this.panelOpen()) return;\n this._outsideClickSub?.unsubscribe();\n\n this.panelOpen.set(false);\n this._focused.set(false);\n this.activeOptionIndex.set(-1);\n this.searchTerm.set('');\n this._disposeOverlay();\n this.openedChange.emit(false);\n this._onTouched();\n\n // Clear active state on all options\n this.options().forEach((opt) => {\n opt.setInactive();\n });\n\n // Return focus to trigger\n setTimeout(() => {\n this.trigger?.nativeElement.focus();\n }, 0);\n }\n\n // Handle option selection (called by FuiOptionComponent or internally)\n _onOptionSelected(option: FuiOptionComponent): void {\n const newValue = option.value();\n\n // Deselect previous option\n const opts = this.options();\n opts.forEach((opt) => {\n if (opt !== option) {\n opt.deselect();\n }\n });\n\n option.select();\n this._value.set(newValue);\n this._onChange(newValue);\n this.valueChange.emit(newValue);\n this.selectionChange.emit({ source: this, value: newValue });\n this._announce(`${option.getLabel()} selected`);\n this.close();\n\n this.stateChanges.next();\n }\n\n // Handle search input\n onSearchInput(event: Event): void {\n const target = event.target as HTMLInputElement;\n const term = target.value;\n this.searchTerm.set(term);\n this.searchChange.emit(term);\n\n // Reset active index when search changes\n const filtered = this.filteredOptions();\n if (filtered.length > 0) {\n this._setActiveOptionIndex(0);\n } else {\n this.activeOptionIndex.set(-1);\n }\n }\n\n // Handle add new action\n onAddNew(): void {\n this.close();\n this.addNew.emit();\n }\n\n // Handle refresh action\n onRefresh(): void {\n this.refresh.emit();\n // Keep panel open and clear search\n this.searchTerm.set('');\n }\n\n // Get display value for trigger\n _getDisplayValue(): string {\n return this.displayValue();\n }\n\n // Handle keyboard navigation\n _handleKeydown(event: KeyboardEvent): void {\n if (this.disabled()) return;\n\n const isOpen = this.panelOpen();\n\n if (!isOpen) {\n this._handleClosedKeydown(event);\n } else {\n this._handleOpenKeydown(event);\n }\n }\n\n // Handle keydown when panel is closed\n private _handleClosedKeydown(event: KeyboardEvent): void {\n const key = event.key;\n\n switch (key) {\n case 'Enter':\n case ' ':\n case 'ArrowDown':\n case 'ArrowUp':\n event.preventDefault();\n this.open();\n break;\n }\n }\n\n // Handle keydown when panel is open (for search input)\n _handlePanelKeydown(event: KeyboardEvent): void {\n if (this.disabled()) return;\n\n const key = event.key;\n const opts = this.filteredOptions();\n const activeIndex = this.activeOptionIndex();\n\n switch (key) {\n case 'ArrowDown':\n event.preventDefault();\n this._setNextActiveOption(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this._setNextActiveOption(-1);\n break;\n case 'Home':\n event.preventDefault();\n if (opts.length > 0) {\n this._setActiveOptionIndex(0);\n }\n break;\n case 'End':\n event.preventDefault();\n if (opts.length > 0) {\n this._setActiveOptionIndex(opts.length - 1);\n }\n break;\n case 'PageDown':\n event.preventDefault();\n if (opts.length > 0) {\n const pageSize = Math.min(10, opts.length);\n const newIndex = Math.min(activeIndex + pageSize, opts.length - 1);\n this._setActiveOptionIndex(newIndex);\n }\n break;\n case 'PageUp':\n event.preventDefault();\n if (opts.length > 0) {\n const pageSize = Math.min(10, opts.length);\n const newIndex = Math.max(activeIndex - pageSize, 0);\n this._setActiveOptionIndex(newIndex);\n }\n break;\n case 'Enter':\n event.preventDefault();\n if (activeIndex >= 0 && activeIndex < opts.length) {\n this._onOptionSelected(opts[activeIndex]);\n }\n break;\n case 'Escape':\n event.preventDefault();\n this.close();\n break;\n case 'Tab':\n // Allow tab to close and move to next element\n this.close();\n break;\n }\n }\n\n // Handle keydown when panel is open (for trigger)\n private _handleOpenKeydown(event: KeyboardEvent): void {\n // Delegate to panel keydown handler\n this._handlePanelKeydown(event);\n }\n\n // Set the next active option based on delta\n private _setNextActiveOption(delta: number): void {\n const opts = this.filteredOptions();\n if (opts.length === 0) return;\n\n let currentIndex = this.activeOptionIndex();\n if (currentIndex < 0) {\n currentIndex = delta > 0 ? -1 : opts.length;\n }\n\n let newIndex = currentIndex + delta;\n\n // Wrap around\n if (newIndex < 0) {\n newIndex = opts.length - 1;\n } else if (newIndex >= opts.length) {\n newIndex = 0;\n }\n\n this._setActiveOptionIndex(newIndex);\n }\n\n // Set the active option index\n private _setActiveOptionIndex(index: number): void {\n const opts = this.filteredOptions();\n if (index < 0 || index >= opts.length) return;\n\n // Update active state on options\n const allOpts = this.options();\n allOpts.forEach((opt) => {\n opt.setInactive();\n });\n\n const activeOption = opts[index];\n activeOption.setActive();\n this.activeOptionIndex.set(index);\n this._scrollToActiveOption();\n this._announce(`${activeOption.getLabel()}, ${index + 1} of ${opts.length}`);\n }\n\n // Set initial active option when opening\n private _setInitialActiveOption(): void {\n const opts = this.filteredOptions();\n if (opts.length === 0) {\n this.activeOptionIndex.set(-1);\n return;\n }\n\n const currentValue = this._value();\n const compareFn = this.compareWith();\n\n // Find the selected option\n let selectedIndex = -1;\n if (currentValue !== null && currentValue !== undefined) {\n selectedIndex = opts.findIndex((opt) => compareFn(opt.value(), currentValue));\n }\n\n const initialIndex = selectedIndex >= 0 ? selectedIndex : 0;\n this._setActiveOptionIndex(initialIndex);\n }\n\n // Scroll to active option\n private _scrollToActiveOption(): void {\n const opts = this.filteredOptions();\n const activeIndex = this.activeOptionIndex();\n\n if (activeIndex < 0 || activeIndex >= opts.length) return;\n\n const activeOption = opts[activeIndex];\n const element = activeOption._getHostElement();\n const panelElement = this.panel?.nativeElement;\n\n if (element && panelElement) {\n const optionsContainer = panelElement.querySelector('.fui-autocomplete__options');\n if (optionsContainer) {\n const optionTop = element.offsetTop - (optionsContainer as HTMLElement).offsetTop;\n const optionBottom = optionTop + element.offsetHeight;\n const containerTop = optionsContainer.scrollTop;\n const containerBottom = containerTop + optionsContainer.clientHeight;\n\n if (optionTop < containerTop) {\n optionsContainer.scrollTop = optionTop;\n } else if (optionBottom > containerBottom) {\n optionsContainer.scrollTop = optionBottom - optionsContainer.clientHeight;\n }\n }\n }\n }\n\n // Start listening for outside clicks when panel opens\n private _listenForOutsideClicks(): void {\n this._outsideClickSub?.unsubscribe();\n\n this._ngZone.runOutsideAngular(() => {\n setTimeout(() => {\n this._outsideClickSub = fromEvent<MouseEvent>(this._document, 'click')\n .pipe(\n filter(() => this.panelOpen()),\n filter((event) => {\n const target = event.target as HTMLElement;\n const triggerElement = this.trigger?.nativeElement;\n const panelElement = this.panel?.nativeElement;\n const overlayElement = this._overlayRef?.overlayElement;\n return (\n !triggerElement?.contains(target) &&\n !panelElement?.contains(target) &&\n !overlayElement?.contains(target)\n );\n }),\n )\n .subscribe(() => {\n this._ngZone.run(() => {\n this.close();\n });\n });\n });\n });\n }\n\n // Create overlay for panel\n private _createOverlay(): void {\n if (this._overlayRef || !this.panel || !this.trigger) return;\n\n const triggerElement = this.trigger.nativeElement;\n const triggerWidth = triggerElement.getBoundingClientRect().width;\n\n const positions: FuiConnectedPosition[] = [\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n offsetY: 4,\n },\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'bottom',\n offsetY: -4,\n },\n ];\n\n const positionStrategy = this._overlayService\n .position()\n .connectedTo(triggerElement, positions)\n .withPush(true)\n .withViewportMargin(8);\n\n this._overlayRef = this._overlayService.create({\n positionStrategy,\n scrollStrategy: this._overlayService.scrollStrategies.reposition(),\n hasBackdrop: true,\n backdropClass: 'fui-autocomplete-backdrop',\n backdropClickBehavior: 'close',\n panelClass: ['fui-autocomplete-overlay-panel'],\n minWidth: triggerWidth,\n });\n\n // Track overlay subscriptions for proper cleanup\n this._overlaySubscriptions.unsubscribe();\n this._overlaySubscriptions = new Subscription();\n\n this._overlaySubscriptions.add(\n this._overlayRef.backdropClick.subscribe(() => {\n this.close();\n }),\n );\n\n this._overlaySubscriptions.add(\n this._overlayRef.keydownEvents.subscribe((event) => {\n if (event.key === 'Escape') {\n this.close();\n }\n }),\n );\n\n // Attach panel to overlay\n const panelElement = this.panel.nativeElement;\n this._overlayRef.attach(panelElement);\n }\n\n // Dispose overlay\n private _disposeOverlay(): void {\n this._overlaySubscriptions.unsubscribe();\n if (this._overlayRef) {\n this._overlayRef.dispose();\n this._overlayRef = null;\n }\n }\n\n // Get the active option's id for aria-activedescendant\n _getActiveDescendant(): string | null {\n const opts = this.filteredOptions();\n const activeIndex = this.activeOptionIndex();\n if (activeIndex >= 0 && activeIndex < opts.length) {\n return opts[activeIndex].id;\n }\n return null;\n }\n\n // Set active option by index (for template use)\n setActiveOption(index: number, option: FuiOptionComponent): void {\n const allOpts = this.options();\n allOpts.forEach((opt) => {\n opt.setInactive();\n });\n option.setActive();\n this.activeOptionIndex.set(index);\n }\n\n // Mat-autocomplete compatibility methods\n get selected(): unknown {\n return this.value;\n }\n}\n","<!-- Autocomplete Trigger -->\r\n<div\r\n #trigger\r\n [id]=\"id\"\r\n class=\"fui-autocomplete__trigger\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n [attr.role]=\"'combobox'\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-expanded]=\"panelOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-invalid]=\"errorState()\"\r\n [attr.aria-describedby]=\"_ariaDescribedby\"\r\n [attr.aria-required]=\"required()\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-activedescendant]=\"panelOpen() ? _getActiveDescendant() : null\"\r\n [attr.aria-controls]=\"panelOpen() ? id + '-panel' : null\"\r\n (keydown)=\"_handleKeydown($event)\"\r\n>\r\n <span class=\"fui-autocomplete__value\">\r\n @if (empty()) {\r\n <span class=\"fui-autocomplete__placeholder\">{{ placeholder() }}</span>\r\n } @else {\r\n <span class=\"fui-autocomplete__value-text\">{{ _getDisplayValue() }}</span>\r\n }\r\n </span>\r\n\r\n @if (!_readOnly()) {\r\n <!-- Clear button — visible only when a value is selected and not disabled -->\r\n @if (!empty() && !disabled()) {\r\n <span class=\"fui-autocomplete__clear\" role=\"button\" aria-label=\"Clear selection\" (click)=\"clear($event)\">\r\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\r\n <path\r\n d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\"\r\n />\r\n </svg>\r\n </span>\r\n }\r\n\r\n <!-- Dropdown arrow icon -->\r\n <svg\r\n class=\"fui-autocomplete__arrow\"\r\n [class.fui-autocomplete__arrow--open]=\"panelOpen()\"\r\n viewBox=\"0 0 16 16\"\r\n fill=\"currentColor\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M8 11L3 6l.7-.7L8 9.6l4.3-4.3L13 6z\" />\r\n </svg>\r\n }\r\n</div>\r\n\r\n<!-- Hidden container for projected options (used for data binding) -->\r\n<div class=\"fui-autocomplete__options-source\">\r\n <ng-content></ng-content>\r\n</div>\r\n\r\n<!-- Dropdown Panel -->\r\n@if (panelOpen()) {\r\n <div #panel [id]=\"id + '-panel'\" class=\"fui-autocomplete__panel\" [attr.aria-label]=\"placeholder()\">\r\n <!-- Search Input -->\r\n <div class=\"fui-autocomplete__search\">\r\n <fui-icon name=\"magnifying-glass\" size=\"sm\" class=\"fui-autocomplete__search-icon\"> </fui-icon>\r\n <input\r\n #searchInput\r\n type=\"text\"\r\n class=\"fui-autocomplete__search-input\"\r\n [placeholder]=\"searchPlaceholder()\"\r\n [value]=\"searchTerm()\"\r\n autocomplete=\"off\"\r\n role=\"searchbox\"\r\n [attr.aria-label]=\"searchPlaceholder()\"\r\n [attr.aria-controls]=\"id + '-panel-listbox'\"\r\n [attr.aria-activedescendant]=\"_getActiveDescendant()\"\r\n (input)=\"onSearchInput($event)\"\r\n (keydown)=\"_handlePanelKeydown($event)\"\r\n />\r\n </div>\r\n <!-- Live region for announcing result count to screen readers -->\r\n <div class=\"fui-visually-hidden\" aria-live=\"assertive\" aria-atomic=\"true\">\r\n @if (_liveAnnouncement()) {\r\n {{ _liveAnnouncement() }}\r\n } @else if (hasFilteredOptions()) {\r\n {{ filteredOptions().length }} results available.\r\n } @else {\r\n No results available.\r\n }\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n @if (showAddButton() || showRefreshButton()) {\r\n <div class=\"fui-autocomplete__actions\">\r\n @if (showAddButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onAddNew()\"\r\n >\r\n <fui-icon name=\"plus\" size=\"sm\"></fui-icon>\r\n {{ addButtonLabel() }}\r\n </button>\r\n }\r\n @if (showRefreshButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"ghost\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onRefresh()\"\r\n >\r\n <fui-icon name=\"refresh-cw\" size=\"sm\"></fui-icon>\r\n {{ refreshButtonLabel() }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Options List -->\r\n <div\r\n class=\"fui-autocomplete__options\"\r\n [id]=\"id + '-panel-listbox'\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"placeholder()\"\r\n >\r\n @if (hasFilteredOptions()) {\r\n @for (option of filteredOptions(); track option.id; let i = $index) {\r\n <div\r\n class=\"fui-autocomplete__option\"\r\n [class.fui-autocomplete__option--active]=\"activeOptionIndex() === i\"\r\n [class.fui-autocomplete__option--selected]=\"option._selected()\"\r\n role=\"option\"\r\n [attr.id]=\"option.id\"\r\n [attr.aria-selected]=\"option._selected()\"\r\n (click)=\"_onOptionSelected(option)\"\r\n (mouseenter)=\"setActiveOption(i, option)\"\r\n (mouseleave)=\"option.setInactive()\"\r\n >\r\n <span class=\"fui-autocomplete__option-text\">{{ option.getLabel() }}</span>\r\n @if (option._selected()) {\r\n <fui-icon name=\"check\" size=\"sm\" class=\"fui-autocomplete__option-check\"></fui-icon>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"fui-autocomplete__no-options\">\r\n {{ noOptionsText() }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"raintonic-formaui-components-autocomplete.mjs","sources":["../../../lib/components/autocomplete/autocomplete.intl.ts","../../../lib/components/autocomplete/autocomplete.component.ts","../../../lib/components/autocomplete/autocomplete.component.html","../../../lib/components/autocomplete/raintonic-formaui-components-autocomplete.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { FuiIntlBase } from '@raintonic/formaui/core';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FuiAutocompleteIntl extends FuiIntlBase {\r\n addButtonLabel = 'Add New';\r\n refreshButtonLabel = 'Refresh';\r\n noOptionsText = 'No options found';\r\n searchPlaceholder = 'Search...';\r\n clearSelectionAriaLabel = 'Clear selection';\r\n noResultsAvailableText = 'No results available.';\r\n\r\n resultsAvailableText(count: number): string {\r\n return `${count} results available.`;\r\n }\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n computed,\r\n contentChildren,\r\n DoCheck,\r\n effect,\r\n ElementRef,\r\n inject,\r\n InjectionToken,\r\n NgZone,\r\n input,\r\n InputSignal,\r\n OnDestroy,\r\n output,\r\n OutputEmitterRef,\r\n signal,\r\n Signal,\r\n ViewChild,\r\n ViewEncapsulation,\r\n WritableSignal,\r\n} from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\n\r\nimport {\r\n ControlValueAccessor,\r\n FormGroupDirective,\r\n NG_VALUE_ACCESSOR,\r\n NgControl,\r\n NgForm,\r\n ReactiveFormsModule,\r\n} from '@angular/forms';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { fromEvent, Subject, Subscription } from 'rxjs';\r\nimport { filter } from 'rxjs/operators';\r\nimport { injectNgControl, updateErrorState, syncRequiredState, syncNgControlDisabled } from '@raintonic/formaui/cdk/form-field';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\nimport { FuiButtonDirective } from '@raintonic/formaui/components/button';\r\nimport { FUI_FORM_FIELD_CONTROL, FuiFormFieldControl } from '@raintonic/formaui/core';\r\nimport { DefaultErrorStateMatcher, ErrorStateMatcher } from '@raintonic/formaui/core';\r\nimport { FuiOptionComponent } from '@raintonic/formaui/components/select';\r\nimport { FuiOverlayService, FuiOverlayRef, FuiConnectedPosition } from '@raintonic/formaui/cdk/overlay';\r\nimport { FuiAutocompleteIntl } from './autocomplete.intl';\r\n\r\n/**\r\n * Injection token used to provide the parent autocomplete to options\r\n */\r\nexport const FUI_AUTOCOMPLETE = new InjectionToken<FuiAutocompleteComponent>('FUI_AUTOCOMPLETE');\r\n\r\n/**\r\n * Selection change event object emitted when the autocomplete's selection changes\r\n */\r\nexport interface FuiAutocompleteChange {\r\n source: FuiAutocompleteComponent;\r\n value: unknown;\r\n}\r\n\r\n/**\r\n * # fui-autocomplete Component\r\n *\r\n * An autocomplete component designed to work seamlessly with fui-form-field.\r\n * Similar to Angular Material's mat-autocomplete integration with mat-form-field.\r\n * Provides full Reactive Forms support with validation, filtering, and optional\r\n * add/refresh actions.\r\n *\r\n * ## Features\r\n * - Works inside fui-form-field like mat-autocomplete\r\n * - Full Reactive Forms integration (ControlValueAccessor)\r\n * - Options via projected content (fui-option)\r\n * - Built-in search/filter input in the panel\r\n * - Optional \"Add New\" and \"Refresh\" action buttons\r\n * - Disabled and readonly states\r\n * - Full accessibility support\r\n * - Full keyboard navigation (Arrow keys, Enter, Escape, Home, End, PageUp, PageDown)\r\n * - Uses overlay service for proper positioning\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic Autocomplete with Form Field\r\n * ```html\r\n * <fui-form-field>\r\n * <label>Country</label>\r\n * <fui-autocomplete placeholder=\"Search countries...\">\r\n * <fui-option value=\"us\">United States</fui-option>\r\n * <fui-option value=\"ca\">Canada</fui-option>\r\n * <fui-option value=\"mx\">Mexico</fui-option>\r\n * </fui-autocomplete>\r\n * </fui-form-field>\r\n * ```\r\n *\r\n * ### With Reactive Forms and Validation\r\n * ```html\r\n * <form [formGroup]=\"form\">\r\n * <fui-form-field>\r\n * <label>Country</label>\r\n * <fui-autocomplete formControlName=\"country\" placeholder=\"Select a country\">\r\n * <fui-option value=\"us\">United States</fui-option>\r\n * <fui-option value=\"ca\">Canada</fui-option>\r\n * </fui-autocomplete>\r\n * <fui-error *ngIf=\"form.get('country')?.hasError('required')\">\r\n * Country is required\r\n * </fui-error>\r\n * </fui-form-field>\r\n * </form>\r\n * ```\r\n *\r\n * ### With Add/Refresh Buttons\r\n * ```html\r\n * <fui-form-field>\r\n * <label>Category</label>\r\n * <fui-autocomplete\r\n * placeholder=\"Search categories...\"\r\n * [showAddButton]=\"true\"\r\n * [showRefreshButton]=\"true\"\r\n * (addNew)=\"openAddCategoryDialog()\"\r\n * (refresh)=\"refreshCategories()\">\r\n * @for (category of categories; track category.id) {\r\n * <fui-option [value]=\"category.id\">{{ category.name }}</fui-option>\r\n * }\r\n * </fui-autocomplete>\r\n * </fui-form-field>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-autocomplete',\r\n standalone: true,\r\n imports: [FuiIconComponent, ReactiveFormsModule, FuiButtonDirective],\r\n templateUrl: './autocomplete.component.html',\r\n styleUrls: ['./autocomplete.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-autocomplete',\r\n '[attr.id]': 'id',\r\n '[class.fui-autocomplete--open]': 'panelOpen()',\r\n '[class.fui-autocomplete--disabled]': 'disabled()',\r\n '[class.fui-autocomplete--focused]': 'focused()',\r\n '[class.fui-autocomplete--error]': 'errorState()',\r\n '[class.fui-autocomplete--readonly]': '_readOnly()',\r\n },\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: FuiAutocompleteComponent,\r\n multi: true,\r\n },\r\n {\r\n provide: FUI_FORM_FIELD_CONTROL,\r\n useExisting: FuiAutocompleteComponent,\r\n },\r\n {\r\n provide: FUI_AUTOCOMPLETE,\r\n useExisting: FuiAutocompleteComponent,\r\n },\r\n ],\r\n})\r\nexport class FuiAutocompleteComponent implements ControlValueAccessor, FuiFormFieldControl, DoCheck, OnDestroy {\r\n // Static properties\r\n static nextId = 0;\r\n readonly controlType = 'fui-autocomplete';\r\n\r\n // Injected dependencies required by input resolvers (must be declared before computed fields below)\r\n readonly intl = inject(FuiAutocompleteIntl);\r\n private readonly _cdr = inject(ChangeDetectorRef);\r\n\r\n // Inputs using signal-based API\r\n readonly placeholderInput: InputSignal<string> = input('', {\r\n alias: 'placeholder',\r\n });\r\n readonly disabledInput: InputSignal<boolean> = input(false, {\r\n alias: 'disabled',\r\n });\r\n readonly readonly: InputSignal<boolean> = input(false);\r\n readonly showAddButton: InputSignal<boolean> = input(false);\r\n readonly showRefreshButton: InputSignal<boolean> = input(false);\r\n readonly addButtonLabel = input<string | undefined>(undefined);\r\n readonly refreshButtonLabel = input<string | undefined>(undefined);\r\n readonly noOptionsText = input<string | undefined>(undefined);\r\n readonly searchPlaceholder = input<string | undefined>(undefined);\r\n readonly errorStateMatcher: InputSignal<ErrorStateMatcher | null> = input<ErrorStateMatcher | null>(null);\r\n\r\n // Resolved i18n labels: per-instance input wins, Intl service is fallback\r\n readonly resolvedAddButtonLabel = computed(() => this.addButtonLabel() ?? this.intl.addButtonLabel);\r\n readonly resolvedRefreshButtonLabel = computed(() => this.refreshButtonLabel() ?? this.intl.refreshButtonLabel);\r\n readonly resolvedNoOptionsText = computed(() => this.noOptionsText() ?? this.intl.noOptionsText);\r\n readonly resolvedSearchPlaceholder = computed(() => this.searchPlaceholder() ?? this.intl.searchPlaceholder);\r\n\r\n /**\r\n * Whether to compare option values using object identity or deep equality\r\n */\r\n readonly compareWith: InputSignal<(o1: unknown, o2: unknown) => boolean> = input<\r\n (o1: unknown, o2: unknown) => boolean\r\n >((o1, o2) => o1 === o2);\r\n\r\n // Outputs\r\n readonly valueChange: OutputEmitterRef<unknown> = output<unknown>();\r\n readonly selectionChange: OutputEmitterRef<FuiAutocompleteChange> = output<FuiAutocompleteChange>();\r\n readonly openedChange: OutputEmitterRef<boolean> = output<boolean>();\r\n readonly addNew: OutputEmitterRef<void> = output();\r\n readonly refresh: OutputEmitterRef<void> = output();\r\n readonly searchChange: OutputEmitterRef<string> = output<string>();\r\n\r\n // Internal state signals\r\n private readonly _value: WritableSignal<unknown> = signal(null);\r\n private readonly _focused: WritableSignal<boolean> = signal(false);\r\n private readonly _disabled: WritableSignal<boolean> = signal(false);\r\n readonly _readOnly: WritableSignal<boolean> = signal(false);\r\n\r\n // FuiFormFieldControl implementation\r\n readonly stateChanges = new Subject<void>();\r\n private _uid = `fui-autocomplete-${FuiAutocompleteComponent.nextId++}`;\r\n _ariaDescribedby: string | null = null;\r\n\r\n // Error state\r\n private readonly _errorState: WritableSignal<boolean> = signal(false);\r\n readonly errorState = this._errorState;\r\n\r\n // Form control references\r\n private _parentForm = inject(NgForm, { optional: true });\r\n private _parentFormGroup = inject(FormGroupDirective, { optional: true });\r\n private _defaultErrorStateMatcher = inject(DefaultErrorStateMatcher);\r\n private readonly _ngControlRef = injectNgControl();\r\n get ngControl(): NgControl | null {\r\n return this._ngControlRef.ngControl;\r\n }\r\n\r\n // Interface implementation\r\n readonly placeholder = computed(() => this.placeholderInput());\r\n private readonly _required: WritableSignal<boolean> = signal(false);\r\n readonly required = this._required;\r\n\r\n readonly value = this._value;\r\n readonly focused = this._focused;\r\n\r\n private readonly _ngControlDisabled: WritableSignal<boolean> = signal(false);\r\n readonly disabled = computed(() => this._disabled() || this.disabledInput() || this._ngControlDisabled());\r\n\r\n readonly empty = computed(() => {\r\n const val = this._value();\r\n return val === null || val === undefined;\r\n });\r\n\r\n readonly id = this._uid;\r\n\r\n // ViewChild for trigger and panel\r\n @ViewChild('trigger', { static: false }) trigger?: ElementRef<HTMLDivElement>;\r\n @ViewChild('panel', { static: false }) panel?: ElementRef<HTMLDivElement>;\r\n @ViewChild('searchInput', { static: false })\r\n searchInput?: ElementRef<HTMLInputElement>;\r\n\r\n // ContentChildren for options\r\n readonly options = contentChildren(FuiOptionComponent, { descendants: true });\r\n\r\n // Panel open/close state\r\n readonly panelOpen = signal(false);\r\n\r\n // Search term for filtering\r\n readonly searchTerm: WritableSignal<string> = signal('');\r\n\r\n // Active option index for keyboard navigation\r\n readonly activeOptionIndex: WritableSignal<number> = signal(-1);\r\n\r\n // Live announcement for screen readers\r\n readonly _liveAnnouncement = signal('');\r\n\r\n _announce(message: string): void {\r\n this._liveAnnouncement.set('');\r\n setTimeout(() => {\r\n this._liveAnnouncement.set(message);\r\n }, 50);\r\n }\r\n\r\n // Overlay reference\r\n private _overlayRef: FuiOverlayRef | null = null;\r\n private _overlaySubscriptions = new Subscription();\r\n\r\n // Services\r\n private readonly _overlayService = inject(FuiOverlayService);\r\n private readonly _elementRef = inject(ElementRef);\r\n private readonly _document = inject(DOCUMENT);\r\n private readonly _ngZone = inject(NgZone);\r\n private _outsideClickSub?: Subscription;\r\n\r\n // ControlValueAccessor callbacks\r\n private _onChange: (value: unknown) => void = () => {\r\n // Intentionally empty: will be replaced by Angular forms\r\n };\r\n private _onTouched: () => void = () => {\r\n // Intentionally empty: will be replaced by Angular forms\r\n };\r\n\r\n // Computed properties\r\n readonly displayValue: Signal<string> = computed(() => {\r\n const currentValue = this.value();\r\n const opts = this.options();\r\n\r\n if (currentValue === null || currentValue === undefined) {\r\n return '';\r\n }\r\n\r\n const selectedOption = opts.find((opt) => this.compareWith()(opt.value(), currentValue));\r\n return selectedOption ? selectedOption.getLabel() : String(currentValue);\r\n });\r\n\r\n // Filtered options based on search term\r\n readonly filteredOptions: Signal<FuiOptionComponent[]> = computed(() => {\r\n const opts = this.options();\r\n const term = this.searchTerm().toLowerCase().trim();\r\n\r\n if (!term) {\r\n return opts.filter((opt) => !opt.disabled());\r\n }\r\n\r\n return opts.filter((opt) => !opt.disabled() && opt.getLabel().toLowerCase().includes(term));\r\n });\r\n\r\n readonly hasFilteredOptions: Signal<boolean> = computed(() => {\r\n return this.filteredOptions().length > 0;\r\n });\r\n\r\n constructor() {\r\n // Set valueAccessor after NgControl is resolved\r\n void Promise.resolve().then(() => {\r\n if (this._ngControlRef.ngControl) {\r\n this._ngControlRef.ngControl.valueAccessor = this;\r\n }\r\n });\r\n\r\n // Subscribe to Intl changes to trigger re-render when labels mutate at runtime\r\n this.intl.changes.pipe(takeUntilDestroyed()).subscribe(() => { this._cdr.markForCheck(); });\r\n\r\n // Effect to emit state changes\r\n effect(() => {\r\n // Track all reactive inputs and internal signals\r\n this.placeholderInput();\r\n this.readonly();\r\n this.disabledInput();\r\n this.errorStateMatcher();\r\n this._focused();\r\n this._disabled();\r\n this._value();\r\n this._ngControlDisabled();\r\n this._required();\r\n this._errorState();\r\n\r\n // Emit state change\r\n this.stateChanges.next();\r\n });\r\n\r\n // Effect to update options selected state when value changes\r\n effect(() => {\r\n const currentValue = this._value();\r\n const opts = this.options();\r\n const compareFn = this.compareWith();\r\n\r\n opts.forEach((option) => {\r\n const optValue = option.value();\r\n const isSelected = compareFn(currentValue, optValue);\r\n\r\n if (isSelected) {\r\n option.select();\r\n } else {\r\n option.deselect();\r\n }\r\n });\r\n\r\n // Notify form-field that state may have changed\r\n this.stateChanges.next();\r\n });\r\n }\r\n\r\n ngDoCheck(): void {\r\n if (this.ngControl) {\r\n updateErrorState(\r\n this.ngControl,\r\n this._errorState,\r\n this.errorStateMatcher(),\r\n this._defaultErrorStateMatcher,\r\n this._parentForm,\r\n this._parentFormGroup,\r\n this.stateChanges,\r\n );\r\n syncRequiredState(this.ngControl, this._required, this.stateChanges);\r\n syncNgControlDisabled(this.ngControl, this._ngControlDisabled, this.stateChanges);\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.stateChanges.complete();\r\n this._outsideClickSub?.unsubscribe();\r\n this._disposeOverlay();\r\n }\r\n\r\n // ControlValueAccessor implementation\r\n writeValue(value: unknown): void {\r\n this._value.set(value ?? null);\r\n this.stateChanges.next();\r\n }\r\n\r\n registerOnChange(fn: (value: unknown) => void): void {\r\n this._onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: () => void): void {\r\n this._onTouched = fn;\r\n }\r\n\r\n setDisabledState(isDisabled: boolean): void {\r\n this._disabled.set(isDisabled);\r\n this.stateChanges.next();\r\n }\r\n\r\n // FuiFormFieldControl implementation\r\n onContainerClick(_event: MouseEvent): void {\r\n if (!this.disabled()) {\r\n this.toggle();\r\n }\r\n }\r\n\r\n setDescribedByIds(ids: string[]): void {\r\n this._ariaDescribedby = ids.length ? ids.join(' ') : null;\r\n }\r\n\r\n setReadOnly(readOnly: boolean): void {\r\n this._readOnly.set(readOnly);\r\n }\r\n\r\n // Public methods\r\n clear(event: Event): void {\r\n event.stopPropagation();\r\n this._value.set(null);\r\n this._onChange(null);\r\n this.valueChange.emit(null);\r\n this.selectionChange.emit({ source: this, value: null });\r\n this.stateChanges.next();\r\n }\r\n\r\n focus(): void {\r\n this.trigger?.nativeElement.focus();\r\n }\r\n\r\n blur(): void {\r\n this.trigger?.nativeElement.blur();\r\n }\r\n\r\n // Toggle panel open/close\r\n toggle(): void {\r\n if (this.disabled()) return;\r\n if (this.panelOpen()) {\r\n this.close();\r\n } else {\r\n this.open();\r\n }\r\n }\r\n\r\n // Open the dropdown panel\r\n open(): void {\r\n if (this.disabled() || this.readonly() || this.panelOpen()) return;\r\n\r\n this.panelOpen.set(true);\r\n this._focused.set(true);\r\n this.searchTerm.set('');\r\n this.openedChange.emit(true);\r\n\r\n // Set active option to currently selected or first option\r\n this._setInitialActiveOption();\r\n\r\n // Create overlay after the view updates\r\n setTimeout(() => {\r\n this._createOverlay();\r\n this._scrollToActiveOption();\r\n this._listenForOutsideClicks();\r\n // Focus the search input\r\n this.searchInput?.nativeElement.focus();\r\n }, 0);\r\n }\r\n\r\n // Close the dropdown panel\r\n close(): void {\r\n if (!this.panelOpen()) return;\r\n this._outsideClickSub?.unsubscribe();\r\n\r\n this.panelOpen.set(false);\r\n this._focused.set(false);\r\n this.activeOptionIndex.set(-1);\r\n this.searchTerm.set('');\r\n this._disposeOverlay();\r\n this.openedChange.emit(false);\r\n this._onTouched();\r\n\r\n // Clear active state on all options\r\n this.options().forEach((opt) => {\r\n opt.setInactive();\r\n });\r\n\r\n // Return focus to trigger\r\n setTimeout(() => {\r\n this.trigger?.nativeElement.focus();\r\n }, 0);\r\n }\r\n\r\n // Handle option selection (called by FuiOptionComponent or internally)\r\n _onOptionSelected(option: FuiOptionComponent): void {\r\n const newValue = option.value();\r\n\r\n // Deselect previous option\r\n const opts = this.options();\r\n opts.forEach((opt) => {\r\n if (opt !== option) {\r\n opt.deselect();\r\n }\r\n });\r\n\r\n option.select();\r\n this._value.set(newValue);\r\n this._onChange(newValue);\r\n this.valueChange.emit(newValue);\r\n this.selectionChange.emit({ source: this, value: newValue });\r\n this._announce(`${option.getLabel()} selected`);\r\n this.close();\r\n\r\n this.stateChanges.next();\r\n }\r\n\r\n // Handle search input\r\n onSearchInput(event: Event): void {\r\n const target = event.target as HTMLInputElement;\r\n const term = target.value;\r\n this.searchTerm.set(term);\r\n this.searchChange.emit(term);\r\n\r\n // Reset active index when search changes\r\n const filtered = this.filteredOptions();\r\n if (filtered.length > 0) {\r\n this._setActiveOptionIndex(0);\r\n } else {\r\n this.activeOptionIndex.set(-1);\r\n }\r\n }\r\n\r\n // Handle add new action\r\n onAddNew(): void {\r\n this.close();\r\n this.addNew.emit();\r\n }\r\n\r\n // Handle refresh action\r\n onRefresh(): void {\r\n this.refresh.emit();\r\n // Keep panel open and clear search\r\n this.searchTerm.set('');\r\n }\r\n\r\n // Get display value for trigger\r\n _getDisplayValue(): string {\r\n return this.displayValue();\r\n }\r\n\r\n // Handle keyboard navigation\r\n _handleKeydown(event: KeyboardEvent): void {\r\n if (this.disabled()) return;\r\n\r\n const isOpen = this.panelOpen();\r\n\r\n if (!isOpen) {\r\n this._handleClosedKeydown(event);\r\n } else {\r\n this._handleOpenKeydown(event);\r\n }\r\n }\r\n\r\n // Handle keydown when panel is closed\r\n private _handleClosedKeydown(event: KeyboardEvent): void {\r\n const key = event.key;\r\n\r\n switch (key) {\r\n case 'Enter':\r\n case ' ':\r\n case 'ArrowDown':\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this.open();\r\n break;\r\n }\r\n }\r\n\r\n // Handle keydown when panel is open (for search input)\r\n _handlePanelKeydown(event: KeyboardEvent): void {\r\n if (this.disabled()) return;\r\n\r\n const key = event.key;\r\n const opts = this.filteredOptions();\r\n const activeIndex = this.activeOptionIndex();\r\n\r\n switch (key) {\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n this._setNextActiveOption(1);\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this._setNextActiveOption(-1);\r\n break;\r\n case 'Home':\r\n event.preventDefault();\r\n if (opts.length > 0) {\r\n this._setActiveOptionIndex(0);\r\n }\r\n break;\r\n case 'End':\r\n event.preventDefault();\r\n if (opts.length > 0) {\r\n this._setActiveOptionIndex(opts.length - 1);\r\n }\r\n break;\r\n case 'PageDown':\r\n event.preventDefault();\r\n if (opts.length > 0) {\r\n const pageSize = Math.min(10, opts.length);\r\n const newIndex = Math.min(activeIndex + pageSize, opts.length - 1);\r\n this._setActiveOptionIndex(newIndex);\r\n }\r\n break;\r\n case 'PageUp':\r\n event.preventDefault();\r\n if (opts.length > 0) {\r\n const pageSize = Math.min(10, opts.length);\r\n const newIndex = Math.max(activeIndex - pageSize, 0);\r\n this._setActiveOptionIndex(newIndex);\r\n }\r\n break;\r\n case 'Enter':\r\n event.preventDefault();\r\n if (activeIndex >= 0 && activeIndex < opts.length) {\r\n this._onOptionSelected(opts[activeIndex]);\r\n }\r\n break;\r\n case 'Escape':\r\n event.preventDefault();\r\n this.close();\r\n break;\r\n case 'Tab':\r\n // Allow tab to close and move to next element\r\n this.close();\r\n break;\r\n }\r\n }\r\n\r\n // Handle keydown when panel is open (for trigger)\r\n private _handleOpenKeydown(event: KeyboardEvent): void {\r\n // Delegate to panel keydown handler\r\n this._handlePanelKeydown(event);\r\n }\r\n\r\n // Set the next active option based on delta\r\n private _setNextActiveOption(delta: number): void {\r\n const opts = this.filteredOptions();\r\n if (opts.length === 0) return;\r\n\r\n let currentIndex = this.activeOptionIndex();\r\n if (currentIndex < 0) {\r\n currentIndex = delta > 0 ? -1 : opts.length;\r\n }\r\n\r\n let newIndex = currentIndex + delta;\r\n\r\n // Wrap around\r\n if (newIndex < 0) {\r\n newIndex = opts.length - 1;\r\n } else if (newIndex >= opts.length) {\r\n newIndex = 0;\r\n }\r\n\r\n this._setActiveOptionIndex(newIndex);\r\n }\r\n\r\n // Set the active option index\r\n private _setActiveOptionIndex(index: number): void {\r\n const opts = this.filteredOptions();\r\n if (index < 0 || index >= opts.length) return;\r\n\r\n // Update active state on options\r\n const allOpts = this.options();\r\n allOpts.forEach((opt) => {\r\n opt.setInactive();\r\n });\r\n\r\n const activeOption = opts[index];\r\n activeOption.setActive();\r\n this.activeOptionIndex.set(index);\r\n this._scrollToActiveOption();\r\n this._announce(`${activeOption.getLabel()}, ${index + 1} of ${opts.length}`);\r\n }\r\n\r\n // Set initial active option when opening\r\n private _setInitialActiveOption(): void {\r\n const opts = this.filteredOptions();\r\n if (opts.length === 0) {\r\n this.activeOptionIndex.set(-1);\r\n return;\r\n }\r\n\r\n const currentValue = this._value();\r\n const compareFn = this.compareWith();\r\n\r\n // Find the selected option\r\n let selectedIndex = -1;\r\n if (currentValue !== null && currentValue !== undefined) {\r\n selectedIndex = opts.findIndex((opt) => compareFn(opt.value(), currentValue));\r\n }\r\n\r\n const initialIndex = selectedIndex >= 0 ? selectedIndex : 0;\r\n this._setActiveOptionIndex(initialIndex);\r\n }\r\n\r\n // Scroll to active option\r\n private _scrollToActiveOption(): void {\r\n const opts = this.filteredOptions();\r\n const activeIndex = this.activeOptionIndex();\r\n\r\n if (activeIndex < 0 || activeIndex >= opts.length) return;\r\n\r\n const activeOption = opts[activeIndex];\r\n const element = activeOption._getHostElement();\r\n const panelElement = this.panel?.nativeElement;\r\n\r\n if (element && panelElement) {\r\n const optionsContainer = panelElement.querySelector('.fui-autocomplete__options');\r\n if (optionsContainer) {\r\n const optionTop = element.offsetTop - (optionsContainer as HTMLElement).offsetTop;\r\n const optionBottom = optionTop + element.offsetHeight;\r\n const containerTop = optionsContainer.scrollTop;\r\n const containerBottom = containerTop + optionsContainer.clientHeight;\r\n\r\n if (optionTop < containerTop) {\r\n optionsContainer.scrollTop = optionTop;\r\n } else if (optionBottom > containerBottom) {\r\n optionsContainer.scrollTop = optionBottom - optionsContainer.clientHeight;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Start listening for outside clicks when panel opens\r\n private _listenForOutsideClicks(): void {\r\n this._outsideClickSub?.unsubscribe();\r\n\r\n this._ngZone.runOutsideAngular(() => {\r\n setTimeout(() => {\r\n this._outsideClickSub = fromEvent<MouseEvent>(this._document, 'click')\r\n .pipe(\r\n filter(() => this.panelOpen()),\r\n filter((event) => {\r\n const target = event.target as HTMLElement;\r\n const triggerElement = this.trigger?.nativeElement;\r\n const panelElement = this.panel?.nativeElement;\r\n const overlayElement = this._overlayRef?.overlayElement;\r\n return (\r\n !triggerElement?.contains(target) &&\r\n !panelElement?.contains(target) &&\r\n !overlayElement?.contains(target)\r\n );\r\n }),\r\n )\r\n .subscribe(() => {\r\n this._ngZone.run(() => {\r\n this.close();\r\n });\r\n });\r\n });\r\n });\r\n }\r\n\r\n // Create overlay for panel\r\n private _createOverlay(): void {\r\n if (this._overlayRef || !this.panel || !this.trigger) return;\r\n\r\n const triggerElement = this.trigger.nativeElement;\r\n const triggerWidth = triggerElement.getBoundingClientRect().width;\r\n\r\n const positions: FuiConnectedPosition[] = [\r\n {\r\n originX: 'start',\r\n originY: 'bottom',\r\n overlayX: 'start',\r\n overlayY: 'top',\r\n offsetY: 4,\r\n },\r\n {\r\n originX: 'start',\r\n originY: 'top',\r\n overlayX: 'start',\r\n overlayY: 'bottom',\r\n offsetY: -4,\r\n },\r\n ];\r\n\r\n const positionStrategy = this._overlayService\r\n .position()\r\n .connectedTo(triggerElement, positions)\r\n .withPush(true)\r\n .withViewportMargin(8);\r\n\r\n this._overlayRef = this._overlayService.create({\r\n positionStrategy,\r\n scrollStrategy: this._overlayService.scrollStrategies.reposition(),\r\n hasBackdrop: true,\r\n backdropClass: 'fui-autocomplete-backdrop',\r\n backdropClickBehavior: 'close',\r\n panelClass: ['fui-autocomplete-overlay-panel'],\r\n minWidth: triggerWidth,\r\n });\r\n\r\n // Track overlay subscriptions for proper cleanup\r\n this._overlaySubscriptions.unsubscribe();\r\n this._overlaySubscriptions = new Subscription();\r\n\r\n this._overlaySubscriptions.add(\r\n this._overlayRef.backdropClick.subscribe(() => {\r\n this.close();\r\n }),\r\n );\r\n\r\n this._overlaySubscriptions.add(\r\n this._overlayRef.keydownEvents.subscribe((event) => {\r\n if (event.key === 'Escape') {\r\n this.close();\r\n }\r\n }),\r\n );\r\n\r\n // Attach panel to overlay\r\n const panelElement = this.panel.nativeElement;\r\n this._overlayRef.attach(panelElement);\r\n }\r\n\r\n // Dispose overlay\r\n private _disposeOverlay(): void {\r\n this._overlaySubscriptions.unsubscribe();\r\n if (this._overlayRef) {\r\n this._overlayRef.dispose();\r\n this._overlayRef = null;\r\n }\r\n }\r\n\r\n // Get the active option's id for aria-activedescendant\r\n _getActiveDescendant(): string | null {\r\n const opts = this.filteredOptions();\r\n const activeIndex = this.activeOptionIndex();\r\n if (activeIndex >= 0 && activeIndex < opts.length) {\r\n return opts[activeIndex].id;\r\n }\r\n return null;\r\n }\r\n\r\n // Set active option by index (for template use)\r\n setActiveOption(index: number, option: FuiOptionComponent): void {\r\n const allOpts = this.options();\r\n allOpts.forEach((opt) => {\r\n opt.setInactive();\r\n });\r\n option.setActive();\r\n this.activeOptionIndex.set(index);\r\n }\r\n\r\n // Mat-autocomplete compatibility methods\r\n get selected(): unknown {\r\n return this.value;\r\n }\r\n}\r\n","<!-- Autocomplete Trigger -->\r\n<div\r\n #trigger\r\n [id]=\"id\"\r\n class=\"fui-autocomplete__trigger\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n [attr.role]=\"'combobox'\"\r\n [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-expanded]=\"panelOpen()\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n [attr.aria-invalid]=\"errorState()\"\r\n [attr.aria-describedby]=\"_ariaDescribedby\"\r\n [attr.aria-required]=\"required()\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-activedescendant]=\"panelOpen() ? _getActiveDescendant() : null\"\r\n [attr.aria-controls]=\"panelOpen() ? id + '-panel' : null\"\r\n (keydown)=\"_handleKeydown($event)\"\r\n>\r\n <span class=\"fui-autocomplete__value\">\r\n @if (empty()) {\r\n <span class=\"fui-autocomplete__placeholder\">{{ placeholder() }}</span>\r\n } @else {\r\n <span class=\"fui-autocomplete__value-text\">{{ _getDisplayValue() }}</span>\r\n }\r\n </span>\r\n\r\n @if (!_readOnly()) {\r\n <!-- Clear button — visible only when a value is selected and not disabled -->\r\n @if (!empty() && !disabled()) {\r\n <span class=\"fui-autocomplete__clear\" role=\"button\" [attr.aria-label]=\"intl.clearSelectionAriaLabel\" (click)=\"clear($event)\">\r\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\r\n <path\r\n d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\"\r\n />\r\n </svg>\r\n </span>\r\n }\r\n\r\n <!-- Dropdown arrow icon -->\r\n <svg\r\n class=\"fui-autocomplete__arrow\"\r\n [class.fui-autocomplete__arrow--open]=\"panelOpen()\"\r\n viewBox=\"0 0 16 16\"\r\n fill=\"currentColor\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M8 11L3 6l.7-.7L8 9.6l4.3-4.3L13 6z\" />\r\n </svg>\r\n }\r\n</div>\r\n\r\n<!-- Hidden container for projected options (used for data binding) -->\r\n<div class=\"fui-autocomplete__options-source\">\r\n <ng-content></ng-content>\r\n</div>\r\n\r\n<!-- Dropdown Panel -->\r\n@if (panelOpen()) {\r\n <div #panel [id]=\"id + '-panel'\" class=\"fui-autocomplete__panel\" [attr.aria-label]=\"placeholder()\">\r\n <!-- Search Input -->\r\n <div class=\"fui-autocomplete__search\">\r\n <fui-icon name=\"magnifying-glass\" size=\"sm\" class=\"fui-autocomplete__search-icon\"> </fui-icon>\r\n <input\r\n #searchInput\r\n type=\"text\"\r\n class=\"fui-autocomplete__search-input\"\r\n [placeholder]=\"resolvedSearchPlaceholder()\"\r\n [value]=\"searchTerm()\"\r\n autocomplete=\"off\"\r\n role=\"searchbox\"\r\n [attr.aria-label]=\"resolvedSearchPlaceholder()\"\r\n [attr.aria-controls]=\"id + '-panel-listbox'\"\r\n [attr.aria-activedescendant]=\"_getActiveDescendant()\"\r\n (input)=\"onSearchInput($event)\"\r\n (keydown)=\"_handlePanelKeydown($event)\"\r\n />\r\n </div>\r\n <!-- Live region for announcing result count to screen readers -->\r\n <div class=\"fui-sr-only\" aria-live=\"assertive\" aria-atomic=\"true\">\r\n @if (_liveAnnouncement()) {\r\n {{ _liveAnnouncement() }}\r\n } @else if (hasFilteredOptions()) {\r\n {{ intl.resultsAvailableText(filteredOptions().length) }}\r\n } @else {\r\n {{ intl.noResultsAvailableText }}\r\n }\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n @if (showAddButton() || showRefreshButton()) {\r\n <div class=\"fui-autocomplete__actions\">\r\n @if (showAddButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"tertiary\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onAddNew()\"\r\n >\r\n <fui-icon name=\"plus\" size=\"sm\"></fui-icon>\r\n {{ resolvedAddButtonLabel() }}\r\n </button>\r\n }\r\n @if (showRefreshButton()) {\r\n <button\r\n type=\"button\"\r\n fuiButton\r\n variant=\"tertiary\"\r\n size=\"sm\"\r\n class=\"fui-autocomplete__action-button\"\r\n (click)=\"onRefresh()\"\r\n >\r\n <fui-icon name=\"refresh-cw\" size=\"sm\"></fui-icon>\r\n {{ resolvedRefreshButtonLabel() }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Options List -->\r\n <div\r\n class=\"fui-autocomplete__options\"\r\n [id]=\"id + '-panel-listbox'\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"placeholder()\"\r\n >\r\n @if (hasFilteredOptions()) {\r\n @for (option of filteredOptions(); track option.id; let i = $index) {\r\n <div\r\n class=\"fui-autocomplete__option\"\r\n [class.fui-autocomplete__option--active]=\"activeOptionIndex() === i\"\r\n [class.fui-autocomplete__option--selected]=\"option._selected()\"\r\n role=\"option\"\r\n [attr.id]=\"option.id\"\r\n [attr.aria-selected]=\"option._selected()\"\r\n (click)=\"_onOptionSelected(option)\"\r\n (mouseenter)=\"setActiveOption(i, option)\"\r\n (mouseleave)=\"option.setInactive()\"\r\n >\r\n <span class=\"fui-autocomplete__option-text\">{{ option.getLabel() }}</span>\r\n @if (option._selected()) {\r\n <fui-icon name=\"check\" size=\"sm\" class=\"fui-autocomplete__option-check\"></fui-icon>\r\n }\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"fui-autocomplete__no-options\">\r\n {{ resolvedNoOptionsText() }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAIM,MAAO,mBAAoB,SAAQ,WAAW,CAAA;IAClD,cAAc,GAAG,SAAS;IAC1B,kBAAkB,GAAG,SAAS;IAC9B,aAAa,GAAG,kBAAkB;IAClC,iBAAiB,GAAG,WAAW;IAC/B,uBAAuB,GAAG,iBAAiB;IAC3C,sBAAsB,GAAG,uBAAuB;AAEhD,IAAA,oBAAoB,CAAC,KAAa,EAAA;QAChC,OAAO,CAAA,EAAG,KAAK,CAAA,mBAAA,CAAqB;IACtC;uGAVW,mBAAmB,EAAA,IAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,cADN,MAAM,EAAA,CAAA;;2FACnB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAD/B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;AC0ClC;;AAEG;MACU,gBAAgB,GAAG,IAAI,cAAc,CAA2B,kBAAkB;AAU/F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEG;MAkCU,wBAAwB,CAAA;;AAEnC,IAAA,OAAO,MAAM,GAAG,CAAC;IACR,WAAW,GAAG,kBAAkB;;AAGhC,IAAA,IAAI,GAAG,MAAM,CAAC,mBAAmB,CAAC;AAC1B,IAAA,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;;IAGxC,gBAAgB,GAAwB,KAAK,CAAC,EAAE,wFACvD,KAAK,EAAE,aAAa,EAAA,CACpB;IACO,aAAa,GAAyB,KAAK,CAAC,KAAK,qFACxD,KAAK,EAAE,UAAU,EAAA,CACjB;AACO,IAAA,QAAQ,GAAyB,KAAK,CAAC,KAAK,+EAAC;AAC7C,IAAA,aAAa,GAAyB,KAAK,CAAC,KAAK,oFAAC;AAClD,IAAA,iBAAiB,GAAyB,KAAK,CAAC,KAAK,wFAAC;AACtD,IAAA,cAAc,GAAG,KAAK,CAAqB,SAAS,qFAAC;AACrD,IAAA,kBAAkB,GAAG,KAAK,CAAqB,SAAS,yFAAC;AACzD,IAAA,aAAa,GAAG,KAAK,CAAqB,SAAS,oFAAC;AACpD,IAAA,iBAAiB,GAAG,KAAK,CAAqB,SAAS,wFAAC;AACxD,IAAA,iBAAiB,GAA0C,KAAK,CAA2B,IAAI,wFAAC;;AAGhG,IAAA,sBAAsB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc,6FAAC;AAC1F,IAAA,0BAA0B,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,kBAAkB,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,kBAAkB,iGAAC;AACtG,IAAA,qBAAqB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,4FAAC;AACvF,IAAA,yBAAyB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,iBAAiB,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,iBAAiB,gGAAC;AAE5G;;AAEG;AACM,IAAA,WAAW,GAAuD,KAAK,CAE9E,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,kFAAC;;IAGf,WAAW,GAA8B,MAAM,EAAW;IAC1D,eAAe,GAA4C,MAAM,EAAyB;IAC1F,YAAY,GAA8B,MAAM,EAAW;IAC3D,MAAM,GAA2B,MAAM,EAAE;IACzC,OAAO,GAA2B,MAAM,EAAE;IAC1C,YAAY,GAA6B,MAAM,EAAU;;AAGjD,IAAA,MAAM,GAA4B,MAAM,CAAC,IAAI,6EAAC;AAC9C,IAAA,QAAQ,GAA4B,MAAM,CAAC,KAAK,+EAAC;AACjD,IAAA,SAAS,GAA4B,MAAM,CAAC,KAAK,gFAAC;AAC1D,IAAA,SAAS,GAA4B,MAAM,CAAC,KAAK,gFAAC;;AAGlD,IAAA,YAAY,GAAG,IAAI,OAAO,EAAQ;AACnC,IAAA,IAAI,GAAG,CAAA,iBAAA,EAAoB,wBAAwB,CAAC,MAAM,EAAE,EAAE;IACtE,gBAAgB,GAAkB,IAAI;;AAGrB,IAAA,WAAW,GAA4B,MAAM,CAAC,KAAK,kFAAC;AAC5D,IAAA,UAAU,GAAG,IAAI,CAAC,WAAW;;IAG9B,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAChD,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACjE,IAAA,yBAAyB,GAAG,MAAM,CAAC,wBAAwB,CAAC;IACnD,aAAa,GAAG,eAAe,EAAE;AAClD,IAAA,IAAI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS;IACrC;;IAGS,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,gBAAgB,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,aAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAC;AAC7C,IAAA,SAAS,GAA4B,MAAM,CAAC,KAAK,gFAAC;AAC1D,IAAA,QAAQ,GAAG,IAAI,CAAC,SAAS;AAEzB,IAAA,KAAK,GAAG,IAAI,CAAC,MAAM;AACnB,IAAA,OAAO,GAAG,IAAI,CAAC,QAAQ;AAEf,IAAA,kBAAkB,GAA4B,MAAM,CAAC,KAAK,yFAAC;IACnE,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,aAAa,EAAE,IAAI,IAAI,CAAC,kBAAkB,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,UAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAC;AAEhG,IAAA,KAAK,GAAG,QAAQ,CAAC,MAAK;AAC7B,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE;AACzB,QAAA,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;AAC1C,IAAA,CAAC,4EAAC;AAEO,IAAA,EAAE,GAAG,IAAI,CAAC,IAAI;;AAGkB,IAAA,OAAO;AACT,IAAA,KAAK;AAE5C,IAAA,WAAW;;IAGF,OAAO,GAAG,eAAe,CAAC,kBAAkB,+EAAI,WAAW,EAAE,IAAI,EAAA,CAAG;;AAGpE,IAAA,SAAS,GAAG,MAAM,CAAC,KAAK,gFAAC;;AAGzB,IAAA,UAAU,GAA2B,MAAM,CAAC,EAAE,iFAAC;;AAG/C,IAAA,iBAAiB,GAA2B,MAAM,CAAC,CAAC,CAAC,wFAAC;;AAGtD,IAAA,iBAAiB,GAAG,MAAM,CAAC,EAAE,wFAAC;AAEvC,IAAA,SAAS,CAAC,OAAe,EAAA;AACvB,QAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC;QACrC,CAAC,EAAE,EAAE,CAAC;IACR;;IAGQ,WAAW,GAAyB,IAAI;AACxC,IAAA,qBAAqB,GAAG,IAAI,YAAY,EAAE;;AAGjC,IAAA,eAAe,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAC3C,IAAA,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC;AAChC,IAAA,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC5B,IAAA,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;AACjC,IAAA,gBAAgB;;IAGhB,SAAS,GAA6B,MAAK;;AAEnD,IAAA,CAAC;IACO,UAAU,GAAe,MAAK;;AAEtC,IAAA,CAAC;;AAGQ,IAAA,YAAY,GAAmB,QAAQ,CAAC,MAAK;AACpD,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,EAAE;AACjC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE;QAE3B,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,SAAS,EAAE;AACvD,YAAA,OAAO,EAAE;QACX;QAEA,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,YAAY,CAAC,CAAC;AACxF,QAAA,OAAO,cAAc,GAAG,cAAc,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;AAC1E,IAAA,CAAC,mFAAC;;AAGO,IAAA,eAAe,GAAiC,QAAQ,CAAC,MAAK;AACrE,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE;AAC3B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE;QAEnD,IAAI,CAAC,IAAI,EAAE;AACT,YAAA,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9C;AAEA,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC7F,IAAA,CAAC,sFAAC;AAEO,IAAA,kBAAkB,GAAoB,QAAQ,CAAC,MAAK;QAC3D,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC,MAAM,GAAG,CAAC;AAC1C,IAAA,CAAC,yFAAC;AAEF,IAAA,WAAA,GAAA;;QAEE,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,MAAK;AAC/B,YAAA,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE;gBAChC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,aAAa,GAAG,IAAI;YACnD;AACF,QAAA,CAAC,CAAC;;QAGF,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,SAAS,CAAC,MAAK,EAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;;QAG3F,MAAM,CAAC,MAAK;;YAEV,IAAI,CAAC,gBAAgB,EAAE;YACvB,IAAI,CAAC,QAAQ,EAAE;YACf,IAAI,CAAC,aAAa,EAAE;YACpB,IAAI,CAAC,iBAAiB,EAAE;YACxB,IAAI,CAAC,QAAQ,EAAE;YACf,IAAI,CAAC,SAAS,EAAE;YAChB,IAAI,CAAC,MAAM,EAAE;YACb,IAAI,CAAC,kBAAkB,EAAE;YACzB,IAAI,CAAC,SAAS,EAAE;YAChB,IAAI,CAAC,WAAW,EAAE;;AAGlB,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;AAC1B,QAAA,CAAC,CAAC;;QAGF,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE;AAClC,YAAA,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE;AAC3B,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE;AAEpC,YAAA,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAI;AACtB,gBAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE;gBAC/B,MAAM,UAAU,GAAG,SAAS,CAAC,YAAY,EAAE,QAAQ,CAAC;gBAEpD,IAAI,UAAU,EAAE;oBACd,MAAM,CAAC,MAAM,EAAE;gBACjB;qBAAO;oBACL,MAAM,CAAC,QAAQ,EAAE;gBACnB;AACF,YAAA,CAAC,CAAC;;AAGF,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;AAC1B,QAAA,CAAC,CAAC;IACJ;IAEA,SAAS,GAAA;AACP,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,gBAAgB,CACd,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,iBAAiB,EAAE,EACxB,IAAI,CAAC,yBAAyB,EAC9B,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,gBAAgB,EACrB,IAAI,CAAC,YAAY,CAClB;AACD,YAAA,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC;AACpE,YAAA,qBAAqB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,YAAY,CAAC;QACnF;IACF;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE;AAC5B,QAAA,IAAI,CAAC,gBAAgB,EAAE,WAAW,EAAE;QACpC,IAAI,CAAC,eAAe,EAAE;IACxB;;AAGA,IAAA,UAAU,CAAC,KAAc,EAAA;QACvB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC;AAC9B,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;AAEA,IAAA,gBAAgB,CAAC,EAA4B,EAAA;AAC3C,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;IACrB;AAEA,IAAA,iBAAiB,CAAC,EAAc,EAAA;AAC9B,QAAA,IAAI,CAAC,UAAU,GAAG,EAAE;IACtB;AAEA,IAAA,gBAAgB,CAAC,UAAmB,EAAA;AAClC,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC;AAC9B,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;;AAGA,IAAA,gBAAgB,CAAC,MAAkB,EAAA;AACjC,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;YACpB,IAAI,CAAC,MAAM,EAAE;QACf;IACF;AAEA,IAAA,iBAAiB,CAAC,GAAa,EAAA;AAC7B,QAAA,IAAI,CAAC,gBAAgB,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI;IAC3D;AAEA,IAAA,WAAW,CAAC,QAAiB,EAAA;AAC3B,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC9B;;AAGA,IAAA,KAAK,CAAC,KAAY,EAAA;QAChB,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;AACrB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AACpB,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3B,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACxD,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,EAAE;IACrC;IAEA,IAAI,GAAA;AACF,QAAA,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,EAAE;IACpC;;IAGA,MAAM,GAAA;QACJ,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AACrB,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;YACpB,IAAI,CAAC,KAAK,EAAE;QACd;aAAO;YACL,IAAI,CAAC,IAAI,EAAE;QACb;IACF;;IAGA,IAAI,GAAA;AACF,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE;YAAE;AAE5D,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;AACxB,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;AACvB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;AACvB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;;QAG5B,IAAI,CAAC,uBAAuB,EAAE;;QAG9B,UAAU,CAAC,MAAK;YACd,IAAI,CAAC,cAAc,EAAE;YACrB,IAAI,CAAC,qBAAqB,EAAE;YAC5B,IAAI,CAAC,uBAAuB,EAAE;;AAE9B,YAAA,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,KAAK,EAAE;QACzC,CAAC,EAAE,CAAC,CAAC;IACP;;IAGA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE;AACvB,QAAA,IAAI,CAAC,gBAAgB,EAAE,WAAW,EAAE;AAEpC,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC9B,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,IAAI,CAAC,eAAe,EAAE;AACtB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAC7B,IAAI,CAAC,UAAU,EAAE;;QAGjB,IAAI,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;YAC7B,GAAG,CAAC,WAAW,EAAE;AACnB,QAAA,CAAC,CAAC;;QAGF,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,EAAE;QACrC,CAAC,EAAE,CAAC,CAAC;IACP;;AAGA,IAAA,iBAAiB,CAAC,MAA0B,EAAA;AAC1C,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE;;AAG/B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE;AAC3B,QAAA,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;AACnB,YAAA,IAAI,GAAG,KAAK,MAAM,EAAE;gBAClB,GAAG,CAAC,QAAQ,EAAE;YAChB;AACF,QAAA,CAAC,CAAC;QAEF,MAAM,CAAC,MAAM,EAAE;AACf,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;AACzB,QAAA,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;AACxB,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC;AAC/B,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;QAC5D,IAAI,CAAC,SAAS,CAAC,CAAA,EAAG,MAAM,CAAC,QAAQ,EAAE,CAAA,SAAA,CAAW,CAAC;QAC/C,IAAI,CAAC,KAAK,EAAE;AAEZ,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;IAC1B;;AAGA,IAAA,aAAa,CAAC,KAAY,EAAA;AACxB,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAA0B;AAC/C,QAAA,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK;AACzB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;;AAG5B,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE;AACvC,QAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;AACvB,YAAA,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC/B;aAAO;YACL,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChC;IACF;;IAGA,QAAQ,GAAA;QACN,IAAI,CAAC,KAAK,EAAE;AACZ,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;IACpB;;IAGA,SAAS,GAAA;AACP,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;;AAEnB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;IACzB;;IAGA,gBAAgB,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,YAAY,EAAE;IAC5B;;AAGA,IAAA,cAAc,CAAC,KAAoB,EAAA;QACjC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AAErB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE;QAE/B,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC;QAClC;aAAO;AACL,YAAA,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;QAChC;IACF;;AAGQ,IAAA,oBAAoB,CAAC,KAAoB,EAAA;AAC/C,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG;QAErB,QAAQ,GAAG;AACT,YAAA,KAAK,OAAO;AACZ,YAAA,KAAK,GAAG;AACR,YAAA,KAAK,WAAW;AAChB,YAAA,KAAK,SAAS;gBACZ,KAAK,CAAC,cAAc,EAAE;gBACtB,IAAI,CAAC,IAAI,EAAE;gBACX;;IAEN;;AAGA,IAAA,mBAAmB,CAAC,KAAoB,EAAA;QACtC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AAErB,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG;AACrB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;AACnC,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE;QAE5C,QAAQ,GAAG;AACT,YAAA,KAAK,WAAW;gBACd,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;gBAC5B;AACF,YAAA,KAAK,SAAS;gBACZ,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;gBAC7B;AACF,YAAA,KAAK,MAAM;gBACT,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;AACnB,oBAAA,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;gBAC/B;gBACA;AACF,YAAA,KAAK,KAAK;gBACR,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;oBACnB,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC7C;gBACA;AACF,YAAA,KAAK,UAAU;gBACb,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;AACnB,oBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC;AAC1C,oBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,QAAQ,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;AAClE,oBAAA,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC;gBACtC;gBACA;AACF,YAAA,KAAK,QAAQ;gBACX,KAAK,CAAC,cAAc,EAAE;AACtB,gBAAA,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;AACnB,oBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC;AAC1C,oBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,QAAQ,EAAE,CAAC,CAAC;AACpD,oBAAA,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC;gBACtC;gBACA;AACF,YAAA,KAAK,OAAO;gBACV,KAAK,CAAC,cAAc,EAAE;gBACtB,IAAI,WAAW,IAAI,CAAC,IAAI,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE;oBACjD,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC3C;gBACA;AACF,YAAA,KAAK,QAAQ;gBACX,KAAK,CAAC,cAAc,EAAE;gBACtB,IAAI,CAAC,KAAK,EAAE;gBACZ;AACF,YAAA,KAAK,KAAK;;gBAER,IAAI,CAAC,KAAK,EAAE;gBACZ;;IAEN;;AAGQ,IAAA,kBAAkB,CAAC,KAAoB,EAAA;;AAE7C,QAAA,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC;IACjC;;AAGQ,IAAA,oBAAoB,CAAC,KAAa,EAAA;AACxC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;AACnC,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE;AAEvB,QAAA,IAAI,YAAY,GAAG,IAAI,CAAC,iBAAiB,EAAE;AAC3C,QAAA,IAAI,YAAY,GAAG,CAAC,EAAE;AACpB,YAAA,YAAY,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM;QAC7C;AAEA,QAAA,IAAI,QAAQ,GAAG,YAAY,GAAG,KAAK;;AAGnC,QAAA,IAAI,QAAQ,GAAG,CAAC,EAAE;AAChB,YAAA,QAAQ,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC;QAC5B;AAAO,aAAA,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE;YAClC,QAAQ,GAAG,CAAC;QACd;AAEA,QAAA,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC;IACtC;;AAGQ,IAAA,qBAAqB,CAAC,KAAa,EAAA;AACzC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;QACnC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM;YAAE;;AAGvC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;AAC9B,QAAA,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;YACtB,GAAG,CAAC,WAAW,EAAE;AACnB,QAAA,CAAC,CAAC;AAEF,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC;QAChC,YAAY,CAAC,SAAS,EAAE;AACxB,QAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC;QACjC,IAAI,CAAC,qBAAqB,EAAE;AAC5B,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAA,EAAA,EAAK,KAAK,GAAG,CAAC,CAAA,IAAA,EAAO,IAAI,CAAC,MAAM,CAAA,CAAE,CAAC;IAC9E;;IAGQ,uBAAuB,GAAA;AAC7B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;AACnC,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;YACrB,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC9B;QACF;AAEA,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE;AAClC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE;;AAGpC,QAAA,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,SAAS,EAAE;YACvD,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,YAAY,CAAC,CAAC;QAC/E;AAEA,QAAA,MAAM,YAAY,GAAG,aAAa,IAAI,CAAC,GAAG,aAAa,GAAG,CAAC;AAC3D,QAAA,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC;IAC1C;;IAGQ,qBAAqB,GAAA;AAC3B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;AACnC,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE;QAE5C,IAAI,WAAW,GAAG,CAAC,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM;YAAE;AAEnD,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC;AACtC,QAAA,MAAM,OAAO,GAAG,YAAY,CAAC,eAAe,EAAE;AAC9C,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,EAAE,aAAa;AAE9C,QAAA,IAAI,OAAO,IAAI,YAAY,EAAE;YAC3B,MAAM,gBAAgB,GAAG,YAAY,CAAC,aAAa,CAAC,4BAA4B,CAAC;YACjF,IAAI,gBAAgB,EAAE;gBACpB,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,GAAI,gBAAgC,CAAC,SAAS;AACjF,gBAAA,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC,YAAY;AACrD,gBAAA,MAAM,YAAY,GAAG,gBAAgB,CAAC,SAAS;AAC/C,gBAAA,MAAM,eAAe,GAAG,YAAY,GAAG,gBAAgB,CAAC,YAAY;AAEpE,gBAAA,IAAI,SAAS,GAAG,YAAY,EAAE;AAC5B,oBAAA,gBAAgB,CAAC,SAAS,GAAG,SAAS;gBACxC;AAAO,qBAAA,IAAI,YAAY,GAAG,eAAe,EAAE;oBACzC,gBAAgB,CAAC,SAAS,GAAG,YAAY,GAAG,gBAAgB,CAAC,YAAY;gBAC3E;YACF;QACF;IACF;;IAGQ,uBAAuB,GAAA;AAC7B,QAAA,IAAI,CAAC,gBAAgB,EAAE,WAAW,EAAE;AAEpC,QAAA,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,MAAK;YAClC,UAAU,CAAC,MAAK;gBACd,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAa,IAAI,CAAC,SAAS,EAAE,OAAO;AAClE,qBAAA,IAAI,CACH,MAAM,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,EAC9B,MAAM,CAAC,CAAC,KAAK,KAAI;AACf,oBAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB;AAC1C,oBAAA,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,aAAa;AAClD,oBAAA,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,EAAE,aAAa;AAC9C,oBAAA,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc;AACvD,oBAAA,QACE,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC;AACjC,wBAAA,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC;AAC/B,wBAAA,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC;AAErC,gBAAA,CAAC,CAAC;qBAEH,SAAS,CAAC,MAAK;AACd,oBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAK;wBACpB,IAAI,CAAC,KAAK,EAAE;AACd,oBAAA,CAAC,CAAC;AACJ,gBAAA,CAAC,CAAC;AACN,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;IACJ;;IAGQ,cAAc,GAAA;AACpB,QAAA,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE;AAEtD,QAAA,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa;QACjD,MAAM,YAAY,GAAG,cAAc,CAAC,qBAAqB,EAAE,CAAC,KAAK;AAEjE,QAAA,MAAM,SAAS,GAA2B;AACxC,YAAA;AACE,gBAAA,OAAO,EAAE,OAAO;AAChB,gBAAA,OAAO,EAAE,QAAQ;AACjB,gBAAA,QAAQ,EAAE,OAAO;AACjB,gBAAA,QAAQ,EAAE,KAAK;AACf,gBAAA,OAAO,EAAE,CAAC;AACX,aAAA;AACD,YAAA;AACE,gBAAA,OAAO,EAAE,OAAO;AAChB,gBAAA,OAAO,EAAE,KAAK;AACd,gBAAA,QAAQ,EAAE,OAAO;AACjB,gBAAA,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE,CAAC,CAAC;AACZ,aAAA;SACF;AAED,QAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC3B,aAAA,QAAQ;AACR,aAAA,WAAW,CAAC,cAAc,EAAE,SAAS;aACrC,QAAQ,CAAC,IAAI;aACb,kBAAkB,CAAC,CAAC,CAAC;QAExB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;YAC7C,gBAAgB;YAChB,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,UAAU,EAAE;AAClE,YAAA,WAAW,EAAE,IAAI;AACjB,YAAA,aAAa,EAAE,2BAA2B;AAC1C,YAAA,qBAAqB,EAAE,OAAO;YAC9B,UAAU,EAAE,CAAC,gCAAgC,CAAC;AAC9C,YAAA,QAAQ,EAAE,YAAY;AACvB,SAAA,CAAC;;AAGF,QAAA,IAAI,CAAC,qBAAqB,CAAC,WAAW,EAAE;AACxC,QAAA,IAAI,CAAC,qBAAqB,GAAG,IAAI,YAAY,EAAE;AAE/C,QAAA,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAC5B,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,MAAK;YAC5C,IAAI,CAAC,KAAK,EAAE;QACd,CAAC,CAAC,CACH;AAED,QAAA,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAC5B,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,KAAI;AACjD,YAAA,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE;gBAC1B,IAAI,CAAC,KAAK,EAAE;YACd;QACF,CAAC,CAAC,CACH;;AAGD,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa;AAC7C,QAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC;IACvC;;IAGQ,eAAe,GAAA;AACrB,QAAA,IAAI,CAAC,qBAAqB,CAAC,WAAW,EAAE;AACxC,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE;AACpB,YAAA,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;AAC1B,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;QACzB;IACF;;IAGA,oBAAoB,GAAA;AAClB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE;AACnC,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE;QAC5C,IAAI,WAAW,IAAI,CAAC,IAAI,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE;AACjD,YAAA,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE;QAC7B;AACA,QAAA,OAAO,IAAI;IACb;;IAGA,eAAe,CAAC,KAAa,EAAE,MAA0B,EAAA;AACvD,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;AAC9B,QAAA,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;YACtB,GAAG,CAAC,WAAW,EAAE;AACnB,QAAA,CAAC,CAAC;QACF,MAAM,CAAC,SAAS,EAAE;AAClB,QAAA,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC;IACnC;;AAGA,IAAA,IAAI,QAAQ,GAAA;QACV,OAAO,IAAI,CAAC,KAAK;IACnB;uGAxsBW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAxB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,wBAAwB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,EAAA,gBAAA,EAAA,EAAA,iBAAA,EAAA,kBAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,MAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,SAAA,EAAA,IAAA,EAAA,8BAAA,EAAA,aAAA,EAAA,kCAAA,EAAA,YAAA,EAAA,iCAAA,EAAA,WAAA,EAAA,+BAAA,EAAA,cAAA,EAAA,kCAAA,EAAA,aAAA,EAAA,EAAA,cAAA,EAAA,kBAAA,EAAA,EAAA,SAAA,EAhBxB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,iBAAiB;AAC1B,gBAAA,WAAW,EAAE,wBAAwB;AACrC,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACD,YAAA;AACE,gBAAA,OAAO,EAAE,sBAAsB;AAC/B,gBAAA,WAAW,EAAE,wBAAwB;AACtC,aAAA;AACD,YAAA;AACE,gBAAA,OAAO,EAAE,gBAAgB;AACzB,gBAAA,WAAW,EAAE,wBAAwB;AACtC,aAAA;SACF,EAAA,OAAA,EAAA,CAAA,EAAA,YAAA,EAAA,SAAA,EAAA,SAAA,EAiGkC,kBAAkB,kVC5PvD,wwLA0JA,EAAA,MAAA,EAAA,CAAA,kmRAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,ED3BY,gBAAgB,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,QAAA,EAAA,OAAA,EAAA,WAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,mBAAmB,+BAAE,kBAAkB,EAAA,QAAA,EAAA,iCAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,WAAA,EAAA,SAAA,EAAA,UAAA,EAAA,YAAA,EAAA,MAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FA8BxD,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBAjCpC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,kBAAkB,cAChB,IAAI,EAAA,OAAA,EACP,CAAC,gBAAgB,EAAE,mBAAmB,EAAE,kBAAkB,CAAC,EAAA,eAAA,EAGnD,uBAAuB,CAAC,MAAM,iBAChC,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,KAAK,EAAE,kBAAkB;AACzB,wBAAA,WAAW,EAAE,IAAI;AACjB,wBAAA,gCAAgC,EAAE,aAAa;AAC/C,wBAAA,oCAAoC,EAAE,YAAY;AAClD,wBAAA,mCAAmC,EAAE,WAAW;AAChD,wBAAA,iCAAiC,EAAE,cAAc;AACjD,wBAAA,oCAAoC,EAAE,aAAa;qBACpD,EAAA,SAAA,EACU;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,iBAAiB;AAC1B,4BAAA,WAAW,EAAA,wBAA0B;AACrC,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACD,wBAAA;AACE,4BAAA,OAAO,EAAE,sBAAsB;AAC/B,4BAAA,WAAW,EAAA,wBAA0B;AACtC,yBAAA;AACD,wBAAA;AACE,4BAAA,OAAO,EAAE,gBAAgB;AACzB,4BAAA,WAAW,EAAA,wBAA0B;AACtC,yBAAA;AACF,qBAAA,EAAA,QAAA,EAAA,wwLAAA,EAAA,MAAA,EAAA,CAAA,kmRAAA,CAAA,EAAA;;sBA2FA,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,SAAS,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;;sBACtC,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;;sBACpC,SAAS;AAAC,gBAAA,IAAA,EAAA,CAAA,aAAa,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;AAIR,aAAA,CAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,UAAA,CAAA,MAAA,kBAAkB,CAAA,EAAA,EAAA,GAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AE5P9E;;AAEG;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raintonic-formaui-components-avatar.mjs","sources":["../../../lib/components/avatar/avatar.component.ts","../../../lib/components/avatar/avatar.component.html","../../../lib/components/avatar/raintonic-formaui-components-avatar.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input, Signal, signal } from '@angular/core';\n\nexport type FuiAvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\n/**\n * @component FuiAvatarComponent\n * @selector fui-avatar\n * @description Displays a user avatar with image, initials fallback, and configurable shape/size.\n * Automatically computes initials from name fields and generates a background color from an identity key.\n *\n * @input size - Avatar size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' or a numeric pixel value. Default 'md'.\n * @input shape - Avatar shape: 'circle' | 'rounded' | 'square'. Default 'circle'.\n * @input src - Image URL or data URI for the avatar.\n * @input avatarUrl - Backward-compatible alias for src.\n * @input srcSet - HTML srcset attribute for responsive images.\n * @input sizesAttr - HTML sizes attribute for responsive images.\n * @input name - First name used to compute initials.\n * @input surname - Last name used to compute initials.\n * @input fullName - Full name (overrides name + surname for initials).\n * @input alt - Alt text for the image element.\n * @input identityKey - Key (e.g. email) used to deterministically pick a background color.\n *\n * @example\n * <fui-avatar [src]=\"user.photoUrl\" [fullName]=\"user.displayName\" size=\"lg\"></fui-avatar>\n */\n@Component({\n selector: 'fui-avatar',\n standalone: true,\n imports: [],\n templateUrl: './avatar.component.html',\n styleUrls: ['./avatar.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FuiAvatarComponent {\n // Inputs (signals)\n readonly size = input<FuiAvatarSize | number>('md');\n readonly shape = input<'circle' | 'rounded' | 'square'>('circle');\n readonly src = input<string | null>(null); // URL or data URI\n // Backward compatibility with previous API\n readonly avatarUrl = input<string | null>(null);\n readonly srcSet = input<string | null>(null);\n readonly sizesAttr = input<string | null>(null);\n readonly name = input<string | null>(null);\n readonly surname = input<string | null>(null);\n readonly fullName = input<string | null>(null);\n readonly alt = input<string | null>(null);\n readonly identityKey = input<string | null>(null); // e.g., email for color hashing\n\n // Local state\n private readonly imageFailed = signal(false);\n\n // Derived values\n readonly normalizedName: Signal<string> = computed(() => {\n const fn = (this.fullName() ?? `${this.name() ?? ''} ${this.surname() ?? ''}`).trim();\n return fn.replace(/\\s+/g, ' ');\n });\n\n readonly initials: Signal<string> = computed(() => {\n const parts = this.normalizedName().split(' ').filter(Boolean);\n if (parts.length === 0) return '?';\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n });\n\n readonly pixelSize: Signal<number> = computed(() => {\n const s = this.size();\n if (typeof s === 'number') return s;\n return { xs: 16, sm: 24, md: 32, lg: 40, xl: 48 }[s] ?? 32;\n });\n\n readonly displayImage: Signal<string | null> = computed(() => {\n if (this.imageFailed()) return null;\n return this.src() ?? this.avatarUrl();\n });\n\n readonly bgColor: Signal<string> = computed(() => {\n const key = this.identityKey() ?? this.normalizedName() ?? this.initials();\n const palette = ['var(--fui-primary)'];\n let h = 0;\n for (let i = 0; i < key.length; i++) h = ((h << 5) - h + key.charCodeAt(i)) | 0;\n return palette[Math.abs(h) % palette.length];\n });\n\n readonly ariaLabel: Signal<string> = computed(() => {\n return this.alt() ?? (this.normalizedName() ? `Avatar for ${this.normalizedName()}` : 'User avatar');\n });\n\n onImgError(): void {\n this.imageFailed.set(true);\n }\n}\n","<div\r\n class=\"fui-avatar\"\r\n [style.--fui-avatar-size.px]=\"pixelSize()\"\r\n [class.fui-avatar--rounded]=\"shape() === 'rounded'\"\r\n [class.fui-avatar--square]=\"shape() === 'square'\"\r\n>\r\n @if (displayImage(); as img) {\r\n <img\r\n class=\"fui-avatar__img\"\r\n [src]=\"img\"\r\n [srcset]=\"srcSet() || null\"\r\n [sizes]=\"sizesAttr() || null\"\r\n [attr.alt]=\"ariaLabel()\"\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n referrerpolicy=\"no-referrer\"\r\n (error)=\"onImgError()\"\r\n />\r\n } @else {\r\n <div class=\"fui-avatar__initials\" role=\"img\" [attr.aria-label]=\"ariaLabel()\" [style.background-color]=\"bgColor()\">\r\n {{ initials() }}\r\n </div>\r\n }\r\n\r\n <ng-content select=\"[avatar-badge]\"></ng-content>\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"raintonic-formaui-components-avatar.mjs","sources":["../../../lib/components/avatar/avatar.component.ts","../../../lib/components/avatar/avatar.component.html","../../../lib/components/avatar/raintonic-formaui-components-avatar.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input, Signal, signal } from '@angular/core';\r\n\r\nexport type FuiAvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\r\n\r\n/**\r\n * @component FuiAvatarComponent\r\n * @selector fui-avatar\r\n * @description Displays a user avatar with image, initials fallback, and configurable shape/size.\r\n * Automatically computes initials from name fields and generates a background color from an identity key.\r\n *\r\n * @input size - Avatar size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' or a numeric pixel value. Default 'md'.\r\n * @input shape - Avatar shape: 'circle' | 'rounded' | 'square'. Default 'circle'.\r\n * @input src - Image URL or data URI for the avatar.\r\n * @input avatarUrl - Backward-compatible alias for src.\r\n * @input srcSet - HTML srcset attribute for responsive images.\r\n * @input sizesAttr - HTML sizes attribute for responsive images.\r\n * @input name - First name used to compute initials.\r\n * @input surname - Last name used to compute initials.\r\n * @input fullName - Full name (overrides name + surname for initials).\r\n * @input alt - Alt text for the image element.\r\n * @input identityKey - Key (e.g. email) used to deterministically pick a background color.\r\n *\r\n * @example\r\n * <fui-avatar [src]=\"user.photoUrl\" [fullName]=\"user.displayName\" size=\"lg\"></fui-avatar>\r\n */\r\n@Component({\r\n selector: 'fui-avatar',\r\n standalone: true,\r\n imports: [],\r\n templateUrl: './avatar.component.html',\r\n styleUrls: ['./avatar.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class FuiAvatarComponent {\r\n // Inputs (signals)\r\n readonly size = input<FuiAvatarSize | number>('md');\r\n readonly shape = input<'circle' | 'rounded' | 'square'>('circle');\r\n readonly src = input<string | null>(null); // URL or data URI\r\n // Backward compatibility with previous API\r\n readonly avatarUrl = input<string | null>(null);\r\n readonly srcSet = input<string | null>(null);\r\n readonly sizesAttr = input<string | null>(null);\r\n readonly name = input<string | null>(null);\r\n readonly surname = input<string | null>(null);\r\n readonly fullName = input<string | null>(null);\r\n readonly alt = input<string | null>(null);\r\n readonly identityKey = input<string | null>(null); // e.g., email for color hashing\r\n\r\n // Local state\r\n private readonly imageFailed = signal(false);\r\n\r\n // Derived values\r\n readonly normalizedName: Signal<string> = computed(() => {\r\n const fn = (this.fullName() ?? `${this.name() ?? ''} ${this.surname() ?? ''}`).trim();\r\n return fn.replace(/\\s+/g, ' ');\r\n });\r\n\r\n readonly initials: Signal<string> = computed(() => {\r\n const parts = this.normalizedName().split(' ').filter(Boolean);\r\n if (parts.length === 0) return '?';\r\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\r\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\r\n });\r\n\r\n readonly pixelSize: Signal<number> = computed(() => {\r\n const s = this.size();\r\n if (typeof s === 'number') return s;\r\n return { xs: 16, sm: 24, md: 32, lg: 40, xl: 48 }[s] ?? 32;\r\n });\r\n\r\n readonly displayImage: Signal<string | null> = computed(() => {\r\n if (this.imageFailed()) return null;\r\n return this.src() ?? this.avatarUrl();\r\n });\r\n\r\n readonly bgColor: Signal<string> = computed(() => {\r\n const key = this.identityKey() ?? this.normalizedName() ?? this.initials();\r\n const palette = ['var(--fui-primary)'];\r\n let h = 0;\r\n for (let i = 0; i < key.length; i++) h = ((h << 5) - h + key.charCodeAt(i)) | 0;\r\n return palette[Math.abs(h) % palette.length];\r\n });\r\n\r\n readonly ariaLabel: Signal<string> = computed(() => {\r\n return this.alt() ?? (this.normalizedName() ? `Avatar for ${this.normalizedName()}` : 'User avatar');\r\n });\r\n\r\n onImgError(): void {\r\n this.imageFailed.set(true);\r\n }\r\n}\r\n","<div\r\n class=\"fui-avatar\"\r\n [style.--fui-avatar-size.px]=\"pixelSize()\"\r\n [class.fui-avatar--rounded]=\"shape() === 'rounded'\"\r\n [class.fui-avatar--square]=\"shape() === 'square'\"\r\n>\r\n @if (displayImage(); as img) {\r\n <img\r\n class=\"fui-avatar__img\"\r\n [src]=\"img\"\r\n [srcset]=\"srcSet() || null\"\r\n [sizes]=\"sizesAttr() || null\"\r\n [attr.alt]=\"ariaLabel()\"\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n referrerpolicy=\"no-referrer\"\r\n (error)=\"onImgError()\"\r\n />\r\n } @else {\r\n <div class=\"fui-avatar__initials\" role=\"img\" [attr.aria-label]=\"ariaLabel()\" [style.background-color]=\"bgColor()\">\r\n {{ initials() }}\r\n </div>\r\n }\r\n\r\n <ng-content select=\"[avatar-badge]\"></ng-content>\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|