ng-virtual-list 21.12.2 → 21.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.
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, inject, viewChild, signal, ElementRef, DestroyRef, effect, computed, ChangeDetectionStrategy, Component, output, Input, Directive, Injector, InjectionToken, input, ViewChild, ViewContainerRef, ViewEncapsulation, NO_ERRORS_SCHEMA, NgModule } from '@angular/core';
3
- import { Subject, BehaviorSubject, tap, map, fromEvent, race, of, debounceTime, switchMap as switchMap$1, combineLatest, filter as filter$1, delay, takeUntil as takeUntil$1, startWith, from, distinctUntilChanged, take, skip } from 'rxjs';
3
+ import { Subject, BehaviorSubject, distinctUntilChanged, combineLatest, tap, map, fromEvent, race, of, debounceTime, switchMap as switchMap$1, filter as filter$1, delay, takeUntil as takeUntil$1, startWith, from, take, skip } from 'rxjs';
4
4
  import { takeUntilDestroyed, toSignal, toObservable } from '@angular/core/rxjs-interop';
5
5
  import { BehaviorSubject as BehaviorSubject$1 } from 'rxjs/internal/BehaviorSubject';
6
6
  import * as i1 from '@angular/common';
7
7
  import { CommonModule } from '@angular/common';
8
- import { switchMap, takeUntil, filter, tap as tap$1 } from 'rxjs/operators';
8
+ import { tap as tap$1, switchMap, takeUntil, filter } from 'rxjs/operators';
9
9
  import * as i4 from '@angular/cdk/scrolling';
10
10
  import { CdkScrollable, CdkScrollableModule } from '@angular/cdk/scrolling';
11
11
 
@@ -248,6 +248,7 @@ var TextDirections;
248
248
  TextDirections["LTR"] = "ltr";
249
249
  })(TextDirections || (TextDirections = {}));
250
250
 
251
+ const INVISIBLE_POSITION = -10000;
251
252
  const SERVICE_PROP_DUMMY_ID = '__service-dummy-id__';
252
253
  const SERVICE_PROP_DUMMY = '__service-dummy__';
253
254
  const SERVICE_TYPE_DUMMY = '__service-type-dummy__';
@@ -277,7 +278,7 @@ const DEFAULT_MOTION_BLUR = 0.15;
277
278
  const DEFAULT_MOTION_BLUR_ENABLED = false;
278
279
  const DEFAULT_MAX_MOTION_BLUR = 0.5;
