@eui/ecl 15.0.0-rc.13 → 15.0.0-rc.15

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 (27) hide show
  1. package/docs/components/EclCarouselComponent.html +138 -1
  2. package/docs/components/EclMultiselectComponent.html +1 -0
  3. package/docs/components/EclRadioLabelComponent.html +1 -1
  4. package/docs/dependencies.html +2 -2
  5. package/docs/directives/EclRadioDirective.html +1 -2
  6. package/docs/injectables/EclDefaultLanguageService.html +1 -1
  7. package/docs/js/search/search_index.js +2 -2
  8. package/docs/miscellaneous/enumerations.html +34 -4
  9. package/esm2020/lib/components/ecl-carousel/ecl-carousel.component.mjs +52 -23
  10. package/esm2020/lib/components/ecl-multiselect/ecl-multiselect.component.mjs +238 -45
  11. package/esm2020/lib/components/ecl-radio/ecl-radio-label.component.mjs +3 -3
  12. package/esm2020/lib/components/ecl-radio/ecl-radio.directive.mjs +7 -10
  13. package/esm2020/lib/components/ecl-select/ecl-select.directive.mjs +3 -4
  14. package/esm2020/lib/services/ecl-default-language.service.mjs +3 -3
  15. package/fesm2015/eui-ecl.mjs +319 -100
  16. package/fesm2015/eui-ecl.mjs.map +1 -1
  17. package/fesm2020/eui-ecl.mjs +318 -100
  18. package/fesm2020/eui-ecl.mjs.map +1 -1
  19. package/lib/components/ecl-carousel/ecl-carousel.component.d.ts +13 -4
  20. package/lib/components/ecl-carousel/ecl-carousel.component.d.ts.map +1 -1
  21. package/lib/components/ecl-multiselect/ecl-multiselect.component.d.ts +29 -5
  22. package/lib/components/ecl-multiselect/ecl-multiselect.component.d.ts.map +1 -1
  23. package/lib/components/ecl-radio/ecl-radio.directive.d.ts +5 -6
  24. package/lib/components/ecl-radio/ecl-radio.directive.d.ts.map +1 -1
  25. package/lib/components/ecl-select/ecl-select.directive.d.ts.map +1 -1
  26. package/lib/services/ecl-default-language.service.d.ts.map +1 -1
  27. package/package.json +1 -1
@@ -8,7 +8,7 @@ import { __decorate } from 'tslib';
8
8
  import { coerceBoolean, coerceElement, coerceNumber, coerceArray, DefaultConfig, EuiPagination } from '@eui/base';
9
9
  import * as i2$1 from '@eui/core';
10
10
  import { GLOBAL_CONFIG_TOKEN } from '@eui/core';
11
- import { Subject, takeUntil, interval, delay, fromEvent, of } from 'rxjs';
11
+ import { ReplaySubject, Subject, takeUntil, switchMap, interval, delay, fromEvent, of } from 'rxjs';
12
12
  import { takeUntil as takeUntil$1, mergeWith } from 'rxjs/operators';
13
13
  import * as i1$1 from '@angular/forms';
14
14
  import { NG_VALUE_ACCESSOR, ReactiveFormsModule, FormsModule } from '@angular/forms';
