@i-cell/ids-angular 0.2.22 → 0.2.24

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.
@@ -1,19 +1,18 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, InjectionToken, inject, input, computed, ChangeDetectionStrategy, ViewEncapsulation, Component, ElementRef, viewChild, signal, output, effect, Directive, Injector, booleanAttribute, Input, contentChildren, ChangeDetectorRef, contentChild, isDevMode, viewChildren, model, untracked, forwardRef } from '@angular/core';
3
- import { ComponentBase, coerceBooleanAttribute, ComponentBaseWithDefaults, IdsSize, coerceNumberAttribute } from '@i-cell/ids-angular/core';
2
+ import { Injectable, InjectionToken, inject, Injector, signal, input, effect, booleanAttribute, computed, Directive, Input, contentChildren, ChangeDetectionStrategy, ViewEncapsulation, Component, ElementRef, ChangeDetectorRef, viewChild, contentChild, output, model, untracked, forwardRef, Renderer2, afterNextRender, isDevMode } from '@angular/core';
3
+ import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
4
+ import { NgForm, FormGroupDirective, NgControl, Validators, NG_VALUE_ACCESSOR, StatusChangeEvent } from '@angular/forms';
5
+ import { ComponentBaseWithDefaults, IdsSize, ComponentBase, coerceBooleanAttribute, coerceNumberAttribute } from '@i-cell/ids-angular/core';
6
+ import { Subject, observeOn, asapScheduler, tap, switchMap, of, startWith } from 'rxjs';
4
7
  import { IdsIconComponent } from '@i-cell/ids-angular/icon';
5
8
  import { hasModifierKey } from '@angular/cdk/keycodes';
6
- import { takeUntilDestroyed, toObservable, rxResource } from '@angular/core/rxjs-interop';
7
- import * as i1 from '@angular/forms';
8
- import { NgForm, FormGroupDirective, NgControl, Validators, StatusChangeEvent, ValueChangeEvent, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
9
- import { Subject, observeOn, asapScheduler, tap, switchMap, of, startWith, filter } from 'rxjs';
10
- import { LiveAnnouncer, ActiveDescendantKeyManager } from '@angular/cdk/a11y';
11
- import { SelectionModel } from '@angular/cdk/collections';
12
- import { CdkOverlayOrigin } from '@angular/cdk/overlay';
13
- import { IdsIconButtonComponent } from '@i-cell/ids-angular/icon-button';
9
+ import { IdsIconButtonAppearance, IdsIconButtonComponent } from '@i-cell/ids-angular/icon-button';
14
10
  import { IdsOverlayPanelComponent } from '@i-cell/ids-angular/overlay-panel';
15
- import { IdsSpinnerComponent } from '@i-cell/ids-angular/spinner';
11
+ import { IdsSpinnerVariant, IdsSpinnerComponent } from '@i-cell/ids-angular/spinner';
16
12
  import { IdsTooltipDirective } from '@i-cell/ids-angular/tooltip';
13
+ import { LiveAnnouncer, ActiveDescendantKeyManager } from '@angular/cdk/a11y';
14
+ import { SelectionModel } from '@angular/cdk/collections';
15
+ import { IdsChipAppearance, IdsChipVariant, IdsChipComponent } from '@i-cell/ids-angular/chip';
17
16
 
18
17
  class AbstractErrorStateMatcher {
19
18
  }
@@ -95,223 +94,11 @@ const IDS_AUTOCOMPLETE_DEFAULT_CONFIG = new InjectionToken('IDS_AUTOCOMPLETE_DEF
95
94
  });
96
95
  function IDS_AUTOCOMPLETE_DEFAULT_CONFIG_FACTORY() {
97
96
  return {
98
- minChars: 1,
99
- hintLoading: 'Loading...',
100
- hintNoResults: 'No results found',
101
- hintMinChars: 'Please provide at least 1 characters',
102
- hintMaxLength: 'Too many results, please refine your search',
103
- typeaheadDebounceInterval: 300,
97
+ errorStateMatcher: ErrorStateMatcher,
98
+ successStateMatcher: SuccessStateMatcher,
104
99
  };
105
100
  }
106
101
 
107
- const IDS_AUTOCOMPLETE_LOADER = new InjectionToken('IDS_AUTOCOMPLETE_LOADER');
108
-
109
- const IDS_OPTION_GROUP = new InjectionToken('IdsOptionGroup');
110
-
111
- const IDS_OPTION_PARENT_COMPONENT = new InjectionToken('IDS_OPTION_PARENT_COMPONENT');
112
-
113
- class IdsOptionSelectionChange {
114
- constructor(source, selected, isUserInput = false) {
115
- this.source = source;
116
- this.selected = selected;
117
- this.isUserInput = isUserInput;
118
- }
119
- }
120
-
121
- const IdsFormFieldVariant = {
122
- SURFACE: 'surface',
123
- LIGHT: 'light',
124
- };
125
-
126
- const IDS_PSEUDO_CHECKBOX_PARENT = new InjectionToken('IDS_PSEUDO_CHECKBOX_PARENT');
127
-
128
- const IdsPseudoCheckboxState = {
129
- UNCHECKED: 'unchecked',
130
- CHECKED: 'checked',
131
- INDETERMINATE: 'indeterminate',
132
- };
133
-
134
- class PseudoCheckboxComponent extends ComponentBase {
135
- constructor() {
136
- super(...arguments);
137
- this._parent = inject(IDS_PSEUDO_CHECKBOX_PARENT, { optional: true });
138
- this.checkboxState = input(IdsPseudoCheckboxState.UNCHECKED, ...(ngDevMode ? [{ debugName: "checkboxState" }] : []));
139
- this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: coerceBooleanAttribute }] : [{ transform: coerceBooleanAttribute }]));
140
- this._isChecked = computed(() => this.checkboxState() === IdsPseudoCheckboxState.CHECKED, ...(ngDevMode ? [{ debugName: "_isChecked" }] : []));
141
- this._isIndeterminate = computed(() => this.checkboxState() === IdsPseudoCheckboxState.INDETERMINATE, ...(ngDevMode ? [{ debugName: "_isIndeterminate" }] : []));
142
- this._hostClasses = computed(() => this._getHostClasses([
143
- this._parent?.embeddedPseudoCheckboxSize(),
144
- this._parent?.embeddedPseudoCheckboxVariant(),
145
- this.disabled() ? 'disabled' : null,
146
- ]), ...(ngDevMode ? [{ debugName: "_hostClasses" }] : []));
147
- }
148
- get _hostName() {
149
- return 'pseudo-checkbox';
150
- }
151
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PseudoCheckboxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
152
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: PseudoCheckboxComponent, isStandalone: true, selector: "ids-pseudo-checkbox", inputs: { checkboxState: { classPropertyName: "checkboxState", publicName: "checkboxState", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div class=\"ids-pseudo-checkbox__input-wrapper\">\n <input\n type=\"checkbox\"\n [disabled]=\"disabled()\"\n [attr.aria-checked]=\"_isIndeterminate() ? 'mixed' : null\"\n [checked]=\"_isChecked()\"\n [indeterminate]=\"_isIndeterminate()\"\n (change)=\"$event.stopPropagation()\"\n />\n <div class=\"ids-pseudo-checkbox__icon\" aria-hidden=\"true\">\n @if (_isIndeterminate()) {\n <ids-icon fontIcon=\"remove\" aria-hidden=\"true\" />\n }\n @if (_isChecked()) {\n <ids-icon fontIcon=\"done\" aria-hidden=\"true\" />\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: IdsIconComponent, selector: "ids-icon", inputs: ["size", "sizeCollection", "variant", "fontIcon", "svgIcon", "aria-hidden"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
153
- }
154
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PseudoCheckboxComponent, decorators: [{
155
- type: Component,
156
- args: [{ selector: 'ids-pseudo-checkbox', imports: [IdsIconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ids-pseudo-checkbox__input-wrapper\">\n <input\n type=\"checkbox\"\n [disabled]=\"disabled()\"\n [attr.aria-checked]=\"_isIndeterminate() ? 'mixed' : null\"\n [checked]=\"_isChecked()\"\n [indeterminate]=\"_isIndeterminate()\"\n (change)=\"$event.stopPropagation()\"\n />\n <div class=\"ids-pseudo-checkbox__icon\" aria-hidden=\"true\">\n @if (_isIndeterminate()) {\n <ids-icon fontIcon=\"remove\" aria-hidden=\"true\" />\n }\n @if (_isChecked()) {\n <ids-icon fontIcon=\"done\" aria-hidden=\"true\" />\n }\n </div>\n</div>\n" }]
157
- }] });
158
-
159
- class IdsOptionComponent extends ComponentBase {
160
- get _hostName() {
161
- return 'option';
162
- }
163
- constructor() {
164
- super();
165
- this._parent = inject(IDS_OPTION_PARENT_COMPONENT);
166
- this._element = inject(ElementRef);
167
- this.group = inject(IDS_OPTION_GROUP, { optional: true });
168
- this._textElement = viewChild.required('text');
169
- this.selected = signal(false, ...(ngDevMode ? [{ debugName: "selected" }] : []));
170
- this._active = signal(false, ...(ngDevMode ? [{ debugName: "_active" }] : []));
171
- this.size = computed(() => this._parent.parentSize(), ...(ngDevMode ? [{ debugName: "size" }] : []));
172
- this.variant = computed(() => this._parent.parentVariant(), ...(ngDevMode ? [{ debugName: "variant" }] : []));
173
- this.value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
174
- this.explicitViewValue = input(null, ...(ngDevMode ? [{ debugName: "explicitViewValue", alias: 'viewValue' }] : [{ alias: 'viewValue' }]));
175
- this.disabledInput = input(false, ...(ngDevMode ? [{ debugName: "disabledInput", alias: 'disabled', transform: coerceBooleanAttribute }] : [{ alias: 'disabled', transform: coerceBooleanAttribute }]));
176
- this.disabled = false; // Do not delete this class member, until ListKeyManagerOption requires: `disabled: boolean`
177
- this._groupOrOptionIsDisabled = computed(() => this.group?.disabled() || this.disabledInput(), ...(ngDevMode ? [{ debugName: "_groupOrOptionIsDisabled" }] : []));
178
- this._multiSelect = Boolean(this._parent?.multiSelect());
179
- // eslint-disable-next-line @angular-eslint/no-output-on-prefix
180
- this.onSelectionChange = output();
181
- this.viewValue = computed(() => this.explicitViewValue() || this._textElement().nativeElement.textContent || '', ...(ngDevMode ? [{ debugName: "viewValue" }] : []));
182
- this._hostClasses = computed(() => this._getHostClasses([
183
- this.selected() ? 'selected' : null,
184
- this._active() ? 'active' : null,
185
- this._groupOrOptionIsDisabled() ? 'disabled' : null,
186
- this._multiSelect ? 'multiselect' : null,
187
- this.size(),
188
- this.variant(),
189
- ]), ...(ngDevMode ? [{ debugName: "_hostClasses" }] : []));
190
- this._pseudoCheckboxState = computed(() => (this.selected() ? IdsPseudoCheckboxState.CHECKED : IdsPseudoCheckboxState.UNCHECKED), ...(ngDevMode ? [{ debugName: "_pseudoCheckboxState" }] : []));
191
- this.embeddedPseudoCheckboxSize = computed(() => this.size(), ...(ngDevMode ? [{ debugName: "embeddedPseudoCheckboxSize" }] : []));
192
- this.embeddedPseudoCheckboxVariant = signal(IdsFormFieldVariant.SURFACE, ...(ngDevMode ? [{ debugName: "embeddedPseudoCheckboxVariant" }] : []));
193
- effect(() => {
194
- this.disabled = this.disabledInput();
195
- });
196
- }
197
- ngOnInit() {
198
- const parent = this._parent;
199
- if (parent.isOptionPreSelectedByValue(this.value())) {
200
- this.selected.set(true);
201
- }
202
- }
203
- _handleKeydown(event) {
204
- if ((event.key === 'ENTER' || event.key === ' ') && !hasModifierKey(event)) {
205
- this.selectViaInteraction();
206
- event.preventDefault();
207
- }
208
- }
209
- selectViaInteraction() {
210
- if (!this._groupOrOptionIsDisabled()) {
211
- this._emitSelectionChangeEvent(!this.selected(), true);
212
- }
213
- }
214
- getHostElement() {
215
- return this._element.nativeElement;
216
- }
217
- select(emitEvent = true) {
218
- if (!this.selected()) {
219
- if (emitEvent) {
220
- this._emitSelectionChangeEvent(true);
221
- }
222
- }
223
- }
224
- deselect(emitEvent = true) {
225
- if (this.selected()) {
226
- if (emitEvent) {
227
- this._emitSelectionChangeEvent(false);
228
- }
229
- }
230
- }
231
- focus(_origin, options) {
232
- const element = this._element.nativeElement;
233
- if (typeof element.focus === 'function') {
234
- element.focus(options);
235
- }
236
- }
237
- setActiveStyles() {
238
- if (!this._active()) {
239
- this._active.set(true);
240
- }
241
- }
242
- setInactiveStyles() {
243
- if (this._active()) {
244
- this._active.set(false);
245
- }
246
- }
247
- getLabel() {
248
- return this.viewValue();
249
- }
250
- _emitSelectionChangeEvent(selected, isUserInput = false) {
251
- if (this._multiSelect || !this.selected()) {
252
- this.onSelectionChange.emit(new IdsOptionSelectionChange(this, selected, isUserInput));
253
- }
254
- }
255
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsOptionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
256
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: IdsOptionComponent, isStandalone: true, selector: "ids-option", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, explicitViewValue: { classPropertyName: "explicitViewValue", publicName: "viewValue", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelectionChange: "onSelectionChange" }, host: { attributes: { "role": "option" }, listeners: { "click": "selectViaInteraction()", "keydown": "_handleKeydown($event)" }, properties: { "attr.aria-selected": "selected()", "attr.aria-disabled": "disabled.toString()" } }, providers: [
257
- {
258
- provide: IDS_PSEUDO_CHECKBOX_PARENT,
259
- useExisting: IdsOptionComponent,
260
- },
261
- ], viewQueries: [{ propertyName: "_textElement", first: true, predicate: ["text"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (_multiSelect) {\n <ids-pseudo-checkbox aria-hidden=\"true\" [disabled]=\"_groupOrOptionIsDisabled()\" [checkboxState]=\"_pseudoCheckboxState()\" />\n}\n\n<div #text class=\"ids-option__text\"><ng-content /></div>\n\n@if (!_multiSelect && selected()) {\n <ids-icon fontIcon=\"done\" />\n}\n", dependencies: [{ kind: "component", type: IdsIconComponent, selector: "ids-icon", inputs: ["size", "sizeCollection", "variant", "fontIcon", "svgIcon", "aria-hidden"] }, { kind: "component", type: PseudoCheckboxComponent, selector: "ids-pseudo-checkbox", inputs: ["checkboxState", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
262
- }
263
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsOptionComponent, decorators: [{
264
- type: Component,
265
- args: [{ selector: 'ids-option', imports: [
266
- IdsIconComponent,
267
- PseudoCheckboxComponent,
268
- ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
269
- {
270
- provide: IDS_PSEUDO_CHECKBOX_PARENT,
271
- useExisting: IdsOptionComponent,
272
- },
273
- ], host: {
274
- 'role': 'option',
275
- '[attr.aria-selected]': 'selected()',
276
- '[attr.aria-disabled]': 'disabled.toString()',
277
- '(click)': 'selectViaInteraction()',
278
- '(keydown)': '_handleKeydown($event)',
279
- }, template: "@if (_multiSelect) {\n <ids-pseudo-checkbox aria-hidden=\"true\" [disabled]=\"_groupOrOptionIsDisabled()\" [checkboxState]=\"_pseudoCheckboxState()\" />\n}\n\n<div #text class=\"ids-option__text\"><ng-content /></div>\n\n@if (!_multiSelect && selected()) {\n <ids-icon fontIcon=\"done\" />\n}\n" }]
280
- }], ctorParameters: () => [] });
281
- function _countGroupLabelsBeforeOption(optionIndex, options, optionGroups) {
282
- if (optionGroups.length) {
283
- let groupCounter = 0;
284
- for (let i = 0; i < optionIndex + 1; i++) {
285
- if (options[i].group && options[i].group === optionGroups[groupCounter]) {
286
- groupCounter++;
287
- }
288
- }
289
- return groupCounter;
290
- }
291
- return 0;
292
- }
293
- function _getOptionScrollPosition(optionOffset, optionHeight, currentScrollPosition, panelHeight) {
294
- if (optionOffset < currentScrollPosition) {
295
- return optionOffset;
296
- }
297
- if (optionOffset + optionHeight > currentScrollPosition + panelHeight) {
298
- return Math.max(0, optionOffset - panelHeight + optionHeight);
299
- }
300
- return currentScrollPosition;
301
- }
302
-
303
- class IdsFormFieldActionDirective {
304
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsFormFieldActionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
305
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: IdsFormFieldActionDirective, isStandalone: true, selector: "[idsFormFieldAction]", ngImport: i0 }); }
306
- }
307
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsFormFieldActionDirective, decorators: [{
308
- type: Directive,
309
- args: [{
310
- selector: '[idsFormFieldAction]',
311
- standalone: true,
312
- }]
313
- }] });
314
-
315
102
  const formFieldControlClass = 'ids-form-field-control';
