@eui/ecl 22.0.0-alpha.56 → 22.0.0-alpha.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # eui documentation
2
2
 
3
- > Generated by compodoc 2.0.0 at 2026-11-04T16:12:18.788Z, llm-md export.
3
+ > Generated by compodoc 2.0.0 at 2026-11-06T14:59:45.321Z, llm-md export.
4
4
 
5
5
  ## Modules
6
6
 
@@ -322,11 +322,10 @@ Methods:
322
322
  File: `packages/ecl/components/ecl-carousel/ecl-carousel.component.ts`
323
323
  Selector: `ecl-carousel`
324
324
 
325
- Description: Carousel (slideshow) component following the ECL design system. Renders a sequence of EclCarouselItemComponent slides with autoplay, keyboard navigation, responsive breakpoint awareness, and RTL layout support. The slide engine is powered by Embla (via embla-carousel-angular ), matching the upstream ECL implementation: an infinite loop , the Autoplay plugin driving the teaser loading bars, and a slider pager with previous/next/play/pause controls, a counter, and a tablist of teaser buttons (one per slide). Selector: ecl-carousel . Project ecl-carousel-item elements as slides (also via contentChildren ). ariaLabel — ARIA label for the carousel landmark; aliased as aria-label . isAutoplay — enables automatic slide advancement; boolean attribute. playInterval — milliseconds between automatic transitions; default 5000 . counterLabel — separator label used by the counter, defaults to ecl.common.OF . slide — emits EclSlideEvent when the active slide changes.
325
+ Description: Carousel (slideshow) component following the ECL design system. Renders a sequence of EclCarouselItemComponent slides with autoplay, keyboard navigation, responsive breakpoint awareness, and RTL layout support. The slide engine is powered by Embla (via embla-carousel-angular ), matching the upstream ECL implementation: an infinite loop , the Autoplay plugin driving the teaser loading bars, and a slider pager with previous/next/play/pause controls, a counter, and a tablist of teaser buttons (one per slide). Selector: ecl-carousel . Project ecl-carousel-item elements as slides (also via contentChildren ). ariaLabel — ARIA label for the carousel landmark; aliased as aria-label . isAutoplay — enables automatic slide advancement; boolean attribute. playInterval — milliseconds between automatic transitions; default 5000 . slide — emits EclSlideEvent when the active slide changes.
326
326
 
327
327
  Inputs:
328
328
  - `aria-label: string | null = 'Carousel description here'` — Aria-label for screen readers to describe the carousel.
329
- - `counterLabel: string = ''` — Separator label used by the counter, e.g. the "of" in "1 of 5". Defaults to the translated ecl.common.OF key.
330
329
  - `isAutoplay: boolean = undefined` — Determines whether the carousel should autoplay.
331
330
  - `playInterval: number = 5000` — Interval in milliseconds between automatic slide transitions.
332
331
  - `class: string = ''`
@@ -361,10 +360,9 @@ Methods:
361
360
  File: `packages/ecl/components/ecl-carousel/ecl-carousel-item.component.ts`
362
361
  Selector: `ecl-carousel-item`
363
362
 
364
- Description: Single slide item for use inside an EclCarouselComponent . Renders a role="tabpanel" element with an aria-roledescription="slide" and handles the inert attribute so only the active slide is interactive. Selector: ecl-carousel-item . id — optional unique identifier; used by the carousel for navigation buttons. isCurrent (input alias) — initial active state; kept as a linkedSignal so the parent carousel can update it imperatively as the user navigates. slideClick — emits EclSlideEvent when the slide is clicked. index / ariaLabel — writable signals assigned by the parent carousel. Project an optional EclBannerComponent inside the slide for banner-style slides.
363
+ Description: Single slide item for use inside an EclCarouselComponent . Renders a role="tabpanel" element with an aria-roledescription="slide" and handles the inert attribute so only the active slide is interactive. Selector: ecl-carousel-item . isCurrent (input alias) — initial active state; kept as a linkedSignal so the parent carousel can update it imperatively as the user navigates. slideClick — emits EclSlideEvent when the slide is clicked. index / ariaLabel — writable signals assigned by the parent carousel. Project an optional EclBannerComponent inside the slide for banner-style slides.
365
364
 
366
365
  Inputs:
367
- - `id: string` — The unique identifier of the slide.
368
366
  - `isCurrent: boolean = false` — Input controlling whether this slide starts as the active/visible one. Automatically coerced to a boolean value.
369
367
  - `teaserText: string = ''` — Text shown in the carousel teaser (navigation) button for this slide. Optional; when empty, no teaser label is rendered for the slide.
370
368
  - `class: string = ''`
@@ -7893,7 +7891,6 @@ File: `packages/ecl/components/ecl-carousel/models/ecl-carousel-item.model.ts`
7893
7891
  Description: Interface implemented by EclCarouselItemComponent . Defines the minimal contract the carousel uses to manage slide state.
7894
7892
 
7895
7893
  Properties:
7896
- - `id?: Signal<string | undefined>` — Optional slide identifier used for navigation buttons.
7897
7894
  - `index: WritableSignal<number | undefined>` — Zero-based index assigned by the parent carousel.
7898
7895
  - `isCurrent: WritableSignal<boolean>` — Whether this slide is currently active (visible).
7899
7896
 
@@ -128,7 +128,7 @@
128
128
  </ol>
129
129
  <ul class="properties-list">
130
130
  <li>
131
- <b>Version</b> : 22.0.0-alpha.56</li>
131
+ <b>Version</b> : 22.0.0-alpha.58</li>
132
132
  </ul>
133
133
 
134
134
 
@@ -20,7 +20,6 @@ var EclCarouselItemComponent = class EclCarouselItemComponent extends ECLBaseDir
20
20
  super(...arguments);
21
21
  this.el = inject(ElementRef);
