@ethlete/cdk 2.5.0 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/esm2022/lib/components/forms/components/select/components/combobox/components/combobox/combobox.component.mjs +193 -263
  3. package/esm2022/lib/components/forms/components/select/components/select/directives/select/select.directive.mjs +7 -1
  4. package/esm2022/lib/components/forms/components/select/components/select-field/select-field.component.mjs +8 -5
  5. package/esm2022/lib/components/forms/components/select/directives/index.mjs +2 -0
  6. package/esm2022/lib/components/forms/components/select/directives/public-api.mjs +2 -0
  7. package/esm2022/lib/components/forms/components/select/directives/select-field/public-api.mjs +2 -0
  8. package/esm2022/lib/components/forms/components/select/directives/select-field/select-field.directive.mjs +21 -0
  9. package/esm2022/lib/components/forms/components/select/public-api.mjs +2 -1
  10. package/fesm2022/ethlete-cdk.mjs +216 -264
  11. package/fesm2022/ethlete-cdk.mjs.map +1 -1
  12. package/lib/components/forms/components/select/components/combobox/components/combobox/combobox.component.d.ts +10 -31
  13. package/lib/components/forms/components/select/components/select/directives/select/select.directive.d.ts +1 -0
  14. package/lib/components/forms/components/select/components/select-field/select-field.component.d.ts +5 -4
  15. package/lib/components/forms/components/select/directives/index.d.ts +1 -0
  16. package/lib/components/forms/components/select/directives/public-api.d.ts +1 -0
  17. package/lib/components/forms/components/select/directives/select-field/public-api.d.ts +1 -0
  18. package/lib/components/forms/components/select/directives/select-field/select-field.directive.d.ts +8 -0
  19. package/lib/components/forms/components/select/public-api.d.ts +1 -0
  20. package/package.json +2 -2
@@ -5,8 +5,8 @@ import { AsyncPipe, NgIf, NgClass, NgTemplateOutlet, NgForOf, JsonPipe, NgFor, D
5
5
  import * as i0 from '@angular/core';
6
6
  import { Component, ViewEncapsulation, ChangeDetectionStrategy, Directive, InjectionToken, Input, ContentChild, ContentChildren, inject, ElementRef, Injector, HostBinding, isDevMode, Injectable, TemplateRef, ViewContainerRef, forwardRef, ViewChild, EventEmitter, Output, Optional, Inject, SkipSelf, HostListener, ChangeDetectorRef, Renderer2, Attribute } from '@angular/core';
7
7
  import * as i1$1 from '@ethlete/core';
8
- import { LetDirective, createDestroy, ScrollObserverFirstElementDirective, ScrollObserverLastElementDirective, Memo, createReactiveBindings, IS_EMAIL, MUST_MATCH, IS_ARRAY_NOT_EMPTY, equal, ResizeObserverService, createFlipAnimation, ClickOutsideDirective, ANIMATED_LIFECYCLE_TOKEN, AnimatedLifecycleDirective, clone, AnimatedOverlayDirective, ObserveContentDirective, clamp, nextFrame, DELAYABLE_TOKEN, ObserveResizeDirective, SmartBlockScrollStrategy, RouterStateService, ClickObserverService, FocusVisibleService, scrollToElement, IS_ACTIVE_ELEMENT, CursorDragScrollDirective, ObserveScrollStateDirective, ScrollObserverIgnoreTargetDirective, TypedQueryList } from '@ethlete/core';
9
- import { BehaviorSubject, startWith, map, switchMap, combineLatest, pairwise, tap, takeUntil, skip, of, Subject, debounceTime, filter, distinctUntilChanged, withLatestFrom, shareReplay, catchError, throwError, firstValueFrom, fromEvent, merge, take, timer, skipUntil, defer, Subscription, Observable } from 'rxjs';
8
+ import { LetDirective, createDestroy, ScrollObserverFirstElementDirective, ScrollObserverLastElementDirective, Memo, createReactiveBindings, IS_EMAIL, MUST_MATCH, IS_ARRAY_NOT_EMPTY, equal, ResizeObserverService, createFlipAnimation, ClickOutsideDirective, ANIMATED_LIFECYCLE_TOKEN, AnimatedLifecycleDirective, RuntimeError, AnimatedOverlayDirective, SelectionModel, ObserveContentDirective, clamp, nextFrame, DELAYABLE_TOKEN, ObserveResizeDirective, SmartBlockScrollStrategy, RouterStateService, ClickObserverService, FocusVisibleService, scrollToElement, IS_ACTIVE_ELEMENT, CursorDragScrollDirective, ObserveScrollStateDirective, ScrollObserverIgnoreTargetDirective, TypedQueryList } from '@ethlete/core';
9
+ import { BehaviorSubject, startWith, map, switchMap, combineLatest, pairwise, tap, takeUntil, skip, of, Subject, debounceTime, filter, distinctUntilChanged, withLatestFrom, skipWhile, catchError, throwError, firstValueFrom, fromEvent, merge, take, timer, skipUntil, defer, Subscription, Observable } from 'rxjs';
10
10
  import { trigger, state, style, transition, animate } from '@angular/animations';
11
11
  import { __decorate, __metadata } from 'tslib';
12
12
  import { extractQuery, isQueryStateLoading, isQueryStateSuccess, isQueryStateFailure, QueryDirective } from '@ethlete/query';
@@ -14,7 +14,7 @@ import * as i1$2 from '@angular/cdk/a11y';
14
14
  import { FocusMonitor, LiveAnnouncer, AriaDescriber, FocusKeyManager, A11yModule } from '@angular/cdk/a11y';
15
15
  import { AutofillMonitor } from '@angular/cdk/text-field';
16
16
  import { FormControl, NgControl, Validators, NG_VALUE_ACCESSOR } from '@angular/forms';
17
- import { ENTER, ESCAPE, TAB as TAB$1, DOWN_ARROW, UP_ARROW, LEFT_ARROW, RIGHT_ARROW, SPACE, hasModifierKey, PAGE_DOWN, PAGE_UP, END, HOME, A } from '@angular/cdk/keycodes';
17
+ import { ENTER, SPACE, ESCAPE, TAB as TAB$1, DOWN_ARROW, UP_ARROW, PAGE_UP, PAGE_DOWN, HOME, END, A, LEFT_ARROW, RIGHT_ARROW, hasModifierKey } from '@angular/cdk/keycodes';
18
18
  import * as i1$4 from '@angular/cdk/bidi';
19
19
  import { Directionality } from '@angular/cdk/bidi';
20
20
  import { CdkDialogContainer, Dialog, DialogConfig, DIALOG_SCROLL_STRATEGY_PROVIDER as DIALOG_SCROLL_STRATEGY_PROVIDER$1 } from '@angular/cdk/dialog';
@@ -3415,13 +3415,30 @@ const SegmentedButtonImports = [
3415
3415
  SegmentedButtonGroupComponent,
3416
3416
  ];
3417
3417
 
3418
+ const SELECT_FIELD_TOKEN = new InjectionToken('ET_SELECT_FIELD_DIRECTIVE_TOKEN');
3419
+ class SelectFieldDirective {
3420
+ constructor() {
3421
+ this._bindings = createReactiveBindings();
3422
+ }
3423
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: SelectFieldDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3424
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.2", type: SelectFieldDirective, isStandalone: true, providers: [{ provide: SELECT_FIELD_TOKEN, useExisting: SelectFieldDirective }], exportAs: ["etSelectField"], ngImport: i0 }); }
3425
+ }
3426
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: SelectFieldDirective, decorators: [{
3427
+ type: Directive,
3428
+ args: [{
3429
+ standalone: true,
3430
+ providers: [{ provide: SELECT_FIELD_TOKEN, useExisting: SelectFieldDirective }],
3431
+ exportAs: 'etSelectField',
3432
+ }]
3433
+ }] });
3434
+
3418
3435
  class SelectFieldComponent extends DecoratedFormFieldBase {
3419
3436
  constructor() {
3420
3437
  super(...arguments);
3421
3438
  this.inputState = inject(InputStateService);
3422
3439
  }
3423
3440
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: SelectFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3424
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.2", type: SelectFieldComponent, isStandalone: true, selector: "et-select-field", host: { classAttribute: "et-form-field et-select-field" }, usesInheritance: true, hostDirectives: [{ directive: StaticFormFieldDirective }, { directive: WriteableInputDirective }, { directive: i0.forwardRef(function () { return DynamicFormFieldDirective; }), inputs: ["hideErrorMessage", "hideErrorMessage"] }], ngImport: i0, template: `
3441
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.2", type: SelectFieldComponent, isStandalone: true, selector: "et-select-field", host: { classAttribute: "et-form-field et-select-field" }, usesInheritance: true, hostDirectives: [{ directive: SelectFieldDirective }, { directive: StaticFormFieldDirective }, { directive: WriteableInputDirective }, { directive: i0.forwardRef(function () { return DynamicFormFieldDirective; }), inputs: ["hideErrorMessage", "hideErrorMessage"] }], ngImport: i0, template: `
3425
3442
  <ng-content select="et-label" />
3426
3443
  <div class="et-select-field-input">
3427
3444
  <ng-content />
@@ -3447,6 +3464,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImpor
3447
3464
  class: 'et-form-field et-select-field',
3448
3465
  },
