@ethlete/cdk 4.19.5 → 4.20.0

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.
@@ -57,7 +57,7 @@ export class NavTabsComponent extends PaginatedTabHeaderDirective {
57
57
  return this.tabOutlet ? 'tablist' : this._elementRef.nativeElement.getAttribute('role');
58
58
  }
59
59
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: NavTabsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
60
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.5", type: NavTabsComponent, isStandalone: true, selector: "[et-nav-tabs]", inputs: { tabOutlet: "tabOutlet" }, host: { properties: { "attr.role": "this._attrRole" }, classAttribute: "et-nav-tabs" }, queries: [{ propertyName: "_items", predicate: i0.forwardRef(() => NavTabLinkComponent), descendants: true }, { propertyName: "_inkBars", predicate: i0.forwardRef(() => ActiveTabUnderlineDirective), descendants: true }], viewQueries: [{ propertyName: "_scrollable", first: true, predicate: ScrollableComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<et-scrollable\n [itemSize]=\"itemSize\"\n [renderButtons]=\"renderButtons\"\n [scrollableClass]=\"scrollableClass\"\n [renderMasks]=\"renderMasks\"\n [renderScrollbars]=\"renderScrollbars\"\n (keydown)=\"_handleKeydown($event)\"\n (contentChanged)=\"_onContentChanges()\"\n>\n <ng-content />\n</et-scrollable>\n", dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
60
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.5", type: NavTabsComponent, isStandalone: true, selector: "[et-nav-tabs]", inputs: { tabOutlet: "tabOutlet" }, host: { properties: { "attr.role": "this._attrRole" }, classAttribute: "et-nav-tabs" }, queries: [{ propertyName: "_items", predicate: i0.forwardRef(() => NavTabLinkComponent), descendants: true }, { propertyName: "_inkBars", predicate: i0.forwardRef(() => ActiveTabUnderlineDirective), descendants: true }], viewQueries: [{ propertyName: "_scrollable", first: true, predicate: ScrollableComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<et-scrollable\n [itemSize]=\"itemSize\"\n [renderButtons]=\"renderButtons\"\n [scrollableClass]=\"scrollableClass\"\n [renderMasks]=\"renderMasks\"\n [renderScrollbars]=\"renderScrollbars\"\n (keydown)=\"_handleKeydown($event)\"\n (contentChanged)=\"_onContentChanges()\"\n>\n <ng-content />\n</et-scrollable>\n", dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "buttonPosition", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin", "scrollOrigin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
61
61
  }