@@ -546,7 +546,7 @@ class EclDefaultLanguageService {
546
546
  constructor(config, i18nService) {
547
547
  this.config = config;
548
548
  this.i18nService = i18nService;
549
- this.currentLanguage$ = new Subject();
549
+ this.currentLanguage$ = new ReplaySubject();
550
550
  this.FALLBACK_LANGUAGE = { code: 'en', label: 'English' };
551
551
  this.destroy$ = new Subject();
552
552
  this.handleActiveLanguageChangeState();
@@ -3934,6 +3934,9 @@ class EclCarouselComponent extends ECLBaseDirective {
3934
3934
  this.playInterval = 5000;
3935
3935
  this.slide = new EventEmitter();
3936
3936
  this.isPlaying = false;
3937
+ this.isPaused = false;
3938
+ this.playSubject = new Subject();
3939
+ this.stopSubject = new Subject();
3937
3940
  this.isMobileBreakpoint = false;
3938
3941
  this.destroy$ = new Subject();
3939
3942
  }
@@ -3942,6 +3945,9 @@ class EclCarouselComponent extends ECLBaseDirective {
3942
3945
  super.getCssClasses('ecl-carousel')
3943
3946
  ].join(' ').trim();
3944
3947
  }
3948
+ ngOnInit() {
3949
+ this.initAutoplay();
3950
+ }
3945
3951
  ngAfterContentInit() {
3946
3952
  this.observeBreakpointChanges();
3947
3953
  this.initializeSlider();
@@ -3972,6 +3978,15 @@ class EclCarouselComponent extends ECLBaseDirective {
3972
3978
  this.stopPlaying();
3973
3979
  this.goToPreviousSlide();
3974
3980
  }
3981
+ onSlideHover() {
3982
+ this.pausePlaying();
3983
+ }
3984
+ onSlideHoverout() {
3985
+ this.resumePlaying();
3986
+ }
3987
+ isPlayingState() {
3988
+ return this.isPlaying && !this.isPaused;
3989
+ }
3975
3990
  isPadded() {
3976
3991
  return !this.isMobileBreakpoint;
3977
3992
  }
@@ -3993,29 +4008,32 @@ class EclCarouselComponent extends ECLBaseDirective {
3993
4008
  getCarouselSlidesOffset() {
3994
4009
  return -1 * this.carouselContainerElement?.offsetWidth * this.getCurrentSlideIndex();
3995
4010
  }
4011
+ initAutoplay() {
4012
+ const start$ = this.playSubject.asObservable();
4013
+ const stop$ = this.stopSubject.asObservable();
4014
+ start$.pipe(switchMap(() => interval(this.playInterval)
4015
+ .pipe(takeUntil(stop$))), takeUntil(this.destroy$)).subscribe(() => {
4016
+ this.goToNextSlide();
4017
+ });
4018
+ }
3996
4019
  initializeSlider() {
3997
4020
  this.slides.forEach((item, idx) => {
3998
- item.index = idx;
3999
- item.ariaLabel = `slide ${idx + 1} of ${this.getSlidesCount()}`;
4000
- item.width = 100 / this.getSlidesCount();
4021
+ this.initSlide(item, idx);
4001
4022
  });
4002
4023
  if (this.hasControls) {
4003
- this.playInterval$ = interval(this.playInterval);
4004
4024
  if (this.isNoSlideSelected()) {
4005
4025
  this.activateSlide(this.slides.first);
4006
4026
  }
4007
- if (this.isAutoplay) {
4027
+ if (this.isAutoplay && !this.isMobileBreakpoint) {
4008
4028
  this.startPlaying();
4009
4029
  }
4010
- this.slides.forEach(item => {
4011
- item.slideClick
4012
- .pipe(takeUntil(this.destroy$))
4013
- .subscribe(() => {
4014
- this.stopPlaying();
4015
- });
4016
- });
4017
4030
  }
4018
4031
  }
4032
+ initSlide(item, idx) {
4033
+ item.index = idx;
4034
+ item.ariaLabel = `slide ${idx + 1} of ${this.getSlidesCount()}`;
4035
+ item.width = 100 / this.getSlidesCount();
4036
+ }
4019
4037
  goToNextSlide() {
4020
4038
  this.activateSlide(this.getNextSlide());
4021
4039
  }
@@ -4033,16 +4051,24 @@ class EclCarouselComponent extends ECLBaseDirective {
4033
4051
  }
4034
4052
  startPlaying() {
4035
4053
  this.isPlaying = true;
4036
- this.playIntervalSubscription = this.playInterval$
4037
- .pipe(takeUntil(this.destroy$))
4038
- .subscribe(n => {
4039
- this.goToNextSlide();
4040
- });
4054
+ this.isPaused = false;
4055
+ this.playSubject.next();
4041
4056
  }
4042
4057
  stopPlaying() {
4043
4058
  this.isPlaying = false;
4044
- if (this.playIntervalSubscription) {
4045
- this.playIntervalSubscription.unsubscribe();
4059
+ this.isPaused = true;
4060
+ this.stopSubject.next();
4061
+ }
4062
+ pausePlaying() {
4063
+ if (this.isPlaying) {
4064
+ this.isPaused = true;
4065
+ this.stopSubject.next();
4066
+ }
4067
+ }
4068
+ resumePlaying() {
4069
+ if (this.isPlaying) {
4070
+ this.isPaused = false;
4071
+ this.playSubject.next();
4046
4072
  }
4047
4073
  }
4048
4074
  getNextSlide() {
@@ -4077,6 +4103,9 @@ class EclCarouselComponent extends ECLBaseDirective {
4077
4103
  .pipe(takeUntil(this.destroy$))
4078
4104
  .subscribe(result => {
4079
4105
  this.isMobileBreakpoint = result.matches;
4106
+ if (this.isMobileBreakpoint) {
4107
+ this.stopPlaying();
4108
+ }
4080
4109
  });
4081
4110
  }
4082
4111
  observeElementSizeChanges() {
@@ -4086,7 +4115,7 @@ class EclCarouselComponent extends ECLBaseDirective {
4086
4115
  }
4087
4116
  }
4088
4117
  /** @nocollapse */ EclCarouselComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclCarouselComponent, deps: [{ token: i0.Renderer2 }, { token: i1$2.BreakpointObserver }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4089
- /** @nocollapse */ EclCarouselComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: EclCarouselComponent, selector: "ecl-carousel", inputs: { isAutoplay: "isAutoplay", playInterval: "playInterval" }, outputs: { slide: "slide" }, host: { properties: { "class": "this.cssClasses" } }, queries: [{ propertyName: "slides", predicate: i0.forwardRef(function () { return EclCarouselItemComponent; }) }], viewQueries: [{ propertyName: "carouselContainerElement", first: true, predicate: ["carouselContainer"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div #carouselContainer \n class=\"ecl-carousel__container\" \n [class.ecl-carousel-container--padded]=\"isPadded()\">\n <div class=\"ecl-carousel__slides\"\n [style.width.px]=\"getCarouselSlidesWidth()\" \n [style.left.px]=\"getCarouselSlidesOffset()\">\n <ng-content></ng-content>\n </div>\n\n <button *ngIf=\"hasControls() && !isMobileBreakpoint\"\n class=\"ecl-carousel__prev\" \n (click)=\"onPreviousSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-270\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PREV-SLIDES' | translate }}</span>\n </button>\n\n <button *ngIf=\"hasControls() && !isMobileBreakpoint\"\n class=\"ecl-carousel__next\" \n (click)=\"onNextSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-90\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.NEXT-SLIDES' | translate }}</div>\n </button>\n</div>\n\n<div *ngIf=\"hasControls()\" \n class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__autoplay\">\n <button *ngIf=\"!isPlaying\" \n class=\"ecl-carousel__play\"\n (click)=\"onPlayClick()\">\n <ecl-icon \n icon=\"play\" \n size=\"l\" \n class=\"ecl-carousel__icon-default\"\n isInverted>\n </ecl-icon>\n <ecl-icon \n icon=\"play-filled\" \n size=\"l\" \n class=\"ecl-carousel__icon-active\"\n isInverted>\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.AUTOPLAY' | translate }}</div>\n </button>\n <button *ngIf=\"isPlaying\" \n class=\"ecl-carousel__pause\"\n (click)=\"onPauseClick()\">\n <ecl-icon \n icon=\"pause\" \n size=\"l\" \n class=\"ecl-carousel__icon-default\"\n isInverted>\n </ecl-icon>\n <ecl-icon \n icon=\"pause-filled\" \n size=\"l\" \n class=\"ecl-carousel__icon-active\"\n isInverted>\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PAUSE' | translate }}</div>\n </button>\n </div>\n\n <div class=\"ecl-carousel__navigation\">\n <button \n *ngFor=\"let slide of slides; let i = index\" \n [attr.aria-current]=\"slide.isCurrent\"\n class=\"ecl-carousel__navigation-item\"\n (click)=\"onSlideControlClick(slide)\">\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.GO-TO-SLIDE' | translate }} {{ i + 1 }}</span>\n </button>\n </div>\n\n <button *ngIf=\"isMobileBreakpoint\"\n class=\"ecl-carousel__prev\" \n (click)=\"onPreviousSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-270\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PREV-SLIDES' | translate }}</span>\n </button>\n \n <div class=\"ecl-carousel__pagination\">\n <span class=\"ecl-carousel__current\">{{ getCurrentSlideIndex() + 1 }}</span>\n {{ 'ecl.common.OF' | translate }}\n <span class=\"ecl-carousel__max\">{{ slides.length }}</span>\n </div>\n\n <button *ngIf=\"isMobileBreakpoint\"\n class=\"ecl-carousel__next\" \n (click)=\"onNextSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-90\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.NEXT-SLIDES' | translate }}</div>\n </button>\n </div>\n</div>", styles: [":host{display:block}.ecl-carousel__container{width:100%}.ecl-carousel__slides{transition-duration:.4s}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "isInverted", "ariaHidden", "focusable"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
4118
+ /** @nocollapse */ EclCarouselComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: EclCarouselComponent, selector: "ecl-carousel", inputs: { isAutoplay: "isAutoplay", playInterval: "playInterval" }, outputs: { slide: "slide" }, host: { properties: { "class": "this.cssClasses" } }, queries: [{ propertyName: "slides", predicate: i0.forwardRef(function () { return EclCarouselItemComponent; }) }], viewQueries: [{ propertyName: "carouselContainerElement", first: true, predicate: ["carouselContainer"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div #carouselContainer \n class=\"ecl-carousel__container\" \n [class.ecl-carousel-container--padded]=\"isPadded()\">\n <div class=\"ecl-carousel__slides\"\n [style.width.px]=\"getCarouselSlidesWidth()\" \n [style.left.px]=\"getCarouselSlidesOffset()\"\n (mouseover)=\"onSlideHover()\"\n (mouseout)=\"onSlideHoverout()\">\n <ng-content></ng-content>\n </div>\n\n <button *ngIf=\"hasControls() && !isMobileBreakpoint\"\n class=\"ecl-carousel__prev\" \n (click)=\"onPreviousSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-270\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PREV-SLIDES' | translate }}</span>\n </button>\n\n <button *ngIf=\"hasControls() && !isMobileBreakpoint\"\n class=\"ecl-carousel__next\" \n (click)=\"onNextSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-90\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.NEXT-SLIDES' | translate }}</div>\n </button>\n</div>\n\n<div *ngIf=\"hasControls()\" \n class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__autoplay\">\n <button *ngIf=\"!isPlayingState()\" \n class=\"ecl-carousel__play\"\n (click)=\"onPlayClick()\">\n <ecl-icon \n icon=\"play\" \n size=\"l\" \n class=\"ecl-carousel__icon-default\"\n isInverted>\n </ecl-icon>\n <ecl-icon \n icon=\"play-filled\" \n size=\"l\" \n class=\"ecl-carousel__icon-active\"\n isInverted>\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.AUTOPLAY' | translate }}</div>\n </button>\n <button *ngIf=\"isPlayingState()\" \n class=\"ecl-carousel__pause\"\n (click)=\"onPauseClick()\">\n <ecl-icon \n icon=\"pause\" \n size=\"l\" \n class=\"ecl-carousel__icon-default\"\n isInverted>\n </ecl-icon>\n <ecl-icon \n icon=\"pause-filled\" \n size=\"l\" \n class=\"ecl-carousel__icon-active\"\n isInverted>\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PAUSE' | translate }}</div>\n </button>\n </div>\n\n <div class=\"ecl-carousel__navigation\">\n <button \n *ngFor=\"let slide of slides; let i = index\" \n [attr.aria-current]=\"slide.isCurrent\"\n class=\"ecl-carousel__navigation-item\"\n (click)=\"onSlideControlClick(slide)\">\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.GO-TO-SLIDE' | translate }} {{ i + 1 }}</span>\n </button>\n </div>\n\n <button *ngIf=\"isMobileBreakpoint\"\n class=\"ecl-carousel__prev\" \n (click)=\"onPreviousSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-270\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PREV-SLIDES' | translate }}</span>\n </button>\n \n <div class=\"ecl-carousel__pagination\">\n <span class=\"ecl-carousel__current\">{{ getCurrentSlideIndex() + 1 }}</span>\n {{ 'ecl.common.OF' | translate }}\n <span class=\"ecl-carousel__max\">{{ slides.length }}</span>\n </div>\n\n <button *ngIf=\"isMobileBreakpoint\"\n class=\"ecl-carousel__next\" \n (click)=\"onNextSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-90\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.NEXT-SLIDES' | translate }}</div>\n </button>\n </div>\n</div>", styles: [":host{display:block}.ecl-carousel__container{width:100%}.ecl-carousel__slides{transition-duration:.4s}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "isInverted", "ariaHidden", "focusable"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
4090
4119
  __decorate([
4091
4120
  coerceBoolean
4092
4121
  ], EclCarouselComponent.prototype, "isAutoplay", void 0);
@@ -4098,7 +4127,7 @@ __decorate([
4098
4127
  ], EclCarouselComponent.prototype, "carouselContainerElement", void 0);
4099
4128
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclCarouselComponent, decorators: [{
4100
4129
  type: Component,
4101
- args: [{ selector: 'ecl-carousel', template: "<div #carouselContainer \n class=\"ecl-carousel__container\" \n [class.ecl-carousel-container--padded]=\"isPadded()\">\n <div class=\"ecl-carousel__slides\"\n [style.width.px]=\"getCarouselSlidesWidth()\" \n [style.left.px]=\"getCarouselSlidesOffset()\">\n <ng-content></ng-content>\n </div>\n\n <button *ngIf=\"hasControls() && !isMobileBreakpoint\"\n class=\"ecl-carousel__prev\" \n (click)=\"onPreviousSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-270\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PREV-SLIDES' | translate }}</span>\n </button>\n\n <button *ngIf=\"hasControls() && !isMobileBreakpoint\"\n class=\"ecl-carousel__next\" \n (click)=\"onNextSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-90\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.NEXT-SLIDES' | translate }}</div>\n </button>\n</div>\n\n<div *ngIf=\"hasControls()\" \n class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__autoplay\">\n <button *ngIf=\"!isPlaying\" \n class=\"ecl-carousel__play\"\n (click)=\"onPlayClick()\">\n <ecl-icon \n icon=\"play\" \n size=\"l\" \n class=\"ecl-carousel__icon-default\"\n isInverted>\n </ecl-icon>\n <ecl-icon \n icon=\"play-filled\" \n size=\"l\" \n class=\"ecl-carousel__icon-active\"\n isInverted>\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.AUTOPLAY' | translate }}</div>\n </button>\n <button *ngIf=\"isPlaying\" \n class=\"ecl-carousel__pause\"\n (click)=\"onPauseClick()\">\n <ecl-icon \n icon=\"pause\" \n size=\"l\" \n class=\"ecl-carousel__icon-default\"\n isInverted>\n </ecl-icon>\n <ecl-icon \n icon=\"pause-filled\" \n size=\"l\" \n class=\"ecl-carousel__icon-active\"\n isInverted>\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PAUSE' | translate }}</div>\n </button>\n </div>\n\n <div class=\"ecl-carousel__navigation\">\n <button \n *ngFor=\"let slide of slides; let i = index\" \n [attr.aria-current]=\"slide.isCurrent\"\n class=\"ecl-carousel__navigation-item\"\n (click)=\"onSlideControlClick(slide)\">\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.GO-TO-SLIDE' | translate }} {{ i + 1 }}</span>\n </button>\n </div>\n\n <button *ngIf=\"isMobileBreakpoint\"\n class=\"ecl-carousel__prev\" \n (click)=\"onPreviousSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-270\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PREV-SLIDES' | translate }}</span>\n </button>\n \n <div class=\"ecl-carousel__pagination\">\n <span class=\"ecl-carousel__current\">{{ getCurrentSlideIndex() + 1 }}</span>\n {{ 'ecl.common.OF' | translate }}\n <span class=\"ecl-carousel__max\">{{ slides.length }}</span>\n </div>\n\n <button *ngIf=\"isMobileBreakpoint\"\n class=\"ecl-carousel__next\" \n (click)=\"onNextSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-90\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.NEXT-SLIDES' | translate }}</div>\n </button>\n </div>\n</div>", styles: [":host{display:block}.ecl-carousel__container{width:100%}.ecl-carousel__slides{transition-duration:.4s}\n"] }]
4130
+ args: [{ selector: 'ecl-carousel', template: "<div #carouselContainer \n class=\"ecl-carousel__container\" \n [class.ecl-carousel-container--padded]=\"isPadded()\">\n <div class=\"ecl-carousel__slides\"\n [style.width.px]=\"getCarouselSlidesWidth()\" \n [style.left.px]=\"getCarouselSlidesOffset()\"\n (mouseover)=\"onSlideHover()\"\n (mouseout)=\"onSlideHoverout()\">\n <ng-content></ng-content>\n </div>\n\n <button *ngIf=\"hasControls() && !isMobileBreakpoint\"\n class=\"ecl-carousel__prev\" \n (click)=\"onPreviousSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-270\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PREV-SLIDES' | translate }}</span>\n </button>\n\n <button *ngIf=\"hasControls() && !isMobileBreakpoint\"\n class=\"ecl-carousel__next\" \n (click)=\"onNextSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-90\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.NEXT-SLIDES' | translate }}</div>\n </button>\n</div>\n\n<div *ngIf=\"hasControls()\" \n class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__autoplay\">\n <button *ngIf=\"!isPlayingState()\" \n class=\"ecl-carousel__play\"\n (click)=\"onPlayClick()\">\n <ecl-icon \n icon=\"play\" \n size=\"l\" \n class=\"ecl-carousel__icon-default\"\n isInverted>\n </ecl-icon>\n <ecl-icon \n icon=\"play-filled\" \n size=\"l\" \n class=\"ecl-carousel__icon-active\"\n isInverted>\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.AUTOPLAY' | translate }}</div>\n </button>\n <button *ngIf=\"isPlayingState()\" \n class=\"ecl-carousel__pause\"\n (click)=\"onPauseClick()\">\n <ecl-icon \n icon=\"pause\" \n size=\"l\" \n class=\"ecl-carousel__icon-default\"\n isInverted>\n </ecl-icon>\n <ecl-icon \n icon=\"pause-filled\" \n size=\"l\" \n class=\"ecl-carousel__icon-active\"\n isInverted>\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PAUSE' | translate }}</div>\n </button>\n </div>\n\n <div class=\"ecl-carousel__navigation\">\n <button \n *ngFor=\"let slide of slides; let i = index\" \n [attr.aria-current]=\"slide.isCurrent\"\n class=\"ecl-carousel__navigation-item\"\n (click)=\"onSlideControlClick(slide)\">\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.GO-TO-SLIDE' | translate }} {{ i + 1 }}</span>\n </button>\n </div>\n\n <button *ngIf=\"isMobileBreakpoint\"\n class=\"ecl-carousel__prev\" \n (click)=\"onPreviousSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-270\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <span class=\"ecl-u-sr-only\">{{ 'ecl.carousel.PREV-SLIDES' | translate }}</span>\n </button>\n \n <div class=\"ecl-carousel__pagination\">\n <span class=\"ecl-carousel__current\">{{ getCurrentSlideIndex() + 1 }}</span>\n {{ 'ecl.common.OF' | translate }}\n <span class=\"ecl-carousel__max\">{{ slides.length }}</span>\n </div>\n\n <button *ngIf=\"isMobileBreakpoint\"\n class=\"ecl-carousel__next\" \n (click)=\"onNextSlideClick()\">\n <ecl-icon \n icon=\"corner-arrow\" \n size=\"m\" \n transform=\"rotate-90\" \n isInverted \n class=\"ecl-carousel__icon-default\">\n </ecl-icon>\n <div class=\"ecl-u-sr-only\">{{ 'ecl.carousel.NEXT-SLIDES' | translate }}</div>\n </button>\n </div>\n</div>", styles: [":host{display:block}.ecl-carousel__container{width:100%}.ecl-carousel__slides{transition-duration:.4s}\n"] }]
4102
4131
  }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i1$2.BreakpointObserver }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { isAutoplay: [{
4103
4132
  type: Input
4104
4133
  }], playInterval: [{
@@ -8542,8 +8571,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImpor
8542
8571
 
8543
8572
  var KEY_CODE;
8544
8573
  (function (KEY_CODE) {
8545
- KEY_CODE[KEY_CODE["RIGHT_ARROW"] = 39] = "RIGHT_ARROW";
8546
- KEY_CODE[KEY_CODE["LEFT_ARROW"] = 37] = "LEFT_ARROW";
8574
+ KEY_CODE["ARROW_UP"] = "ArrowUp";
8575
+ KEY_CODE["ARROW_DOWN"] = "ArrowDown";
8576
+ KEY_CODE["ESCAPE"] = "Escape";
8577
+ KEY_CODE["ENTER"] = "Enter";
8578
+ KEY_CODE["TAB"] = "Tab";
8547
8579
  })(KEY_CODE || (KEY_CODE = {}));
8548
8580
  class EclMultiselectComponent extends ECLBaseDirective {
8549
8581
  constructor(ngControl, el, viewContainerRef, differs, translate) {
@@ -8568,6 +8600,7 @@ class EclMultiselectComponent extends ECLBaseDirective {
8568
8600
  if (this.ngControl) {
8569
8601
  this.ngControl.valueAccessor = this;
8570
8602
  }
8603
+ this.bindCallbacks();
8571
8604
  }
8572
8605
  set eclPlaceholder(value) {
8573
8606
  this._eclPlaceholder = value;
@@ -8594,7 +8627,6 @@ class EclMultiselectComponent extends ECLBaseDirective {
8594
8627
  this.hostParentEl = this.getHostParentElement(this.hostEl);
8595
8628
  this.hostWrapperEl = this.createHostWrapperContainer();
8596
8629
  this.selectIconContainerEl = this.createIconContainer();
8597
- this.eclIconComponentEl = this.createIconComponent();
8598
8630
  this.multiselectWrapper = this.createWrapperMultiselect();
8599
8631
  this.multiselectContainer = this.createSelectContainerMultiselect();
8600
8632
  if (this.hostParentEl != null) {
@@ -8607,6 +8639,7 @@ class EclMultiselectComponent extends ECLBaseDirective {
8607
8639
  ngDoCheck() {
8608
8640
  this.multiselectContainer.classList.toggle('ecl-select__container--disabled', this.disabled);
8609
8641
  this.multiselectContainer.classList.toggle('ecl-select__container--invalid', this.isInvalid);
8642
+ this.handleSelectAllDisableStatus();
8610
8643
  if (this.disabled) {
8611
8644
  this.multiSelectInput.disabled = true;
8612
8645
  }
@@ -8627,6 +8660,7 @@ class EclMultiselectComponent extends ECLBaseDirective {
8627
8660
  ngOnDestroy() {
8628
8661
  this.destroy$.next(true);
8629
8662
  this.destroy$.unsubscribe();
8663
+ this.removeAllListeners();
8630
8664
  }
8631
8665
  writeValue(value) {
8632
8666
  if (value) {
@@ -8645,25 +8679,12 @@ class EclMultiselectComponent extends ECLBaseDirective {
8645
8679
  this.propagateTouched = fn;
8646
8680
  }
8647
8681
  onEscapeKey(event) {
8648
- this.multiDropdown.style.display = 'none';
8682
+ this.closeMultiselectDropdown();
8649
8683
  }
8650
- // @HostListener('keyup.ArrowDown', ['$event']) onArrowDownKey(event: KeyboardEvent) {
8651
- // this.multiDropdown.style.display = 'block';
8652
- // }
8653
- // @HostListener('window:keyup', ['$event'])
8654
- // keyEvent(event: KeyboardEvent) {
8655
- // console.log(event);
8656
- // if (event.key === KEY_CODE.RIGHT_ARROW) {
8657
- // this.increment();
8658
- // }
8659
- // if (event.keyCode === KEY_CODE.LEFT_ARROW) {
8660
- // this.decrement();
8661
- // }
8662
- // }
8663
8684
  onKeyUp(ev) {
8664
8685
  const isClickInside = this.multiDropdown.contains(ev.target) || this.multiSelectInput.contains(ev.target);
8665
8686
  if (!isClickInside) {
8666
- this.multiDropdown.style.display = 'none';
8687
+ this.closeMultiselectDropdown();
8667
8688
  }
8668
8689
  }
8669
8690
  removeAllOptions() {
@@ -8691,7 +8712,7 @@ class EclMultiselectComponent extends ECLBaseDirective {
8691
8712
  this.hostParentEl.appendChild(this.multiselectWrapper);
8692
8713
  this.multiselectWrapper.appendChild(this.multiselectContainer);
8693
8714
  this.multiselectContainer.appendChild(this.selectIconContainerEl);
8694
- this.selectIconContainerEl.appendChild(this.eclIconComponentEl);
8715
+ this.selectIconContainerEl.appendChild(this.createIconComponent());
8695
8716
  }
8696
8717
  buildMultiselectDropdown(withOptions) {
8697
8718
  this.multiDropdown = this.createDropdownForMultiselect();
@@ -8737,12 +8758,10 @@ class EclMultiselectComponent extends ECLBaseDirective {
8737
8758
  if (this.hostEl.hasAttribute('formControlName')) {
8738
8759
  this.multiSelectInput.setAttribute('formControlName', this.hostEl.getAttribute('formControlName'));
8739
8760
  }
8740
- this.multiSelectInput.onclick = (e) => {
8741
- e.preventDefault();
8742
- this.multiDropdown.style.display = this.multiDropdown.style.display === 'none' ? 'block' : 'none';
8743
- };
8761
+ this.multiSelectInput.addEventListener('click', this.handleClickOnMainInput);
8744
8762
  this.multiSelectInput.classList.add('ecl-select');
8745
8763
  this.multiSelectInput.classList.add('ecl-select__multiple-toggle');
8764
+ this.multiSelectInput.addEventListener('keydown', this.handleKeydownOnMainInput);
8746
8765
  if (this.disabled) {
8747
8766
  this.multiSelectInput.disabled = true;
8748
8767
  }
@@ -8763,10 +8782,9 @@ class EclMultiselectComponent extends ECLBaseDirective {
8763
8782
  multiSearch.type = 'text';
8764
8783
  multiSearch.classList.add('ecl-text-input');
8765
8784
  multiSearch.placeholder = 'Search';
8766
- // Search elements. Elements that don't match the criteria are hidden
8767
- multiSearch.onkeyup = () => {
8768
- this.searchOptions(multiSearch.value);
8769
- };
8785
+ multiSearch.addEventListener('keydown', this.handleKeydownOnSearch);
8786
+ multiSearch.addEventListener('keyup', this.onSearchOptions);
8787
+ this.searchEl = multiSearch;
8770
8788
  return multiSearch;
8771
8789
  }
8772
8790
  createOptionWithCheckbox(el) {
@@ -8784,17 +8802,14 @@ class EclMultiselectComponent extends ECLBaseDirective {
8784
8802
  checkboxInput.disabled = true;
8785
8803
  }
8786
8804
  else {
8787
- checkboxInput.onclick = () => {
8788
- this.updateCurrentValue();
8789
- this.propagateTouched();
8790
- this.eclChange.emit(this.selectedValues);
8791
- };
8805
+ checkboxInput.addEventListener('click', this.handleClickOnOption);
8792
8806
  }
8793
8807
  if (el.selected || (this.selectedValues.indexOf(el.value) > -1)) {
8794
8808
  checkboxInput.checked = true;
8795
8809
  this.multiSelectInput.value = this.multiSelectInput.value === '' ? el.label :
8796
8810
  this.multiSelectInput.value + ',' + el.label;
8797
8811
  }
8812
+ checkboxInput.addEventListener('keydown', this.handleKeydownOnOption);
8798
8813
  checkboxDiv.appendChild(checkboxInput);
8799
8814
  const checkboxLabel = this.createCheckboxLabel(el.label, id);
8800
8815
  checkboxDiv.appendChild(checkboxLabel);
@@ -8819,8 +8834,8 @@ class EclMultiselectComponent extends ECLBaseDirective {
8819
8834
  }
8820
8835
  // Add/remove values from the select input
8821
8836
  updateCurrentValue() {
8822
- let selectedElementsArray = [];
8823
- let selectedElementsValuesArray = [];
8837
+ const selectedElementsArray = [];
8838
+ const selectedElementsValuesArray = [];
8824
8839
  this.checkboxSelectAll.checked = false;
8825
8840
  this.multiSelectOptions.forEach(el => {
8826
8841
  const input = el.childNodes[0];
@@ -8840,13 +8855,12 @@ class EclMultiselectComponent extends ECLBaseDirective {
8840
8855
  checkboxDiv.classList.add('ecl-checkbox');
8841
8856
  checkboxDiv.classList.add('ecl-select__multiple-all');
8842
8857
  this.checkboxSelectAll = this.createCheckboxInput('select-multiple-all' + idStr.substring(idStr.lastIndexOf('.') + 1), 'all');
8843
- this.checkboxSelectAll.onclick = () => {
8844
- this.propagateTouched();
8845
- this.selectAll();
8846
- };
8858
+ this.checkboxSelectAll.addEventListener('keydown', this.handleKeydownOnSelectAll);
8859
+ this.checkboxSelectAll.addEventListener('click', this.handleClickOnSelectAll);
8847
8860
  checkboxDiv.appendChild(this.checkboxSelectAll);
8848
8861
  this.checkboxLabel = this.createCheckboxLabel('Select all', 'select-multiple-all' + idStr.substring(idStr.lastIndexOf('.') + 1));
8849
8862
  checkboxDiv.appendChild(this.checkboxLabel);
8863
+ this.selectAllEll = checkboxDiv;
8850
8864
  return checkboxDiv;
8851
8865
  }
8852
8866
  createOptionsWrapper() {
@@ -8854,9 +8868,9 @@ class EclMultiselectComponent extends ECLBaseDirective {
8854
8868
  div.classList.add('ecl-select__multiple-options');
8855
8869
  return div;
8856
8870
  }
8857
- selectAll() {
8858
- let selectedElementsArray = [];
8859
- let selectedElementsValuesArray = [];
8871
+ onSelectAll() {
8872
+ const selectedElementsArray = [];
8873
+ const selectedElementsValuesArray = [];
8860
8874
  // Select all the elements, that are not disabled
8861
8875
  this.multiSelectOptions.filter(elem => elem.style.display !== 'none').forEach(el => {
8862
8876
  const input = el.childNodes[0];
@@ -8888,17 +8902,26 @@ class EclMultiselectComponent extends ECLBaseDirective {
8888
8902
  selectIconContainer.classList.add('ecl-select__icon');
8889
8903
  return selectIconContainer;
8890
8904
  }
8891
- searchOptions(keyword = '') {
8905
+ onSearchOptions(evt) {
8906
+ const keyword = evt.target.value;
8892
8907
  if (keyword === '') {
8893
8908
  this.multiSelectOptions.forEach(item => {
8894
8909
  item.style.display = 'flex';
8895
8910
  });
8896
8911
  }
8897
- this.multiSelectOptions.forEach((item, cnt) => {
8912
+ this.multiSelectOptions.forEach(item => {
8898
8913
  if (item.textContent.toLowerCase().indexOf(keyword.toLowerCase()) < 0) {
8899
8914
  item.style.display = 'none';
8900
8915
  }
8916
+ else {
8917
+ item.style.display = 'flex';
8918
+ }
8901
8919
  });
8920
+ this.handleSelectAllDisableStatus();
8921
+ }
8922
+ handleSelectAllDisableStatus() {
8923
+ this.checkboxSelectAll.disabled = this.getActiveOptions().length < 2;
8924
+ this.selectAllEll.classList.toggle('ecl-checkbox--disabled', this.checkboxSelectAll.disabled);
8902
8925
  }
8903
8926
  resetComponent() {
8904
8927
  this.multiSelectOptions.forEach(el => {
@@ -8916,10 +8939,209 @@ class EclMultiselectComponent extends ECLBaseDirective {
8916
8939
  .stream('ecl.multiselect.SELECT-ALL')
8917
8940
  .pipe(takeUntil(this.destroy$)).subscribe((translation) => {
8918
8941
  if (this.checkboxLabel) {
8919
- this.checkboxLabel.textContent = translation;
8942
+ this.checkboxLabel.lastElementChild.textContent = translation;
8920
8943
  }
8921
8944
  });
8922
8945
  }
8946
+ closeMultiselectDropdown() {
8947
+ this.multiDropdown.style.display = 'none';
8948
+ }
8949
+ openMultiselect() {
8950
+ this.multiDropdown.style.display = 'block';
8951
+ }
8952
+ getOptionIndexByIdFromActiveOptions(id) {
8953
+ return this.getActiveOptions().findIndex(option => option.firstElementChild.id === id);
8954
+ }
8955
+ handleClickOnMainInput(evt) {
8956
+ evt.preventDefault();
8957
+ this.toggleDropdown();
8958
+ }
8959
+ toggleDropdown() {
8960
+ this.multiDropdown.style.display = this.multiDropdown.style.display === 'none' ? 'block' : 'none';
8961
+ }
8962
+ handleKeydownOnMainInput(evt) {
8963
+ switch (evt.key) {
8964
+ case KEY_CODE.ARROW_DOWN: {
8965
+ this.onMainInputArrowDown(evt);
8966
+ break;
8967
+ }
8968
+ default: {
8969
+ break;
8970
+ }
8971
+ }
8972
+ }
8973
+ onMainInputArrowDown(evt) {
8974
+ evt.preventDefault();
8975
+ this.openMultiselect();
8976
+ this.searchEl.focus();
8977
+ }
8978
+ handleKeydownOnSearch(evt) {
8979
+ switch (evt.key) {
8980
+ case KEY_CODE.ARROW_DOWN: {
8981
+ this.onSearchArrowDown();
8982
+ break;
8983
+ }
8984
+ case KEY_CODE.ARROW_UP: {
8985
+ this.onSearchArrowUp(evt);
8986
+ break;
8987
+ }
8988
+ case KEY_CODE.ESCAPE: {
8989
+ this.closeMultiselectDropdown();
8990
+ break;
8991
+ }
8992
+ default: {
8993
+ break;
8994
+ }
8995
+ }
8996
+ }
8997
+ onSearchArrowDown() {
8998
+ const currentOptions = this.getActiveOptions();
8999
+ if (currentOptions.length > 1) {
9000
+ this.checkboxSelectAll.focus();
9001
+ }
9002
+ else {
9003
+ const firstOption = currentOptions[0].firstElementChild;
9004
+ firstOption.focus();
9005
+ }
9006
+ ;
9007
+ }
9008
+ onSearchArrowUp(evt) {
9009
+ evt.preventDefault();
9010
+ this.closeMultiselectDropdown();
9011
+ this.multiSelectInput.focus();
9012
+ }
9013
+ handleClickOnSelectAll() {
9014
+ this.propagateTouched();
9015
+ this.onSelectAll();
9016
+ }
9017
+ handleKeydownOnSelectAll(evt) {
9018
+ switch (evt.key) {
9019
+ case KEY_CODE.ARROW_DOWN: {
9020
+ this.onSelectAllArrowDown(evt);
9021
+ break;
9022
+ }
9023
+ case KEY_CODE.ARROW_UP: {
9024
+ this.onSelectAllArrowUp();
9025
+ break;
9026
+ }
9027
+ case KEY_CODE.ENTER: {
9028
+ this.checkboxSelectAll.click();
9029
+ break;
9030
+ }
9031
+ case KEY_CODE.ESCAPE: {
9032
+ this.closeMultiselectDropdown();
9033
+ break;
9034
+ }
9035
+ default: {
9036
+ break;
9037
+ }
9038
+ }
9039
+ }
9040
+ onSelectAllArrowDown(evt) {
9041
+ evt.preventDefault();
9042
+ const currentOptions = this.getActiveOptions();
9043
+ if (currentOptions.length > 0) {
9044
+ const nextSiblingCheckbox = currentOptions[0].firstElementChild;
9045
+ nextSiblingCheckbox.focus();
9046
+ }
9047
+ }
9048
+ onSelectAllArrowUp() {
9049
+ this.searchEl.focus();
9050
+ }
9051
+ handleClickOnOption(evt) {
9052
+ this.updateCurrentValue();
9053
+ this.propagateTouched();
9054
+ this.eclChange.emit(this.selectedValues);
9055
+ }
9056
+ handleKeydownOnOption(evt) {
9057
+ switch (evt.key) {
9058
+ case KEY_CODE.ARROW_DOWN:
9059
+ {
9060
+ this.onOptionArrowDown(evt);
9061
+ break;
9062
+ }
9063
+ ;
9064
+ case KEY_CODE.ARROW_UP: {
9065
+ this.onOptionArrowUp(evt);
9066
+ break;
9067
+ }
9068
+ case KEY_CODE.ESCAPE: {
9069
+ this.closeMultiselectDropdown();
9070
+ break;
9071
+ }
9072
+ case KEY_CODE.ENTER: {
9073
+ evt.target.click();
9074
+ break;
9075
+ }
9076
+ case KEY_CODE.TAB: {
9077
+ this.onOptionTab(evt);
9078
+ break;
9079
+ }
9080
+ default: {
9081
+ break;
9082
+ }
9083
+ }
9084
+ }
9085
+ onOptionArrowDown(evt) {
9086
+ evt.preventDefault();
9087
+ const index = this.getOptionIndexByIdFromActiveOptions(evt.target.id);
9088
+ const currentOptions = this.getActiveOptions();
9089
+ if (index !== currentOptions.length - 1) {
9090
+ const nextSiblingCheckbox = currentOptions[index + 1].firstElementChild;
9091
+ nextSiblingCheckbox.focus();
9092
+ }
9093
+ else {
9094
+ this.multiSelectInput.focus();
9095
+ }
9096
+ }
9097
+ onOptionArrowUp(evt) {
9098
+ evt.preventDefault();
9099
+ const index = this.getOptionIndexByIdFromActiveOptions(evt.target.id);
9100
+ if (index !== 0) {
9101
+ const prevSiblingCheckbox = this.getActiveOptions()[index - 1].firstElementChild;
9102
+ prevSiblingCheckbox.focus();
9103
+ }
9104
+ else if (this.checkboxSelectAll.disabled) {
9105
+ this.searchEl.focus();
9106
+ }
9107
+ else {
9108
+ this.checkboxSelectAll.focus();
9109
+ }
9110
+ }
9111
+ onOptionTab(evt) {
9112
+ const index = this.getOptionIndexByIdFromActiveOptions(evt.target.id);
9113
+ if (index === this.getActiveOptions().length - 1) {
9114
+ this.multiSelectInput.focus(); // Trap tab
9115
+ evt.preventDefault();
9116
+ }
9117
+ }
9118
+ getActiveOptions() {
9119
+ return this.multiSelectOptions.filter(item => item.style.display !== 'none' &&
9120
+ !item.classList.contains('ecl-checkbox--disabled'));
9121
+ }
9122
+ removeAllListeners() {
9123
+ this.multiSelectInput.removeEventListener('keydown', this.handleKeydownOnMainInput);
9124
+ this.multiSelectInput.removeEventListener('click', this.handleClickOnMainInput);
9125
+ this.searchEl.removeEventListener('keydown', this.handleKeydownOnSearch);
9126
+ this.searchEl.removeEventListener('keyup', this.onSearchOptions);
9127
+ this.checkboxSelectAll.removeEventListener('keydown', this.handleKeydownOnSelectAll);
9128
+ this.checkboxSelectAll.removeEventListener('click', this.handleClickOnSelectAll);
9129
+ this.multiSelectOptions.forEach(el => {
9130
+ const checboxEl = el.firstElementChild;
9131
+ checboxEl.removeEventListener('keydown', this.handleKeydownOnOption);
9132
+ checboxEl.removeEventListener('click', this.handleClickOnOption);
9133
+ });
9134
+ }
9135
+ bindCallbacks() {
9136
+ this.handleKeydownOnMainInput = this.handleKeydownOnMainInput.bind(this);
9137
+ this.handleKeydownOnSearch = this.handleKeydownOnSearch.bind(this);
9138
+ this.onSearchOptions = this.onSearchOptions.bind(this);
9139
+ this.handleKeydownOnSelectAll = this.handleKeydownOnSelectAll.bind(this);
9140
+ this.handleKeydownOnOption = this.handleKeydownOnOption.bind(this);
9141
+ this.handleClickOnMainInput = this.handleClickOnMainInput.bind(this);
9142
+ this.handleClickOnSelectAll = this.handleClickOnSelectAll.bind(this);
9143
+ this.handleClickOnOption = this.handleClickOnOption.bind(this);
9144
+ }
8923
9145
  }
8924
9146
  /** @nocollapse */ EclMultiselectComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclMultiselectComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.IterableDiffers }, { token: i2.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
8925
9147
  /** @nocollapse */ EclMultiselectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: EclMultiselectComponent, selector: "select[eclMultiselect]", inputs: { isInvalid: "isInvalid", eclPlaceholder: "eclPlaceholder", disabled: "disabled", eclSize: "eclSize" }, outputs: { eclChange: "eclChange" }, host: { listeners: { "document:keyup.escape": "onEscapeKey($event)", "document:click": "onKeyUp($event)" }, properties: { "attr.disabled": "this.disabled", "class": "this.cssClasses" } }, queries: [{ propertyName: "eclOptionItems", predicate: EclMultiselectOptionDirective }], usesInheritance: true, ngImport: i0, template: "<ng-content></ng-content>" });
@@ -10538,62 +10760,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImpor
10538
10760
  }]
10539
10761
  }] });
10540
10762
 
10541
- class EclRadioLabelComponent extends ECLBaseDirective {
10763
+ class EclRadioHelpComponent extends ECLBaseDirective {
10542
10764
  constructor() {
10543
10765
  super(...arguments);
10544
- this.isInvalid = false;
10545
10766
  this.isDisabled = false;
10546
10767
  }
10547
10768
  get cssClasses() {
10548
10769
  return [
10549
- super.getCssClasses('ecl-radio__label'),
10770
+ super.getCssClasses('ecl-radio__help'),
10550
10771
  ].join(' ').trim();
10551
10772
  }
10552
10773
  }
10553
- /** @nocollapse */ EclRadioLabelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclRadioLabelComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
10554
- /** @nocollapse */ EclRadioLabelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: EclRadioLabelComponent, selector: "[eclRadioLabel]", inputs: { isInvalid: "isInvalid", isDisabled: "isDisabled" }, host: { properties: { "class": "this.cssClasses" } }, usesInheritance: true, ngImport: i0, template: "<!--\n @TODO\n Uncomment markup below once eui is fixed\n Due to eui css spillover following markup has to be commented to avoid double radioes being drawn\n https://webgate.ec.europa.eu/CITnet/jira/browse/EUI-3459\n-->\n\n<span class=\"ecl-radio__box\"\n [class.ecl-radio__box--disabled]=\"isDisabled\"\n [class.ecl-radio__box--invalid]=\"isInvalid\">\n</span>\n\n<ng-content></ng-content>\n", styles: [".ecl-radio__label{margin-top:0;margin-bottom:0}.ecl-radio__help{margin-bottom:0}.ecl-radio__box:before{box-sizing:initial}\n"], encapsulation: i0.ViewEncapsulation.None });
10555
- __decorate([
10556
- coerceBoolean
10557
- ], EclRadioLabelComponent.prototype, "isInvalid", void 0);
10774
+ /** @nocollapse */ EclRadioHelpComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclRadioHelpComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
10775
+ /** @nocollapse */ EclRadioHelpComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: EclRadioHelpComponent, selector: "[eclRadioHelp]", inputs: { isDisabled: "isDisabled" }, host: { properties: { "class.ecl-radio__help--disabled": "this.isDisabled", "class": "this.cssClasses" } }, usesInheritance: true, ngImport: i0, template: "<ng-content></ng-content>\n" });
10558
10776
  __decorate([
10559
10777
  coerceBoolean
10560
- ], EclRadioLabelComponent.prototype, "isDisabled", void 0);
10561
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclRadioLabelComponent, decorators: [{
10778
+ ], EclRadioHelpComponent.prototype, "isDisabled", void 0);
10779
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclRadioHelpComponent, decorators: [{
10562
10780
  type: Component,
10563
- args: [{ selector: '[eclRadioLabel]', encapsulation: ViewEncapsulation.None, template: "<!--\n @TODO\n Uncomment markup below once eui is fixed\n Due to eui css spillover following markup has to be commented to avoid double radioes being drawn\n https://webgate.ec.europa.eu/CITnet/jira/browse/EUI-3459\n-->\n\n<span class=\"ecl-radio__box\"\n [class.ecl-radio__box--disabled]=\"isDisabled\"\n [class.ecl-radio__box--invalid]=\"isInvalid\">\n</span>\n\n<ng-content></ng-content>\n", styles: [".ecl-radio__label{margin-top:0;margin-bottom:0}.ecl-radio__help{margin-bottom:0}.ecl-radio__box:before{box-sizing:initial}\n"] }]
10564
- }], propDecorators: { isInvalid: [{
10565
- type: Input
10566
- }], isDisabled: [{
10781
+ args: [{ selector: '[eclRadioHelp]', template: "<ng-content></ng-content>\n" }]
10782
+ }], propDecorators: { isDisabled: [{
10567
10783
  type: Input
10784
+ }, {
10785
+ type: HostBinding,
10786
+ args: ['class.ecl-radio__help--disabled']
10568
10787
  }], cssClasses: [{
10569
10788
  type: HostBinding,
10570
10789
  args: ['class']
10571
10790
  }] } });
10572
10791
 
10573
- class EclRadioHelpComponent extends ECLBaseDirective {
10792
+ class EclRadioLabelComponent extends ECLBaseDirective {
10574
10793
  constructor() {
10575
10794
  super(...arguments);
10795
+ this.isInvalid = false;
10576
10796
  this.isDisabled = false;
10577
10797
  }
10578
10798
  get cssClasses() {
10579
10799
  return [
10580
- super.getCssClasses('ecl-radio__help'),
10800
+ super.getCssClasses('ecl-radio__label'),
10581
10801
  ].join(' ').trim();
10582
10802
  }
10583
10803
  }
10584
- /** @nocollapse */ EclRadioHelpComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclRadioHelpComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
10585
- /** @nocollapse */ EclRadioHelpComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: EclRadioHelpComponent, selector: "[eclRadioHelp]", inputs: { isDisabled: "isDisabled" }, host: { properties: { "class.ecl-radio__help--disabled": "this.isDisabled", "class": "this.cssClasses" } }, usesInheritance: true, ngImport: i0, template: "<ng-content></ng-content>\n" });
10804
+ /** @nocollapse */ EclRadioLabelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclRadioLabelComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
10805
+ /** @nocollapse */ EclRadioLabelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: EclRadioLabelComponent, selector: "[eclRadioLabel]", inputs: { isInvalid: "isInvalid", isDisabled: "isDisabled" }, host: { properties: { "class": "this.cssClasses" } }, usesInheritance: true, ngImport: i0, template: "<span class=\"ecl-radio__box\"\n [class.ecl-radio__box--disabled]=\"isDisabled\"\n [class.ecl-radio__box--invalid]=\"isInvalid\">\n</span>\n\n<ng-content></ng-content>\n", styles: [".ecl-radio__label{margin-top:0;margin-bottom:0}.ecl-radio__help{margin-bottom:0}.ecl-radio__box:before{box-sizing:initial}\n"], encapsulation: i0.ViewEncapsulation.None });
10586
10806
  __decorate([
10587
10807
  coerceBoolean
10588
- ], EclRadioHelpComponent.prototype, "isDisabled", void 0);
10589
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclRadioHelpComponent, decorators: [{
10808
+ ], EclRadioLabelComponent.prototype, "isInvalid", void 0);
10809
+ __decorate([
10810
+ coerceBoolean
10811
+ ], EclRadioLabelComponent.prototype, "isDisabled", void 0);
10812
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclRadioLabelComponent, decorators: [{
10590
10813
  type: Component,
10591
- args: [{ selector: '[eclRadioHelp]', template: "<ng-content></ng-content>\n" }]
10592
- }], propDecorators: { isDisabled: [{
10814
+ args: [{ selector: '[eclRadioLabel]', encapsulation: ViewEncapsulation.None, template: "<span class=\"ecl-radio__box\"\n [class.ecl-radio__box--disabled]=\"isDisabled\"\n [class.ecl-radio__box--invalid]=\"isInvalid\">\n</span>\n\n<ng-content></ng-content>\n", styles: [".ecl-radio__label{margin-top:0;margin-bottom:0}.ecl-radio__help{margin-bottom:0}.ecl-radio__box:before{box-sizing:initial}\n"] }]
10815
+ }], propDecorators: { isInvalid: [{
10816
+ type: Input
10817
+ }], isDisabled: [{
10593
10818
  type: Input
10594
- }, {
10595
- type: HostBinding,
10596
- args: ['class.ecl-radio__help--disabled']
10597
10819
  }], cssClasses: [{
10598
10820
  type: HostBinding,
10599
10821
  args: ['class']
@@ -10611,10 +10833,7 @@ class EclRadioDirective extends ECLBaseDirective {
10611
10833
  this.isBinary ? 'ecl-radio--binary' : '',
10612
10834
  ].join(' ').trim();
10613
10835
  }
10614
- ngAfterContentInit() {
10615
- this.updateChildElements();
10616
- }
10617
- ngOnChanges() {
10836
+ ngDoCheck() {
10618
10837
  this.updateChildElements();
10619
10838
  }
10620
10839
  updateChildElements() {
@@ -10628,7 +10847,7 @@ class EclRadioDirective extends ECLBaseDirective {
10628
10847
  }
10629
10848
  }
10630
10849
  /** @nocollapse */ EclRadioDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: EclRadioDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
10631
- /** @nocollapse */ EclRadioDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.0", type: EclRadioDirective, selector: "[eclRadio]", inputs: { isBinary: "isBinary", isDisabled: "isDisabled", isInvalid: "isInvalid" }, host: { properties: { "class.ecl-radio--disabled": "this.isDisabled", "class.ecl-radio--invalid": "this.isInvalid", "class": "this.cssClasses" } }, queries: [{ propertyName: "eclRadioLabelComponent", first: true, predicate: i0.forwardRef(function () { return EclRadioLabelComponent; }), descendants: true }, { propertyName: "eclRadioHelpComponent", first: true, predicate: i0.forwardRef(function () { return EclRadioHelpComponent; }), descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0 });
10850
+ /** @nocollapse */ EclRadioDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.0", type: EclRadioDirective, selector: "[eclRadio]", inputs: { isBinary: "isBinary", isDisabled: "isDisabled", isInvalid: "isInvalid" }, host: { properties: { "class.ecl-radio--disabled": "this.isDisabled", "class.ecl-radio--invalid": "this.isInvalid", "class": "this.cssClasses" } }, queries: [{ propertyName: "eclRadioLabelComponent", first: true, predicate: i0.forwardRef(function () { return EclRadioLabelComponent; }), descendants: true }, { propertyName: "eclRadioHelpComponent", first: true, predicate: i0.forwardRef(function () { return EclRadioHelpComponent; }), descendants: true }], usesInheritance: true, ngImport: i0 });
10632
10851
  __decorate([
10633
10852
  coerceBoolean
10634
10853
  ], EclRadioDirective.prototype, "isBinary", void 0);
@@ -10878,9 +11097,8 @@ class EclSelectDirective extends ECLBaseDirective {
10878
11097
  this.handleMarkup();
10879
11098
  }
10880
11099
  ngDoCheck() {
10881
- if (this.ngControl) {
10882
- this.hostWrapperEl.classList.toggle('ecl-select__container--disabled', this.ngControl.disabled || this.disabled);
10883
- }
11100
+ this.hostWrapperEl.classList.toggle('ecl-select__container--disabled', this.ngControl?.disabled || this.disabled);
11101
+ this.hostWrapperEl.classList.toggle('ecl-select__container--invalid', this.ngControl?.touched && this.ngControl?.invalid || this.isInvalid);
10884
11102
  }
10885
11103
  handleMarkup() {
10886
11104
  if (this.hostParentEl != null) {