ng-virtual-list 14.12.2 → 14.12.4

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 (29) hide show
  1. package/README.md +2 -2
  2. package/esm2020/lib/components/ng-list-item/base/base-virtual-list-item-component.mjs +9 -5
  3. package/esm2020/lib/components/ng-list-item/const/index.mjs +2 -1
  4. package/esm2020/lib/components/ng-list-item/ng-virtual-list-item.component.mjs +14 -8
  5. package/esm2020/lib/components/ng-prerender-container/components/ng-prerender-list-item/ng-prerender-list-item.component.mjs +3 -3
  6. package/esm2020/lib/components/ng-scroll-view/ng-scroll-view.component.mjs +20 -14
  7. package/esm2020/lib/components/ng-scroller/ng-scroller.component.mjs +6 -2
  8. package/esm2020/lib/const/index.mjs +6 -3
  9. package/esm2020/lib/core/track-box.mjs +31 -9
  10. package/esm2020/lib/directives/virtual-click/virtual-click.directive.mjs +35 -15
  11. package/esm2020/lib/models/display-object-config.model.mjs +1 -1
  12. package/esm2020/lib/ng-virtual-list.component.mjs +43 -11
  13. package/esm2020/lib/ng-virtual-list.service.mjs +31 -2
  14. package/esm2020/lib/utils/animator/animator.mjs +39 -14
  15. package/fesm2015/ng-virtual-list.mjs +228 -77
  16. package/fesm2015/ng-virtual-list.mjs.map +1 -1
  17. package/fesm2020/ng-virtual-list.mjs +223 -73
  18. package/fesm2020/ng-virtual-list.mjs.map +1 -1
  19. package/lib/components/ng-list-item/base/base-virtual-list-item-component.d.ts +1 -1
  20. package/lib/components/ng-list-item/ng-virtual-list-item.component.d.ts +3 -1
  21. package/lib/components/ng-scroll-view/ng-scroll-view.component.d.ts +5 -2
  22. package/lib/components/ng-scroller/ng-scroller.component.d.ts +1 -1
  23. package/lib/const/index.d.ts +3 -1
  24. package/lib/directives/virtual-click/virtual-click.directive.d.ts +11 -6
  25. package/lib/models/display-object-config.model.d.ts +4 -0
  26. package/lib/ng-virtual-list.component.d.ts +2 -1
  27. package/lib/ng-virtual-list.service.d.ts +13 -0
  28. package/lib/utils/animator/animator.d.ts +11 -2
  29. 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
 
@@ -251,6 +251,7 @@ var TextDirections;
251
251
  TextDirections["LTR"] = "ltr";
252
252
  })(TextDirections || (TextDirections = {}));
253
253
 
254
+ const INVISIBLE_POSITION = -10000;
254
255
  const SERVICE_PROP_DUMMY_ID = '__service-dummy-id__';
255
256
  const SERVICE_PROP_DUMMY = '__service-dummy__';
256
257
  const SERVICE_TYPE_DUMMY = '__service-type-dummy__';
@@ -280,7 +281,7 @@ const DEFAULT_MOTION_BLUR = 0.15;
280
281
  const DEFAULT_MOTION_BLUR_ENABLED = false;
281
282
  const DEFAULT_MAX_MOTION_BLUR = 0.5;