22
22
  this.ariaLabel = signal(void 0, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
23
- this.id = input(...ngDevMode ? [void 0, { debugName: "id" }] : /* istanbul ignore next */ []);
24
23
  this.isCurrentInput = input(false, {
25
24
  ...ngDevMode ? { debugName: "isCurrentInput" } : /* istanbul ignore next */ {},
26
25
  alias: "isCurrent",
@@ -54,13 +53,6 @@ var EclCarouselItemComponent = class EclCarouselItemComponent extends ECLBaseDir
54
53
  isStandalone: true,
55
54
  selector: "ecl-carousel-item",
56
55
  inputs: {
57
- id: {
58
- classPropertyName: "id",
59
- publicName: "id",
60
- isSignal: true,
61
- isRequired: false,
62
- transformFunction: null
63
- },
64
56
  isCurrentInput: {
65
57
  classPropertyName: "isCurrentInput",
66
58
  publicName: "isCurrent",
@@ -123,14 +115,6 @@ i0.ɵɵngDeclareClassMetadata({
123
115
  }]
124
116
  }],
125
117
  propDecorators: {
126
- id: [{
127
- type: i0.Input,
128
- args: [{
129
- isSignal: true,
130
- alias: "id",
131
- required: false
132
- }]
133
- }],
134
118
  isCurrentInput: [{
135
119
  type: i0.Input,
136
120
  args: [{
@@ -173,7 +157,6 @@ var EclCarouselComponent = class EclCarouselComponent extends ECLBaseDirective {
173
157
  ...ngDevMode ? { debugName: "playInterval" } : /* istanbul ignore next */ {},
174
158
  transform: numberAttribute
175
159
  });
176
- this.counterLabel = input("", ...ngDevMode ? [{ debugName: "counterLabel" }] : /* istanbul ignore next */ []);
177
160
  this.slide = output();
178
161
  this.carouselContainerElement = viewChild("carouselContainer", ...ngDevMode ? [{ debugName: "carouselContainerElement" }] : /* istanbul ignore next */ []);
179
162
  this.slides = contentChildren(forwardRef(() => EclCarouselItemComponent), ...ngDevMode ? [{ debugName: "slides" }] : /* istanbul ignore next */ []);
@@ -537,13 +520,6 @@ var EclCarouselComponent = class EclCarouselComponent extends ECLBaseDirective {
537
520
  isSignal: true,
538
521
  isRequired: false,
539
522
  transformFunction: null
540
- },
541
- counterLabel: {
542
- classPropertyName: "counterLabel",
543
- publicName: "counterLabel",
544
- isSignal: true,
545
- isRequired: false,
546
- transformFunction: null
547
523
  }
548
524
  },
549
525
  outputs: { slide: "slide" },
@@ -588,7 +564,7 @@ var EclCarouselComponent = class EclCarouselComponent extends ECLBaseDirective {
588
564
  ],
589
565
  usesInheritance: true,
590
566
  ngImport: i0,
591
- template: "@if (hasControls()) {\n<div class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__navigation\">\n <div class=\"ecl-carousel__pager-container\">\n <ecl-slider-pager\n class=\"ecl-carousel__pager\"\n [variant]=\"pagerVariant()\"\n size=\"m\"\n [isPlaying]=\"isPagerPlaying()\"\n [activeIndex]=\"getCurrentSlideIndex()\"\n [dotIndices]=\"getDotIndices()\"\n [dotAriaLabels]=\"getDotAriaLabels()\"\n prevExtraClasses=\"ecl-carousel__prev\"\n nextExtraClasses=\"ecl-carousel__next\"\n dotsExtraClasses=\"ecl-carousel__dots\"\n dotExtraClasses=\"ecl-carousel__dot\"\n playExtraClasses=\"ecl-carousel__play\"\n pauseExtraClasses=\"ecl-carousel__pause\"\n (play)=\"onPlayClick()\"\n (pause)=\"onPauseClick()\"\n (prev)=\"onPreviousSlideClick()\"\n (next)=\"onNextSlideClick()\"\n (goTo)=\"onDotClick($event)\">\n </ecl-slider-pager>\n <div class=\"ecl-carousel__counter\" dir=\"ltr\">\n {{ getCounterCurrent() }} {{ counterLabel() || ('ecl.common.OF' | translate) }} {{ getCounterTotal() }}\n </div>\n </div>\n\n <div class=\"ecl-carousel__teasers\" role=\"tablist\">\n @for (slide of slides(); let i = $index; track slide) {\n <button #teaserButton type=\"button\" class=\"ecl-carousel__teaser-button\" role=\"tab\"\n [attr.data-ecl-carousel-slide-index]=\"i\"\n [attr.aria-current]=\"i === getCurrentSlideIndex() ? true : null\"\n [attr.tabindex]=\"i === getCurrentSlideIndex() ? null : -1\"\n [style.display]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.pointer-events]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.order]=\"getTeaserOrder(i)\" (click)=\"onTeaserClick(i)\"\n (keydown)=\"onTeaserKeyboardPress($event, i)\">\n <span class=\"ecl-carousel__teaser-loading-bar\" aria-hidden=\"true\"\n [class.is-active]=\"(isPlaying() || isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\"\n [class.is-paused]=\"(isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\">\n <span #loadingBar class=\"ecl-carousel__teaser-loading-bar-completion\"></span>\n </span>\n <span class=\"ecl-carousel__teaser-content\">\n @if (slide.teaserText()) {\n <span class=\"ecl-carousel__teaser-title\">{{ slide.teaserText() }}</span>\n }\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n</div>\n}\n<div #carouselContainer class=\"ecl-carousel__viewport\" [class.ecl-carousel-container--padded]=\"isPadded()\"\n emblaCarousel #embla=\"emblaCarousel\" [options]=\"emblaOptions\" [plugins]=\"emblaPlugins\"\n [subscribeToEvents]=\"emblaEvents\" (emblaChange)=\"onEmblaEvent($event)\"\n (mouseenter)=\"onViewportPause()\" (mouseleave)=\"onViewportResume()\"\n (focusin)=\"onViewportPause()\" (focusout)=\"onViewportResume()\">\n <div class=\"ecl-carousel__slides\">\n <ng-content></ng-content>\n </div>\n</div>\n",
567
+ template: "@if (hasControls()) {\n<div class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__navigation\">\n <div class=\"ecl-carousel__pager-container\">\n <ecl-slider-pager\n class=\"ecl-carousel__pager\"\n [variant]=\"pagerVariant()\"\n size=\"m\"\n [isPlaying]=\"isPagerPlaying()\"\n [activeIndex]=\"getCurrentSlideIndex()\"\n [dotIndices]=\"getDotIndices()\"\n [dotAriaLabels]=\"getDotAriaLabels()\"\n prevExtraClasses=\"ecl-carousel__prev\"\n nextExtraClasses=\"ecl-carousel__next\"\n dotsExtraClasses=\"ecl-carousel__dots\"\n dotExtraClasses=\"ecl-carousel__dot\"\n playExtraClasses=\"ecl-carousel__play\"\n pauseExtraClasses=\"ecl-carousel__pause\"\n (play)=\"onPlayClick()\"\n (pause)=\"onPauseClick()\"\n (prev)=\"onPreviousSlideClick()\"\n (next)=\"onNextSlideClick()\"\n (goTo)=\"onDotClick($event)\">\n </ecl-slider-pager>\n <div class=\"ecl-carousel__counter\" dir=\"ltr\">\n {{ getCounterCurrent() }} {{ ('ecl.common.OF' | translate) }} {{ getCounterTotal() }}\n </div>\n </div>\n\n <div class=\"ecl-carousel__teasers\" role=\"tablist\">\n @for (slide of slides(); let i = $index; track slide) {\n <button #teaserButton type=\"button\" class=\"ecl-carousel__teaser-button\" role=\"tab\"\n [attr.data-ecl-carousel-slide-index]=\"i\"\n [attr.aria-current]=\"i === getCurrentSlideIndex() ? true : null\"\n [attr.tabindex]=\"i === getCurrentSlideIndex() ? null : -1\"\n [style.display]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.pointer-events]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.order]=\"getTeaserOrder(i)\" (click)=\"onTeaserClick(i)\"\n (keydown)=\"onTeaserKeyboardPress($event, i)\">\n <span class=\"ecl-carousel__teaser-loading-bar\" aria-hidden=\"true\"\n [class.is-active]=\"(isPlaying() || isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\"\n [class.is-paused]=\"(isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\">\n <span #loadingBar class=\"ecl-carousel__teaser-loading-bar-completion\"></span>\n </span>\n <span class=\"ecl-carousel__teaser-content\">\n @if (slide.teaserText()) {\n <span class=\"ecl-carousel__teaser-title\">{{ slide.teaserText() }}</span>\n }\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n</div>\n}\n<div #carouselContainer class=\"ecl-carousel__viewport\" [class.ecl-carousel-container--padded]=\"isPadded()\"\n emblaCarousel #embla=\"emblaCarousel\" [options]=\"emblaOptions\" [plugins]=\"emblaPlugins\"\n [subscribeToEvents]=\"emblaEvents\" (emblaChange)=\"onEmblaEvent($event)\"\n (mouseenter)=\"onViewportPause()\" (mouseleave)=\"onViewportResume()\"\n (focusin)=\"onViewportPause()\" (focusout)=\"onViewportResume()\">\n <div class=\"ecl-carousel__slides\">\n <ng-content></ng-content>\n </div>\n</div>\n",
592
568
  dependencies: [
593
569
  {
594
570
  kind: "directive",
@@ -660,7 +636,7 @@ i0.ɵɵngDeclareClassMetadata({
660
636
  "[class]": "cssClasses()",
661
637
  "[style.--ecl-carousel-slide-duration]": "playInterval() + \"ms\""
662
638
  },
663
- template: "@if (hasControls()) {\n<div class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__navigation\">\n <div class=\"ecl-carousel__pager-container\">\n <ecl-slider-pager\n class=\"ecl-carousel__pager\"\n [variant]=\"pagerVariant()\"\n size=\"m\"\n [isPlaying]=\"isPagerPlaying()\"\n [activeIndex]=\"getCurrentSlideIndex()\"\n [dotIndices]=\"getDotIndices()\"\n [dotAriaLabels]=\"getDotAriaLabels()\"\n prevExtraClasses=\"ecl-carousel__prev\"\n nextExtraClasses=\"ecl-carousel__next\"\n dotsExtraClasses=\"ecl-carousel__dots\"\n dotExtraClasses=\"ecl-carousel__dot\"\n playExtraClasses=\"ecl-carousel__play\"\n pauseExtraClasses=\"ecl-carousel__pause\"\n (play)=\"onPlayClick()\"\n (pause)=\"onPauseClick()\"\n (prev)=\"onPreviousSlideClick()\"\n (next)=\"onNextSlideClick()\"\n (goTo)=\"onDotClick($event)\">\n </ecl-slider-pager>\n <div class=\"ecl-carousel__counter\" dir=\"ltr\">\n {{ getCounterCurrent() }} {{ counterLabel() || ('ecl.common.OF' | translate) }} {{ getCounterTotal() }}\n </div>\n </div>\n\n <div class=\"ecl-carousel__teasers\" role=\"tablist\">\n @for (slide of slides(); let i = $index; track slide) {\n <button #teaserButton type=\"button\" class=\"ecl-carousel__teaser-button\" role=\"tab\"\n [attr.data-ecl-carousel-slide-index]=\"i\"\n [attr.aria-current]=\"i === getCurrentSlideIndex() ? true : null\"\n [attr.tabindex]=\"i === getCurrentSlideIndex() ? null : -1\"\n [style.display]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.pointer-events]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.order]=\"getTeaserOrder(i)\" (click)=\"onTeaserClick(i)\"\n (keydown)=\"onTeaserKeyboardPress($event, i)\">\n <span class=\"ecl-carousel__teaser-loading-bar\" aria-hidden=\"true\"\n [class.is-active]=\"(isPlaying() || isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\"\n [class.is-paused]=\"(isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\">\n <span #loadingBar class=\"ecl-carousel__teaser-loading-bar-completion\"></span>\n </span>\n <span class=\"ecl-carousel__teaser-content\">\n @if (slide.teaserText()) {\n <span class=\"ecl-carousel__teaser-title\">{{ slide.teaserText() }}</span>\n }\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n</div>\n}\n<div #carouselContainer class=\"ecl-carousel__viewport\" [class.ecl-carousel-container--padded]=\"isPadded()\"\n emblaCarousel #embla=\"emblaCarousel\" [options]=\"emblaOptions\" [plugins]=\"emblaPlugins\"\n [subscribeToEvents]=\"emblaEvents\" (emblaChange)=\"onEmblaEvent($event)\"\n (mouseenter)=\"onViewportPause()\" (mouseleave)=\"onViewportResume()\"\n (focusin)=\"onViewportPause()\" (focusout)=\"onViewportResume()\">\n <div class=\"ecl-carousel__slides\">\n <ng-content></ng-content>\n </div>\n</div>\n"
639
+ template: "@if (hasControls()) {\n<div class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__navigation\">\n <div class=\"ecl-carousel__pager-container\">\n <ecl-slider-pager\n class=\"ecl-carousel__pager\"\n [variant]=\"pagerVariant()\"\n size=\"m\"\n [isPlaying]=\"isPagerPlaying()\"\n [activeIndex]=\"getCurrentSlideIndex()\"\n [dotIndices]=\"getDotIndices()\"\n [dotAriaLabels]=\"getDotAriaLabels()\"\n prevExtraClasses=\"ecl-carousel__prev\"\n nextExtraClasses=\"ecl-carousel__next\"\n dotsExtraClasses=\"ecl-carousel__dots\"\n dotExtraClasses=\"ecl-carousel__dot\"\n playExtraClasses=\"ecl-carousel__play\"\n pauseExtraClasses=\"ecl-carousel__pause\"\n (play)=\"onPlayClick()\"\n (pause)=\"onPauseClick()\"\n (prev)=\"onPreviousSlideClick()\"\n (next)=\"onNextSlideClick()\"\n (goTo)=\"onDotClick($event)\">\n </ecl-slider-pager>\n <div class=\"ecl-carousel__counter\" dir=\"ltr\">\n {{ getCounterCurrent() }} {{ ('ecl.common.OF' | translate) }} {{ getCounterTotal() }}\n </div>\n </div>\n\n <div class=\"ecl-carousel__teasers\" role=\"tablist\">\n @for (slide of slides(); let i = $index; track slide) {\n <button #teaserButton type=\"button\" class=\"ecl-carousel__teaser-button\" role=\"tab\"\n [attr.data-ecl-carousel-slide-index]=\"i\"\n [attr.aria-current]=\"i === getCurrentSlideIndex() ? true : null\"\n [attr.tabindex]=\"i === getCurrentSlideIndex() ? null : -1\"\n [style.display]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.pointer-events]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.order]=\"getTeaserOrder(i)\" (click)=\"onTeaserClick(i)\"\n (keydown)=\"onTeaserKeyboardPress($event, i)\">\n <span class=\"ecl-carousel__teaser-loading-bar\" aria-hidden=\"true\"\n [class.is-active]=\"(isPlaying() || isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\"\n [class.is-paused]=\"(isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\">\n <span #loadingBar class=\"ecl-carousel__teaser-loading-bar-completion\"></span>\n </span>\n <span class=\"ecl-carousel__teaser-content\">\n @if (slide.teaserText()) {\n <span class=\"ecl-carousel__teaser-title\">{{ slide.teaserText() }}</span>\n }\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n</div>\n}\n<div #carouselContainer class=\"ecl-carousel__viewport\" [class.ecl-carousel-container--padded]=\"isPadded()\"\n emblaCarousel #embla=\"emblaCarousel\" [options]=\"emblaOptions\" [plugins]=\"emblaPlugins\"\n [subscribeToEvents]=\"emblaEvents\" (emblaChange)=\"onEmblaEvent($event)\"\n (mouseenter)=\"onViewportPause()\" (mouseleave)=\"onViewportResume()\"\n (focusin)=\"onViewportPause()\" (focusout)=\"onViewportResume()\">\n <div class=\"ecl-carousel__slides\">\n <ng-content></ng-content>\n </div>\n</div>\n"
664
640
  }]
665
641
  }],
666
642
  ctorParameters: () => [],
@@ -689,14 +665,6 @@ i0.ɵɵngDeclareClassMetadata({
689
665
  required: false
690
666
  }]
691
667
  }],
692
- counterLabel: [{
693
- type: i0.Input,
694
- args: [{
695
- isSignal: true,
696
- alias: "counterLabel",
697
- required: false
698
- }]
699
- }],
700
668
  slide: [{
701
669
  type: i0.Output,
702
670
  args: ["slide"]
@@ -1 +1 @@
1
- {"version":3,"file":"eui-ecl-components-ecl-carousel.mjs","names":[],"sources":["../../components/ecl-carousel/events/ecl-slide.event.ts","../../components/ecl-carousel/ecl-carousel-item.component.ts","../../components/ecl-carousel/ecl-carousel-item.component.html","../../components/ecl-carousel/ecl-carousel.component.ts","../../components/ecl-carousel/ecl-carousel.component.html","../../components/ecl-carousel/index.ts"],"sourcesContent":["import { EclBaseEvent } from '@eui/ecl/core';\nimport { EclCarouselItem } from '../models/ecl-carousel-item.model';\n\n/**\n * Event emitted by `EclCarouselComponent` when the active slide changes, and by\n * `EclCarouselItemComponent` when a slide is clicked.\n * Carries the `EclCarouselItem` that became active or was clicked.\n */\nexport class EclSlideEvent extends EclBaseEvent {\n /**\n * @param item The carousel item that was activated or clicked.\n */\n constructor(public item: EclCarouselItem) {\n super();\n }\n}","import {\n Component,\n ElementRef,\n booleanAttribute,\n computed,\n forwardRef,\n inject,\n input,\n linkedSignal,\n output,\n signal,\n contentChild,\n} from '@angular/core';\nimport { ECLBaseDirective } from '@eui/ecl/core';\nimport { EclBannerComponent } from '@eui/ecl/components/ecl-banner';\nimport { EclSlideEvent } from './events/ecl-slide.event';\nimport { EclCarouselItem } from './models/ecl-carousel-item.model';\n\n/**\n * Single slide item for use inside an `EclCarouselComponent`.\n * Renders a `role=\"tabpanel\"` element with an `aria-roledescription=\"slide\"` and handles\n * the `inert` attribute so only the active slide is interactive.\n *\n * - Selector: `ecl-carousel-item`.\n * - `id` — optional unique identifier; used by the carousel for navigation buttons.\n * - `isCurrent` (input alias) — initial active state; kept as a `linkedSignal` so the parent\n * carousel can update it imperatively as the user navigates.\n * - `slideClick` — emits `EclSlideEvent` when the slide is clicked.\n * - `index` / `ariaLabel` — writable signals assigned by the parent carousel.\n * - Project an optional `EclBannerComponent` inside the slide for banner-style slides.\n */\n@Component({\n selector: 'ecl-carousel-item',\n templateUrl: './ecl-carousel-item.component.html',\n host: {\n role: 'tabpanel',\n '[attr.aria-label]': 'ariaLabel()',\n '[attr.aria-roledescription]': '\"slide\"',\n '[attr.inert]': '!isCurrent() || undefined',\n '[class]': 'cssClasses()',\n '(click)': 'onSlideClick()',\n },\n styles: [\n `\n /* TODO: remove by implementing full ECL specs */\n :host:before {\n left: 0 !important;\n display: none;\n }\n `,\n ],\n})\nexport class EclCarouselItemComponent extends ECLBaseDirective implements EclCarouselItem {\n el = inject(ElementRef);\n\n /**\n * The aria-label for the slide, assigned dynamically by the carousel.\n */\n readonly ariaLabel = signal<string | undefined>(undefined);\n\n /**\n * The unique identifier of the slide.\n */\n readonly id = input<string>();\n\n /**\n * Input controlling whether this slide starts as the active/visible one.\n * Automatically coerced to a boolean value.\n */\n readonly isCurrentInput = input(false, { alias: 'isCurrent', transform: booleanAttribute });\n\n /**\n * Indicates whether this slide is currently active/visible.\n * Seeded from the `isCurrent` input but can be updated imperatively by the\n * parent carousel as the user navigates between slides.\n */\n readonly isCurrent = linkedSignal(() => this.isCurrentInput());\n\n /**\n * Text shown in the carousel teaser (navigation) button for this slide.\n * Optional; when empty, no teaser label is rendered for the slide.\n */\n readonly teaserText = input<string>('');\n\n /**\n * Emits an event when the slide is clicked.\n */\n readonly slideClick = output<EclSlideEvent>();\n\n /**\n * Optionally captures a banner component projected into the slide.\n */\n readonly banner = contentChild(forwardRef(() => EclBannerComponent));\n\n /**\n * Internal slide index, assigned dynamically by the carousel.\n */\n readonly index = signal<number | undefined>(undefined);\n\n /**\n * Computes the slide's CSS class.\n */\n protected readonly cssClasses = computed<string>(() =>\n super.getCssClasses('ecl-carousel__slide'));\n\n /**\n * Handles click events on the slide and emits a slideClick event.\n */\n onSlideClick(): void {\n this.slideClick.emit(new EclSlideEvent(this));\n }\n}\n","<ng-content></ng-content>\n","import { BreakpointObserver } from '@angular/cdk/layout';\nimport {\n AfterContentInit,\n ChangeDetectorRef,\n Component,\n DOCUMENT,\n ElementRef,\n OnDestroy,\n OnInit,\n Renderer2,\n afterNextRender,\n booleanAttribute,\n computed,\n contentChildren,\n forwardRef,\n inject,\n input,\n numberAttribute,\n output,\n signal,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { EUI_ECL_SLIDER } from '@eui/ecl/components/ecl-slider';\nimport { ECLBaseDirective, EclRtlService, KeyCode } from '@eui/ecl/core';\nimport { TranslatePipe, TranslateService } from '@ngx-translate/core';\nimport {\n EmblaEventType,\n EmblaOptionsType,\n EmblaPluginType,\n} from 'embla-carousel';\nimport { EmblaCarouselDirective } from 'embla-carousel-angular';\nimport Autoplay from 'embla-carousel-autoplay';\nimport { Subject, auditTime, fromEvent, takeUntil } from 'rxjs';\nimport { EclCarouselItemComponent } from './ecl-carousel-item.component';\nimport { EclSlideEvent } from './events/ecl-slide.event';\n\n/**\n * Number of teaser buttons visible at once on the desktop breakpoint.\n */\nconst VISIBLE_TEASERS = 4;\n\n/**\n * Carousel (slideshow) component following the ECL design system.\n * Renders a sequence of `EclCarouselItemComponent` slides with autoplay, keyboard navigation,\n * responsive breakpoint awareness, and RTL layout support.\n *\n * The slide engine is powered by Embla (via `embla-carousel-angular`), matching the upstream\n * ECL implementation: an infinite `loop`, the `Autoplay` plugin driving the teaser loading bars,\n * and a slider pager with previous/next/play/pause controls, a counter, and a tablist of teaser\n * buttons (one per slide).\n *\n * - Selector: `ecl-carousel`.\n * - Project `ecl-carousel-item` elements as slides (also via `contentChildren`).\n * - `ariaLabel` — ARIA label for the carousel landmark; aliased as `aria-label`.\n * - `isAutoplay` — enables automatic slide advancement; boolean attribute.\n * - `playInterval` — milliseconds between automatic transitions; default `5000`.\n * - `counterLabel` — separator label used by the counter, defaults to `ecl.common.OF`.\n * - `slide` — emits `EclSlideEvent` when the active slide changes.\n */\n@Component({\n selector: 'ecl-carousel',\n templateUrl: './ecl-carousel.component.html',\n imports: [\n TranslatePipe,\n EmblaCarouselDirective,\n ...EUI_ECL_SLIDER,\n ],\n host: {\n '[attr.aria-label]': 'ariaLabel()',\n '[attr.aria-roledescription]': '\"carousel\"',\n '[class]': 'cssClasses()',\n // Drives the teaser loading-bar animation duration (see @eui/styles).\n // It has no CSS fallback, so without it the progress animation never\n // runs; it must match the autoplay delay.\n '[style.--ecl-carousel-slide-duration]': 'playInterval() + \"ms\"',\n },\n})\nexport class EclCarouselComponent extends ECLBaseDirective implements OnInit, OnDestroy, AfterContentInit {\n /**\n * Aria-label for screen readers to describe the carousel.\n */\n readonly ariaLabel = input<string | null>('Carousel description here', { alias: 'aria-label' });\n\n /**\n * Determines whether the carousel should autoplay.\n */\n readonly isAutoplay = input<boolean, unknown>(undefined, { transform: booleanAttribute });\n\n /**\n * Interval in milliseconds between automatic slide transitions.\n */\n readonly playInterval = input(5000, { transform: numberAttribute });\n\n /**\n * Separator label used by the counter, e.g. the \"of\" in \"1 of 5\".\n * Defaults to the translated `ecl.common.OF` key.\n */\n readonly counterLabel = input<string>('');\n\n /**\n * Event emitted when a slide change occurs.\n */\n readonly slide = output<EclSlideEvent>();\n\n /**\n * Reference to the main carousel viewport element (the Embla root).\n */\n readonly carouselContainerElement = viewChild<ElementRef>('carouselContainer');\n\n /**\n * Collection of slide components rendered inside the carousel.\n */\n readonly slides = contentChildren(forwardRef(() => EclCarouselItemComponent));\n\n /**\n * Indicates whether autoplay is currently active.\n */\n readonly isPlaying = signal(false);\n\n /**\n * Indicates whether autoplay was manually paused (via the pause button or\n * on mobile). When paused this way the loading bar is cleared.\n */\n readonly isPausedForced = signal(false);\n\n /**\n * Indicates whether the layout is currently in RTL mode.\n */\n isRtl = false;\n\n /**\n * Zero-based index of the currently active slide (mirrors Embla's selected snap).\n */\n private activeIndex = 0;\n\n /**\n * Start index of the currently visible teaser window (desktop only).\n */\n private teaserWindowStart = 0;\n\n /**\n * Indicates whether autoplay is temporarily paused by hover/focus. Unlike a\n * manual pause, the loading bar stays visible and frozen at its current\n * progress (matching ECL), resuming when the pointer/focus leaves.\n */\n protected readonly isHoverPaused = signal(false);\n\n /**\n * Whether the current viewport is at the mobile breakpoint. A signal so the\n * template can react (the pager drops play/pause on mobile, matching ECL,\n * where play/pause is a desktop-only control).\n */\n protected readonly isMobileBreakpoint = signal(false);\n\n /**\n * Whether the viewport is at or above the ECL desktop breakpoint (1140px).\n * This is the boundary the ECL CSS uses to show the play/pause controls and\n * the teaser tablist (and to hide the mobile dots). A signal so the pager\n * variant can react: play/pause only renders at/above this width, matching\n * the CSS so the pause button never leaks onto narrower viewports.\n */\n protected readonly isDesktopBreakpointActive = signal(false);\n\n /**\n * Embla options, mirroring the upstream ECL configuration.\n */\n protected emblaOptions: EmblaOptionsType = {\n loop: true,\n align: 'start',\n duration: 20,\n };\n\n /**\n * Embla plugins. Built once so the Embla directive does not needlessly re-init.\n */\n protected emblaPlugins: EmblaPluginType[] = [];\n\n /**\n * Embla events the component reacts to.\n */\n protected readonly emblaEvents: EmblaEventType[] = [\n 'select',\n 'reInit',\n 'autoplay:timerset',\n ];\n\n /**\n * Reference to the Embla directive driving the slide engine.\n */\n private readonly embla = viewChild<EmblaCarouselDirective>('embla');\n\n /**\n * References to the teaser navigation buttons corresponding to each slide.\n */\n private readonly teaserButtons = viewChildren<ElementRef>('teaserButton');\n\n /**\n * References to the teaser loading-bar completion elements (one per slide),\n * used to restart the progress animation when the active slide changes.\n */\n private readonly loadingBars = viewChildren<ElementRef>('loadingBar');\n\n private isTabletBreakpoint = false;\n private isLargeBreakpoint = false;\n private isDesktopBreakpoint = false;\n\n private destroy$: Subject<boolean> = new Subject<boolean>();\n\n /**\n * Debounce interval (ms) used internally for timing and transitions.\n */\n private readonly TIMEOUT_INTERVAL = 400;\n private readonly cdkBreakpointObserver = inject(BreakpointObserver);\n private readonly cd = inject(ChangeDetectorRef);\n private readonly renderer2 = inject(Renderer2);\n private readonly eclRtlService = inject(EclRtlService);\n private readonly translate = inject(TranslateService);\n private readonly document = inject<Document>(DOCUMENT);\n private readonly window = this.document.defaultView;\n /**\n * Host element, used to locate the slider pager's play/pause buttons by their\n * ECL classes for focus management after a play/pause toggle.\n */\n private readonly hostEl = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /**\n * Returns the computed CSS class list for the component.\n */\n protected readonly cssClasses = computed<string>(() =>\n super.getCssClasses('ecl-carousel'));\n\n constructor() {\n super();\n afterNextRender(() => {\n this.observeElementSizeChanges();\n this.observeBreakpointChanges();\n this.syncFromEmbla();\n\n if (this.window) {\n fromEvent(this.window, 'resize')\n .pipe(auditTime(50), takeUntil(this.destroy$))\n .subscribe(() => this.observeElementSizeChanges());\n }\n });\n }\n\n /**\n * Angular lifecycle hook: initializes RTL detection and the Embla plugins.\n */\n ngOnInit(): void {\n this.emblaOptions = {\n ...this.emblaOptions,\n direction: this.isRtl ? 'rtl' : 'ltr',\n };\n const autoplayDesired = this.isAutoplayDesired();\n // Reflect the initial play state so the current slide's loading bar is\n // shown on load (the plugin self-starts via playOnInit).\n this.isPlaying.set(autoplayDesired);\n this.emblaPlugins = [\n Autoplay({\n delay: this.playInterval(),\n // Autoplay is on by default (matching ECL) unless explicitly\n // disabled via [isAutoplay]=\"false\". Letting the plugin start\n // itself avoids a race with Embla's own initialization.\n playOnInit: autoplayDesired,\n stopOnInteraction: false,\n stopOnMouseEnter: true,\n stopOnFocusIn: true,\n }),\n ];\n this.handleRtlChangeState();\n }\n\n /**\n * Angular lifecycle hook: called after content (slides) is initialized.\n */\n ngAfterContentInit(): void {\n setTimeout(() => {\n this.initSlides();\n });\n }\n\n /**\n * Angular lifecycle hook: cleans up subscriptions.\n */\n ngOnDestroy(): void {\n this.destroy$.next(true);\n this.destroy$.unsubscribe();\n }\n\n /**\n * Returns whether the carousel has padding applied (e.g., on desktop breakpoint).\n */\n isPadded(): boolean {\n return this.isDesktopBreakpoint;\n }\n\n /**\n * Checks whether there are enough slides to render controls.\n */\n hasControls(): boolean {\n return this.getSlidesCount() > 1;\n }\n\n /**\n * Retrieves the current active slide index (zero-based).\n */\n getCurrentSlideIndex(): number {\n return this.activeIndex;\n }\n\n /**\n * Returns the 1-based position of the active slide (for the counter).\n */\n getCounterCurrent(): number {\n return this.activeIndex + 1;\n }\n\n /**\n * Returns the total number of slides (for the counter).\n */\n getCounterTotal(): number {\n return this.getSlidesCount();\n }\n\n /**\n * Dot indices for the mobile slider pager (one dot per slide). The dots are\n * hidden on desktop via the ECL CSS (`.ecl-carousel__dots { display: none }`)\n * and shown at the mobile breakpoint.\n */\n getDotIndices(): number[] {\n return Array.from({ length: this.getSlidesCount() }, (_unused, dotIndex) => dotIndex);\n }\n\n /**\n * Pre-translated accessible label for each pager dot. Translated here since\n * the shared `ecl-slider-pager` receives plain strings.\n */\n getDotAriaLabels(): string[] {\n const total = this.getSlidesCount();\n return Array.from({ length: total }, (_unused, dotIndex) =>\n this.translate.instant('ecl.carousel.GO-TO-SLIDE', {\n current: dotIndex + 1,\n total,\n }),\n );\n }\n\n /**\n * Returns whether a teaser button should be visible in the current window.\n */\n isTeaserVisible(index: number): boolean {\n const count = this.getSlidesCount();\n if (count <= VISIBLE_TEASERS) {\n return true;\n }\n const position = ((index - this.teaserWindowStart) % count + count) % count;\n return position < VISIBLE_TEASERS;\n }\n\n /**\n * Returns the flex order of a teaser button within the visible window.\n */\n getTeaserOrder(index: number): number {\n const count = this.getSlidesCount();\n return ((index - this.teaserWindowStart) % count + count) % count;\n }\n\n /**\n * Whether the pager should show the \"pause\" control (i.e. autoplay is\n * actively running). While the pointer/focus hover-pauses the carousel the\n * timer is suspended, so the pager must show \"play\" even though a manual\n * pause was not triggered. Mirrors upstream ECL, where hovering flips the\n * control to play.\n */\n protected isPagerPlaying(): boolean {\n return this.isPlaying() && !this.isHoverPaused();\n }\n\n /**\n * Pager variant by breakpoint. Below the ECL desktop breakpoint (1140px)\n * the carousel shows only the dots navigation (prev / dots / next);\n * play/pause is a desktop-only control in ECL. Rendering `'dots'` there\n * avoids the pager's inline play/pause `display` style (which would\n * otherwise beat the ECL CSS and leave the pause button visible on narrower\n * viewports). At/above 1140px the dots are hidden by CSS, so\n * `'play-pause-dots'` yields play/pause + prev/next + teasers.\n *\n * The 1140px boundary mirrors the media query the ECL CSS uses to toggle\n * `.ecl-carousel__play/__pause` and `.ecl-carousel__teasers`.\n */\n protected pagerVariant(): 'dots' | 'play-pause-dots' {\n return this.isDesktopBreakpointActive() ? 'play-pause-dots' : 'dots';\n }\n\n /**\n * Handles the throttled Embla events the component subscribed to.\n */\n protected onEmblaEvent(event: EmblaEventType): void {\n switch (event) {\n case 'select':\n case 'reInit':\n this.syncFromEmbla();\n break;\n case 'autoplay:timerset':\n // Fired each time the autoplay timer (re)starts for the current\n // slide; replay the loading-bar fill animation from zero.\n this.restartActiveLoadingBar();\n break;\n default:\n break;\n }\n }\n\n /**\n * Starts autoplay.\n *\n * @param moveFocus when true (a user clicked play) focus moves to the pause\n * button. Auto-starts (e.g. on breakpoint changes) pass false so the\n * page is not scrolled to the carousel on load.\n */\n protected onPlayClick(moveFocus = true): void {\n this.getAutoplay()?.play();\n this.isPlaying.set(true);\n this.isPausedForced.set(false);\n this.isHoverPaused.set(false);\n this.cd.detectChanges();\n if (moveFocus) {\n this.focusPagerButton('.ecl-carousel__pause');\n }\n }\n\n /**\n * Stops autoplay and focuses the play button.\n */\n protected onPauseClick(): void {\n // Pause (not full stop): halt the autoplay timer but keep the active\n // teaser loading bar visible, frozen at its current progress (matching\n // upstream ECL's `handleAutoPlay(false, true)`). The installed\n // embla-carousel-autoplay exposes no `pause()`, so we call `stop()`\n // WITHOUT `reset()` — the frozen bar is driven by our `is-paused` CSS\n // class, not the plugin. A full stop+reset (which clears the bar) only\n // happens on prev/next/teaser navigation via `stopAutoplay()`.\n this.getAutoplay()?.stop();\n this.isPlaying.set(false);\n this.isPausedForced.set(true);\n this.isHoverPaused.set(false);\n this.cd.detectChanges();\n this.focusPagerButton('.ecl-carousel__play');\n }\n\n /**\n * Navigates to the next slide and stops autoplay.\n */\n protected onNextSlideClick(): void {\n this.stopAutoplay();\n this.embla()?.scrollNext();\n }\n\n /**\n * Navigates to the previous slide and stops autoplay.\n */\n protected onPreviousSlideClick(): void {\n this.stopAutoplay();\n this.embla()?.scrollPrev();\n }\n\n /**\n * Handles user interaction with a teaser button: activates the matching slide.\n */\n protected onTeaserClick(index: number): void {\n this.stopAutoplay();\n this.embla()?.scrollTo(index);\n }\n\n /**\n * Handles a dot activation from the mobile slider pager: scrolls to the\n * matching slide and stops autoplay (same behavior as a teaser click).\n */\n protected onDotClick(index: number): void {\n this.stopAutoplay();\n this.embla()?.scrollTo(index);\n }\n\n /**\n * Handles keyboard navigation (ArrowLeft/ArrowRight) across teaser buttons.\n */\n protected onTeaserKeyboardPress(event: KeyboardEvent, index: number): void {\n if (event.key !== KeyCode.ARROW_RIGHT && event.key !== KeyCode.ARROW_LEFT) {\n return;\n }\n event.preventDefault();\n const direction = event.key === KeyCode.ARROW_RIGHT ? 1 : -1;\n const count = this.getSlidesCount();\n const nextIndex = (index + direction + count) % count;\n this.stopAutoplay();\n this.embla()?.scrollTo(nextIndex);\n this.focusOnButton(this.teaserButtons()[nextIndex]);\n }\n\n /**\n * Freezes the loading bar while the pointer/focus is over the carousel.\n * The Embla autoplay plugin pauses the timer itself (stopOnMouseEnter /\n * stopOnFocusIn); this only mirrors that as a visible paused state.\n */\n protected onViewportPause(): void {\n if (this.isPlaying() && !this.isPausedForced()) {\n this.isHoverPaused.set(true);\n this.cd.detectChanges();\n }\n }\n\n /**\n * Resumes the loading bar once the pointer/focus leaves the carousel.\n */\n protected onViewportResume(): void {\n if (this.isHoverPaused()) {\n this.isHoverPaused.set(false);\n this.cd.detectChanges();\n }\n }\n\n /**\n * Sets focus on the specified button.\n */\n private focusOnButton(button: ElementRef): void {\n if (!button) {\n return;\n }\n button.nativeElement.focus();\n }\n\n /**\n * Focuses the slider pager button matching the given ECL class selector\n * (e.g. `.ecl-carousel__play`). Used after a play/pause toggle so focus\n * follows the now-visible control, since the pager swaps play/pause\n * visibility via CSS. No-op if the button is not rendered (e.g. mobile).\n */\n private focusPagerButton(selector: string): void {\n const button = this.hostEl.nativeElement.querySelector<HTMLElement>(selector);\n button?.focus();\n }\n\n /**\n * Returns the Embla autoplay plugin instance, but only when the carousel\n * actually has more than one scroll snap.\n *\n * The `embla-carousel-autoplay` plugin skips its own initialization when\n * `scrollSnapList().length <= 1` (see the plugin's `init`), which leaves its\n * internal `delay` lookup table undefined. Calling `play()` in that state\n * throws (`delay[selectedScrollSnap()]` -> reading `0` of undefined). This\n * happens whenever Embla cannot lay out multiple snaps — notably in a jsdom\n * test or during SSR. Gating on the same `> 1` condition the plugin uses\n * keeps autoplay a safe no-op until the carousel is genuinely slideable.\n */\n private getAutoplay() {\n const api = this.embla()?.emblaApi;\n if (!api || api.scrollSnapList().length <= 1) {\n return undefined;\n }\n return api.plugins()?.autoplay;\n }\n\n /**\n * Whether autoplay should run. On by default (matching ECL); only disabled\n * when the consumer explicitly sets `[isAutoplay]=\"false\"`.\n */\n private isAutoplayDesired(): boolean {\n const isAutoplay = this.isAutoplay();\n return isAutoplay || isAutoplay === undefined;\n }\n\n /**\n * Stops autoplay and resets it (mirrors ECL's `handleAutoPlay(true)`),\n * clearing the loading-bar state.\n */\n private stopAutoplay(): void {\n const autoplay = this.getAutoplay();\n autoplay?.stop();\n autoplay?.reset();\n this.isPlaying.set(false);\n this.isPausedForced.set(false);\n this.isHoverPaused.set(false);\n this.cd.detectChanges();\n }\n\n /**\n * Synchronizes component state from Embla's current selected snap:\n * active index, slide `isCurrent` flags, teaser window and the slide event.\n */\n private syncFromEmbla(): void {\n const api = this.embla()?.emblaApi;\n if (!api) {\n return;\n }\n const selected = api.selectedScrollSnap();\n this.setActiveIndex(selected);\n this.updateTeaserWindow();\n this.slide.emit(new EclSlideEvent(this.slides().at(this.activeIndex)));\n this.cd.detectChanges();\n }\n\n /**\n * Subscribes to RTL layout state changes to adapt carousel direction.\n */\n private handleRtlChangeState(): void {\n this.eclRtlService.currentRtlState$.pipe(takeUntil(this.destroy$)).subscribe((rtlState) => {\n const changed = this.isRtl !== rtlState;\n this.isRtl = rtlState;\n if (changed) {\n this.emblaOptions = {\n ...this.emblaOptions,\n direction: this.isRtl ? 'rtl' : 'ltr',\n };\n this.cd.detectChanges();\n }\n });\n }\n\n /**\n * Initializes slides (index, ARIA label, banner height management).\n */\n private initSlides(): void {\n const slides = this.slides();\n slides.forEach((item, idx) => {\n item.index.set(idx);\n item.ariaLabel.set(`slide ${idx + 1} of ${slides.length}`);\n item.isCurrent.set(idx === 0);\n const banner = item.banner();\n if (banner) {\n banner.skipHeightManagement = true;\n }\n });\n this.cd.detectChanges();\n }\n\n /**\n * Updates the active index and synchronizes slide active/inert state.\n */\n private setActiveIndex(index: number): void {\n this.activeIndex = index;\n this.slides().forEach((item, idx) => {\n item.isCurrent.set(idx === index);\n });\n }\n\n /**\n * Restarts the CSS progress animation on the active slide's loading bar.\n * The animation uses `forwards`, so re-applying the `is-active` class alone\n * will not replay it; the animation must be reset explicitly.\n */\n private restartActiveLoadingBar(): void {\n if (!this.getAutoplay()?.isPlaying()) {\n return;\n }\n const bar = this.loadingBars()[this.activeIndex]?.nativeElement as HTMLElement | undefined;\n if (!bar) {\n return;\n }\n bar.style.animation = 'none';\n // Force reflow so the browser registers the reset before re-enabling.\n void bar.offsetWidth;\n bar.style.animation = '';\n }\n\n /**\n * Advances the visible teaser window when the active slide moves out of it.\n */\n private updateTeaserWindow(): void {\n const count = this.getSlidesCount();\n if (count <= VISIBLE_TEASERS) {\n this.teaserWindowStart = 0;\n return;\n }\n const firstHiddenIndex = (this.teaserWindowStart + VISIBLE_TEASERS) % count;\n if (this.activeIndex === firstHiddenIndex) {\n this.teaserWindowStart = firstHiddenIndex;\n }\n }\n\n /**\n * Returns the number of actual visible slides.\n */\n private getSlidesCount(): number {\n return this.slides()?.length ?? 0;\n }\n\n /**\n * Observes screen breakpoint changes to adjust autoplay and layout behavior.\n */\n private observeBreakpointChanges(): void {\n this.cdkBreakpointObserver\n .observe([\n '(max-width: 768px)',\n '(min-width: 998px)',\n '(min-width: 1140px)',\n '(min-width: 1140px) and (max-width: 1260px)',\n ])\n .pipe(takeUntil(this.destroy$))\n .subscribe((result) => {\n this.isMobileBreakpoint.set(result.breakpoints['(max-width: 768px)']);\n this.isTabletBreakpoint = result.breakpoints['(min-width: 998px)'];\n this.isLargeBreakpoint = result.breakpoints['(min-width: 1140px)'];\n this.isDesktopBreakpointActive.set(result.breakpoints['(min-width: 1140px)']);\n this.isDesktopBreakpoint = result.breakpoints['(min-width: 1140px) and (max-width: 1260px)'];\n\n // Deactivate autoplay on mobile; (re)activate it on larger\n // screens if autoplay is desired. Focus is never moved here so\n // the page is not scrolled to the carousel on load/resize.\n if (this.isMobileBreakpoint()) {\n this.stopAutoplay();\n return;\n }\n\n if (this.isTabletBreakpoint && this.isAutoplayDesired() && !this.isPausedForced()) {\n this.onPlayClick(false);\n }\n });\n }\n\n /**\n * Observes changes to the carousel's viewport element size using a timeout debounce.\n */\n private observeElementSizeChanges(): void {\n setTimeout(() => {\n if (this.isLargeBreakpoint) {\n this.checkBannerHeights();\n } else {\n this.resetHeight();\n }\n this.embla()?.reInit();\n }, this.TIMEOUT_INTERVAL);\n }\n\n /**\n * Normalizes the height of all banners to match the tallest banner.\n */\n private checkBannerHeights(): void {\n this.slides().forEach((slide) => {\n const banner = slide.banner();\n if (banner) {\n banner.calculateHeight();\n }\n });\n\n const heightValues = this.slides().map((slide) => {\n const el = slide.banner()?.el.nativeElement;\n if (!el) return undefined;\n\n const styleHeight = el.style.height;\n\n if (styleHeight === 'auto' || styleHeight === '') {\n return el.offsetHeight;\n }\n\n const height = parseInt(styleHeight, 10);\n if (Number.isNaN(height) || height === 100) {\n return 1;\n }\n\n return height;\n });\n\n const elementHeights = heightValues.filter((h) => h !== undefined) as number[];\n const tallestElementHeight = Math.max(...elementHeights);\n\n const slides = this.slides();\n if (tallestElementHeight > 1 && elementHeights.length === slides.length) {\n slides.forEach((slide) => {\n const banner = slide.banner();\n if (!banner) return;\n\n const el = banner.el.nativeElement;\n const bannerImage = banner.eclBannerImage();\n const bannerVideo = banner.eclBannerVideo();\n\n this.renderer2.setStyle(el, 'height', `${tallestElementHeight}px`);\n this.renderer2.setStyle(el, 'aspect-ratio', 'auto');\n\n if (bannerImage) {\n this.renderer2.setStyle(bannerImage.el.nativeElement, 'aspect-ratio', 'auto');\n }\n if (bannerVideo) {\n this.renderer2.setStyle(bannerVideo.el.nativeElement, 'aspect-ratio', 'auto');\n }\n });\n }\n }\n\n /**\n * Clears all explicit banner height and aspect ratio styling for smaller breakpoints.\n */\n private resetHeight(): void {\n this.slides().forEach((slide) => {\n const banner = slide.banner();\n if (banner) {\n const bannerImage = banner.eclBannerImage();\n const bannerVideo = banner.eclBannerVideo();\n this.renderer2.removeStyle(banner.el.nativeElement, 'height');\n this.renderer2.removeStyle(banner.el.nativeElement, 'aspect-ratio');\n if (bannerImage) {\n this.renderer2.removeStyle(bannerImage.el.nativeElement, 'aspect-ratio');\n }\n if (bannerVideo) {\n this.renderer2.removeStyle(bannerVideo.el.nativeElement, 'aspect-ratio');\n }\n }\n });\n }\n}\n","@if (hasControls()) {\n<div class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__navigation\">\n <div class=\"ecl-carousel__pager-container\">\n <ecl-slider-pager\n class=\"ecl-carousel__pager\"\n [variant]=\"pagerVariant()\"\n size=\"m\"\n [isPlaying]=\"isPagerPlaying()\"\n [activeIndex]=\"getCurrentSlideIndex()\"\n [dotIndices]=\"getDotIndices()\"\n [dotAriaLabels]=\"getDotAriaLabels()\"\n prevExtraClasses=\"ecl-carousel__prev\"\n nextExtraClasses=\"ecl-carousel__next\"\n dotsExtraClasses=\"ecl-carousel__dots\"\n dotExtraClasses=\"ecl-carousel__dot\"\n playExtraClasses=\"ecl-carousel__play\"\n pauseExtraClasses=\"ecl-carousel__pause\"\n (play)=\"onPlayClick()\"\n (pause)=\"onPauseClick()\"\n (prev)=\"onPreviousSlideClick()\"\n (next)=\"onNextSlideClick()\"\n (goTo)=\"onDotClick($event)\">\n </ecl-slider-pager>\n <div class=\"ecl-carousel__counter\" dir=\"ltr\">\n {{ getCounterCurrent() }} {{ counterLabel() || ('ecl.common.OF' | translate) }} {{ getCounterTotal() }}\n </div>\n </div>\n\n <div class=\"ecl-carousel__teasers\" role=\"tablist\">\n @for (slide of slides(); let i = $index; track slide) {\n <button #teaserButton type=\"button\" class=\"ecl-carousel__teaser-button\" role=\"tab\"\n [attr.data-ecl-carousel-slide-index]=\"i\"\n [attr.aria-current]=\"i === getCurrentSlideIndex() ? true : null\"\n [attr.tabindex]=\"i === getCurrentSlideIndex() ? null : -1\"\n [style.display]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.pointer-events]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.order]=\"getTeaserOrder(i)\" (click)=\"onTeaserClick(i)\"\n (keydown)=\"onTeaserKeyboardPress($event, i)\">\n <span class=\"ecl-carousel__teaser-loading-bar\" aria-hidden=\"true\"\n [class.is-active]=\"(isPlaying() || isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\"\n [class.is-paused]=\"(isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\">\n <span #loadingBar class=\"ecl-carousel__teaser-loading-bar-completion\"></span>\n </span>\n <span class=\"ecl-carousel__teaser-content\">\n @if (slide.teaserText()) {\n <span class=\"ecl-carousel__teaser-title\">{{ slide.teaserText() }}</span>\n }\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n</div>\n}\n<div #carouselContainer class=\"ecl-carousel__viewport\" [class.ecl-carousel-container--padded]=\"isPadded()\"\n emblaCarousel #embla=\"emblaCarousel\" [options]=\"emblaOptions\" [plugins]=\"emblaPlugins\"\n [subscribeToEvents]=\"emblaEvents\" (emblaChange)=\"onEmblaEvent($event)\"\n (mouseenter)=\"onViewportPause()\" (mouseleave)=\"onViewportResume()\"\n (focusin)=\"onViewportPause()\" (focusout)=\"onViewportResume()\">\n <div class=\"ecl-carousel__slides\">\n <ng-content></ng-content>\n </div>\n</div>\n","import { EclCarouselComponent } from './ecl-carousel.component';\nimport { EclCarouselItemComponent } from './ecl-carousel-item.component';\n\nexport * from './ecl-carousel.component';\nexport * from './ecl-carousel-item.component';\nexport * from './events/ecl-slide.event';\nexport * from './models/ecl-carousel-item.model';\n\nexport const EUI_ECL_CAROUSEL = [\n EclCarouselComponent,\n EclCarouselItemComponent,\n] as const;\n"],"mappings":";;;;;;;;;;;AAQA,IAAa,gBAAb,cAAmC,aAAY;CAI3C,YAAmB,MAAqB;EACpC,MAAK;EADU,KAAA,OAAA;CAEnB;AACH;ACqCD,IAAa,2BAAb,MAAa,iCAAiC,iBAAgB;CArB9D,cAAA;;EAsBI,KAAA,KAAK,OAAO,UAAU;EAKb,KAAA,YAAY,OAA2B,QAAU,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;EAKjD,KAAA,KAAK,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,KAAA,CAAA,+BAAA,CAAA,CAAA;EAMpB,KAAA,iBAAiB,MAAM,OAAK;GAAA,GAAA,YAAA,EAAA,WAAA,iBAAA,+BAAA,CAAA;GAAI,OAAO;GAAa,WAAW;EAAgB,CAAA;EAO/E,KAAA,YAAY,mBAAmB,KAAK,eAAc,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;EAMrD,KAAA,aAAa,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;EAK9B,KAAA,aAAa,OAAM;EAKnB,KAAA,SAAS,aAAa,iBAAiB,kBAAkB,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAK3D,KAAA,QAAQ,OAA2B,QAAU,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;EAKnC,KAAA,aAAa,eAC5B,MAAM,cAAc,qBAAqB,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAQlD;CAHG,eAAY;EACR,KAAK,WAAW,KAAK,IAAI,cAAc,IAAI,CAAC;CAChD;CA1DS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAwB,MAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAxB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAwB,cAAA;GAAA,UAAA;GAAA,QAAA;IAAA,IAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,gBAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,YAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;GAAA;GAAA,SAAA,EAAA,YAAA,aAAA;GAAA,MAAA;IAAA,YAAA,EAAA,QAAA,WAAA;IAAA,WAAA,EAAA,SAAA,iBAAA;IAAA,YAAA;KAAA,mBAAA;KAAA,6BAAA;KAAA,cAAA;KAAA,SAAA;IAAA;GAAA;GAAA,SAAA,CAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WAAA,GAAA,iBAwCe,kBAAkB;IAAA,aAAA;IAAA,UAAA;GAAA,CAAA;GAAA,iBAAA;GAAA,UAAA;GAAA,UC5FtE;GACA,QAAA,CAAA,+CAAA;EAAA,CAAA;CAAA;;ADmDa,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAwB,YAAA,CAAA;EArBpC,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAmB,MAEvB;IACF,MAAM;IACN,qBAAqB;IACrB,+BAA+B;IAC/B,gBAAgB;IAChB,WAAW;IACX,WAAW;GACd;GAAA,UAAA;GAAA,QAAA,CAAA,+CAAA;EAAA,CAAA;CAmD8B,CAAA;CAAA,gBAAA;EAAA,IAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,gBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,YAAA;EAAA,CAAA;EAAA,QAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,iBAAiB,kBAAkB,GAAC,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;CAAA;AAAA,CAAA;AEpDvE,MAAM,kBAAkB;AAsCxB,IAAa,uBAAb,MAAa,6BAA6B,iBAAgB;CA0JtD,cAAA;EACI,MAAK;EAvJA,KAAA,YAAY,MAAqB,6BAA2B;GAAA,GAAA,YAAA,EAAA,WAAA,YAAA,+BAAA,CAAA;GAAI,OAAO;EAAY,CAAA;EAKnF,KAAA,aAAa,MAAwB,QAAS;GAAA,GAAA,YAAA,EAAA,WAAA,aAAA,+BAAA,CAAA;GAAI,WAAW;EAAgB,CAAA;EAK7E,KAAA,eAAe,MAAM,KAAI;GAAA,GAAA,YAAA,EAAA,WAAA,eAAA,+BAAA,CAAA;GAAI,WAAW;EAAe,CAAA;EAMvD,KAAA,eAAe,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;EAKhC,KAAA,QAAQ,OAAM;EAKd,KAAA,2BAA2B,UAAsB,qBAAoB,GAAA,YAAA,CAAA,EAAA,WAAA,2BAAA,CAAA,+BAAA,CAAA,CAAA;EAKrE,KAAA,SAAS,gBAAgB,iBAAiB,wBAAwB,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAKpE,KAAA,YAAY,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;EAMzB,KAAA,iBAAiB,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;EAKvC,KAAA,QAAQ;EAKA,KAAA,cAAc;EAKd,KAAA,oBAAoB;EAOT,KAAA,gBAAgB,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;EAO7B,KAAA,qBAAqB,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,qBAAA,CAAA,+BAAA,CAAA,CAAA;EASlC,KAAA,4BAA4B,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,4BAAA,CAAA,+BAAA,CAAA,CAAA;EAKlD,KAAA,eAAiC;GACvC,MAAM;GACN,OAAO;GACP,UAAU;EACb;EAKS,KAAA,eAAkC,CAAA;EAKzB,KAAA,cAAgC;GAC/C;GACA;GACA;EACH;EAKgB,KAAA,QAAQ,UAAkC,SAAQ,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;EAKlD,KAAA,gBAAgB,aAAyB,gBAAe,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;EAMxD,KAAA,cAAc,aAAyB,cAAa,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;EAE7D,KAAA,qBAAqB;EACrB,KAAA,oBAAoB;EACpB,KAAA,sBAAsB;EAEtB,KAAA,WAA6B,IAAI,QAAO;EAK/B,KAAA,mBAAmB;EACnB,KAAA,wBAAwB,OAAO,kBAAkB;EACjD,KAAA,KAAK,OAAO,iBAAiB;EAC7B,KAAA,YAAY,OAAO,SAAS;EAC5B,KAAA,gBAAgB,OAAO,aAAa;EACpC,KAAA,YAAY,OAAO,gBAAgB;EACnC,KAAA,WAAW,OAAiB,QAAQ;EACpC,KAAA,SAAS,KAAK,SAAS;EAKvB,KAAA,SAAS,OAAgC,UAAU;EAKjD,KAAA,aAAa,eAC5B,MAAM,cAAc,cAAc,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;EAIpC,sBAAqB;GACjB,KAAK,0BAAyB;GAC9B,KAAK,yBAAwB;GAC7B,KAAK,cAAa;GAElB,IAAI,KAAK,QACL,UAAU,KAAK,QAAQ,QAAQ,CAAC,CAC3B,KAAK,UAAU,EAAE,GAAG,UAAU,KAAK,QAAQ,CAAC,CAAC,CAC7C,gBAAgB,KAAK,0BAAyB,CAAE;EAE7D,CAAC;CACL;CAKA,WAAQ;EACJ,KAAK,eAAe;GAChB,GAAG,KAAK;GACR,WAAW,KAAK,QAAQ,QAAQ;EACnC;EACD,MAAM,kBAAkB,KAAK,kBAAiB;EAG9C,KAAK,UAAU,IAAI,eAAe;EAClC,KAAK,eAAe,CAChB,SAAS;GACL,OAAO,KAAK,aAAY;GAIxB,YAAY;GACZ,mBAAmB;GACnB,kBAAkB;GAClB,eAAe;EAClB,CAAA,CACJ;EACD,KAAK,qBAAoB;CAC7B;CAKA,qBAAkB;EACd,iBAAgB;GACZ,KAAK,WAAU;EACnB,CAAC;CACL;CAKA,cAAW;EACP,KAAK,SAAS,KAAK,IAAI;EACvB,KAAK,SAAS,YAAW;CAC7B;CAKA,WAAQ;EACJ,OAAO,KAAK;CAChB;CAKA,cAAW;EACP,OAAO,KAAK,eAAc,IAAK;CACnC;CAKA,uBAAoB;EAChB,OAAO,KAAK;CAChB;CAKA,oBAAiB;EACb,OAAO,KAAK,cAAc;CAC9B;CAKA,kBAAe;EACX,OAAO,KAAK,eAAc;CAC9B;CAOA,gBAAa;EACT,OAAO,MAAM,KAAK,EAAE,QAAQ,KAAK,eAAc,EAAE,IAAK,SAAS,aAAa,QAAQ;CACxF;CAMA,mBAAgB;EACZ,MAAM,QAAQ,KAAK,eAAc;EACjC,OAAO,MAAM,KAAK,EAAE,QAAQ,MAAK,IAAK,SAAS,aAC3C,KAAK,UAAU,QAAQ,4BAA4B;GAC/C,SAAS,WAAW;GACpB;EACH,CAAA,CAAC;CAEV;CAKA,gBAAgB,OAAa;EACzB,MAAM,QAAQ,KAAK,eAAc;EACjC,IAAI,SAAS,iBACT,OAAO;EAGX,SADmB,QAAQ,KAAK,qBAAqB,QAAQ,SAAS,QACpD;CACtB;CAKA,eAAe,OAAa;EACxB,MAAM,QAAQ,KAAK,eAAc;EACjC,SAAS,QAAQ,KAAK,qBAAqB,QAAQ,SAAS;CAChE;CASU,iBAAc;EACpB,OAAO,KAAK,UAAS,KAAM,CAAC,KAAK,cAAa;CAClD;CAcU,eAAY;EAClB,OAAO,KAAK,0BAAyB,IAAK,oBAAoB;CAClE;CAKU,aAAa,OAAqB;EACxC,QAAQ,OAAR;GACI,KAAK;GACL,KAAK;IACD,KAAK,cAAa;IAClB;GACJ,KAAK,qBAGD,KAAK,wBAAuB;EAIpC;CACJ;CASU,YAAY,YAAY,MAAI;EAClC,KAAK,YAAW,CAAE,EAAE,KAAI;EACxB,KAAK,UAAU,IAAI,IAAI;EACvB,KAAK,eAAe,IAAI,KAAK;EAC7B,KAAK,cAAc,IAAI,KAAK;EAC5B,KAAK,GAAG,cAAa;EACrB,IAAI,WACA,KAAK,iBAAiB,sBAAsB;CAEpD;CAKU,eAAY;EAQlB,KAAK,YAAW,CAAE,EAAE,KAAI;EACxB,KAAK,UAAU,IAAI,KAAK;EACxB,KAAK,eAAe,IAAI,IAAI;EAC5B,KAAK,cAAc,IAAI,KAAK;EAC5B,KAAK,GAAG,cAAa;EACrB,KAAK,iBAAiB,qBAAqB;CAC/C;CAKU,mBAAgB;EACtB,KAAK,aAAY;EACjB,KAAK,MAAK,CAAE,EAAE,WAAU;CAC5B;CAKU,uBAAoB;EAC1B,KAAK,aAAY;EACjB,KAAK,MAAK,CAAE,EAAE,WAAU;CAC5B;CAKU,cAAc,OAAa;EACjC,KAAK,aAAY;EACjB,KAAK,MAAK,CAAE,EAAE,SAAS,KAAK;CAChC;CAMU,WAAW,OAAa;EAC9B,KAAK,aAAY;EACjB,KAAK,MAAK,CAAE,EAAE,SAAS,KAAK;CAChC;CAKU,sBAAsB,OAAsB,OAAa;EAC/D,IAAI,MAAM,QAAQ,QAAQ,eAAe,MAAM,QAAQ,QAAQ,YAC3D;EAEJ,MAAM,eAAc;EACpB,MAAM,YAAY,MAAM,QAAQ,QAAQ,cAAc,IAAI;EAC1D,MAAM,QAAQ,KAAK,eAAc;EACjC,MAAM,aAAa,QAAQ,YAAY,SAAS;EAChD,KAAK,aAAY;EACjB,KAAK,MAAK,CAAE,EAAE,SAAS,SAAS;EAChC,KAAK,cAAc,KAAK,cAAa,CAAE,CAAC,UAAU;CACtD;CAOU,kBAAe;EACrB,IAAI,KAAK,UAAS,KAAM,CAAC,KAAK,eAAc,GAAI;GAC5C,KAAK,cAAc,IAAI,IAAI;GAC3B,KAAK,GAAG,cAAa;EACzB;CACJ;CAKU,mBAAgB;EACtB,IAAI,KAAK,cAAa,GAAI;GACtB,KAAK,cAAc,IAAI,KAAK;GAC5B,KAAK,GAAG,cAAa;EACzB;CACJ;CAKQ,cAAc,QAAkB;EACpC,IAAI,CAAC,QACD;EAEJ,OAAO,cAAc,MAAK;CAC9B;CAQQ,iBAAiB,UAAgB;EAErC,AADe,KAAK,OAAO,cAAc,cAA2B,QACpE,CAAA,EAAQ,MAAK;CACjB;CAcQ,cAAW;EACf,MAAM,MAAM,KAAK,MAAK,CAAE,EAAE;EAC1B,IAAI,CAAC,OAAO,IAAI,eAAc,CAAE,CAAC,UAAU,GACvC;EAEJ,OAAO,IAAI,QAAO,CAAE,EAAE;CAC1B;CAMQ,oBAAiB;EACrB,MAAM,aAAa,KAAK,WAAU;EAClC,OAAO,cAAc,eAAe;CACxC;CAMQ,eAAY;EAChB,MAAM,WAAW,KAAK,YAAW;EACjC,UAAU,KAAI;EACd,UAAU,MAAK;EACf,KAAK,UAAU,IAAI,KAAK;EACxB,KAAK,eAAe,IAAI,KAAK;EAC7B,KAAK,cAAc,IAAI,KAAK;EAC5B,KAAK,GAAG,cAAa;CACzB;CAMQ,gBAAa;EACjB,MAAM,MAAM,KAAK,MAAK,CAAE,EAAE;EAC1B,IAAI,CAAC,KACD;EAEJ,MAAM,WAAW,IAAI,mBAAkB;EACvC,KAAK,eAAe,QAAQ;EAC5B,KAAK,mBAAkB;EACvB,KAAK,MAAM,KAAK,IAAI,cAAc,KAAK,OAAM,CAAE,CAAC,GAAG,KAAK,WAAW,CAAC,CAAC;EACrE,KAAK,GAAG,cAAa;CACzB;CAKQ,uBAAoB;EACxB,KAAK,cAAc,iBAAiB,KAAK,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,aAAY;GACtF,MAAM,UAAU,KAAK,UAAU;GAC/B,KAAK,QAAQ;GACb,IAAI,SAAS;IACT,KAAK,eAAe;KAChB,GAAG,KAAK;KACR,WAAW,KAAK,QAAQ,QAAQ;IACnC;IACD,KAAK,GAAG,cAAa;GACzB;EACJ,CAAC;CACL;CAKQ,aAAU;EACd,MAAM,SAAS,KAAK,OAAM;EAC1B,OAAO,SAAS,MAAM,QAAO;GACzB,KAAK,MAAM,IAAI,GAAG;GAClB,KAAK,UAAU,IAAI,SAAS,MAAM,EAAC,MAAO,OAAO,QAAQ;GACzD,KAAK,UAAU,IAAI,QAAQ,CAAC;GAC5B,MAAM,SAAS,KAAK,OAAM;GAC1B,IAAI,QACA,OAAO,uBAAuB;EAEtC,CAAC;EACD,KAAK,GAAG,cAAa;CACzB;CAKQ,eAAe,OAAa;EAChC,KAAK,cAAc;EACnB,KAAK,OAAM,CAAE,CAAC,SAAS,MAAM,QAAO;GAChC,KAAK,UAAU,IAAI,QAAQ,KAAK;EACpC,CAAC;CACL;CAOQ,0BAAuB;EAC3B,IAAI,CAAC,KAAK,YAAW,CAAE,EAAE,UAAS,GAC9B;EAEJ,MAAM,MAAM,KAAK,YAAW,CAAE,CAAC,KAAK,YAAY,EAAE;EAClD,IAAI,CAAC,KACD;EAEJ,IAAI,MAAM,YAAY;EAEtB,AAAK,IAAI;EACT,IAAI,MAAM,YAAY;CAC1B;CAKQ,qBAAkB;EACtB,MAAM,QAAQ,KAAK,eAAc;EACjC,IAAI,SAAS,iBAAiB;GAC1B,KAAK,oBAAoB;GACzB;EACJ;EACA,MAAM,oBAAoB,KAAK,oBAAoB,mBAAmB;EACtE,IAAI,KAAK,gBAAgB,kBACrB,KAAK,oBAAoB;CAEjC;CAKQ,iBAAc;EAClB,OAAO,KAAK,OAAM,CAAE,EAAE,UAAU;CACpC;CAKQ,2BAAwB;EAC5B,KAAK,sBACA,QAAQ;GACL;GACA;GACA;GACA;EACH,CAAA,CAAC,CACD,KAAK,UAAU,KAAK,QAAQ,CAAC,CAAC,CAC9B,WAAW,WAAU;GAClB,KAAK,mBAAmB,IAAI,OAAO,YAAY,qBAAqB;GACpE,KAAK,qBAAqB,OAAO,YAAY;GAC7C,KAAK,oBAAoB,OAAO,YAAY;GAC5C,KAAK,0BAA0B,IAAI,OAAO,YAAY,sBAAsB;GAC5E,KAAK,sBAAsB,OAAO,YAAY;GAK9C,IAAI,KAAK,mBAAkB,GAAI;IAC3B,KAAK,aAAY;IACjB;GACJ;GAEA,IAAI,KAAK,sBAAsB,KAAK,kBAAiB,KAAM,CAAC,KAAK,eAAc,GAC3E,KAAK,YAAY,KAAK;EAE9B,CAAC;CACT;CAKQ,4BAAyB;EAC7B,iBAAgB;GACZ,IAAI,KAAK,mBACL,KAAK,mBAAkB;QAEvB,KAAK,YAAW;GAEpB,KAAK,MAAK,CAAE,EAAE,OAAM;EACxB,GAAG,KAAK,gBAAgB;CAC5B;CAKQ,qBAAkB;EACtB,KAAK,OAAM,CAAE,CAAC,SAAS,UAAS;GAC5B,MAAM,SAAS,MAAM,OAAM;GAC3B,IAAI,QACA,OAAO,gBAAe;EAE9B,CAAC;EAoBD,MAAM,iBAlBe,KAAK,OAAM,CAAE,CAAC,KAAK,UAAS;GAC7C,MAAM,KAAK,MAAM,OAAM,CAAE,EAAE,GAAG;GAC9B,IAAI,CAAC,IAAI,OAAO;GAEhB,MAAM,cAAc,GAAG,MAAM;GAE7B,IAAI,gBAAgB,UAAU,gBAAgB,IAC1C,OAAO,GAAG;GAGd,MAAM,SAAS,SAAS,aAAa,EAAE;GACvC,IAAI,OAAO,MAAM,MAAM,KAAK,WAAW,KACnC,OAAO;GAGX,OAAO;EACX,CAEuB,CAAA,CAAa,QAAQ,MAAM,MAAM,MAAS;EACjE,MAAM,uBAAuB,KAAK,IAAI,GAAG,cAAc;EAEvD,MAAM,SAAS,KAAK,OAAM;EAC1B,IAAI,uBAAuB,KAAK,eAAe,WAAW,OAAO,QAC7D,OAAO,SAAS,UAAS;GACrB,MAAM,SAAS,MAAM,OAAM;GAC3B,IAAI,CAAC,QAAQ;GAEb,MAAM,KAAK,OAAO,GAAG;GACrB,MAAM,cAAc,OAAO,eAAc;GACzC,MAAM,cAAc,OAAO,eAAc;GAEzC,KAAK,UAAU,SAAS,IAAI,UAAU,GAAG,qBAAoB,GAAI;GACjE,KAAK,UAAU,SAAS,IAAI,gBAAgB,MAAM;GAElD,IAAI,aACA,KAAK,UAAU,SAAS,YAAY,GAAG,eAAe,gBAAgB,MAAM;GAEhF,IAAI,aACA,KAAK,UAAU,SAAS,YAAY,GAAG,eAAe,gBAAgB,MAAM;EAEpF,CAAC;CAET;CAKQ,cAAW;EACf,KAAK,OAAM,CAAE,CAAC,SAAS,UAAS;GAC5B,MAAM,SAAS,MAAM,OAAM;GAC3B,IAAI,QAAQ;IACR,MAAM,cAAc,OAAO,eAAc;IACzC,MAAM,cAAc,OAAO,eAAc;IACzC,KAAK,UAAU,YAAY,OAAO,GAAG,eAAe,QAAQ;IAC5D,KAAK,UAAU,YAAY,OAAO,GAAG,eAAe,cAAc;IAClE,IAAI,aACA,KAAK,UAAU,YAAY,YAAY,GAAG,eAAe,cAAc;IAE3E,IAAI,aACA,KAAK,UAAU,YAAY,YAAY,GAAG,eAAe,cAAc;GAE/E;EACJ,CAAC;CACL;CA3tBS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAoB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAApB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAoB,cAAA;GAAA,UAAA;GAAA,QAAA;IAAA,WAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,YAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,cAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,cAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;GAAA;GAAA,SAAA,EAAA,OAAA,QAAA;GAAA,MAAA,EAAA,YAAA;IAAA,mBAAA;IAAA,6BAAA;IAAA,SAAA;IAAA,uCAAA;GAAA,EAAA;GAAA,SAAA,CAAA;IAAA,cAAA;IAAA,WAAA,GAAA,iBAmCsB,wBAAwB;IAAA,UAAA;GAAA,CAAA;GAAA,aAAA;IAAA;KAAA,cAAA;KAAA,OAAA;KAAA,WAAA,CAAA,mBAAA;KAAA,aAAA;KAAA,UAAA;IAAA;IAAA;KAAA,cAAA;KAAA,OAAA;KAAA,WAAA,CAAA,OAAA;KAAA,aAAA;KAAA,UAAA;IAAA;IAAA;KAAA,cAAA;KAAA,WAAA,CAAA,cAAA;KAAA,aAAA;KAAA,UAAA;IAAA;IAAA;KAAA,cAAA;KAAA,WAAA,CAAA,YAAA;KAAA,aAAA;KAAA,UAAA;IAAA;GAAA;GAAA,iBAAA;GAAA,UAAA;GAAA,UCjH/E;GAkEA,cAAA;IAAA;KAAA,MAAA;KAAA,MDDQ;KAAsB,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;KAAA;KAAA,SAAA,CAAA,aAAA;KAAA,UAAA,CAAA,eAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MAAA,GAAA;KAAA,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;KAAA,SAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MADtB;KAAa,MAAA;IAAA;GAAA;EAAA,CAAA;CAAA;;AAcR,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAoB,YAAA,CAAA;EAlBhC,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAc,SAEf;IACL;IACA;IACA,GAAG;GACN;GAAA,MACK;IACF,qBAAqB;IACrB,+BAA+B;IAC/B,WAAW;IAIX,yCAAyC;GAC5C;GAAA,UAAA;EAAA,CAAA;CAgCyD,CAAA;CAAA,sBAAA,CAAA;CAAA,gBAAA;EAAA,WAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,cAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,cAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,OAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,OAAA;EAAA,CAAA;EAAA,0BAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,qBAAmB,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,QAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAK3C,iBAAiB,wBAAwB,GAAC,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,OAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CA6EjB,SAAO,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,eAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAKR,gBAAc,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAMhB,cAAY,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;CAAA;AAAA,CAAA;AEjMxE,MAAa,mBAAmB,CAC9B,sBACA,wBACQ"}
1
+ {"version":3,"file":"eui-ecl-components-ecl-carousel.mjs","names":[],"sources":["../../components/ecl-carousel/events/ecl-slide.event.ts","../../components/ecl-carousel/ecl-carousel-item.component.ts","../../components/ecl-carousel/ecl-carousel-item.component.html","../../components/ecl-carousel/ecl-carousel.component.ts","../../components/ecl-carousel/ecl-carousel.component.html","../../components/ecl-carousel/index.ts"],"sourcesContent":["import { EclBaseEvent } from '@eui/ecl/core';\nimport { EclCarouselItem } from '../models/ecl-carousel-item.model';\n\n/**\n * Event emitted by `EclCarouselComponent` when the active slide changes, and by\n * `EclCarouselItemComponent` when a slide is clicked.\n * Carries the `EclCarouselItem` that became active or was clicked.\n */\nexport class EclSlideEvent extends EclBaseEvent {\n /**\n * @param item The carousel item that was activated or clicked.\n */\n constructor(public item: EclCarouselItem) {\n super();\n }\n}","import {\n Component,\n ElementRef,\n booleanAttribute,\n computed,\n forwardRef,\n inject,\n input,\n linkedSignal,\n output,\n signal,\n contentChild,\n} from '@angular/core';\nimport { ECLBaseDirective } from '@eui/ecl/core';\nimport { EclBannerComponent } from '@eui/ecl/components/ecl-banner';\nimport { EclSlideEvent } from './events/ecl-slide.event';\nimport { EclCarouselItem } from './models/ecl-carousel-item.model';\n\n/**\n * Single slide item for use inside an `EclCarouselComponent`.\n * Renders a `role=\"tabpanel\"` element with an `aria-roledescription=\"slide\"` and handles\n * the `inert` attribute so only the active slide is interactive.\n *\n * - Selector: `ecl-carousel-item`.\n * - `isCurrent` (input alias) — initial active state; kept as a `linkedSignal` so the parent\n * carousel can update it imperatively as the user navigates.\n * - `slideClick` — emits `EclSlideEvent` when the slide is clicked.\n * - `index` / `ariaLabel` — writable signals assigned by the parent carousel.\n * - Project an optional `EclBannerComponent` inside the slide for banner-style slides.\n */\n@Component({\n selector: 'ecl-carousel-item',\n templateUrl: './ecl-carousel-item.component.html',\n host: {\n role: 'tabpanel',\n '[attr.aria-label]': 'ariaLabel()',\n '[attr.aria-roledescription]': '\"slide\"',\n '[attr.inert]': '!isCurrent() || undefined',\n '[class]': 'cssClasses()',\n '(click)': 'onSlideClick()',\n },\n styles: [\n `\n /* TODO: remove by implementing full ECL specs */\n :host:before {\n left: 0 !important;\n display: none;\n }\n `,\n ],\n})\nexport class EclCarouselItemComponent extends ECLBaseDirective implements EclCarouselItem {\n el = inject(ElementRef);\n\n /**\n * The aria-label for the slide, assigned dynamically by the carousel.\n */\n readonly ariaLabel = signal<string | undefined>(undefined);\n\n /**\n * Input controlling whether this slide starts as the active/visible one.\n * Automatically coerced to a boolean value.\n */\n readonly isCurrentInput = input(false, { alias: 'isCurrent', transform: booleanAttribute });\n\n /**\n * Indicates whether this slide is currently active/visible.\n * Seeded from the `isCurrent` input but can be updated imperatively by the\n * parent carousel as the user navigates between slides.\n */\n readonly isCurrent = linkedSignal(() => this.isCurrentInput());\n\n /**\n * Text shown in the carousel teaser (navigation) button for this slide.\n * Optional; when empty, no teaser label is rendered for the slide.\n */\n readonly teaserText = input<string>('');\n\n /**\n * Emits an event when the slide is clicked.\n */\n readonly slideClick = output<EclSlideEvent>();\n\n /**\n * Optionally captures a banner component projected into the slide.\n */\n readonly banner = contentChild(forwardRef(() => EclBannerComponent));\n\n /**\n * Internal slide index, assigned dynamically by the carousel.\n */\n readonly index = signal<number | undefined>(undefined);\n\n /**\n * Computes the slide's CSS class.\n */\n protected readonly cssClasses = computed<string>(() =>\n super.getCssClasses('ecl-carousel__slide'));\n\n /**\n * Handles click events on the slide and emits a slideClick event.\n */\n onSlideClick(): void {\n this.slideClick.emit(new EclSlideEvent(this));\n }\n}\n","<ng-content></ng-content>\n","import { BreakpointObserver } from '@angular/cdk/layout';\nimport {\n AfterContentInit,\n ChangeDetectorRef,\n Component,\n DOCUMENT,\n ElementRef,\n OnDestroy,\n OnInit,\n Renderer2,\n afterNextRender,\n booleanAttribute,\n computed,\n contentChildren,\n forwardRef,\n inject,\n input,\n numberAttribute,\n output,\n signal,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { EUI_ECL_SLIDER } from '@eui/ecl/components/ecl-slider';\nimport { ECLBaseDirective, EclRtlService, KeyCode } from '@eui/ecl/core';\nimport { TranslatePipe, TranslateService } from '@ngx-translate/core';\nimport {\n EmblaEventType,\n EmblaOptionsType,\n EmblaPluginType,\n} from 'embla-carousel';\nimport { EmblaCarouselDirective } from 'embla-carousel-angular';\nimport Autoplay from 'embla-carousel-autoplay';\nimport { Subject, auditTime, fromEvent, takeUntil } from 'rxjs';\nimport { EclCarouselItemComponent } from './ecl-carousel-item.component';\nimport { EclSlideEvent } from './events/ecl-slide.event';\n\n/**\n * Number of teaser buttons visible at once on the desktop breakpoint.\n */\nconst VISIBLE_TEASERS = 4;\n\n/**\n * Carousel (slideshow) component following the ECL design system.\n * Renders a sequence of `EclCarouselItemComponent` slides with autoplay, keyboard navigation,\n * responsive breakpoint awareness, and RTL layout support.\n *\n * The slide engine is powered by Embla (via `embla-carousel-angular`), matching the upstream\n * ECL implementation: an infinite `loop`, the `Autoplay` plugin driving the teaser loading bars,\n * and a slider pager with previous/next/play/pause controls, a counter, and a tablist of teaser\n * buttons (one per slide).\n *\n * - Selector: `ecl-carousel`.\n * - Project `ecl-carousel-item` elements as slides (also via `contentChildren`).\n * - `ariaLabel` — ARIA label for the carousel landmark; aliased as `aria-label`.\n * - `isAutoplay` — enables automatic slide advancement; boolean attribute.\n * - `playInterval` — milliseconds between automatic transitions; default `5000`.\n * - `slide` — emits `EclSlideEvent` when the active slide changes.\n */\n@Component({\n selector: 'ecl-carousel',\n templateUrl: './ecl-carousel.component.html',\n imports: [\n TranslatePipe,\n EmblaCarouselDirective,\n ...EUI_ECL_SLIDER,\n ],\n host: {\n '[attr.aria-label]': 'ariaLabel()',\n '[attr.aria-roledescription]': '\"carousel\"',\n '[class]': 'cssClasses()',\n // Drives the teaser loading-bar animation duration (see @eui/styles).\n // It has no CSS fallback, so without it the progress animation never\n // runs; it must match the autoplay delay.\n '[style.--ecl-carousel-slide-duration]': 'playInterval() + \"ms\"',\n },\n})\nexport class EclCarouselComponent extends ECLBaseDirective implements OnInit, OnDestroy, AfterContentInit {\n /**\n * Aria-label for screen readers to describe the carousel.\n */\n readonly ariaLabel = input<string | null>('Carousel description here', { alias: 'aria-label' });\n\n /**\n * Determines whether the carousel should autoplay.\n */\n readonly isAutoplay = input<boolean, unknown>(undefined, { transform: booleanAttribute });\n\n /**\n * Interval in milliseconds between automatic slide transitions.\n */\n readonly playInterval = input(5000, { transform: numberAttribute });\n\n /**\n * Event emitted when a slide change occurs.\n */\n readonly slide = output<EclSlideEvent>();\n\n /**\n * Reference to the main carousel viewport element (the Embla root).\n */\n readonly carouselContainerElement = viewChild<ElementRef>('carouselContainer');\n\n /**\n * Collection of slide components rendered inside the carousel.\n */\n readonly slides = contentChildren(forwardRef(() => EclCarouselItemComponent));\n\n /**\n * Indicates whether autoplay is currently active.\n */\n readonly isPlaying = signal(false);\n\n /**\n * Indicates whether autoplay was manually paused (via the pause button or\n * on mobile). When paused this way the loading bar is cleared.\n */\n readonly isPausedForced = signal(false);\n\n /**\n * Indicates whether the layout is currently in RTL mode.\n */\n isRtl = false;\n\n /**\n * Zero-based index of the currently active slide (mirrors Embla's selected snap).\n */\n private activeIndex = 0;\n\n /**\n * Start index of the currently visible teaser window (desktop only).\n */\n private teaserWindowStart = 0;\n\n /**\n * Indicates whether autoplay is temporarily paused by hover/focus. Unlike a\n * manual pause, the loading bar stays visible and frozen at its current\n * progress (matching ECL), resuming when the pointer/focus leaves.\n */\n protected readonly isHoverPaused = signal(false);\n\n /**\n * Whether the current viewport is at the mobile breakpoint. A signal so the\n * template can react (the pager drops play/pause on mobile, matching ECL,\n * where play/pause is a desktop-only control).\n */\n protected readonly isMobileBreakpoint = signal(false);\n\n /**\n * Whether the viewport is at or above the ECL desktop breakpoint (1140px).\n * This is the boundary the ECL CSS uses to show the play/pause controls and\n * the teaser tablist (and to hide the mobile dots). A signal so the pager\n * variant can react: play/pause only renders at/above this width, matching\n * the CSS so the pause button never leaks onto narrower viewports.\n */\n protected readonly isDesktopBreakpointActive = signal(false);\n\n /**\n * Embla options, mirroring the upstream ECL configuration.\n */\n protected emblaOptions: EmblaOptionsType = {\n loop: true,\n align: 'start',\n duration: 20,\n };\n\n /**\n * Embla plugins. Built once so the Embla directive does not needlessly re-init.\n */\n protected emblaPlugins: EmblaPluginType[] = [];\n\n /**\n * Embla events the component reacts to.\n */\n protected readonly emblaEvents: EmblaEventType[] = [\n 'select',\n 'reInit',\n 'autoplay:timerset',\n ];\n\n /**\n * Reference to the Embla directive driving the slide engine.\n */\n private readonly embla = viewChild<EmblaCarouselDirective>('embla');\n\n /**\n * References to the teaser navigation buttons corresponding to each slide.\n */\n private readonly teaserButtons = viewChildren<ElementRef>('teaserButton');\n\n /**\n * References to the teaser loading-bar completion elements (one per slide),\n * used to restart the progress animation when the active slide changes.\n */\n private readonly loadingBars = viewChildren<ElementRef>('loadingBar');\n\n private isTabletBreakpoint = false;\n private isLargeBreakpoint = false;\n private isDesktopBreakpoint = false;\n\n private destroy$: Subject<boolean> = new Subject<boolean>();\n\n /**\n * Debounce interval (ms) used internally for timing and transitions.\n */\n private readonly TIMEOUT_INTERVAL = 400;\n private readonly cdkBreakpointObserver = inject(BreakpointObserver);\n private readonly cd = inject(ChangeDetectorRef);\n private readonly renderer2 = inject(Renderer2);\n private readonly eclRtlService = inject(EclRtlService);\n private readonly translate = inject(TranslateService);\n private readonly document = inject<Document>(DOCUMENT);\n private readonly window = this.document.defaultView;\n /**\n * Host element, used to locate the slider pager's play/pause buttons by their\n * ECL classes for focus management after a play/pause toggle.\n */\n private readonly hostEl = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /**\n * Returns the computed CSS class list for the component.\n */\n protected readonly cssClasses = computed<string>(() =>\n super.getCssClasses('ecl-carousel'));\n\n constructor() {\n super();\n afterNextRender(() => {\n this.observeElementSizeChanges();\n this.observeBreakpointChanges();\n this.syncFromEmbla();\n\n if (this.window) {\n fromEvent(this.window, 'resize')\n .pipe(auditTime(50), takeUntil(this.destroy$))\n .subscribe(() => this.observeElementSizeChanges());\n }\n });\n }\n\n /**\n * Angular lifecycle hook: initializes RTL detection and the Embla plugins.\n */\n ngOnInit(): void {\n this.emblaOptions = {\n ...this.emblaOptions,\n direction: this.isRtl ? 'rtl' : 'ltr',\n };\n const autoplayDesired = this.isAutoplayDesired();\n // Reflect the initial play state so the current slide's loading bar is\n // shown on load (the plugin self-starts via playOnInit).\n this.isPlaying.set(autoplayDesired);\n this.emblaPlugins = [\n Autoplay({\n delay: this.playInterval(),\n // Autoplay is on by default (matching ECL) unless explicitly\n // disabled via [isAutoplay]=\"false\". Letting the plugin start\n // itself avoids a race with Embla's own initialization.\n playOnInit: autoplayDesired,\n stopOnInteraction: false,\n stopOnMouseEnter: true,\n stopOnFocusIn: true,\n }),\n ];\n this.handleRtlChangeState();\n }\n\n /**\n * Angular lifecycle hook: called after content (slides) is initialized.\n */\n ngAfterContentInit(): void {\n setTimeout(() => {\n this.initSlides();\n });\n }\n\n /**\n * Angular lifecycle hook: cleans up subscriptions.\n */\n ngOnDestroy(): void {\n this.destroy$.next(true);\n this.destroy$.unsubscribe();\n }\n\n /**\n * Returns whether the carousel has padding applied (e.g., on desktop breakpoint).\n */\n isPadded(): boolean {\n return this.isDesktopBreakpoint;\n }\n\n /**\n * Checks whether there are enough slides to render controls.\n */\n hasControls(): boolean {\n return this.getSlidesCount() > 1;\n }\n\n /**\n * Retrieves the current active slide index (zero-based).\n */\n getCurrentSlideIndex(): number {\n return this.activeIndex;\n }\n\n /**\n * Returns the 1-based position of the active slide (for the counter).\n */\n getCounterCurrent(): number {\n return this.activeIndex + 1;\n }\n\n /**\n * Returns the total number of slides (for the counter).\n */\n getCounterTotal(): number {\n return this.getSlidesCount();\n }\n\n /**\n * Dot indices for the mobile slider pager (one dot per slide). The dots are\n * hidden on desktop via the ECL CSS (`.ecl-carousel__dots { display: none }`)\n * and shown at the mobile breakpoint.\n */\n getDotIndices(): number[] {\n return Array.from({ length: this.getSlidesCount() }, (_unused, dotIndex) => dotIndex);\n }\n\n /**\n * Pre-translated accessible label for each pager dot. Translated here since\n * the shared `ecl-slider-pager` receives plain strings.\n */\n getDotAriaLabels(): string[] {\n const total = this.getSlidesCount();\n return Array.from({ length: total }, (_unused, dotIndex) =>\n this.translate.instant('ecl.carousel.GO-TO-SLIDE', {\n current: dotIndex + 1,\n total,\n }),\n );\n }\n\n /**\n * Returns whether a teaser button should be visible in the current window.\n */\n isTeaserVisible(index: number): boolean {\n const count = this.getSlidesCount();\n if (count <= VISIBLE_TEASERS) {\n return true;\n }\n const position = ((index - this.teaserWindowStart) % count + count) % count;\n return position < VISIBLE_TEASERS;\n }\n\n /**\n * Returns the flex order of a teaser button within the visible window.\n */\n getTeaserOrder(index: number): number {\n const count = this.getSlidesCount();\n return ((index - this.teaserWindowStart) % count + count) % count;\n }\n\n /**\n * Whether the pager should show the \"pause\" control (i.e. autoplay is\n * actively running). While the pointer/focus hover-pauses the carousel the\n * timer is suspended, so the pager must show \"play\" even though a manual\n * pause was not triggered. Mirrors upstream ECL, where hovering flips the\n * control to play.\n */\n protected isPagerPlaying(): boolean {\n return this.isPlaying() && !this.isHoverPaused();\n }\n\n /**\n * Pager variant by breakpoint. Below the ECL desktop breakpoint (1140px)\n * the carousel shows only the dots navigation (prev / dots / next);\n * play/pause is a desktop-only control in ECL. Rendering `'dots'` there\n * avoids the pager's inline play/pause `display` style (which would\n * otherwise beat the ECL CSS and leave the pause button visible on narrower\n * viewports). At/above 1140px the dots are hidden by CSS, so\n * `'play-pause-dots'` yields play/pause + prev/next + teasers.\n *\n * The 1140px boundary mirrors the media query the ECL CSS uses to toggle\n * `.ecl-carousel__play/__pause` and `.ecl-carousel__teasers`.\n */\n protected pagerVariant(): 'dots' | 'play-pause-dots' {\n return this.isDesktopBreakpointActive() ? 'play-pause-dots' : 'dots';\n }\n\n /**\n * Handles the throttled Embla events the component subscribed to.\n */\n protected onEmblaEvent(event: EmblaEventType): void {\n switch (event) {\n case 'select':\n case 'reInit':\n this.syncFromEmbla();\n break;\n case 'autoplay:timerset':\n // Fired each time the autoplay timer (re)starts for the current\n // slide; replay the loading-bar fill animation from zero.\n this.restartActiveLoadingBar();\n break;\n default:\n break;\n }\n }\n\n /**\n * Starts autoplay.\n *\n * @param moveFocus when true (a user clicked play) focus moves to the pause\n * button. Auto-starts (e.g. on breakpoint changes) pass false so the\n * page is not scrolled to the carousel on load.\n */\n protected onPlayClick(moveFocus = true): void {\n this.getAutoplay()?.play();\n this.isPlaying.set(true);\n this.isPausedForced.set(false);\n this.isHoverPaused.set(false);\n this.cd.detectChanges();\n if (moveFocus) {\n this.focusPagerButton('.ecl-carousel__pause');\n }\n }\n\n /**\n * Stops autoplay and focuses the play button.\n */\n protected onPauseClick(): void {\n // Pause (not full stop): halt the autoplay timer but keep the active\n // teaser loading bar visible, frozen at its current progress (matching\n // upstream ECL's `handleAutoPlay(false, true)`). The installed\n // embla-carousel-autoplay exposes no `pause()`, so we call `stop()`\n // WITHOUT `reset()` — the frozen bar is driven by our `is-paused` CSS\n // class, not the plugin. A full stop+reset (which clears the bar) only\n // happens on prev/next/teaser navigation via `stopAutoplay()`.\n this.getAutoplay()?.stop();\n this.isPlaying.set(false);\n this.isPausedForced.set(true);\n this.isHoverPaused.set(false);\n this.cd.detectChanges();\n this.focusPagerButton('.ecl-carousel__play');\n }\n\n /**\n * Navigates to the next slide and stops autoplay.\n */\n protected onNextSlideClick(): void {\n this.stopAutoplay();\n this.embla()?.scrollNext();\n }\n\n /**\n * Navigates to the previous slide and stops autoplay.\n */\n protected onPreviousSlideClick(): void {\n this.stopAutoplay();\n this.embla()?.scrollPrev();\n }\n\n /**\n * Handles user interaction with a teaser button: activates the matching slide.\n */\n protected onTeaserClick(index: number): void {\n this.stopAutoplay();\n this.embla()?.scrollTo(index);\n }\n\n /**\n * Handles a dot activation from the mobile slider pager: scrolls to the\n * matching slide and stops autoplay (same behavior as a teaser click).\n */\n protected onDotClick(index: number): void {\n this.stopAutoplay();\n this.embla()?.scrollTo(index);\n }\n\n /**\n * Handles keyboard navigation (ArrowLeft/ArrowRight) across teaser buttons.\n */\n protected onTeaserKeyboardPress(event: KeyboardEvent, index: number): void {\n if (event.key !== KeyCode.ARROW_RIGHT && event.key !== KeyCode.ARROW_LEFT) {\n return;\n }\n event.preventDefault();\n const direction = event.key === KeyCode.ARROW_RIGHT ? 1 : -1;\n const count = this.getSlidesCount();\n const nextIndex = (index + direction + count) % count;\n this.stopAutoplay();\n this.embla()?.scrollTo(nextIndex);\n this.focusOnButton(this.teaserButtons()[nextIndex]);\n }\n\n /**\n * Freezes the loading bar while the pointer/focus is over the carousel.\n * The Embla autoplay plugin pauses the timer itself (stopOnMouseEnter /\n * stopOnFocusIn); this only mirrors that as a visible paused state.\n */\n protected onViewportPause(): void {\n if (this.isPlaying() && !this.isPausedForced()) {\n this.isHoverPaused.set(true);\n this.cd.detectChanges();\n }\n }\n\n /**\n * Resumes the loading bar once the pointer/focus leaves the carousel.\n */\n protected onViewportResume(): void {\n if (this.isHoverPaused()) {\n this.isHoverPaused.set(false);\n this.cd.detectChanges();\n }\n }\n\n /**\n * Sets focus on the specified button.\n */\n private focusOnButton(button: ElementRef): void {\n if (!button) {\n return;\n }\n button.nativeElement.focus();\n }\n\n /**\n * Focuses the slider pager button matching the given ECL class selector\n * (e.g. `.ecl-carousel__play`). Used after a play/pause toggle so focus\n * follows the now-visible control, since the pager swaps play/pause\n * visibility via CSS. No-op if the button is not rendered (e.g. mobile).\n */\n private focusPagerButton(selector: string): void {\n const button = this.hostEl.nativeElement.querySelector<HTMLElement>(selector);\n button?.focus();\n }\n\n /**\n * Returns the Embla autoplay plugin instance, but only when the carousel\n * actually has more than one scroll snap.\n *\n * The `embla-carousel-autoplay` plugin skips its own initialization when\n * `scrollSnapList().length <= 1` (see the plugin's `init`), which leaves its\n * internal `delay` lookup table undefined. Calling `play()` in that state\n * throws (`delay[selectedScrollSnap()]` -> reading `0` of undefined). This\n * happens whenever Embla cannot lay out multiple snaps — notably in a jsdom\n * test or during SSR. Gating on the same `> 1` condition the plugin uses\n * keeps autoplay a safe no-op until the carousel is genuinely slideable.\n */\n private getAutoplay() {\n const api = this.embla()?.emblaApi;\n if (!api || api.scrollSnapList().length <= 1) {\n return undefined;\n }\n return api.plugins()?.autoplay;\n }\n\n /**\n * Whether autoplay should run. On by default (matching ECL); only disabled\n * when the consumer explicitly sets `[isAutoplay]=\"false\"`.\n */\n private isAutoplayDesired(): boolean {\n const isAutoplay = this.isAutoplay();\n return isAutoplay || isAutoplay === undefined;\n }\n\n /**\n * Stops autoplay and resets it (mirrors ECL's `handleAutoPlay(true)`),\n * clearing the loading-bar state.\n */\n private stopAutoplay(): void {\n const autoplay = this.getAutoplay();\n autoplay?.stop();\n autoplay?.reset();\n this.isPlaying.set(false);\n this.isPausedForced.set(false);\n this.isHoverPaused.set(false);\n this.cd.detectChanges();\n }\n\n /**\n * Synchronizes component state from Embla's current selected snap:\n * active index, slide `isCurrent` flags, teaser window and the slide event.\n */\n private syncFromEmbla(): void {\n const api = this.embla()?.emblaApi;\n if (!api) {\n return;\n }\n const selected = api.selectedScrollSnap();\n this.setActiveIndex(selected);\n this.updateTeaserWindow();\n this.slide.emit(new EclSlideEvent(this.slides().at(this.activeIndex)));\n this.cd.detectChanges();\n }\n\n /**\n * Subscribes to RTL layout state changes to adapt carousel direction.\n */\n private handleRtlChangeState(): void {\n this.eclRtlService.currentRtlState$.pipe(takeUntil(this.destroy$)).subscribe((rtlState) => {\n const changed = this.isRtl !== rtlState;\n this.isRtl = rtlState;\n if (changed) {\n this.emblaOptions = {\n ...this.emblaOptions,\n direction: this.isRtl ? 'rtl' : 'ltr',\n };\n this.cd.detectChanges();\n }\n });\n }\n\n /**\n * Initializes slides (index, ARIA label, banner height management).\n */\n private initSlides(): void {\n const slides = this.slides();\n slides.forEach((item, idx) => {\n item.index.set(idx);\n item.ariaLabel.set(`slide ${idx + 1} of ${slides.length}`);\n item.isCurrent.set(idx === 0);\n const banner = item.banner();\n if (banner) {\n banner.skipHeightManagement = true;\n }\n });\n this.cd.detectChanges();\n }\n\n /**\n * Updates the active index and synchronizes slide active/inert state.\n */\n private setActiveIndex(index: number): void {\n this.activeIndex = index;\n this.slides().forEach((item, idx) => {\n item.isCurrent.set(idx === index);\n });\n }\n\n /**\n * Restarts the CSS progress animation on the active slide's loading bar.\n * The animation uses `forwards`, so re-applying the `is-active` class alone\n * will not replay it; the animation must be reset explicitly.\n */\n private restartActiveLoadingBar(): void {\n if (!this.getAutoplay()?.isPlaying()) {\n return;\n }\n const bar = this.loadingBars()[this.activeIndex]?.nativeElement as HTMLElement | undefined;\n if (!bar) {\n return;\n }\n bar.style.animation = 'none';\n // Force reflow so the browser registers the reset before re-enabling.\n void bar.offsetWidth;\n bar.style.animation = '';\n }\n\n /**\n * Advances the visible teaser window when the active slide moves out of it.\n */\n private updateTeaserWindow(): void {\n const count = this.getSlidesCount();\n if (count <= VISIBLE_TEASERS) {\n this.teaserWindowStart = 0;\n return;\n }\n const firstHiddenIndex = (this.teaserWindowStart + VISIBLE_TEASERS) % count;\n if (this.activeIndex === firstHiddenIndex) {\n this.teaserWindowStart = firstHiddenIndex;\n }\n }\n\n /**\n * Returns the number of actual visible slides.\n */\n private getSlidesCount(): number {\n return this.slides()?.length ?? 0;\n }\n\n /**\n * Observes screen breakpoint changes to adjust autoplay and layout behavior.\n */\n private observeBreakpointChanges(): void {\n this.cdkBreakpointObserver\n .observe([\n '(max-width: 768px)',\n '(min-width: 998px)',\n '(min-width: 1140px)',\n '(min-width: 1140px) and (max-width: 1260px)',\n ])\n .pipe(takeUntil(this.destroy$))\n .subscribe((result) => {\n this.isMobileBreakpoint.set(result.breakpoints['(max-width: 768px)']);\n this.isTabletBreakpoint = result.breakpoints['(min-width: 998px)'];\n this.isLargeBreakpoint = result.breakpoints['(min-width: 1140px)'];\n this.isDesktopBreakpointActive.set(result.breakpoints['(min-width: 1140px)']);\n this.isDesktopBreakpoint = result.breakpoints['(min-width: 1140px) and (max-width: 1260px)'];\n\n // Deactivate autoplay on mobile; (re)activate it on larger\n // screens if autoplay is desired. Focus is never moved here so\n // the page is not scrolled to the carousel on load/resize.\n if (this.isMobileBreakpoint()) {\n this.stopAutoplay();\n return;\n }\n\n if (this.isTabletBreakpoint && this.isAutoplayDesired() && !this.isPausedForced()) {\n this.onPlayClick(false);\n }\n });\n }\n\n /**\n * Observes changes to the carousel's viewport element size using a timeout debounce.\n */\n private observeElementSizeChanges(): void {\n setTimeout(() => {\n if (this.isLargeBreakpoint) {\n this.checkBannerHeights();\n } else {\n this.resetHeight();\n }\n this.embla()?.reInit();\n }, this.TIMEOUT_INTERVAL);\n }\n\n /**\n * Normalizes the height of all banners to match the tallest banner.\n */\n private checkBannerHeights(): void {\n this.slides().forEach((slide) => {\n const banner = slide.banner();\n if (banner) {\n banner.calculateHeight();\n }\n });\n\n const heightValues = this.slides().map((slide) => {\n const el = slide.banner()?.el.nativeElement;\n if (!el) return undefined;\n\n const styleHeight = el.style.height;\n\n if (styleHeight === 'auto' || styleHeight === '') {\n return el.offsetHeight;\n }\n\n const height = parseInt(styleHeight, 10);\n if (Number.isNaN(height) || height === 100) {\n return 1;\n }\n\n return height;\n });\n\n const elementHeights = heightValues.filter((h) => h !== undefined) as number[];\n const tallestElementHeight = Math.max(...elementHeights);\n\n const slides = this.slides();\n if (tallestElementHeight > 1 && elementHeights.length === slides.length) {\n slides.forEach((slide) => {\n const banner = slide.banner();\n if (!banner) return;\n\n const el = banner.el.nativeElement;\n const bannerImage = banner.eclBannerImage();\n const bannerVideo = banner.eclBannerVideo();\n\n this.renderer2.setStyle(el, 'height', `${tallestElementHeight}px`);\n this.renderer2.setStyle(el, 'aspect-ratio', 'auto');\n\n if (bannerImage) {\n this.renderer2.setStyle(bannerImage.el.nativeElement, 'aspect-ratio', 'auto');\n }\n if (bannerVideo) {\n this.renderer2.setStyle(bannerVideo.el.nativeElement, 'aspect-ratio', 'auto');\n }\n });\n }\n }\n\n /**\n * Clears all explicit banner height and aspect ratio styling for smaller breakpoints.\n */\n private resetHeight(): void {\n this.slides().forEach((slide) => {\n const banner = slide.banner();\n if (banner) {\n const bannerImage = banner.eclBannerImage();\n const bannerVideo = banner.eclBannerVideo();\n this.renderer2.removeStyle(banner.el.nativeElement, 'height');\n this.renderer2.removeStyle(banner.el.nativeElement, 'aspect-ratio');\n if (bannerImage) {\n this.renderer2.removeStyle(bannerImage.el.nativeElement, 'aspect-ratio');\n }\n if (bannerVideo) {\n this.renderer2.removeStyle(bannerVideo.el.nativeElement, 'aspect-ratio');\n }\n }\n });\n }\n}\n","@if (hasControls()) {\n<div class=\"ecl-carousel__controls\">\n <div class=\"ecl-container\">\n <div class=\"ecl-carousel__navigation\">\n <div class=\"ecl-carousel__pager-container\">\n <ecl-slider-pager\n class=\"ecl-carousel__pager\"\n [variant]=\"pagerVariant()\"\n size=\"m\"\n [isPlaying]=\"isPagerPlaying()\"\n [activeIndex]=\"getCurrentSlideIndex()\"\n [dotIndices]=\"getDotIndices()\"\n [dotAriaLabels]=\"getDotAriaLabels()\"\n prevExtraClasses=\"ecl-carousel__prev\"\n nextExtraClasses=\"ecl-carousel__next\"\n dotsExtraClasses=\"ecl-carousel__dots\"\n dotExtraClasses=\"ecl-carousel__dot\"\n playExtraClasses=\"ecl-carousel__play\"\n pauseExtraClasses=\"ecl-carousel__pause\"\n (play)=\"onPlayClick()\"\n (pause)=\"onPauseClick()\"\n (prev)=\"onPreviousSlideClick()\"\n (next)=\"onNextSlideClick()\"\n (goTo)=\"onDotClick($event)\">\n </ecl-slider-pager>\n <div class=\"ecl-carousel__counter\" dir=\"ltr\">\n {{ getCounterCurrent() }} {{ ('ecl.common.OF' | translate) }} {{ getCounterTotal() }}\n </div>\n </div>\n\n <div class=\"ecl-carousel__teasers\" role=\"tablist\">\n @for (slide of slides(); let i = $index; track slide) {\n <button #teaserButton type=\"button\" class=\"ecl-carousel__teaser-button\" role=\"tab\"\n [attr.data-ecl-carousel-slide-index]=\"i\"\n [attr.aria-current]=\"i === getCurrentSlideIndex() ? true : null\"\n [attr.tabindex]=\"i === getCurrentSlideIndex() ? null : -1\"\n [style.display]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.pointer-events]=\"isTeaserVisible(i) ? null : 'none'\"\n [style.order]=\"getTeaserOrder(i)\" (click)=\"onTeaserClick(i)\"\n (keydown)=\"onTeaserKeyboardPress($event, i)\">\n <span class=\"ecl-carousel__teaser-loading-bar\" aria-hidden=\"true\"\n [class.is-active]=\"(isPlaying() || isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\"\n [class.is-paused]=\"(isHoverPaused() || isPausedForced()) && i === getCurrentSlideIndex()\">\n <span #loadingBar class=\"ecl-carousel__teaser-loading-bar-completion\"></span>\n </span>\n <span class=\"ecl-carousel__teaser-content\">\n @if (slide.teaserText()) {\n <span class=\"ecl-carousel__teaser-title\">{{ slide.teaserText() }}</span>\n }\n </span>\n </button>\n }\n </div>\n </div>\n </div>\n</div>\n}\n<div #carouselContainer class=\"ecl-carousel__viewport\" [class.ecl-carousel-container--padded]=\"isPadded()\"\n emblaCarousel #embla=\"emblaCarousel\" [options]=\"emblaOptions\" [plugins]=\"emblaPlugins\"\n [subscribeToEvents]=\"emblaEvents\" (emblaChange)=\"onEmblaEvent($event)\"\n (mouseenter)=\"onViewportPause()\" (mouseleave)=\"onViewportResume()\"\n (focusin)=\"onViewportPause()\" (focusout)=\"onViewportResume()\">\n <div class=\"ecl-carousel__slides\">\n <ng-content></ng-content>\n </div>\n</div>\n","import { EclCarouselComponent } from './ecl-carousel.component';\nimport { EclCarouselItemComponent } from './ecl-carousel-item.component';\n\nexport * from './ecl-carousel.component';\nexport * from './ecl-carousel-item.component';\nexport * from './events/ecl-slide.event';\nexport * from './models/ecl-carousel-item.model';\n\nexport const EUI_ECL_CAROUSEL = [\n EclCarouselComponent,\n EclCarouselItemComponent,\n] as const;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eui/ecl",
3
- "version": "22.0.0-alpha.56",
3
+ "version": "22.0.0-alpha.58",
4
4
  "tag": "next",
5
5
  "description": "eUI ECL components package",
6
6
  "homepage": "https://eui.ecdevops.eu",
@@ -1,5 +1,5 @@
1
1
  import * as i0 from "@angular/core";
2
- import { AfterContentInit, ElementRef, OnDestroy, OnInit, Signal, WritableSignal } from "@angular/core";
2
+ import { AfterContentInit, ElementRef, OnDestroy, OnInit, WritableSignal } from "@angular/core";
3
3
  import { ECLBaseDirective, EclBaseEvent } from "@eui/ecl/core";
4
4
  import { EmblaEventType, EmblaOptionsType, EmblaPluginType } from "embla-carousel";
5
5
  /**
@@ -11,8 +11,6 @@ export interface EclCarouselItem {
11
11
  isCurrent: WritableSignal<boolean>;
12
12
  /** Zero-based index assigned by the parent carousel. */
13
13
  index: WritableSignal<number | undefined>;
14
- /** Optional slide identifier used for navigation buttons. */
15
- id?: Signal<string | undefined>;
16
14
  }
17
15
  /**
18
16
  * Event emitted by `EclCarouselComponent` when the active slide changes, and by
@@ -41,7 +39,6 @@ export declare class EclSlideEvent extends EclBaseEvent {
41
39
  * - `ariaLabel` — ARIA label for the carousel landmark; aliased as `aria-label`.
42
40
  * - `isAutoplay` — enables automatic slide advancement; boolean attribute.
43
41
  * - `playInterval` — milliseconds between automatic transitions; default `5000`.
44
- * - `counterLabel` — separator label used by the counter, defaults to `ecl.common.OF`.
45
42
  * - `slide` — emits `EclSlideEvent` when the active slide changes.
46
43
  */
47
44
  export declare class EclCarouselComponent extends ECLBaseDirective implements OnInit, OnDestroy, AfterContentInit {
@@ -57,11 +54,6 @@ export declare class EclCarouselComponent extends ECLBaseDirective implements On
57
54
  * Interval in milliseconds between automatic slide transitions.
58
55
  */
59
56
  readonly playInterval: import("@angular/core").InputSignalWithTransform<number, unknown>;
60
- /**
61
- * Separator label used by the counter, e.g. the "of" in "1 of 5".
62
- * Defaults to the translated `ecl.common.OF` key.
63
- */
64
- readonly counterLabel: import("@angular/core").InputSignal<string>;
65
57
  /**
66
58
  * Event emitted when a slide change occurs.
67
59
  */
@@ -382,11 +374,6 @@ export declare class EclCarouselComponent extends ECLBaseDirective implements On
382
374
  "required": false;
383
375
  "isSignal": true;
384
376
  };
385
- "counterLabel": {
386
- "alias": "counterLabel";
387
- "required": false;
388
- "isSignal": true;
389
- };
390
377
  }, {
391
378
  "slide": "slide";
392
379
  }, ["slides"], ["*"], true, never>;
@@ -397,7 +384,6 @@ export declare class EclCarouselComponent extends ECLBaseDirective implements On
397
384
  * the `inert` attribute so only the active slide is interactive.
398
385
  *
399
386
  * - Selector: `ecl-carousel-item`.
400
- * - `id` — optional unique identifier; used by the carousel for navigation buttons.
401
387
  * - `isCurrent` (input alias) — initial active state; kept as a `linkedSignal` so the parent
402
388
  * carousel can update it imperatively as the user navigates.
403
389
  * - `slideClick` — emits `EclSlideEvent` when the slide is clicked.
@@ -410,10 +396,6 @@ export declare class EclCarouselItemComponent extends ECLBaseDirective implement
410
396
  * The aria-label for the slide, assigned dynamically by the carousel.
411
397
  */
412
398
  readonly ariaLabel: import("@angular/core").WritableSignal<string>;
413
- /**
414
- * The unique identifier of the slide.
415
- */
416
- readonly id: import("@angular/core").InputSignal<string>;
417
399
  /**
418
400
  * Input controlling whether this slide starts as the active/visible one.
419
401
  * Automatically coerced to a boolean value.
@@ -452,11 +434,6 @@ export declare class EclCarouselItemComponent extends ECLBaseDirective implement
452
434
  onSlideClick(): void;
453
435
  static ɵfac: i0.ɵɵFactoryDeclaration<EclCarouselItemComponent, never>;
454
436
  static ɵcmp: i0.ɵɵComponentDeclaration<EclCarouselItemComponent, "ecl-carousel-item", never, {
455
- "id": {
456
- "alias": "id";
457
- "required": false;
458
- "isSignal": true;
459
- };
460
437
  "isCurrentInput": {
461
438
  "alias": "isCurrent";
462
439
  "required": false;
@@ -1 +1 @@
1
- {"version":3,"file":"eui-ecl-components-ecl-carousel.d.ts","names":[],"sources":["../../components/ecl-carousel/models/ecl-carousel-item.model.ts","../../components/ecl-carousel/events/ecl-slide.event.ts","../../components/ecl-carousel/ecl-carousel.component.ts","../../components/ecl-carousel/ecl-carousel-item.component.ts","../../components/ecl-carousel/index.ts"],"mappings":";;;;;;;;iBAMiB;;EAEhB,WAAW;;EAEX,OAAO;;EAEP,KAAK;;;;;;;qBCJO,sBAAsB;EAIZ,MAAM;;;;EAAN,YAAA,MAAM;;;;;;;;;;;;;;;;;;;;qBCkEhB,6BAA6B,4BAA4B,QAAQ,WAAW;;;;WAI5E,mCAAS;;;;WAKT,oCAAU;;;;WAKV,sCAAY;;;;;WAMZ,sCAAY;;;;WAKZ,+BAAK,iBAAA;;;;WAKL,kDAAwB,OAAA;;;;WAKxB,gCAAM;;;;WAKN,mCAAS;;;;;WAMT,wCAAc;;;;EAKvB;;;;UAKQ;;;;UAKA;;;;;;qBAOW,uCAAa;;;;;;qBAOb,4CAAkB;;;;;;;;qBASlB,mDAAyB;;;;YAKlC,cAAc;;;;YASd,cAAc;;;;qBAKL,aAAa;;;;mBASf;;;;mBAKA;;;;;mBAMA;UAET;UACA;UACA;UAEA;;;;mBAKS;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;;;;;mBAKA;;;;qBAKE,oCAAU;;;;;EAqB7B;;;;EA2BA;;;;EASA;;;;EAQA;;;;EAOA;;;;EAOA;;;;EAOA;;;;EAOA;;;;;;EASA;;;;;EAQA;;;;EAaA,gBAAgB;;;;EAYhB,eAAe;;;;;;;;YAYL;;;;;;;;;;;;;YAgBA;;;;YAOA,aAAa,OAAO;;;;;;;;YAuBpB,YAAY;;;;YAcZ;;;;YAmBA;;;;YAQA;;;;YAQA,cAAc;;;;;YASd,WAAW;;;;YAQX,sBAAsB,OAAO,eAAe;;;;;;YAkB5C;;;;YAUA;;;;UAUF;;;;;;;UAaA;;;;;;;;;;;;;UAiBA;;;;;UAYA;;;;;UASA;;;;;UAcA;;;;UAeA;;;;UAiBA;;;;UAiBA;;;;;;UAYA;;;;UAiBA;;;;UAeA;;;;UAOA;;;;UAiCA;;;;UAcA;;;;UAuDA;SA3sBC,MAAA,GAAA,qBAAA;SAAA,MAAA,GAAA,uBAAA;IAAoB;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;;IAAA;;;;;;;;;;;;;;;;qBC1BpB,iCAAiC,4BAA4B;EACtE,IAAE;;;;WAKO,mCAAS;;;;WAKT,4BAAE;;;;;WAMF,wCAAc;;;;;;WAOd,mCAAS;;;;;WAMT,oCAAU;;;;WAKV,oCAAU,iBAAA;;;;WAKV,gCAAM;;;;WAKN,+BAAK;;;;qBAKK,oCAAU;;;;EAM7B;SAxDS,MAAA,GAAA,qBAAA;SAAA,MAAA,GAAA,uBAAA;IAAwB;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;;IAAA;;;qBC5CxB,mCAAgB,6BAAA"}
1
+ {"version":3,"file":"eui-ecl-components-ecl-carousel.d.ts","names":[],"sources":["../../components/ecl-carousel/models/ecl-carousel-item.model.ts","../../components/ecl-carousel/events/ecl-slide.event.ts","../../components/ecl-carousel/ecl-carousel.component.ts","../../components/ecl-carousel/ecl-carousel-item.component.ts","../../components/ecl-carousel/index.ts"],"mappings":";;;;;;;;iBAMiB;;EAEhB,WAAW;;EAEX,OAAO;;;;;;;qBCFK,sBAAsB;EAIZ,MAAM;;;;EAAN,YAAA,MAAM;;;;;;;;;;;;;;;;;;;qBCiEhB,6BAA6B,4BAA4B,QAAQ,WAAW;;;;WAI5E,mCAAS;;;;WAKT,oCAAU;;;;WAKV,sCAAY;;;;WAKZ,+BAAK,iBAAA;;;;WAKL,kDAAwB,OAAA;;;;WAKxB,gCAAM;;;;WAKN,mCAAS;;;;;WAMT,wCAAc;;;;EAKvB;;;;UAKQ;;;;UAKA;;;;;;qBAOW,uCAAa;;;;;;qBAOb,4CAAkB;;;;;;;;qBASlB,mDAAyB;;;;YAKlC,cAAc;;;;YASd,cAAc;;;;qBAKL,aAAa;;;;mBASf;;;;mBAKA;;;;;mBAMA;UAET;UACA;UACA;UAEA;;;;mBAKS;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;;;;;mBAKA;;;;qBAKE,oCAAU;;;;;EAqB7B;;;;EA2BA;;;;EASA;;;;EAQA;;;;EAOA;;;;EAOA;;;;EAOA;;;;EAOA;;;;;;EASA;;;;;EAQA;;;;EAaA,gBAAgB;;;;EAYhB,eAAe;;;;;;;;YAYL;;;;;;;;;;;;;YAgBA;;;;YAOA,aAAa,OAAO;;;;;;;;YAuBpB,YAAY;;;;YAcZ;;;;YAmBA;;;;YAQA;;;;YAQA,cAAc;;;;;YASd,WAAW;;;;YAQX,sBAAsB,OAAO,eAAe;;;;;;YAkB5C;;;;YAUA;;;;UAUF;;;;;;;UAaA;;;;;;;;;;;;;UAiBA;;;;;UAYA;;;;;UASA;;;;;UAcA;;;;UAeA;;;;UAiBA;;;;UAiBA;;;;;;UAYA;;;;UAiBA;;;;UAeA;;;;UAOA;;;;UAiCA;;;;UAcA;;;;UAuDA;SArsBC,MAAA,GAAA,qBAAA;SAAA,MAAA,GAAA,uBAAA;IAAoB;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;;IAAA;;;;;;;;;;;;;;;qBC1BpB,iCAAiC,4BAA4B;EACtE,IAAE;;;;WAKO,mCAAS;;;;;WAMT,wCAAc;;;;;;WAOd,mCAAS;;;;;WAMT,oCAAU;;;;WAKV,oCAAU,iBAAA;;;;WAKV,gCAAM;;;;WAKN,+BAAK;;;;qBAKK,oCAAU;;;;EAM7B;SAnDS,MAAA,GAAA,qBAAA;SAAA,MAAA,GAAA,uBAAA;IAAwB;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;;IAAA;;;qBC3CxB,mCAAgB,6BAAA"}