ng-virtual-list 18.12.2 → 18.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +2 -2
  2. package/esm2022/lib/components/ng-list-item/base/base-virtual-list-item-component.mjs +9 -5
  3. package/esm2022/lib/components/ng-list-item/const/index.mjs +2 -1
  4. package/esm2022/lib/components/ng-list-item/ng-virtual-list-item.component.mjs +14 -8
  5. package/esm2022/lib/components/ng-prerender-container/components/ng-prerender-list-item/ng-prerender-list-item.component.mjs +3 -3
  6. package/esm2022/lib/components/ng-scroll-view/ng-scroll-view.component.mjs +20 -14
  7. package/esm2022/lib/components/ng-scroller/ng-scroller.component.mjs +6 -2
  8. package/esm2022/lib/const/index.mjs +6 -3
  9. package/esm2022/lib/core/track-box.mjs +31 -9
  10. package/esm2022/lib/directives/virtual-click/virtual-click.directive.mjs +35 -16
  11. package/esm2022/lib/models/display-object-config.model.mjs +1 -1
  12. package/esm2022/lib/ng-virtual-list.component.mjs +43 -11
  13. package/esm2022/lib/ng-virtual-list.service.mjs +31 -2
  14. package/esm2022/lib/utils/animator/animator.mjs +31 -8
  15. package/fesm2022/ng-virtual-list.mjs +214 -67
  16. package/fesm2022/ng-virtual-list.mjs.map +1 -1
  17. package/lib/components/ng-list-item/base/base-virtual-list-item-component.d.ts +1 -1
  18. package/lib/components/ng-list-item/ng-virtual-list-item.component.d.ts +3 -1
  19. package/lib/components/ng-scroll-view/ng-scroll-view.component.d.ts +5 -2
  20. package/lib/components/ng-scroller/ng-scroller.component.d.ts +1 -1
  21. package/lib/const/index.d.ts +3 -1
  22. package/lib/directives/virtual-click/virtual-click.directive.d.ts +11 -6
  23. package/lib/models/display-object-config.model.d.ts +4 -0
  24. package/lib/ng-virtual-list.component.d.ts +2 -1
  25. package/lib/ng-virtual-list.service.d.ts +13 -0
  26. package/lib/utils/animator/animator.d.ts +10 -2
  27. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, inject, Component, ChangeDetectorRef, ElementRef, ChangeDetectionStrategy, ViewChild, EventEmitter as EventEmitter$1, Directive, Input, Output, Injector, InjectionToken, TemplateRef, ViewContainerRef, ViewEncapsulation, NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
3
- import { Subject, BehaviorSubject, takeUntil, tap, map, combineLatest, fromEvent, race, of, debounceTime, switchMap as switchMap$1, distinctUntilChanged, filter as filter$1, delay, startWith, from, take, skip } from 'rxjs';
3
+ import { Subject, BehaviorSubject, takeUntil, distinctUntilChanged, combineLatest, tap, map, fromEvent, race, of, debounceTime, switchMap as switchMap$1, filter as filter$1, delay, startWith, from, take, skip } from 'rxjs';
4
4
  import { BehaviorSubject as BehaviorSubject$1 } from 'rxjs/internal/BehaviorSubject';
5
5
  import * as i1 from '@angular/common';
6
6
  import { CommonModule } from '@angular/common';
7
- import { takeUntil as takeUntil$1, switchMap, filter, tap as tap$1 } from 'rxjs/operators';
7
+ import { takeUntil as takeUntil$1, tap as tap$1, switchMap, filter } from 'rxjs/operators';
8
8
  import * as i4 from '@angular/cdk/scrolling';
9
9
  import { CdkScrollable, CdkScrollableModule } from '@angular/cdk/scrolling';
10
10
 
@@ -247,6 +247,7 @@ var TextDirections;
247
247
  TextDirections["LTR"] = "ltr";
248
248
  })(TextDirections || (TextDirections = {}));
249
249
 
250
+ const INVISIBLE_POSITION = -10000;
250
251
  const SERVICE_PROP_DUMMY_ID = '__service-dummy-id__';
251
252
  const SERVICE_PROP_DUMMY = '__service-dummy__';
252
253
  const SERVICE_TYPE_DUMMY = '__service-type-dummy__';
@@ -276,7 +277,7 @@ const DEFAULT_MOTION_BLUR = 0.15;
276
277
  const DEFAULT_MOTION_BLUR_ENABLED = false;
277
278
  const DEFAULT_MAX_MOTION_BLUR = 0.5;