316
103
  class IdsFormFieldControl extends ComponentBaseWithDefaults {
317
104
  constructor() {
@@ -384,6 +171,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
384
171
  type: Directive
385
172
  }], ctorParameters: () => [] });
386
173
 
174
+ const IdsFormFieldVariant = {
175
+ SURFACE: 'surface',
176
+ LIGHT: 'light',
177
+ };
178
+
387
179
  const IDS_FORM_FIELD_DEFAULT_CONFIG = new InjectionToken('IDS_FORM_FIELD_DEFAULT_CONFIG', {
388
180
  providedIn: 'root',
389
181
  factory: IDS_FORM_FIELD_DEFAULT_CONFIG_FACTORY,
@@ -397,6 +189,18 @@ function IDS_FORM_FIELD_DEFAULT_CONFIG_FACTORY() {
397
189
 
398
190
  const IDS_FORM_FIELD_CONTROL = new InjectionToken('IDS_FORM_FIELD_CONTROL');
399
191
 
192
+ class IdsFormFieldActionDirective {
193
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsFormFieldActionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
194
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: IdsFormFieldActionDirective, isStandalone: true, selector: "[idsFormFieldAction]", ngImport: i0 }); }
195
+ }
196
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsFormFieldActionDirective, decorators: [{
197
+ type: Directive,
198
+ args: [{
199
+ selector: '[idsFormFieldAction]',
200
+ standalone: true,
201
+ }]
202
+ }] });
203
+
400
204
  class IdsPrefixDirective {
401
205
  constructor() {
402
206
  this.isLeadingIcon = false;
@@ -816,253 +620,265 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
816
620
  args: [{ selector: 'ids-form-field', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<label class=\"ids-form-field__label\" [for]=\"_inputId()\">\n @if (hasRequiredValidator()) {\n <span class=\"ids-form-field__required-marker\"></span>\n }\n <ng-content select=\"ids-label\" />\n</label>\n\n<div #fieldWrapper class=\"ids-form-field__field-wrapper\">\n <div class=\"ids-form-field__field-wrapper__container\" (click)=\"containerClick($event)\">\n @if (_hasLeadingIcon()) {\n <div class=\"ids-form-field__leading-icon\">\n <ng-content select=\"ids-icon[idsLeadingIcon]\" />\n </div>\n }\n @if (_hasPrefix()) {\n <div class=\"ids-form-field__prefix\">\n <ng-content select=\"[idsPrefix]\" />\n </div>\n }\n <div class=\"ids-form-field__infix\">\n <ng-content />\n </div>\n @if (_hasSuffix()) {\n <div class=\"ids-form-field__suffix\">\n <ng-content select=\"[idsSuffix]\" />\n </div>\n }\n @if (_hasTrailingIcon()) {\n <div class=\"ids-form-field__trailing-icon\">\n <ng-content select=\"ids-icon[idsTrailingIcon]\" />\n </div>\n }\n </div>\n @if (_hasActions()) {\n <div class=\"ids-form-field__field-wrapper__action\">\n <ng-content select=\"[idsFormFieldAction]\" />\n </div>\n }\n</div>\n\n<div class=\"ids-form-field__subscript-wrapper\">\n @let messages = _displayedMessages();\n @if (messages) {\n <div class=\"ids-form-field__message-container\">\n @switch (messages) {\n @case (\"error\") {\n <ng-content select=\"ids-error-message\" />\n }\n @case (\"success\") {\n <ng-content select=\"ids-success-message\" />\n }\n @case (\"hint\") {\n <ng-content select=\"ids-hint-message\" />\n }\n }\n </div>\n }\n</div>\n" }]
817
621
  }] });
818
622
 
819
- const IDS_INPUT_DEFAULT_CONFIG = new InjectionToken('IDS_INPUT_DEFAULT_CONFIG', {
820
- providedIn: 'root',
821
- factory: IDS_INPUT_DEFAULT_CONFIG_FACTORY,
822
- });
823
- function IDS_INPUT_DEFAULT_CONFIG_FACTORY() {
824
- return {
825
- errorStateMatcher: ErrorStateMatcher,
826
- successStateMatcher: SuccessStateMatcher,
827
- };
623
+ const IDS_OPTION_GROUP = new InjectionToken('IdsOptionGroup');
624
+
625
+ const IDS_OPTION_PARENT_COMPONENT = new InjectionToken('IDS_OPTION_PARENT_COMPONENT');
626
+
627
+ class IdsOptionSelectionChange {
628
+ constructor(source, selected, isUserInput = false) {
629
+ this.source = source;
630
+ this.selected = selected;
631
+ this.isUserInput = isUserInput;
632
+ }
828
633
  }
829
634
 
830
- const defaultConfig$1 = IDS_INPUT_DEFAULT_CONFIG_FACTORY();
831
- const IDS_INPUT_INVALID_TYPES = [
832
- 'button',
833
- 'checkbox',
834
- 'file',
835
- 'hidden',
836
- 'image',
837
- 'radio',
838
- 'range',
839
- 'reset',
840
- 'submit',
841
- ];
842
- class IdsInputDirective extends IdsFormFieldControl {
635
+ const IDS_PSEUDO_CHECKBOX_PARENT = new InjectionToken('IDS_PSEUDO_CHECKBOX_PARENT');
636
+
637
+ const IdsPseudoCheckboxState = {
638
+ UNCHECKED: 'unchecked',
639
+ CHECKED: 'checked',
640
+ INDETERMINATE: 'indeterminate',
641
+ };
642
+
643
+ class PseudoCheckboxComponent extends ComponentBase {
843
644
  constructor() {
844
645
  super(...arguments);
845
- this._elementRef = inject(ElementRef);
846
- this._defaultConfig = this._getDefaultConfig(defaultConfig$1, IDS_INPUT_DEFAULT_CONFIG);
847
- this._focused = false;
848
- this.name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
849
- this.type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : []));
850
- this.errorStateMatcher = input(inject(this._defaultConfig.errorStateMatcher), ...(ngDevMode ? [{ debugName: "errorStateMatcher" }] : []));
851
- this.successStateMatcher = input(inject(this._defaultConfig.successStateMatcher), ...(ngDevMode ? [{ debugName: "successStateMatcher" }] : []));
852
- this._hostClasses = computed(() => this._getHostClasses([], [formFieldControlClass]), ...(ngDevMode ? [{ debugName: "_hostClasses" }] : []));
853
- this._validateTypeEffect = effect(() => {
854
- this._validateType(this.type());
855
- }, ...(ngDevMode ? [{ debugName: "_validateTypeEffect" }] : []));
856
- /**
857
- * Should be an arrow function in order to handle `this` outside of this class
858
- */
859
- this.onContainerClick = () => {
860
- if (!this._focused && !this.readonly() && !this.disabled) {
861
- this.focus();
862
- }
863
- };
646
+ this._parent = inject(IDS_PSEUDO_CHECKBOX_PARENT, { optional: true });
647
+ this.checkboxState = input(IdsPseudoCheckboxState.UNCHECKED, ...(ngDevMode ? [{ debugName: "checkboxState" }] : []));
648
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: coerceBooleanAttribute }] : [{ transform: coerceBooleanAttribute }]));
649
+ this._isChecked = computed(() => this.checkboxState() === IdsPseudoCheckboxState.CHECKED, ...(ngDevMode ? [{ debugName: "_isChecked" }] : []));
650
+ this._isIndeterminate = computed(() => this.checkboxState() === IdsPseudoCheckboxState.INDETERMINATE, ...(ngDevMode ? [{ debugName: "_isIndeterminate" }] : []));
651
+ this._hostClasses = computed(() => this._getHostClasses([
652
+ this._parent?.embeddedPseudoCheckboxSize(),
653
+ this._parent?.embeddedPseudoCheckboxVariant(),
654
+ this.disabled() ? 'disabled' : null,
655
+ ]), ...(ngDevMode ? [{ debugName: "_hostClasses" }] : []));
864
656
  }
865
657
  get _hostName() {
866
- return 'input';
658
+ return 'pseudo-checkbox';
867
659
  }