282
283
  const DEFAULT_ANIMATION_PARAMS = {
283
- scrollToItem: 50,
284
+ scrollToItem: 150,
284
285
  snapToItem: 150,
285
286
  navigateToItem: 150,
286
287
  navigateByKeyboard: NAVIGATION_BY_KEYBOARD_TIMER,
@@ -336,13 +337,15 @@ const POSITION$1 = 'position';
336
337
  const POSITION_RELATIVE = 'relative';
337
338
  const POSITION_ABSOLUTE = 'absolute';
338
339
  const TRANSLATE_3D = 'translate3d';
339
- const ZEROS_TRANSLATE_3D = `${TRANSLATE_3D}(0,0,0)`;
340
+ const INVISIBLE_TRANSLATE_3D = `${TRANSLATE_3D}(${INVISIBLE_POSITION},${INVISIBLE_POSITION},0)`;
340
341
  const HIDDEN_ZINDEX = '-1';
341
342
  const DEFAULT_ZINDEX = '0';
342
343
  const TOP_PROP_NAME = 'top';
343
344
  const LEFT_PROP_NAME = 'left';
344
345
  const X_PROP_NAME = 'x';
345
346
  const Y_PROP_NAME = 'y';
347
+ const TRANSFORMED_X_PROP_NAME = 'transformedX';
348
+ const TRANSFORMED_Y_PROP_NAME = 'transformedY';
346
349
  const WIDTH_PROP_NAME = 'width';
347
350
  const HEIGHT_PROP_NAME = 'height';
348
351
  const MARGIN_TOP = 'marginTop';
@@ -496,6 +499,7 @@ const DEFAULT_TEMPLATE_CONTEXT = {
496
499
  isLast: false,
497
500
  fullSize: false,
498
501
  totalItems: 0,
502
+ grabbing: false,
499
503
  },
500
504
  reseted: false,
501
505
  index: -1,
@@ -684,6 +688,14 @@ class NgVirtualListService {
684
688
  this._$langTextDir = new BehaviorSubject$1(TextDirections.LTR);
685
689
  this.$langTextDir = this._$langTextDir.asObservable();
686
690
  this._langTextDir = TextDirections.LTR;
691
+ this._$grabbing = new BehaviorSubject$1(false);
692
+ this.$grabbing = this._$grabbing.asObservable();
693
+ this._grabbing = false;
694
+ this._$clickPressed = new BehaviorSubject$1(false);
695
+ this.$clickPressed = this._$clickPressed.asObservable();
696
+ this._clickPressed = false;
697
+ this._$isGrabbing = new BehaviorSubject$1(false);
698
+ this.$isGrabbing = this._$isGrabbing.asObservable();
687
699
  this._scrollBarSize = 0;
688
700
  this._$scrollBarSize = new BehaviorSubject$1(this._scrollBarSize);
689
701
  this.$scrollBarSize = this._$scrollBarSize.asObservable();
@@ -698,6 +710,10 @@ class NgVirtualListService {
698
710
  this._onTrackBoxChangeHandler = (v) => {
699
711
  this._$cacheVersion.next(v);
700
712
  };
713
+ const $grabbing = this.$grabbing.pipe(takeUntil(this._$unsubscribe), distinctUntilChanged()), $clickPressed = this.$clickPressed.pipe(takeUntil(this._$unsubscribe), distinctUntilChanged());
714
+ combineLatest([$grabbing, $clickPressed]).pipe(takeUntil(this._$unsubscribe), tap(([grabbing, clickPressed]) => {
715
+ this._$isGrabbing.next(grabbing && !clickPressed);
716
+ })).subscribe();
701
717
  this._$selectingMode.pipe(takeUntil(this._$unsubscribe), tap(v => {
702
718
  switch (v) {
703
719
  case SelectingModesTypes.SELECT: {
@@ -748,6 +764,23 @@ class NgVirtualListService {
748
764
  this._langTextDir = v;
749
765
  this._$langTextDir.next(v);
750
766
  }
767
+ get grabbing() { return this._$grabbing.getValue(); }
768
+ set grabbing(v) {
769
+ if (this._grabbing === v) {
770
+ return;
771
+ }
772
+ this._grabbing = v;
773
+ this._$grabbing.next(v);
774
+ }
775
+ get clickPressed() { return this._$clickPressed.getValue(); }
776
+ set clickPressed(v) {
777
+ if (this._clickPressed === v) {
778
+ return;
779
+ }
780
+ this._clickPressed = v;
781
+ this._$clickPressed.next(v);
782
+ }
783
+ get isGrabbing() { return this._$isGrabbing.getValue(); }
751
784
  get scrollBarSize() { return this._$scrollBarSize.getValue(); }
752
785
  set scrollBarSize(v) {
753
786
  if (this._scrollBarSize === v) {
@@ -1226,6 +1259,9 @@ class BaseVirtualListItemComponent extends DisposableComponent {
1226
1259
  this._id = this._service.generateComponentId();
1227
1260
  this._listId = this._service.id;
1228
1261
  this._displayId = createDisplayId(this._listId, this._id);
1262
+ this._service.$isGrabbing.pipe(takeUntil(this._$unsubscribe), tap(v => {
1263
+ this.updateConfig(this._data, v);
1264
+ })).subscribe();
1229
1265
  const $part = this.$part;
1230
1266
  $part.pipe(takeUntil(this._$unsubscribe), tap(part => {
1231
1267
  this._elementRef.nativeElement.setAttribute('part', part);
@@ -1282,7 +1318,7 @@ class BaseVirtualListItemComponent extends DisposableComponent {
1282
1318
  }
1283
1319
  this._data = v;
1284
1320
  this.updatePartStr(v, this._isSelected, this._isCollapsed);
1285
- this.updateConfig(v);
1321
+ this.updateConfig(v, this._service.isGrabbing);
1286
1322
  this.updateMeasures(v);
1287
1323
  this.update();
1288
1324
  this._$data.next(v);
@@ -1320,9 +1356,9 @@ class BaseVirtualListItemComponent extends DisposableComponent {
1320
1356
  this._$measures.next(v?.measures ? { ...v.measures } : null);
1321
1357
  this._cdr.markForCheck();
1322
1358
  }
1323
- updateConfig(v) {
1359
+ updateConfig(v, grabbing) {
1324
1360
  this._$config.next({
1325
- ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this._$focused.getValue(),
1361
+ ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this._$focused.getValue(), grabbing,
1326
1362
  });
1327
1363
  this._cdr.markForCheck();
1328
1364
  }
@@ -1451,6 +1487,7 @@ class BaseVirtualListItemComponent extends DisposableComponent {
1451
1487
  }
1452
1488
  const el = this._elementRef.nativeElement, styles = el.style;
1453
1489
  styles.zIndex = HIDDEN_ZINDEX;
1490
+ styles.transform = INVISIBLE_TRANSLATE_3D;
1454
1491
  if (this.regular) {
1455
1492
  if (styles.display === DISPLAY_NONE) {
1456
1493
  return;
@@ -1483,9 +1520,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
1483
1520
  args: ['container']
1484
1521
  }] } });
1485
1522
 
1486
- const DEFAULT_MAX_DISTANCE = 40;
1487
1523
  /**
1488
- * ItemClickDirective
1524
+ * VirtualClickDirective
1489
1525
  * Maximum performance for extremely large lists.
1490
1526
  * It is based on algorithms for virtualization of screen objects.
1491
1527
  * @link https://github.com/DjonnyX/ng-virtual-list/blob/14.x/projects/ng-virtual-list/src/lib/directives/item-click/item-click.directive.ts
@@ -1493,26 +1529,39 @@ const DEFAULT_MAX_DISTANCE = 40;
1493
1529
  * @email djonnyx@gmail.com
1494
1530
  */
1495
1531
  class VirtualClickDirective {
1496
- constructor(_elementRef) {
1497
- this._elementRef = _elementRef;
1532
+ constructor() {
1498
1533
  this._$unsubscribe = new Subject();
1499
- this._maxDistance = DEFAULT_MAX_DISTANCE;
1534
+ this._$maxDistance = new BehaviorSubject(null);
1535
+ this.$maxDistance = this._$maxDistance.asObservable();
1536
+ this._maxDistance = null;
1500
1537
  this.onVirtualClick = new EventEmitter$1();
1538
+ this.onVirtualClickPress = new EventEmitter$1();
1539
+ this.onVirtualClickCancel = new EventEmitter$1();
1540
+ this._service = inject(NgVirtualListService);
1541
+ this._elementRef = inject(ElementRef);
1542
+ let maxDistance = this._maxDistance ?? DEFAULT_CLICK_DISTANCE;
1543
+ combineLatest([this._service.$clickDistance, this.$maxDistance]).pipe(takeUntil$1(this._$unsubscribe), tap$1(([clickDistance, distance]) => {
1544
+ maxDistance = distance === null ? clickDistance : distance;
1545
+ })).subscribe();
1501
1546
  const $pointerPressed = fromEvent(this._elementRef.nativeElement, 'pointerdown'), $pointerCancel = race([
1502
1547
  fromEvent(window, 'pointerup').pipe(takeUntil$1(this._$unsubscribe)),
1503
1548
  fromEvent(window, 'pointerleave').pipe(takeUntil$1(this._$unsubscribe)),
1504
1549
  ]), $pointerRelease = fromEvent(this._elementRef.nativeElement, 'pointerup', { passive: false });
1505
1550
  $pointerPressed.pipe(takeUntil$1(this._$unsubscribe), switchMap(e => {
1506
1551
  const x = Math.abs(e.clientX), y = Math.abs(e.clientY);
1552
+ this.onVirtualClickPress.emit(e);
1507
1553
  return $pointerRelease.pipe(takeUntil$1(this._$unsubscribe), takeUntil$1(race([
1508
- $pointerCancel,
1554
+ $pointerCancel.pipe(takeUntil$1(this._$unsubscribe), tap$1(() => {
1555
+ this.onVirtualClickCancel.emit();
1556
+ })),
1509
1557
  fromEvent(window, 'pointermove').pipe(takeUntil$1(this._$unsubscribe), switchMap(e => {
1510
1558
  const xx = x - Math.abs(e.clientX), yy = y - Math.abs(e.clientY), dist = Math.sqrt(Math.pow(xx, 2) + Math.pow(yy, 2));
1511
- if (dist > this._maxDistance) {
1559
+ if (dist > maxDistance) {
1560
+ this.onVirtualClickCancel.emit();
1512
1561
  return of(true);
1513
1562
  }
1514
1563
  return of(false);
1515
- }), takeUntil$1(this._$unsubscribe), filter(v => !!v)),
1564
+ }), filter(v => !!v)),
1516
1565
  ])), takeUntil$1(this._$unsubscribe), tap$1(e => {
1517
1566
  if (e) {
1518
1567
  this.onVirtualClick.emit(e);
@@ -1521,7 +1570,9 @@ class VirtualClickDirective {
1521
1570
  })).subscribe();
1522
1571
  }
1523
1572
  set maxDistance(v) {
1524
- this._maxDistance = (v !== null || v !== undefined) ? Number(v) : DEFAULT_MAX_DISTANCE;
1573
+ const value = (v !== null || v !== undefined) ? Number(v) : null;
1574
+ this._maxDistance = value;
1575
+ this._$maxDistance.next(value);
1525
1576
  }
1526
1577
  ngOnDestroy() {
1527
1578
  if (this._$unsubscribe) {
@@ -1530,19 +1581,23 @@ class VirtualClickDirective {
1530
1581
  }
1531
1582
  }
1532
1583
  }
1533
- VirtualClickDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: VirtualClickDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
1534
- VirtualClickDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: VirtualClickDirective, selector: "[virtualClick]", inputs: { maxDistance: ["maxClickDistance", "maxDistance"] }, outputs: { onVirtualClick: "onVirtualClick" }, ngImport: i0 });
1584
+ VirtualClickDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: VirtualClickDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1585
+ VirtualClickDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: VirtualClickDirective, selector: "[virtualClick]", inputs: { maxDistance: ["maxClickDistance", "maxDistance"] }, outputs: { onVirtualClick: "onVirtualClick", onVirtualClickPress: "onVirtualClickPress", onVirtualClickCancel: "onVirtualClickCancel" }, ngImport: i0 });
1535
1586
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: VirtualClickDirective, decorators: [{
1536
1587
  type: Directive,
1537
1588
  args: [{
1538
1589
  selector: '[virtualClick]',
1539
1590
  standalone: false,
1540
1591
  }]
1541
- }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { maxDistance: [{
1592
+ }], ctorParameters: function () { return []; }, propDecorators: { maxDistance: [{
1542
1593
  type: Input,
1543
1594
  args: ['maxClickDistance']
1544
1595
  }], onVirtualClick: [{
1545
1596
  type: Output
1597
+ }], onVirtualClickPress: [{
1598
+ type: Output
1599
+ }], onVirtualClickCancel: [{
1600
+ type: Output
1546
1601
  }] } });
1547
1602
 
1548
1603
  /**
@@ -1574,12 +1629,12 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1574
1629
  fromEvent(this.element, EVENT_FOCUS_IN).pipe(takeUntil(this._$unsubscribe), tap(e => {
1575
1630
  this._service.focusedId = this.itemId ?? null;
1576
1631
  this._$focused.next(true);
1577
- this.updateConfig(this._data);
1632
+ this.updateConfig(this._data, this._service.isGrabbing);
1578
1633
  this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
1579
1634
  })).subscribe(),
1580
1635
  fromEvent(this.element, EVENT_FOCUS_OUT).pipe(takeUntil(this._$unsubscribe), tap(e => {
1581
1636
  this._$focused.next(false);
1582
- this.updateConfig(this._data);
1637
+ this.updateConfig(this._data, this._service.isGrabbing);
1583
1638
  this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
1584
1639
  })).subscribe();
1585
1640
  $focused.pipe(takeUntil(this._$unsubscribe), debounceTime(this.getNavigationTimeout()), switchMap$1(v => {
@@ -1612,7 +1667,7 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1612
1667
  const actualIds = collapsedIds, isCollapsed = this.itemId !== undefined && actualIds && actualIds.includes(this.itemId);
1613
1668
  this._isCollapsed = isCollapsed;
1614
1669
  this.updatePartStr(this._data, this._isSelected, isCollapsed);
1615
- this.updateConfig(this._data);
1670
+ this.updateConfig(this._data, this._service.isGrabbing);
1616
1671
  this.updateMeasures(this._data);
1617
1672
  })).subscribe();
1618
1673
  }
@@ -1715,24 +1770,30 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1715
1770
  }
1716
1771
  return Number.MIN_SAFE_INTEGER;
1717
1772
  }
1718
- updateConfig(v) {
1773
+ updateConfig(v, grabbing) {
1719
1774
  this._$config.next({
1720
- ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this._$focused.getValue(),
1775
+ ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this._$focused.getValue(), grabbing,
1721
1776
  });
1722
1777
  this._cdr.markForCheck();
1723
1778
  }
1724
1779
  onClickHandler() {
1725
1780
  this._service.virtualClick(this._data);
1726
1781
  }
1782
+ onClickPressHandler() {
1783
+ this._service.clickPressed = true;
1784
+ }
1785
+ onClickCancelHandler() {
1786
+ this._service.clickPressed = false;
1787
+ }
1727
1788
  }
1728
1789
  NgVirtualListItemComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgVirtualListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1729
- NgVirtualListItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", 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 });
1790
+ NgVirtualListItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", 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 });
1730
1791
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
1731
1792
  type: Component,
1732
1793
  args: [{ selector: 'ng-virtual-list-item', host: {
1733
1794
  'class': 'ngvl__item',
1734
1795
  '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"] }]
1796
+ }, 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
1797
  }], ctorParameters: function () { return []; } });
1737
1798
 
1738
1799
  /**
@@ -3286,7 +3347,7 @@ class TrackBox extends CacheMap {
3286
3347
  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 = [];
3287
3348
  if (items.length) {
3288
3349
  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;
3289
- let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0;
3350
+ let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, nexstStickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0;
3290
3351
  const li = layoutIndexOffset + actualItems.length - 1;
3291
3352
  if (stickyEnabled) {
3292
3353
  for (let i = Math.min(itemsFromStartToScrollEnd > 0 ? (divides > 1 ? (itemsFromStartToScrollEnd - 1) : itemsFromStartToScrollEnd) : 0, totalLength - 1); i >= 0; i--) {
@@ -3546,6 +3607,7 @@ class TrackBox extends CacheMap {
3546
3607
  item.measures.x = isVertical ? 0 : snapped ? actualSnippedPosition : pos;
3547
3608
  item.measures.y = isVertical ? snapped ? actualSnippedPosition : pos : 0;
3548
3609
  nextSticky = item;
3610
+ nexstStickyItemIndex = displayItems.length;
3549
3611
  nextSticky.config.snapped = snapped;
3550
3612
  nextSticky.measures.delta = (isVertical ? item.measures.y : item.measures.x) - scrollSize;
3551
3613
  nextSticky.config.zIndex = Z_INDEX_3;
@@ -3568,10 +3630,10 @@ class TrackBox extends CacheMap {
3568
3630
  }
3569
3631
  i++;
3570
3632
  }
3571
- const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME;
3633
+ const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME, transformedAxis = isVertical ? TRANSFORMED_Y_PROP_NAME : TRANSFORMED_X_PROP_NAME;
3572
3634
  if (!!nextSticky && !!stickyItem && nextSticky.measures[axis] <= actualSnippedPosition + stickyItem.measures[sizeProperty]) {
3573
3635
  if (nextSticky.measures[axis] > actualSnippedPosition) {
3574
- stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3636
+ stickyItem.measures[axis] = stickyItem.measures[transformedAxis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3575
3637
  stickyItem.config.snapped = nextSticky.config.snapped = false;
3576
3638
  stickyItem.config.snappedOut = true;
3577
3639
  stickyItem.config.sticky = 1;
@@ -3580,14 +3642,35 @@ class TrackBox extends CacheMap {
3580
3642
  else {
3581
3643
  nextSticky.config.snapped = true;
3582
3644
  nextSticky.measures.delta = (isVertical ? nextSticky.measures.y : nextSticky.measures.x) - scrollSize;
3583
- stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3645
+ stickyItem.measures[axis] = stickyItem.measures[transformedAxis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3584
3646
  stickyItem.measures.delta = (isVertical ? stickyItem.measures.y : stickyItem.measures.x) - scrollSize;
3647
+ const lastStickyItem = displayItems?.[nexstStickyItemIndex + 1];
3648
+ if (lastStickyItem?.config?.sticky === 1 && displayItems?.[nexstStickyItemIndex + 2]?.config?.sticky !== 1) {
3649
+ nextSticky.config.snapped = nextSticky.config.snappedOut = false;
3650
+ stickyItem.config.snappedOut = true;
3651
+ nextSticky.measures.delta = this._scrollStartOffset;
3652
+ if (lastStickyItem.measures[axis] <= actualSnippedPosition) {
3653
+ lastStickyItem.config.snapped = lastStickyItem.config.snappedOut = true;
3654
+ lastStickyItem.measures[axis] = lastStickyItem.measures[transformedAxis] = lastStickyItem.measures.position = actualSnippedPosition;
3655
+ lastStickyItem.measures.delta = this._scrollStartOffset;
3656
+ }
3657
+ }
3658
+ else if (lastStickyItem?.config?.sticky !== 1 && displayItems?.[nexstStickyItemIndex + 2]?.config?.sticky !== 1) {
3659
+ if (nextSticky.measures[axis] <= actualSnippedPosition) {
3660
+ nextSticky.config.snapped = nextSticky.config.snappedOut = true;
3661
+ nextSticky.measures[axis] = nextSticky.measures[transformedAxis] = nextSticky.measures.position = actualSnippedPosition;
3662
+ nextSticky.measures.delta = this._scrollStartOffset;
3663
+ }
3664
+ }
3665
+ else {
3666
+ nextSticky.config.snapped = nextSticky.config.snappedOut = false;
3667
+ }
3585
3668
  }
3586
3669
  }
3587
3670
  if (!!nextEndSticky && !!endStickyItem &&
3588
3671
  (nextEndSticky.measures[axis] >= actualEndSnippedPosition - endStickyItemSize - nextEndSticky.measures[sizeProperty])) {
3589
3672
  if (nextEndSticky.measures[axis] < actualEndSnippedPosition - nextEndSticky.measures[sizeProperty]) {
3590
- endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3673
+ endStickyItem.measures[axis] = endStickyItem.measures[transformedAxis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3591
3674
  endStickyItem.config.snapped = nextEndSticky.config.snapped = false;
3592
3675
  endStickyItem.config.snappedOut = true;
3593
3676
  endStickyItem.config.sticky = 2;
@@ -3595,9 +3678,9 @@ class TrackBox extends CacheMap {
3595
3678
  }
3596
3679
  else {
3597
3680
  nextEndSticky.config.snapped = true;
3598
- nextEndSticky.measures[axis] = actualEndSnippedPosition - nextEndSticky.measures[sizeProperty];
3681
+ nextEndSticky.measures[axis] = nextEndSticky.measures[transformedAxis] = actualEndSnippedPosition - nextEndSticky.measures[sizeProperty];
3599
3682
  nextEndSticky.measures.delta = (isVertical ? nextEndSticky.measures.y : nextEndSticky.measures.x) - scrollSize;
3600
- endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3683
+ endStickyItem.measures[axis] = endStickyItem.measures[transformedAxis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3601
3684
  endStickyItem.measures.delta = (isVertical ? endStickyItem.measures.y : endStickyItem.measures.x) - scrollSize;
3602
3685
  }
3603
3686
  }
@@ -3871,18 +3954,34 @@ class Animator {
3871
3954
  constructor() {
3872
3955
  this._animationId = 0;
3873
3956
  this._currentId = Animator._nextId;
3874
- }
3957
+ this._diff = 0;
3958
+ this._startValue = 0;
3959
+ this._endValue = 0;
3960
+ this._prevPos = 0;
3961
+ }
3962
+ get animated() { return this._animationId > -1; }
3963
+ get isAnimated() { return this.hasAnimation(this._currentId); }
3964
+ get id() { return this._currentId; }
3875
3965
  generateId() {
3876
3966
  return Animator._nextId = Animator._nextId === Number.MAX_SAFE_INTEGER
3877
3967
  ? 0 : Animator._nextId + 1;
3878
3968
  }
3969
+ updateTo(end) {
3970
+ this._endValue = end;
3971
+ this._diff = this._endValue - this._startValue;
3972
+ return this.hasAnimation();
3973
+ }
3879
3974
  animate(params) {
3880
3975
  this.stop();
3881
3976
  const id = this.generateId();
3882
3977
  this._currentId = id;
3883
3978
  const { withDelta = DEFAULT_WITH_DELTA, startValue, endValue, duration = DEFAULT_ANIMATION_DURATION, getPropValue, easingFunction = easeLinear, onUpdate, onComplete, } = params;
3979
+ this._startValue = startValue;
3980
+ this._endValue = endValue;
3884
3981
  const startTime = performance.now();
3885
- let isCanceled = false, prevPos = startValue, start = startValue, startPosDelta = 0, delta = 0, prevTime = startTime, diff = endValue - start, isFinished = false;
3982
+ let isCanceled = false, startPosDelta = 0, delta = 0, prevTime = startTime, isFinished = false;
3983
+ this._prevPos = startValue;
3984
+ this._diff = this._endValue - this._startValue;
3886
3985
  const step = (currentTime) => {
3887
3986
  if (id !== this._currentId) {
3888
3987
  isCanceled = true;
@@ -3892,34 +3991,35 @@ class Animator {
3892
3991
  }
3893
3992
  const cPos = getPropValue?.() || 0;
3894
3993
  let startDelta = 0;
3895
- if (cPos !== prevPos) {
3896
- startDelta = cPos - prevPos;
3994
+ if (cPos !== this._prevPos) {
3995
+ startDelta = cPos - this._prevPos;
3897
3996
  startPosDelta += startDelta;
3898
3997
  }
3899
- 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();
3998
+ const elapsed = currentTime - startTime, progress = this._startValue === this._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();
3900
3999
  isFinished = progress === 1;
3901
- delta = currentValue - startDelta - prevPos;
3902
- const ts = t - prevTime, timestamp = ts < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : ts;
4000
+ delta = currentValue - startDelta - this._prevPos;
4001
+ const frameTimestamp = t - prevTime, actualFrameTimestamp = frameTimestamp < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : frameTimestamp;
3903
4002
  prevTime = t;
3904
- prevPos = currentValue;
4003
+ this._prevPos = currentValue;
3905
4004
  if (onUpdate !== undefined) {
3906
4005
  const data = {
3907
4006
  id,
3908
4007
  delta,
3909
4008
  elapsed,
3910
- value: !withDelta && isFinished ? endValue : currentValue,
3911
- timestamp,
4009
+ value: currentValue,
4010
+ timestamp: actualFrameTimestamp,
3912
4011
  };
3913
4012
  onUpdate(data);
3914
4013
  }
3915
4014
  if (isFinished) {
4015
+ this._animationId = -1;
3916
4016
  if (onComplete !== undefined) {
3917
4017
  const data = {
3918
4018
  id,
3919
4019
  delta,
3920
4020
  elapsed,
3921
- value: withDelta ? currentValue : endValue,
3922
- timestamp,
4021
+ value: currentValue,
4022
+ timestamp: actualFrameTimestamp,
3923
4023
  };
3924
4024
  onComplete(data);
3925
4025
  }
@@ -3929,9 +4029,17 @@ class Animator {
3929
4029
  }
3930
4030
  };
3931
4031
  this._animationId = requestAnimationFrame(step);
4032
+ return this._currentId;
4033
+ }
4034
+ hasAnimation(id = -1) {
4035
+ if ((this._currentId === id || id === -1) && this.animated) {
4036
+ return true;
4037
+ }
4038
+ return false;
3932
4039
  }
3933
- stop() {
3934
- cancelAnimationFrame(this._animationId);
4040
+ stop(id = -1) {
4041
+ cancelAnimationFrame(id === -1 ? this._animationId : id);
4042
+ this._animationId = -1;
3935
4043
  }
3936
4044
  dispose() {
3937
4045
  this.stop();
@@ -4518,6 +4626,7 @@ class NgScrollView extends BaseScrollView {
4518
4626
  }
4519
4627
  }
4520
4628
  get startLayoutOffset() { return this._startLayoutOffset; }
4629
+ get animated() { return this._animator?.isAnimated ?? false; }
4521
4630
  ngAfterViewInit() {
4522
4631
  let mouseCanceled = false, touchCanceled = false;
4523
4632
  const $viewportBounds = this.$viewportBounds;
@@ -4708,6 +4817,7 @@ class NgScrollView extends BaseScrollView {
4708
4817
  }));
4709
4818
  })).subscribe();
4710
4819
  }
4820
+ hasAnimation(id = -1) { return this._animator?.hasAnimation(id) ?? false; }
4711
4821
  updateDirection(position, prePosition) {
4712
4822
  const delta = (position - this._delta) - prePosition;
4713
4823
  this._scrollDirection.add(delta > 0 ? 1 : delta < 0 ? -1 : 0);
@@ -4870,7 +4980,7 @@ class NgScrollView extends BaseScrollView {
4870
4980
  moveWithAcceleration(isVertical, position, v0, v, a0, timestamp) {
4871
4981
  if (a0 !== 0 && timestamp < MAX_VELOCITY_TIMESTAMP) {
4872
4982
  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;
4873
- this.animate(startPosition, Math.round(positionWithVelocity), aDuration, easeOutQuad, true);
4983
+ this.animate(startPosition, Math.round(positionWithVelocity), aDuration, easeOutQuad, false, true);
4874
4984
  }
4875
4985
  else {
4876
4986
  this.alignPosition(true, true);
@@ -4883,11 +4993,17 @@ class NgScrollView extends BaseScrollView {
4883
4993
  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;
4884
4994
  return result;
4885
4995
  }
4886
- animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
4996
+ animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, blending = false, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
4887
4997
  const isVertical = this._$isVertical.getValue();
4888
4998
  let position = startValue;
4889
4999
  this._isAlignmentAnimation = !alignmentAtComplete;
4890
- this._animator.animate({
5000
+ if (this.hasAnimation() && blending) {
5001
+ const updatable = this._animator.updateTo(endValue);
5002
+ if (updatable) {
5003
+ return this._animator.id;
5004
+ }
5005
+ }
5006
+ return this._animator.animate({
4891
5007
  withDelta: this._service.dynamic && !this.isInfinity,
4892
5008
  startValue,
4893
5009
  endValue,
@@ -4899,7 +5015,7 @@ class NgScrollView extends BaseScrollView {
4899
5015
  if (this._isCoordinatesOverrided && !skipOverridedCoordinates) {
4900
5016
  this._isCoordinatesOverrided = false;
4901
5017
  const currentCoordinate = isVertical ? this._y : this._x, delta = endValue - value;
4902
- this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, userAction, alignmentAtComplete);
5018
+ this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, blending, userAction, alignmentAtComplete);
4903
5019
  return;
4904
5020
  }
4905
5021
  const v0 = calculateVelocity(position, value - this._delta, timestamp) ?? this.averageVelocity;
@@ -5031,7 +5147,7 @@ class NgScrollView extends BaseScrollView {
5031
5147
  const cPos = (isVertical ? this.scrollTop : this.scrollLeft);
5032
5148
  if (position !== null && position !== cPos) {
5033
5149
  this.stopScrolling(true);
5034
- this.animate(cPos, position, animated ? this.animationParams.snapToItem : 1, easeOutQuad, false, false, true);
5150
+ this.animate(cPos, position, animated ? this._$animationParams.getValue().snapToItem : 1, easeOutQuad, false, false, false, true);
5035
5151
  return true;
5036
5152
  }
5037
5153
  return false;
@@ -5117,21 +5233,18 @@ class NgScrollView extends BaseScrollView {
5117
5233
  if (behavior === AUTO || behavior === SMOOTH) {
5118
5234
  if (isVertical) {
5119
5235
  if (prevY !== y) {
5120
- this.animate(prevY, y, duration, ease, userAction);
5236
+ return this.animate(prevY, y, duration, ease, blending, userAction);
5121
5237
  }
5122
5238
  }
5123
5239
  else {
5124
5240
  if (prevX !== x) {
5125
- this.animate(prevX, x, duration, ease, userAction);
5241
+ return this.animate(prevX, x, duration, ease, blending, userAction);
5126
5242
  }
5127
5243
  }
5128
5244
  }
5129
5245
  else {
5130
5246
  if (isVertical) {
5131
5247
  if (this._y !== y || force) {
5132
- if (!blending) {
5133
- this.stopScrolling(force);
5134
- }
5135
5248
  this.setY(y, snap, normalize);
5136
5249
  this.emitScrollableEvent();
5137
5250
  if (fireUpdate) {
@@ -5141,9 +5254,6 @@ class NgScrollView extends BaseScrollView {
5141
5254
  }
5142
5255
  else {
5143
5256
  if (this._x !== x || force) {
5144
- if (!blending) {
5145
- this.stopScrolling(force);
5146
- }
5147
5257
  this.setX(x, snap, normalize);
5148
5258
  this.emitScrollableEvent();
5149
5259
  if (fireUpdate) {
@@ -5152,6 +5262,7 @@ class NgScrollView extends BaseScrollView {
5152
5262
  }
5153
5263
  }
5154
5264
  }
5265
+ return -1;
5155
5266
  }
5156
5267
  emitScrollableEvent() {
5157
5268
  if (!!this.cdkScrollable) {
@@ -5170,6 +5281,9 @@ class NgScrollView extends BaseScrollView {
5170
5281
  this.stopScrolling();
5171
5282
  this.move(this._$isVertical.getValue(), offset);
5172
5283
  }
5284
+ stopAnimation(id) {
5285
+ this._animator.stop(id);
5286
+ }
5173
5287
  ngOnDestroy() {
5174
5288
  super.ngOnDestroy();
5175
5289
  if (this._animator) {
@@ -5836,6 +5950,10 @@ class NgScrollerComponent extends NgScrollView {
5836
5950
  $updateScrollBar.pipe(takeUntil(this._$unsubscribe), debounceTime(0), tap(() => {
5837
5951
  this.updateScrollBarHandler(!this._isScrollbarUserAction);
5838
5952
  })).subscribe();
5953
+ const $grabbing = this.$grabbing;
5954
+ $grabbing.pipe(takeUntil(this._$unsubscribe), tap(v => {
5955
+ this._service.grabbing = v;
5956
+ })).subscribe();
5839
5957
  combineLatest([this.$classes, this.$direction, this.$grabbing, this.$motionBlurEnabled]).pipe(takeUntil(this._$unsubscribe), distinctUntilChanged(), debounceTime(0), tap(([classes, direction, grabbing, filtered]) => {
5840
5958
  this._$actualClasses.next({ ...classes, [direction]: true, grabbing, filtered });
5841
5959
  })).subscribe();
@@ -5973,7 +6091,7 @@ class NgScrollerComponent extends NgScrollView {
5973
6091
  this._isScrollbarUserAction = false;
5974
6092
  this.scrollBar?.stopScrolling();
5975
6093
  }
5976
- this.scroll({ ...params, userAction: userAction });
6094
+ return this.scroll({ ...params, userAction: userAction });
5977
6095
  }
5978
6096
  stopScrollbar() {
5979
6097
  if (!!this.scrollBar) {
@@ -6377,13 +6495,13 @@ class NgPrerenderVirtualListItemComponent extends NgVirtualListItemComponent {
6377
6495
  }
6378
6496
  }
6379
6497
  NgPrerenderVirtualListItemComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgPrerenderVirtualListItemComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
6380
- NgPrerenderVirtualListItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", 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 });
6498
+ NgPrerenderVirtualListItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", 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 });
6381
6499
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgPrerenderVirtualListItemComponent, decorators: [{
6382
6500
  type: Component,
6383
6501
  args: [{ selector: 'ng-prerender-virtual-list-item', host: {
6384
6502
  'class': 'ngvl__item',
6385
6503
  'role': 'listitem',
6386
- }, 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"] }]
6504
+ }, 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"] }]
6387
6505
  }] });
6388
6506
 
6389
6507
  /**
@@ -7912,6 +8030,7 @@ class NgVirtualListComponent extends DisposableComponent {
7912
8030
  this._readyForShow = false;
7913
8031
  this._cached = false;
7914
8032
  this._isLoading = false;
8033
+ this._animationId = -1;
7915
8034
  this._$viewInit = new BehaviorSubject(false);
7916
8035
  this.$viewInit = this._$viewInit.asObservable();
7917
8036
  this._$destroy = new Subject();
@@ -8441,7 +8560,7 @@ class NgVirtualListComponent extends DisposableComponent {
8441
8560
  ;
8442
8561
  get motionBlurEnabled() { return this._$motionBlurEnabled.getValue(); }
8443
8562
  /**
8444
- * Animation parameters. The default value is "{ scrollToItem: 50, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
8563
+ * Animation parameters. The default value is "{ scrollToItem: 150, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
8445
8564
  */
8446
8565
  set animationParams(v) {
8447
8566
  if (this._$animationParams.getValue() === v) {
@@ -8728,6 +8847,7 @@ class NgVirtualListComponent extends DisposableComponent {
8728
8847
  return this.dynamicSize && (this._trackBox?.isSnappedToEnd ?? false);
8729
8848
  }
8730
8849
  ngAfterViewInit() {
8850
+ let readyForAnimations = false;
8731
8851
  const _$created = new BehaviorSubject(false), $created = _$created.asObservable();
8732
8852
  combineLatest([$created, this.$show]).pipe(takeUntil(this._$unsubscribe), filter$1(([created, shown]) => created && shown), debounceTime(1), tap(v => {
8733
8853
  this._$initialized.next(true);
@@ -8920,6 +9040,7 @@ class NgVirtualListComponent extends DisposableComponent {
8920
9040
  }), tap(items => {
8921
9041
  this._trackBox.resetCollection(items, this.actualItemSize);
8922
9042
  }), switchMap$1(i => of((i ?? []).length > 0)), distinctUntilChanged(), tap(v => {
9043
+ readyForAnimations = false;
8923
9044
  if (!v) {
8924
9045
  this.cacheClean();
8925
9046
  this.cleanup();
@@ -9259,12 +9380,22 @@ class NgVirtualListComponent extends DisposableComponent {
9259
9380
  }), debounceTime(100), tap(() => {
9260
9381
  this._isLoading = false;
9261
9382
  })).subscribe();
9383
+ let prevCacheVersion = -1, prevScrollable = false;
9384
+ $viewInit.pipe(takeUntil(this._$unsubscribe), filter$1(v => !!v), switchMap$1(() => {
9385
+ return this.$show.pipe(takeUntil(this._$unsubscribe), debounceTime(Math.max(500, this._$animationParams.getValue().scrollToItem)), tap(() => {
9386
+ if (this._readyForShow || (this.cachable && this._cached)) {
9387
+ readyForAnimations = true;
9388
+ }
9389
+ }));
9390
+ })).subscribe();
9262
9391
  const update = (params) => {
9263
- const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, itemTransform, } = params;
9392
+ const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, cacheVersion, itemTransform, } = params;
9393
+ const cacheChanged = prevCacheVersion !== cacheVersion;
9394
+ prevCacheVersion = cacheVersion;
9264
9395
  const scroller = this._scrollerComponent;
9265
9396
  let totalSize = 0;
9266
9397
  if (!!scroller) {
9267
- 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;
9398
+ 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;
9268
9399
  if (this._readyForShow || (cachable && cached)) {
9269
9400
  const currentScrollSize = (isVertical ? scroller.scrollTop : scroller.scrollLeft);
9270
9401
  let actualScrollSize = !this._readyForShow && snapScrollToEnd ? (isVertical ? scroller.scrollHeight : scroller.scrollWidth) :
@@ -9308,12 +9439,13 @@ class NgVirtualListComponent extends DisposableComponent {
9308
9439
  if (!_$created.getValue()) {
9309
9440
  _$created.next(true);
9310
9441
  }
9311
- const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.scrollHeight : scroller.scrollWidth;
9442
+ const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.actualScrollHeight : scroller.actualScrollWidth;
9312
9443
  if (this._isSnappingMethodAdvanced) {
9313
9444
  this.updateRegularRenderer();
9314
9445
  }
9315
9446
  this.updateOffsetsByAllignment();
9316
9447
  scroller.delta = delta;
9448
+ prevScrollable = scroller.scrollable;
9317
9449
  if ((snapScrollToStart && this._trackBox.isSnappedToStart && scroller.scrollable) ||
9318
9450
  (snapScrollToStart && currentScrollSize <= MIN_PIXELS_FOR_PREVENT_SNAPPING)) {
9319
9451
  if (currentScrollSize !== roundedScrollPositionAfterUpdate) {
@@ -9324,9 +9456,16 @@ class NgVirtualListComponent extends DisposableComponent {
9324
9456
  this._trackBox.isScrollEnd;
9325
9457
  const params = {
9326
9458
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: 0, userAction,
9327
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT,
9328
- blending: false, duration: this.animationParams.scrollToItem,
9459
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams.scrollToItem > 0 && this.scrollBehavior !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT),
9460
+ blending: useAnimations && scroller.hasAnimation(this._animationId), duration: this.animationParams.scrollToItem,
9329
9461
  };
9462
+ const animationId = scroller?.scrollTo?.(params);
9463
+ if (animationId > -1) {
9464
+ this._animationId = animationId;
9465
+ }
9466
+ else {
9467
+ scroller.stopAnimation(this._animationId);
9468
+ }
9330
9469
  scroller?.scrollTo?.(params);
9331
9470
  if (emitUpdate) {
9332
9471
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
@@ -9347,9 +9486,16 @@ class NgVirtualListComponent extends DisposableComponent {
9347
9486
  }
9348
9487
  const params = {
9349
9488
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: roundedMaxPositionAfterUpdate,
9350
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT, userAction: false,
9351
- blending: false, duration: this.animationParams.scrollToItem,
9489
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams.scrollToItem > 0 && this.scrollBehavior !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT), userAction: false,
9490
+ blending: useAnimations && scroller.hasAnimation(this._animationId) || cacheChanged, duration: this.animationParams.scrollToItem,
9352
9491
  };
9492
+ const animationId = scroller?.scrollTo?.(params);
9493
+ if (animationId > -1) {
9494
+ this._animationId = animationId;
9495
+ }
9496
+ else {
9497
+ scroller.stopAnimation(this._animationId);
9498
+ }
9353
9499
  scroller?.scrollTo?.(params);
9354
9500
  if (emitUpdate) {
9355
9501
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
@@ -9363,9 +9509,13 @@ class NgVirtualListComponent extends DisposableComponent {
9363
9509
  if (this._readyForShow) {
9364
9510
  this.emitScrollEvent(true, false, userAction);
9365
9511
  }
9512
+ if (this._animationId > -1) {
9513
+ scroller.stopAnimation(this._animationId);
9514
+ this._animationId = -1;
9515
+ }
9366
9516
  const params = {
9367
9517
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollPositionAfterUpdate, blending: true, userAction,
9368
- fireUpdate, behavior: BEHAVIOR_INSTANT, duration: this.animationParams.scrollToItem,
9518
+ fireUpdate, behavior: BEHAVIOR_INSTANT, duration: 0,
9369
9519
  };
9370
9520
  scroller.scrollTo(params);
9371
9521
  if (emitUpdate) {
@@ -10080,7 +10230,7 @@ class NgVirtualListComponent extends DisposableComponent {
10080
10230
  comp?.destroy();
10081
10231
  }
10082
10232
  }
10083
- if (this._displayComponents) {
10233
+ if (!!this._displayComponents) {
10084
10234
  while (this._displayComponents.length > 0) {
10085
10235
  const comp = this._displayComponents.shift();
10086
10236
  comp?.destroy();