@tedi-design-system/angular 8.2.0-rc.5 → 8.2.0-rc.6

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.
@@ -15654,6 +15654,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
15654
15654
  }]
15655
15655
  }] });
15656
15656
 
15657
+ /** Ignore tiny calculation differences when deciding the carousel’s position. */
15658
+ const EPSILON = 0.001;
15657
15659
  class CarouselContentComponent {
15658
15660
  /** Slides per view (minimum 1, can be fractional, e.g. 1.25 for peeking) */
15659
15661
  slidesPerView = input({ xs: 1 }, ...(ngDevMode ? [{ debugName: "slidesPerView", transform: (v) => breakpointInput(v) }] : [{ transform: (v) => breakpointInput(v) }]));
@@ -15663,6 +15665,12 @@ class CarouselContentComponent {
15663
15665
  fade = input(false, ...(ngDevMode ? [{ debugName: "fade" }] : []));
15664
15666
  /** Transition duration in ms */
15665
15667
  transitionMs = input(400, ...(ngDevMode ? [{ debugName: "transitionMs" }] : []));
15668
+ /**
15669
+ * Whether navigation wraps around at the ends. When `false`, it stops at the
15670
+ * first and last reachable positions and disables the corresponding arrow.
15671
+ * @default true
15672
+ */
15673
+ loop = input(true, ...(ngDevMode ? [{ debugName: "loop", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
15666
15674
  /** Accessible label for the carousel region. Falls back to the `carousel` translation. */
15667
15675
  ariaLabel = input(...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : []));
15668
15676
  translationService = inject(TediTranslationService);
@@ -15726,18 +15734,46 @@ class CarouselContentComponent {
15726
15734
  return this.gap().xs;
15727
15735
  }
15728
15736
  }, ...(ngDevMode ? [{ debugName: "currentGap" }] : []));
15729
- buffer = computed(() => this.slides().length, ...(ngDevMode ? [{ debugName: "buffer" }] : []));
15737
+ buffer = computed(() => (this.loop() ? this.slides().length : 0), ...(ngDevMode ? [{ debugName: "buffer" }] : []));
15738
+ /** Furthest track position in bounded mode; may be fractional to show the last slide fully. */
15739
+ maxIndex = computed(() => Math.max(0, this.slides().length - this.currentSlidesPerView()), ...(ngDevMode ? [{ debugName: "maxIndex" }] : []));
15740
+ /** Number of indicator positions: one per slide when looping, or one per reachable stop when bounded. */
15741
+ positionCount = computed(() => {
15742
+ if (this.loop() || !this.slides().length) {
15743
+ return this.slides().length;
15744
+ }
15745
+ return Math.ceil(this.maxIndex() - EPSILON) + 1;
15746
+ }, ...(ngDevMode ? [{ debugName: "positionCount" }] : []));
15747
+ /** Index of the active indicator; a fractional final stop gets its own index. */
15748
+ activePosition = computed(() => {
15749
+ if (this.loop()) {
15750
+ return this.slideIndex();
15751
+ }
15752
+ const nearest = this.snap(this.trackIndex());
15753
+ return nearest >= this.maxIndex() - EPSILON
15754
+ ? this.positionCount() - 1
15755
+ : Math.round(nearest);
15756
+ }, ...(ngDevMode ? [{ debugName: "activePosition" }] : []));
15757
+ /** Index of the leftmost visible slide, skipping a partially visible one in bounded mode. */
15730
15758
  slideIndex = computed(() => {
15731
15759
  const slidesCount = this.slides().length;
15732
15760
  if (slidesCount === 0) {
15733
15761
  return 0;
15734
15762
  }
15763
+ if (!this.loop()) {
15764
+ return Math.min(Math.max(Math.ceil(this.trackIndex() - EPSILON), 0), slidesCount - 1);
15765
+ }
15735
15766
  const i = Math.floor(this.trackIndex());
15736
15767
  return ((i % slidesCount) + slidesCount) % slidesCount;
15737
15768
  }, ...(ngDevMode ? [{ debugName: "slideIndex" }] : []));
15738
15769
  renderedActiveIndex = computed(() => {
15770
+ if (!this.loop()) {
15771
+ return this.trackIndex();
15772
+ }
15739
15773
  return this.trackIndex() - this.windowBase() + this.buffer();
15740
15774
  }, ...(ngDevMode ? [{ debugName: "renderedActiveIndex" }] : []));
15775
+ canPrev = computed(() => this.loop() || this.trackIndex() > EPSILON, ...(ngDevMode ? [{ debugName: "canPrev" }] : []));
15776
+ canNext = computed(() => this.loop() || this.trackIndex() < this.maxIndex() - EPSILON, ...(ngDevMode ? [{ debugName: "canNext" }] : []));
15741
15777
  /**
15742
15778
  * Checks if a slide at the given rendered index is currently visible in the viewport.
15743
15779
  * Used to determine which slides should be accessible to screen readers.
@@ -15753,6 +15789,9 @@ class CarouselContentComponent {
15753
15789
  if (!slidesCount) {
15754
15790
  return [];
15755
15791
  }
15792
+ if (!this.loop()) {
15793
+ return Array.from({ length: slidesCount }, (_, i) => i);
15794
+ }
15756
15795
  const total = 2 * this.buffer() + Math.ceil(this.currentSlidesPerView());
15757
15796
  const start = this.windowBase() - this.buffer();
15758
15797
  return Array.from({ length: total }, (_, i) => (((start + i) % slidesCount) + slidesCount) % slidesCount);
@@ -15785,7 +15824,7 @@ class CarouselContentComponent {
15785
15824
  }
15786
15825
  const totalGapWidth = gap * (slidesPerView - 1);
15787
15826
  const slideWidth = (viewportWidth - totalGapWidth) / slidesPerView;
15788
- const offsetSlides = this.trackIndex() - this.windowBase() + this.buffer();
15827
+ const offsetSlides = this.renderedActiveIndex();
15789
15828
  const translateX = -offsetSlides * (slideWidth + gap);
15790
15829
  return {
15791
15830
  gap: `${gap}px`,
@@ -15795,6 +15834,16 @@ class CarouselContentComponent {
15795
15834
  : "none",
15796
15835
  };
15797
15836
  }, ...(ngDevMode ? [{ debugName: "trackStyle" }] : []));
15837
+ constructor() {
15838
+ // Re-clamp without animation when bounded mode starts or its limit changes.
15839
+ // Don't track the current position: normal navigation must not rerun this effect.
15840
+ effect(() => {
15841
+ if (!this.loop()) {
15842
+ const max = this.maxIndex();
15843
+ untracked(() => this.clampIntoRange(max));
15844
+ }
15845
+ });
15846
+ }
15798
15847
  locked = false;
15799
15848
  dragging = false;
15800
15849
  pendingFocus = false;
@@ -15831,9 +15880,7 @@ class CarouselContentComponent {
15831
15880
  }
15832
15881
  const deltaSlides = delta / cellWidth;
15833
15882
  this.scrollDelta += deltaSlides;
15834
- const maxDelta = this.buffer() * 0.9;
15835
- const min = this.windowBase() - maxDelta;
15836
- const max = this.windowBase() + maxDelta;
15883
+ const { min, max } = this.dragBounds(this.windowBase());
15837
15884
  const unclamped = this.trackIndex() + deltaSlides;
15838
15885
  const clamped = Math.min(Math.max(unclamped, min), max);
15839
15886
  const wasClamped = clamped !== unclamped;
@@ -15842,17 +15889,20 @@ class CarouselContentComponent {
15842
15889
  clearTimeout(this.wheelTimeout);
15843
15890
  this.wheelTimeout = setTimeout(() => {
15844
15891
  this.animate.set(true);
15892
+ // Recalculate bounds: the viewport or slide count may have changed before snapping.
15893
+ const { min, max } = this.dragBounds(this.windowBase());
15845
15894
  const direction = Math.sign(this.scrollDelta);
15846
15895
  const current = this.trackIndex();
15847
- let snapIndex = Math.round(current);
15896
+ let snapIndex = this.snap(current);
15848
15897
  if (Math.abs(this.scrollDelta) > 0.3) {
15849
15898
  snapIndex = direction > 0 ? Math.ceil(current) : Math.floor(current);
15850
15899
  }
15900
+ // If scrolling hit a limit, snap inward when looping or to the exact bound otherwise.
15851
15901
  if (wasClamped) {
15852
15902
  if (current <= min)
15853
- snapIndex = Math.ceil(min);
15903
+ snapIndex = this.loop() ? Math.ceil(min) : min;
15854
15904
  if (current >= max)
15855
- snapIndex = Math.floor(max);
15905
+ snapIndex = this.loop() ? Math.floor(max) : max;
15856
15906
  }
15857
15907
  const finalIndex = Math.min(Math.max(snapIndex, min), max);
15858
15908
  this.trackIndex.set(finalIndex);
@@ -15893,7 +15943,9 @@ class CarouselContentComponent {
15893
15943
  this.animate.set(false);
15894
15944
  this.startX = ev.clientX;
15895
15945
  this.startIndex = this.trackIndex();
15896
- this.windowBase.set(Math.floor(this.startIndex));
15946
+ if (this.loop()) {
15947
+ this.windowBase.set(Math.floor(this.startIndex));
15948
+ }
15897
15949
  }
15898
15950
  onPointerMove(ev) {
15899
15951
  if (!this.dragging) {
@@ -15909,9 +15961,7 @@ class CarouselContentComponent {
15909
15961
  }
15910
15962
  const deltaSlides = dx / cellWidth;
15911
15963
  const targetIndex = this.startIndex - deltaSlides;
15912
- const maxDelta = this.buffer() * 0.9;
15913
- const min = this.windowBase() - maxDelta;
15914
- const max = this.windowBase() + maxDelta;
15964
+ const { min, max } = this.dragBounds(Math.floor(this.startIndex));
15915
15965
  const clamped = Math.min(Math.max(targetIndex, min), max);
15916
15966
  this.trackIndex.set(clamped);
15917
15967
  }
@@ -15921,13 +15971,14 @@ class CarouselContentComponent {
15921
15971
  }
15922
15972
  this.dragging = false;
15923
15973
  this.animate.set(true);
15924
- this.trackIndex.set(Math.round(this.trackIndex()));
15974
+ this.trackIndex.set(this.snap(this.trackIndex()));
15925
15975
  }
15926
15976
  ngAfterViewInit() {
15927
15977
  const viewport = this.host.nativeElement;
15928
15978
  this.viewportWidth.set(viewport.clientWidth);
15929
- this.ro = new ResizeObserver(() => {
15930
- this.viewportWidth.set(viewport.clientWidth);
15979
+ // Use the fractional width to keep track translation aligned with CSS-sized slides.
15980
+ this.ro = new ResizeObserver(([entry]) => {
15981
+ this.viewportWidth.set(entry.contentRect.width);
15931
15982
  });
15932
15983
  this.ro.observe(viewport);
15933
15984
  }
@@ -15935,20 +15986,21 @@ class CarouselContentComponent {
15935
15986
  this.ro?.disconnect();
15936
15987
  }
15937
15988
  next() {
15938
- if (!this.slides().length || this.locked) {
15989
+ if (!this.slides().length || this.locked || !this.canNext()) {
15939
15990
  return;
15940
15991
  }
15941
15992
  this.animate.set(true);
15942
- this.trackIndex.update((i) => i + 1);
15993
+ // Move to the next whole position, clamping to a fractional final position.
15994
+ this.trackIndex.update((i) => this.clampIndex(Math.floor(i + EPSILON) + 1));
15943
15995
  this.lockNavigation();
15944
15996
  this.announceSlideChange();
15945
15997
  }
15946
15998
  prev() {
15947
- if (!this.slides().length || this.locked) {
15999
+ if (!this.slides().length || this.locked || !this.canPrev()) {
15948
16000
  return;
15949
16001
  }
15950
16002
  this.animate.set(true);
15951
- this.trackIndex.update((i) => i - 1);
16003
+ this.trackIndex.update((i) => this.clampIndex(Math.ceil(i - EPSILON) - 1));
15952
16004
  this.lockNavigation();
15953
16005
  this.announceSlideChange();
15954
16006
  }
@@ -15957,11 +16009,16 @@ class CarouselContentComponent {
15957
16009
  if (!slidesCount || this.locked) {
15958
16010
  return;
15959
16011
  }
15960
- const current = this.slideIndex();
15961
- const normalized = ((index % slidesCount) + slidesCount) % slidesCount;
15962
- const delta = normalized - current;
15963
16012
  this.animate.set(true);
15964
- this.trackIndex.update((i) => i + delta);
16013
+ if (this.loop()) {
16014
+ const current = this.slideIndex();
16015
+ const normalized = ((index % slidesCount) + slidesCount) % slidesCount;
16016
+ const delta = normalized - current;
16017
+ this.trackIndex.update((i) => i + delta);
16018
+ }
16019
+ else {
16020
+ this.trackIndex.set(this.clampIndex(index));
16021
+ }
15965
16022
  if (options?.focusSlide) {
15966
16023
  // Focus after transition completes so DOM positions are stable
15967
16024
  this.pendingFocus = true;
@@ -15976,7 +16033,8 @@ class CarouselContentComponent {
15976
16033
  */
15977
16034
  focusActiveSlide() {
15978
16035
  setTimeout(() => {
15979
- const activeIndex = this.renderedActiveIndex();
16036
+ // A bounded track can rest at a fractional index; focus the first fully visible slide.
16037
+ const activeIndex = Math.ceil(this.renderedActiveIndex() - EPSILON);
15980
16038
  const slideElement = this.slideElements()[activeIndex];
15981
16039
  if (slideElement) {
15982
16040
  slideElement.nativeElement.focus({ preventScroll: true });
@@ -15996,14 +16054,42 @@ class CarouselContentComponent {
15996
16054
  this.focusActiveSlide();
15997
16055
  }
15998
16056
  }
16057
+ clampIntoRange(max) {
16058
+ const current = this.trackIndex();
16059
+ const clamped = Math.min(Math.max(current, 0), max);
16060
+ if (clamped !== current) {
16061
+ this.animate.set(false);
16062
+ this.trackIndex.set(clamped);
16063
+ this.windowBase.set(Math.floor(clamped));
16064
+ }
16065
+ }
16066
+ clampIndex(value) {
16067
+ return this.loop() ? value : Math.min(Math.max(value, 0), this.maxIndex());
16068
+ }
16069
+ /** Snap to the nearest reachable position, including a fractional end. */
16070
+ snap(value) {
16071
+ if (this.loop()) {
16072
+ return Math.round(value);
16073
+ }
16074
+ const below = this.clampIndex(Math.floor(value));
16075
+ const above = this.clampIndex(Math.ceil(value));
16076
+ return value - below <= above - value ? below : above;
16077
+ }
16078
+ /**
16079
+ * Range the track may be dragged or wheeled within. A looping track stays inside
16080
+ * its rendered duplicate buffer around `base`; a bounded one stops at the ends.
16081
+ */
16082
+ dragBounds(base) {
16083
+ if (!this.loop()) {
16084
+ return { min: 0, max: this.maxIndex() };
16085
+ }
16086
+ const maxDelta = this.buffer() * 0.9;
16087
+ return { min: base - maxDelta, max: base + maxDelta };
16088
+ }
15999
16089
  lockNavigation() {
16000
16090
  this.locked = true;
16001
16091
  setTimeout(() => (this.locked = false), this.transitionMs());
16002
16092
  }
16003
- /**
16004
- * Announces the current slide position to screen readers via LiveAnnouncer.
16005
- * Called after navigation to inform users of the slide change.
16006
- */
16007
16093
  announceSlideChange() {
16008
16094
  setTimeout(() => {
16009
16095
  const slideNumber = this.slideIndex() + 1;
@@ -16013,7 +16099,7 @@ class CarouselContentComponent {
16013
16099
  }, 100);
16014
16100
  }
16015
16101
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CarouselContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16016
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: CarouselContentComponent, isStandalone: true, selector: "tedi-carousel-content", inputs: { slidesPerView: { classPropertyName: "slidesPerView", publicName: "slidesPerView", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, fade: { classPropertyName: "fade", publicName: "fade", isSignal: true, isRequired: false, transformFunction: null }, transitionMs: { classPropertyName: "transitionMs", publicName: "transitionMs", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "tabindex": "0", "role": "region", "aria-roledescription": "carousel", "aria-live": "off" }, listeners: { "scroll": "onScroll()", "wheel": "onWheel($event)", "keydown": "onKeyDown($event)", "pointerdown": "onPointerDown($event)", "pointermove": "onPointerMove($event)", "pointerup": "onPointerUp()", "pointercancel": "onPointerUp()", "lostpointercapture": "onPointerUp()" }, properties: { "attr.aria-label": "resolvedAriaLabel()", "class": "classes()" } }, queries: [{ propertyName: "slides", predicate: CarouselSlideDirective, isSignal: true }], viewQueries: [{ propertyName: "track", first: true, predicate: ["track"], descendants: true, isSignal: true }, { propertyName: "slideElements", predicate: ["slide"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #track\n class=\"tedi-carousel__track\"\n [style]=\"trackStyle()\"\n (transitionend)=\"onTransitionEnd($event)\"\n>\n @for (idx of renderedIndices(); track $index) {\n <div\n #slide\n class=\"tedi-carousel__slide\"\n [attr.role]=\"isSlideVisible($index) ? 'group' : 'presentation'\"\n aria-roledescription=\"slide\"\n [attr.aria-label]=\"\n translationService.track('carousel.slide', idx + 1, slides().length)()\n \"\n [attr.aria-current]=\"$index === renderedActiveIndex() ? 'true' : null\"\n [attr.aria-hidden]=\"isSlideVisible($index) ? null : 'true'\"\n [attr.tabindex]=\"isSlideVisible($index) ? '-1' : null\"\n [style.flex]=\"slideFlex()\"\n >\n <ng-container *ngTemplateOutlet=\"slides()[idx].template\"></ng-container>\n </div>\n }\n</div>\n", styles: [".tedi-carousel__content{position:relative;width:100%;overflow:hidden;overscroll-behavior:contain;touch-action:pan-y;cursor:grab}.tedi-carousel__content:focus-visible{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--tedi-borders-03))}.tedi-carousel__content:active{cursor:grabbing}.tedi-carousel__content--fade-right{-webkit-mask-image:linear-gradient(to right,black 90%,transparent 100%);mask-image:linear-gradient(to right,black 90%,transparent 100%)}.tedi-carousel__content--fade-x{-webkit-mask-image:linear-gradient(to right,black 85%,transparent 100%),linear-gradient(to left,black 85%,transparent 100%);mask-image:linear-gradient(to right,black 85%,transparent 100%),linear-gradient(to left,black 85%,transparent 100%);-webkit-mask-composite:source-in;mask-composite:intersect}.tedi-carousel__track{display:flex;will-change:transform}.tedi-carousel__slide{-webkit-user-select:none;user-select:none;scroll-snap-align:none;scroll-margin:0;-webkit-user-drag:none}.tedi-carousel__slide:focus{outline:none}.tedi-carousel__slide:focus-visible{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--tedi-borders-03))}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16102
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: CarouselContentComponent, isStandalone: true, selector: "tedi-carousel-content", inputs: { slidesPerView: { classPropertyName: "slidesPerView", publicName: "slidesPerView", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, fade: { classPropertyName: "fade", publicName: "fade", isSignal: true, isRequired: false, transformFunction: null }, transitionMs: { classPropertyName: "transitionMs", publicName: "transitionMs", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "tabindex": "0", "role": "region", "aria-roledescription": "carousel", "aria-live": "off" }, listeners: { "scroll": "onScroll()", "wheel": "onWheel($event)", "keydown": "onKeyDown($event)", "pointerdown": "onPointerDown($event)", "pointermove": "onPointerMove($event)", "pointerup": "onPointerUp()", "pointercancel": "onPointerUp()", "lostpointercapture": "onPointerUp()" }, properties: { "attr.aria-label": "resolvedAriaLabel()", "class": "classes()" } }, queries: [{ propertyName: "slides", predicate: CarouselSlideDirective, isSignal: true }], viewQueries: [{ propertyName: "track", first: true, predicate: ["track"], descendants: true, isSignal: true }, { propertyName: "slideElements", predicate: ["slide"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #track\n class=\"tedi-carousel__track\"\n [style]=\"trackStyle()\"\n (transitionend)=\"onTransitionEnd($event)\"\n>\n @for (idx of renderedIndices(); track $index) {\n <div\n #slide\n class=\"tedi-carousel__slide\"\n [attr.role]=\"isSlideVisible($index) ? 'group' : 'presentation'\"\n aria-roledescription=\"slide\"\n [attr.aria-label]=\"\n translationService.track('carousel.slide', idx + 1, slides().length)()\n \"\n [attr.aria-current]=\"$index === renderedActiveIndex() ? 'true' : null\"\n [attr.aria-hidden]=\"isSlideVisible($index) ? null : 'true'\"\n [attr.tabindex]=\"isSlideVisible($index) ? '-1' : null\"\n [style.flex]=\"slideFlex()\"\n >\n <ng-container *ngTemplateOutlet=\"slides()[idx].template\"></ng-container>\n </div>\n }\n</div>\n", styles: [".tedi-carousel__content{position:relative;width:100%;overflow:hidden;overscroll-behavior:contain;touch-action:pan-y;cursor:grab}.tedi-carousel__content:focus-visible{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--tedi-borders-03))}.tedi-carousel__content:active{cursor:grabbing}.tedi-carousel__content--fade-right{-webkit-mask-image:linear-gradient(to right,black 90%,transparent 100%);mask-image:linear-gradient(to right,black 90%,transparent 100%)}.tedi-carousel__content--fade-x{-webkit-mask-image:linear-gradient(to right,black 85%,transparent 100%),linear-gradient(to left,black 85%,transparent 100%);mask-image:linear-gradient(to right,black 85%,transparent 100%),linear-gradient(to left,black 85%,transparent 100%);-webkit-mask-composite:source-in;mask-composite:intersect}.tedi-carousel__track{display:flex;will-change:transform}.tedi-carousel__slide{-webkit-user-select:none;user-select:none;scroll-snap-align:none;scroll-margin:0;-webkit-user-drag:none}.tedi-carousel__slide:focus{outline:none}.tedi-carousel__slide:focus-visible{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--tedi-borders-03))}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16017
16103
  }
16018
16104
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CarouselContentComponent, decorators: [{
16019
16105
  type: Component,
@@ -16025,7 +16111,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
16025
16111
  "aria-live": "off",
16026
16112
  "[class]": "classes()",
16027
16113
  }, template: "<div\n #track\n class=\"tedi-carousel__track\"\n [style]=\"trackStyle()\"\n (transitionend)=\"onTransitionEnd($event)\"\n>\n @for (idx of renderedIndices(); track $index) {\n <div\n #slide\n class=\"tedi-carousel__slide\"\n [attr.role]=\"isSlideVisible($index) ? 'group' : 'presentation'\"\n aria-roledescription=\"slide\"\n [attr.aria-label]=\"\n translationService.track('carousel.slide', idx + 1, slides().length)()\n \"\n [attr.aria-current]=\"$index === renderedActiveIndex() ? 'true' : null\"\n [attr.aria-hidden]=\"isSlideVisible($index) ? null : 'true'\"\n [attr.tabindex]=\"isSlideVisible($index) ? '-1' : null\"\n [style.flex]=\"slideFlex()\"\n >\n <ng-container *ngTemplateOutlet=\"slides()[idx].template\"></ng-container>\n </div>\n }\n</div>\n", styles: [".tedi-carousel__content{position:relative;width:100%;overflow:hidden;overscroll-behavior:contain;touch-action:pan-y;cursor:grab}.tedi-carousel__content:focus-visible{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--tedi-borders-03))}.tedi-carousel__content:active{cursor:grabbing}.tedi-carousel__content--fade-right{-webkit-mask-image:linear-gradient(to right,black 90%,transparent 100%);mask-image:linear-gradient(to right,black 90%,transparent 100%)}.tedi-carousel__content--fade-x{-webkit-mask-image:linear-gradient(to right,black 85%,transparent 100%),linear-gradient(to left,black 85%,transparent 100%);mask-image:linear-gradient(to right,black 85%,transparent 100%),linear-gradient(to left,black 85%,transparent 100%);-webkit-mask-composite:source-in;mask-composite:intersect}.tedi-carousel__track{display:flex;will-change:transform}.tedi-carousel__slide{-webkit-user-select:none;user-select:none;scroll-snap-align:none;scroll-margin:0;-webkit-user-drag:none}.tedi-carousel__slide:focus{outline:none}.tedi-carousel__slide:focus-visible{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--tedi-borders-03))}\n"] }]
16028
- }], propDecorators: { slidesPerView: [{ type: i0.Input, args: [{ isSignal: true, alias: "slidesPerView", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], fade: [{ type: i0.Input, args: [{ isSignal: true, alias: "fade", required: false }] }], transitionMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "transitionMs", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], track: [{ type: i0.ViewChild, args: ["track", { isSignal: true }] }], slideElements: [{ type: i0.ViewChildren, args: ["slide", { isSignal: true }] }], slides: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CarouselSlideDirective), { isSignal: true }] }], onScroll: [{
16114
+ }], ctorParameters: () => [], propDecorators: { slidesPerView: [{ type: i0.Input, args: [{ isSignal: true, alias: "slidesPerView", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], fade: [{ type: i0.Input, args: [{ isSignal: true, alias: "fade", required: false }] }], transitionMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "transitionMs", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], track: [{ type: i0.ViewChild, args: ["track", { isSignal: true }] }], slideElements: [{ type: i0.ViewChildren, args: ["slide", { isSignal: true }] }], slides: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CarouselSlideDirective), { isSignal: true }] }], onScroll: [{
16029
16115
  type: HostListener,
16030
16116
  args: ["scroll"]
16031
16117
  }], onWheel: [{
@@ -16054,11 +16140,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
16054
16140
  class CarouselComponent {
16055
16141
  carouselContent = contentChild.required(CarouselContentComponent);
16056
16142
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CarouselComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16057
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.24", type: CarouselComponent, isStandalone: true, selector: "tedi-carousel", queries: [{ propertyName: "carouselContent", first: true, predicate: CarouselContentComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-content select=\"tedi-carousel-header\" />\n<ng-content select=\"tedi-carousel-content\" />\n<ng-content select=\"tedi-carousel-footer\" />\n", styles: ["tedi-carousel{display:flex;flex-direction:column;gap:var(--layout-grid-gutters-08)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16143
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.24", type: CarouselComponent, isStandalone: true, selector: "tedi-carousel", queries: [{ propertyName: "carouselContent", first: true, predicate: CarouselContentComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-content select=\"tedi-carousel-header\" />\n<div class=\"tedi-carousel__body\">\n <ng-content select=\"tedi-carousel-content\" />\n <ng-content select=\"tedi-carousel-navigation\" />\n</div>\n<ng-content select=\"tedi-carousel-footer\" />\n", styles: ["tedi-carousel{display:flex;flex-direction:column;gap:var(--layout-grid-gutters-08)}.tedi-carousel__body{position:relative;display:flex;flex-direction:column}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16058
16144
  }
16059
16145
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CarouselComponent, decorators: [{
16060
16146
  type: Component,
16061
- args: [{ standalone: true, selector: "tedi-carousel", encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content select=\"tedi-carousel-header\" />\n<ng-content select=\"tedi-carousel-content\" />\n<ng-content select=\"tedi-carousel-footer\" />\n", styles: ["tedi-carousel{display:flex;flex-direction:column;gap:var(--layout-grid-gutters-08)}\n"] }]
16147
+ args: [{ standalone: true, selector: "tedi-carousel", encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content select=\"tedi-carousel-header\" />\n<div class=\"tedi-carousel__body\">\n <ng-content select=\"tedi-carousel-content\" />\n <ng-content select=\"tedi-carousel-navigation\" />\n</div>\n<ng-content select=\"tedi-carousel-footer\" />\n", styles: ["tedi-carousel{display:flex;flex-direction:column;gap:var(--layout-grid-gutters-08)}.tedi-carousel__body{position:relative;display:flex;flex-direction:column}\n"] }]
16062
16148
  }], propDecorators: { carouselContent: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CarouselContentComponent), { isSignal: true }] }] } });
16063
16149
 
16064
16150
  class CarouselFooterComponent {
@@ -16086,11 +16172,11 @@ class CarouselIndicatorsComponent {
16086
16172
  variant = input("dots", ...(ngDevMode ? [{ debugName: "variant" }] : []));
16087
16173
  translationService = inject(TediTranslationService);
16088
16174
  carousel = inject(CarouselComponent);
16089
- indicatorsArray = computed(() => Array.from({ length: this.carousel.carouselContent().slides().length }, (_, i) => ({
16175
+ indicatorsArray = computed(() => Array.from({ length: this.carousel.carouselContent().positionCount() }, (_, i) => ({
16090
16176
  index: i,
16091
- active: this.carousel.carouselContent().slideIndex() === i,
16177
+ active: this.carousel.carouselContent().activePosition() === i,
16092
16178
  })), ...(ngDevMode ? [{ debugName: "indicatorsArray" }] : []));
16093
- activeSlideNumber = computed(() => this.carousel.carouselContent().slideIndex() + 1, ...(ngDevMode ? [{ debugName: "activeSlideNumber" }] : []));
16179
+ activeSlideNumber = computed(() => this.carousel.carouselContent().activePosition() + 1, ...(ngDevMode ? [{ debugName: "activeSlideNumber" }] : []));
16094
16180
  handleNext() {
16095
16181
  this.carousel.carouselContent().next();
16096
16182
  }
@@ -16101,16 +16187,24 @@ class CarouselIndicatorsComponent {
16101
16187
  this.carousel.carouselContent().goToIndex(index, { focusSlide: true });
16102
16188
  }
16103
16189
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CarouselIndicatorsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16104
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: CarouselIndicatorsComponent, isStandalone: true, selector: "tedi-carousel-indicators", inputs: { withArrows: { classPropertyName: "withArrows", publicName: "withArrows", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n (click)=\"handlePrev()\"\n >\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n </button>\n}\n\n@if (variant() === \"dots\") {\n @for (indicator of indicatorsArray(); track indicator.index) {\n <button\n type=\"button\"\n class=\"tedi-carousel__indicator\"\n [attr.aria-label]=\"\n translationService.track('carousel.showSlide', indicator.index + 1)()\n \"\n [ngClass]=\"indicator.active ? 'tedi-carousel__indicator--active' : null\"\n (click)=\"handleIndicatorClick(indicator.index)\"\n ></button>\n }\n} @else if (activeSlideNumber()) {\n <div>\n <b tedi-text color=\"brand\">{{ activeSlideNumber() }}</b>\n <span tedi-text color=\"tertiary\"> / {{ indicatorsArray().length }}</span>\n </div>\n}\n\n@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n (click)=\"handleNext()\"\n >\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n </button>\n}\n", styles: ["tedi-carousel-indicators{display:flex;gap:var(--layout-grid-gutters-04);align-items:center;min-height:24px}.tedi-carousel__indicator{position:relative;width:24px;height:24px;cursor:pointer;background:none;border:none}.tedi-carousel__indicator:after{position:absolute;top:50%;left:50%;width:22px;height:8px;content:\"\";background-color:transparent;border:1px solid var(--tedi-primary-600);border-radius:100px;transform:translate(-50%,-50%)}.tedi-carousel__indicator:hover:after{border-color:var(--tedi-primary-700)}.tedi-carousel__indicator:active:after{background-color:var(--tedi-primary-800);border-color:var(--tedi-primary-800)}.tedi-carousel__indicator:focus-visible:after{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:var(--tedi-borders-01)}.tedi-carousel__indicator--active:after{background-color:var(--tedi-primary-600)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ButtonComponent, selector: "[tedi-button]", inputs: ["variant", "size"] }, { kind: "component", type: IconComponent, selector: "tedi-icon", inputs: ["name", "size", "color", "background", "variant", "type", "label"] }, { kind: "component", type: TextComponent, selector: "[tedi-text]", inputs: ["modifiers", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16190
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: CarouselIndicatorsComponent, isStandalone: true, selector: "tedi-carousel-indicators", inputs: { withArrows: { classPropertyName: "withArrows", publicName: "withArrows", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n [disabled]=\"!carousel.carouselContent().canPrev()\"\n (click)=\"handlePrev()\"\n >\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n </button>\n}\n\n@if (variant() === \"dots\") {\n @for (indicator of indicatorsArray(); track indicator.index) {\n <button\n type=\"button\"\n class=\"tedi-carousel__indicator\"\n [attr.aria-label]=\"\n translationService.track('carousel.showSlide', indicator.index + 1)()\n \"\n [ngClass]=\"indicator.active ? 'tedi-carousel__indicator--active' : null\"\n (click)=\"handleIndicatorClick(indicator.index)\"\n ></button>\n }\n} @else if (indicatorsArray().length) {\n <div>\n <b tedi-text color=\"brand\">{{ activeSlideNumber() }}</b>\n <span tedi-text color=\"tertiary\"> / {{ indicatorsArray().length }}</span>\n </div>\n}\n\n@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n [disabled]=\"!carousel.carouselContent().canNext()\"\n (click)=\"handleNext()\"\n >\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n </button>\n}\n", styles: ["tedi-carousel-indicators{display:flex;gap:var(--layout-grid-gutters-04);align-items:center;min-height:24px}.tedi-carousel__indicator{position:relative;width:24px;height:24px;cursor:pointer;background:none;border:none}.tedi-carousel__indicator:after{position:absolute;top:50%;left:50%;width:22px;height:8px;content:\"\";background-color:transparent;border:1px solid var(--tedi-primary-600);border-radius:100px;transform:translate(-50%,-50%)}.tedi-carousel__indicator:hover:after{border-color:var(--tedi-primary-700)}.tedi-carousel__indicator:active:after{background-color:var(--tedi-primary-800);border-color:var(--tedi-primary-800)}.tedi-carousel__indicator:focus-visible:after{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:var(--tedi-borders-01)}.tedi-carousel__indicator--active:after{background-color:var(--tedi-primary-600)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ButtonComponent, selector: "[tedi-button]", inputs: ["variant", "size"] }, { kind: "component", type: IconComponent, selector: "tedi-icon", inputs: ["name", "size", "color", "background", "variant", "type", "label"] }, { kind: "component", type: TextComponent, selector: "[tedi-text]", inputs: ["modifiers", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16105
16191
  }
16106
16192
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CarouselIndicatorsComponent, decorators: [{
16107
16193
  type: Component,
16108
- args: [{ standalone: true, selector: "tedi-carousel-indicators", changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [NgClass, ButtonComponent, IconComponent, TextComponent], template: "@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n (click)=\"handlePrev()\"\n >\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n </button>\n}\n\n@if (variant() === \"dots\") {\n @for (indicator of indicatorsArray(); track indicator.index) {\n <button\n type=\"button\"\n class=\"tedi-carousel__indicator\"\n [attr.aria-label]=\"\n translationService.track('carousel.showSlide', indicator.index + 1)()\n \"\n [ngClass]=\"indicator.active ? 'tedi-carousel__indicator--active' : null\"\n (click)=\"handleIndicatorClick(indicator.index)\"\n ></button>\n }\n} @else if (activeSlideNumber()) {\n <div>\n <b tedi-text color=\"brand\">{{ activeSlideNumber() }}</b>\n <span tedi-text color=\"tertiary\"> / {{ indicatorsArray().length }}</span>\n </div>\n}\n\n@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n (click)=\"handleNext()\"\n >\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n </button>\n}\n", styles: ["tedi-carousel-indicators{display:flex;gap:var(--layout-grid-gutters-04);align-items:center;min-height:24px}.tedi-carousel__indicator{position:relative;width:24px;height:24px;cursor:pointer;background:none;border:none}.tedi-carousel__indicator:after{position:absolute;top:50%;left:50%;width:22px;height:8px;content:\"\";background-color:transparent;border:1px solid var(--tedi-primary-600);border-radius:100px;transform:translate(-50%,-50%)}.tedi-carousel__indicator:hover:after{border-color:var(--tedi-primary-700)}.tedi-carousel__indicator:active:after{background-color:var(--tedi-primary-800);border-color:var(--tedi-primary-800)}.tedi-carousel__indicator:focus-visible:after{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:var(--tedi-borders-01)}.tedi-carousel__indicator--active:after{background-color:var(--tedi-primary-600)}\n"] }]
16194
+ args: [{ standalone: true, selector: "tedi-carousel-indicators", changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [NgClass, ButtonComponent, IconComponent, TextComponent], template: "@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n [disabled]=\"!carousel.carouselContent().canPrev()\"\n (click)=\"handlePrev()\"\n >\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n </button>\n}\n\n@if (variant() === \"dots\") {\n @for (indicator of indicatorsArray(); track indicator.index) {\n <button\n type=\"button\"\n class=\"tedi-carousel__indicator\"\n [attr.aria-label]=\"\n translationService.track('carousel.showSlide', indicator.index + 1)()\n \"\n [ngClass]=\"indicator.active ? 'tedi-carousel__indicator--active' : null\"\n (click)=\"handleIndicatorClick(indicator.index)\"\n ></button>\n }\n} @else if (indicatorsArray().length) {\n <div>\n <b tedi-text color=\"brand\">{{ activeSlideNumber() }}</b>\n <span tedi-text color=\"tertiary\"> / {{ indicatorsArray().length }}</span>\n </div>\n}\n\n@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n [disabled]=\"!carousel.carouselContent().canNext()\"\n (click)=\"handleNext()\"\n >\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n </button>\n}\n", styles: ["tedi-carousel-indicators{display:flex;gap:var(--layout-grid-gutters-04);align-items:center;min-height:24px}.tedi-carousel__indicator{position:relative;width:24px;height:24px;cursor:pointer;background:none;border:none}.tedi-carousel__indicator:after{position:absolute;top:50%;left:50%;width:22px;height:8px;content:\"\";background-color:transparent;border:1px solid var(--tedi-primary-600);border-radius:100px;transform:translate(-50%,-50%)}.tedi-carousel__indicator:hover:after{border-color:var(--tedi-primary-700)}.tedi-carousel__indicator:active:after{background-color:var(--tedi-primary-800);border-color:var(--tedi-primary-800)}.tedi-carousel__indicator:focus-visible:after{outline:var(--tedi-borders-02) solid var(--tedi-primary-500);outline-offset:var(--tedi-borders-01)}.tedi-carousel__indicator--active:after{background-color:var(--tedi-primary-600)}\n"] }]
16109
16195
  }], propDecorators: { withArrows: [{ type: i0.Input, args: [{ isSignal: true, alias: "withArrows", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
16110
16196
 
16111
16197
  class CarouselNavigationComponent {
16198
+ /**
16199
+ * Shows floating navigation buttons over the slides. Place navigation directly
16200
+ * inside `tedi-carousel`, outside the header and footer.
16201
+ * @default false
16202
+ */
16203
+ overlay = input(false, ...(ngDevMode ? [{ debugName: "overlay", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
16112
16204
  translationService = inject(TediTranslationService);
16113
16205
  carousel = inject(CarouselComponent);
16206
+ canPrev = computed(() => this.carousel.carouselContent().canPrev(), ...(ngDevMode ? [{ debugName: "canPrev" }] : []));
16207
+ canNext = computed(() => this.carousel.carouselContent().canNext(), ...(ngDevMode ? [{ debugName: "canNext" }] : []));
16114
16208
  handleNext() {
16115
16209
  this.carousel.carouselContent().next();
16116
16210
  }
@@ -16118,12 +16212,14 @@ class CarouselNavigationComponent {
16118
16212
  this.carousel.carouselContent().prev();
16119
16213
  }
16120
16214
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CarouselNavigationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16121
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.24", type: CarouselNavigationComponent, isStandalone: true, selector: "tedi-carousel-navigation", ngImport: i0, template: "<button\n tedi-button\n type=\"button\"\n variant=\"secondary\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n (click)=\"handlePrev()\"\n>\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n</button>\n<button\n tedi-button\n type=\"button\"\n variant=\"secondary\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n (click)=\"handleNext()\"\n>\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n</button>\n", styles: ["tedi-carousel-navigation{display:flex;gap:var(--layout-grid-gutters-08);align-items:center}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "[tedi-button]", inputs: ["variant", "size"] }, { kind: "component", type: IconComponent, selector: "tedi-icon", inputs: ["name", "size", "color", "background", "variant", "type", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16215
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: CarouselNavigationComponent, isStandalone: true, selector: "tedi-carousel-navigation", inputs: { overlay: { classPropertyName: "overlay", publicName: "overlay", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.tedi-carousel-navigation--overlay": "overlay()" } }, ngImport: i0, template: "@if (overlay()) {\n <button\n tedi-floating-button\n type=\"button\"\n variant=\"secondary\"\n position=\"static\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n [disabled]=\"!canPrev()\"\n (click)=\"handlePrev()\"\n >\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n </button>\n <button\n tedi-floating-button\n type=\"button\"\n variant=\"secondary\"\n position=\"static\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n [disabled]=\"!canNext()\"\n (click)=\"handleNext()\"\n >\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n </button>\n} @else {\n <button\n tedi-button\n type=\"button\"\n variant=\"secondary\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n [disabled]=\"!canPrev()\"\n (click)=\"handlePrev()\"\n >\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n </button>\n <button\n tedi-button\n type=\"button\"\n variant=\"secondary\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n [disabled]=\"!canNext()\"\n (click)=\"handleNext()\"\n >\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n </button>\n}\n", styles: ["tedi-carousel-navigation{display:flex;gap:var(--layout-grid-gutters-08);align-items:center}tedi-carousel-navigation.tedi-carousel-navigation--overlay{position:absolute;inset:0;z-index:1;box-sizing:border-box;justify-content:space-between;padding:var(--layout-grid-gutters-08);pointer-events:none}tedi-carousel-navigation.tedi-carousel-navigation--overlay>*{pointer-events:auto}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "[tedi-button]", inputs: ["variant", "size"] }, { kind: "component", type: FloatingButtonComponent, selector: "[tedi-floating-button]", inputs: ["variant", "size", "axis", "position", "placement", "offset", "zIndex"] }, { kind: "component", type: IconComponent, selector: "tedi-icon", inputs: ["name", "size", "color", "background", "variant", "type", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16122
16216
  }
16123
16217
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CarouselNavigationComponent, decorators: [{
16124
16218
  type: Component,
16125
- args: [{ standalone: true, selector: "tedi-carousel-navigation", changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [ButtonComponent, IconComponent], template: "<button\n tedi-button\n type=\"button\"\n variant=\"secondary\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n (click)=\"handlePrev()\"\n>\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n</button>\n<button\n tedi-button\n type=\"button\"\n variant=\"secondary\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n (click)=\"handleNext()\"\n>\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n</button>\n", styles: ["tedi-carousel-navigation{display:flex;gap:var(--layout-grid-gutters-08);align-items:center}\n"] }]
16126
- }] });
16219
+ args: [{ standalone: true, selector: "tedi-carousel-navigation", changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [ButtonComponent, FloatingButtonComponent, IconComponent], host: {
16220
+ "[class.tedi-carousel-navigation--overlay]": "overlay()",
16221
+ }, template: "@if (overlay()) {\n <button\n tedi-floating-button\n type=\"button\"\n variant=\"secondary\"\n position=\"static\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n [disabled]=\"!canPrev()\"\n (click)=\"handlePrev()\"\n >\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n </button>\n <button\n tedi-floating-button\n type=\"button\"\n variant=\"secondary\"\n position=\"static\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n [disabled]=\"!canNext()\"\n (click)=\"handleNext()\"\n >\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n </button>\n} @else {\n <button\n tedi-button\n type=\"button\"\n variant=\"secondary\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n [disabled]=\"!canPrev()\"\n (click)=\"handlePrev()\"\n >\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n </button>\n <button\n tedi-button\n type=\"button\"\n variant=\"secondary\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n [disabled]=\"!canNext()\"\n (click)=\"handleNext()\"\n >\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n </button>\n}\n", styles: ["tedi-carousel-navigation{display:flex;gap:var(--layout-grid-gutters-08);align-items:center}tedi-carousel-navigation.tedi-carousel-navigation--overlay{position:absolute;inset:0;z-index:1;box-sizing:border-box;justify-content:space-between;padding:var(--layout-grid-gutters-08);pointer-events:none}tedi-carousel-navigation.tedi-carousel-navigation--overlay>*{pointer-events:auto}\n"] }]
16222
+ }], propDecorators: { overlay: [{ type: i0.Input, args: [{ isSignal: true, alias: "overlay", required: false }] }] } });
16127
16223
 
16128
16224
  const range = (start, end) => {
16129
16225
  if (end < start)