278
279
  const DEFAULT_ANIMATION_PARAMS = {
279
- scrollToItem: 50,
280
+ scrollToItem: 150,
280
281
  snapToItem: 150,
281
282
  navigateToItem: 150,
282
283
  navigateByKeyboard: NAVIGATION_BY_KEYBOARD_TIMER,
@@ -332,13 +333,15 @@ const POSITION$1 = 'position';
332
333
  const POSITION_RELATIVE = 'relative';
333
334
  const POSITION_ABSOLUTE = 'absolute';
334
335
  const TRANSLATE_3D = 'translate3d';
335
- const ZEROS_TRANSLATE_3D = `${TRANSLATE_3D}(0,0,0)`;
336
+ const INVISIBLE_TRANSLATE_3D = `${TRANSLATE_3D}(${INVISIBLE_POSITION},${INVISIBLE_POSITION},0)`;
336
337
  const HIDDEN_ZINDEX = '-1';
337
338
  const DEFAULT_ZINDEX = '0';
338
339
  const TOP_PROP_NAME = 'top';
339
340
  const LEFT_PROP_NAME = 'left';
340
341
  const X_PROP_NAME = 'x';
341
342
  const Y_PROP_NAME = 'y';
343
+ const TRANSFORMED_X_PROP_NAME = 'transformedX';
344
+ const TRANSFORMED_Y_PROP_NAME = 'transformedY';
342
345
  const WIDTH_PROP_NAME = 'width';
343
346
  const HEIGHT_PROP_NAME = 'height';
344
347
  const MARGIN_TOP = 'marginTop';
@@ -492,6 +495,7 @@ const DEFAULT_TEMPLATE_CONTEXT = {
492
495
  isLast: false,
493
496
  fullSize: false,
494
497
  totalItems: 0,
498
+ grabbing: false,
495
499
  },
496
500
  reseted: false,
497
501
  index: -1,
@@ -707,6 +711,31 @@ class NgVirtualListService {
707
711
  this._langTextDir = v;
708
712
  this._$langTextDir.next(v);
709
713
  }
714
+ _$grabbing = new BehaviorSubject$1(false);
715
+ $grabbing = this._$grabbing.asObservable();
716
+ get grabbing() { return this._$grabbing.getValue(); }
717
+ _grabbing = false;
718
+ set grabbing(v) {
719
+ if (this._grabbing === v) {
720
+ return;
721
+ }
722
+ this._grabbing = v;
723
+ this._$grabbing.next(v);
724
+ }
725
+ _$clickPressed = new BehaviorSubject$1(false);
726
+ $clickPressed = this._$clickPressed.asObservable();
727
+ get clickPressed() { return this._$clickPressed.getValue(); }
728
+ _clickPressed = false;
729
+ set clickPressed(v) {
730
+ if (this._clickPressed === v) {
731
+ return;
732
+ }
733
+ this._clickPressed = v;
734
+ this._$clickPressed.next(v);
735
+ }
736
+ _$isGrabbing = new BehaviorSubject$1(false);
737
+ $isGrabbing = this._$isGrabbing.asObservable();
738
+ get isGrabbing() { return this._$isGrabbing.getValue(); }
710
739
  get scrollBarSize() { return this._$scrollBarSize.getValue(); }
711
740
  _scrollBarSize = 0;
712
741
  set scrollBarSize(v) {
@@ -750,6 +779,10 @@ class NgVirtualListService {
750
779
  }
751
780
  get collapsedIds() { return this._$collapsedIds.getValue(); }
752
781
  constructor() {
782
+ const $grabbing = this.$grabbing.pipe(takeUntil(this._$unsubscribe), distinctUntilChanged()), $clickPressed = this.$clickPressed.pipe(takeUntil(this._$unsubscribe), distinctUntilChanged());
783
+ combineLatest([$grabbing, $clickPressed]).pipe(takeUntil(this._$unsubscribe), tap(([grabbing, clickPressed]) => {
784
+ this._$isGrabbing.next(grabbing && !clickPressed);
785
+ })).subscribe();
753
786
  this._$selectingMode.pipe(takeUntil(this._$unsubscribe), tap(v => {
754
787
  switch (v) {
755
788
  case SelectingModesTypes.SELECT: {
@@ -1230,7 +1263,7 @@ class BaseVirtualListItemComponent extends DisposableComponent {
1230
1263
  }
1231
1264
  this._data = v;
1232
1265
  this.updatePartStr(v, this._isSelected, this._isCollapsed);
1233
- this.updateConfig(v);
1266
+ this.updateConfig(v, this._service.isGrabbing);
1234
1267
  this.updateMeasures(v);
1235
1268
  this.update();
1236
1269
  this._$data.next(v);
@@ -1282,6 +1315,9 @@ class BaseVirtualListItemComponent extends DisposableComponent {
1282
1315
  this._id = this._service.generateComponentId();
1283
1316
  this._listId = this._service.id;
1284
1317
  this._displayId = createDisplayId(this._listId, this._id);
1318
+ this._service.$isGrabbing.pipe(takeUntil(this._$unsubscribe), tap(v => {
1319
+ this.updateConfig(this._data, v);
1320
+ })).subscribe();
1285
1321
  const $part = this.$part;
1286
1322
  $part.pipe(takeUntil(this._$unsubscribe), tap(part => {
1287
1323
  this._elementRef.nativeElement.setAttribute('part', part);
@@ -1319,9 +1355,9 @@ class BaseVirtualListItemComponent extends DisposableComponent {
1319
1355
  this._$measures.next(v?.measures ? { ...v.measures } : null);
1320
1356
  this._cdr.markForCheck();
1321
1357
  }
1322
- updateConfig(v) {
1358
+ updateConfig(v, grabbing) {
1323
1359
  this._$config.next({
1324
- ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this._$focused.getValue(),
1360
+ ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this._$focused.getValue(), grabbing,
1325
1361
  });
1326
1362
  this._cdr.markForCheck();
1327
1363
  }
@@ -1450,6 +1486,7 @@ class BaseVirtualListItemComponent extends DisposableComponent {
1450
1486
  }
1451
1487
  const el = this._elementRef.nativeElement, styles = el.style;
1452
1488
  styles.zIndex = HIDDEN_ZINDEX;
1489
+ styles.transform = INVISIBLE_TRANSLATE_3D;
1453
1490
  if (this.regular) {
1454
1491
  if (styles.display === DISPLAY_NONE) {
1455
1492
  return;
@@ -1482,9 +1519,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
1482
1519
  args: ['container']
1483
1520
  }] } });
1484
1521
 
1485
- const DEFAULT_MAX_DISTANCE = 40;
1486
1522
  /**
1487
- * ItemClickDirective
1523
+ * VirtualClickDirective
1488
1524
  * Maximum performance for extremely large lists.
1489
1525
  * It is based on algorithms for virtualization of screen objects.
1490
1526
  * @link https://github.com/DjonnyX/ng-virtual-list/blob/18.x/projects/ng-virtual-list/src/lib/directives/item-click/item-click.directive.ts
@@ -1492,30 +1528,44 @@ const DEFAULT_MAX_DISTANCE = 40;
1492
1528
  * @email djonnyx@gmail.com
1493
1529
  */
1494
1530
  class VirtualClickDirective {
1495
- _elementRef;
1496
1531
  _$unsubscribe = new Subject();
1497
- _maxDistance = DEFAULT_MAX_DISTANCE;
1532
+ _$maxDistance = new BehaviorSubject(null);
1533
+ $maxDistance = this._$maxDistance.asObservable();
1534
+ _maxDistance = null;
1498
1535
  set maxDistance(v) {
1499
- this._maxDistance = (v !== null || v !== undefined) ? Number(v) : DEFAULT_MAX_DISTANCE;
1536
+ const value = (v !== null || v !== undefined) ? Number(v) : null;
1537
+ this._maxDistance = value;
1538
+ this._$maxDistance.next(value);
1500
1539
  }
1501
1540
  onVirtualClick = new EventEmitter$1();
1502
- constructor(_elementRef) {
1503
- this._elementRef = _elementRef;
1541
+ onVirtualClickPress = new EventEmitter$1();
1542
+ onVirtualClickCancel = new EventEmitter$1();
1543
+ _service = inject(NgVirtualListService);
1544
+ _elementRef = inject(ElementRef);
1545
+ constructor() {
1546
+ let maxDistance = this._maxDistance ?? DEFAULT_CLICK_DISTANCE;
1547
+ combineLatest([this._service.$clickDistance, this.$maxDistance]).pipe(takeUntil$1(this._$unsubscribe), tap$1(([clickDistance, distance]) => {
1548
+ maxDistance = distance === null ? clickDistance : distance;
1549
+ })).subscribe();
1504
1550
  const $pointerPressed = fromEvent(this._elementRef.nativeElement, 'pointerdown'), $pointerCancel = race([
1505
1551
  fromEvent(window, 'pointerup').pipe(takeUntil$1(this._$unsubscribe)),
1506
1552
  fromEvent(window, 'pointerleave').pipe(takeUntil$1(this._$unsubscribe)),
1507
1553
  ]), $pointerRelease = fromEvent(this._elementRef.nativeElement, 'pointerup', { passive: false });
1508
1554
  $pointerPressed.pipe(takeUntil$1(this._$unsubscribe), switchMap(e => {
1509
1555
  const x = Math.abs(e.clientX), y = Math.abs(e.clientY);
1556
+ this.onVirtualClickPress.emit(e);
1510
1557
  return $pointerRelease.pipe(takeUntil$1(this._$unsubscribe), takeUntil$1(race([
1511
- $pointerCancel,
1558
+ $pointerCancel.pipe(takeUntil$1(this._$unsubscribe), tap$1(() => {
1559
+ this.onVirtualClickCancel.emit();
1560
+ })),
1512
1561
  fromEvent(window, 'pointermove').pipe(takeUntil$1(this._$unsubscribe), switchMap(e => {
1513
1562
  const xx = x - Math.abs(e.clientX), yy = y - Math.abs(e.clientY), dist = Math.sqrt(Math.pow(xx, 2) + Math.pow(yy, 2));
1514
- if (dist > this._maxDistance) {
1563
+ if (dist > maxDistance) {
1564
+ this.onVirtualClickCancel.emit();
1515
1565
  return of(true);
1516
1566
  }
1517
1567
  return of(false);
1518
- }), takeUntil$1(this._$unsubscribe), filter(v => !!v)),
1568
+ }), filter(v => !!v)),
1519
1569
  ])), takeUntil$1(this._$unsubscribe), tap$1(e => {
1520
1570
  if (e) {
1521
1571
  this.onVirtualClick.emit(e);
@@ -1529,8 +1579,8 @@ class VirtualClickDirective {
1529
1579
  this._$unsubscribe.complete();
1530
1580
  }
1531
1581
  }
1532
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VirtualClickDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
1533
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: VirtualClickDirective, selector: "[virtualClick]", inputs: { maxDistance: ["maxClickDistance", "maxDistance"] }, outputs: { onVirtualClick: "onVirtualClick" }, ngImport: i0 });
1582
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VirtualClickDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1583
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: VirtualClickDirective, selector: "[virtualClick]", inputs: { maxDistance: ["maxClickDistance", "maxDistance"] }, outputs: { onVirtualClick: "onVirtualClick", onVirtualClickPress: "onVirtualClickPress", onVirtualClickCancel: "onVirtualClickCancel" }, ngImport: i0 });
1534
1584
  }
1535
1585
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VirtualClickDirective, decorators: [{
1536
1586
  type: Directive,
@@ -1538,11 +1588,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
1538
1588
  selector: '[virtualClick]',
1539
1589
  standalone: false,
1540
1590
  }]
1541
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { maxDistance: [{
1591
+ }], ctorParameters: () => [], propDecorators: { maxDistance: [{
1542
1592
  type: Input,
1543
1593
  args: ['maxClickDistance']
1544
1594
  }], onVirtualClick: [{
1545
1595
  type: Output
1596
+ }], onVirtualClickPress: [{
1597
+ type: Output
1598
+ }], onVirtualClickCancel: [{
1599
+ type: Output
1546
1600
  }] } });
1547
1601
 
1548
1602
  /**
@@ -1574,12 +1628,12 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1574
1628
  fromEvent(this.element, EVENT_FOCUS_IN).pipe(takeUntil(this._$unsubscribe), tap(e => {
1575
1629
  this._service.focusedId = this.itemId ?? null;
1576
1630
  this._$focused.next(true);
1577
- this.updateConfig(this._data);
1631
+ this.updateConfig(this._data, this._service.isGrabbing);
1578
1632
  this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
1579
1633
  })).subscribe(),
1580
1634
  fromEvent(this.element, EVENT_FOCUS_OUT).pipe(takeUntil(this._$unsubscribe), tap(e => {
1581
1635
  this._$focused.next(false);
1582
- this.updateConfig(this._data);
1636
+ this.updateConfig(this._data, this._service.isGrabbing);
1583
1637
  this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
1584
1638
  })).subscribe();
1585
1639
  $focused.pipe(takeUntil(this._$unsubscribe), debounceTime(this.getNavigationTimeout()), switchMap$1(v => {
@@ -1612,7 +1666,7 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1612
1666
  const actualIds = collapsedIds, isCollapsed = this.itemId !== undefined && actualIds && actualIds.includes(this.itemId);
1613
1667
  this._isCollapsed = isCollapsed;
1614
1668
  this.updatePartStr(this._data, this._isSelected, isCollapsed);
1615
- this.updateConfig(this._data);
1669
+ this.updateConfig(this._data, this._service.isGrabbing);
1616
1670
  this.updateMeasures(this._data);
1617
1671
  })).subscribe();
1618
1672
  }
@@ -1715,24 +1769,30 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1715
1769
  }
1716
1770
  return Number.MIN_SAFE_INTEGER;
1717
1771
  }
1718
- updateConfig(v) {
1772
+ updateConfig(v, grabbing) {
1719
1773
  this._$config.next({
1720
- ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this._$focused.getValue(),
1774
+ ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this._$focused.getValue(), grabbing,
1721
1775
  });
1722
1776
  this._cdr.markForCheck();
1723
1777
  }
1724
1778
  onClickHandler() {
1725
1779
  this._service.virtualClick(this._data);
1726
1780
  }
1781
+ onClickPressHandler() {
1782
+ this._service.clickPressed = true;
1783
+ }
1784
+ onClickCancelHandler() {
1785
+ this._service.clickPressed = false;
1786
+ }
1727
1787
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgVirtualListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1728
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NgVirtualListItemComponent, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"($data | async) as data\">\r\n <div #item class=\"ngvl-item\" [ngClass]=\"($classes | async)!\" [part]=\"($part | async)!\" [attr.ngvl-index]=\"($index | async)!\"\r\n [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n <div *ngIf=\"_blendColor\" class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n <div #container virtualClick [part]=\"$fxPart | async\" [maxClickDistance]=\"$maxClickDistance | async\"\r\n class=\"ngvl-item__container\" [ngClass]=\"($classes | async)!\" (onVirtualClick)=\"onClickHandler()\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer ?? null\"\r\n [ngTemplateOutletContext]=\"$templateContext | async\"></ng-container>\r\n </div>\r\n </div>\r\n</ng-container>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1788
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NgVirtualListItemComponent, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"($data | async) as data\">\r\n <div #item class=\"ngvl-item\" [ngClass]=\"($classes | async)!\" [part]=\"($part | async)!\"\r\n [attr.ngvl-index]=\"($index | async)!\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n <div *ngIf=\"_blendColor\" class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n <div #container virtualClick [part]=\"$fxPart | async\" [maxClickDistance]=\"($maxClickDistance | async)!\"\r\n class=\"ngvl-item__container\" [ngClass]=\"($classes | async)!\" (onVirtualClick)=\"onClickHandler()\"\r\n (onVirtualClickPress)=\"onClickPressHandler()\" (onVirtualClickCancel)=\"onClickCancelHandler()\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer ?? null\"\r\n [ngTemplateOutletContext]=\"$templateContext | async\"></ng-container>\r\n </div>\r\n </div>\r\n</ng-container>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick", "onVirtualClickPress", "onVirtualClickCancel"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1729
1789
  }
1730
1790
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
1731
1791
  type: Component,
1732
1792
  args: [{ selector: 'ng-virtual-list-item', host: {
1733
1793
  'class': 'ngvl__item',
1734
1794
  'role': 'listitem',
1735
- }, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"($data | async) as data\">\r\n <div #item class=\"ngvl-item\" [ngClass]=\"($classes | async)!\" [part]=\"($part | async)!\" [attr.ngvl-index]=\"($index | async)!\"\r\n [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n <div *ngIf=\"_blendColor\" class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n <div #container virtualClick [part]=\"$fxPart | async\" [maxClickDistance]=\"$maxClickDistance | async\"\r\n class=\"ngvl-item__container\" [ngClass]=\"($classes | async)!\" (onVirtualClick)=\"onClickHandler()\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer ?? null\"\r\n [ngTemplateOutletContext]=\"$templateContext | async\"></ng-container>\r\n </div>\r\n </div>\r\n</ng-container>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n"] }]
1795
+ }, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"($data | async) as data\">\r\n <div #item class=\"ngvl-item\" [ngClass]=\"($classes | async)!\" [part]=\"($part | async)!\"\r\n [attr.ngvl-index]=\"($index | async)!\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n <div *ngIf=\"_blendColor\" class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n <div #container virtualClick [part]=\"$fxPart | async\" [maxClickDistance]=\"($maxClickDistance | async)!\"\r\n class=\"ngvl-item__container\" [ngClass]=\"($classes | async)!\" (onVirtualClick)=\"onClickHandler()\"\r\n (onVirtualClickPress)=\"onClickPressHandler()\" (onVirtualClickCancel)=\"onClickCancelHandler()\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer ?? null\"\r\n [ngTemplateOutletContext]=\"$templateContext | async\"></ng-container>\r\n </div>\r\n </div>\r\n</ng-container>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n"] }]
1736
1796
  }], ctorParameters: () => [] });
1737
1797
 
1738
1798
  /**
@@ -3292,7 +3352,7 @@ class TrackBox extends CacheMap {
3292
3352
  const { width, height, normalizedItemWidth, normalizedItemHeight, dynamicSize, divides, itemsOnDisplayLength, itemsFromStartToScrollEnd, isVertical, leftLayoutOffset: layoutOffset, leftLayoutIndexOffset: layoutIndexOffset, renderItems: renderItemsLength, scrollSize, sizeProperty, stickyEnabled, stickyPos, startPosition, totalLength, startIndex, typicalItemSize, minItemSize, maxItemSize, snapToItem, snapToItemAlign, itemTransform, } = metrics, displayItems = [];
3293
3353
  if (items.length) {
3294
3354
  const trackBy = this._trackingPropertyName, actualSnippedPosition = stickyPos, isSnappingMethodAdvanced = this._isSnappingMethodAdvanced, deltaOffet = (isSnappingMethodAdvanced ? scrollSize : 0), scrollDirection = this._scrollDirection, boundsSize = isVertical ? height : width, actualEndSnippedPosition = scrollSize + boundsSize - this._scrollEndOffset;
3295
- let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0;
3355
+ let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, nexstStickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0;
3296
3356
  const li = layoutIndexOffset + actualItems.length - 1;
3297
3357
  if (stickyEnabled) {
3298
3358
  for (let i = Math.min(itemsFromStartToScrollEnd > 0 ? (divides > 1 ? (itemsFromStartToScrollEnd - 1) : itemsFromStartToScrollEnd) : 0, totalLength - 1); i >= 0; i--) {
@@ -3552,6 +3612,7 @@ class TrackBox extends CacheMap {
3552
3612
  item.measures.x = isVertical ? 0 : snapped ? actualSnippedPosition : pos;
3553
3613
  item.measures.y = isVertical ? snapped ? actualSnippedPosition : pos : 0;
3554
3614
  nextSticky = item;
3615
+ nexstStickyItemIndex = displayItems.length;
3555
3616
  nextSticky.config.snapped = snapped;
3556
3617
  nextSticky.measures.delta = (isVertical ? item.measures.y : item.measures.x) - scrollSize;
3557
3618
  nextSticky.config.zIndex = Z_INDEX_3;
@@ -3574,10 +3635,10 @@ class TrackBox extends CacheMap {
3574
3635
  }
3575
3636
  i++;
3576
3637
  }
3577
- const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME;
3638
+ const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME, transformedAxis = isVertical ? TRANSFORMED_Y_PROP_NAME : TRANSFORMED_X_PROP_NAME;
3578
3639
  if (!!nextSticky && !!stickyItem && nextSticky.measures[axis] <= actualSnippedPosition + stickyItem.measures[sizeProperty]) {
3579
3640
  if (nextSticky.measures[axis] > actualSnippedPosition) {
3580
- stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3641
+ stickyItem.measures[axis] = stickyItem.measures[transformedAxis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3581
3642
  stickyItem.config.snapped = nextSticky.config.snapped = false;
3582
3643
  stickyItem.config.snappedOut = true;
3583
3644
  stickyItem.config.sticky = 1;
@@ -3586,14 +3647,35 @@ class TrackBox extends CacheMap {
3586
3647
  else {
3587
3648
  nextSticky.config.snapped = true;
3588
3649
  nextSticky.measures.delta = (isVertical ? nextSticky.measures.y : nextSticky.measures.x) - scrollSize;
3589
- stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3650
+ stickyItem.measures[axis] = stickyItem.measures[transformedAxis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3590
3651
  stickyItem.measures.delta = (isVertical ? stickyItem.measures.y : stickyItem.measures.x) - scrollSize;
3652
+ const lastStickyItem = displayItems?.[nexstStickyItemIndex + 1];
3653
+ if (lastStickyItem?.config?.sticky === 1 && displayItems?.[nexstStickyItemIndex + 2]?.config?.sticky !== 1) {
3654
+ nextSticky.config.snapped = nextSticky.config.snappedOut = false;
3655
+ stickyItem.config.snappedOut = true;
3656
+ nextSticky.measures.delta = this._scrollStartOffset;
3657
+ if (lastStickyItem.measures[axis] <= actualSnippedPosition) {
3658
+ lastStickyItem.config.snapped = lastStickyItem.config.snappedOut = true;
3659
+ lastStickyItem.measures[axis] = lastStickyItem.measures[transformedAxis] = lastStickyItem.measures.position = actualSnippedPosition;
3660
+ lastStickyItem.measures.delta = this._scrollStartOffset;
3661
+ }
3662
+ }
3663
+ else if (lastStickyItem?.config?.sticky !== 1 && displayItems?.[nexstStickyItemIndex + 2]?.config?.sticky !== 1) {
3664
+ if (nextSticky.measures[axis] <= actualSnippedPosition) {
3665
+ nextSticky.config.snapped = nextSticky.config.snappedOut = true;
3666
+ nextSticky.measures[axis] = nextSticky.measures[transformedAxis] = nextSticky.measures.position = actualSnippedPosition;
3667
+ nextSticky.measures.delta = this._scrollStartOffset;
3668
+ }
3669
+ }
3670
+ else {
3671
+ nextSticky.config.snapped = nextSticky.config.snappedOut = false;
3672
+ }
3591
3673
  }
3592
3674
  }
3593
3675
  if (!!nextEndSticky && !!endStickyItem &&
3594
3676
  (nextEndSticky.measures[axis] >= actualEndSnippedPosition - endStickyItemSize - nextEndSticky.measures[sizeProperty])) {
3595
3677
  if (nextEndSticky.measures[axis] < actualEndSnippedPosition - nextEndSticky.measures[sizeProperty]) {
3596
- endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3678
+ endStickyItem.measures[axis] = endStickyItem.measures[transformedAxis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3597
3679
  endStickyItem.config.snapped = nextEndSticky.config.snapped = false;
3598
3680
  endStickyItem.config.snappedOut = true;
3599
3681
  endStickyItem.config.sticky = 2;
@@ -3601,9 +3683,9 @@ class TrackBox extends CacheMap {
3601
3683
  }
3602
3684
  else {
3603
3685
  nextEndSticky.config.snapped = true;
3604
- nextEndSticky.measures[axis] = actualEndSnippedPosition - nextEndSticky.measures[sizeProperty];
3686
+ nextEndSticky.measures[axis] = nextEndSticky.measures[transformedAxis] = actualEndSnippedPosition - nextEndSticky.measures[sizeProperty];
3605
3687
  nextEndSticky.measures.delta = (isVertical ? nextEndSticky.measures.y : nextEndSticky.measures.x) - scrollSize;
3606
- endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3688
+ endStickyItem.measures[axis] = endStickyItem.measures[transformedAxis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3607
3689
  endStickyItem.measures.delta = (isVertical ? endStickyItem.measures.y : endStickyItem.measures.x) - scrollSize;
3608
3690
  }
3609
3691
  }
@@ -3879,18 +3961,32 @@ const easeLinear = (t) => {
3879
3961
  class Animator {
3880
3962
  static _nextId = 0;
3881
3963
  _animationId = 0;
3964
+ get animated() { return this._animationId > -1; }
3965
+ get isAnimated() { return this.hasAnimation(this._currentId); }
3882
3966
  _currentId = Animator._nextId;
3967
+ get id() { return this._currentId; }
3883
3968
  generateId() {
3884
3969
  return Animator._nextId = Animator._nextId === Number.MAX_SAFE_INTEGER
3885
3970
  ? 0 : Animator._nextId + 1;
3886
3971
  }
3972
+ _diff = 0;
3973
+ _startValue = 0;
3974
+ _endValue = 0;
3975
+ updateTo(value) {
3976
+ this._endValue = value;
3977
+ this._diff = this._endValue - this._startValue;
3978
+ return this.hasAnimation();
3979
+ }
3887
3980
  animate(params) {
3888
3981
  this.stop();
3889
3982
  const id = this.generateId();
3890
3983
  this._currentId = id;
3891
3984
  const { withDelta = DEFAULT_WITH_DELTA, startValue, endValue, duration = DEFAULT_ANIMATION_DURATION, getPropValue, easingFunction = easeLinear, onUpdate, onComplete, } = params;
3985
+ this._startValue = startValue;
3986
+ this._endValue = endValue;
3892
3987
  const startTime = performance.now();
3893
- let isCanceled = false, prevPos = startValue, start = startValue, startPosDelta = 0, delta = 0, prevTime = startTime, diff = endValue - start, isFinished = false;
3988
+ let isCanceled = false, prevPos = startValue, startPosDelta = 0, delta = 0, prevTime = startTime, isFinished = false;
3989
+ this._diff = this._endValue - this._startValue;
3894
3990
  const step = (currentTime) => {
3895
3991
  if (id !== this._currentId) {
3896
3992
  isCanceled = true;
@@ -3904,10 +4000,10 @@ class Animator {
3904
4000
  startDelta = cPos - prevPos;
3905
4001
  startPosDelta += startDelta;
3906
4002
  }
3907
- const elapsed = currentTime - startTime, progress = start === endValue ? 1 : Math.min(duration > 0 ? elapsed / duration : 0, 1), easedProgress = easingFunction(progress), val = (withDelta ? startPosDelta : 0) + start + diff * easedProgress, currentValue = val, t = performance.now();
4003
+ const elapsed = currentTime - startTime, progress = this._startValue === endValue ? 1 : Math.min(duration > 0 ? elapsed / duration : 0, 1), easedProgress = easingFunction(progress), val = (withDelta ? startPosDelta : 0) + this._startValue + this._diff * easedProgress, currentValue = val, t = performance.now();
3908
4004
  isFinished = progress === 1;
3909
4005
  delta = currentValue - startDelta - prevPos;
3910
- const ts = t - prevTime, timestamp = ts < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : ts;
4006
+ const frameTimestamp = t - prevTime, actualFrameTimestamp = frameTimestamp < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : frameTimestamp;
3911
4007
  prevTime = t;
3912
4008
  prevPos = currentValue;
3913
4009
  if (onUpdate !== undefined) {
@@ -3916,18 +4012,19 @@ class Animator {
3916
4012
  delta,
3917
4013
  elapsed,
3918
4014
  value: !withDelta && isFinished ? endValue : currentValue,
3919
- timestamp,
4015
+ timestamp: actualFrameTimestamp,
3920
4016
  };
3921
4017
  onUpdate(data);
3922
4018
  }
3923
4019
  if (isFinished) {
4020
+ this._animationId = -1;
3924
4021
  if (onComplete !== undefined) {
3925
4022
  const data = {
3926
4023
  id,
3927
4024
  delta,
3928
4025
  elapsed,
3929
4026
  value: withDelta ? currentValue : endValue,
3930
- timestamp,
4027
+ timestamp: actualFrameTimestamp,
3931
4028
  };
3932
4029
  onComplete(data);
3933
4030
  }
@@ -3937,9 +4034,17 @@ class Animator {
3937
4034
  }
3938
4035
  };
3939
4036
  this._animationId = requestAnimationFrame(step);
4037
+ return this._currentId;
4038
+ }
4039
+ hasAnimation(id = -1) {
4040
+ if ((this._currentId === id || id === -1) && this.animated) {
4041
+ return true;
4042
+ }
4043
+ return false;
3940
4044
  }
3941
- stop() {
3942
- cancelAnimationFrame(this._animationId);
4045
+ stop(id = -1) {
4046
+ cancelAnimationFrame(id === -1 ? this._animationId : id);
4047
+ this._animationId = -1;
3943
4048
  }
3944
4049
  dispose() {
3945
4050
  this.stop();
@@ -4526,6 +4631,7 @@ class NgScrollView extends BaseScrollView {
4526
4631
  get startLayoutOffset() { return this._startLayoutOffset; }
4527
4632
  _intersectionComponentId = null;
4528
4633
  _isAlignmentAnimation = false;
4634
+ get animated() { return this._animator?.isAnimated ?? false; }
4529
4635
  constructor() {
4530
4636
  super();
4531
4637
  }
@@ -4719,6 +4825,7 @@ class NgScrollView extends BaseScrollView {
4719
4825
  }));
4720
4826
  })).subscribe();
4721
4827
  }
4828
+ hasAnimation(id = -1) { return this._animator?.hasAnimation(id) ?? false; }
4722
4829
  updateDirection(position, prePosition) {
4723
4830
  const delta = (position - this._delta) - prePosition;
4724
4831
  this._scrollDirection.add(delta > 0 ? 1 : delta < 0 ? -1 : 0);
@@ -4881,7 +4988,7 @@ class NgScrollView extends BaseScrollView {
4881
4988
  moveWithAcceleration(isVertical, position, v0, v, a0, timestamp) {
4882
4989
  if (a0 !== 0 && timestamp < MAX_VELOCITY_TIMESTAMP) {
4883
4990
  const dvSign = Math.sign(v), mass = this.scrollingSettings?.mass ?? MASS, duration = DURATION, maxDuration = this.scrollingSettings?.maxDuration ?? MAX_DURATION, maxDist = this.scrollingSettings?.maxDistance ?? MAX_DIST, maxDistance = dvSign * maxDist, s = (dvSign * Math.abs((a0 * Math.pow(duration, 2)) * .5) / 10000) / mass, distance = Math.abs(s) < maxDist ? s : maxDistance, positionWithVelocity = position + (this._inversion ? -1 : 1) * distance, ad = Math.abs(a0 !== 0 ? Math.sqrt(a0) : 0) * ACCELERATION_SCALE / mass, aDuration = ad < maxDuration ? ad : maxDuration, startPosition = isVertical ? this.y : this.x;
4884
- this.animate(startPosition, Math.round(positionWithVelocity), aDuration, easeOutQuad, true);
4991
+ this.animate(startPosition, Math.round(positionWithVelocity), aDuration, easeOutQuad, false, true);
4885
4992
  }
4886
4993
  else {
4887
4994
  this.alignPosition(true, true);
@@ -4894,11 +5001,17 @@ class NgScrollView extends BaseScrollView {
4894
5001
  const isVertical = this._$isVertical.getValue(), startOffset = this._normalizeValueFromZero ? 0 : this.startOffset, scrollSize = this.scrollable ? ((isVertical ? this.scrollHeight : this.scrollWidth) - this.alignmentEndOffset) : 0, result = this.scrollable ? (value <= startOffset ? startOffset : value > scrollSize ? scrollSize : value) : startOffset;
4895
5002
  return result;
4896
5003
  }
4897
- animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
5004
+ animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, blending = false, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
4898
5005
  const isVertical = this._$isVertical.getValue();
4899
5006
  let position = startValue;
4900
5007
  this._isAlignmentAnimation = !alignmentAtComplete;
4901
- this._animator.animate({
5008
+ if (this.hasAnimation() && blending) {
5009
+ const updatable = this._animator.updateTo(endValue);
5010
+ if (updatable) {
5011
+ return this._animator.id;
5012
+ }
5013
+ }
5014
+ return this._animator.animate({
4902
5015
  withDelta: this._service.dynamic && !this.isInfinity,
4903
5016
  startValue,
4904
5017
  endValue,
@@ -4910,7 +5023,7 @@ class NgScrollView extends BaseScrollView {
4910
5023
  if (this._isCoordinatesOverrided && !skipOverridedCoordinates) {
4911
5024
  this._isCoordinatesOverrided = false;
4912
5025
  const currentCoordinate = isVertical ? this._y : this._x, delta = endValue - value;
4913
- this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, userAction, alignmentAtComplete);
5026
+ this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, blending, userAction, alignmentAtComplete);
4914
5027
  return;
4915
5028
  }
4916
5029
  const v0 = calculateVelocity(position, value - this._delta, timestamp) ?? this.averageVelocity;
@@ -5042,7 +5155,7 @@ class NgScrollView extends BaseScrollView {
5042
5155
  const cPos = (isVertical ? this.scrollTop : this.scrollLeft);
5043
5156
  if (position !== null && position !== cPos) {
5044
5157
  this.stopScrolling(true);
5045
- this.animate(cPos, position, animated ? this.animationParams.snapToItem : 1, easeOutQuad, false, false, true);
5158
+ this.animate(cPos, position, animated ? this._$animationParams.getValue().snapToItem : 1, easeOutQuad, false, false, false, true);
5046
5159
  return true;
5047
5160
  }
5048
5161
  return false;
@@ -5128,21 +5241,18 @@ class NgScrollView extends BaseScrollView {
5128
5241
  if (behavior === AUTO || behavior === SMOOTH) {
5129
5242
  if (isVertical) {
5130
5243
  if (prevY !== y) {
5131
- this.animate(prevY, y, duration, ease, userAction);
5244
+ return this.animate(prevY, y, duration, ease, blending, userAction);
5132
5245
  }
5133
5246
  }
5134
5247
  else {
5135
5248
  if (prevX !== x) {
5136
- this.animate(prevX, x, duration, ease, userAction);
5249
+ return this.animate(prevX, x, duration, ease, blending, userAction);
5137
5250
  }
5138
5251
  }
5139
5252
  }
5140
5253
  else {
5141
5254
  if (isVertical) {
5142
5255
  if (this._y !== y || force) {
5143
- if (!blending) {
5144
- this.stopScrolling(force);
5145
- }
5146
5256
  this.setY(y, snap, normalize);
5147
5257
  this.emitScrollableEvent();
5148
5258
  if (fireUpdate) {
@@ -5152,9 +5262,6 @@ class NgScrollView extends BaseScrollView {
5152
5262
  }
5153
5263
  else {
5154
5264
  if (this._x !== x || force) {
5155
- if (!blending) {
5156
- this.stopScrolling(force);
5157
- }
5158
5265
  this.setX(x, snap, normalize);
5159
5266
  this.emitScrollableEvent();
5160
5267
  if (fireUpdate) {
@@ -5163,6 +5270,7 @@ class NgScrollView extends BaseScrollView {
5163
5270
  }
5164
5271
  }
5165
5272
  }
5273
+ return -1;
5166
5274
  }
5167
5275
  emitScrollableEvent() {
5168
5276
  if (!!this.cdkScrollable) {
@@ -5181,6 +5289,9 @@ class NgScrollView extends BaseScrollView {
5181
5289
  this.stopScrolling();
5182
5290
  this.move(this._$isVertical.getValue(), offset);
5183
5291
  }
5292
+ stopAnimation(id) {
5293
+ this._animator.stop(id);
5294
+ }
5184
5295
  ngOnDestroy() {
5185
5296
  super.ngOnDestroy();
5186
5297
  if (this._animator) {
@@ -5852,6 +5963,10 @@ class NgScrollerComponent extends NgScrollView {
5852
5963
  $updateScrollBar.pipe(takeUntil(this._$unsubscribe), debounceTime(0), tap(() => {
5853
5964
  this.updateScrollBarHandler(!this._isScrollbarUserAction);
5854
5965
  })).subscribe();
5966
+ const $grabbing = this.$grabbing;
5967
+ $grabbing.pipe(takeUntil(this._$unsubscribe), tap(v => {
5968
+ this._service.grabbing = v;
5969
+ })).subscribe();
5855
5970
  combineLatest([this.$classes, this.$direction, this.$grabbing, this.$motionBlurEnabled]).pipe(takeUntil(this._$unsubscribe), distinctUntilChanged(), debounceTime(0), tap(([classes, direction, grabbing, filtered]) => {
5856
5971
  this._$actualClasses.next({ ...classes, [direction]: true, grabbing, filtered });
5857
5972
  })).subscribe();
@@ -5989,7 +6104,7 @@ class NgScrollerComponent extends NgScrollView {
5989
6104
  this._isScrollbarUserAction = false;
5990
6105
  this.scrollBar?.stopScrolling();
5991
6106
  }
5992
- this.scroll({ ...params, userAction: userAction });
6107
+ return this.scroll({ ...params, userAction: userAction });
5993
6108
  }
5994
6109
  stopScrollbar() {
5995
6110
  if (!!this.scrollBar) {
@@ -6389,14 +6504,14 @@ class NgPrerenderVirtualListItemComponent extends NgVirtualListItemComponent {
6389
6504
  }
6390
6505
  }
6391
6506
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgPrerenderVirtualListItemComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
6392
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NgPrerenderVirtualListItemComponent, selector: "ng-prerender-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"($data | async) as data\">\r\n <div #item class=\"ngvl-item\" [ngClass]=\"($classes | async)!\" [part]=\"($part | async)!\" [attr.ngvl-index]=\"($index | async)!\"\r\n [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n <div *ngIf=\"_blendColor\" class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n <div #container virtualClick [part]=\"$fxPart | async\" [maxClickDistance]=\"$maxClickDistance | async\"\r\n class=\"ngvl-item__container\" [ngClass]=\"($classes | async)!\" (onVirtualClick)=\"onClickHandler()\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer ?? null\"\r\n [ngTemplateOutletContext]=\"$templateContext | async\"></ng-container>\r\n </div>\r\n </div>\r\n</ng-container>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n", ":host{display:block;position:absolute!important;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;pointer-events:none;-webkit-user-select:none;user-select:none;text-rendering:optimizeSpeed;image-rendering:pixelated}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6507
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NgPrerenderVirtualListItemComponent, selector: "ng-prerender-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"($data | async) as data\">\r\n <div #item class=\"ngvl-item\" [ngClass]=\"($classes | async)!\" [part]=\"($part | async)!\"\r\n [attr.ngvl-index]=\"($index | async)!\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n <div *ngIf=\"_blendColor\" class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n <div #container virtualClick [part]=\"$fxPart | async\" [maxClickDistance]=\"($maxClickDistance | async)!\"\r\n class=\"ngvl-item__container\" [ngClass]=\"($classes | async)!\" (onVirtualClick)=\"onClickHandler()\"\r\n (onVirtualClickPress)=\"onClickPressHandler()\" (onVirtualClickCancel)=\"onClickCancelHandler()\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer ?? null\"\r\n [ngTemplateOutletContext]=\"$templateContext | async\"></ng-container>\r\n </div>\r\n </div>\r\n</ng-container>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n", ":host{display:block;position:absolute!important;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;pointer-events:none;-webkit-user-select:none;user-select:none;text-rendering:optimizeSpeed;image-rendering:pixelated}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick", "onVirtualClickPress", "onVirtualClickCancel"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6393
6508
  }
6394
6509
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgPrerenderVirtualListItemComponent, decorators: [{
6395
6510
  type: Component,
6396
6511
  args: [{ selector: 'ng-prerender-virtual-list-item', host: {
6397
6512
  'class': 'ngvl__item',
6398
6513
  'role': 'listitem',
6399
- }, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"($data | async) as data\">\r\n <div #item class=\"ngvl-item\" [ngClass]=\"($classes | async)!\" [part]=\"($part | async)!\" [attr.ngvl-index]=\"($index | async)!\"\r\n [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n <div *ngIf=\"_blendColor\" class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n <div #container virtualClick [part]=\"$fxPart | async\" [maxClickDistance]=\"$maxClickDistance | async\"\r\n class=\"ngvl-item__container\" [ngClass]=\"($classes | async)!\" (onVirtualClick)=\"onClickHandler()\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer ?? null\"\r\n [ngTemplateOutletContext]=\"$templateContext | async\"></ng-container>\r\n </div>\r\n </div>\r\n</ng-container>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n", ":host{display:block;position:absolute!important;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;pointer-events:none;-webkit-user-select:none;user-select:none;text-rendering:optimizeSpeed;image-rendering:pixelated}\n"] }]
6514
+ }, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"($data | async) as data\">\r\n <div #item class=\"ngvl-item\" [ngClass]=\"($classes | async)!\" [part]=\"($part | async)!\"\r\n [attr.ngvl-index]=\"($index | async)!\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n <div *ngIf=\"_blendColor\" class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n <div #container virtualClick [part]=\"$fxPart | async\" [maxClickDistance]=\"($maxClickDistance | async)!\"\r\n class=\"ngvl-item__container\" [ngClass]=\"($classes | async)!\" (onVirtualClick)=\"onClickHandler()\"\r\n (onVirtualClickPress)=\"onClickPressHandler()\" (onVirtualClickCancel)=\"onClickCancelHandler()\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer ?? null\"\r\n [ngTemplateOutletContext]=\"$templateContext | async\"></ng-container>\r\n </div>\r\n </div>\r\n</ng-container>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n", ":host{display:block;position:absolute!important;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;pointer-events:none;-webkit-user-select:none;user-select:none;text-rendering:optimizeSpeed;image-rendering:pixelated}\n"] }]
6400
6515
  }] });
6401
6516
 
6402
6517
  /**
@@ -8044,7 +8159,7 @@ class NgVirtualListComponent extends DisposableComponent {
8044
8159
  return v;
8045
8160
  };
8046
8161
  /**
8047
- * Animation parameters. The default value is "{ scrollToItem: 50, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
8162
+ * Animation parameters. The default value is "{ scrollToItem: 150, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
8048
8163
  */
8049
8164
  set animationParams(v) {
8050
8165
  if (this._$animationParams.getValue() === v) {
@@ -8691,6 +8806,7 @@ class NgVirtualListComponent extends DisposableComponent {
8691
8806
  _readyForShow = false;
8692
8807
  _cached = false;
8693
8808
  _isLoading = false;
8809
+ _animationId = -1;
8694
8810
  get cachable() {
8695
8811
  return this._prerender?.active ?? false;
8696
8812
  }
@@ -8752,6 +8868,7 @@ class NgVirtualListComponent extends DisposableComponent {
8752
8868
  })).subscribe();
8753
8869
  }
8754
8870
  ngAfterViewInit() {
8871
+ let readyForAnimations = false;
8755
8872
  const _$created = new BehaviorSubject(false), $created = _$created.asObservable();
8756
8873
  combineLatest([$created, this.$show]).pipe(takeUntil(this._$unsubscribe), filter$1(([created, shown]) => created && shown), debounceTime(1), tap(v => {
8757
8874
  this._$initialized.next(true);
@@ -8944,6 +9061,7 @@ class NgVirtualListComponent extends DisposableComponent {
8944
9061
  }), tap(items => {
8945
9062
  this._trackBox.resetCollection(items, this.actualItemSize);
8946
9063
  }), switchMap$1(i => of((i ?? []).length > 0)), distinctUntilChanged(), tap(v => {
9064
+ readyForAnimations = false;
8947
9065
  if (!v) {
8948
9066
  this.cacheClean();
8949
9067
  this.cleanup();
@@ -9283,12 +9401,22 @@ class NgVirtualListComponent extends DisposableComponent {
9283
9401
  }), debounceTime(100), tap(() => {
9284
9402
  this._isLoading = false;
9285
9403
  })).subscribe();
9404
+ let prevCacheVersion = -1, prevScrollable = false;
9405
+ $viewInit.pipe(takeUntil(this._$unsubscribe), filter$1(v => !!v), switchMap$1(() => {
9406
+ return this.$show.pipe(takeUntil(this._$unsubscribe), debounceTime(Math.max(500, this._$animationParams.getValue().scrollToItem)), tap(() => {
9407
+ if (this._readyForShow || (this.cachable && this._cached)) {
9408
+ readyForAnimations = true;
9409
+ }
9410
+ }));
9411
+ })).subscribe();
9286
9412
  const update = (params) => {
9287
- const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, itemTransform, } = params;
9413
+ const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, cacheVersion, itemTransform, } = params;
9414
+ const cacheChanged = prevCacheVersion !== cacheVersion;
9415
+ prevCacheVersion = cacheVersion;
9288
9416
  const scroller = this._scrollerComponent;
9289
9417
  let totalSize = 0;
9290
9418
  if (!!scroller) {
9291
- const isInfinity = this.isInfinity, collapsable = collapsedIds.length > 0, cachable = this.cachable, cached = this._cached, waitingCache = cachable && !cached, emitUpdate = !this._readyForShow || waitingCache || collapsable || isChunkLoading, fireUpdate = !this._readyForShow || this._$scrollingTo.getValue(), fireUpdateAtEdges = fireUpdate || !isInfinity;
9419
+ const isInfinity = this.isInfinity, collapsable = collapsedIds.length > 0, cachable = this.cachable, cached = this._cached, waitingCache = cachable && !cached, emitUpdate = !this._readyForShow || waitingCache || collapsable || isChunkLoading, fireUpdate = !this._readyForShow || this._$scrollingTo.getValue(), fireUpdateAtEdges = fireUpdate || !isInfinity, useAnimations = !isInfinity && readyForAnimations && prevScrollable;
9292
9420
  if (this._readyForShow || (cachable && cached)) {
9293
9421
  const currentScrollSize = (isVertical ? scroller.scrollTop : scroller.scrollLeft);
9294
9422
  let actualScrollSize = !this._readyForShow && snapScrollToEnd ? (isVertical ? scroller.scrollHeight : scroller.scrollWidth) :
@@ -9332,12 +9460,13 @@ class NgVirtualListComponent extends DisposableComponent {
9332
9460
  if (!_$created.getValue()) {
9333
9461
  _$created.next(true);
9334
9462
  }
9335
- const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.scrollHeight : scroller.scrollWidth;
9463
+ const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.actualScrollHeight : scroller.actualScrollWidth;
9336
9464
  if (this._isSnappingMethodAdvanced) {
9337
9465
  this.updateRegularRenderer();
9338
9466
  }
9339
9467
  this.updateOffsetsByAllignment();
9340
9468
  scroller.delta = delta;
9469
+ prevScrollable = scroller.scrollable;
9341
9470
  if ((snapScrollToStart && this._trackBox.isSnappedToStart && scroller.scrollable) ||
9342
9471
  (snapScrollToStart && currentScrollSize <= MIN_PIXELS_FOR_PREVENT_SNAPPING)) {
9343
9472
  if (currentScrollSize !== roundedScrollPositionAfterUpdate) {
@@ -9348,9 +9477,16 @@ class NgVirtualListComponent extends DisposableComponent {
9348
9477
  this._trackBox.isScrollEnd;
9349
9478
  const params = {
9350
9479
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: 0, userAction,
9351
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT,
9352
- blending: false, duration: this.animationParams.scrollToItem,
9480
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams.scrollToItem > 0 && this.scrollBehavior !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT),
9481
+ blending: useAnimations && scroller.hasAnimation(this._animationId), duration: this.animationParams.scrollToItem,
9353
9482
  };
9483
+ const animationId = scroller?.scrollTo?.(params);
9484
+ if (animationId > -1) {
9485
+ this._animationId = animationId;
9486
+ }
9487
+ else {
9488
+ scroller.stopAnimation(this._animationId);
9489
+ }
9354
9490
  scroller?.scrollTo?.(params);
9355
9491
  if (emitUpdate) {
9356
9492
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
@@ -9371,9 +9507,16 @@ class NgVirtualListComponent extends DisposableComponent {
9371
9507
  }
9372
9508
  const params = {
9373
9509
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: roundedMaxPositionAfterUpdate,
9374
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT, userAction: false,
9375
- blending: false, duration: this.animationParams.scrollToItem,
9510
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams.scrollToItem > 0 && this.scrollBehavior !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT), userAction: false,
9511
+ blending: useAnimations && scroller.hasAnimation(this._animationId) || cacheChanged, duration: this.animationParams.scrollToItem,
9376
9512
  };
9513
+ const animationId = scroller?.scrollTo?.(params);
9514
+ if (animationId > -1) {
9515
+ this._animationId = animationId;
9516
+ }
9517
+ else {
9518
+ scroller.stopAnimation(this._animationId);
9519
+ }
9377
9520
  scroller?.scrollTo?.(params);
9378
9521
  if (emitUpdate) {
9379
9522
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
@@ -9387,9 +9530,13 @@ class NgVirtualListComponent extends DisposableComponent {
9387
9530
  if (this._readyForShow) {
9388
9531
  this.emitScrollEvent(true, false, userAction);
9389
9532
  }
9533
+ if (this._animationId > -1) {
9534
+ scroller.stopAnimation(this._animationId);
9535
+ this._animationId = -1;
9536
+ }
9390
9537
  const params = {
9391
9538
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollPositionAfterUpdate, blending: true, userAction,
9392
- fireUpdate, behavior: BEHAVIOR_INSTANT, duration: this.animationParams.scrollToItem,
9539
+ fireUpdate, behavior: BEHAVIOR_INSTANT, duration: 0,
9393
9540
  };
9394
9541
  scroller.scrollTo(params);
9395
9542
  if (emitUpdate) {
@@ -10104,7 +10251,7 @@ class NgVirtualListComponent extends DisposableComponent {
10104
10251
  comp?.destroy();
10105
10252
  }
10106
10253
  }
10107
- if (this._displayComponents) {
10254
+ if (!!this._displayComponents) {
10108
10255
  while (this._displayComponents.length > 0) {
10109
10256
  const comp = this._displayComponents.shift();
10110
10257
  comp?.destroy();