279
280
  const DEFAULT_ANIMATION_PARAMS = {
280
- scrollToItem: 50,
281
+ scrollToItem: 150,
281
282
  snapToItem: 150,
282
283
  navigateToItem: 150,
283
284
  navigateByKeyboard: NAVIGATION_BY_KEYBOARD_TIMER,
@@ -333,13 +334,15 @@ const POSITION$1 = 'position';
333
334
  const POSITION_RELATIVE = 'relative';
334
335
  const POSITION_ABSOLUTE = 'absolute';
335
336
  const TRANSLATE_3D = 'translate3d';
336
- const ZEROS_TRANSLATE_3D = `${TRANSLATE_3D}(0,0,0)`;
337
+ const INVISIBLE_TRANSLATE_3D = `${TRANSLATE_3D}(${INVISIBLE_POSITION},${INVISIBLE_POSITION},0)`;
337
338
  const HIDDEN_ZINDEX = '-1';
338
339
  const DEFAULT_ZINDEX = '0';
339
340
  const TOP_PROP_NAME = 'top';
340
341
  const LEFT_PROP_NAME = 'left';
341
342
  const X_PROP_NAME = 'x';
342
343
  const Y_PROP_NAME = 'y';
344
+ const TRANSFORMED_X_PROP_NAME = 'transformedX';
345
+ const TRANSFORMED_Y_PROP_NAME = 'transformedY';
343
346
  const WIDTH_PROP_NAME = 'width';
344
347
  const HEIGHT_PROP_NAME = 'height';
345
348
  const MARGIN_TOP = 'marginTop';
@@ -669,6 +672,31 @@ class NgVirtualListService {
669
672
  this._langTextDir = v;
670
673
  this._$langTextDir.next(v);
671
674
  }
675
+ _$grabbing = new BehaviorSubject$1(false);
676
+ $grabbing = this._$grabbing.asObservable();
677
+ get grabbing() { return this._$grabbing.getValue(); }
678
+ _grabbing = false;
679
+ set grabbing(v) {
680
+ if (this._grabbing === v) {
681
+ return;
682
+ }
683
+ this._grabbing = v;
684
+ this._$grabbing.next(v);
685
+ }
686
+ _$clickPressed = new BehaviorSubject$1(false);
687
+ $clickPressed = this._$clickPressed.asObservable();
688
+ get clickPressed() { return this._$clickPressed.getValue(); }
689
+ _clickPressed = false;
690
+ set clickPressed(v) {
691
+ if (this._clickPressed === v) {
692
+ return;
693
+ }
694
+ this._clickPressed = v;
695
+ this._$clickPressed.next(v);
696
+ }
697
+ _$isGrabbing = new BehaviorSubject$1(false);
698
+ $isGrabbing = this._$isGrabbing.asObservable();
699
+ get isGrabbing() { return this._$isGrabbing.getValue(); }
672
700
  get scrollBarSize() { return this._$scrollBarSize.getValue(); }
673
701
  _scrollBarSize = 0;
674
702
  set scrollBarSize(v) {
@@ -712,6 +740,10 @@ class NgVirtualListService {
712
740
  }
713
741
  get collapsedIds() { return this._$collapsedIds.getValue(); }
714
742
  constructor() {
743
+ const $grabbing = this.$grabbing.pipe(takeUntilDestroyed(), distinctUntilChanged()), $clickPressed = this.$clickPressed.pipe(takeUntilDestroyed(), distinctUntilChanged());
744
+ combineLatest([$grabbing, $clickPressed]).pipe(takeUntilDestroyed(), tap(([grabbing, clickPressed]) => {
745
+ this._$isGrabbing.next(grabbing && !clickPressed);
746
+ })).subscribe();
715
747
  this._$selectingMode.pipe(takeUntilDestroyed(), tap(v => {
716
748
  switch (v) {
717
749
  case SelectingModesTypes.SELECT: {
@@ -1154,7 +1186,7 @@ class BaseVirtualListItemComponent {
1154
1186
  }
1155
1187
  this._data = v;
1156
1188
  this.updatePartStr(v, this._isSelected, this._isCollapsed);
1157
- this.updateConfig(v);
1189
+ this.updateConfig(v, this._service.isGrabbing);
1158
1190
  this.updateMeasures(v);
1159
1191
  this.update();
1160
1192
  this.data.set(v);
@@ -1203,6 +1235,9 @@ class BaseVirtualListItemComponent {
1203
1235
  this._id = this._service.generateComponentId();
1204
1236
  this._listId = this._service.id;
1205
1237
  this._displayId = createDisplayId(this._listId, this._id);
1238
+ this._service.$isGrabbing.pipe(takeUntilDestroyed(), tap(v => {
1239
+ this.updateConfig(this._data, v);
1240
+ })).subscribe();
1206
1241
  effect(() => {
1207
1242
  const part = this.part();
1208
1243
  this._elementRef.nativeElement.setAttribute('part', part);
@@ -1240,9 +1275,9 @@ class BaseVirtualListItemComponent {
1240
1275
  updateMeasures(v) {
1241
1276
  this.measures.set(v?.measures ? { ...v.measures } : null);
1242
1277
  }
1243
- updateConfig(v) {
1278
+ updateConfig(v, grabbing) {
1244
1279
  this.config.set({
1245
- ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this.focused(),
1280
+ ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this.focused(), grabbing,
1246
1281
  });
1247
1282
  }
1248
1283
  update() {
@@ -1368,6 +1403,7 @@ class BaseVirtualListItemComponent {
1368
1403
  }
1369
1404
  const el = this._elementRef.nativeElement, styles = el.style;
1370
1405
  styles.zIndex = HIDDEN_ZINDEX;
1406
+ styles.transform = INVISIBLE_TRANSLATE_3D;
1371
1407
  if (this.regular) {
1372
1408
  if (styles.display === DISPLAY_NONE) {
1373
1409
  return;
@@ -1394,7 +1430,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
1394
1430
  }]
1395
1431
  }], ctorParameters: () => [], propDecorators: { _item: [{ type: i0.ViewChild, args: ['item', { isSignal: true }] }], _container: [{ type: i0.ViewChild, args: ['container', { isSignal: true }] }] } });
1396
1432
 
1397
- const DEFAULT_MAX_DISTANCE = 40;
1398
1433
  /**
1399
1434
  * VirtualClickDirective
1400
1435
  * Maximum performance for extremely large lists.
@@ -1404,29 +1439,44 @@ const DEFAULT_MAX_DISTANCE = 40;
1404
1439
  * @email djonnyx@gmail.com
1405
1440
  */
1406
1441
  class VirtualClickDirective {
1407
- _maxDistance = DEFAULT_MAX_DISTANCE;
1442
+ _$maxDistance = new BehaviorSubject(null);
1443
+ $maxDistance = this._$maxDistance.asObservable();
1444
+ _maxDistance = null;
1408
1445
  set maxDistance(v) {
1409
- this._maxDistance = (v !== null || v !== undefined) ? Number(v) : DEFAULT_MAX_DISTANCE;
1446
+ const value = (v !== null || v !== undefined) ? Number(v) : null;
1447
+ this._maxDistance = value;
1448
+ this._$maxDistance.next(value);
1410
1449
  }
1411
1450
  onVirtualClick = output();
1451
+ onVirtualClickPress = output();
1452
+ onVirtualClickCancel = output();
1453
+ _service = inject(NgVirtualListService);
1412
1454
  _elementRef = inject(ElementRef);
1413
1455
  _destroyRef = inject(DestroyRef);
1414
1456
  constructor() {
1457
+ let maxDistance = this._maxDistance ?? DEFAULT_CLICK_DISTANCE;
1458
+ combineLatest([this._service.$clickDistance, this.$maxDistance]).pipe(takeUntilDestroyed(), tap$1(([clickDistance, distance]) => {
1459
+ maxDistance = distance === null ? clickDistance : distance;
1460
+ })).subscribe();
1415
1461
  const $pointerPressed = fromEvent(this._elementRef.nativeElement, 'pointerdown'), $pointerCancel = race([
1416
1462
  fromEvent(window, 'pointerup').pipe(takeUntilDestroyed()),
1417
1463
  fromEvent(window, 'pointerleave').pipe(takeUntilDestroyed()),
1418
1464
  ]), $pointerRelease = fromEvent(this._elementRef.nativeElement, 'pointerup', { passive: false });
1419
1465
  $pointerPressed.pipe(takeUntilDestroyed(), switchMap(e => {
1420
1466
  const x = Math.abs(e.clientX), y = Math.abs(e.clientY);
1467
+ this.onVirtualClickPress.emit(e);
1421
1468
  return $pointerRelease.pipe(takeUntilDestroyed(this._destroyRef), takeUntil(race([
1422
- $pointerCancel,
1469
+ $pointerCancel.pipe(takeUntilDestroyed(this._destroyRef), tap$1(() => {
1470
+ this.onVirtualClickCancel.emit();
1471
+ })),
1423
1472
  fromEvent(window, 'pointermove').pipe(takeUntilDestroyed(this._destroyRef), switchMap(e => {
1424
1473
  const xx = x - Math.abs(e.clientX), yy = y - Math.abs(e.clientY), dist = Math.sqrt(Math.pow(xx, 2) + Math.pow(yy, 2));
1425
- if (dist > this._maxDistance) {
1474
+ if (dist > maxDistance) {
1475
+ this.onVirtualClickCancel.emit();
1426
1476
  return of(true);
1427
1477
  }
1428
1478
  return of(false);
1429
- }), takeUntilDestroyed(this._destroyRef), filter(v => !!v)),
1479
+ }), filter(v => !!v)),
1430
1480
  ])), takeUntilDestroyed(this._destroyRef), tap$1(e => {
1431
1481
  if (e) {
1432
1482
  this.onVirtualClick.emit(e);
@@ -1435,7 +1485,7 @@ class VirtualClickDirective {
1435
1485
  })).subscribe();
1436
1486
  }
1437
1487
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: VirtualClickDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1438
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.0", type: VirtualClickDirective, isStandalone: false, selector: "[virtualClick]", inputs: { maxDistance: ["maxClickDistance", "maxDistance"] }, outputs: { onVirtualClick: "onVirtualClick" }, ngImport: i0 });
1488
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.0", type: VirtualClickDirective, isStandalone: false, selector: "[virtualClick]", inputs: { maxDistance: ["maxClickDistance", "maxDistance"] }, outputs: { onVirtualClick: "onVirtualClick", onVirtualClickPress: "onVirtualClickPress", onVirtualClickCancel: "onVirtualClickCancel" }, ngImport: i0 });
1439
1489
  }
1440
1490
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: VirtualClickDirective, decorators: [{
1441
1491
  type: Directive,
@@ -1446,7 +1496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
1446
1496
  }], ctorParameters: () => [], propDecorators: { maxDistance: [{
1447
1497
  type: Input,
1448
1498
  args: ['maxClickDistance']
1449
- }], onVirtualClick: [{ type: i0.Output, args: ["onVirtualClick"] }] } });
1499
+ }], onVirtualClick: [{ type: i0.Output, args: ["onVirtualClick"] }], onVirtualClickPress: [{ type: i0.Output, args: ["onVirtualClickPress"] }], onVirtualClickCancel: [{ type: i0.Output, args: ["onVirtualClickCancel"] }] } });
1450
1500
 
1451
1501
  /**
1452
1502
  * Virtual list component.
@@ -1476,12 +1526,12 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1476
1526
  fromEvent(this.element, EVENT_FOCUS_IN).pipe(takeUntilDestroyed(this._destroyRef), tap(e => {
1477
1527
  this._service.focusedId = this.itemId ?? null;
1478
1528
  this.focused.set(true);
1479
- this.updateConfig(this._data);
1529
+ this.updateConfig(this._data, this._service.isGrabbing);
1480
1530
  this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
1481
1531
  })).subscribe(),
1482
1532
  fromEvent(this.element, EVENT_FOCUS_OUT).pipe(takeUntilDestroyed(this._destroyRef), tap(e => {
1483
1533
  this.focused.set(false);
1484
- this.updateConfig(this._data);
1534
+ this.updateConfig(this._data, this._service.isGrabbing);
1485
1535
  this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
1486
1536
  })).subscribe();
1487
1537
  $focused.pipe(takeUntilDestroyed(this._destroyRef), debounceTime(this.getNavigationTimeout()), switchMap$1(v => {
@@ -1514,7 +1564,7 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1514
1564
  const actualIds = collapsedIds, isCollapsed = this.itemId !== undefined && actualIds && actualIds.includes(this.itemId);
1515
1565
  this._isCollapsed = isCollapsed;
1516
1566
  this.updatePartStr(this._data, this._isSelected, isCollapsed);
1517
- this.updateConfig(this._data);
1567
+ this.updateConfig(this._data, this._service.isGrabbing);
1518
1568
  this.updateMeasures(this._data);
1519
1569
  })).subscribe();
1520
1570
  }
@@ -1617,23 +1667,29 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1617
1667
  }
1618
1668
  return Number.MIN_SAFE_INTEGER;
1619
1669
  }
1620
- updateConfig(v) {
1670
+ updateConfig(v, grabbing) {
1621
1671
  this.config.set({
1622
- ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this.focused(),
1672
+ ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this.focused(), grabbing,
1623
1673
  });
1624
1674
  }
1625
1675
  onClickHandler() {
1626
1676
  this._service.virtualClick(this._data);
1627
1677
  }
1678
+ onClickPressHandler() {
1679
+ this._service.clickPressed = true;
1680
+ }
1681
+ onClickCancelHandler() {
1682
+ this._service.clickPressed = false;
1683
+ }
1628
1684
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgVirtualListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1629
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgVirtualListItemComponent, isStandalone: false, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", 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.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1685
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgVirtualListItemComponent, isStandalone: false, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\"\r\n [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\" (onVirtualClickPress)=\"onClickPressHandler()\"\r\n (onVirtualClickCancel)=\"onClickCancelHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", 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.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick", "onVirtualClickPress", "onVirtualClickCancel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1630
1686
  }
1631
1687
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
1632
1688
  type: Component,
1633
1689
  args: [{ selector: 'ng-virtual-list-item', host: {
1634
1690
  'class': 'ngvl__item',
1635
1691
  'role': 'listitem',
1636
- }, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", 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"] }]
1692
+ }, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\"\r\n [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\" (onVirtualClickPress)=\"onClickPressHandler()\"\r\n (onVirtualClickCancel)=\"onClickCancelHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", 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"] }]
1637
1693
  }], ctorParameters: () => [] });
1638
1694
 
1639
1695
  /**
@@ -3193,7 +3249,7 @@ class TrackBox extends CacheMap {
3193
3249
  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 = [];
3194
3250
  if (items.length) {
3195
3251
  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;
3196
- let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0;
3252
+ let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, nexstStickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0;
3197
3253
  const li = layoutIndexOffset + actualItems.length - 1;
3198
3254
  if (stickyEnabled) {
3199
3255
  for (let i = Math.min(itemsFromStartToScrollEnd > 0 ? (divides > 1 ? (itemsFromStartToScrollEnd - 1) : itemsFromStartToScrollEnd) : 0, totalLength - 1); i >= 0; i--) {
@@ -3453,6 +3509,7 @@ class TrackBox extends CacheMap {
3453
3509
  item.measures.x = isVertical ? 0 : snapped ? actualSnippedPosition : pos;
3454
3510
  item.measures.y = isVertical ? snapped ? actualSnippedPosition : pos : 0;
3455
3511
  nextSticky = item;
3512
+ nexstStickyItemIndex = displayItems.length;
3456
3513
  nextSticky.config.snapped = snapped;
3457
3514
  nextSticky.measures.delta = (isVertical ? item.measures.y : item.measures.x) - scrollSize;
3458
3515
  nextSticky.config.zIndex = Z_INDEX_3;
@@ -3475,10 +3532,10 @@ class TrackBox extends CacheMap {
3475
3532
  }
3476
3533
  i++;
3477
3534
  }
3478
- const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME;
3535
+ const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME, transformedAxis = isVertical ? TRANSFORMED_Y_PROP_NAME : TRANSFORMED_X_PROP_NAME;
3479
3536
  if (!!nextSticky && !!stickyItem && nextSticky.measures[axis] <= actualSnippedPosition + stickyItem.measures[sizeProperty]) {
3480
3537
  if (nextSticky.measures[axis] > actualSnippedPosition) {
3481
- stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3538
+ stickyItem.measures[axis] = stickyItem.measures[transformedAxis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3482
3539
  stickyItem.config.snapped = nextSticky.config.snapped = false;
3483
3540
  stickyItem.config.snappedOut = true;
3484
3541
  stickyItem.config.sticky = 1;
@@ -3487,14 +3544,35 @@ class TrackBox extends CacheMap {
3487
3544
  else {
3488
3545
  nextSticky.config.snapped = true;
3489
3546
  nextSticky.measures.delta = (isVertical ? nextSticky.measures.y : nextSticky.measures.x) - scrollSize;
3490
- stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3547
+ stickyItem.measures[axis] = stickyItem.measures[transformedAxis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3491
3548
  stickyItem.measures.delta = (isVertical ? stickyItem.measures.y : stickyItem.measures.x) - scrollSize;
3549
+ const lastStickyItem = displayItems?.[nexstStickyItemIndex + 1];
3550
+ if (lastStickyItem?.config?.sticky === 1 && displayItems?.[nexstStickyItemIndex + 2]?.config?.sticky !== 1) {
3551
+ nextSticky.config.snapped = nextSticky.config.snappedOut = false;
3552
+ stickyItem.config.snappedOut = true;
3553
+ nextSticky.measures.delta = this._scrollStartOffset;
3554
+ if (lastStickyItem.measures[axis] <= actualSnippedPosition) {
3555
+ lastStickyItem.config.snapped = lastStickyItem.config.snappedOut = true;
3556
+ lastStickyItem.measures[axis] = lastStickyItem.measures[transformedAxis] = lastStickyItem.measures.position = actualSnippedPosition;
3557
+ lastStickyItem.measures.delta = this._scrollStartOffset;
3558
+ }
3559
+ }
3560
+ else if (lastStickyItem?.config?.sticky !== 1 && displayItems?.[nexstStickyItemIndex + 2]?.config?.sticky !== 1) {
3561
+ if (nextSticky.measures[axis] <= actualSnippedPosition) {
3562
+ nextSticky.config.snapped = nextSticky.config.snappedOut = true;
3563
+ nextSticky.measures[axis] = nextSticky.measures[transformedAxis] = nextSticky.measures.position = actualSnippedPosition;
3564
+ nextSticky.measures.delta = this._scrollStartOffset;
3565
+ }
3566
+ }
3567
+ else {
3568
+ nextSticky.config.snapped = nextSticky.config.snappedOut = false;
3569
+ }
3492
3570
  }
3493
3571
  }
3494
3572
  if (!!nextEndSticky && !!endStickyItem &&
3495
3573
  (nextEndSticky.measures[axis] >= actualEndSnippedPosition - endStickyItemSize - nextEndSticky.measures[sizeProperty])) {
3496
3574
  if (nextEndSticky.measures[axis] < actualEndSnippedPosition - nextEndSticky.measures[sizeProperty]) {
3497
- endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3575
+ endStickyItem.measures[axis] = endStickyItem.measures[transformedAxis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3498
3576
  endStickyItem.config.snapped = nextEndSticky.config.snapped = false;
3499
3577
  endStickyItem.config.snappedOut = true;
3500
3578
  endStickyItem.config.sticky = 2;
@@ -3502,9 +3580,9 @@ class TrackBox extends CacheMap {
3502
3580
  }
3503
3581
  else {
3504
3582
  nextEndSticky.config.snapped = true;
3505
- nextEndSticky.measures[axis] = actualEndSnippedPosition - nextEndSticky.measures[sizeProperty];
3583
+ nextEndSticky.measures[axis] = nextEndSticky.measures[transformedAxis] = actualEndSnippedPosition - nextEndSticky.measures[sizeProperty];
3506
3584
  nextEndSticky.measures.delta = (isVertical ? nextEndSticky.measures.y : nextEndSticky.measures.x) - scrollSize;
3507
- endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3585
+ endStickyItem.measures[axis] = endStickyItem.measures[transformedAxis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3508
3586
  endStickyItem.measures.delta = (isVertical ? endStickyItem.measures.y : endStickyItem.measures.x) - scrollSize;
3509
3587
  }
3510
3588
  }
@@ -3968,18 +4046,34 @@ const easeLinear = (t) => {
3968
4046
  class Animator {
3969
4047
  static _nextId = 0;
3970
4048
  _animationId = 0;
4049
+ get animated() { return this._animationId > -1; }
4050
+ get isAnimated() { return this.hasAnimation(this._currentId); }
3971
4051
  _currentId = Animator._nextId;
4052
+ get id() { return this._currentId; }
3972
4053
  generateId() {
3973
4054
  return Animator._nextId = Animator._nextId === Number.MAX_SAFE_INTEGER
3974
4055
  ? 0 : Animator._nextId + 1;
3975
4056
  }
4057
+ _diff = 0;
4058
+ _startValue = 0;
4059
+ _endValue = 0;
4060
+ _prevPos = 0;
4061
+ updateTo(end) {
4062
+ this._endValue = end;
4063
+ this._diff = this._endValue - this._startValue;
4064
+ return this.hasAnimation();
4065
+ }
3976
4066
  animate(params) {
3977
4067
  this.stop();
3978
4068
  const id = this.generateId();
3979
4069
  this._currentId = id;
3980
4070
  const { withDelta = DEFAULT_WITH_DELTA, startValue, endValue, duration = DEFAULT_ANIMATION_DURATION, getPropValue, easingFunction = easeLinear, onUpdate, onComplete, } = params;
4071
+ this._startValue = startValue;
4072
+ this._endValue = endValue;
3981
4073
  const startTime = performance.now();
3982
- let isCanceled = false, prevPos = startValue, start = startValue, startPosDelta = 0, delta = 0, prevTime = startTime, diff = endValue - start, isFinished = false;
4074
+ let isCanceled = false, startPosDelta = 0, delta = 0, prevTime = startTime, isFinished = false;
4075
+ this._prevPos = startValue;
4076
+ this._diff = this._endValue - this._startValue;
3983
4077
  const step = (currentTime) => {
3984
4078
  if (id !== this._currentId) {
3985
4079
  isCanceled = true;
@@ -3989,34 +4083,35 @@ class Animator {
3989
4083
  }
3990
4084
  const cPos = getPropValue?.() || 0;
3991
4085
  let startDelta = 0;
3992
- if (cPos !== prevPos) {
3993
- startDelta = cPos - prevPos;
4086
+ if (cPos !== this._prevPos) {
4087
+ startDelta = cPos - this._prevPos;
3994
4088
  startPosDelta += startDelta;
3995
4089
  }
3996
- 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();
4090
+ 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();
3997
4091
  isFinished = progress === 1;
3998
- delta = currentValue - startDelta - prevPos;
3999
- const ts = t - prevTime, timestamp = ts < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : ts;
4092
+ delta = currentValue - startDelta - this._prevPos;
4093
+ const frameTimestamp = t - prevTime, actualFrameTimestamp = frameTimestamp < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : frameTimestamp;
4000
4094
  prevTime = t;
4001
- prevPos = currentValue;
4095
+ this._prevPos = currentValue;
4002
4096
  if (onUpdate !== undefined) {
4003
4097
  const data = {
4004
4098
  id,
4005
4099
  delta,
4006
4100
  elapsed,
4007
- value: !withDelta && isFinished ? endValue : currentValue,
4008
- timestamp,
4101
+ value: currentValue,
4102
+ timestamp: actualFrameTimestamp,
4009
4103
  };
4010
4104
  onUpdate(data);
4011
4105
  }
4012
4106
  if (isFinished) {
4107
+ this._animationId = -1;
4013
4108
  if (onComplete !== undefined) {
4014
4109
  const data = {
4015
4110
  id,
4016
4111
  delta,
4017
4112
  elapsed,
4018
- value: withDelta ? currentValue : endValue,
4019
- timestamp,
4113
+ value: currentValue,
4114
+ timestamp: actualFrameTimestamp,
4020
4115
  };
4021
4116
  onComplete(data);
4022
4117
  }
@@ -4026,9 +4121,17 @@ class Animator {
4026
4121
  }
4027
4122
  };
4028
4123
  this._animationId = requestAnimationFrame(step);
4124
+ return this._currentId;
4125
+ }
4126
+ hasAnimation(id = -1) {
4127
+ if ((this._currentId === id || id === -1) && this.animated) {
4128
+ return true;
4129
+ }
4130
+ return false;
4029
4131
  }
4030
- stop() {
4031
- cancelAnimationFrame(this._animationId);
4132
+ stop(id = -1) {
4133
+ cancelAnimationFrame(id === -1 ? this._animationId : id);
4134
+ this._animationId = -1;
4032
4135
  }
4033
4136
  dispose() {
4034
4137
  this.stop();
@@ -4465,6 +4568,7 @@ class NgScrollView extends BaseScrollView {
4465
4568
  get startLayoutOffset() { return this._startLayoutOffset; }
4466
4569
  _intersectionComponentId = null;
4467
4570
  _isAlignmentAnimation = false;
4571
+ get animated() { return this._animator?.isAnimated ?? false; }
4468
4572
  constructor() {
4469
4573
  super();
4470
4574
  let mouseCanceled = false, touchCanceled = false;
@@ -4656,6 +4760,7 @@ class NgScrollView extends BaseScrollView {
4656
4760
  }));
4657
4761
  })).subscribe();
4658
4762
  }
4763
+ hasAnimation(id = -1) { return this._animator?.hasAnimation(id) ?? false; }
4659
4764
  updateDirection(position, prePosition) {
4660
4765
  const delta = (position - this._delta) - prePosition;
4661
4766
  this._scrollDirection.add(delta > 0 ? 1 : delta < 0 ? -1 : 0);
@@ -4818,7 +4923,7 @@ class NgScrollView extends BaseScrollView {
4818
4923
  moveWithAcceleration(isVertical, position, v0, v, a0, timestamp) {
4819
4924
  if (a0 !== 0 && timestamp < MAX_VELOCITY_TIMESTAMP) {
4820
4925
  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;
4821
- this.animate(startPosition, Math.round(positionWithVelocity), aDuration, easeOutQuad, true);
4926
+ this.animate(startPosition, Math.round(positionWithVelocity), aDuration, easeOutQuad, false, true);
4822
4927
  }
4823
4928
  else {
4824
4929
  this.alignPosition(true, true);
@@ -4831,11 +4936,17 @@ class NgScrollView extends BaseScrollView {
4831
4936
  const isVertical = this.isVertical(), 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;
4832
4937
  return result;
4833
4938
  }
4834
- animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
4939
+ animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, blending = false, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
4835
4940
  const isVertical = this.isVertical();
4836
4941
  let position = startValue;
4837
4942
  this._isAlignmentAnimation = !alignmentAtComplete;
4838
- this._animator.animate({
4943
+ if (this.hasAnimation() && blending) {
4944
+ const updatable = this._animator.updateTo(endValue);
4945
+ if (updatable) {
4946
+ return this._animator.id;
4947
+ }
4948
+ }
4949
+ return this._animator.animate({
4839
4950
  withDelta: this._service.dynamic && !this.isInfinity(),
4840
4951
  startValue,
4841
4952
  endValue,
@@ -4847,7 +4958,7 @@ class NgScrollView extends BaseScrollView {
4847
4958
  if (this._isCoordinatesOverrided && !skipOverridedCoordinates) {
4848
4959
  this._isCoordinatesOverrided = false;
4849
4960
  const currentCoordinate = isVertical ? this._y : this._x, delta = endValue - value;
4850
- this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, userAction, alignmentAtComplete);
4961
+ this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, blending, userAction, alignmentAtComplete);
4851
4962
  return;
4852
4963
  }
4853
4964
  const v0 = calculateVelocity(position, value - this._delta, timestamp) ?? this.averageVelocity;
@@ -4979,7 +5090,7 @@ class NgScrollView extends BaseScrollView {
4979
5090
  const cPos = (isVertical ? this.scrollTop : this.scrollLeft);
4980
5091
  if (position !== null && position !== cPos) {
4981
5092
  this.stopScrolling(true);
4982
- this.animate(cPos, position, animated ? this.animationParams().snapToItem : 1, easeOutQuad, false, false, true);
5093
+ this.animate(cPos, position, animated ? this.animationParams().snapToItem : 1, easeOutQuad, false, false, false, true);
4983
5094
  return true;
4984
5095
  }
4985
5096
  return false;
@@ -5065,21 +5176,18 @@ class NgScrollView extends BaseScrollView {
5065
5176
  if (behavior === AUTO || behavior === SMOOTH) {
5066
5177
  if (isVertical) {
5067
5178
  if (prevY !== y) {
5068
- this.animate(prevY, y, duration, ease, userAction);
5179
+ return this.animate(prevY, y, duration, ease, blending, userAction);
5069
5180
  }
5070
5181
  }
5071
5182
  else {
5072
5183
  if (prevX !== x) {
5073
- this.animate(prevX, x, duration, ease, userAction);
5184
+ return this.animate(prevX, x, duration, ease, blending, userAction);
5074
5185
  }
5075
5186
  }
5076
5187
  }
5077
5188
  else {
5078
5189
  if (isVertical) {
5079
5190
  if (this._y !== y || force) {
5080
- if (!blending) {
5081
- this.stopScrolling(force);
5082
- }
5083
5191
  this.setY(y, snap, normalize);
5084
5192
  this.emitScrollableEvent();
5085
5193
  if (fireUpdate) {
@@ -5089,9 +5197,6 @@ class NgScrollView extends BaseScrollView {
5089
5197
  }
5090
5198
  else {
5091
5199
  if (this._x !== x || force) {
5092
- if (!blending) {
5093
- this.stopScrolling(force);
5094
- }
5095
5200
  this.setX(x, snap, normalize);
5096
5201
  this.emitScrollableEvent();
5097
5202
  if (fireUpdate) {
@@ -5100,6 +5205,7 @@ class NgScrollView extends BaseScrollView {
5100
5205
  }
5101
5206
  }
5102
5207
  }
5208
+ return -1;
5103
5209
  }
5104
5210
  emitScrollableEvent() {
5105
5211
  if (!!this.cdkScrollable) {
@@ -5118,6 +5224,9 @@ class NgScrollView extends BaseScrollView {
5118
5224
  this.stopScrolling();
5119
5225
  this.move(this.isVertical(), offset);
5120
5226
  }
5227
+ stopAnimation(id) {
5228
+ this._animator.stop(id);
5229
+ }
5121
5230
  ngOnDestroy() {
5122
5231
  if (this._animator) {
5123
5232
  this._animator.dispose();
@@ -5496,6 +5605,10 @@ class NgScrollerComponent extends NgScrollView {
5496
5605
  $updateScrollBar.pipe(takeUntilDestroyed(this._destroyRef), debounceTime(0), tap(() => {
5497
5606
  this.updateScrollBarHandler(!this._isScrollbarUserAction);
5498
5607
  })).subscribe();
5608
+ effect(() => {
5609
+ const grabbing = this.grabbing();
5610
+ this._service.grabbing = grabbing;
5611
+ });
5499
5612
  this.actualClasses = computed(() => {
5500
5613
  const classes = this.classes(), direction = this.direction(), filtered = this.motionBlurEnabled();
5501
5614
  return { ...classes, [direction]: true, grabbing: this.grabbing(), filtered };
@@ -5633,7 +5746,7 @@ class NgScrollerComponent extends NgScrollView {
5633
5746
  this._isScrollbarUserAction = false;
5634
5747
  this.scrollBar?.stopScrolling();
5635
5748
  }
5636
- this.scroll({ ...params, userAction: userAction });
5749
+ return this.scroll({ ...params, userAction: userAction });
5637
5750
  }
5638
5751
  stopScrollbar() {
5639
5752
  if (!!this.scrollBar) {
@@ -6002,14 +6115,14 @@ class NgPrerenderVirtualListItemComponent extends NgVirtualListItemComponent {
6002
6115
  }
6003
6116
  }
6004
6117
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgPrerenderVirtualListItemComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
6005
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgPrerenderVirtualListItemComponent, isStandalone: false, selector: "ng-prerender-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", 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.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6118
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgPrerenderVirtualListItemComponent, isStandalone: false, selector: "ng-prerender-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\"\r\n [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\" (onVirtualClickPress)=\"onClickPressHandler()\"\r\n (onVirtualClickCancel)=\"onClickCancelHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", 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.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick", "onVirtualClickPress", "onVirtualClickCancel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6006
6119
  }
6007
6120
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgPrerenderVirtualListItemComponent, decorators: [{
6008
6121
  type: Component,
6009
6122
  args: [{ selector: 'ng-prerender-virtual-list-item', host: {
6010
6123
  'class': 'ngvl__item',
6011
6124
  'role': 'listitem',
6012
- }, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", 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"] }]
6125
+ }, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\"\r\n [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\" (onVirtualClickPress)=\"onClickPressHandler()\"\r\n (onVirtualClickCancel)=\"onClickCancelHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", 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"] }]
6013
6126
  }] });
6014
6127
 
6015
6128
  /**
@@ -7029,7 +7142,7 @@ class NgVirtualListComponent {
7029
7142
  },
7030
7143
  };
7031
7144
  /**
7032
- * Animation parameters. The default value is "{ scrollToItem: 50, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
7145
+ * Animation parameters. The default value is "{ scrollToItem: 150, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
7033
7146
  */
7034
7147
  animationParams = input(DEFAULT_ANIMATION_PARAMS, { ...(ngDevMode ? { debugName: "animationParams" } : {}), ...this._animationParamsOptions });
7035
7148
  _overscrollEnabledOptions = {
@@ -7503,6 +7616,7 @@ class NgVirtualListComponent {
7503
7616
  _readyForShow = false;
7504
7617
  _cached = false;
7505
7618
  _isLoading = false;
7619
+ _animationId = -1;
7506
7620
  get cachable() {
7507
7621
  return this._prerender()?.active ?? false;
7508
7622
  }
@@ -7517,6 +7631,7 @@ class NgVirtualListComponent {
7517
7631
  NgVirtualListComponent.__nextId = NgVirtualListComponent.__nextId + 1 === Number.MAX_SAFE_INTEGER
7518
7632
  ? 0 : NgVirtualListComponent.__nextId + 1;
7519
7633
  this._id = NgVirtualListComponent.__nextId;
7634
+ let readyForAnimations = false;
7520
7635
  const _$created = new BehaviorSubject(false), $created = _$created.asObservable();
7521
7636
  combineLatest([$created, this.$show]).pipe(takeUntilDestroyed(), filter$1(([created, shown]) => created && shown), debounceTime(1), tap(v => {
7522
7637
  this._$initialized.next(true);
@@ -7753,6 +7868,7 @@ class NgVirtualListComponent {
7753
7868
  }), tap(items => {
7754
7869
  this._trackBox.resetCollection(items, this._actualItemSize());
7755
7870
  }), switchMap$1(i => of((i ?? []).length > 0)), distinctUntilChanged(), tap(v => {
7871
+ readyForAnimations = false;
7756
7872
  if (!v) {
7757
7873
  this.cacheClean();
7758
7874
  this.cleanup();
@@ -8094,12 +8210,22 @@ class NgVirtualListComponent {
8094
8210
  }), debounceTime(100), tap(() => {
8095
8211
  this._isLoading = false;
8096
8212
  })).subscribe();
8213
+ let prevCacheVersion = -1, prevScrollable = false;
8214
+ $viewInit.pipe(takeUntilDestroyed(), filter$1(v => !!v), switchMap$1(() => {
8215
+ return this.$show.pipe(takeUntilDestroyed(this._destroyRef), debounceTime(Math.max(500, this.animationParams().scrollToItem)), tap(() => {
8216
+ if (this._readyForShow || (this.cachable && this._cached)) {
8217
+ readyForAnimations = true;
8218
+ }
8219
+ }));
8220
+ })).subscribe();
8097
8221
  const update = (params) => {
8098
- const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, itemTransform, } = params;
8222
+ const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, cacheVersion, itemTransform, } = params;
8223
+ const cacheChanged = prevCacheVersion !== cacheVersion;
8224
+ prevCacheVersion = cacheVersion;
8099
8225
  const scroller = this._scrollerComponent();
8100
8226
  let totalSize = 0;
8101
8227
  if (!!scroller) {
8102
- 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;
8228
+ 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;
8103
8229
  if (this._readyForShow || (cachable && cached)) {
8104
8230
  const currentScrollSize = (isVertical ? scroller.scrollTop : scroller.scrollLeft);
8105
8231
  let actualScrollSize = !this._readyForShow && snapScrollToEnd ? (isVertical ? scroller.scrollHeight : scroller.scrollWidth) :
@@ -8143,12 +8269,13 @@ class NgVirtualListComponent {
8143
8269
  if (!_$created.getValue()) {
8144
8270
  _$created.next(true);
8145
8271
  }
8146
- const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.scrollHeight : scroller.scrollWidth;
8272
+ const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.actualScrollHeight : scroller.actualScrollWidth;
8147
8273
  if (this._isSnappingMethodAdvanced) {
8148
8274
  this.updateRegularRenderer();
8149
8275
  }
8150
8276
  this.updateOffsetsByAllignment();
8151
8277
  scroller.delta = delta;
8278
+ prevScrollable = scroller.scrollable;
8152
8279
  if ((snapScrollToStart && this._trackBox.isSnappedToStart && scroller.scrollable) ||
8153
8280
  (snapScrollToStart && currentScrollSize <= MIN_PIXELS_FOR_PREVENT_SNAPPING)) {
8154
8281
  if (currentScrollSize !== roundedScrollPositionAfterUpdate) {
@@ -8159,10 +8286,16 @@ class NgVirtualListComponent {
8159
8286
  this._trackBox.isScrollEnd;
8160
8287
  const params = {
8161
8288
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: 0, userAction,
8162
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT,
8163
- blending: false, duration: this.animationParams().scrollToItem,
8289
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams().scrollToItem > 0 && this.scrollBehavior() !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT),
8290
+ blending: useAnimations && scroller.hasAnimation(this._animationId), duration: this.animationParams().scrollToItem,
8164
8291
  };
8165
- scroller?.scrollTo?.(params);
8292
+ const animationId = scroller?.scrollTo?.(params);
8293
+ if (animationId > -1) {
8294
+ this._animationId = animationId;
8295
+ }
8296
+ else {
8297
+ scroller.stopAnimation(this._animationId);
8298
+ }
8166
8299
  if (emitUpdate) {
8167
8300
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
8168
8301
  }
@@ -8182,10 +8315,16 @@ class NgVirtualListComponent {
8182
8315
  }
8183
8316
  const params = {
8184
8317
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: roundedMaxPositionAfterUpdate,
8185
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT, userAction: false,
8186
- blending: false, duration: this.animationParams().scrollToItem,
8318
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams().scrollToItem > 0 && this.scrollBehavior() !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT), userAction: false,
8319
+ blending: useAnimations && scroller.hasAnimation(this._animationId) || cacheChanged, duration: this.animationParams().scrollToItem,
8187
8320
  };
8188
- scroller?.scrollTo?.(params);
8321
+ const animationId = scroller?.scrollTo?.(params);
8322
+ if (animationId > -1) {
8323
+ this._animationId = animationId;
8324
+ }
8325
+ else {
8326
+ scroller.stopAnimation(this._animationId);
8327
+ }
8189
8328
  if (emitUpdate) {
8190
8329
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
8191
8330
  }
@@ -8198,9 +8337,13 @@ class NgVirtualListComponent {
8198
8337
  if (this._readyForShow) {
8199
8338
  this.emitScrollEvent(true, false, userAction);
8200
8339
  }
8340
+ if (this._animationId > -1) {
8341
+ scroller.stopAnimation(this._animationId);
8342
+ this._animationId = -1;
8343
+ }
8201
8344
  const params = {
8202
8345
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollPositionAfterUpdate, blending: true, userAction,
8203
- fireUpdate, behavior: BEHAVIOR_INSTANT, duration: this.animationParams().scrollToItem,
8346
+ fireUpdate, behavior: BEHAVIOR_INSTANT, duration: 0,
8204
8347
  };
8205
8348
  scroller.scrollTo(params);
8206
8349
  if (emitUpdate) {
@@ -8887,7 +9030,7 @@ class NgVirtualListComponent {
8887
9030
  this._isScrollStart.set(false);
8888
9031
  this._isScrollEnd.set(false);
8889
9032
  this._trackBox.preventScrollSnapping(true);
8890
- if (scroller) {
9033
+ if (!!scroller) {
8891
9034
  scroller.stopScrolling();
8892
9035
  }
8893
9036
  }
@@ -8913,7 +9056,7 @@ class NgVirtualListComponent {
8913
9056
  comp?.destroy();
8914
9057
  }
8915
9058
  }
8916
- if (this._displayComponents) {
9059
+ if (!!this._displayComponents) {
8917
9060
  while (this._displayComponents.length > 0) {
8918
9061
  const comp = this._displayComponents.shift();
8919
9062
  comp?.destroy();