62
62
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: NavTabsComponent, decorators: [{
63
63
  type: Component,
@@ -14,7 +14,7 @@ export class InlineTabHeaderComponent extends PaginatedTabHeaderDirective {
14
14
  event.preventDefault();
15
15
  }
16
16
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: InlineTabHeaderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
17
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.5", type: InlineTabHeaderComponent, isStandalone: true, selector: "et-inline-tab-header", host: { classAttribute: "et-inline-tab-header" }, queries: [{ propertyName: "_items", predicate: InlineTabLabelWrapperDirective }, { propertyName: "_inkBars", predicate: i0.forwardRef(() => ActiveTabUnderlineDirective), descendants: true }], viewQueries: [{ propertyName: "_scrollable", first: true, predicate: ScrollableComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<et-scrollable\n [itemSize]=\"itemSize\"\n [renderButtons]=\"renderButtons\"\n [scrollableClass]=\"scrollableClass\"\n [renderMasks]=\"renderMasks\"\n [renderScrollbars]=\"renderScrollbars\"\n (keydown)=\"_handleKeydown($event)\"\n (contentChanged)=\"_onContentChanges()\"\n>\n <ng-content />\n</et-scrollable>\n", dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
17
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.5", type: InlineTabHeaderComponent, isStandalone: true, selector: "et-inline-tab-header", host: { classAttribute: "et-inline-tab-header" }, queries: [{ propertyName: "_items", predicate: InlineTabLabelWrapperDirective }, { propertyName: "_inkBars", predicate: i0.forwardRef(() => ActiveTabUnderlineDirective), descendants: true }], viewQueries: [{ propertyName: "_scrollable", first: true, predicate: ScrollableComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<et-scrollable\n [itemSize]=\"itemSize\"\n [renderButtons]=\"renderButtons\"\n [scrollableClass]=\"scrollableClass\"\n [renderMasks]=\"renderMasks\"\n [renderScrollbars]=\"renderScrollbars\"\n (keydown)=\"_handleKeydown($event)\"\n (contentChanged)=\"_onContentChanges()\"\n>\n <ng-content />\n</et-scrollable>\n", dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "buttonPosition", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin", "scrollOrigin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
18
18
  }
19
19
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: InlineTabHeaderComponent, decorators: [{
20
20
  type: Component,
@@ -4,7 +4,7 @@ import { AsyncPipe, NgClass, NgTemplateOutlet, JsonPipe, NgComponentOutlet, DOCU
4
4
  import * as i0 from '@angular/core';
5
5
  import { Component, ViewEncapsulation, ChangeDetectionStrategy, InjectionToken, Directive, booleanAttribute, Input, ContentChild, ContentChildren, inject, ElementRef, Injector, HostBinding, input, numberAttribute, computed, signal, contentChildren, viewChild, isDevMode, Injectable, ChangeDetectorRef, TemplateRef, ViewContainerRef, ViewChild, forwardRef, EventEmitter, Output, ViewChildren, Optional, Inject, SkipSelf, HostListener, effect, NgZone, NgModule, isSignal, DestroyRef, contentChild, viewChildren, assertInInjectionContext, Attribute } from '@angular/core';
6
6
  import * as i1$1 from '@ethlete/core';
7
- import { LetDirective, createDestroy, Memo, signalHostAttributes, signalHostClasses, previousSignalValue, signalHostStyles, nextFrame, syncSignal, injectHostElement, ObserveVisibilityDirective, signalVisibilityChangeClasses, IS_EMAIL, MUST_MATCH, IS_ARRAY_NOT_EMPTY, AT_LEAST_ONE_REQUIRED, equal, switchQueryListChanges, signalAttributes, ResizeObserverService, createFlipAnimation, AnimatedOverlayDirective, RuntimeError, SelectionModel, ActiveSelectionModel, KeyPressManager, signalClasses, scrollToElement, isEmptyArray, isObjectArray, isPrimitiveArray, createComponentId, ClickOutsideDirective, ANIMATED_LIFECYCLE_TOKEN, AnimatedLifecycleDirective, ObserveContentDirective, clamp, DELAYABLE_TOKEN, ObserveResizeDirective, SmartBlockScrollStrategy, RouterStateService, signalElementScrollState, signalElementIntersection, signalElementChildren, signalHostElementDimensions, isElementVisible, getFirstAndLastPartialIntersection, CursorDragScrollDirective, ObserveScrollStateDirective, ClickObserverService, RootBoundaryDirective, elementCanScroll, cloneFormGroup, getFormGroupValue, fromNextFrame, ViewportService, ROOT_BOUNDARY_TOKEN, AnimatedIfDirective, FocusVisibleService, inferMimeType, ScrollObserverIgnoreTargetDirective, TypedQueryList } from '@ethlete/core';
7
+ import { LetDirective, createDestroy, Memo, signalHostAttributes, signalHostClasses, previousSignalValue, signalHostStyles, nextFrame, syncSignal, injectHostElement, ObserveVisibilityDirective, signalVisibilityChangeClasses, IS_EMAIL, MUST_MATCH, IS_ARRAY_NOT_EMPTY, AT_LEAST_ONE_REQUIRED, equal, switchQueryListChanges, signalAttributes, ResizeObserverService, createFlipAnimation, AnimatedOverlayDirective, RuntimeError, SelectionModel, ActiveSelectionModel, KeyPressManager, signalClasses, scrollToElement, isEmptyArray, isObjectArray, isPrimitiveArray, createComponentId, ClickOutsideDirective, ANIMATED_LIFECYCLE_TOKEN, AnimatedLifecycleDirective, ObserveContentDirective, clamp, DELAYABLE_TOKEN, ObserveResizeDirective, SmartBlockScrollStrategy, RouterStateService, signalElementDimensions, signalElementScrollState, signalElementIntersection, signalElementChildren, signalHostElementDimensions, isElementVisible, getIntersectionInfo, CursorDragScrollDirective, ObserveScrollStateDirective, ClickObserverService, RootBoundaryDirective, elementCanScroll, cloneFormGroup, getFormGroupValue, fromNextFrame, ViewportService, ROOT_BOUNDARY_TOKEN, AnimatedIfDirective, FocusVisibleService, inferMimeType, ScrollObserverIgnoreTargetDirective, TypedQueryList } from '@ethlete/core';
8
8
  import { BehaviorSubject, startWith, map, switchMap, combineLatest, pairwise, tap, takeUntil, skip, of, merge, timer, takeWhile, filter, fromEvent, Subject, Observable, debounceTime, withLatestFrom, distinctUntilChanged, take, skipUntil, skipWhile, catchError, throwError, defer, partition, from, finalize, Subscription } from 'rxjs';
9
9
  import { trigger, state, style, transition, animate } from '@angular/animations';
10
10
  import { __decorate, __metadata } from 'tslib';
@@ -8743,6 +8743,9 @@ class ScrollableComponent {
8743
8743
  set _renderButtons(v) {
8744
8744
  this.renderButtons.set(v);
8745
8745
  }
8746
+ set _buttonPosition(v) {
8747
+ this.buttonPosition.set(v);
8748
+ }
8746
8749
  set _renderScrollbars(v) {
8747
8750
  this.renderScrollbars.set(v);
8748
8751
  }
@@ -8764,6 +8767,9 @@ class ScrollableComponent {
8764
8767
  set _scrollMargin(v) {
8765
8768
  this.scrollMargin.set(v);
8766
8769
  }
8770
+ set _scrollOrigin(v) {
8771
+ this.scrollOrigin.set(v);
8772
+ }
8767
8773
  set _scrollable(e) {
8768
8774
  this.scrollable.set(e);
8769
8775
  }
@@ -8789,6 +8795,9 @@ class ScrollableComponent {
8789
8795
  this.renderNavigation = signal(false);
8790
8796
  this.renderMasks = signal(true);
8791
8797
  this.renderButtons = signal(true);
8798
+ this.renderButtonsInside = computed(() => this.buttonPosition() === 'inside' && this.renderButtons());
8799
+ this.renderButtonsInFooter = computed(() => this.buttonPosition() === 'footer' && this.renderButtons());
8800
+ this.buttonPosition = signal('inside');
8792
8801
  this.renderScrollbars = signal(false);
8793
8802
  this.stickyButtons = signal(false);
8794
8803
  this.cursorDragScroll = signal(true);
@@ -8796,6 +8805,7 @@ class ScrollableComponent {
8796
8805
  this.scrollMode = signal('container');
8797
8806
  this.snap = signal(false);
8798
8807
  this.scrollMargin = signal(0);
8808
+ this.scrollOrigin = signal('auto');
8799
8809
  this.scrollStateChange = new EventEmitter();
8800
8810
  this.intersectionChange = new EventEmitter();
8801
8811
  this.scrollable = signal(null);
@@ -8803,6 +8813,9 @@ class ScrollableComponent {
8803
8813
  this.firstElement = signal(null);
8804
8814
  this.lastElement = signal(null);
8805
8815
  this.activeElementList = signal(null);
8816
+ this.navigationDotsContainer = viewChild('navigationDotsContainer');
8817
+ this.firstNavigationDot = viewChild('navigationDot');
8818
+ this.navigationDotDimensions = signalElementDimensions(this.firstNavigationDot);
8806
8819
  this.containerScrollState = signalElementScrollState(this.scrollable);
8807
8820
  this.firstElementIntersection = signalElementIntersection(this.firstElement, { root: this.scrollable });
8808
8821
  this.firstElementVisibility = signal(null);
@@ -8874,19 +8887,28 @@ class ScrollableComponent {
8874
8887
  if (!highestIntersection) {
8875
8888
  return [];
8876
8889
  }
8890
+ const activeIndex = manualActiveNavigationIndex !== null
8891
+ ? manualActiveNavigationIndex
8892
+ : allIntersections.findIndex((i) => i === highestIntersection);
8877
8893
  return allIntersections.map((i, index) => ({
8878
8894
  isActive: manualActiveNavigationIndex !== null
8879
8895
  ? manualActiveNavigationIndex === index
8880
8896
  : i === highestIntersection && highestIntersection.intersectionRatio > 0,
8897
+ activeOffset: index === activeIndex ? 0 : Math.abs(index - activeIndex),
8881
8898
  element: i.target,
8882
8899
  }));
8883
8900
  });
8901
+ this.activeIndex = computed(() => {
8902
+ const scrollableNavigation = this.scrollableNavigation();
8903
+ const activeIndex = scrollableNavigation.findIndex((element) => element.isActive);
8904
+ return activeIndex;
8905
+ });
8884
8906
  this.hostAttributeBindings = signalHostAttributes({
8885
8907
  'item-size': this.itemSize,
8886
8908
  'actual-item-size': this._actualItemSize,
8887
8909
  direction: this.direction,
8888
8910
  'render-scrollbars': this.renderScrollbars,
8889
- 'sticky-buttons': this.stickyButtons,
8911
+ 'sticky-buttons': computed(() => this.stickyButtons() && this.renderButtonsInside()),
8890
8912
  });
8891
8913
  this.hostClassBindings = signalHostClasses({
8892
8914
  'et-scrollable--can-scroll': computed(() => this.canScroll() && !this.isAtStart() && !this.isAtEnd()),
@@ -8897,6 +8919,16 @@ class ScrollableComponent {
8897
8919
  this.hostStyleBindings = signalHostStyles({
8898
8920
  '--actual-item-size': computed(() => (this._actualItemSize() !== null ? `${this._actualItemSize()}px` : undefined)),
8899
8921
  });
8922
+ effect(() => {
8923
+ // Responsible for centering the active dot in navigation bar by using 'translate'
8924
+ const scrollableDotsContainer = this.navigationDotsContainer();
8925
+ const activeIndex = this.activeIndex();
8926
+ const childCount = this.scrollableContentIntersections().length;
8927
+ const offset = this.getNavigationDotsContainerTranslate(childCount, activeIndex);
8928
+ if (!scrollableDotsContainer)
8929
+ return;
8930
+ scrollableDotsContainer.nativeElement.style.transform = `translateX(${offset})`;
8931
+ });
8900
8932
  effect(() => {
8901
8933
  const scrollable = this.scrollable()?.nativeElement;
8902
8934
  const firstElement = this.firstElement()?.nativeElement;
@@ -8927,18 +8959,21 @@ class ScrollableComponent {
8927
8959
  const elementList = this.scrollableChildren();
8928
8960
  const scrollable = this.scrollable()?.nativeElement;
8929
8961
  const renderNavigation = this.renderNavigation();
8930
- if (!elementList || !scrollable || !renderNavigation) {
8962
+ const renderButtonsInFooter = this.renderButtonsInFooter();
8963
+ if (!elementList || !scrollable || (!renderNavigation && !renderButtonsInFooter)) {
8931
8964
  return;
8932
8965
  }
8933
8966
  const firstVisibleElement = elementList.find((e) => isElementVisible({ container: scrollable, element: e }));
8934
8967
  if (!firstVisibleElement) {
8935
8968
  return;
8936
8969
  }
8937
- const initialNavigationItems = elementList.map((e) => ({
8970
+ const firstVisibleElementIndex = elementList.indexOf(firstVisibleElement);
8971
+ const initialNavigationItems = elementList.map((e, i) => ({
8938
8972
  isActive: e === firstVisibleElement,
8939
8973
  element: e,
8974
+ activeOffset: Math.abs(i - firstVisibleElementIndex),
8940
8975
  }));
8941
- this._initialScrollableNavigation.set(initialNavigationItems);
8976
+ this._initialScrollableNavigation.set(initialNavigationItems ?? []);
8942
8977
  }, { allowSignalWrites: true });
8943
8978
  effect(() => {
8944
8979
  const isAtStart = this.isAtStart();
@@ -8969,6 +9004,31 @@ class ScrollableComponent {
8969
9004
  })));
8970
9005
  }))
8971
9006
  .subscribe();
9007
+ toObservable(this.manualActiveNavigationIndex)
9008
+ .pipe(filter((i) => i !== null), takeUntilDestroyed(), switchMap(() => {
9009
+ const scrollable = this.scrollable()?.nativeElement;
9010
+ if (!scrollable) {
9011
+ return of(null);
9012
+ }
9013
+ return fromEvent(scrollable, 'scroll');
9014
+ }), debounceTime(50), tap(() => this.manualActiveNavigationIndex.set(null)))
9015
+ .subscribe();
9016
+ }
9017
+ getNavigationDotsContainerTranslate(navigationDotCount, activeIndex) {
9018
+ if (navigationDotCount <= 5) {
9019
+ return '0px';
9020
+ }
9021
+ else {
9022
+ const dotContainerWidth = this.navigationDotDimensions().rect?.width ?? 20;
9023
+ let offset = -(activeIndex - 2);
9024
+ if (activeIndex < 3) {
9025
+ offset = 0;
9026
+ }
9027
+ else if (activeIndex >= navigationDotCount - 3) {
9028
+ offset = 5 - navigationDotCount;
9029
+ }
9030
+ return `${offset * dotContainerWidth}px`;
9031
+ }
8972
9032
  }
8973
9033
  scrollOneContainerSize(direction) {
8974
9034
  const scrollElement = this.scrollable()?.nativeElement;
@@ -8980,8 +9040,8 @@ class ScrollableComponent {
8980
9040
  if (isSnappingEnabled) {
8981
9041
  // If snapping is enabled we want to scroll to a position where no further snapping will happen after the scroll.
8982
9042
  const allIntersections = this.scrollableContentIntersections();
8983
- const intersections = getFirstAndLastPartialIntersection(allIntersections);
8984
- const relevantIntersection = direction === 'start' ? intersections?.first : intersections?.last;
9043
+ const intersections = getIntersectionInfo(allIntersections);
9044
+ const relevantIntersection = direction === 'start' ? intersections?.partial.first : intersections?.partial.last;
8985
9045
  if (!relevantIntersection)
8986
9046
  return;
8987
9047
  const nextIndex = relevantIntersection.intersection.intersectionRatio !== 1
@@ -9015,16 +9075,16 @@ class ScrollableComponent {
9015
9075
  }
9016
9076
  return;
9017
9077
  }
9018
- const intersections = getFirstAndLastPartialIntersection(allIntersections);
9078
+ const intersections = getIntersectionInfo(allIntersections);
9019
9079
  if (!intersections || !scrollElement)
9020
9080
  return;
9021
9081
  // Means the current element is bigger than the scrollable container.
9022
9082
  // In this case we should scroll to the start of the current element. If we are already there we should scroll to the end of the previous element.
9023
9083
  // This applies to the other direction as well.
9024
- const isFirstAndLastIntersectionEqual = intersections.first.intersection === intersections.last.intersection;
9084
+ const isFirstAndLastIntersectionEqual = intersections.partial.first.intersection === intersections.partial.last.intersection;
9025
9085
  const scrollableRect = scrollElement.getBoundingClientRect();
9026
9086
  if (isFirstAndLastIntersectionEqual) {
9027
- const intersection = intersections.first.intersection.target.getBoundingClientRect();
9087
+ const intersection = intersections.partial.first.intersection.target.getBoundingClientRect();
9028
9088
  const isStartOfElementVisible = this.direction() === 'horizontal'
9029
9089
  ? Math.round(intersection.left) >= Math.round(scrollableRect.left)
9030
9090
  : Math.round(intersection.top) >= Math.round(scrollableRect.top);
@@ -9035,7 +9095,7 @@ class ScrollableComponent {
9035
9095
  if (direction === 'start') {
9036
9096
  if (isStartOfElementVisible) {
9037
9097
  // to the end of the previous element
9038
- const previousIndex = intersections.first.index - 1;
9098
+ const previousIndex = intersections.partial.first.index - 1;
9039
9099
  const elementToScrollTo = allIntersections[previousIndex]?.target;
9040
9100
  if (!elementToScrollTo)
9041
9101
  return;
@@ -9043,19 +9103,21 @@ class ScrollableComponent {
9043
9103
  element: elementToScrollTo,
9044
9104
  origin: 'end',
9045
9105
  });
9106
+ this.manualActiveNavigationIndex.set(previousIndex);
9046
9107
  }
9047
9108
  else {
9048
9109
  // to the start of the current element
9049
9110
  this.scrollToElement({
9050
- element: intersections.first.intersection.target,
9111
+ element: intersections.partial.first.intersection.target,
9051
9112
  origin: 'start',
9052
9113
  });
9114
+ this.manualActiveNavigationIndex.set(intersections.partial.first.index);
9053
9115
  }
9054
9116
  }
9055
9117
  else {
9056
9118
  if (isEndOfElementVisible) {
9057
9119
  // to the start of the next element
9058
- const nextIndex = intersections.last.index + 1;
9120
+ const nextIndex = intersections.partial.last.index + 1;
9059
9121
  const elementToScrollTo = allIntersections[nextIndex]?.target;
9060
9122
  if (!elementToScrollTo)
9061
9123
  return;
@@ -9063,20 +9125,34 @@ class ScrollableComponent {
9063
9125
  element: elementToScrollTo,
9064
9126
  origin: 'start',
9065
9127
  });
9128
+ this.manualActiveNavigationIndex.set(nextIndex);
9066
9129
  }
9067
9130
  else {
9068
9131
  // to the end of the current element
9069
9132
  this.scrollToElement({
9070
- element: intersections.last.intersection.target,
9133
+ element: intersections.partial.last.intersection.target,
9071
9134
  origin: 'end',
9072
9135
  });
9136
+ this.manualActiveNavigationIndex.set(intersections.partial.last.index);
9073
9137
  }
9074
9138
  }
9075
9139
  return;
9076
9140
  }
9077
9141
  }
9078
- const data = direction === 'start' ? intersections.first : intersections.last;
9142
+ else if (this.scrollOrigin() === 'center') {
9143
+ // If the scroll origin is forced to be center we should always snap to the center of the next partial intersection in the scroll direction.
9144
+ const nextPartialIntersection = direction === 'start' ? intersections.partial.first : intersections.partial.last;
9145
+ const nextIndex = nextPartialIntersection.index;
9146
+ this.scrollToElement({
9147
+ element: nextPartialIntersection.intersection.target,
9148
+ origin: 'center',
9149
+ });
9150
+ this.manualActiveNavigationIndex.set(nextIndex);
9151
+ return;
9152
+ }
9153
+ const data = direction === 'start' ? intersections.partial.first : intersections.partial.last;
9079
9154
  let elementToScrollTo = data.intersection.target;
9155
+ let nextIndex = data.index;
9080
9156
  if (Math.round(data.intersection.intersectionRatio) === 1) {
9081
9157
  if (direction === 'start' && data.index === 0) {
9082
9158
  return;
@@ -9084,18 +9160,21 @@ class ScrollableComponent {
9084
9160
  if (direction === 'end' && data.index === allIntersections.length - 1) {
9085
9161
  return;
9086
9162
  }
9087
- const nextIndex = direction === 'start' ? data.index - 1 : data.index + 1;
9163
+ nextIndex = direction === 'start' ? data.index - 1 : data.index + 1;
9088
9164
  elementToScrollTo = allIntersections[nextIndex]?.target;
9165
+ if (!elementToScrollTo)
9166
+ return;
9089
9167
  }
9090
- if (!elementToScrollTo)
9091
- return;
9092
9168
  this.scrollToElement({
9093
9169
  element: elementToScrollTo,
9094
9170
  origin: direction,
9095
9171
  });
9172
+ this.manualActiveNavigationIndex.set(nextIndex);
9096
9173
  }
9097
9174
  scrollToElement(options) {
9098
9175
  const scrollElement = this.scrollable()?.nativeElement;
9176
+ const { origin } = options;
9177
+ const forcedOrigin = this.scrollOrigin();
9099
9178
  scrollToElement({
9100
9179
  container: scrollElement,
9101
9180
  direction: this.direction() === 'horizontal' ? 'inline' : 'block',
@@ -9103,13 +9182,16 @@ class ScrollableComponent {
9103
9182
  ? { scrollInlineMargin: this.scrollMargin() }
9104
9183
  : { scrollBlockMargin: this.scrollMargin() }),
9105
9184
  ...options,
9185
+ ...(forcedOrigin === 'auto' || options.ignoreForcedOrigin ? { origin } : { origin: forcedOrigin }),
9106
9186
  });
9107
9187
  }
9108
9188
  scrollToElementByIndex(options) {
9109
9189
  const elements = this.scrollableChildren();
9190
+ const { origin } = options;
9191
+ const forcedOrigin = this.scrollOrigin();
9110
9192
  if (!elements.length) {
9111
9193
  if (isDevMode()) {
9112
- console.warn('No elements found to scroll to. Make sure to apply the isElement directive to the elements you want to scroll to.');
9194
+ console.warn('No elements found to scroll to.');
9113
9195
  }
9114
9196
  return;
9115
9197
  }
@@ -9122,19 +9204,15 @@ class ScrollableComponent {
9122
9204
  ? { scrollInlineMargin: this.scrollMargin() }
9123
9205
  : { scrollBlockMargin: this.scrollMargin() }),
9124
9206
  ...options,
9207
+ ...(forcedOrigin === 'auto' || options.ignoreForcedOrigin ? { origin } : { origin: forcedOrigin }),
9125
9208
  });
9126
9209
  }
9127
- scrollToElementViaNavigation(elementIndex, element) {
9210
+ scrollToElementViaNavigation(elementIndex) {
9211
+ const element = this.scrollableChildren()[elementIndex];
9128
9212
  this.manualActiveNavigationIndex.set(elementIndex);
9129
9213
  this.scrollToElement({
9130
9214
  element,
9131
9215
  });
9132
- const scrollElement = this.scrollable()?.nativeElement;
9133
- if (!scrollElement)
9134
- return;
9135
- fromEvent(scrollElement, 'scroll')
9136
- .pipe(debounceTime(50), take(1), tap(() => this.manualActiveNavigationIndex.set(null)))
9137
- .subscribe();
9138
9216
  }
9139
9217
  setIsCursorDragging(isDragging) {
9140
9218
  this._isCursorDragging$.next(isDragging);
@@ -9161,13 +9239,25 @@ class ScrollableComponent {
9161
9239
  const scrollElement = this.scrollable()?.nativeElement;
9162
9240
  if (!scrollElement)
9163
9241
  return;
9164
- const intersections = getFirstAndLastPartialIntersection(allIntersections);
9242
+ const intersections = getIntersectionInfo(allIntersections);
9165
9243
  if (!intersections)
9166
9244
  return;
9167
- const isFirstAndLastIntersectionEqual = intersections.first.intersection === intersections.last.intersection;
9245
+ const isFirstAndLastIntersectionEqual = intersections.partial.first.intersection === intersections.partial.last.intersection;
9168
9246
  const scrollableRect = scrollElement.getBoundingClientRect();
9169
- if (isFirstAndLastIntersectionEqual) {
9170
- const intersection = intersections.first.intersection.target.getBoundingClientRect();
9247
+ if (this.scrollOrigin() === 'center' && intersections.full.hasMultiple) {
9248
+ // If there is more than one fully visible element we should not snap at all.
9249
+ return;
9250
+ }
9251
+ else if (this.scrollOrigin() === 'center' && intersections.full.first.intersection) {
9252
+ // If there is already a fully visible element we should snap it to the center.
9253
+ this.scrollToElement({
9254
+ element: intersections.full.first.intersection.target,
9255
+ origin: 'center',
9256
+ });
9257
+ return;
9258
+ }
9259
+ else if (isFirstAndLastIntersectionEqual) {
9260
+ const intersection = intersections.partial.first.intersection.target.getBoundingClientRect();
9171
9261
  const isStartOfElementVisible = this.direction() === 'horizontal'
9172
9262
  ? intersection.left >= scrollableRect.left
9173
9263
  : intersection.top >= scrollableRect.top;
@@ -9181,7 +9271,7 @@ class ScrollableComponent {
9181
9271
  // If the start of the element is visible we should snap to the start.
9182
9272
  if (isStartOfElementVisible) {
9183
9273
  this.scrollToElement({
9184
- element: intersections.first.intersection.target,
9274
+ element: intersections.partial.first.intersection.target,
9185
9275
  origin: 'start',
9186
9276
  });
9187
9277
  return;
@@ -9189,28 +9279,29 @@ class ScrollableComponent {
9189
9279
  // If the end of the element is visible we should snap to the end.
9190
9280
  if (isEndOfElementVisible) {
9191
9281
  this.scrollToElement({
9192
- element: intersections.last.intersection.target,
9282
+ element: intersections.partial.last.intersection.target,
9193
9283
  origin: 'end',
9194
9284
  });
9195
9285
  return;
9196
9286
  }
9197
9287
  }
9198
9288
  else if ((this.direction() === 'horizontal' &&
9199
- intersections.biggest.intersection.boundingClientRect.width > scrollableRect.width) ||
9289
+ intersections.partial.biggest.intersection.boundingClientRect.width > scrollableRect.width) ||
9200
9290
  (this.direction() === 'vertical' &&
9201
- intersections.biggest.intersection.boundingClientRect.height > scrollableRect.height)) {
9291
+ intersections.partial.biggest.intersection.boundingClientRect.height > scrollableRect.height)) {
9202
9292
  // If the current element is bigger than the scrollable container we should snap to the start of the current element if the scroll direction is forward
9203
9293
  // and to the end of the current element if the scroll direction is backwards.
9204
- const origin = intersections.biggest.index === intersections.first.index ? 'end' : 'start';
9294
+ const origin = intersections.partial.biggest.index === intersections.partial.first.index ? 'end' : 'start';
9205
9295
  this.scrollToElement({
9206
- element: intersections.biggest.intersection.target,
9296
+ element: intersections.partial.biggest.intersection.target,
9207
9297
  origin,
9298
+ ignoreForcedOrigin: true,
9208
9299
  });
9209
9300
  }
9210
9301
  else {
9211
9302
  // No special case. Just snap to the biggest intersection.
9212
9303
  this.scrollToElement({
9213
- element: intersections.biggest.intersection.target,
9304
+ element: intersections.partial.biggest.intersection.target,
9214
9305
  });
9215
9306
  }
9216
9307
  }), takeUntil(this._disableSnapping$))
@@ -9220,7 +9311,7 @@ class ScrollableComponent {
9220
9311
  this._disableSnapping$.next();
9221
9312
  }
9222
9313
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: ScrollableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9223
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.5", type: ScrollableComponent, isStandalone: true, selector: "et-scrollable", inputs: { _itemSize: ["itemSize", "_itemSize"], _direction: ["direction", "_direction"], _scrollableRole: ["scrollableRole", "_scrollableRole"], _scrollableClass: ["scrollableClass", "_scrollableClass"], _renderNavigation: ["renderNavigation", "_renderNavigation", booleanAttribute], _renderMasks: ["renderMasks", "_renderMasks", booleanAttribute], _renderButtons: ["renderButtons", "_renderButtons", booleanAttribute], _renderScrollbars: ["renderScrollbars", "_renderScrollbars", booleanAttribute], _stickyButtons: ["stickyButtons", "_stickyButtons", booleanAttribute], _cursorDragScroll: ["cursorDragScroll", "_cursorDragScroll", booleanAttribute], _disableActiveElementScrolling: ["disableActiveElementScrolling", "_disableActiveElementScrolling", booleanAttribute], _scrollMode: ["scrollMode", "_scrollMode"], _snap: ["snap", "_snap", booleanAttribute], _scrollMargin: ["scrollMargin", "_scrollMargin", numberAttribute] }, outputs: { scrollStateChange: "scrollStateChange", intersectionChange: "intersectionChange" }, host: { classAttribute: "et-scrollable" }, queries: [{ propertyName: "_activeElementList", predicate: SCROLLABLE_IS_ACTIVE_CHILD_TOKEN, descendants: true }], viewQueries: [{ propertyName: "_scrollable", first: true, predicate: ["scrollable"], descendants: true, static: true }, { propertyName: "_scrollableContainer", first: true, predicate: ["scrollableContainer"], descendants: true, static: true }, { propertyName: "_firstElement", first: true, predicate: ["firstElement"], descendants: true, static: true }, { propertyName: "_lastElement", first: true, predicate: ["lastElement"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"et-scrollable-wrapper\">\n <div\n #scrollable\n [attr.role]=\"scrollableRole() ?? undefined\"\n [etCursorDragScroll]=\"cursorDragScroll() && (!isAtStart() || !isAtEnd())\"\n [allowedDirection]=\"direction()\"\n (cursorDragStart)=\"setIsCursorDragging(true)\"\n (cursorDragEnd)=\"setIsCursorDragging(false)\"\n class=\"et-scrollable-container-outer\"\n >\n <div #scrollableContainer [ngClass]=\"scrollableClass()\" class=\"et-scrollable-container\">\n <div #firstElement class=\"et-scroll-observer-first-element\" etScrollableIgnoreChild></div>\n <ng-content />\n <div #lastElement class=\"et-scroll-observer-last-element\" etScrollableIgnoreChild></div>\n </div>\n </div>\n\n @if (renderMasks()) {\n <div class=\"et-scrollable-masks\">\n <div class=\"et-scrollable-mask et-scrollable-mask--start\"></div>\n <div class=\"et-scrollable-mask et-scrollable-mask--end\"></div>\n </div>\n }\n\n @if (renderButtons()) {\n <div class=\"et-scrollable-buttons\">\n <button\n (click)=\"scrollToStartDirection()\"\n class=\"et-scrollable-button et-scrollable-button--start\"\n aria-hidden=\"true\"\n type=\"button\"\n tabindex=\"-1\"\n >\n <et-chevron-icon />\n </button>\n <button\n (click)=\"scrollToEndDirection()\"\n class=\"et-scrollable-button et-scrollable-button--end\"\n aria-hidden=\"true\"\n type=\"button\"\n tabindex=\"-1\"\n >\n <et-chevron-icon />\n </button>\n </div>\n }\n</div>\n\n@if (renderNavigation() && scrollableNavigation().length > 1) {\n <div class=\"et-scrollable-navigation\" aria-hidden=\"true\">\n @for (item of scrollableNavigation(); track i; let i = $index) {\n <button\n [class.et-scrollable-navigation-item--active]=\"item.isActive\"\n (click)=\"scrollToElementViaNavigation(i, item.element)\"\n class=\"et-scrollable-navigation-item\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n ></button>\n }\n </div>\n}\n", styles: [".et-scrollable{--mask: #121212 0, transparent 100%;--mask-size: 25px;--_auto-size: min-content;--_flow: column;display:block}.et-scrollable .et-scrollable-wrapper{display:grid;position:relative}.et-scrollable[item-size=same]{--_auto-size: 1fr}.et-scrollable[item-size=full]{--_auto-size: var(--actual-item-size)}.et-scrollable[render-scrollbars=false] .et-scrollable-container-outer{scrollbar-width:none}.et-scrollable[render-scrollbars=false] .et-scrollable-container-outer::-webkit-scrollbar{display:none}.et-scrollable[direction=horizontal] .et-scrollable-container-outer{overflow-x:auto;overflow-y:hidden}.et-scrollable[direction=horizontal] .et-scrollable-container{grid-auto-columns:var(--_auto-size)}.et-scrollable[direction=horizontal] .et-scrollable-mask,.et-scrollable[direction=horizontal] .et-scrollable-button{inline-size:var(--mask-size);block-size:100%}.et-scrollable[direction=horizontal] .et-scrollable-mask--start,.et-scrollable[direction=horizontal] .et-scrollable-button--start{inset-block-start:0;inset-inline:0 0}.et-scrollable[direction=horizontal] .et-scrollable-mask--end,.et-scrollable[direction=horizontal] .et-scrollable-button--end{inset-block-start:0;inset-inline:calc(100% - 40px) 0}.et-scrollable[direction=horizontal] .et-scrollable-mask--start{background:linear-gradient(to right,var(--mask))}.et-scrollable[direction=horizontal] .et-scrollable-mask--end{background:linear-gradient(to left,var(--mask));inset-inline:calc(100% - var(--mask-size)) 100%}.et-scrollable[direction=horizontal] .et-scrollable-button--start{inset-block-start:calc(50% - 20px);transform:rotate(-90deg)}.et-scrollable[direction=horizontal] .et-scrollable-button--end{inset-block-start:calc(50% - 20px);transform:rotate(90deg)}.et-scrollable[direction=horizontal] .et-scroll-observer-first-element,.et-scrollable[direction=horizontal] .et-scroll-observer-last-element{block-size:100%;inline-size:1px}.et-scrollable[direction=horizontal] .et-scroll-observer-first-element{inset-inline-start:1px}.et-scrollable[direction=horizontal] .et-scroll-observer-last-element{inset-inline-end:1px}.et-scrollable[direction=vertical]{--_flow: row}.et-scrollable[direction=vertical] .et-scrollable-container-outer{overflow-x:hidden;overflow-y:auto}.et-scrollable[direction=vertical] .et-scrollable-container{grid-auto-rows:var(--_auto-size)}.et-scrollable[direction=vertical] .et-scrollable-mask,.et-scrollable[direction=vertical] .et-scrollable-button{block-size:var(--mask-size);inline-size:100%}.et-scrollable[direction=vertical] .et-scrollable-mask--start,.et-scrollable[direction=vertical] .et-scrollable-button--start{inset-block-start:0;inset-inline-start:0}.et-scrollable[direction=vertical] .et-scrollable-mask--end,.et-scrollable[direction=vertical] .et-scrollable-button--end{inset-block-end:0;inset-inline-start:0}.et-scrollable[direction=vertical] .et-scrollable-mask--start{background:linear-gradient(to bottom,var(--mask))}.et-scrollable[direction=vertical] .et-scrollable-mask--end{background:linear-gradient(to top,var(--mask))}.et-scrollable[direction=vertical] .et-scrollable-button--start{inset-inline-start:calc(50% - 20px);transform:rotate(0)}.et-scrollable[direction=vertical] .et-scrollable-button--end{inset-inline-start:calc(50% - 20px);transform:rotate(180deg)}.et-scrollable[direction=vertical] .et-scroll-observer-first-element,.et-scrollable[direction=vertical] .et-scroll-observer-last-element{inline-size:100%;block-size:1px}.et-scrollable[direction=vertical] .et-scroll-observer-first-element{inset-block-start:1px}.et-scrollable[direction=vertical] .et-scroll-observer-last-element{inset-block-end:1px}.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-masks .et-scrollable-mask--start,.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-buttons .et-scrollable-button--start{opacity:1}.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-buttons .et-scrollable-button--start{pointer-events:all}.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-masks .et-scrollable-mask--end,.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-buttons .et-scrollable-button--end{opacity:1}.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-buttons .et-scrollable-button--end{pointer-events:all}.et-scrollable .et-scrollable-container-outer{overflow:auto;display:grid;position:relative;grid-row:1/1;grid-column:1/1}.et-scrollable .et-scroll-observer-first-element,.et-scrollable .et-scroll-observer-last-element{position:absolute;pointer-events:none}.et-scrollable .et-scrollable-container{display:grid;grid-auto-flow:var(--_flow);position:relative}.et-scrollable .et-scrollable-masks,.et-scrollable .et-scrollable-buttons{grid-row:1/1;grid-column:1/1;pointer-events:none}.et-scrollable .et-scrollable-masks .et-scrollable-mask,.et-scrollable .et-scrollable-masks .et-scrollable-button,.et-scrollable .et-scrollable-buttons .et-scrollable-mask,.et-scrollable .et-scrollable-buttons .et-scrollable-button{position:absolute;opacity:0}.et-scrollable.et-scrollable--can-scroll.et-scrollable--enable-overlay-animations .et-scrollable-mask,.et-scrollable.et-scrollable--can-scroll.et-scrollable--enable-overlay-animations .et-scrollable-button{transition:opacity .3s var(--ease-5)}.et-scrollable .et-scrollable-buttons .et-scrollable-button{background:transparent;border:none;padding:12px;inline-size:40px;block-size:40px;border-radius:4px;cursor:pointer}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-chevron-icon{pointer-events:none}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-scrollable-button--start{inset-inline:0 0}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-scrollable-button--end{inset-inline:calc(100% - 40px) 0}.et-scrollable[sticky-buttons=true]{--_sticky-margin: 10%}.et-scrollable[sticky-buttons=true] .et-scrollable-button{position:sticky}.et-scrollable[sticky-buttons=true][direction=horizontal] .et-scrollable-buttons{margin-block:var(--_sticky-margin)}.et-scrollable[sticky-buttons=true][direction=vertical] .et-scrollable-buttons{margin-inline:var(--_sticky-margin)}.et-scrollable[sticky-buttons=true][direction=vertical] .et-scrollable-buttons .et-scrollable-button--end{inset-block-start:100%}.et-scrollable .et-scrollable-navigation{display:flex;justify-content:center;gap:10px;margin-block-start:10px}.et-scrollable .et-scrollable-navigation .et-scrollable-navigation-item{all:unset;inline-size:10px;block-size:10px;display:block;background-color:#4b4b4b;border-radius:50%;cursor:pointer}.et-scrollable .et-scrollable-navigation .et-scrollable-navigation-item.et-scrollable-navigation-item--active{background-color:#c6c6c6}\n"], dependencies: [{ kind: "directive", type: CursorDragScrollDirective, selector: "[etCursorDragScroll]", inputs: ["etCursorDragScroll", "allowedDirection"], outputs: ["cursorDragStart", "cursorDragMove", "cursorDragEnd"], exportAs: ["etCursorDragScroll"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ChevronIconComponent, selector: "et-chevron-icon" }, { kind: "directive", type: ScrollableIgnoreChildDirective, selector: "[etScrollableIgnoreChild]", inputs: ["etScrollableIgnoreChild"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
9314
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.5", type: ScrollableComponent, isStandalone: true, selector: "et-scrollable", inputs: { _itemSize: ["itemSize", "_itemSize"], _direction: ["direction", "_direction"], _scrollableRole: ["scrollableRole", "_scrollableRole"], _scrollableClass: ["scrollableClass", "_scrollableClass"], _renderNavigation: ["renderNavigation", "_renderNavigation", booleanAttribute], _renderMasks: ["renderMasks", "_renderMasks", booleanAttribute], _renderButtons: ["renderButtons", "_renderButtons", booleanAttribute], _buttonPosition: ["buttonPosition", "_buttonPosition"], _renderScrollbars: ["renderScrollbars", "_renderScrollbars", booleanAttribute], _stickyButtons: ["stickyButtons", "_stickyButtons", booleanAttribute], _cursorDragScroll: ["cursorDragScroll", "_cursorDragScroll", booleanAttribute], _disableActiveElementScrolling: ["disableActiveElementScrolling", "_disableActiveElementScrolling", booleanAttribute], _scrollMode: ["scrollMode", "_scrollMode"], _snap: ["snap", "_snap", booleanAttribute], _scrollMargin: ["scrollMargin", "_scrollMargin", numberAttribute], _scrollOrigin: ["scrollOrigin", "_scrollOrigin"] }, outputs: { scrollStateChange: "scrollStateChange", intersectionChange: "intersectionChange" }, host: { classAttribute: "et-scrollable" }, queries: [{ propertyName: "_activeElementList", predicate: SCROLLABLE_IS_ACTIVE_CHILD_TOKEN, descendants: true }], viewQueries: [{ propertyName: "navigationDotsContainer", first: true, predicate: ["navigationDotsContainer"], descendants: true, isSignal: true }, { propertyName: "firstNavigationDot", first: true, predicate: ["navigationDot"], descendants: true, isSignal: true }, { propertyName: "_scrollable", first: true, predicate: ["scrollable"], descendants: true, static: true }, { propertyName: "_scrollableContainer", first: true, predicate: ["scrollableContainer"], descendants: true, static: true }, { propertyName: "_firstElement", first: true, predicate: ["firstElement"], descendants: true, static: true }, { propertyName: "_lastElement", first: true, predicate: ["lastElement"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"et-scrollable-wrapper\">\n <div\n #scrollable\n [attr.role]=\"scrollableRole() ?? undefined\"\n [etCursorDragScroll]=\"cursorDragScroll() && (!isAtStart() || !isAtEnd())\"\n [allowedDirection]=\"direction()\"\n (cursorDragStart)=\"setIsCursorDragging(true)\"\n (cursorDragEnd)=\"setIsCursorDragging(false)\"\n class=\"et-scrollable-container-outer\"\n >\n <div #scrollableContainer [ngClass]=\"scrollableClass()\" class=\"et-scrollable-container\">\n <div #firstElement class=\"et-scroll-observer-first-element\" etScrollableIgnoreChild></div>\n <ng-content />\n <div #lastElement class=\"et-scroll-observer-last-element\" etScrollableIgnoreChild></div>\n </div>\n </div>\n\n @if (renderMasks()) {\n <div class=\"et-scrollable-masks\">\n <div class=\"et-scrollable-mask et-scrollable-mask--start\"></div>\n <div class=\"et-scrollable-mask et-scrollable-mask--end\"></div>\n </div>\n }\n\n @if (renderButtonsInside()) {\n <div class=\"et-scrollable-buttons\">\n <ng-container *ngTemplateOutlet=\"forwardButtonTpl\" />\n <ng-container *ngTemplateOutlet=\"backwardButtonTpl\" />\n </div>\n }\n</div>\n\n@if (renderButtonsInFooter() || (renderNavigation() && scrollableNavigation().length > 1)) {\n <div\n [ngClass]=\"{\n 'et-scrollable-footer--with-navigation': renderNavigation(),\n 'et-scrollable-footer--with-buttons': renderButtonsInFooter()\n }\"\n class=\"et-scrollable-footer\"\n aria-hidden=\"true\"\n >\n @if (renderButtonsInFooter()) {\n <ng-container *ngTemplateOutlet=\"forwardButtonTpl\" />\n }\n\n @if (renderNavigation()) {\n <div class=\"et-scrollable-progress-bar\">\n <div #navigationDotsContainer class=\"et-scrollable-dots-container\">\n @for (item of scrollableNavigation(); track i; let i = $index) {\n <button\n #navigationDot\n [class.et-scrollable-navigation-item--active]=\"item.isActive\"\n [class.et-scrollable-navigation-item--close]=\"\n scrollableNavigation()[i + 1]?.isActive || scrollableNavigation()[i - 1]?.isActive\n \"\n [class.et-scrollable-navigation-item--far]=\"\n !scrollableNavigation()[i + 1]?.isActive && !scrollableNavigation()[i - 1]?.isActive && !item.isActive\n \"\n [attr.active-offset]=\"item.activeOffset\"\n (click)=\"scrollToElementViaNavigation(i)\"\n class=\"et-scrollable-navigation-item\"\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n ></button>\n }\n </div>\n </div>\n }\n\n @if (renderButtonsInFooter()) {\n <ng-container *ngTemplateOutlet=\"backwardButtonTpl\" />\n }\n </div>\n}\n\n<ng-template #forwardButtonTpl>\n <button\n [disabled]=\"isAtStart()\"\n (click)=\"scrollToStartDirection()\"\n class=\"et-scrollable-button et-scrollable-button--start\"\n aria-hidden=\"true\"\n type=\"button\"\n tabindex=\"-1\"\n >\n <et-chevron-icon />\n </button>\n</ng-template>\n\n<ng-template #backwardButtonTpl>\n <button\n [disabled]=\"isAtEnd()\"\n (click)=\"scrollToEndDirection()\"\n class=\"et-scrollable-button et-scrollable-button--end\"\n aria-hidden=\"true\"\n type=\"button\"\n tabindex=\"-1\"\n >\n <et-chevron-icon />\n </button>\n</ng-template>\n", styles: [".et-scrollable{--mask: #121212 0, transparent 100%;--mask-size: 25px;--_auto-size: min-content;--_flow: column;display:block}.et-scrollable .et-scrollable-wrapper{display:grid;position:relative}.et-scrollable[item-size=same]{--_auto-size: 1fr}.et-scrollable[item-size=full]{--_auto-size: var(--actual-item-size)}.et-scrollable[render-scrollbars=false] .et-scrollable-container-outer{scrollbar-width:none}.et-scrollable[render-scrollbars=false] .et-scrollable-container-outer::-webkit-scrollbar{display:none}.et-scrollable[direction=horizontal] .et-scrollable-container-outer{overflow-x:auto;overflow-y:hidden}.et-scrollable[direction=horizontal] .et-scrollable-container{grid-auto-columns:var(--_auto-size)}.et-scrollable[direction=horizontal] .et-scrollable-mask,.et-scrollable[direction=horizontal] .et-scrollable-button{inline-size:var(--mask-size);block-size:100%}.et-scrollable[direction=horizontal] .et-scrollable-mask--start,.et-scrollable[direction=horizontal] .et-scrollable-button--start{inset-block-start:0;inset-inline:0 0}.et-scrollable[direction=horizontal] .et-scrollable-mask--end,.et-scrollable[direction=horizontal] .et-scrollable-button--end{inset-block-start:0;inset-inline:calc(100% - 40px) 0}.et-scrollable[direction=horizontal] .et-scrollable-mask--start{background:linear-gradient(to right,var(--mask))}.et-scrollable[direction=horizontal] .et-scrollable-mask--end{background:linear-gradient(to left,var(--mask));inset-inline:calc(100% - var(--mask-size)) 100%}.et-scrollable[direction=horizontal] .et-scrollable-button--start{inset-block-start:calc(50% - 20px);transform:rotate(-90deg)}.et-scrollable[direction=horizontal] .et-scrollable-button--end{inset-block-start:calc(50% - 20px);transform:rotate(90deg)}.et-scrollable[direction=horizontal] .et-scroll-observer-first-element,.et-scrollable[direction=horizontal] .et-scroll-observer-last-element{block-size:100%;inline-size:1px}.et-scrollable[direction=horizontal] .et-scroll-observer-first-element{inset-inline-start:1px}.et-scrollable[direction=horizontal] .et-scroll-observer-last-element{inset-inline-end:1px}.et-scrollable[direction=vertical]{--_flow: row}.et-scrollable[direction=vertical] .et-scrollable-container-outer{overflow-x:hidden;overflow-y:auto}.et-scrollable[direction=vertical] .et-scrollable-container{grid-auto-rows:var(--_auto-size)}.et-scrollable[direction=vertical] .et-scrollable-mask,.et-scrollable[direction=vertical] .et-scrollable-button{block-size:var(--mask-size);inline-size:100%}.et-scrollable[direction=vertical] .et-scrollable-mask--start,.et-scrollable[direction=vertical] .et-scrollable-button--start{inset-block-start:0;inset-inline-start:0}.et-scrollable[direction=vertical] .et-scrollable-mask--end,.et-scrollable[direction=vertical] .et-scrollable-button--end{inset-block-end:0;inset-inline-start:0}.et-scrollable[direction=vertical] .et-scrollable-mask--start{background:linear-gradient(to bottom,var(--mask))}.et-scrollable[direction=vertical] .et-scrollable-mask--end{background:linear-gradient(to top,var(--mask))}.et-scrollable[direction=vertical] .et-scrollable-button--start{inset-inline-start:calc(50% - 20px);transform:rotate(0)}.et-scrollable[direction=vertical] .et-scrollable-button--end{inset-inline-start:calc(50% - 20px);transform:rotate(180deg)}.et-scrollable[direction=vertical] .et-scroll-observer-first-element,.et-scrollable[direction=vertical] .et-scroll-observer-last-element{inline-size:100%;block-size:1px}.et-scrollable[direction=vertical] .et-scroll-observer-first-element{inset-block-start:1px}.et-scrollable[direction=vertical] .et-scroll-observer-last-element{inset-block-end:1px}.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-masks .et-scrollable-mask--start,.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-buttons .et-scrollable-button--start{opacity:1}.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-buttons .et-scrollable-button--start{pointer-events:all}.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-masks .et-scrollable-mask--end,.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-buttons .et-scrollable-button--end{opacity:1}.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-buttons .et-scrollable-button--end{pointer-events:all}.et-scrollable .et-scrollable-container-outer{overflow:auto;display:grid;position:relative;grid-row:1/1;grid-column:1/1}.et-scrollable .et-scroll-observer-first-element,.et-scrollable .et-scroll-observer-last-element{position:absolute;pointer-events:none}.et-scrollable .et-scrollable-container{display:grid;grid-auto-flow:var(--_flow);position:relative}.et-scrollable .et-scrollable-masks,.et-scrollable .et-scrollable-buttons{grid-row:1/1;grid-column:1/1;pointer-events:none}.et-scrollable .et-scrollable-masks .et-scrollable-mask,.et-scrollable .et-scrollable-masks .et-scrollable-button,.et-scrollable .et-scrollable-buttons .et-scrollable-mask,.et-scrollable .et-scrollable-buttons .et-scrollable-button{position:absolute;opacity:0}.et-scrollable.et-scrollable--can-scroll.et-scrollable--enable-overlay-animations .et-scrollable-mask,.et-scrollable.et-scrollable--can-scroll.et-scrollable--enable-overlay-animations .et-scrollable-button{transition:opacity .3s var(--ease-5)}.et-scrollable .et-scrollable-buttons .et-scrollable-button{background:transparent;border:none;padding:12px;inline-size:40px;block-size:40px;border-radius:4px;cursor:pointer}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-chevron-icon{pointer-events:none}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-scrollable-button--start{inset-inline:0 0}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-scrollable-button--end{inset-inline:calc(100% - 40px) 0}.et-scrollable[sticky-buttons=true]{--_sticky-margin: 10%}.et-scrollable[sticky-buttons=true] .et-scrollable-button{position:sticky}.et-scrollable[sticky-buttons=true][direction=horizontal] .et-scrollable-buttons{margin-block:var(--_sticky-margin)}.et-scrollable[sticky-buttons=true][direction=vertical] .et-scrollable-buttons{margin-inline:var(--_sticky-margin)}.et-scrollable[sticky-buttons=true][direction=vertical] .et-scrollable-buttons .et-scrollable-button--end{inset-block-start:100%}.et-scrollable .et-scrollable-footer{display:flex;justify-content:center;gap:10px;margin-block-start:10px}.et-scrollable .et-scrollable-navigation-item{display:flex;justify-content:center;align-items:center;border:none;padding:0;inline-size:20px;block-size:20px;border-radius:50%;cursor:pointer;background-color:transparent}.et-scrollable .et-scrollable-navigation-item.et-scrollable-navigation-item--active:after{background-color:#c6c6c6}.et-scrollable .et-scrollable-navigation-item:after{content:\"\";display:block;inline-size:50%;block-size:50%;border-radius:50%;background-color:#4b4b4b;transform:scale(0);transition:background-color .2s linear,transform .2s linear}.et-scrollable .et-scrollable-navigation-item[active-offset=\"0\"]:after{transform:scale(1)}.et-scrollable .et-scrollable-navigation-item[active-offset=\"1\"]:after{transform:scale(.75)}.et-scrollable .et-scrollable-navigation-item[active-offset=\"2\"]:after{transform:scale(.6)}.et-scrollable .et-scrollable-navigation-item[active-offset=\"3\"]:after{transform:scale(.5)}.et-scrollable .et-scrollable-navigation-item[active-offset=\"4\"]:after{transform:scale(.4)}.et-scrollable .et-scrollable-progress-bar{overflow:hidden;max-inline-size:100px;display:flex;align-items:center}.et-scrollable .et-scrollable-progress-bar .et-scrollable-dots-container{display:flex;flex-wrap:nowrap;transition:transform .3s var(--ease-5)}\n"], dependencies: [{ kind: "directive", type: CursorDragScrollDirective, selector: "[etCursorDragScroll]", inputs: ["etCursorDragScroll", "allowedDirection"], outputs: ["cursorDragStart", "cursorDragMove", "cursorDragEnd"], exportAs: ["etCursorDragScroll"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ChevronIconComponent, selector: "et-chevron-icon" }, { kind: "directive", type: ScrollableIgnoreChildDirective, selector: "[etScrollableIgnoreChild]", inputs: ["etScrollableIgnoreChild"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
9224
9315
  }
9225
9316
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: ScrollableComponent, decorators: [{
9226
9317
  type: Component,
@@ -9232,9 +9323,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImpor
9232
9323
  ChevronIconComponent,
9233
9324
  ScrollableIsActiveChildDirective,
9234
9325
  ScrollableIgnoreChildDirective,
9326
+ NgTemplateOutlet,
9235
9327
  ], host: {
9236
9328
  class: 'et-scrollable',
9237
- }, template: "<div class=\"et-scrollable-wrapper\">\n <div\n #scrollable\n [attr.role]=\"scrollableRole() ?? undefined\"\n [etCursorDragScroll]=\"cursorDragScroll() && (!isAtStart() || !isAtEnd())\"\n [allowedDirection]=\"direction()\"\n (cursorDragStart)=\"setIsCursorDragging(true)\"\n (cursorDragEnd)=\"setIsCursorDragging(false)\"\n class=\"et-scrollable-container-outer\"\n >\n <div #scrollableContainer [ngClass]=\"scrollableClass()\" class=\"et-scrollable-container\">\n <div #firstElement class=\"et-scroll-observer-first-element\" etScrollableIgnoreChild></div>\n <ng-content />\n <div #lastElement class=\"et-scroll-observer-last-element\" etScrollableIgnoreChild></div>\n </div>\n </div>\n\n @if (renderMasks()) {\n <div class=\"et-scrollable-masks\">\n <div class=\"et-scrollable-mask et-scrollable-mask--start\"></div>\n <div class=\"et-scrollable-mask et-scrollable-mask--end\"></div>\n </div>\n }\n\n @if (renderButtons()) {\n <div class=\"et-scrollable-buttons\">\n <button\n (click)=\"scrollToStartDirection()\"\n class=\"et-scrollable-button et-scrollable-button--start\"\n aria-hidden=\"true\"\n type=\"button\"\n tabindex=\"-1\"\n >\n <et-chevron-icon />\n </button>\n <button\n (click)=\"scrollToEndDirection()\"\n class=\"et-scrollable-button et-scrollable-button--end\"\n aria-hidden=\"true\"\n type=\"button\"\n tabindex=\"-1\"\n >\n <et-chevron-icon />\n </button>\n </div>\n }\n</div>\n\n@if (renderNavigation() && scrollableNavigation().length > 1) {\n <div class=\"et-scrollable-navigation\" aria-hidden=\"true\">\n @for (item of scrollableNavigation(); track i; let i = $index) {\n <button\n [class.et-scrollable-navigation-item--active]=\"item.isActive\"\n (click)=\"scrollToElementViaNavigation(i, item.element)\"\n class=\"et-scrollable-navigation-item\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n ></button>\n }\n </div>\n}\n", styles: [".et-scrollable{--mask: #121212 0, transparent 100%;--mask-size: 25px;--_auto-size: min-content;--_flow: column;display:block}.et-scrollable .et-scrollable-wrapper{display:grid;position:relative}.et-scrollable[item-size=same]{--_auto-size: 1fr}.et-scrollable[item-size=full]{--_auto-size: var(--actual-item-size)}.et-scrollable[render-scrollbars=false] .et-scrollable-container-outer{scrollbar-width:none}.et-scrollable[render-scrollbars=false] .et-scrollable-container-outer::-webkit-scrollbar{display:none}.et-scrollable[direction=horizontal] .et-scrollable-container-outer{overflow-x:auto;overflow-y:hidden}.et-scrollable[direction=horizontal] .et-scrollable-container{grid-auto-columns:var(--_auto-size)}.et-scrollable[direction=horizontal] .et-scrollable-mask,.et-scrollable[direction=horizontal] .et-scrollable-button{inline-size:var(--mask-size);block-size:100%}.et-scrollable[direction=horizontal] .et-scrollable-mask--start,.et-scrollable[direction=horizontal] .et-scrollable-button--start{inset-block-start:0;inset-inline:0 0}.et-scrollable[direction=horizontal] .et-scrollable-mask--end,.et-scrollable[direction=horizontal] .et-scrollable-button--end{inset-block-start:0;inset-inline:calc(100% - 40px) 0}.et-scrollable[direction=horizontal] .et-scrollable-mask--start{background:linear-gradient(to right,var(--mask))}.et-scrollable[direction=horizontal] .et-scrollable-mask--end{background:linear-gradient(to left,var(--mask));inset-inline:calc(100% - var(--mask-size)) 100%}.et-scrollable[direction=horizontal] .et-scrollable-button--start{inset-block-start:calc(50% - 20px);transform:rotate(-90deg)}.et-scrollable[direction=horizontal] .et-scrollable-button--end{inset-block-start:calc(50% - 20px);transform:rotate(90deg)}.et-scrollable[direction=horizontal] .et-scroll-observer-first-element,.et-scrollable[direction=horizontal] .et-scroll-observer-last-element{block-size:100%;inline-size:1px}.et-scrollable[direction=horizontal] .et-scroll-observer-first-element{inset-inline-start:1px}.et-scrollable[direction=horizontal] .et-scroll-observer-last-element{inset-inline-end:1px}.et-scrollable[direction=vertical]{--_flow: row}.et-scrollable[direction=vertical] .et-scrollable-container-outer{overflow-x:hidden;overflow-y:auto}.et-scrollable[direction=vertical] .et-scrollable-container{grid-auto-rows:var(--_auto-size)}.et-scrollable[direction=vertical] .et-scrollable-mask,.et-scrollable[direction=vertical] .et-scrollable-button{block-size:var(--mask-size);inline-size:100%}.et-scrollable[direction=vertical] .et-scrollable-mask--start,.et-scrollable[direction=vertical] .et-scrollable-button--start{inset-block-start:0;inset-inline-start:0}.et-scrollable[direction=vertical] .et-scrollable-mask--end,.et-scrollable[direction=vertical] .et-scrollable-button--end{inset-block-end:0;inset-inline-start:0}.et-scrollable[direction=vertical] .et-scrollable-mask--start{background:linear-gradient(to bottom,var(--mask))}.et-scrollable[direction=vertical] .et-scrollable-mask--end{background:linear-gradient(to top,var(--mask))}.et-scrollable[direction=vertical] .et-scrollable-button--start{inset-inline-start:calc(50% - 20px);transform:rotate(0)}.et-scrollable[direction=vertical] .et-scrollable-button--end{inset-inline-start:calc(50% - 20px);transform:rotate(180deg)}.et-scrollable[direction=vertical] .et-scroll-observer-first-element,.et-scrollable[direction=vertical] .et-scroll-observer-last-element{inline-size:100%;block-size:1px}.et-scrollable[direction=vertical] .et-scroll-observer-first-element{inset-block-start:1px}.et-scrollable[direction=vertical] .et-scroll-observer-last-element{inset-block-end:1px}.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-masks .et-scrollable-mask--start,.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-buttons .et-scrollable-button--start{opacity:1}.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-buttons .et-scrollable-button--start{pointer-events:all}.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-masks .et-scrollable-mask--end,.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-buttons .et-scrollable-button--end{opacity:1}.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-buttons .et-scrollable-button--end{pointer-events:all}.et-scrollable .et-scrollable-container-outer{overflow:auto;display:grid;position:relative;grid-row:1/1;grid-column:1/1}.et-scrollable .et-scroll-observer-first-element,.et-scrollable .et-scroll-observer-last-element{position:absolute;pointer-events:none}.et-scrollable .et-scrollable-container{display:grid;grid-auto-flow:var(--_flow);position:relative}.et-scrollable .et-scrollable-masks,.et-scrollable .et-scrollable-buttons{grid-row:1/1;grid-column:1/1;pointer-events:none}.et-scrollable .et-scrollable-masks .et-scrollable-mask,.et-scrollable .et-scrollable-masks .et-scrollable-button,.et-scrollable .et-scrollable-buttons .et-scrollable-mask,.et-scrollable .et-scrollable-buttons .et-scrollable-button{position:absolute;opacity:0}.et-scrollable.et-scrollable--can-scroll.et-scrollable--enable-overlay-animations .et-scrollable-mask,.et-scrollable.et-scrollable--can-scroll.et-scrollable--enable-overlay-animations .et-scrollable-button{transition:opacity .3s var(--ease-5)}.et-scrollable .et-scrollable-buttons .et-scrollable-button{background:transparent;border:none;padding:12px;inline-size:40px;block-size:40px;border-radius:4px;cursor:pointer}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-chevron-icon{pointer-events:none}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-scrollable-button--start{inset-inline:0 0}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-scrollable-button--end{inset-inline:calc(100% - 40px) 0}.et-scrollable[sticky-buttons=true]{--_sticky-margin: 10%}.et-scrollable[sticky-buttons=true] .et-scrollable-button{position:sticky}.et-scrollable[sticky-buttons=true][direction=horizontal] .et-scrollable-buttons{margin-block:var(--_sticky-margin)}.et-scrollable[sticky-buttons=true][direction=vertical] .et-scrollable-buttons{margin-inline:var(--_sticky-margin)}.et-scrollable[sticky-buttons=true][direction=vertical] .et-scrollable-buttons .et-scrollable-button--end{inset-block-start:100%}.et-scrollable .et-scrollable-navigation{display:flex;justify-content:center;gap:10px;margin-block-start:10px}.et-scrollable .et-scrollable-navigation .et-scrollable-navigation-item{all:unset;inline-size:10px;block-size:10px;display:block;background-color:#4b4b4b;border-radius:50%;cursor:pointer}.et-scrollable .et-scrollable-navigation .et-scrollable-navigation-item.et-scrollable-navigation-item--active{background-color:#c6c6c6}\n"] }]
9329
+ }, template: "<div class=\"et-scrollable-wrapper\">\n <div\n #scrollable\n [attr.role]=\"scrollableRole() ?? undefined\"\n [etCursorDragScroll]=\"cursorDragScroll() && (!isAtStart() || !isAtEnd())\"\n [allowedDirection]=\"direction()\"\n (cursorDragStart)=\"setIsCursorDragging(true)\"\n (cursorDragEnd)=\"setIsCursorDragging(false)\"\n class=\"et-scrollable-container-outer\"\n >\n <div #scrollableContainer [ngClass]=\"scrollableClass()\" class=\"et-scrollable-container\">\n <div #firstElement class=\"et-scroll-observer-first-element\" etScrollableIgnoreChild></div>\n <ng-content />\n <div #lastElement class=\"et-scroll-observer-last-element\" etScrollableIgnoreChild></div>\n </div>\n </div>\n\n @if (renderMasks()) {\n <div class=\"et-scrollable-masks\">\n <div class=\"et-scrollable-mask et-scrollable-mask--start\"></div>\n <div class=\"et-scrollable-mask et-scrollable-mask--end\"></div>\n </div>\n }\n\n @if (renderButtonsInside()) {\n <div class=\"et-scrollable-buttons\">\n <ng-container *ngTemplateOutlet=\"forwardButtonTpl\" />\n <ng-container *ngTemplateOutlet=\"backwardButtonTpl\" />\n </div>\n }\n</div>\n\n@if (renderButtonsInFooter() || (renderNavigation() && scrollableNavigation().length > 1)) {\n <div\n [ngClass]=\"{\n 'et-scrollable-footer--with-navigation': renderNavigation(),\n 'et-scrollable-footer--with-buttons': renderButtonsInFooter()\n }\"\n class=\"et-scrollable-footer\"\n aria-hidden=\"true\"\n >\n @if (renderButtonsInFooter()) {\n <ng-container *ngTemplateOutlet=\"forwardButtonTpl\" />\n }\n\n @if (renderNavigation()) {\n <div class=\"et-scrollable-progress-bar\">\n <div #navigationDotsContainer class=\"et-scrollable-dots-container\">\n @for (item of scrollableNavigation(); track i; let i = $index) {\n <button\n #navigationDot\n [class.et-scrollable-navigation-item--active]=\"item.isActive\"\n [class.et-scrollable-navigation-item--close]=\"\n scrollableNavigation()[i + 1]?.isActive || scrollableNavigation()[i - 1]?.isActive\n \"\n [class.et-scrollable-navigation-item--far]=\"\n !scrollableNavigation()[i + 1]?.isActive && !scrollableNavigation()[i - 1]?.isActive && !item.isActive\n \"\n [attr.active-offset]=\"item.activeOffset\"\n (click)=\"scrollToElementViaNavigation(i)\"\n class=\"et-scrollable-navigation-item\"\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n ></button>\n }\n </div>\n </div>\n }\n\n @if (renderButtonsInFooter()) {\n <ng-container *ngTemplateOutlet=\"backwardButtonTpl\" />\n }\n </div>\n}\n\n<ng-template #forwardButtonTpl>\n <button\n [disabled]=\"isAtStart()\"\n (click)=\"scrollToStartDirection()\"\n class=\"et-scrollable-button et-scrollable-button--start\"\n aria-hidden=\"true\"\n type=\"button\"\n tabindex=\"-1\"\n >\n <et-chevron-icon />\n </button>\n</ng-template>\n\n<ng-template #backwardButtonTpl>\n <button\n [disabled]=\"isAtEnd()\"\n (click)=\"scrollToEndDirection()\"\n class=\"et-scrollable-button et-scrollable-button--end\"\n aria-hidden=\"true\"\n type=\"button\"\n tabindex=\"-1\"\n >\n <et-chevron-icon />\n </button>\n</ng-template>\n", styles: [".et-scrollable{--mask: #121212 0, transparent 100%;--mask-size: 25px;--_auto-size: min-content;--_flow: column;display:block}.et-scrollable .et-scrollable-wrapper{display:grid;position:relative}.et-scrollable[item-size=same]{--_auto-size: 1fr}.et-scrollable[item-size=full]{--_auto-size: var(--actual-item-size)}.et-scrollable[render-scrollbars=false] .et-scrollable-container-outer{scrollbar-width:none}.et-scrollable[render-scrollbars=false] .et-scrollable-container-outer::-webkit-scrollbar{display:none}.et-scrollable[direction=horizontal] .et-scrollable-container-outer{overflow-x:auto;overflow-y:hidden}.et-scrollable[direction=horizontal] .et-scrollable-container{grid-auto-columns:var(--_auto-size)}.et-scrollable[direction=horizontal] .et-scrollable-mask,.et-scrollable[direction=horizontal] .et-scrollable-button{inline-size:var(--mask-size);block-size:100%}.et-scrollable[direction=horizontal] .et-scrollable-mask--start,.et-scrollable[direction=horizontal] .et-scrollable-button--start{inset-block-start:0;inset-inline:0 0}.et-scrollable[direction=horizontal] .et-scrollable-mask--end,.et-scrollable[direction=horizontal] .et-scrollable-button--end{inset-block-start:0;inset-inline:calc(100% - 40px) 0}.et-scrollable[direction=horizontal] .et-scrollable-mask--start{background:linear-gradient(to right,var(--mask))}.et-scrollable[direction=horizontal] .et-scrollable-mask--end{background:linear-gradient(to left,var(--mask));inset-inline:calc(100% - var(--mask-size)) 100%}.et-scrollable[direction=horizontal] .et-scrollable-button--start{inset-block-start:calc(50% - 20px);transform:rotate(-90deg)}.et-scrollable[direction=horizontal] .et-scrollable-button--end{inset-block-start:calc(50% - 20px);transform:rotate(90deg)}.et-scrollable[direction=horizontal] .et-scroll-observer-first-element,.et-scrollable[direction=horizontal] .et-scroll-observer-last-element{block-size:100%;inline-size:1px}.et-scrollable[direction=horizontal] .et-scroll-observer-first-element{inset-inline-start:1px}.et-scrollable[direction=horizontal] .et-scroll-observer-last-element{inset-inline-end:1px}.et-scrollable[direction=vertical]{--_flow: row}.et-scrollable[direction=vertical] .et-scrollable-container-outer{overflow-x:hidden;overflow-y:auto}.et-scrollable[direction=vertical] .et-scrollable-container{grid-auto-rows:var(--_auto-size)}.et-scrollable[direction=vertical] .et-scrollable-mask,.et-scrollable[direction=vertical] .et-scrollable-button{block-size:var(--mask-size);inline-size:100%}.et-scrollable[direction=vertical] .et-scrollable-mask--start,.et-scrollable[direction=vertical] .et-scrollable-button--start{inset-block-start:0;inset-inline-start:0}.et-scrollable[direction=vertical] .et-scrollable-mask--end,.et-scrollable[direction=vertical] .et-scrollable-button--end{inset-block-end:0;inset-inline-start:0}.et-scrollable[direction=vertical] .et-scrollable-mask--start{background:linear-gradient(to bottom,var(--mask))}.et-scrollable[direction=vertical] .et-scrollable-mask--end{background:linear-gradient(to top,var(--mask))}.et-scrollable[direction=vertical] .et-scrollable-button--start{inset-inline-start:calc(50% - 20px);transform:rotate(0)}.et-scrollable[direction=vertical] .et-scrollable-button--end{inset-inline-start:calc(50% - 20px);transform:rotate(180deg)}.et-scrollable[direction=vertical] .et-scroll-observer-first-element,.et-scrollable[direction=vertical] .et-scroll-observer-last-element{inline-size:100%;block-size:1px}.et-scrollable[direction=vertical] .et-scroll-observer-first-element{inset-block-start:1px}.et-scrollable[direction=vertical] .et-scroll-observer-last-element{inset-block-end:1px}.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-masks .et-scrollable-mask--start,.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-buttons .et-scrollable-button--start{opacity:1}.et-scrollable:not(.et-scrollable--is-at-start) .et-scrollable-buttons .et-scrollable-button--start{pointer-events:all}.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-masks .et-scrollable-mask--end,.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-buttons .et-scrollable-button--end{opacity:1}.et-scrollable:not(.et-scrollable--is-at-end) .et-scrollable-buttons .et-scrollable-button--end{pointer-events:all}.et-scrollable .et-scrollable-container-outer{overflow:auto;display:grid;position:relative;grid-row:1/1;grid-column:1/1}.et-scrollable .et-scroll-observer-first-element,.et-scrollable .et-scroll-observer-last-element{position:absolute;pointer-events:none}.et-scrollable .et-scrollable-container{display:grid;grid-auto-flow:var(--_flow);position:relative}.et-scrollable .et-scrollable-masks,.et-scrollable .et-scrollable-buttons{grid-row:1/1;grid-column:1/1;pointer-events:none}.et-scrollable .et-scrollable-masks .et-scrollable-mask,.et-scrollable .et-scrollable-masks .et-scrollable-button,.et-scrollable .et-scrollable-buttons .et-scrollable-mask,.et-scrollable .et-scrollable-buttons .et-scrollable-button{position:absolute;opacity:0}.et-scrollable.et-scrollable--can-scroll.et-scrollable--enable-overlay-animations .et-scrollable-mask,.et-scrollable.et-scrollable--can-scroll.et-scrollable--enable-overlay-animations .et-scrollable-button{transition:opacity .3s var(--ease-5)}.et-scrollable .et-scrollable-buttons .et-scrollable-button{background:transparent;border:none;padding:12px;inline-size:40px;block-size:40px;border-radius:4px;cursor:pointer}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-chevron-icon{pointer-events:none}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-scrollable-button--start{inset-inline:0 0}.et-scrollable .et-scrollable-buttons .et-scrollable-button .et-scrollable-button--end{inset-inline:calc(100% - 40px) 0}.et-scrollable[sticky-buttons=true]{--_sticky-margin: 10%}.et-scrollable[sticky-buttons=true] .et-scrollable-button{position:sticky}.et-scrollable[sticky-buttons=true][direction=horizontal] .et-scrollable-buttons{margin-block:var(--_sticky-margin)}.et-scrollable[sticky-buttons=true][direction=vertical] .et-scrollable-buttons{margin-inline:var(--_sticky-margin)}.et-scrollable[sticky-buttons=true][direction=vertical] .et-scrollable-buttons .et-scrollable-button--end{inset-block-start:100%}.et-scrollable .et-scrollable-footer{display:flex;justify-content:center;gap:10px;margin-block-start:10px}.et-scrollable .et-scrollable-navigation-item{display:flex;justify-content:center;align-items:center;border:none;padding:0;inline-size:20px;block-size:20px;border-radius:50%;cursor:pointer;background-color:transparent}.et-scrollable .et-scrollable-navigation-item.et-scrollable-navigation-item--active:after{background-color:#c6c6c6}.et-scrollable .et-scrollable-navigation-item:after{content:\"\";display:block;inline-size:50%;block-size:50%;border-radius:50%;background-color:#4b4b4b;transform:scale(0);transition:background-color .2s linear,transform .2s linear}.et-scrollable .et-scrollable-navigation-item[active-offset=\"0\"]:after{transform:scale(1)}.et-scrollable .et-scrollable-navigation-item[active-offset=\"1\"]:after{transform:scale(.75)}.et-scrollable .et-scrollable-navigation-item[active-offset=\"2\"]:after{transform:scale(.6)}.et-scrollable .et-scrollable-navigation-item[active-offset=\"3\"]:after{transform:scale(.5)}.et-scrollable .et-scrollable-navigation-item[active-offset=\"4\"]:after{transform:scale(.4)}.et-scrollable .et-scrollable-progress-bar{overflow:hidden;max-inline-size:100px;display:flex;align-items:center}.et-scrollable .et-scrollable-progress-bar .et-scrollable-dots-container{display:flex;flex-wrap:nowrap;transition:transform .3s var(--ease-5)}\n"] }]
9238
9330
  }], ctorParameters: () => [], propDecorators: { _itemSize: [{
9239
9331
  type: Input,
9240
9332
  args: [{ alias: 'itemSize' }]
@@ -9256,6 +9348,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImpor
9256
9348
  }], _renderButtons: [{
9257
9349
  type: Input,
9258
9350
  args: [{ transform: booleanAttribute, alias: 'renderButtons' }]
9351
+ }], _buttonPosition: [{
9352
+ type: Input,
9353
+ args: [{ alias: 'buttonPosition' }]
9259
9354
  }], _renderScrollbars: [{
9260
9355
  type: Input,
9261
9356
  args: [{ transform: booleanAttribute, alias: 'renderScrollbars' }]
@@ -9277,6 +9372,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImpor
9277
9372
  }], _scrollMargin: [{
9278
9373
  type: Input,
9279
9374
  args: [{ transform: numberAttribute, alias: 'scrollMargin' }]
9375
+ }], _scrollOrigin: [{
9376
+ type: Input,
9377
+ args: [{ alias: 'scrollOrigin' }]
9280
9378
  }], scrollStateChange: [{
9281
9379
  type: Output
9282
9380
  }], intersectionChange: [{
@@ -9702,7 +9800,7 @@ class MenuComponent {
9702
9800
  provide: MENU,
9703
9801
  useExisting: MenuComponent,
9704
9802
  },
9705
- ], queries: [{ propertyName: "__menuItemList", predicate: MENU_ITEM_TOKEN, descendants: true }], ngImport: i0, template: "<et-scrollable\n [direction]=\"orientation()\"\n [renderButtons]=\"renderScrollableButtons()\"\n [renderMasks]=\"renderScrollableMasks()\"\n [cursorDragScroll]=\"orientation() === 'horizontal'\"\n [scrollableClass]=\"scrollableClass()\"\n renderScrollbars\n>\n <ng-content />\n</et-scrollable>\n", styles: [".et-menu{--et-menu-max-inline-size: 300px;--et-menu-max-block-size: 200px;--et-menu-background-color: #b3b3b3;--et-menu-border-radius: 10px}.et-scrollable-container-outer{max-inline-size:var(--et-menu-max-inline-size);max-block-size:min(var(--et-menu-max-block-size),var(--et-floating-max-height, var(--et-menu-max-block-size)));background-color:var(--et-menu-background-color);border-radius:var(--et-menu-border-radius);box-sizing:border-box}\n"], dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
9803
+ ], queries: [{ propertyName: "__menuItemList", predicate: MENU_ITEM_TOKEN, descendants: true }], ngImport: i0, template: "<et-scrollable\n [direction]=\"orientation()\"\n [renderButtons]=\"renderScrollableButtons()\"\n [renderMasks]=\"renderScrollableMasks()\"\n [cursorDragScroll]=\"orientation() === 'horizontal'\"\n [scrollableClass]=\"scrollableClass()\"\n renderScrollbars\n>\n <ng-content />\n</et-scrollable>\n", styles: [".et-menu{--et-menu-max-inline-size: 300px;--et-menu-max-block-size: 200px;--et-menu-background-color: #b3b3b3;--et-menu-border-radius: 10px}.et-scrollable-container-outer{max-inline-size:var(--et-menu-max-inline-size);max-block-size:min(var(--et-menu-max-block-size),var(--et-floating-max-height, var(--et-menu-max-block-size)));background-color:var(--et-menu-background-color);border-radius:var(--et-menu-border-radius);box-sizing:border-box}\n"], dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "buttonPosition", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin", "scrollOrigin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
9706
9804
  }
9707
9805
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: MenuComponent, decorators: [{
9708
9806
  type: Component,
@@ -16793,7 +16891,7 @@ class InlineTabHeaderComponent extends PaginatedTabHeaderDirective {
16793
16891
  event.preventDefault();
16794
16892
  }
16795
16893
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: InlineTabHeaderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
16796
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.5", type: InlineTabHeaderComponent, isStandalone: true, selector: "et-inline-tab-header", host: { classAttribute: "et-inline-tab-header" }, queries: [{ propertyName: "_items", predicate: InlineTabLabelWrapperDirective }, { propertyName: "_inkBars", predicate: i0.forwardRef(() => ActiveTabUnderlineDirective), descendants: true }], viewQueries: [{ propertyName: "_scrollable", first: true, predicate: ScrollableComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<et-scrollable\n [itemSize]=\"itemSize\"\n [renderButtons]=\"renderButtons\"\n [scrollableClass]=\"scrollableClass\"\n [renderMasks]=\"renderMasks\"\n [renderScrollbars]=\"renderScrollbars\"\n (keydown)=\"_handleKeydown($event)\"\n (contentChanged)=\"_onContentChanges()\"\n>\n <ng-content />\n</et-scrollable>\n", dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
16894
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.5", type: InlineTabHeaderComponent, isStandalone: true, selector: "et-inline-tab-header", host: { classAttribute: "et-inline-tab-header" }, queries: [{ propertyName: "_items", predicate: InlineTabLabelWrapperDirective }, { propertyName: "_inkBars", predicate: i0.forwardRef(() => ActiveTabUnderlineDirective), descendants: true }], viewQueries: [{ propertyName: "_scrollable", first: true, predicate: ScrollableComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<et-scrollable\n [itemSize]=\"itemSize\"\n [renderButtons]=\"renderButtons\"\n [scrollableClass]=\"scrollableClass\"\n [renderMasks]=\"renderMasks\"\n [renderScrollbars]=\"renderScrollbars\"\n (keydown)=\"_handleKeydown($event)\"\n (contentChanged)=\"_onContentChanges()\"\n>\n <ng-content />\n</et-scrollable>\n", dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "buttonPosition", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin", "scrollOrigin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
16797
16895
  }
16798
16896
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: InlineTabHeaderComponent, decorators: [{
16799
16897
  type: Component,
@@ -17314,7 +17412,7 @@ class NavTabsComponent extends PaginatedTabHeaderDirective {
17314
17412
  return this.tabOutlet ? 'tablist' : this._elementRef.nativeElement.getAttribute('role');
17315
17413
  }
17316
17414
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: NavTabsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
17317
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.5", type: NavTabsComponent, isStandalone: true, selector: "[et-nav-tabs]", inputs: { tabOutlet: "tabOutlet" }, host: { properties: { "attr.role": "this._attrRole" }, classAttribute: "et-nav-tabs" }, queries: [{ propertyName: "_items", predicate: i0.forwardRef(() => NavTabLinkComponent), descendants: true }, { propertyName: "_inkBars", predicate: i0.forwardRef(() => ActiveTabUnderlineDirective), descendants: true }], viewQueries: [{ propertyName: "_scrollable", first: true, predicate: ScrollableComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<et-scrollable\n [itemSize]=\"itemSize\"\n [renderButtons]=\"renderButtons\"\n [scrollableClass]=\"scrollableClass\"\n [renderMasks]=\"renderMasks\"\n [renderScrollbars]=\"renderScrollbars\"\n (keydown)=\"_handleKeydown($event)\"\n (contentChanged)=\"_onContentChanges()\"\n>\n <ng-content />\n</et-scrollable>\n", dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
17415
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.5", type: NavTabsComponent, isStandalone: true, selector: "[et-nav-tabs]", inputs: { tabOutlet: "tabOutlet" }, host: { properties: { "attr.role": "this._attrRole" }, classAttribute: "et-nav-tabs" }, queries: [{ propertyName: "_items", predicate: i0.forwardRef(() => NavTabLinkComponent), descendants: true }, { propertyName: "_inkBars", predicate: i0.forwardRef(() => ActiveTabUnderlineDirective), descendants: true }], viewQueries: [{ propertyName: "_scrollable", first: true, predicate: ScrollableComponent, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<et-scrollable\n [itemSize]=\"itemSize\"\n [renderButtons]=\"renderButtons\"\n [scrollableClass]=\"scrollableClass\"\n [renderMasks]=\"renderMasks\"\n [renderScrollbars]=\"renderScrollbars\"\n (keydown)=\"_handleKeydown($event)\"\n (contentChanged)=\"_onContentChanges()\"\n>\n <ng-content />\n</et-scrollable>\n", dependencies: [{ kind: "component", type: ScrollableComponent, selector: "et-scrollable", inputs: ["itemSize", "direction", "scrollableRole", "scrollableClass", "renderNavigation", "renderMasks", "renderButtons", "buttonPosition", "renderScrollbars", "stickyButtons", "cursorDragScroll", "disableActiveElementScrolling", "scrollMode", "snap", "scrollMargin", "scrollOrigin"], outputs: ["scrollStateChange", "intersectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
17318
17416
  }
17319
17417
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: NavTabsComponent, decorators: [{
17320
17418
  type: Component,