3449
3466
  hostDirectives: [
3467
+ SelectFieldDirective,
3450
3468
  StaticFormFieldDirective,
3451
3469
  WriteableInputDirective,
3452
3470
  {
@@ -3555,32 +3573,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImpor
3555
3573
  args: [ANIMATED_LIFECYCLE_TOKEN, { static: true }]
3556
3574
  }] } });
3557
3575
 
3558
- class RuntimeError extends Error {
3559
- constructor(code, message, data = '__ET_NO_DATA__') {
3560
- super(formatRuntimeError(code, message));
3561
- this.code = code;
3562
- this.data = data;
3563
- if (data !== '__ET_NO_DATA__') {
3564
- try {
3565
- const _data = clone(data);
3566
- setTimeout(() => {
3567
- console.error(_data);
3568
- }, 1);
3569
- }
3570
- catch {
3571
- setTimeout(() => {
3572
- console.error(data);
3573
- }, 1);
3574
- }
3575
- }
3576
- }
3577
- }
3578
- function formatRuntimeError(code, message) {
3579
- // prefix code with zeros if it's less than 100
3580
- const codeWithZeros = code < 10 ? `00${code}` : code < 100 ? `0${code}` : code;
3581
- const fullCode = `ET${codeWithZeros}`;
3582
- return `${fullCode}${message ? ': ' + message : ''}`;
3583
- }
3584
3576
  const COMBOBOX_ERRORS = {
3585
3577
  1: 'Expected options to be an array of objects. This is due to "bindLabel" and "bindValue" being set.',
3586
3578
  2: 'Expected options to be an array of primitives. This is due to "bindLabel" and "bindValue" not being set or "allowCustomValues" being set to true.',
@@ -3610,46 +3602,35 @@ const isObjectArray = (value) => {
3610
3602
  const isEmptyArray = (value) => {
3611
3603
  return Array.isArray(value) && value.length === 0;
3612
3604
  };
3613
- const isObject = (value) => {
3614
- return typeof value === 'object' && value !== null;
3615
- };
3616
3605
  const ComboboxOptionType = {
3617
3606
  Primitive: 'primitive',
3618
3607
  Object: 'object',
3619
3608
  };
3620
- const ComboboxInputValueType = {
3621
- Single: 'single',
3622
- Array: 'array',
3623
- };
3624
- const getObjectProperty = (obj, prop) => {
3625
- const hasDotNotation = prop.includes('.');
3626
- if (!hasDotNotation)
3627
- return obj[prop];
3628
- const props = prop.split('.');
3629
- let value = obj;
3630
- for (const prop of props) {
3631
- if (!isObject(value))
3632
- return undefined;
3633
- value = value[prop];
3634
- }
3635
- return value;
3636
- };
3637
3609
  const COMBOBOX_TOKEN = new InjectionToken('ET_COMBOBOX_TOKEN');
3638
3610
  class ComboboxComponent extends DecoratedInputBase {
3639
3611
  //#endregion
3640
3612
  //#region Inputs
3641
3613
  get options() {
3642
- return this._options$.value;
3614
+ return this._selectionModel.getFilteredOptions();
3643
3615
  }
3644
3616
  set options(value) {
3645
- this._options$.next(value);
3646
- }
3647
- get initialValue() {
3648
- return this._initialValue$.value;
3617
+ this._selectionModel.setOptions(value);
3649
3618
  }
3650
3619
  set initialValue(value) {
3651
- this._initialValue$.next(value);
3652
- this._updateSelectedOptionsViaInitialValue();
3620
+ this._selectionModel.setSelection(value);
3621
+ }
3622
+ get filterInternal() {
3623
+ return this._filterInternal$.value;
3624
+ }
3625
+ set filterInternal(value) {
3626
+ const val = coerceBooleanProperty(value);
3627
+ this._filterInternal$.next(val);
3628
+ if (!val) {
3629
+ this._selectionModel.setFilter('');
3630
+ }
3631
+ else {
3632
+ this._selectionModel.setFilter(this._currentFilter);
3633
+ }
3653
3634
  }
3654
3635
  get loading() {
3655
3636
  return this._loading$.value;
@@ -3669,23 +3650,14 @@ class ComboboxComponent extends DecoratedInputBase {
3669
3650
  set placeholder(value) {
3670
3651
  this._placeholder$.next(value);
3671
3652
  }
3672
- get multiple() {
3673
- return this._multiple$.value;
3674
- }
3675
3653
  set multiple(value) {
3676
- this._multiple$.next(coerceBooleanProperty(value));
3677
- }
3678
- get bindLabel() {
3679
- return this._bindLabel$.value;
3654
+ this._selectionModel.setAllowMultiple(coerceBooleanProperty(value));
3680
3655
  }
3681
3656
  set bindLabel(value) {
3682
- this._bindLabel$.next(value);
3683
- }
3684
- get bindValue() {
3685
- return this._bindValue$.value;
3657
+ this._selectionModel.setLabelBinding(value);
3686
3658
  }
3687
3659
  set bindValue(value) {
3688
- this._bindValue$.next(value);
3660
+ this._selectionModel.setValueBinding(value);
3689
3661
  }
3690
3662
  get allowCustomValues() {
3691
3663
  return this._allowCustomValues$.value;
@@ -3695,9 +3667,6 @@ class ComboboxComponent extends DecoratedInputBase {
3695
3667
  }
3696
3668
  //#endregion
3697
3669
  //#region Members
3698
- get _rawSelectedOptions() {
3699
- return this._rawSelectedOptions$.value;
3700
- }
3701
3670
  get _currentFilter() {
3702
3671
  return this._currentFilter$.value;
3703
3672
  }
@@ -3705,67 +3674,30 @@ class ComboboxComponent extends DecoratedInputBase {
3705
3674
  return this._animatedOverlay.isMounted;
3706
3675
  }
3707
3676
  //#endregion
3677
+ //#region Computes
3678
+ //#endregion
3708
3679
  //#region Lifecycle
3709
3680
  constructor() {
3710
3681
  super();
3711
3682
  //#region Injects
3712
3683
  this._input = inject(INPUT_TOKEN);
3713
3684
  this._animatedOverlay = inject(AnimatedOverlayDirective);
3714
- this._options$ = new BehaviorSubject([]);
3715
- this.options$ = this._options$.asObservable();
3716
- this._initialValue$ = new BehaviorSubject(null);
3685
+ this._selectField = inject(SELECT_FIELD_TOKEN);
3686
+ this._filterInternal$ = new BehaviorSubject(true);
3717
3687
  this._loading$ = new BehaviorSubject(false);
3718
3688
  this.loading$ = this._loading$.asObservable();
3719
3689
  this._error$ = new BehaviorSubject(null);
3720
3690
  this._placeholder$ = new BehaviorSubject(null);
3721
- this._multiple$ = new BehaviorSubject(false);
3722
- this._bindLabel$ = new BehaviorSubject(null);
3723
- this._bindValue$ = new BehaviorSubject(null);
3724
3691
  this._allowCustomValues$ = new BehaviorSubject(false);
3725
3692
  //#endregion
3726
3693
  //#region Outputs
3727
3694
  this.filterChange = new EventEmitter();
3728
- this._rawSelectedOptions$ = new BehaviorSubject([]);
3729
3695
  this._currentFilter$ = new BehaviorSubject('');
3730
3696
  this._isOpen$ = this._animatedOverlay.isMounted$;
3731
- //#endregion
3732
- //#region Computes
3733
- this._allOptions$ = combineLatest([this._options$, this._rawSelectedOptions$]).pipe(map(([options, rawSelectedOptions]) => [...options, ...rawSelectedOptions]), shareReplay({ bufferSize: 1, refCount: true }));
3734
- this.expectedOptionType$ = combineLatest([
3735
- this._bindLabel$,
3736
- this._bindValue$,
3737
- this._allowCustomValues$,
3738
- ]).pipe(map(([bindLabel, bindValue, allowCustomValues]) => {
3739
- const shouldBeObjects = bindLabel && bindValue && !allowCustomValues;
3740
- if (shouldBeObjects) {
3741
- return ComboboxOptionType.Object;
3742
- }
3743
- return ComboboxOptionType.Primitive;
3744
- }));
3745
- this.expectedInputValueType$ = this._multiple$.pipe(map((multiple) => (multiple ? ComboboxInputValueType.Array : ComboboxInputValueType.Single)));
3746
- this.selectedOptions$ = combineLatest([
3747
- this._input.value$,
3748
- this.expectedInputValueType$,
3749
- this._allOptions$,
3750
- ]).pipe(map(([inputValue, expectedInputValueType, allOptions]) => {
3751
- if (expectedInputValueType === ComboboxInputValueType.Single) {
3752
- if (Array.isArray(inputValue)) {
3753
- return [];
3754
- }
3755
- const option = this._findOptionByValue(inputValue, allOptions);
3756
- return [option];
3757
- }
3758
- else if (expectedInputValueType === ComboboxInputValueType.Array) {
3759
- if (!Array.isArray(inputValue)) {
3760
- return [];
3761
- }
3762
- const options = inputValue.map((value) => this._findOptionByValue(value, allOptions)).filter((v) => !!v);
3763
- if (!options.length)
3764
- return [];
3765
- return options;
3766
- }
3767
- return [];
3768
- }), map((options) => options.filter((v) => !!v)));
3697
+ this._selectionModel = new SelectionModel();
3698
+ this.selectedOptions$ = this._selectionModel.selection$;
3699
+ this.multiple$ = this._selectionModel.allowMultiple$;
3700
+ this.options$ = this._selectionModel.filteredOptions$;
3769
3701
  this._bindings.push({
3770
3702
  attribute: 'class.et-combobox--loading',
3771
3703
  observable: this._loading$,
@@ -3778,6 +3710,10 @@ class ComboboxComponent extends DecoratedInputBase {
3778
3710
  attribute: 'class.et-combobox--open',
3779
3711
  observable: this._isOpen$,
3780
3712
  });
3713
+ this._selectField._bindings.push({
3714
+ attribute: 'class.et-select-field--open',
3715
+ observable: this._isOpen$,
3716
+ });
3781
3717
  }
3782
3718
  ngOnInit() {
3783
3719
  this._initDispatchFilterChanges();
@@ -3785,42 +3721,24 @@ class ComboboxComponent extends DecoratedInputBase {
3785
3721
  if (isDevMode()) {
3786
3722
  this._debugValidateComboboxConfig();
3787
3723
  }
3724
+ this._selectionModel.value$
3725
+ .pipe(takeUntil(this._destroy$), tap((value) => {
3726
+ this._input._updateValue(value);
3727
+ this._setFilterFromInputValue();
3728
+ }))
3729
+ .subscribe();
3788
3730
  }
3789
3731
  //#endregion
3790
3732
  //#region Public Methods
3791
3733
  getOptionLabel(option) {
3792
- if (!this.bindLabel || !isObject(option)) {
3793
- return of(option);
3794
- }
3795
- return this._bindLabel$.pipe(map((label) => {
3796
- if (!label)
3797
- return option;
3798
- return getObjectProperty(option, label) ?? option;
3799
- }));
3734
+ return this._selectionModel.getLabel$(option);
3800
3735
  }
3801
3736
  getOptionValue(option) {
3802
- if (!this.bindValue || !isObject(option)) {
3803
- return of(option);
3804
- }
3805
- return this._bindValue$.pipe(map((value) => {
3806
- if (!value)
3807
- return option;
3808
- return getObjectProperty(option, value) ?? option;
3809
- }));
3737
+ return this._selectionModel.getValue$(option);
3810
3738
  }
3811
3739
  removeSelectedOption(option) {
3740
+ this._selectionModel.removeSelectedOption(option);
3812
3741
  this.input._markAsTouched();
3813
- const selectedOptions = this._rawSelectedOptions;
3814
- const optionValue = this._getOptionValueSync(option);
3815
- const index = selectedOptions.findIndex((v) => {
3816
- const val = this._getOptionValueSync(v);
3817
- return val === optionValue;
3818
- });
3819
- if (index === -1)
3820
- return;
3821
- selectedOptions.splice(index, 1);
3822
- this._rawSelectedOptions$.next(selectedOptions);
3823
- this._removeOrClearInputValue(optionValue);
3824
3742
  }
3825
3743
  open() {
3826
3744
  // if (!this._selectBodyConfig) return;
@@ -3844,70 +3762,102 @@ class ComboboxComponent extends DecoratedInputBase {
3844
3762
  }
3845
3763
  writeValueFromOption(option) {
3846
3764
  this.input._markAsTouched();
3847
- const optionValue = this._getOptionValueSync(option);
3848
- if (this._findOptionByValue(optionValue, this._rawSelectedOptions)) {
3849
- if (this.multiple) {
3850
- this.removeSelectedOption(option);
3851
- this._removeOrClearInputValue(optionValue);
3852
- }
3853
- return;
3765
+ if (this._selectionModel.allowMultiple) {
3766
+ this._selectionModel.toggleSelectedOption(option);
3767
+ }
3768
+ else {
3769
+ this._selectionModel.addSelectedOption(option);
3854
3770
  }
3855
- this._setOrAddToInputValue(optionValue);
3856
- this._addSelectedOption(option);
3857
- if (!this.multiple) {
3771
+ if (!this._selectionModel.allowMultiple) {
3858
3772
  this.close();
3859
3773
  this._setFilterFromInputValue();
3860
3774
  }
3861
3775
  }
3862
3776
  isOptionSelected(option) {
3863
- return combineLatest([this._rawSelectedOptions$, this.getOptionValue(option)]).pipe(map(([selectedOptions, value]) => !!this._findOptionByValue(value, selectedOptions)));
3777
+ return this._selectionModel.isSelected$(option);
3864
3778
  }
3865
3779
  //#endregion
3866
3780
  //#region Protected Methods
3867
3781
  processKeydownEvent(event) {
3868
3782
  const keyCode = event.keyCode;
3869
3783
  const isOpen = this._isOpen;
3870
- const isMultiple = this.multiple;
3784
+ const isMultiple = this._selectionModel.allowMultiple;
3871
3785
  const canAddCustomValue = this.allowCustomValues;
3872
3786
  const value = event.target.value;
3873
- const hasValue = !!value;
3787
+ const hasFilterValue = !!value;
3788
+ const result = {};
3874
3789
  // The user typed a custom value and pressed enter. Add it to the selected options.
3875
- if (keyCode === ENTER && canAddCustomValue && hasValue) {
3876
- // Don't add the value if it already exists.
3877
- if (!this._findOptionByValue(value, this._rawSelectedOptions)) {
3878
- this._addSelectedOption(value);
3879
- this._setOrAddToInputValue(value);
3790
+ if (keyCode === ENTER) {
3791
+ if (canAddCustomValue && hasFilterValue) {
3792
+ result.optionAction = { type: 'add', option: value };
3880
3793
  }
3881
- if (this.multiple) {
3882
- this._updateFilter('');
3794
+ else {
3795
+ if (isMultiple) {
3796
+ // TODO: Toggle the focused option
3797
+ }
3798
+ else {
3799
+ // TODO: Select the focused option
3800
+ }
3883
3801
  }
3884
- return;
3802
+ if (isMultiple) {
3803
+ result.setFilter = '';
3804
+ }
3805
+ else {
3806
+ result.overlayOperation = 'close';
3807
+ }
3808
+ return this._interpretKeyHandlerResult(result);
3809
+ }
3810
+ if (keyCode === SPACE) {
3811
+ if (isMultiple) {
3812
+ result.setFilter = '';
3813
+ // TODO: Toggle the focused option
3814
+ }
3815
+ else {
3816
+ result.overlayOperation = 'close';
3817
+ // TODO: Select the focused option
3818
+ }
3819
+ return this._interpretKeyHandlerResult(result);
3885
3820
  }
3886
3821
  if (keyCode === ESCAPE) {
3887
3822
  if (isOpen) {
3888
- this.close();
3823
+ result.overlayOperation = 'close';
3889
3824
  }
3890
- else {
3891
- if (!isMultiple) {
3892
- this._removeOrClearInputValue(null);
3893
- this._updateFilter('');
3894
- return;
3895
- }
3825
+ else if (!isMultiple) {
3826
+ result.setFilter = '';
3827
+ result.optionAction = 'clear';
3896
3828
  }
3829
+ return this._interpretKeyHandlerResult(result);
3897
3830
  }
3898
3831
  if (keyCode === TAB$1) {
3899
- this.close();
3900
- return;
3832
+ result.overlayOperation = 'close';
3833
+ return this._interpretKeyHandlerResult(result);
3901
3834
  }
3902
3835
  if (!isOpen) {
3903
- this.open();
3836
+ result.overlayOperation = 'open';
3904
3837
  }
3905
3838
  if (keyCode === DOWN_ARROW) {
3906
- // TODO: Implement
3839
+ result.focusAction = 'next';
3907
3840
  }
3908
3841
  if (keyCode === UP_ARROW) {
3909
- // TODO: Implement
3842
+ result.focusAction = 'previous';
3910
3843
  }
3844
+ if (keyCode === PAGE_UP) {
3845
+ result.focusAction = { type: 'offset', offset: -10 };
3846
+ }
3847
+ if (keyCode === PAGE_DOWN) {
3848
+ result.focusAction = { type: 'offset', offset: 10 };
3849
+ }
3850
+ if (keyCode === HOME) {
3851
+ result.focusAction = 'first';
3852
+ }
3853
+ if (keyCode === END) {
3854
+ result.focusAction = 'last';
3855
+ }
3856
+ if (keyCode === A && event.ctrlKey && isMultiple) {
3857
+ result.optionAction = 'toggleAll';
3858
+ event.preventDefault();
3859
+ }
3860
+ return this._interpretKeyHandlerResult(result);
3911
3861
  }
3912
3862
  processInputEvent(event) {
3913
3863
  const value = event.target.value;
@@ -3916,10 +3866,10 @@ class ComboboxComponent extends DecoratedInputBase {
3916
3866
  handleBlurEvent() {
3917
3867
  this.input._markAsTouched();
3918
3868
  this.input._setShouldDisplayError(true);
3919
- if (this.multiple)
3869
+ if (this._selectionModel.allowMultiple)
3920
3870
  return;
3921
3871
  if (this._currentFilter === '') {
3922
- this._removeOrClearInputValue(null);
3872
+ this._selectionModel.clearSelectedOptions();
3923
3873
  return;
3924
3874
  }
3925
3875
  this._setFilterFromInputValue();
@@ -3928,7 +3878,7 @@ class ComboboxComponent extends DecoratedInputBase {
3928
3878
  //#region Private Methods
3929
3879
  _initDispatchFilterChanges() {
3930
3880
  this._currentFilter$
3931
- .pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this._destroy$), tap((v) => this.filterChange.emit(v)))
3881
+ .pipe(skipWhile(() => this.filterInternal), debounceTime(300), distinctUntilChanged(), takeUntil(this._destroy$), tap((v) => this.filterChange.emit(v)))
3932
3882
  .subscribe();
3933
3883
  }
3934
3884
  _initRepositionOnValueChanges() {
@@ -3936,65 +3886,6 @@ class ComboboxComponent extends DecoratedInputBase {
3936
3886
  .pipe(takeUntil(this._destroy$), debounceTime(0), tap(() => this._animatedOverlay._reposition()))
3937
3887
  .subscribe();
3938
3888
  }
3939
- _updateSelectedOptionsViaInitialValue() {
3940
- if (this.initialValue !== null && this.initialValue !== undefined) {
3941
- if (Array.isArray(this.initialValue)) {
3942
- this._addSelectedOptions(this.initialValue);
3943
- }
3944
- else {
3945
- this._addSelectedOption(this.initialValue);
3946
- }
3947
- }
3948
- }
3949
- _addSelectedOption(option) {
3950
- if (this.multiple) {
3951
- this._rawSelectedOptions$.next([...this._rawSelectedOptions, option]);
3952
- }
3953
- else {
3954
- this._rawSelectedOptions$.next([option]);
3955
- }
3956
- }
3957
- _addSelectedOptions(options) {
3958
- if (!this.multiple) {
3959
- return;
3960
- }
3961
- this._rawSelectedOptions$.next([...this._rawSelectedOptions, ...options]);
3962
- }
3963
- _findOptionByValue(value, allOptions) {
3964
- const option = allOptions.find((option) => {
3965
- if (isObject(option) && this.bindValue) {
3966
- return getObjectProperty(option, this.bindValue) === value;
3967
- }
3968
- return option === value;
3969
- });
3970
- return option;
3971
- }
3972
- _setOrAddToInputValue(value) {
3973
- if (this.multiple) {
3974
- if (Array.isArray(this._input.value)) {
3975
- this._input._updateValue([...this._input.value, value]);
3976
- }
3977
- else {
3978
- this._input._updateValue([value]);
3979
- }
3980
- }
3981
- else {
3982
- this._input._updateValue(value);
3983
- }
3984
- }
3985
- _removeOrClearInputValue(value) {
3986
- if (this.multiple) {
3987
- if (Array.isArray(this._input.value)) {
3988
- this._input._updateValue(this._input.value.filter((v) => v !== value));
3989
- }
3990
- else {
3991
- this._input._updateValue([]);
3992
- }
3993
- }
3994
- else {
3995
- this._input._updateValue(null);
3996
- }
3997
- }
3998
3889
  _updateFilter(value) {
3999
3890
  if (this.input.nativeInputRef && this.input.nativeInputRef.element.nativeElement.value !== value) {
4000
3891
  this.input.nativeInputRef.element.nativeElement.value = value;
@@ -4002,52 +3893,106 @@ class ComboboxComponent extends DecoratedInputBase {
4002
3893
  if (this._currentFilter === value)
4003
3894
  return;
4004
3895
  this._currentFilter$.next(value);
4005
- }
4006
- _getOptionValueSync(option) {
4007
- if (!this.bindValue || !isObject(option)) {
4008
- return option;
4009
- }
4010
- return getObjectProperty(option, this.bindValue) ?? option;
4011
- }
4012
- _getOptionLabelSync(option) {
4013
- if (!this.bindLabel || !isObject(option)) {
4014
- return option;
3896
+ if (this.filterInternal) {
3897
+ this._selectionModel.setFilter(value);
4015
3898
  }
4016
- return getObjectProperty(option, this.bindLabel) ?? option;
4017
3899
  }
4018
3900
  _setFilterFromInputValue() {
4019
- if (this.multiple)
3901
+ if (this._selectionModel.allowMultiple)
4020
3902
  return;
4021
3903
  const value = this.input.value;
4022
3904
  if (!value || Array.isArray(value)) {
4023
3905
  this._updateFilter('');
4024
3906
  return;
4025
3907
  }
4026
- const option = this._findOptionByValue(value, this._rawSelectedOptions);
3908
+ const option = this._selectionModel.getOptionByValue(value);
4027
3909
  if (!option)
4028
3910
  return;
4029
- const label = this._getOptionLabelSync(option);
3911
+ const label = this._selectionModel.getLabel(option);
4030
3912
  if (typeof label !== 'string')
4031
3913
  return;
4032
3914
  this._updateFilter(label);
4033
3915
  }
3916
+ _interpretKeyHandlerResult(result) {
3917
+ if (result.overlayOperation === 'close') {
3918
+ this.close();
3919
+ }
3920
+ else if (result.overlayOperation === 'open') {
3921
+ this.open();
3922
+ }
3923
+ if (result.setFilter !== undefined) {
3924
+ this._updateFilter(result.setFilter);
3925
+ }
3926
+ if (result.optionAction) {
3927
+ if (typeof result.optionAction === 'string') {
3928
+ if (result.optionAction === 'clear') {
3929
+ this._selectionModel.clearSelectedOptions();
3930
+ }
3931
+ else if (result.optionAction === 'toggleAll') {
3932
+ this._selectionModel.toggleAllSelectedOptions();
3933
+ }
3934
+ }
3935
+ else {
3936
+ const { type, option } = result.optionAction;
3937
+ if (type === 'add') {
3938
+ this._selectionModel.addSelectedOption(option);
3939
+ }
3940
+ if (type === 'remove') {
3941
+ this._selectionModel.removeSelectedOption(option);
3942
+ }
3943
+ if (type === 'toggle') {
3944
+ this._selectionModel.toggleSelectedOption(option);
3945
+ }
3946
+ }
3947
+ }
3948
+ if (result.focusAction) {
3949
+ if (typeof result.focusAction === 'string') {
3950
+ if (result.focusAction === 'first') {
3951
+ // TODO: Implement
3952
+ }
3953
+ if (result.focusAction === 'last') {
3954
+ // TODO: Implement
3955
+ }
3956
+ if (result.focusAction === 'next') {
3957
+ // TODO: Implement
3958
+ }
3959
+ if (result.focusAction === 'previous') {
3960
+ // TODO: Implement
3961
+ }
3962
+ }
3963
+ else {
3964
+ const { type } = result.focusAction;
3965
+ if (type === 'offset') {
3966
+ const { offset } = result.focusAction;
3967
+ // TODO: Implement
3968
+ }
3969
+ }
3970
+ }
3971
+ }
4034
3972
  //#endregion
4035
3973
  //#region Dev mode
4036
3974
  _debugValidateComboboxConfig(isRetry = false) {
4037
- this.expectedOptionType$
3975
+ combineLatest([this._selectionModel.labelBinding$, this._selectionModel.valueBinding$, this._allowCustomValues$])
4038
3976
  .pipe(skip(isRetry ? 1 : 0), // Skip if retrying to avoid infinite loop
4039
- debounceTime(0), takeUntil(this._destroy$), tap((expectedOptionType) => {
4040
- if (isEmptyArray(this.options)) {
3977
+ debounceTime(0), takeUntil(this._destroy$), map(([bindLabel, bindValue, allowCustomValues]) => {
3978
+ const shouldBeObjects = bindLabel && bindValue && !allowCustomValues;
3979
+ if (shouldBeObjects) {
3980
+ return ComboboxOptionType.Object;
3981
+ }
3982
+ return ComboboxOptionType.Primitive;
3983
+ }), tap((expectedOptionType) => {
3984
+ const options = this._selectionModel.options;
3985
+ if (isEmptyArray(options)) {
4041
3986
  return;
4042
3987
  }
4043
3988
  if (expectedOptionType === ComboboxOptionType.Object) {
4044
- if (!isObjectArray(this.options)) {
4045
- throw comboboxError(1, this.options);
3989
+ if (!isObjectArray(options)) {
3990
+ throw comboboxError(1, options);
4046
3991
  }
4047
3992
  }
4048
3993
  else if (expectedOptionType === ComboboxOptionType.Primitive) {
4049
- if (!isPrimitiveArray(this.options)) {
4050
- throw comboboxError(2, this.options);
3994
+ if (!isPrimitiveArray(options)) {
3995
+ throw comboboxError(2, options);
4051
3996
  }
4052
3997
  }
4053
3998
  }), catchError((e) => {
@@ -4057,12 +4002,12 @@ class ComboboxComponent extends DecoratedInputBase {
4057
4002
  .subscribe();
4058
4003
  }
4059
4004
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ComboboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4060
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.2", type: ComboboxComponent, isStandalone: true, selector: "et-combobox", inputs: { options: "options", initialValue: "initialValue", loading: "loading", error: "error", placeholder: "placeholder", multiple: "multiple", bindLabel: "bindLabel", bindValue: "bindValue", allowCustomValues: "allowCustomValues" }, outputs: { filterChange: "filterChange" }, host: { classAttribute: "et-combobox" }, providers: [
4005
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.2", type: ComboboxComponent, isStandalone: true, selector: "et-combobox", inputs: { options: "options", initialValue: "initialValue", filterInternal: "filterInternal", loading: "loading", error: "error", placeholder: "placeholder", multiple: "multiple", bindLabel: "bindLabel", bindValue: "bindValue", allowCustomValues: "allowCustomValues" }, outputs: { filterChange: "filterChange" }, host: { classAttribute: "et-combobox" }, providers: [
4061
4006
  {
4062
4007
  provide: COMBOBOX_TOKEN,
4063
4008
  useExisting: ComboboxComponent,
4064
4009
  },
4065
- ], usesInheritance: true, hostDirectives: [{ directive: InputDirective }, { directive: i1$1.AnimatedOverlayDirective }], ngImport: i0, template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<!-- eslint-disable @angular-eslint/template/use-track-by-function -->\n<ng-content select=\"[etInputPrefix]\" />\n\n<div class=\"et-combobox-wrapper\">\n <ul *ngIf=\"multiple\" class=\"et-combobox-selected-options\">\n <li *ngFor=\"let item of selectedOptions$ | async\" class=\"et-combobox-selected-option\">\n {{ getOptionLabel(item) | async }}\n <span (click)=\"removeSelectedOption(item)\" class=\"et-combobox-selected-option-remove\" tabindex=\"-1\"> x </span>\n </li>\n </ul>\n\n <input\n (keydown)=\"processKeydownEvent($event)\"\n (click)=\"open()\"\n (blur)=\"handleBlurEvent()\"\n (input)=\"processInputEvent($event)\"\n type=\"text\"\n etNativeInputRef\n />\n\n <et-chevron-icon class=\"et-combobox-chevron\" />\n</div>\n\n<ng-content select=\"[etInputSuffix]\" />\n\n<ng-template>\n <ng-content />\n</ng-template>\n", styles: [".et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-enter-from,.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-leave-to{opacity:0;transform:scaleY(0)}.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-enter-active{transition:transform 125ms var(--ease-out-5),opacity 125ms var(--ease-out-5)}.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-leave-active{transition:transform 50ms var(--ease-in-5),opacity 50ms var(--ease-in-5)}.et-combobox-body.et-with-default-animation[data-popper-placement^=top] .et-combobox-body-container{transform-origin:bottom}.et-combobox-body.et-with-default-animation[data-popper-placement^=bottom] .et-combobox-body-container{transform-origin:top}.et-combobox-body-container{display:block;background-color:#3d3d3d;color:#fff;max-height:300px;overflow:auto}@supports (overflow: overlay){.et-combobox-body-container{overflow:overlay}}.et-combobox-body{width:100%;display:grid}.et-combobox-option{display:block}.et-combobox{display:block;border:1px solid #ccc;padding:15px;position:relative}.et-combobox-chevron{transform:rotate(180deg);display:block;inline-size:15px;block-size:15px;position:absolute;inset-inline-end:15px;inset-block-start:7px}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NativeInputRefDirective, selector: "input[etNativeInputRef], textarea[etNativeInputRef], select[etNativeInputRef], button[etNativeInputRef]" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: ChevronIconComponent, selector: "et-chevron-icon" }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4010
+ ], usesInheritance: true, hostDirectives: [{ directive: InputDirective }, { directive: i1$1.AnimatedOverlayDirective }], ngImport: i0, template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<!-- eslint-disable @angular-eslint/template/use-track-by-function -->\n<ng-content select=\"[etInputPrefix]\" />\n\n<div class=\"et-combobox-wrapper\">\n <ul *ngIf=\"multiple$ | async\" class=\"et-combobox-selected-options\">\n <li *ngFor=\"let item of selectedOptions$ | async\" class=\"et-combobox-selected-option\">\n {{ getOptionLabel(item) | async }}\n <span (click)=\"removeSelectedOption(item)\" class=\"et-combobox-selected-option-remove\" tabindex=\"-1\"> x </span>\n </li>\n </ul>\n\n <input\n (keydown)=\"processKeydownEvent($event)\"\n (click)=\"open()\"\n (blur)=\"handleBlurEvent()\"\n (input)=\"processInputEvent($event)\"\n type=\"text\"\n etNativeInputRef\n />\n\n <et-chevron-icon class=\"et-combobox-chevron\" />\n</div>\n\n<ng-content select=\"[etInputSuffix]\" />\n\n<ng-template>\n <ng-content />\n</ng-template>\n", styles: [".et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-enter-from,.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-leave-to{opacity:0;transform:scaleY(0)}.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-enter-active{transition:transform 125ms var(--ease-out-5),opacity 125ms var(--ease-out-5)}.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-leave-active{transition:transform 50ms var(--ease-in-5),opacity 50ms var(--ease-in-5)}.et-combobox-body.et-with-default-animation[data-popper-placement^=top] .et-combobox-body-container{transform-origin:bottom}.et-combobox-body.et-with-default-animation[data-popper-placement^=bottom] .et-combobox-body-container{transform-origin:top}.et-combobox-body-container{display:block;background-color:#3d3d3d;color:#fff;max-height:300px;overflow:auto}@supports (overflow: overlay){.et-combobox-body-container{overflow:overlay}}.et-combobox-body{width:100%;display:grid}.et-combobox-option{display:block}.et-combobox{display:block;border:1px solid #ccc;padding:15px;position:relative}.et-combobox-chevron{transform:rotate(180deg);display:block;inline-size:15px;block-size:15px;position:absolute;inset-inline-end:15px;inset-block-start:7px}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NativeInputRefDirective, selector: "input[etNativeInputRef], textarea[etNativeInputRef], select[etNativeInputRef], button[etNativeInputRef]" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: ChevronIconComponent, selector: "et-chevron-icon" }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4066
4011
  }
4067
4012
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ComboboxComponent, decorators: [{
4068
4013
  type: Component,
@@ -4073,12 +4018,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImpor
4073
4018
  provide: COMBOBOX_TOKEN,
4074
4019
  useExisting: ComboboxComponent,
4075
4020
  },
4076
- ], template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<!-- eslint-disable @angular-eslint/template/use-track-by-function -->\n<ng-content select=\"[etInputPrefix]\" />\n\n<div class=\"et-combobox-wrapper\">\n <ul *ngIf=\"multiple\" class=\"et-combobox-selected-options\">\n <li *ngFor=\"let item of selectedOptions$ | async\" class=\"et-combobox-selected-option\">\n {{ getOptionLabel(item) | async }}\n <span (click)=\"removeSelectedOption(item)\" class=\"et-combobox-selected-option-remove\" tabindex=\"-1\"> x </span>\n </li>\n </ul>\n\n <input\n (keydown)=\"processKeydownEvent($event)\"\n (click)=\"open()\"\n (blur)=\"handleBlurEvent()\"\n (input)=\"processInputEvent($event)\"\n type=\"text\"\n etNativeInputRef\n />\n\n <et-chevron-icon class=\"et-combobox-chevron\" />\n</div>\n\n<ng-content select=\"[etInputSuffix]\" />\n\n<ng-template>\n <ng-content />\n</ng-template>\n", styles: [".et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-enter-from,.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-leave-to{opacity:0;transform:scaleY(0)}.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-enter-active{transition:transform 125ms var(--ease-out-5),opacity 125ms var(--ease-out-5)}.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-leave-active{transition:transform 50ms var(--ease-in-5),opacity 50ms var(--ease-in-5)}.et-combobox-body.et-with-default-animation[data-popper-placement^=top] .et-combobox-body-container{transform-origin:bottom}.et-combobox-body.et-with-default-animation[data-popper-placement^=bottom] .et-combobox-body-container{transform-origin:top}.et-combobox-body-container{display:block;background-color:#3d3d3d;color:#fff;max-height:300px;overflow:auto}@supports (overflow: overlay){.et-combobox-body-container{overflow:overlay}}.et-combobox-body{width:100%;display:grid}.et-combobox-option{display:block}.et-combobox{display:block;border:1px solid #ccc;padding:15px;position:relative}.et-combobox-chevron{transform:rotate(180deg);display:block;inline-size:15px;block-size:15px;position:absolute;inset-inline-end:15px;inset-block-start:7px}\n"] }]
4021
+ ], template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<!-- eslint-disable @angular-eslint/template/use-track-by-function -->\n<ng-content select=\"[etInputPrefix]\" />\n\n<div class=\"et-combobox-wrapper\">\n <ul *ngIf=\"multiple$ | async\" class=\"et-combobox-selected-options\">\n <li *ngFor=\"let item of selectedOptions$ | async\" class=\"et-combobox-selected-option\">\n {{ getOptionLabel(item) | async }}\n <span (click)=\"removeSelectedOption(item)\" class=\"et-combobox-selected-option-remove\" tabindex=\"-1\"> x </span>\n </li>\n </ul>\n\n <input\n (keydown)=\"processKeydownEvent($event)\"\n (click)=\"open()\"\n (blur)=\"handleBlurEvent()\"\n (input)=\"processInputEvent($event)\"\n type=\"text\"\n etNativeInputRef\n />\n\n <et-chevron-icon class=\"et-combobox-chevron\" />\n</div>\n\n<ng-content select=\"[etInputSuffix]\" />\n\n<ng-template>\n <ng-content />\n</ng-template>\n", styles: [".et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-enter-from,.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-leave-to{opacity:0;transform:scaleY(0)}.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-enter-active{transition:transform 125ms var(--ease-out-5),opacity 125ms var(--ease-out-5)}.et-combobox-body.et-with-default-animation .et-combobox-body-container.et-animation-leave-active{transition:transform 50ms var(--ease-in-5),opacity 50ms var(--ease-in-5)}.et-combobox-body.et-with-default-animation[data-popper-placement^=top] .et-combobox-body-container{transform-origin:bottom}.et-combobox-body.et-with-default-animation[data-popper-placement^=bottom] .et-combobox-body-container{transform-origin:top}.et-combobox-body-container{display:block;background-color:#3d3d3d;color:#fff;max-height:300px;overflow:auto}@supports (overflow: overlay){.et-combobox-body-container{overflow:overlay}}.et-combobox-body{width:100%;display:grid}.et-combobox-option{display:block}.et-combobox{display:block;border:1px solid #ccc;padding:15px;position:relative}.et-combobox-chevron{transform:rotate(180deg);display:block;inline-size:15px;block-size:15px;position:absolute;inset-inline-end:15px;inset-block-start:7px}\n"] }]
4077
4022
  }], ctorParameters: function () { return []; }, propDecorators: { options: [{
4078
4023
  type: Input,
4079
4024
  args: [{ required: true }]
4080
4025
  }], initialValue: [{
4081
4026
  type: Input
4027
+ }], filterInternal: [{
4028
+ type: Input
4082
4029
  }], loading: [{
4083
4030
  type: Input
4084
4031
  }], error: [{
@@ -4418,6 +4365,7 @@ class SelectDirective {
4418
4365
  this._animatedOverlay = inject(AnimatedOverlayDirective);
4419
4366
  this._destroy$ = createDestroy();
4420
4367
  this._liveAnnouncer = inject(LiveAnnouncer);
4368
+ this._selectField = inject(SELECT_FIELD_TOKEN);
4421
4369
  this.input = inject(INPUT_TOKEN);
4422
4370
  this._selectBodyId$ = new BehaviorSubject(null);
4423
4371
  this._isOpen$ = new BehaviorSubject(false);
@@ -4491,6 +4439,10 @@ class SelectDirective {
4491
4439
  });
4492
4440
  this.trackByFn = (_, item) => item.id;
4493
4441
  this._animatedOverlay.placement = 'bottom';
4442
+ this._selectField._bindings.push({
4443
+ attribute: 'class.et-select-field--open',
4444
+ observable: this._isOpen$,
4445
+ });
4494
4446
  }
4495
4447
  ngOnInit() {
4496
4448
  this._unmountSelectBodyOnDisable();
@@ -10334,5 +10286,5 @@ const TABS_CONFIG = new InjectionToken('TABS_CONFIG');
10334
10286
  * Generated bundle index. Do not edit.
10335
10287
  */
10336
10288
 
10337
- export { ACCORDION_COMPONENT, ACCORDION_HINT_WRAPPER_DIRECTIVE, ACCORDION_LABEL_WRAPPER_DIRECTIVE, AccordionComponent, AccordionGroupComponent, AccordionHintDirective, AccordionHintWrapperDirective, AccordionImports, AccordionLabelDirective, AccordionLabelWrapperDirective, ActiveTabUnderlineBarManager, ActiveTabUnderlineDirective, AutosizeTextareaDirective, BOTTOM_SHEET_CONFIG, BOTTOM_SHEET_DATA, BOTTOM_SHEET_DEFAULT_CONFIG, BOTTOM_SHEET_DEFAULT_OPTIONS, BOTTOM_SHEET_MIN_SWIPE_TO_CLOSE_LENGTH, BOTTOM_SHEET_MIN_VELOCITY_TO_CLOSE, BOTTOM_SHEET_SCROLL_STRATEGY, BOTTOM_SHEET_SCROLL_STRATEGY_PROVIDER, BOTTOM_SHEET_SCROLL_STRATEGY_PROVIDER_FACTORY, BRACKET_CONFIG_TOKEN, BRACKET_DEFAULT_CONFIG, BRACKET_MATCH_ID_TOKEN, BRACKET_ROUND_ID_TOKEN, BRACKET_TOKEN, BottomSheetContainerBaseComponent, BottomSheetContainerComponent, BottomSheetDragHandleComponent, BottomSheetImports, BottomSheetRef, BottomSheetService, BottomSheetServiceBase, BottomSheetSwipeHandlerService, BottomSheetTitleDirective, Bracket, BracketComponent, BracketImports, BracketMatchComponent, BracketMatchDirective, BracketRoundDirective, BracketRoundHeaderComponent, ButtonComponent, ButtonDirective, ButtonImports, CHECKBOX_FIELD_TOKEN, CHECKBOX_GROUP_CONTROL_TOKEN, CHECKBOX_GROUP_TOKEN, CHECKBOX_TOKEN, COMBOBOX_DIR_TOKEN, COMBOBOX_TOKEN, CellDefDirective, CellDirective, CheckboxComponent, CheckboxDirective, CheckboxFieldComponent, CheckboxFieldDirective, CheckboxGroupComponent, CheckboxGroupControlDirective, CheckboxGroupDirective, CheckboxImports, ChevronIconComponent, ColumnDefDirective, ComboboxComponent, ComboboxDirective, ComboboxImports, DIALOG_CONFIG, DIALOG_DATA, DIALOG_DEFAULT_CONFIG, DIALOG_DEFAULT_OPTIONS, DIALOG_SCROLL_STRATEGY, DIALOG_SCROLL_STRATEGY_PROVIDER, DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY, DYNAMIC_FORM_FIELD_TOKEN, DYNAMIC_FORM_GROUP_TOKEN, DecoratedFormFieldBase, DecoratedInputBase, DefaultValidatorErrorsService, DialogCloseDirective, DialogContainerBaseComponent, DialogContainerComponent, DialogImports, DialogRef, DialogService, DialogServiceBase, DialogTitleDirective, DynamicFormFieldDirective, DynamicFormGroupDirective, DynamicOverlayService, EMAIL_INPUT_TOKEN, EmailInputComponent, EmailInputDirective, ErrorComponent, FooterCellDefDirective, FooterCellDirective, FooterRowComponent, FooterRowDefDirective, FormFieldStateService, FormGroupStateService, HeaderCellDefDirective, HeaderCellDirective, HeaderRowComponent, HeaderRowDefDirective, INPUT_PREFIX_TOKEN, INPUT_SUFFIX_TOKEN, INPUT_TOKEN, IconImports, IfInputEmptyDirective, IfInputFilledDirective, InlineTabBodyComponent, InlineTabBodyHostDirective, InlineTabChangeEvent, InlineTabComponent, InlineTabContentDirective, InlineTabHeaderComponent, InlineTabLabelDirective, InlineTabLabelWrapperDirective, InlineTabsComponent, InputBase, InputDirective, InputFieldComponent, InputImports, InputPrefixDirective, InputStateService, InputSuffixDirective, LABEL_TOKEN, LabelComponent, LabelImports, LabelSuffixDirective, MASONRY_ITEM_TOKEN, MAX_SAFE_INTEGER, MasonryComponent, MasonryImports, MasonryItemComponent, NATIVE_INPUT_REF_TOKEN, NATIVE_SELECT_INPUT_TOKEN, NATIVE_SELECT_OPTION_TOKEN, NUMBER_INPUT_TOKEN, NativeInputRefDirective, NativeSelectImports, NativeSelectInputComponent, NativeSelectInputDirective, NativeSelectOptionComponent, NativeSelectOptionDirective, NavTabLinkComponent, NavTabsComponent, NavTabsOutletComponent, NoDataRowDirective, NumberInputComponent, NumberInputDirective, PASSWORD_INPUT_TOKEN, PROGRESS_SPINNER_DEFAULT_OPTIONS, PROGRESS_SPINNER_DEFAULT_OPTIONS_FACTORY, PaginatedTabHeaderDirective, PaginationComponent, PaginationImports, PasswordInputComponent, PasswordInputDirective, PasswordInputToggleComponent, PictureComponent, PictureDataDirective, ProgressSpinnerComponent, QueryButtonComponent, QueryButtonDirective, RADIO_FIELD_TOKEN, RADIO_GROUP_TOKEN, RADIO_TOKEN, RadioComponent, RadioDirective, RadioFieldComponent, RadioFieldDirective, RadioGroupComponent, RadioGroupDirective, RadioImports, RecycleRowsDirective, RowComponent, RowDefDirective, RuntimeError, SEARCH_INPUT_TOKEN, SEGMENTED_BUTTON_FIELD_TOKEN, SEGMENTED_BUTTON_GROUP_TOKEN, SEGMENTED_BUTTON_TOKEN, SELECT_BODY_TOKEN, SELECT_OPTION_TOKEN, SELECT_TOKEN, SLIDE_TOGGLE_TOKEN, SORT_DEFAULT_OPTIONS, SORT_HEADER_COLUMN_DEF, SORT_HEADER_INTL_PROVIDER, SORT_HEADER_INTL_PROVIDER_FACTORY, STATIC_FORM_FIELD_TOKEN, STATIC_FORM_GROUP_TOKEN, ScrollableComponent, ScrollableImports, SearchInputClearComponent, SearchInputComponent, SearchInputDirective, SegmentedButtonComponent, SegmentedButtonDirective, SegmentedButtonFieldComponent, SegmentedButtonFieldDirective, SegmentedButtonGroupComponent, SegmentedButtonGroupDirective, SegmentedButtonImports, SelectBodyComponent, SelectBodyDirective, SelectComponent, SelectDirective, SelectFieldComponent, SelectImports, SelectOptionComponent, SelectOptionDirective, SkeletonComponent, SkeletonImports, SkeletonItemComponent, SlideToggleComponent, SlideToggleDirective, SlideToggleFieldComponent, SlideToggleImports, SliderComponent, SliderFieldComponent, SliderImports, SortDirective, SortHeaderComponent, SortHeaderIntl, SortImports, StaticFormFieldDirective, StaticFormGroupDirective, SwipeHandlerService, TAB, TABS_CONFIG, TAB_CONTENT, TAB_GROUP, TAB_LABEL, TEXTAREA_INPUT_TOKEN, TEXT_INPUT_TOKEN, TOGGLETIP, TOGGLETIP_CONFIG, TOGGLETIP_DEFAULT_CONFIG, TOGGLETIP_DIRECTIVE, TOGGLETIP_TEMPLATE, TOGGLETIP_TEXT, TOOLTIP, TOOLTIP_CONFIG, TOOLTIP_DEFAULT_CONFIG, TOOLTIP_DIRECTIVE, TOOLTIP_TEMPLATE, TOOLTIP_TEXT, TabImports, TableBusyDirective, TableBusyOutletDirective, TableComponent, TableDataSource, TableImports, TextColumnComponent, TextInputComponent, TextInputDirective, TextareaInputComponent, TextareaInputDirective, ToggletipComponent, ToggletipDirective, ToggletipImports, TooltipComponent, TooltipDirective, TooltipImports, VALIDATOR_ERROR_SERVICE_TOKEN, WRITEABLE_INPUT_TOKEN, WRITEABLE_INPUT_VALUE_ACCESSOR, WriteableInputDirective, _MAT_INK_BAR_POSITIONER, _MAT_INK_BAR_POSITIONER_FACTORY, accordionAnimations, createBottomSheetConfig, createBracketConfig, createDialogConfig, createToggletipConfig, createTooltipConfig, formatRuntimeError, getClosestBottomSheet, getClosestDialog, isUpperBracketMatch, normalizeRoundType, orderRounds, orderRoundsByRoundNumber, paginate, provideBottomSheet, provideBottomSheetDefaultConfig, provideBracketConfig, provideDialog, provideDialogDefaultConfig, provideSort, provideToggletipConfig, provideTooltipConfig, provideValidatorErrorsService, tabAnimations };
10289
+ export { ACCORDION_COMPONENT, ACCORDION_HINT_WRAPPER_DIRECTIVE, ACCORDION_LABEL_WRAPPER_DIRECTIVE, AccordionComponent, AccordionGroupComponent, AccordionHintDirective, AccordionHintWrapperDirective, AccordionImports, AccordionLabelDirective, AccordionLabelWrapperDirective, ActiveTabUnderlineBarManager, ActiveTabUnderlineDirective, AutosizeTextareaDirective, BOTTOM_SHEET_CONFIG, BOTTOM_SHEET_DATA, BOTTOM_SHEET_DEFAULT_CONFIG, BOTTOM_SHEET_DEFAULT_OPTIONS, BOTTOM_SHEET_MIN_SWIPE_TO_CLOSE_LENGTH, BOTTOM_SHEET_MIN_VELOCITY_TO_CLOSE, BOTTOM_SHEET_SCROLL_STRATEGY, BOTTOM_SHEET_SCROLL_STRATEGY_PROVIDER, BOTTOM_SHEET_SCROLL_STRATEGY_PROVIDER_FACTORY, BRACKET_CONFIG_TOKEN, BRACKET_DEFAULT_CONFIG, BRACKET_MATCH_ID_TOKEN, BRACKET_ROUND_ID_TOKEN, BRACKET_TOKEN, BottomSheetContainerBaseComponent, BottomSheetContainerComponent, BottomSheetDragHandleComponent, BottomSheetImports, BottomSheetRef, BottomSheetService, BottomSheetServiceBase, BottomSheetSwipeHandlerService, BottomSheetTitleDirective, Bracket, BracketComponent, BracketImports, BracketMatchComponent, BracketMatchDirective, BracketRoundDirective, BracketRoundHeaderComponent, ButtonComponent, ButtonDirective, ButtonImports, CHECKBOX_FIELD_TOKEN, CHECKBOX_GROUP_CONTROL_TOKEN, CHECKBOX_GROUP_TOKEN, CHECKBOX_TOKEN, COMBOBOX_DIR_TOKEN, COMBOBOX_TOKEN, CellDefDirective, CellDirective, CheckboxComponent, CheckboxDirective, CheckboxFieldComponent, CheckboxFieldDirective, CheckboxGroupComponent, CheckboxGroupControlDirective, CheckboxGroupDirective, CheckboxImports, ChevronIconComponent, ColumnDefDirective, ComboboxComponent, ComboboxDirective, ComboboxImports, DIALOG_CONFIG, DIALOG_DATA, DIALOG_DEFAULT_CONFIG, DIALOG_DEFAULT_OPTIONS, DIALOG_SCROLL_STRATEGY, DIALOG_SCROLL_STRATEGY_PROVIDER, DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY, DYNAMIC_FORM_FIELD_TOKEN, DYNAMIC_FORM_GROUP_TOKEN, DecoratedFormFieldBase, DecoratedInputBase, DefaultValidatorErrorsService, DialogCloseDirective, DialogContainerBaseComponent, DialogContainerComponent, DialogImports, DialogRef, DialogService, DialogServiceBase, DialogTitleDirective, DynamicFormFieldDirective, DynamicFormGroupDirective, DynamicOverlayService, EMAIL_INPUT_TOKEN, EmailInputComponent, EmailInputDirective, ErrorComponent, FooterCellDefDirective, FooterCellDirective, FooterRowComponent, FooterRowDefDirective, FormFieldStateService, FormGroupStateService, HeaderCellDefDirective, HeaderCellDirective, HeaderRowComponent, HeaderRowDefDirective, INPUT_PREFIX_TOKEN, INPUT_SUFFIX_TOKEN, INPUT_TOKEN, IconImports, IfInputEmptyDirective, IfInputFilledDirective, InlineTabBodyComponent, InlineTabBodyHostDirective, InlineTabChangeEvent, InlineTabComponent, InlineTabContentDirective, InlineTabHeaderComponent, InlineTabLabelDirective, InlineTabLabelWrapperDirective, InlineTabsComponent, InputBase, InputDirective, InputFieldComponent, InputImports, InputPrefixDirective, InputStateService, InputSuffixDirective, LABEL_TOKEN, LabelComponent, LabelImports, LabelSuffixDirective, MASONRY_ITEM_TOKEN, MAX_SAFE_INTEGER, MasonryComponent, MasonryImports, MasonryItemComponent, NATIVE_INPUT_REF_TOKEN, NATIVE_SELECT_INPUT_TOKEN, NATIVE_SELECT_OPTION_TOKEN, NUMBER_INPUT_TOKEN, NativeInputRefDirective, NativeSelectImports, NativeSelectInputComponent, NativeSelectInputDirective, NativeSelectOptionComponent, NativeSelectOptionDirective, NavTabLinkComponent, NavTabsComponent, NavTabsOutletComponent, NoDataRowDirective, NumberInputComponent, NumberInputDirective, PASSWORD_INPUT_TOKEN, PROGRESS_SPINNER_DEFAULT_OPTIONS, PROGRESS_SPINNER_DEFAULT_OPTIONS_FACTORY, PaginatedTabHeaderDirective, PaginationComponent, PaginationImports, PasswordInputComponent, PasswordInputDirective, PasswordInputToggleComponent, PictureComponent, PictureDataDirective, ProgressSpinnerComponent, QueryButtonComponent, QueryButtonDirective, RADIO_FIELD_TOKEN, RADIO_GROUP_TOKEN, RADIO_TOKEN, RadioComponent, RadioDirective, RadioFieldComponent, RadioFieldDirective, RadioGroupComponent, RadioGroupDirective, RadioImports, RecycleRowsDirective, RowComponent, RowDefDirective, SEARCH_INPUT_TOKEN, SEGMENTED_BUTTON_FIELD_TOKEN, SEGMENTED_BUTTON_GROUP_TOKEN, SEGMENTED_BUTTON_TOKEN, SELECT_BODY_TOKEN, SELECT_FIELD_TOKEN, SELECT_OPTION_TOKEN, SELECT_TOKEN, SLIDE_TOGGLE_TOKEN, SORT_DEFAULT_OPTIONS, SORT_HEADER_COLUMN_DEF, SORT_HEADER_INTL_PROVIDER, SORT_HEADER_INTL_PROVIDER_FACTORY, STATIC_FORM_FIELD_TOKEN, STATIC_FORM_GROUP_TOKEN, ScrollableComponent, ScrollableImports, SearchInputClearComponent, SearchInputComponent, SearchInputDirective, SegmentedButtonComponent, SegmentedButtonDirective, SegmentedButtonFieldComponent, SegmentedButtonFieldDirective, SegmentedButtonGroupComponent, SegmentedButtonGroupDirective, SegmentedButtonImports, SelectBodyComponent, SelectBodyDirective, SelectComponent, SelectDirective, SelectFieldComponent, SelectFieldDirective, SelectImports, SelectOptionComponent, SelectOptionDirective, SkeletonComponent, SkeletonImports, SkeletonItemComponent, SlideToggleComponent, SlideToggleDirective, SlideToggleFieldComponent, SlideToggleImports, SliderComponent, SliderFieldComponent, SliderImports, SortDirective, SortHeaderComponent, SortHeaderIntl, SortImports, StaticFormFieldDirective, StaticFormGroupDirective, SwipeHandlerService, TAB, TABS_CONFIG, TAB_CONTENT, TAB_GROUP, TAB_LABEL, TEXTAREA_INPUT_TOKEN, TEXT_INPUT_TOKEN, TOGGLETIP, TOGGLETIP_CONFIG, TOGGLETIP_DEFAULT_CONFIG, TOGGLETIP_DIRECTIVE, TOGGLETIP_TEMPLATE, TOGGLETIP_TEXT, TOOLTIP, TOOLTIP_CONFIG, TOOLTIP_DEFAULT_CONFIG, TOOLTIP_DIRECTIVE, TOOLTIP_TEMPLATE, TOOLTIP_TEXT, TabImports, TableBusyDirective, TableBusyOutletDirective, TableComponent, TableDataSource, TableImports, TextColumnComponent, TextInputComponent, TextInputDirective, TextareaInputComponent, TextareaInputDirective, ToggletipComponent, ToggletipDirective, ToggletipImports, TooltipComponent, TooltipDirective, TooltipImports, VALIDATOR_ERROR_SERVICE_TOKEN, WRITEABLE_INPUT_TOKEN, WRITEABLE_INPUT_VALUE_ACCESSOR, WriteableInputDirective, _MAT_INK_BAR_POSITIONER, _MAT_INK_BAR_POSITIONER_FACTORY, accordionAnimations, createBottomSheetConfig, createBracketConfig, createDialogConfig, createToggletipConfig, createTooltipConfig, getClosestBottomSheet, getClosestDialog, isUpperBracketMatch, normalizeRoundType, orderRounds, orderRoundsByRoundNumber, paginate, provideBottomSheet, provideBottomSheetDefaultConfig, provideBracketConfig, provideDialog, provideDialogDefaultConfig, provideSort, provideToggletipConfig, provideTooltipConfig, provideValidatorErrorsService, tabAnimations };
10338
10290
  //# sourceMappingURL=ethlete-cdk.mjs.map