868
- ngAfterViewInit() {
869
- queueMicrotask(() => {
870
- const control = this.ngControl()?.control;
871
- if (control) {
872
- this._disabled.set(control.status === 'DISABLED');
873
- control.events.pipe(takeUntilDestroyed(this._destroyRef)).subscribe((event) => this.updateControlState(event));
874
- }
660
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PseudoCheckboxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
661
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: PseudoCheckboxComponent, isStandalone: true, selector: "ids-pseudo-checkbox", inputs: { checkboxState: { classPropertyName: "checkboxState", publicName: "checkboxState", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div class=\"ids-pseudo-checkbox__input-wrapper\">\n <input\n type=\"checkbox\"\n [disabled]=\"disabled()\"\n [attr.aria-checked]=\"_isIndeterminate() ? 'mixed' : null\"\n [checked]=\"_isChecked()\"\n [indeterminate]=\"_isIndeterminate()\"\n (change)=\"$event.stopPropagation()\"\n />\n <div class=\"ids-pseudo-checkbox__icon\" aria-hidden=\"true\">\n @if (_isIndeterminate()) {\n <ids-icon fontIcon=\"remove\" aria-hidden=\"true\" />\n }\n @if (_isChecked()) {\n <ids-icon fontIcon=\"done\" aria-hidden=\"true\" />\n }\n </div>\n</div>\n", dependencies: [{ kind: "component", type: IdsIconComponent, selector: "ids-icon", inputs: ["size", "sizeCollection", "variant", "fontIcon", "svgIcon", "aria-hidden"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
662
+ }
663
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PseudoCheckboxComponent, decorators: [{
664
+ type: Component,
665
+ args: [{ selector: 'ids-pseudo-checkbox', imports: [IdsIconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ids-pseudo-checkbox__input-wrapper\">\n <input\n type=\"checkbox\"\n [disabled]=\"disabled()\"\n [attr.aria-checked]=\"_isIndeterminate() ? 'mixed' : null\"\n [checked]=\"_isChecked()\"\n [indeterminate]=\"_isIndeterminate()\"\n (change)=\"$event.stopPropagation()\"\n />\n <div class=\"ids-pseudo-checkbox__icon\" aria-hidden=\"true\">\n @if (_isIndeterminate()) {\n <ids-icon fontIcon=\"remove\" aria-hidden=\"true\" />\n }\n @if (_isChecked()) {\n <ids-icon fontIcon=\"done\" aria-hidden=\"true\" />\n }\n </div>\n</div>\n" }]
666
+ }] });
667
+
668
+ class IdsOptionComponent extends ComponentBase {
669
+ get _hostName() {
670
+ return 'option';
671
+ }
672
+ constructor() {
673
+ super();
674
+ this._parent = inject(IDS_OPTION_PARENT_COMPONENT);
675
+ this._element = inject(ElementRef);
676
+ this.group = inject(IDS_OPTION_GROUP, { optional: true });
677
+ this._textElement = viewChild.required('text');
678
+ this.selected = signal(false, ...(ngDevMode ? [{ debugName: "selected" }] : []));
679
+ this._active = signal(false, ...(ngDevMode ? [{ debugName: "_active" }] : []));
680
+ this.size = computed(() => this._parent.parentSize(), ...(ngDevMode ? [{ debugName: "size" }] : []));
681
+ this.variant = computed(() => this._parent.parentVariant(), ...(ngDevMode ? [{ debugName: "variant" }] : []));
682
+ this.value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
683
+ this.explicitViewValue = input(null, ...(ngDevMode ? [{ debugName: "explicitViewValue", alias: 'viewValue' }] : [{ alias: 'viewValue' }]));
684
+ this.disabledInput = input(false, ...(ngDevMode ? [{ debugName: "disabledInput", alias: 'disabled', transform: coerceBooleanAttribute }] : [{ alias: 'disabled', transform: coerceBooleanAttribute }]));
685
+ this.disabled = false; // Do not delete this class member, until ListKeyManagerOption requires: `disabled: boolean`
686
+ this._groupOrOptionIsDisabled = computed(() => this.group?.disabled() || this.disabledInput(), ...(ngDevMode ? [{ debugName: "_groupOrOptionIsDisabled" }] : []));
687
+ this._multiSelect = Boolean(this._parent?.multiSelect());
688
+ // eslint-disable-next-line @angular-eslint/no-output-on-prefix
689
+ this.onSelectionChange = output();
690
+ this.viewValue = computed(() => this.explicitViewValue() || this._textElement().nativeElement.textContent || '', ...(ngDevMode ? [{ debugName: "viewValue" }] : []));
691
+ this._hostClasses = computed(() => this._getHostClasses([
692
+ this.selected() ? 'selected' : null,
693
+ this._active() ? 'active' : null,
694
+ this._groupOrOptionIsDisabled() ? 'disabled' : null,
695
+ this._multiSelect ? 'multiselect' : null,
696
+ this.size(),
697
+ this.variant(),
698
+ ]), ...(ngDevMode ? [{ debugName: "_hostClasses" }] : []));
699
+ this._pseudoCheckboxState = computed(() => (this.selected() ? IdsPseudoCheckboxState.CHECKED : IdsPseudoCheckboxState.UNCHECKED), ...(ngDevMode ? [{ debugName: "_pseudoCheckboxState" }] : []));
700
+ this.embeddedPseudoCheckboxSize = computed(() => this.size(), ...(ngDevMode ? [{ debugName: "embeddedPseudoCheckboxSize" }] : []));
701
+ this.embeddedPseudoCheckboxVariant = signal(IdsFormFieldVariant.SURFACE, ...(ngDevMode ? [{ debugName: "embeddedPseudoCheckboxVariant" }] : []));
702
+ effect(() => {
703
+ this.disabled = this.disabledInput();
875
704
  });
876
705
  }
877
- _validateType(type) {
878
- if (isDevMode() && IDS_INPUT_INVALID_TYPES.indexOf(type) > -1) {
879
- throw this._createHostError(`Input type ${type} is not supportedby idsInput`);
706
+ ngOnInit() {
707
+ const parent = this._parent;
708
+ if (parent.isOptionPreSelectedByValue(this.value())) {
709
+ this.selected.set(true);
880
710
  }
881
711
  }
882
- focus(options) {
883
- this._elementRef.nativeElement.focus(options);
712
+ _handleKeydown(event) {
713
+ if ((event.key === 'ENTER' || event.key === ' ') && !hasModifierKey(event)) {
714
+ this.selectViaInteraction();
715
+ event.preventDefault();
716
+ }
884
717
  }
885
- _focusChanged(isFocused) {
886
- if (isFocused !== this._focused) {
887
- this._focused = isFocused;
718
+ selectViaInteraction() {
719
+ if (!this._groupOrOptionIsDisabled()) {
720
+ this._emitSelectionChangeEvent(!this.selected(), true);
888
721
  }
889
722
  }
890
- updateControlState(event) {
891
- this._errorStateTracker?.updateErrorState();
892
- this._successStateTracker?.updateSuccessState();
893
- if (event instanceof StatusChangeEvent) {
894
- this._disabled.set(event.status === 'DISABLED');
723
+ getHostElement() {
724
+ return this._element.nativeElement;
725
+ }
726
+ select(emitEvent = true) {
727
+ if (!this.selected()) {
728
+ if (emitEvent) {
729
+ this._emitSelectionChangeEvent(true);
730
+ }
895
731
  }
896
732
  }
897
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsInputDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
898
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: IdsInputDirective, isStandalone: true, selector: "input[idsInput][ngModel]:not([formControl]):not([formControlName]),\n input[idsInput][formControl]:not([ngModel]):not([formControlName]),\n input[idsInput][formControlName]:not([ngModel]):not([formControl]),\n textarea[idsInput][ngModel]:not([formControl]):not([formControlName]),\n textarea[idsInput][formControl]:not([ngModel]):not([formControlName]),\n textarea[idsInput][formControlName]:not([ngModel]):not([formControl])", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, errorStateMatcher: { classPropertyName: "errorStateMatcher", publicName: "errorStateMatcher", isSignal: true, isRequired: false, transformFunction: null }, successStateMatcher: { classPropertyName: "successStateMatcher", publicName: "successStateMatcher", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focus": "_focusChanged(true)", "blur": "_focusChanged(false)" }, properties: { "attr.placeholder": "placeholder()", "attr.disabled": "disabled() ? \"\" : null", "attr.readonly": "readonly() ? \"\" : null" } }, providers: [
733
+ deselect(emitEvent = true) {
734
+ if (this.selected()) {
735
+ if (emitEvent) {
736
+ this._emitSelectionChangeEvent(false);
737
+ }
738
+ }
739
+ }
740
+ focus(_origin, options) {
741
+ const element = this._element.nativeElement;
742
+ if (typeof element.focus === 'function') {
743
+ element.focus(options);
744
+ }
745
+ }
746
+ setActiveStyles() {
747
+ if (!this._active()) {
748
+ this._active.set(true);
749
+ }
750
+ }
751
+ setInactiveStyles() {
752
+ if (this._active()) {
753
+ this._active.set(false);
754
+ }
755
+ }
756
+ getLabel() {
757
+ return this.viewValue();
758
+ }
759
+ _emitSelectionChangeEvent(selected, isUserInput = false) {
760
+ if (this._multiSelect || !this.selected()) {
761
+ this.onSelectionChange.emit(new IdsOptionSelectionChange(this, selected, isUserInput));
762
+ }
763
+ }
764
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsOptionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
765
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: IdsOptionComponent, isStandalone: true, selector: "ids-option", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, explicitViewValue: { classPropertyName: "explicitViewValue", publicName: "viewValue", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelectionChange: "onSelectionChange" }, host: { attributes: { "role": "option" }, listeners: { "click": "selectViaInteraction()", "keydown": "_handleKeydown($event)" }, properties: { "attr.aria-selected": "selected()", "attr.aria-disabled": "disabled.toString()" } }, providers: [
899
766
  {
900
- provide: IDS_FORM_FIELD_CONTROL,
901
- useExisting: IdsInputDirective,
767
+ provide: IDS_PSEUDO_CHECKBOX_PARENT,
768
+ useExisting: IdsOptionComponent,
902
769
  },
903
- ], exportAs: ["idsInput"], usesInheritance: true, ngImport: i0 }); }
770
+ ], viewQueries: [{ propertyName: "_textElement", first: true, predicate: ["text"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (_multiSelect) {\n <ids-pseudo-checkbox aria-hidden=\"true\" [disabled]=\"_groupOrOptionIsDisabled()\" [checkboxState]=\"_pseudoCheckboxState()\" />\n}\n\n<div #text class=\"ids-option__text\"><ng-content /></div>\n\n@if (!_multiSelect && selected()) {\n <ids-icon fontIcon=\"done\" />\n}\n", dependencies: [{ kind: "component", type: IdsIconComponent, selector: "ids-icon", inputs: ["size", "sizeCollection", "variant", "fontIcon", "svgIcon", "aria-hidden"] }, { kind: "component", type: PseudoCheckboxComponent, selector: "ids-pseudo-checkbox", inputs: ["checkboxState", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
904
771
  }
905
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsInputDirective, decorators: [{
906
- type: Directive,
907
- args: [{
908
- selector: `input[idsInput][ngModel]:not([formControl]):not([formControlName]),
909
- input[idsInput][formControl]:not([ngModel]):not([formControlName]),
910
- input[idsInput][formControlName]:not([ngModel]):not([formControl]),
911
- textarea[idsInput][ngModel]:not([formControl]):not([formControlName]),
912
- textarea[idsInput][formControl]:not([ngModel]):not([formControlName]),
913
- textarea[idsInput][formControlName]:not([ngModel]):not([formControl])`,
914
- exportAs: 'idsInput',
915
- standalone: true,
916
- providers: [
772
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsOptionComponent, decorators: [{
773
+ type: Component,
774
+ args: [{ selector: 'ids-option', imports: [
775
+ IdsIconComponent,
776
+ PseudoCheckboxComponent,
777
+ ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
917
778
  {
918
- provide: IDS_FORM_FIELD_CONTROL,
919
- useExisting: IdsInputDirective,
779
+ provide: IDS_PSEUDO_CHECKBOX_PARENT,
780
+ useExisting: IdsOptionComponent,
920
781
  },
921
- ],
922
- host: {
923
- '[attr.placeholder]': 'placeholder()',
924
- '[attr.disabled]': 'disabled() ? "" : null',
925
- '[attr.readonly]': 'readonly() ? "" : null',
926
- '(focus)': '_focusChanged(true)',
927
- '(blur)': '_focusChanged(false)',
928
- },
929
- }]
930
- }] });
782
+ ], host: {
783
+ 'role': 'option',
784
+ '[attr.aria-selected]': 'selected()',
785
+ '[attr.aria-disabled]': 'disabled.toString()',
786
+ '(click)': 'selectViaInteraction()',
787
+ '(keydown)': '_handleKeydown($event)',
788
+ }, template: "@if (_multiSelect) {\n <ids-pseudo-checkbox aria-hidden=\"true\" [disabled]=\"_groupOrOptionIsDisabled()\" [checkboxState]=\"_pseudoCheckboxState()\" />\n}\n\n<div #text class=\"ids-option__text\"><ng-content /></div>\n\n@if (!_multiSelect && selected()) {\n <ids-icon fontIcon=\"done\" />\n}\n" }]
789
+ }], ctorParameters: () => [] });
790
+ function _countGroupLabelsBeforeOption(optionIndex, options, optionGroups) {
791
+ if (optionGroups.length) {
792
+ let groupCounter = 0;
793
+ for (let i = 0; i < optionIndex + 1; i++) {
794
+ if (options[i].group && options[i].group === optionGroups[groupCounter]) {
795
+ groupCounter++;
796
+ }
797
+ }
798
+ return groupCounter;
799
+ }
800
+ return 0;
801
+ }
802
+ function _getOptionScrollPosition(optionOffset, optionHeight, currentScrollPosition, panelHeight) {
803
+ if (optionOffset < currentScrollPosition) {
804
+ return optionOffset;
805
+ }
806
+ if (optionOffset + optionHeight > currentScrollPosition + panelHeight) {
807
+ return Math.max(0, optionOffset - panelHeight + optionHeight);
808
+ }
809
+ return currentScrollPosition;
810
+ }
931
811
 
932
- const defaultConfig = IDS_AUTOCOMPLETE_DEFAULT_CONFIG_FACTORY();
933
- const LIVE_ANNOUNCE_DURATION_MS = 10000;
812
+ const defaultConfig$1 = IDS_AUTOCOMPLETE_DEFAULT_CONFIG_FACTORY();
934
813
  class IdsAutocompleteComponent extends IdsFormFieldControl {
935
814
  get _hostName() {
936
815
  return 'autocomplete';
937
816
  }
938
- get _empty() {
939
- return Boolean(this._selectionModel?.isEmpty());
940
- }
941
- get selected() {
942
- return this.multiSelect() ? this._selectionModel?.selected : this._selectionModel?.selected?.[0];
943
- }
944
- get _triggerValue() {
945
- if (this._empty) {
946
- return '';
947
- }
948
- if (this.multiSelect()) {
949
- const selectedOptions = this._selectionModel?.selected;
950
- return selectedOptions?.join(', ') || '';
951
- }
952
- return this._selectionModel?.selected?.[0] || '';
953
- }
954
817
  constructor() {
955
818
  super();
956
- this._defaultConfig = this._getDefaultConfig(defaultConfig, IDS_AUTOCOMPLETE_DEFAULT_CONFIG);
957
- this._elementRef = inject(ElementRef);
958
- this._changeDetectorRef = inject(ChangeDetectorRef);
959
- this._liveAnnouncer = inject(LiveAnnouncer);
960
- this._parentFormField = inject(IdsFormFieldComponent);
961
- this._overlayWidth = 0;
962
- /**
963
- * Minimum number of characters to initiate actual search.
964
- * Warning is shown when input length is not met.
965
- * (Resource loader/stream function needs to be adjusted accordingly!)
966
- */
967
- this.minChars = input(1, ...(ngDevMode ? [{ debugName: "minChars", transform: coerceNumberAttribute }] : [{ transform: coerceNumberAttribute }]));
968
- /** Max length of options allowed to show. Warning is shown when available options is higher than this number */
969
- this.maxLength = input(null, ...(ngDevMode ? [{ debugName: "maxLength", transform: coerceNumberAttribute }] : [{ transform: coerceNumberAttribute }]));
970
- this.multiSelect = input(false, ...(ngDevMode ? [{ debugName: "multiSelect" }] : []));
971
819
  this.ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel", alias: 'aria-label' }] : [{ alias: 'aria-label' }]));
972
820
  this.ariaLabelledby = input('', ...(ngDevMode ? [{ debugName: "ariaLabelledby", alias: 'aria-labelledby' }] : [{ alias: 'aria-labelledby' }]));
973
- this.ariaLabelClearButton = input('Clear', ...(ngDevMode ? [{ debugName: "ariaLabelClearButton" }] : []));
974
- this.ariaLabelToggleButton = input('Toggle', ...(ngDevMode ? [{ debugName: "ariaLabelToggleButton" }] : []));
975
- this.valueCompareFn = input((o1, o2) => o1 === o2, ...(ngDevMode ? [{ debugName: "valueCompareFn" }] : []));
976
- this.sortCompareFn = input(...(ngDevMode ? [undefined, { debugName: "sortCompareFn" }] : []));
821
+ this.ariaLabelClear = input('', ...(ngDevMode ? [{ debugName: "ariaLabelClear" }] : []));
822
+ this.ariaLabelLoading = input('', ...(ngDevMode ? [{ debugName: "ariaLabelLoading" }] : []));
823
+ this.multiSelect = input(false, ...(ngDevMode ? [{ debugName: "multiSelect", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
977
824
  this.tabIndex = input(0, ...(ngDevMode ? [{ debugName: "tabIndex", transform: coerceNumberAttribute }] : [{ transform: coerceNumberAttribute }]));
978
- this.typeaheadDebounceInterval = input(this._defaultConfig.typeaheadDebounceInterval, ...(ngDevMode ? [{ debugName: "typeaheadDebounceInterval", transform: coerceNumberAttribute }] : [{
979
- transform: coerceNumberAttribute,
980
- }]));
981
- this.hintLoading = input(this._defaultConfig.hintLoading, ...(ngDevMode ? [{ debugName: "hintLoading" }] : []));
982
- this.hintNoResults = input(this._defaultConfig.hintNoResults, ...(ngDevMode ? [{ debugName: "hintNoResults" }] : []));
983
- this.hintMinChars = input(this._defaultConfig.hintMinChars, ...(ngDevMode ? [{ debugName: "hintMinChars" }] : []));
984
- this.hintMaxLength = input(this._defaultConfig.hintMaxLength, ...(ngDevMode ? [{ debugName: "hintMaxLength" }] : []));
825
+ this.sortCompareFn = input((a, b) => a.viewValue.localeCompare(b.viewValue), ...(ngDevMode ? [{ debugName: "sortCompareFn" }] : []));
826
+ this.valueCompareFn = input((o1, o2) => JSON.stringify(o1) === JSON.stringify(o2), ...(ngDevMode ? [{ debugName: "valueCompareFn" }] : []));
827
+ this.trigger = input.required(...(ngDevMode ? [{ debugName: "trigger" }] : []));
985
828
  this.panelClasses = input('', ...(ngDevMode ? [{ debugName: "panelClasses" }] : []));
829
+ this.panelOpen = model(false, ...(ngDevMode ? [{ debugName: "panelOpen" }] : []));
830
+ this.options = contentChildren(IdsOptionComponent, ...(ngDevMode ? [{ debugName: "options", descendants: true }] : [{ descendants: true }]));
831
+ this.optionGroups = contentChildren(IDS_OPTION_GROUP, ...(ngDevMode ? [{ debugName: "optionGroups", descendants: true }] : [{ descendants: true }]));
832
+ this.overlayPanel = viewChild('overlayPanel', ...(ngDevMode ? [{ debugName: "overlayPanel" }] : []));
833
+ this.panel = viewChild('panel', ...(ngDevMode ? [{ debugName: "panel", read: (ElementRef) }] : [{ read: (ElementRef) }]));
834
+ this.appearance = input(IdsIconButtonAppearance.STANDARD, ...(ngDevMode ? [{ debugName: "appearance" }] : []));
986
835
  this.parentSize = computed(() => this._parentFormField.parentOrSelfSize(), ...(ngDevMode ? [{ debugName: "parentSize" }] : []));
987
836
  this.parentVariant = computed(() => this._parentFormField.parentOrSelfVariant(), ...(ngDevMode ? [{ debugName: "parentVariant" }] : []));
988
- this.errorStateMatcher = signal(inject(ErrorStateMatcher), ...(ngDevMode ? [{ debugName: "errorStateMatcher" }] : []));
989
- this.successStateMatcher = signal(inject(SuccessStateMatcher), ...(ngDevMode ? [{ debugName: "successStateMatcher" }] : []));
990
- this.options = viewChildren(IdsOptionComponent, ...(ngDevMode ? [{ debugName: "options" }] : []));
991
- this.overlayPanel = viewChild.required(IdsOverlayPanelComponent);
992
- this.onContainerClick = () => { };
837
+ this.spinnerVariant = input(IdsSpinnerVariant.SURFACE, ...(ngDevMode ? [{ debugName: "spinnerVariant" }] : []));
838
+ this.isLoading = input(false, ...(ngDevMode ? [{ debugName: "isLoading", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
839
+ this.onChange = () => { };
840
+ this.onTouched = () => { };
841
+ this._parentFormField = inject(IdsFormFieldComponent);
842
+ // declarations of IdsFormFieldControl variables
843
+ this._defaultConfig = this._getDefaultConfig(defaultConfig$1, IDS_AUTOCOMPLETE_DEFAULT_CONFIG);
844
+ this.errorStateMatcher = input(inject(this._defaultConfig.errorStateMatcher), ...(ngDevMode ? [{ debugName: "errorStateMatcher" }] : []));
845
+ this.successStateMatcher = input(inject(this._defaultConfig.successStateMatcher), ...(ngDevMode ? [{ debugName: "successStateMatcher" }] : []));
846
+ this._elementRef = inject(ElementRef);
993
847
  this._hostClasses = computed(() => this._getHostClasses([
994
848
  this.parentSize(),
995
- this.parentVariant(),
996
849
  this.disabled() ? 'disabled' : null,
997
- this.readonly() ? 'readonly' : null,
998
850
  ], [formFieldControlClass]), ...(ngDevMode ? [{ debugName: "_hostClasses" }] : []));
999
851
  this._panelClasses = computed(() => [
1000
- 'ids-overlay-panel__autocomplete-panel',
852
+ 'ids-autocomplete-overlay-panel',
1001
853
  this.panelClasses(),
1002
854
  ].join(' '), ...(ngDevMode ? [{ debugName: "_panelClasses" }] : []));
1003
- this._focused = signal(false, ...(ngDevMode ? [{ debugName: "_focused" }] : []));
1004
- this._canOpen = computed(() => !this.overlayPanel().open() && !this.disabled() && !this.readonly() && this.options().length > 0, ...(ngDevMode ? [{ debugName: "_canOpen" }] : []));
1005
- this._panel = viewChild('overlay', ...(ngDevMode ? [{ debugName: "_panel", read: (ElementRef) }] : [{ read: (ElementRef) }]));
1006
- this._inputElemment = viewChild('fallbackOverlayOrigin', ...(ngDevMode ? [{ debugName: "_inputElemment", read: (ElementRef) }] : [{ read: (ElementRef) }]));
1007
- this._resource = rxResource({
1008
- defaultValue: [],
1009
- params: () => ({ search: this._searchText() }),
1010
- stream: inject(IDS_AUTOCOMPLETE_LOADER),
1011
- });
1012
- this._onChange = () => { };
1013
- this._onTouched = () => { };
1014
- this._searchText = model('', ...(ngDevMode ? [{ debugName: "_searchText" }] : []));
1015
- this._skipPredicate = (option) => {
1016
- if (this.overlayPanel().open()) {
1017
- return false;
855
+ // #region IdsFormFieldControl implementation
856
+ this.onContainerClick = (event) => {
857
+ if (!this.readonly() && !this.disabled()) {
858
+ const target = event.target;
859
+ // 'clear' button should not trigger focus on the input
860
+ if (target.parentElement?.tagName === 'BUTTON' || (target.tagName === 'IDS-ICON' && target.parentElement?.tagName === 'BUTTON')) {
861
+ return;
862
+ }
863
+ this.trigger().focus();
1018
864
  }
1019
- return option.disabledInput();
1020
865
  };
1021
866
  effect(() => {
1022
- this._keyManager?.withTypeAhead(this.typeaheadDebounceInterval());
1023
- });
1024
- effect(() => {
1025
- const options = this.options();
1026
- untracked(() => {
1027
- if (options.length > 0) {
1028
- this._initKeyManager();
1029
- this.options().forEach((option) => {
1030
- if (this._selectionModel?.selected.includes(option.viewValue())) {
1031
- option.selected.set(true);
1032
- }
1033
- });
1034
- this._subscribeOptionChanges();
1035
- }
1036
- });
1037
- });
1038
- effect(() => {
1039
- const searchText = this._searchText();
867
+ const overlayPanelOpen = this.overlayPanel()?.open() ?? false;
1040
868
  untracked(() => {
1041
- const control = this.ngControl()?.control;
1042
- const controlValue = control?.value;
1043
- if (controlValue && searchText !== controlValue) {
1044
- control.setValue(null);
1045
- this._clearSelection();
869
+ if (!overlayPanelOpen && this.panelOpen()) {
870
+ this.panelOpen.set(false);
1046
871
  }
1047
872
  });
1048
873
  });
1049
874
  }
1050
875
  ngOnInit() {
1051
876
  if (!this._parentFormField) {
1052
- throw this._createHostError('Select must be in a form field');
877
+ throw this.createHostError('Select must be in a form field');
1053
878
  }
1054
- this._selectionModel = new SelectionModel(this.multiSelect(), undefined, false, this.valueCompareFn());
1055
- queueMicrotask(() => {
1056
- const control = this.ngControl()?.control;
1057
- if (control) {
1058
- control.events
1059
- .pipe(filter((event) => event instanceof ValueChangeEvent), takeUntilDestroyed(this._destroyRef))
1060
- .subscribe(() => this._changeDetectorRef.markForCheck());
1061
- }
1062
- });
1063
- this._initErrorStateTracker();
1064
879
  }
1065
880
  ngAfterViewInit() {
881
+ this._initErrorStateTracker();
1066
882
  queueMicrotask(() => {
1067
883
  const controlDir = this.ngControl();
1068
884
  if (controlDir?.control) {
@@ -1074,276 +890,493 @@ class IdsAutocompleteComponent extends IdsFormFieldControl {
1074
890
  this._errorStateTracker?.updateErrorState();
1075
891
  this._successStateTracker?.updateSuccessState();
1076
892
  }
1077
- ngOnDestroy() {
1078
- this._keyManager?.destroy();
1079
- }
1080
- _initKeyManager() {
1081
- this._keyManager = new ActiveDescendantKeyManager(this.options())
1082
- .withTypeAhead(this.typeaheadDebounceInterval())
1083
- .withVerticalOrientation()
1084
- .withHorizontalOrientation('ltr')
1085
- .withHomeAndEnd()
1086
- .withPageUpDown()
1087
- .withAllowedModifierKeys(['shiftKey'])
1088
- .skipPredicate(this._skipPredicate);
1089
- this._keyManager.change.subscribe(() => {
1090
- if (this.overlayPanel().open() && this._panel()) {
1091
- this._scrollOptionIntoView(this._keyManager?.activeItemIndex || 0);
1092
- }
1093
- });
1094
- }
1095
- _subscribeOptionChanges() {
1096
- this.options().forEach((option) => {
1097
- option.onSelectionChange.subscribe((change) => {
1098
- this._handleOptionChange(change);
1099
- });
1100
- });
1101
- }
1102
- _handleOptionChange(change) {
1103
- const { source, selected, isUserInput } = change;
1104
- if (!this.multiSelect()) {
1105
- this._clearSelection();
1106
- }
1107
- source.selected.set(selected);
1108
- if (isUserInput) {
1109
- this._keyManager?.setActiveItem(source);
1110
- }
1111
- if (isUserInput && !this.multiSelect() && this.overlayPanel().open()) {
1112
- this.close();
1113
- }
1114
- if (this.multiSelect()) {
1115
- this._sortValues();
1116
- }
1117
- if (selected) {
1118
- this._selectionModel?.select(source.viewValue());
1119
- this._searchText.set(source.viewValue());
893
+ // #region ControlValueAccessor implementation
894
+ writeValue(value) {
895
+ if (value !== null) {
896
+ this._patchValue(value);
1120
897
  }
1121
898
  else {
1122
- this._selectionModel?.deselect(source.viewValue());
899
+ this.trigger()?.clear();
1123
900
  }
1124
- this._handleChange();
1125
- this._onTouched();
1126
- this._inputElemment()?.nativeElement.blur();
1127
- this.overlayPanel().open.set(false);
901
+ this._value = value;
1128
902
  }
1129
- _handleKeydown(event) {
1130
- if (!this.disabled() && !this.readonly()) {
1131
- this.overlayPanel().open() ? this._handleOpenedPanelKeydown(event) : this._handleClosedPanelKeydown(event);
1132
- // announce number of options when a key is pressed
1133
- this._liveAnnouncer.announce(this.options()
1134
- .filter((option) => !option.disabled)
1135
- .length.toString(), LIVE_ANNOUNCE_DURATION_MS);
1136
- }
903
+ registerOnChange(fn) {
904
+ this.onChange = fn;
1137
905
  }
1138
- _handleClosedPanelKeydown(event) {
1139
- const key = event.key;
1140
- const targetElement = event.target;
1141
- const isButtonTarget = targetElement.localName === 'button';
1142
- if (isButtonTarget && (key === 'Enter' || key === ' ')) {
1143
- event.preventDefault();
1144
- targetElement.click();
1145
- targetElement.blur();
1146
- return;
1147
- }
1148
- const manager = this._keyManager;
1149
- const isArrowKey = key === 'ArrowDown' || key === 'ArrowUp' || key === 'ArrowLeft' || key === 'ArrowRight';
1150
- const isOpenKey = key === 'Enter' || key === ' ';
1151
- if ((!manager?.isTyping() && isOpenKey && !hasModifierKey(event)) ||
1152
- isArrowKey ||
1153
- this.options().length > 0 ||
1154
- this._resource.value().length > 0) {
1155
- if (isArrowKey || isOpenKey) {
1156
- event.preventDefault();
1157
- }
1158
- this.open();
1159
- }
1160
- else if (!this.multiSelect()) {
1161
- const previouslySelectedOption = this.selected;
1162
- manager?.onKeydown(event);
1163
- const selectedOption = this.selected;
1164
- if (selectedOption && previouslySelectedOption !== selectedOption) {
1165
- this._liveAnnouncer.announce(selectedOption, LIVE_ANNOUNCE_DURATION_MS);
1166
- }
1167
- }
906
+ registerOnTouched(fn) {
907
+ this.onTouched = fn;
1168
908
  }
1169
- _handleOpenedPanelKeydown(event) {
1170
- const key = event.key;
1171
- const targetElement = event.target;
1172
- const isButtonTarget = targetElement.localName === 'button';
1173
- if (isButtonTarget && (key === 'Enter' || key === ' ')) {
1174
- event.preventDefault();
1175
- targetElement.click();
1176
- targetElement.blur();
1177
- return;
1178
- }
1179
- const manager = this._keyManager;
1180
- const isArrowKey = key === 'ArrowDown' || key === 'ArrowUp';
1181
- const isTyping = manager?.isTyping();
1182
- if (isArrowKey && event.altKey) {
1183
- event.preventDefault();
1184
- this.close();
1185
- }
1186
- else if (!isTyping && (key === 'Enter' || key === ' ') && manager?.activeItem && !hasModifierKey(event)) {
1187
- event.preventDefault();
1188
- manager.activeItem.selectViaInteraction();
909
+ setDisabledState(isDisabled) {
910
+ this._disabled.set(isDisabled);
911
+ }
912
+ // #endregion
913
+ handleChange(value) {
914
+ this._value = value;
915
+ this.onChange(value);
916
+ }
917
+ // #endregion
918
+ // #region required as `IDS_OPTION_PARENT`, but not used here as it cannot handle option content changes.
919
+ // Selection is handled by `_updateCurrentSelection` method of `AutocompleteTriggerDirective`
920
+ isOptionPreSelectedByValue() {
921
+ return false;
922
+ }
923
+ // #endregion
924
+ setScrollTop(scrollTop) {
925
+ if (this.panel()) {
926
+ this.panel().nativeElement.scrollTop = scrollTop;
1189
927
  }
1190
- else if (!isTyping && this.multiSelect() && key === 'a' && event.ctrlKey) {
1191
- event.preventDefault();
1192
- const hasDeselectedOptions = this.options().some((opt) => !opt.disabled && !opt.selected());
1193
- this.options().forEach((option) => {
1194
- if (!option.disabled) {
1195
- hasDeselectedOptions ? option.select() : option.deselect();
928
+ }
929
+ getScrollTop() {
930
+ return this.panel() ? this.panel()?.nativeElement.scrollTop : 0;
931
+ }
932
+ setPanelOpen() {
933
+ this._overlayOrigin = this._parentFormField?.getConnectedOverlayOrigin();
934
+ this.overlayPanel()?.overlayDir()?.overlayRef?.updateSize({ width: this._overlayOrigin.nativeElement.getBoundingClientRect().width });
935
+ this._observeOverlayOrigin();
936
+ this.panelOpen.set(true);
937
+ }
938
+ createHostError(message) {
939
+ throw this._createHostError(message);
940
+ }
941
+ _observeOverlayOrigin() {
942
+ const observer = new ResizeObserver(() => {
943
+ this.overlayPanel()?.overlayDir()?.overlayRef?.updatePosition();
944
+ this.overlayPanel()?.overlayDir()?.overlayRef?.updateSize({ width: this._overlayOrigin.nativeElement.getBoundingClientRect().width });
945
+ });
946
+ observer.observe(this._overlayOrigin.nativeElement);
947
+ }
948
+ // "async" way to patch value to ensure options are loaded before setting selection
949
+ _patchValue(value) {
950
+ const patchEffect = effect(() => {
951
+ const options = this.options();
952
+ untracked(() => {
953
+ if (options.length > 0) {
954
+ this.trigger().setSelectionByValue(value);
955
+ patchEffect.destroy();
1196
956
  }
1197
957
  });
1198
- }
1199
- else {
1200
- const previouslyFocusedIndex = manager?.activeItemIndex;
1201
- manager?.onKeydown(event);
1202
- if (this.multiSelect() &&
1203
- isArrowKey &&
1204
- event.shiftKey &&
1205
- manager?.activeItem &&
1206
- manager?.activeItemIndex !== previouslyFocusedIndex) {
1207
- manager?.activeItem.selectViaInteraction();
958
+ }, ...(ngDevMode ? [{ debugName: "patchEffect", injector: this._injector, manualCleanup: true }] : [{ injector: this._injector, manualCleanup: true }]));
959
+ }
960
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
961
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: IdsAutocompleteComponent, isStandalone: true, selector: "ids-autocomplete", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelClear: { classPropertyName: "ariaLabelClear", publicName: "ariaLabelClear", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelLoading: { classPropertyName: "ariaLabelLoading", publicName: "ariaLabelLoading", isSignal: true, isRequired: false, transformFunction: null }, multiSelect: { classPropertyName: "multiSelect", publicName: "multiSelect", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, sortCompareFn: { classPropertyName: "sortCompareFn", publicName: "sortCompareFn", isSignal: true, isRequired: false, transformFunction: null }, valueCompareFn: { classPropertyName: "valueCompareFn", publicName: "valueCompareFn", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: true, transformFunction: null }, panelClasses: { classPropertyName: "panelClasses", publicName: "panelClasses", isSignal: true, isRequired: false, transformFunction: null }, panelOpen: { classPropertyName: "panelOpen", publicName: "panelOpen", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, spinnerVariant: { classPropertyName: "spinnerVariant", publicName: "spinnerVariant", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, errorStateMatcher: { classPropertyName: "errorStateMatcher", publicName: "errorStateMatcher", isSignal: true, isRequired: false, transformFunction: null }, successStateMatcher: { classPropertyName: "successStateMatcher", publicName: "successStateMatcher", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { panelOpen: "panelOpenChange" }, providers: [
962
+ { provide: IDS_FORM_FIELD_CONTROL, useExisting: IdsAutocompleteComponent },
963
+ { provide: IDS_OPTION_PARENT_COMPONENT, useExisting: IdsAutocompleteComponent },
964
+ {
965
+ provide: NG_VALUE_ACCESSOR,
966
+ useExisting: forwardRef(() => IdsAutocompleteComponent),
967
+ multi: true,
968
+ },
969
+ ], queries: [{ propertyName: "options", predicate: IdsOptionComponent, descendants: true, isSignal: true }, { propertyName: "optionGroups", predicate: IDS_OPTION_GROUP, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "overlayPanel", first: true, predicate: ["overlayPanel"], descendants: true, isSignal: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true, read: ElementRef, isSignal: true }], exportAs: ["idsAutocomplete"], usesInheritance: true, ngImport: i0, template: `
970
+ @if (panelOpen()) {
971
+ <ids-overlay-panel
972
+ #overlayPanel
973
+ appearance="elevated"
974
+ [origin]="_overlayOrigin"
975
+ [open]="panelOpen()"
976
+ [size]="parentSize()"
977
+ [panelClasses]="_panelClasses()"
978
+ >
979
+ <div
980
+ #panel
981
+ class="ids-autocomplete-panel"
982
+ role="listbox"
983
+ [id]="id() + '-panel'"
984
+ [attr.aria-multiselectable]="multiSelect()"
985
+ [attr.aria-label]="ariaLabel() || null"
986
+ [attr.aria-labelledby]="ariaLabelledby() || null"
987
+ >
988
+ <ng-content />
989
+ </div>
990
+ </ids-overlay-panel>
991
+ }
992
+ <span class="ids-autocomplete-suffix">
993
+ @if (trigger().selected.length > 0) {
994
+ <button
995
+ type="button"
996
+ idsIconButton
997
+ [appearance]="appearance()"
998
+ [variant]="parentVariant()"
999
+ [size]="parentSize()"
1000
+ [disabled]="disabled()"
1001
+ [ariaLabel]="ariaLabelClear()"
1002
+ [idsTooltip]="ariaLabelClear()"
1003
+ [idsTooltipDisabled]="!ariaLabelClear()"
1004
+ [idsTooltipIgnoreClipped]="true"
1005
+ (click)="trigger().clear()"
1006
+ >
1007
+ <ids-icon alt="" aria-hidden="true" fontIcon="close" />
1008
+ </button>
1009
+ }
1010
+ @if (isLoading()) {
1011
+ <ids-spinner
1012
+ sizeCollection="small"
1013
+ [size]="parentSize()"
1014
+ [variant]="spinnerVariant()"
1015
+ [isTrack]="true"
1016
+ [aria-label]="ariaLabelLoading()"
1017
+ />
1018
+ } @else {
1019
+ <ids-icon
1020
+ alt=""
1021
+ aria-hidden="true"
1022
+ [size]="parentSize()"
1023
+ [fontIcon]="trigger().autocomplete().panelOpen() ? 'chevron-up' : 'chevron-down'"
1024
+ />
1025
+ }
1026
+ </span>
1027
+ `, isInline: true, dependencies: [{ kind: "component", type: IdsIconComponent, selector: "ids-icon", inputs: ["size", "sizeCollection", "variant", "fontIcon", "svgIcon", "aria-hidden"] }, { kind: "component", type: IdsIconButtonComponent, selector: "button[idsIconButton], a[idsIconButton]", inputs: ["appearance", "size", "variant", "disabled", "allowCustomContent"] }, { kind: "component", type: IdsOverlayPanelComponent, selector: "ids-overlay-panel", inputs: ["open", "origin", "positions", "appearance", "size", "variant", "panelClasses", "width"], outputs: ["openChange"] }, { kind: "component", type: IdsSpinnerComponent, selector: "ids-spinner", inputs: ["size", "sizeCollection", "variant", "isTrack", "aria-label"] }, { kind: "directive", type: IdsTooltipDirective, selector: "[idsTooltip]", inputs: ["idsTooltip", "idsTooltipPosition", "idsTooltipSize", "idsTooltipVariant", "idsTooltipShowDelay", "idsTooltipHideDelay", "idsTooltipDisabled", "idsTooltipTouchGestures", "idsTooltipTextAlign", "idsTooltipClass", "idsTooltipShowPointer", "idsTooltipIgnoreClipped"] }] }); }
1028
+ }
1029
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteComponent, decorators: [{
1030
+ type: Component,
1031
+ args: [{
1032
+ selector: 'ids-autocomplete',
1033
+ imports: [
1034
+ IdsIconComponent,
1035
+ IdsIconButtonComponent,
1036
+ IdsOverlayPanelComponent,
1037
+ IdsSpinnerComponent,
1038
+ IdsTooltipDirective,
1039
+ ],
1040
+ template: `
1041
+ @if (panelOpen()) {
1042
+ <ids-overlay-panel
1043
+ #overlayPanel
1044
+ appearance="elevated"
1045
+ [origin]="_overlayOrigin"
1046
+ [open]="panelOpen()"
1047
+ [size]="parentSize()"
1048
+ [panelClasses]="_panelClasses()"
1049
+ >
1050
+ <div
1051
+ #panel
1052
+ class="ids-autocomplete-panel"
1053
+ role="listbox"
1054
+ [id]="id() + '-panel'"
1055
+ [attr.aria-multiselectable]="multiSelect()"
1056
+ [attr.aria-label]="ariaLabel() || null"
1057
+ [attr.aria-labelledby]="ariaLabelledby() || null"
1058
+ >
1059
+ <ng-content />
1060
+ </div>
1061
+ </ids-overlay-panel>
1062
+ }
1063
+ <span class="ids-autocomplete-suffix">
1064
+ @if (trigger().selected.length > 0) {
1065
+ <button
1066
+ type="button"
1067
+ idsIconButton
1068
+ [appearance]="appearance()"
1069
+ [variant]="parentVariant()"
1070
+ [size]="parentSize()"
1071
+ [disabled]="disabled()"
1072
+ [ariaLabel]="ariaLabelClear()"
1073
+ [idsTooltip]="ariaLabelClear()"
1074
+ [idsTooltipDisabled]="!ariaLabelClear()"
1075
+ [idsTooltipIgnoreClipped]="true"
1076
+ (click)="trigger().clear()"
1077
+ >
1078
+ <ids-icon alt="" aria-hidden="true" fontIcon="close" />
1079
+ </button>
1080
+ }
1081
+ @if (isLoading()) {
1082
+ <ids-spinner
1083
+ sizeCollection="small"
1084
+ [size]="parentSize()"
1085
+ [variant]="spinnerVariant()"
1086
+ [isTrack]="true"
1087
+ [aria-label]="ariaLabelLoading()"
1088
+ />
1089
+ } @else {
1090
+ <ids-icon
1091
+ alt=""
1092
+ aria-hidden="true"
1093
+ [size]="parentSize()"
1094
+ [fontIcon]="trigger().autocomplete().panelOpen() ? 'chevron-up' : 'chevron-down'"
1095
+ />
1096
+ }
1097
+ </span>
1098
+ `,
1099
+ exportAs: 'idsAutocomplete',
1100
+ providers: [
1101
+ { provide: IDS_FORM_FIELD_CONTROL, useExisting: IdsAutocompleteComponent },
1102
+ { provide: IDS_OPTION_PARENT_COMPONENT, useExisting: IdsAutocompleteComponent },
1103
+ {
1104
+ provide: NG_VALUE_ACCESSOR,
1105
+ useExisting: forwardRef(() => IdsAutocompleteComponent),
1106
+ multi: true,
1107
+ },
1108
+ ],
1109
+ }]
1110
+ }], ctorParameters: () => [] });
1111
+
1112
+ const LIVE_ANNOUNCER_DURATION = 10000;
1113
+ class IdsAutocompleteTriggerDirective {
1114
+ get selected() {
1115
+ return this._selectionModel?.selected ?? [];
1116
+ }
1117
+ get selectedOptions() {
1118
+ const selectedValues = this.selected.map((option) => option.value) ?? [];
1119
+ return this.autocomplete()
1120
+ .options()
1121
+ .filter((option) => selectedValues.includes(option.value()));
1122
+ }
1123
+ constructor() {
1124
+ this.autocomplete = input.required(...(ngDevMode ? [{ debugName: "autocomplete", alias: 'idsAutocompleteTriggerFor' }] : [{ alias: 'idsAutocompleteTriggerFor' }]));
1125
+ this._disabled = computed(() => this.autocomplete().disabled(), ...(ngDevMode ? [{ debugName: "_disabled" }] : []));
1126
+ this._readonly = computed(() => this.autocomplete().readonly(), ...(ngDevMode ? [{ debugName: "_readonly" }] : []));
1127
+ this._inputElement = inject((ElementRef));
1128
+ this._liveAnnouncer = inject(LiveAnnouncer);
1129
+ this._renderer = inject(Renderer2);
1130
+ this._injector = inject(Injector);
1131
+ this._skipPredicate = (option) => {
1132
+ if (this.autocomplete().panelOpen()) {
1133
+ return false;
1208
1134
  }
1209
- }
1135
+ return option.disabledInput();
1136
+ };
1137
+ effect(() => {
1138
+ const options = this.autocomplete().options();
1139
+ untracked(() => {
1140
+ if (options.length > 0) {
1141
+ this._initKeyManager();
1142
+ this._subscribeOptionChanges();
1143
+ this._liveAnnouncer.announce(options.length.toString(), LIVE_ANNOUNCER_DURATION);
1144
+ if (!this._selectionModel.isEmpty()) {
1145
+ this._updateCurrentSelection();
1146
+ }
1147
+ }
1148
+ });
1149
+ });
1210
1150
  }
1211
- _scrollOptionIntoView(index) {
1212
- const option = this.options()[index];
1213
- if (option) {
1214
- const panel = this._panel().nativeElement;
1215
- const element = option.getHostElement();
1216
- if (index === 0) {
1217
- panel.scrollTop = 0;
1151
+ ngOnInit() {
1152
+ this._selectionModel = new SelectionModel(true, undefined, true, this.autocomplete().valueCompareFn());
1153
+ this._selectionModel.changed.subscribe(() => {
1154
+ if (this.autocomplete().multiSelect()) {
1155
+ this._selectionModel?.sort(this.autocomplete().sortCompareFn());
1218
1156
  }
1219
1157
  else {
1220
- panel.scrollTop = _getOptionScrollPosition(element.offsetTop, element.offsetHeight, panel.scrollTop, panel.offsetHeight);
1158
+ this._updateInputValue(this.selected[0]?.viewValue);
1221
1159
  }
1222
- }
1223
- }
1224
- _sortValues() {
1225
- if (this.multiSelect()) {
1226
- const options = this.options().map((option) => option.viewValue());
1227
- const sortComparator = this.sortCompareFn();
1228
- this._selectionModel?.sort((a, b) => (sortComparator ? sortComparator(a, b, options) : options.indexOf(a) - options.indexOf(b)));
1229
- }
1160
+ this.autocomplete().handleChange(this.autocomplete().multiSelect() ? this.selected.map((option) => option.value) : (this.selected[0]?.value ?? null));
1161
+ this.autocomplete().onTouched();
1162
+ });
1230
1163
  }
1231
- _getOverlayWidth(preferredOrigin) {
1232
- const refToMeasure = preferredOrigin instanceof CdkOverlayOrigin ? preferredOrigin.elementRef : preferredOrigin || this._elementRef;
1233
- return refToMeasure.nativeElement.getBoundingClientRect().width;
1164
+ ngOnDestroy() {
1165
+ this._keyManager?.destroy();
1234
1166
  }
1235
1167
  toggle() {
1236
- this.overlayPanel().open() ? this.close() : this.open();
1168
+ this.autocomplete().panelOpen() ? this.close() : this.open();
1237
1169
  }
1238
1170
  open() {
1239
1171
  if (!this._canOpen()) {
1240
1172
  return;
1241
1173
  }
1242
- if (this._parentFormField) {
1243
- this._preferredOverlayOrigin = this._parentFormField?.getConnectedOverlayOrigin();
1244
- }
1245
- this._overlayWidth = this._getOverlayWidth(this._preferredOverlayOrigin);
1246
- this.overlayPanel().open.set(true);
1174
+ this.autocomplete().setPanelOpen();
1247
1175
  this._keyManager?.withHorizontalOrientation(null);
1248
- this._highlightCorrectOption();
1249
- this._changeDetectorRef.markForCheck();
1176
+ // wait for opening panel...
1177
+ afterNextRender(() => {
1178
+ this._scrollOptionIntoView(this._keyManager?.activeItemIndex ?? 0);
1179
+ this._highlightCorrectOption();
1180
+ }, { injector: this._injector });
1250
1181
  }
1251
1182
  close() {
1252
- if (this.overlayPanel().open()) {
1253
- this.overlayPanel().open.set(false);
1254
- this._changeDetectorRef.markForCheck();
1255
- this._onTouched();
1183
+ if (this.autocomplete().panelOpen()) {
1184
+ this.autocomplete().panelOpen.set(false);
1185
+ this._keyManager?.withHorizontalOrientation('ltr');
1186
+ this.autocomplete().onTouched();
1256
1187
  }
1257
1188
  }
1258
1189
  clear() {
1259
- this._searchText.set('');
1260
- }
1261
- // #region ControlValueAccessor implementation
1262
- writeValue(value) {
1263
- this._setSelectionByValue(value);
1190
+ this._clearSelection();
1191
+ this._updateInputValue('');
1264
1192
  }
1265
- registerOnChange(fn) {
1266
- this._onChange = fn;
1267
- }
1268
- registerOnTouched(fn) {
1269
- this._onTouched = fn;
1193
+ removeOption(optionValue) {
1194
+ const option = this.autocomplete()
1195
+ .options()
1196
+ .find((opt) => opt.value() === optionValue.value);
1197
+ if (option) {
1198
+ this._handleOptionChange({
1199
+ source: option,
1200
+ selected: false,
1201
+ isUserInput: true,
1202
+ });
1203
+ }
1204
+ else {
1205
+ // item to be removed is NOT the current option list, but present in selection model --> deselect directly
1206
+ this._selectionModel?.deselect(optionValue);
1207
+ }
1270
1208
  }
1271
- setDisabledState(isDisabled) {
1272
- this._disabled.set(isDisabled);
1273
- this._changeDetectorRef.markForCheck();
1209
+ focus(options) {
1210
+ this._inputElement.nativeElement.focus(options);
1211
+ this.open();
1274
1212
  }
1275
- // #endregion
1276
- _setSelectionByValue(value) {
1277
- this.options().forEach((option) => {
1278
- option.setInactiveStyles();
1279
- option.selected.set(false);
1280
- });
1281
- this._selectionModel?.clear();
1282
- this._rawValue = value;
1283
- if (this.options().length === 0) {
1284
- return;
1285
- }
1286
- if (this.multiSelect() && value) {
1213
+ setSelectionByValue(value) {
1214
+ if (this.autocomplete().multiSelect() && value !== null) {
1287
1215
  if (!Array.isArray(value)) {
1288
- throw this._createHostError('value must be an array in multiple-selection mode');
1216
+ throw this.autocomplete().createHostError('value must be an array in multiple-selection mode');
1217
+ }
1218
+ else {
1219
+ value.forEach((currentValue) => this._selectValue(currentValue));
1289
1220
  }
1290
- value.forEach((currentValue) => this._selectValue(currentValue));
1291
- this._sortValues();
1292
1221
  }
1293
1222
  else {
1294
1223
  const correspondingOption = this._selectValue(value);
1295
1224
  if (correspondingOption) {
1296
1225
  this._keyManager?.updateActiveItem(correspondingOption);
1297
1226
  }
1298
- else if (!this.overlayPanel().open()) {
1227
+ else if (!this.autocomplete().panelOpen()) {
1299
1228
  this._keyManager?.updateActiveItem(-1);
1300
1229
  }
1301
1230
  }
1302
1231
  }
1303
- _selectValue(value) {
1304
- const valueCompareFn = this.valueCompareFn();
1305
- const correspondingOption = this.options().find((option) => {
1306
- if (this._selectionModel?.isSelected(option.viewValue())) {
1307
- return false;
1308
- }
1309
- try {
1310
- return valueCompareFn?.(option.value(), value);
1311
- }
1312
- catch (error) {
1313
- if (isDevMode()) {
1314
- console.warn(error);
1232
+ _handleKeydown(event) {
1233
+ if (!this._disabled() && !this._readonly()) {
1234
+ this.autocomplete().panelOpen() ? this._handleOpenedPanelKeydown(event) : this._handleClosedPanelKeydown(event);
1235
+ }
1236
+ }
1237
+ _onBlur() {
1238
+ if (!this._disabled()) {
1239
+ this.autocomplete().onTouched();
1240
+ }
1241
+ }
1242
+ _getAriaActiveDescendant() {
1243
+ if (this.autocomplete().panelOpen() && this._keyManager?.activeItem) {
1244
+ return this._keyManager.activeItem.id();
1245
+ }
1246
+ return null;
1247
+ }
1248
+ _initKeyManager() {
1249
+ this._keyManager = new ActiveDescendantKeyManager(this.autocomplete().options())
1250
+ .withVerticalOrientation()
1251
+ .withHorizontalOrientation('ltr')
1252
+ .withHomeAndEnd()
1253
+ .withPageUpDown()
1254
+ .withAllowedModifierKeys(['shiftKey'])
1255
+ .skipPredicate(this._skipPredicate);
1256
+ this._keyManager.tabOut.subscribe(() => {
1257
+ if (this.autocomplete().panelOpen()) {
1258
+ if (!this.autocomplete().multiSelect() && this._keyManager?.activeItem) {
1259
+ this._keyManager.activeItem.selectViaInteraction();
1315
1260
  }
1316
- return false;
1261
+ this.focus();
1262
+ this.close();
1263
+ }
1264
+ });
1265
+ this._keyManager.change.subscribe(() => {
1266
+ if (this.autocomplete().panelOpen()) {
1267
+ this._scrollOptionIntoView(this._keyManager?.activeItemIndex ?? 0);
1317
1268
  }
1318
1269
  });
1319
- if (correspondingOption) {
1320
- correspondingOption.selected.set(true);
1321
- this._selectionModel?.select(correspondingOption.viewValue());
1270
+ }
1271
+ _subscribeOptionChanges() {
1272
+ this.autocomplete()
1273
+ .options()
1274
+ .forEach((option) => {
1275
+ option.onSelectionChange.subscribe((change) => {
1276
+ this._handleOptionChange(change);
1277
+ });
1278
+ });
1279
+ }
1280
+ _handleOptionChange(change) {
1281
+ const { source, selected, isUserInput } = change;
1282
+ if (!this.autocomplete().multiSelect()) {
1283
+ this._clearSelection();
1284
+ }
1285
+ source.selected.set(selected);
1286
+ if (isUserInput) {
1287
+ this._keyManager?.setActiveItem(source);
1288
+ }
1289
+ if (isUserInput && !this.autocomplete().multiSelect() && this.autocomplete().panelOpen()) {
1290
+ this.close();
1291
+ }
1292
+ const optionValue = this._getAsOptionValue(source);
1293
+ if (selected) {
1294
+ this._selectionModel?.select(optionValue);
1295
+ }
1296
+ else {
1297
+ this._selectionModel?.deselect(optionValue);
1322
1298
  }
1323
- return correspondingOption;
1324
1299
  }
1325
1300
  _clearSelection() {
1326
1301
  this._selectionModel?.clear();
1327
- this.options().forEach((option) => {
1302
+ this._clearOptionsSelection();
1303
+ }
1304
+ _clearOptionsSelection() {
1305
+ this.autocomplete()
1306
+ .options()
1307
+ .forEach((option) => {
1308
+ option.setInactiveStyles();
1328
1309
  option.selected.set(false);
1329
1310
  });
1330
1311
  }
1331
- _handleChange() {
1332
- const selectionModelValues = this._selectionModel?.selected;
1333
- if (this.multiSelect()) {
1334
- this._onChange(selectionModelValues);
1312
+ _canOpen() {
1313
+ return !this._readonly() && !this._disabled();
1314
+ }
1315
+ _handleOpenedPanelKeydown(event) {
1316
+ const manager = this._keyManager;
1317
+ const key = event.key;
1318
+ const isArrowKey = key === 'ArrowDown' || key === 'ArrowUp';
1319
+ const isTyping = manager !== undefined && manager.isTyping();
1320
+ const isEscapeKey = key === 'Escape';
1321
+ if ((isArrowKey && event.altKey) || isEscapeKey) {
1322
+ event.preventDefault();
1323
+ this.close();
1324
+ }
1325
+ else if (!isTyping && (key === 'Enter' || key === ' ') && manager?.activeItem && !hasModifierKey(event)) {
1326
+ event.preventDefault();
1327
+ manager.activeItem.selectViaInteraction();
1328
+ }
1329
+ else if (!isTyping && this.autocomplete().multiSelect() && key === 'a' && event.ctrlKey) {
1330
+ event.preventDefault();
1331
+ const hasDeselectedOptions = this.autocomplete()
1332
+ .options()
1333
+ .some((opt) => !opt.disabled && !opt.selected());
1334
+ this.autocomplete()
1335
+ .options()
1336
+ .forEach((option) => {
1337
+ if (!option.disabled) {
1338
+ hasDeselectedOptions ? option.select() : option.deselect();
1339
+ }
1340
+ });
1335
1341
  }
1336
1342
  else {
1337
- this._onChange(selectionModelValues?.[0]);
1343
+ const previouslyFocusedIndex = manager?.activeItemIndex;
1344
+ manager?.onKeydown(event);
1345
+ this._scrollOptionIntoView(manager?.activeItemIndex ?? 0);
1346
+ if (this.autocomplete().multiSelect() &&
1347
+ isArrowKey &&
1348
+ event.shiftKey &&
1349
+ manager?.activeItem &&
1350
+ manager?.activeItemIndex !== previouslyFocusedIndex) {
1351
+ manager?.activeItem.selectViaInteraction();
1352
+ }
1353
+ }
1354
+ }
1355
+ _handleClosedPanelKeydown(event) {
1356
+ const manager = this._keyManager;
1357
+ const key = event.key;
1358
+ const isArrowKey = key === 'ArrowDown' || key === 'ArrowUp' || key === 'ArrowLeft' || key === 'ArrowRight';
1359
+ const isOpenKey = key === 'Enter' || key === ' ';
1360
+ const isEscapeKey = key === 'Escape';
1361
+ if ((manager && !manager.isTyping() && isOpenKey && !hasModifierKey(event)) || isArrowKey) {
1362
+ event.preventDefault();
1363
+ this.open();
1364
+ }
1365
+ else if (!this.autocomplete().multiSelect() && !isEscapeKey) {
1366
+ const previouslySelectedOption = this.selectedOptions[0];
1367
+ manager?.onKeydown(event);
1368
+ const selectedOption = this.selectedOptions[0];
1369
+ if (selectedOption?.viewValue() && previouslySelectedOption !== selectedOption) {
1370
+ this._liveAnnouncer.announce(selectedOption.viewValue(), LIVE_ANNOUNCER_DURATION);
1371
+ }
1338
1372
  }
1339
- this._changeDetectorRef.markForCheck();
1340
1373
  }
1341
1374
  _highlightCorrectOption() {
1342
1375
  if (this._keyManager) {
1343
- if (this._empty) {
1376
+ if (this._selectionModel?.isEmpty() ?? true) {
1344
1377
  let firstEnabledOptionIndex = -1;
1345
- for (let index = 0; index < this.options().length; index++) {
1346
- const option = this.options()[index];
1378
+ for (let index = 0; index < this.autocomplete().options().length; index++) {
1379
+ const option = this.autocomplete().options()[index];
1347
1380
  if (!option.disabled) {
1348
1381
  firstEnabledOptionIndex = index;
1349
1382
  break;
@@ -1353,104 +1386,182 @@ class IdsAutocompleteComponent extends IdsFormFieldControl {
1353
1386
  }
1354
1387
  else {
1355
1388
  if (this._selectionModel) {
1356
- const activeItem = this.options().find((option) => this._selectionModel?.isSelected(option.viewValue()));
1357
- if (activeItem) {
1358
- this._keyManager.setActiveItem(activeItem);
1359
- }
1389
+ this._keyManager.setActiveItem(this.selectedOptions[0]);
1360
1390
  }
1361
1391
  }
1362
1392
  }
1363
1393
  }
1364
- isOptionPreSelectedByValue(optionValue) {
1365
- if (this._rawValue === undefined) {
1366
- return false;
1367
- }
1368
- if (this.multiSelect() && Array.isArray(this._rawValue)) {
1369
- return this._rawValue.some((value) => optionValue != null && value === optionValue);
1370
- }
1371
- return optionValue === this._rawValue;
1372
- }
1373
- _onFocus() {
1374
- if (!this.disabled()) {
1375
- this._focused.set(true);
1394
+ _scrollOptionIntoView(index) {
1395
+ const option = this.autocomplete().options()[index];
1396
+ if (option !== undefined) {
1397
+ const labelCount = _countGroupLabelsBeforeOption(index, this.autocomplete().options(), this.autocomplete().optionGroups());
1398
+ const element = option.getHostElement();
1399
+ if (index === 0 || (index === 0 && labelCount === 1)) {
1400
+ this.autocomplete().setScrollTop(0);
1401
+ }
1402
+ else {
1403
+ const newScrollPosition = _getOptionScrollPosition(element.offsetTop, element.offsetHeight, this.autocomplete().getScrollTop(), this.autocomplete().panel()?.nativeElement.offsetHeight);
1404
+ this.autocomplete().setScrollTop(newScrollPosition);
1405
+ }
1376
1406
  }
1377
1407
  }
1378
- _onBlur() {
1379
- this._focused.set(false);
1380
- this._keyManager?.cancelTypeahead();
1381
- if (!this.disabled() && !this.overlayPanel().open()) {
1382
- this._onTouched();
1383
- this._changeDetectorRef.markForCheck();
1408
+ _selectValue(value) {
1409
+ const valueCompareFn = this.autocomplete().valueCompareFn();
1410
+ const correspondingOption = this.autocomplete()
1411
+ .options()
1412
+ .find((option) => {
1413
+ if (this._selectionModel && this._selectionModel.isSelected(this._getAsOptionValue(option))) {
1414
+ return false;
1415
+ }
1416
+ try {
1417
+ return valueCompareFn?.(option.value(), value);
1418
+ }
1419
+ catch (error) {
1420
+ if (isDevMode()) {
1421
+ console.warn(error);
1422
+ }
1423
+ return false;
1424
+ }
1425
+ });
1426
+ if (correspondingOption) {
1427
+ correspondingOption.selected.set(true);
1428
+ const correspondingOptionValue = this._getAsOptionValue(correspondingOption);
1429
+ this._selectionModel?.select(correspondingOptionValue);
1384
1430
  }
1431
+ return correspondingOption;
1385
1432
  }
1386
- _getAriaActiveDescendant() {
1387
- if (this.overlayPanel().open() && this._keyManager?.activeItem) {
1388
- return this._keyManager.activeItem.id();
1389
- }
1390
- return null;
1433
+ _updateCurrentSelection() {
1434
+ this._clearOptionsSelection();
1435
+ this.selectedOptions.reverse().forEach((option) => {
1436
+ option.selected.set(true);
1437
+ option.setActiveStyles();
1438
+ this._keyManager?.setActiveItem(option);
1439
+ });
1391
1440
  }
1392
- focus(options) {
1393
- this._elementRef.nativeElement.focus(options);
1441
+ _getAsOptionValue(option) {
1442
+ return { value: option.value(), viewValue: option.viewValue() };
1394
1443
  }
1395
- _onInputClick() {
1396
- if (!this._focused() && !this.readonly() && !this.disabled() && this._searchText().length) {
1397
- this.open();
1398
- }
1444
+ _updateInputValue(value) {
1445
+ const input = this._inputElement.nativeElement;
1446
+ this._renderer.setProperty(input, 'value', value);
1447
+ input.dispatchEvent(new Event('input', { bubbles: true }));
1399
1448
  }
1400
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1401
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: IdsAutocompleteComponent, isStandalone: true, selector: "ids-autocomplete[ngModel]:not([formControl]):not([formControlName]),\n ids-autocomplete[formControl]:not([ngModel]):not([formControlName]),\n ids-autocomplete[formControlName]:not([ngModel]):not([formControl])", inputs: { minChars: { classPropertyName: "minChars", publicName: "minChars", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, multiSelect: { classPropertyName: "multiSelect", publicName: "multiSelect", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelClearButton: { classPropertyName: "ariaLabelClearButton", publicName: "ariaLabelClearButton", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelToggleButton: { classPropertyName: "ariaLabelToggleButton", publicName: "ariaLabelToggleButton", isSignal: true, isRequired: false, transformFunction: null }, valueCompareFn: { classPropertyName: "valueCompareFn", publicName: "valueCompareFn", isSignal: true, isRequired: false, transformFunction: null }, sortCompareFn: { classPropertyName: "sortCompareFn", publicName: "sortCompareFn", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, typeaheadDebounceInterval: { classPropertyName: "typeaheadDebounceInterval", publicName: "typeaheadDebounceInterval", isSignal: true, isRequired: false, transformFunction: null }, hintLoading: { classPropertyName: "hintLoading", publicName: "hintLoading", isSignal: true, isRequired: false, transformFunction: null }, hintNoResults: { classPropertyName: "hintNoResults", publicName: "hintNoResults", isSignal: true, isRequired: false, transformFunction: null }, hintMinChars: { classPropertyName: "hintMinChars", publicName: "hintMinChars", isSignal: true, isRequired: false, transformFunction: null }, hintMaxLength: { classPropertyName: "hintMaxLength", publicName: "hintMaxLength", isSignal: true, isRequired: false, transformFunction: null }, panelClasses: { classPropertyName: "panelClasses", publicName: "panelClasses", isSignal: true, isRequired: false, transformFunction: null }, _searchText: { classPropertyName: "_searchText", publicName: "_searchText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { _searchText: "_searchTextChange" }, host: { attributes: { "role": "combobox", "aria-autocomplete": "list", "aria-haspopup": "listbox" }, listeners: { "keydown": "_handleKeydown($event)", "focus": "focus()", "blur": "_onBlur()" }, properties: { "attr.tabindex": "disabled() ? -1 : tabIndex()", "attr.aria-controls": "overlayPanel().open() ? id() + \"-panel\" : null", "attr.aria-owns": "overlayPanel().open() ? id() + \"-panel\" : null", "attr.aria-expanded": "overlayPanel().open()", "attr.aria-label": "ariaLabel() || null", "attr.aria-labelledby": "ariaLabelledby() || null", "attr.aria-required": "required().toString()", "attr.aria-disabled": "disabled().toString()", "attr.aria-invalid": "hasErrorState()", "attr.aria-activedescendant": "_getAriaActiveDescendant()" } }, providers: [
1402
- { provide: IDS_FORM_FIELD_CONTROL, useExisting: IdsAutocompleteComponent },
1403
- { provide: IDS_OPTION_PARENT_COMPONENT, useExisting: IdsAutocompleteComponent },
1404
- {
1405
- provide: NG_VALUE_ACCESSOR,
1406
- useExisting: forwardRef(() => IdsAutocompleteComponent),
1407
- multi: true,
1408
- },
1409
- ], viewQueries: [{ propertyName: "options", predicate: IdsOptionComponent, descendants: true, isSignal: true }, { propertyName: "overlayPanel", first: true, predicate: IdsOverlayPanelComponent, descendants: true, isSignal: true }, { propertyName: "_panel", first: true, predicate: ["overlay"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_inputElemment", first: true, predicate: ["fallbackOverlayOrigin"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@let isLoading = _resource.isLoading();\n@let optionsLength = _resource.value().length;\n@let maxOptionsLength = maxLength();\n\n<input\n #fallbackOverlayOrigin=\"cdkOverlayOrigin\"\n cdkOverlayOrigin\n idsInput\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [required]=\"false\"\n [(ngModel)]=\"_searchText\"\n (click)=\"_onInputClick()\"\n (blur)=\"_onBlur()\"\n/>\n@if (_searchText().length > 0) {\n <div idsFormFieldAction>\n <button\n type=\"button\"\n idsIconButton\n appearance=\"standard\"\n variant=\"surface\"\n size=\"dense\"\n [attr.aria-label]=\"ariaLabelClearButton()\"\n [idsTooltip]=\"ariaLabelClearButton()\"\n [idsTooltipDisabled]=\"!ariaLabelClearButton() || disabled()\"\n [idsTooltipIgnoreClipped]=\"true\"\n [disabled]=\"disabled()\"\n (click)=\"clear()\"\n >\n <ids-icon alt=\"\" aria-hidden=\"true\" fontIcon=\"close\" />\n </button>\n </div>\n}\n@if (!isLoading && optionsLength > 0) {\n <div idsFormFieldAction>\n <button\n type=\"button\"\n idsIconButton\n appearance=\"standard\"\n variant=\"surface\"\n size=\"dense\"\n [attr.aria-label]=\"ariaLabelToggleButton()\"\n [idsTooltip]=\"ariaLabelToggleButton()\"\n [idsTooltipDisabled]=\"!ariaLabelToggleButton() || disabled()\"\n [idsTooltipIgnoreClipped]=\"true\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\"\n >\n <ids-icon alt=\"\" aria-hidden=\"true\" [fontIcon]=\"overlay.open() ? 'chevron-up' : 'chevron-down'\" />\n </button>\n </div>\n}\n@if (isLoading) {\n <div idsFormFieldAction>\n <ids-spinner sizeCollection=\"small\" size=\"compact\" variant=\"surface\" [isTrack]=\"true\" [aria-label]=\"hintLoading()\" />\n </div>\n}\n<ids-overlay-panel\n #overlay\n variant=\"light\"\n [id]=\"id() + '-panel'\"\n [origin]=\"_preferredOverlayOrigin || fallbackOverlayOrigin\"\n [size]=\"parentSize()\"\n [width]=\"_overlayWidth\"\n [panelClasses]=\"_panelClasses()\"\n>\n @let showHintLoading = isLoading;\n @let showHintMinChars = _searchText().length < minChars();\n @let showHintMaxLength = maxOptionsLength && optionsLength > maxOptionsLength;\n @let showHintNoResults = optionsLength === 0;\n\n @if (showHintLoading || showHintMinChars || showHintMaxLength || showHintNoResults) {\n <div class=\"ids-overlay-panel__autocomplete-message\">\n <ids-option disabled>\n @if (showHintLoading && !showHintMinChars) {\n {{ hintLoading() }}\n } @else if (showHintMinChars) {\n {{ hintMinChars() }}\n } @else if (showHintMaxLength) {\n {{ hintMaxLength() }}\n } @else if (showHintNoResults) {\n {{ hintNoResults() }}\n }\n </ids-option>\n </div>\n } @else {\n @for (option of _resource.value(); track $index) {\n <ids-option [value]=\"option\">{{ option }}</ids-option>\n }\n }\n</ids-overlay-panel>\n", dependencies: [{ kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: IdsFormFieldActionDirective, selector: "[idsFormFieldAction]" }, { kind: "directive", type: IdsInputDirective, selector: "input[idsInput][ngModel]:not([formControl]):not([formControlName]),\n input[idsInput][formControl]:not([ngModel]):not([formControlName]),\n input[idsInput][formControlName]:not([ngModel]):not([formControl]),\n textarea[idsInput][ngModel]:not([formControl]):not([formControlName]),\n textarea[idsInput][formControl]:not([ngModel]):not([formControlName]),\n textarea[idsInput][formControlName]:not([ngModel]):not([formControl])", inputs: ["name", "type", "errorStateMatcher", "successStateMatcher"], exportAs: ["idsInput"] }, { kind: "component", type: IdsIconComponent, selector: "ids-icon", inputs: ["size", "sizeCollection", "variant", "fontIcon", "svgIcon", "aria-hidden"] }, { kind: "component", type: IdsIconButtonComponent, selector: "button[idsIconButton], a[idsIconButton]", inputs: ["appearance", "size", "variant", "disabled", "allowCustomContent"] }, { kind: "component", type: IdsOverlayPanelComponent, selector: "ids-overlay-panel", inputs: ["open", "origin", "positions", "appearance", "size", "variant", "panelClasses", "width"], outputs: ["openChange"] }, { kind: "component", type: IdsOptionComponent, selector: "ids-option", inputs: ["value", "viewValue", "disabled"], outputs: ["onSelectionChange"] }, { kind: "component", type: IdsSpinnerComponent, selector: "ids-spinner", inputs: ["size", "sizeCollection", "variant", "isTrack", "aria-label"] }, { kind: "directive", type: IdsTooltipDirective, selector: "[idsTooltip]", inputs: ["idsTooltip", "idsTooltipPosition", "idsTooltipSize", "idsTooltipVariant", "idsTooltipShowDelay", "idsTooltipHideDelay", "idsTooltipDisabled", "idsTooltipTouchGestures", "idsTooltipTextAlign", "idsTooltipClass", "idsTooltipShowPointer", "idsTooltipIgnoreClipped"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1449
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1450
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: IdsAutocompleteTriggerDirective, isStandalone: true, selector: "input[idsAutocompleteTriggerFor]", inputs: { autocomplete: { classPropertyName: "autocomplete", publicName: "idsAutocompleteTriggerFor", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "keydown": "_handleKeydown($event)", "focus": "focus()", "blur": "_onBlur()" }, properties: { "attr.role": "_disabled() ? null : \"combobox\"", "attr.autocomplete": "_disabled() ? \"off\" : \"auto\"", "attr.aria-autocomplete": "_disabled() ? null : \"list\"", "attr.aria-activedescendant": "_getAriaActiveDescendant()", "attr.aria-owns": "autocomplete().panelOpen() ? autocomplete().id() + \"-panel\" : null", "attr.aria-expanded": "_disabled() ? null : autocomplete().panelOpen().toString()", "attr.aria-controls": "(_disabled() || !autocomplete().panelOpen()) ? null : autocomplete()?.id()", "attr.aria-haspopup": "_disabled() ? null : \"listbox\"", "attr.tabindex": "_disabled() ? -1 : autocomplete().tabIndex()", "attr.aria-required": "autocomplete().required().toString()", "attr.aria-disabled": "_disabled().toString()", "attr.aria-invalid": "autocomplete().hasErrorState()", "attr.readonly": "_readonly() ? \"true\" : null", "disabled": "_disabled()" }, classAttribute: "ids-form-field-control" }, exportAs: ["idsAutocompleteTrigger"], ngImport: i0 }); }
1410
1451
  }
1411
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteComponent, decorators: [{
1412
- type: Component,
1413
- args: [{ selector: `ids-autocomplete[ngModel]:not([formControl]):not([formControlName]),
1414
- ids-autocomplete[formControl]:not([ngModel]):not([formControlName]),
1415
- ids-autocomplete[formControlName]:not([ngModel]):not([formControl])`, imports: [
1416
- CdkOverlayOrigin,
1417
- FormsModule,
1418
- IdsFormFieldActionDirective,
1419
- IdsInputDirective,
1420
- IdsIconComponent,
1421
- IdsIconButtonComponent,
1422
- IdsOverlayPanelComponent,
1423
- IdsOptionComponent,
1424
- IdsSpinnerComponent,
1425
- IdsTooltipDirective,
1426
- ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
1427
- { provide: IDS_FORM_FIELD_CONTROL, useExisting: IdsAutocompleteComponent },
1428
- { provide: IDS_OPTION_PARENT_COMPONENT, useExisting: IdsAutocompleteComponent },
1429
- {
1430
- provide: NG_VALUE_ACCESSOR,
1431
- useExisting: forwardRef(() => IdsAutocompleteComponent),
1432
- multi: true,
1433
- },
1434
- ], host: {
1435
- role: 'combobox',
1436
- 'aria-autocomplete': 'list',
1437
- 'aria-haspopup': 'listbox',
1438
- '[attr.tabindex]': 'disabled() ? -1 : tabIndex()',
1439
- '[attr.aria-controls]': 'overlayPanel().open() ? id() + "-panel" : null',
1440
- '[attr.aria-owns]': 'overlayPanel().open() ? id() + "-panel" : null',
1441
- '[attr.aria-expanded]': 'overlayPanel().open()',
1442
- '[attr.aria-label]': 'ariaLabel() || null',
1443
- '[attr.aria-labelledby]': 'ariaLabelledby() || null',
1444
- '[attr.aria-required]': 'required().toString()',
1445
- '[attr.aria-disabled]': 'disabled().toString()',
1446
- '[attr.aria-invalid]': 'hasErrorState()',
1452
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteTriggerDirective, decorators: [{
1453
+ type: Directive,
1454
+ args: [{
1455
+ selector: 'input[idsAutocompleteTriggerFor]',
1456
+ host: {
1457
+ class: 'ids-form-field-control',
1458
+ '[attr.role]': '_disabled() ? null : "combobox"',
1459
+ '[attr.autocomplete]': '_disabled() ? "off" : "auto"',
1460
+ '[attr.aria-autocomplete]': '_disabled() ? null : "list"',
1447
1461
  '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',
1462
+ '[attr.aria-owns]': 'autocomplete().panelOpen() ? autocomplete().id() + "-panel" : null',
1463
+ '[attr.aria-expanded]': '_disabled() ? null : autocomplete().panelOpen().toString()',
1464
+ '[attr.aria-controls]': '(_disabled() || !autocomplete().panelOpen()) ? null : autocomplete()?.id()',
1465
+ '[attr.aria-haspopup]': '_disabled() ? null : "listbox"',
1466
+ '[attr.tabindex]': '_disabled() ? -1 : autocomplete().tabIndex()',
1467
+ '[attr.aria-required]': 'autocomplete().required().toString()',
1468
+ '[attr.aria-disabled]': '_disabled().toString()',
1469
+ '[attr.aria-invalid]': 'autocomplete().hasErrorState()',
1470
+ '[attr.readonly]': '_readonly() ? "true" : null',
1471
+ '[disabled]': '_disabled()',
1448
1472
  '(keydown)': '_handleKeydown($event)',
1449
1473
  '(focus)': 'focus()',
1450
1474
  '(blur)': '_onBlur()',
1451
- }, template: "@let isLoading = _resource.isLoading();\n@let optionsLength = _resource.value().length;\n@let maxOptionsLength = maxLength();\n\n<input\n #fallbackOverlayOrigin=\"cdkOverlayOrigin\"\n cdkOverlayOrigin\n idsInput\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [required]=\"false\"\n [(ngModel)]=\"_searchText\"\n (click)=\"_onInputClick()\"\n (blur)=\"_onBlur()\"\n/>\n@if (_searchText().length > 0) {\n <div idsFormFieldAction>\n <button\n type=\"button\"\n idsIconButton\n appearance=\"standard\"\n variant=\"surface\"\n size=\"dense\"\n [attr.aria-label]=\"ariaLabelClearButton()\"\n [idsTooltip]=\"ariaLabelClearButton()\"\n [idsTooltipDisabled]=\"!ariaLabelClearButton() || disabled()\"\n [idsTooltipIgnoreClipped]=\"true\"\n [disabled]=\"disabled()\"\n (click)=\"clear()\"\n >\n <ids-icon alt=\"\" aria-hidden=\"true\" fontIcon=\"close\" />\n </button>\n </div>\n}\n@if (!isLoading && optionsLength > 0) {\n <div idsFormFieldAction>\n <button\n type=\"button\"\n idsIconButton\n appearance=\"standard\"\n variant=\"surface\"\n size=\"dense\"\n [attr.aria-label]=\"ariaLabelToggleButton()\"\n [idsTooltip]=\"ariaLabelToggleButton()\"\n [idsTooltipDisabled]=\"!ariaLabelToggleButton() || disabled()\"\n [idsTooltipIgnoreClipped]=\"true\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\"\n >\n <ids-icon alt=\"\" aria-hidden=\"true\" [fontIcon]=\"overlay.open() ? 'chevron-up' : 'chevron-down'\" />\n </button>\n </div>\n}\n@if (isLoading) {\n <div idsFormFieldAction>\n <ids-spinner sizeCollection=\"small\" size=\"compact\" variant=\"surface\" [isTrack]=\"true\" [aria-label]=\"hintLoading()\" />\n </div>\n}\n<ids-overlay-panel\n #overlay\n variant=\"light\"\n [id]=\"id() + '-panel'\"\n [origin]=\"_preferredOverlayOrigin || fallbackOverlayOrigin\"\n [size]=\"parentSize()\"\n [width]=\"_overlayWidth\"\n [panelClasses]=\"_panelClasses()\"\n>\n @let showHintLoading = isLoading;\n @let showHintMinChars = _searchText().length < minChars();\n @let showHintMaxLength = maxOptionsLength && optionsLength > maxOptionsLength;\n @let showHintNoResults = optionsLength === 0;\n\n @if (showHintLoading || showHintMinChars || showHintMaxLength || showHintNoResults) {\n <div class=\"ids-overlay-panel__autocomplete-message\">\n <ids-option disabled>\n @if (showHintLoading && !showHintMinChars) {\n {{ hintLoading() }}\n } @else if (showHintMinChars) {\n {{ hintMinChars() }}\n } @else if (showHintMaxLength) {\n {{ hintMaxLength() }}\n } @else if (showHintNoResults) {\n {{ hintNoResults() }}\n }\n </ids-option>\n </div>\n } @else {\n @for (option of _resource.value(); track $index) {\n <ids-option [value]=\"option\">{{ option }}</ids-option>\n }\n }\n</ids-overlay-panel>\n" }]
1475
+ },
1476
+ exportAs: 'idsAutocompleteTrigger',
1477
+ }]
1452
1478
  }], ctorParameters: () => [] });
1453
1479
 
1480
+ class IdsAutocompleteChipListComponent {
1481
+ constructor() {
1482
+ this.autocompleteTrigger = input.required(...(ngDevMode ? [{ debugName: "autocompleteTrigger", alias: 'for' }] : [{ alias: 'for' }]));
1483
+ this.options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
1484
+ this.appearance = input(IdsChipAppearance.OUTLINED, ...(ngDevMode ? [{ debugName: "appearance" }] : []));
1485
+ this.size = input(IdsSize.COMPACT, ...(ngDevMode ? [{ debugName: "size" }] : []));
1486
+ this.variant = input(IdsChipVariant.SURFACE, ...(ngDevMode ? [{ debugName: "variant" }] : []));
1487
+ }
1488
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteChipListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1489
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: IdsAutocompleteChipListComponent, isStandalone: true, selector: "ids-autocomplete-chip-list", inputs: { autocompleteTrigger: { classPropertyName: "autocompleteTrigger", publicName: "for", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ids-autocomplete-chip-list" }, ngImport: i0, template: `
1490
+ @for (option of autocompleteTrigger().selected; track $index) {
1491
+ <button
1492
+ idsChip
1493
+ type="button"
1494
+ [appearance]="appearance()"
1495
+ [size]="size()"
1496
+ [variant]="variant()"
1497
+ [disabled]="autocompleteTrigger().autocomplete().disabled()"
1498
+ [removable]="true"
1499
+ (removed)="autocompleteTrigger().removeOption(option)"
1500
+ >
1501
+ {{ option.viewValue }}
1502
+ </button>
1503
+ }
1504
+ `, isInline: true, dependencies: [{ kind: "component", type: IdsChipComponent, selector: "ids-chip, button[idsChip]", inputs: ["removable", "appearance", "size", "variant", "disabled", "tabIndex"], outputs: ["removed"] }] }); }
1505
+ }
1506
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteChipListComponent, decorators: [{
1507
+ type: Component,
1508
+ args: [{
1509
+ selector: 'ids-autocomplete-chip-list',
1510
+ host: {
1511
+ class: 'ids-autocomplete-chip-list',
1512
+ },
1513
+ imports: [IdsChipComponent],
1514
+ template: `
1515
+ @for (option of autocompleteTrigger().selected; track $index) {
1516
+ <button
1517
+ idsChip
1518
+ type="button"
1519
+ [appearance]="appearance()"
1520
+ [size]="size()"
1521
+ [variant]="variant()"
1522
+ [disabled]="autocompleteTrigger().autocomplete().disabled()"
1523
+ [removable]="true"
1524
+ (removed)="autocompleteTrigger().removeOption(option)"
1525
+ >
1526
+ {{ option.viewValue }}
1527
+ </button>
1528
+ }
1529
+ `,
1530
+ }]
1531
+ }] });
1532
+
1533
+ class IdsAutocompleteHintComponent {
1534
+ constructor() {
1535
+ this.variant = input(IdsMessageVariant.SURFACE, ...(ngDevMode ? [{ debugName: "variant" }] : []));
1536
+ this.size = input(IdsSize.COMFORTABLE, ...(ngDevMode ? [{ debugName: "size" }] : []));
1537
+ }
1538
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteHintComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1539
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.7", type: IdsAutocompleteHintComponent, isStandalone: true, selector: "ids-autocomplete-hint", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ids-autocomplete-hint" }, ngImport: i0, template: `
1540
+ <div class="ids-autocomplete-hint__wrapper">
1541
+ <ids-hint-message [size]="size()" [variant]="variant()">
1542
+ <ng-content />
1543
+ </ids-hint-message>
1544
+ </div>
1545
+ `, isInline: true, dependencies: [{ kind: "component", type: IdsHintMessageComponent, selector: "ids-hint-message" }] }); }
1546
+ }
1547
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsAutocompleteHintComponent, decorators: [{
1548
+ type: Component,
1549
+ args: [{
1550
+ selector: 'ids-autocomplete-hint',
1551
+ host: {
1552
+ class: 'ids-autocomplete-hint',
1553
+ },
1554
+ imports: [IdsHintMessageComponent],
1555
+ template: `
1556
+ <div class="ids-autocomplete-hint__wrapper">
1557
+ <ids-hint-message [size]="size()" [variant]="variant()">
1558
+ <ng-content />
1559
+ </ids-hint-message>
1560
+ </div>
1561
+ `,
1562
+ }]
1563
+ }] });
1564
+
1454
1565
  class IdsFieldsetRowComponent extends ComponentBase {
1455
1566
  constructor() {
1456
1567
  super(...arguments);
@@ -1467,6 +1578,119 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
1467
1578
  args: [{ selector: 'ids-fieldset-row', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />\n" }]
1468
1579
  }] });
1469
1580
 
1581
+ const IDS_INPUT_DEFAULT_CONFIG = new InjectionToken('IDS_INPUT_DEFAULT_CONFIG', {
1582
+ providedIn: 'root',
1583
+ factory: IDS_INPUT_DEFAULT_CONFIG_FACTORY,
1584
+ });
1585
+ function IDS_INPUT_DEFAULT_CONFIG_FACTORY() {
1586
+ return {
1587
+ errorStateMatcher: ErrorStateMatcher,
1588
+ successStateMatcher: SuccessStateMatcher,
1589
+ };
1590
+ }
1591
+
1592
+ const defaultConfig = IDS_INPUT_DEFAULT_CONFIG_FACTORY();
1593
+ const IDS_INPUT_INVALID_TYPES = [
1594
+ 'button',
1595
+ 'checkbox',
1596
+ 'file',
1597
+ 'hidden',
1598
+ 'image',
1599
+ 'radio',
1600
+ 'range',
1601
+ 'reset',
1602
+ 'submit',
1603
+ ];
1604
+ class IdsInputDirective extends IdsFormFieldControl {
1605
+ constructor() {
1606
+ super(...arguments);
1607
+ this._elementRef = inject(ElementRef);
1608
+ this._defaultConfig = this._getDefaultConfig(defaultConfig, IDS_INPUT_DEFAULT_CONFIG);
1609
+ this._focused = false;
1610
+ this.name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
1611
+ this.type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : []));
1612
+ this.errorStateMatcher = input(inject(this._defaultConfig.errorStateMatcher), ...(ngDevMode ? [{ debugName: "errorStateMatcher" }] : []));
1613
+ this.successStateMatcher = input(inject(this._defaultConfig.successStateMatcher), ...(ngDevMode ? [{ debugName: "successStateMatcher" }] : []));
1614
+ this._hostClasses = computed(() => this._getHostClasses([], [formFieldControlClass]), ...(ngDevMode ? [{ debugName: "_hostClasses" }] : []));
1615
+ this._validateTypeEffect = effect(() => {
1616
+ this._validateType(this.type());
1617
+ }, ...(ngDevMode ? [{ debugName: "_validateTypeEffect" }] : []));
1618
+ /**
1619
+ * Should be an arrow function in order to handle `this` outside of this class
1620
+ */
1621
+ this.onContainerClick = () => {
1622
+ if (!this._focused && !this.readonly() && !this.disabled) {
1623
+ this.focus();
1624
+ }
1625
+ };
1626
+ }
1627
+ get _hostName() {
1628
+ return 'input';
1629
+ }
1630
+ ngAfterViewInit() {
1631
+ queueMicrotask(() => {
1632
+ const control = this.ngControl()?.control;
1633
+ if (control) {
1634
+ this._disabled.set(control.status === 'DISABLED');
1635
+ control.events.pipe(takeUntilDestroyed(this._destroyRef)).subscribe((event) => this.updateControlState(event));
1636
+ }
1637
+ });
1638
+ }
1639
+ _validateType(type) {
1640
+ if (isDevMode() && IDS_INPUT_INVALID_TYPES.indexOf(type) > -1) {
1641
+ throw this._createHostError(`Input type ${type} is not supportedby idsInput`);
1642
+ }
1643
+ }
1644
+ focus(options) {
1645
+ this._elementRef.nativeElement.focus(options);
1646
+ }
1647
+ _focusChanged(isFocused) {
1648
+ if (isFocused !== this._focused) {
1649
+ this._focused = isFocused;
1650
+ }
1651
+ }
1652
+ updateControlState(event) {
1653
+ this._errorStateTracker?.updateErrorState();
1654
+ this._successStateTracker?.updateSuccessState();
1655
+ if (event instanceof StatusChangeEvent) {
1656
+ this._disabled.set(event.status === 'DISABLED');
1657
+ }
1658
+ }
1659
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsInputDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1660
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: IdsInputDirective, isStandalone: true, selector: "input[idsInput][ngModel]:not([formControl]):not([formControlName]),\n input[idsInput][formControl]:not([ngModel]):not([formControlName]),\n input[idsInput][formControlName]:not([ngModel]):not([formControl]),\n textarea[idsInput][ngModel]:not([formControl]):not([formControlName]),\n textarea[idsInput][formControl]:not([ngModel]):not([formControlName]),\n textarea[idsInput][formControlName]:not([ngModel]):not([formControl])", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, errorStateMatcher: { classPropertyName: "errorStateMatcher", publicName: "errorStateMatcher", isSignal: true, isRequired: false, transformFunction: null }, successStateMatcher: { classPropertyName: "successStateMatcher", publicName: "successStateMatcher", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focus": "_focusChanged(true)", "blur": "_focusChanged(false)" }, properties: { "attr.placeholder": "placeholder()", "attr.disabled": "disabled() ? \"\" : null", "attr.readonly": "readonly() ? \"\" : null" } }, providers: [
1661
+ {
1662
+ provide: IDS_FORM_FIELD_CONTROL,
1663
+ useExisting: IdsInputDirective,
1664
+ },
1665
+ ], exportAs: ["idsInput"], usesInheritance: true, ngImport: i0 }); }
1666
+ }
1667
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: IdsInputDirective, decorators: [{
1668
+ type: Directive,
1669
+ args: [{
1670
+ selector: `input[idsInput][ngModel]:not([formControl]):not([formControlName]),
1671
+ input[idsInput][formControl]:not([ngModel]):not([formControlName]),
1672
+ input[idsInput][formControlName]:not([ngModel]):not([formControl]),
1673
+ textarea[idsInput][ngModel]:not([formControl]):not([formControlName]),
1674
+ textarea[idsInput][formControl]:not([ngModel]):not([formControlName]),
1675
+ textarea[idsInput][formControlName]:not([ngModel]):not([formControl])`,
1676
+ exportAs: 'idsInput',
1677
+ standalone: true,
1678
+ providers: [
1679
+ {
1680
+ provide: IDS_FORM_FIELD_CONTROL,
1681
+ useExisting: IdsInputDirective,
1682
+ },
1683
+ ],
1684
+ host: {
1685
+ '[attr.placeholder]': 'placeholder()',
1686
+ '[attr.disabled]': 'disabled() ? "" : null',
1687
+ '[attr.readonly]': 'readonly() ? "" : null',
1688
+ '(focus)': '_focusChanged(true)',
1689
+ '(blur)': '_focusChanged(false)',
1690
+ },
1691
+ }]
1692
+ }] });
1693
+
1470
1694
  const Message = {
1471
1695
  HINT: 'hint',
1472
1696
  ERROR: 'error',
@@ -1518,5 +1742,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
1518
1742
  * Generated bundle index. Do not edit.
1519
1743
  */
1520
1744
 
1521
- export { AbstractErrorStateMatcher, AbstractSuccessStateMatcher, ErrorStateMatcher, ErrorStateTracker, IDS_AUTOCOMPLETE_DEFAULT_CONFIG, IDS_AUTOCOMPLETE_DEFAULT_CONFIG_FACTORY, IDS_AUTOCOMPLETE_LOADER, IDS_FIELDSET_DEFAULT_CONFIG, IDS_FIELDSET_DEFAULT_CONFIG_FACTORY, IDS_FORM_FIELD_CONTROL, IDS_FORM_FIELD_DEFAULT_CONFIG, IDS_FORM_FIELD_DEFAULT_CONFIG_FACTORY, IDS_INPUT_DEFAULT_CONFIG, IDS_INPUT_DEFAULT_CONFIG_FACTORY, IDS_MESSAGE_DEFAULT_CONFIG, IDS_MESSAGE_DEFAULT_CONFIG_FACTORY, IDS_OPTION_GROUP, IDS_OPTION_PARENT_COMPONENT, IDS_PSEUDO_CHECKBOX_PARENT, IdsAutocompleteComponent, IdsErrorDefinitionDirective, IdsErrorMessageComponent, IdsFieldsetComponent, IdsFieldsetMessageDirective, IdsFieldsetRowComponent, IdsFormFieldActionDirective, IdsFormFieldComponent, IdsFormFieldControl, IdsFormFieldVariant, IdsHintMessageComponent, IdsInputDirective, IdsLabelDirective, IdsMessageDirective, IdsMessagePrefixDirective, IdsMessageSuffixDirective, IdsMessageVariant, IdsOptionComponent, IdsOptionGroupComponent, IdsOptionSelectionChange, IdsPrefixDirective, IdsPseudoCheckboxState, IdsSuccessMessageComponent, IdsSuffixDirective, IdsValidators, Message, PseudoCheckboxComponent, SuccessStateMatcher, SuccessStateTracker, _countGroupLabelsBeforeOption, _getOptionScrollPosition, formFieldControlClass, requiredFalseValidator, requiredTrueValidator, requiredValidator };
1745
+ export { AbstractErrorStateMatcher, AbstractSuccessStateMatcher, ErrorStateMatcher, ErrorStateTracker, IDS_AUTOCOMPLETE_DEFAULT_CONFIG, IDS_AUTOCOMPLETE_DEFAULT_CONFIG_FACTORY, IDS_FIELDSET_DEFAULT_CONFIG, IDS_FIELDSET_DEFAULT_CONFIG_FACTORY, IDS_FORM_FIELD_CONTROL, IDS_FORM_FIELD_DEFAULT_CONFIG, IDS_FORM_FIELD_DEFAULT_CONFIG_FACTORY, IDS_INPUT_DEFAULT_CONFIG, IDS_INPUT_DEFAULT_CONFIG_FACTORY, IDS_MESSAGE_DEFAULT_CONFIG, IDS_MESSAGE_DEFAULT_CONFIG_FACTORY, IDS_OPTION_GROUP, IDS_OPTION_PARENT_COMPONENT, IDS_PSEUDO_CHECKBOX_PARENT, IdsAutocompleteChipListComponent, IdsAutocompleteComponent, IdsAutocompleteHintComponent, IdsAutocompleteTriggerDirective, IdsErrorDefinitionDirective, IdsErrorMessageComponent, IdsFieldsetComponent, IdsFieldsetMessageDirective, IdsFieldsetRowComponent, IdsFormFieldActionDirective, IdsFormFieldComponent, IdsFormFieldControl, IdsFormFieldVariant, IdsHintMessageComponent, IdsInputDirective, IdsLabelDirective, IdsMessageDirective, IdsMessagePrefixDirective, IdsMessageSuffixDirective, IdsMessageVariant, IdsOptionComponent, IdsOptionGroupComponent, IdsOptionSelectionChange, IdsPrefixDirective, IdsPseudoCheckboxState, IdsSuccessMessageComponent, IdsSuffixDirective, IdsValidators, Message, PseudoCheckboxComponent, SuccessStateMatcher, SuccessStateTracker, _countGroupLabelsBeforeOption, _getOptionScrollPosition, formFieldControlClass, requiredFalseValidator, requiredTrueValidator, requiredValidator };
1522
1746
  //# sourceMappingURL=i-cell-ids-angular-forms.mjs.map