ng-virtual-list 22.12.2 → 22.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: {
@@ -1162,7 +1194,7 @@ class BaseVirtualListItemComponent {
1162
1194
  }
1163
1195
  this._data = v;
1164
1196
  this.updatePartStr(v, this._isSelected, this._isCollapsed);
1165
- this.updateConfig(v);
1197
+ this.updateConfig(v, this._service.isGrabbing);
1166
1198
  this.updateMeasures(v);
1167
1199
  this.update();
1168
1200
  this.data.set(v);
@@ -1212,6 +1244,9 @@ class BaseVirtualListItemComponent {
1212
1244
  this._id = this._service.generateComponentId();
1213
1245
  this._listId = this._service.id;
1214
1246
  this._displayId = createDisplayId(this._listId, this._id);
1247
+ this._service.$isGrabbing.pipe(takeUntilDestroyed(), tap(v => {
1248
+ this.updateConfig(this._data, v);
1249
+ })).subscribe();
1215
1250
  effect(() => {
1216
1251
  const part = this.part();
1217
1252
  this._elementRef.nativeElement.setAttribute('part', part);
@@ -1252,9 +1287,9 @@ class BaseVirtualListItemComponent {
1252
1287
  updateMeasures(v) {
1253
1288
  this.measures.set(v?.measures ? { ...v.measures } : null);
1254
1289
  }
1255
- updateConfig(v) {
1290
+ updateConfig(v, grabbing) {
1256
1291
  this.config.set({
1257
- ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this.focused(),
1292
+ ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this.focused(), grabbing,
1258
1293
  });
1259
1294
  }
1260
1295
  update() {
@@ -1380,6 +1415,7 @@ class BaseVirtualListItemComponent {
1380
1415
  }
1381
1416
  const el = this._elementRef.nativeElement, styles = el.style;
1382
1417
  styles.zIndex = HIDDEN_ZINDEX;
1418
+ styles.transform = INVISIBLE_TRANSLATE_3D;
1383
1419
  if (this.regular) {
1384
1420
  if (styles.display === DISPLAY_NONE) {
1385
1421
  return;
@@ -1406,7 +1442,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
1406
1442
  }]
1407
1443
  }], ctorParameters: () => [], propDecorators: { _item: [{ type: i0.ViewChild, args: ['item', { isSignal: true }] }], _container: [{ type: i0.ViewChild, args: ['container', { isSignal: true }] }] } });
1408
1444
 
1409
- const DEFAULT_MAX_DISTANCE = 40;
1410
1445
  /**
1411
1446
  * VirtualClickDirective
1412
1447
  * Maximum performance for extremely large lists.
@@ -1416,29 +1451,44 @@ const DEFAULT_MAX_DISTANCE = 40;
1416
1451
  * @email djonnyx@gmail.com
1417
1452
  */
1418
1453
  class VirtualClickDirective {
1419
- _maxDistance = DEFAULT_MAX_DISTANCE;
1454
+ _$maxDistance = new BehaviorSubject(null);
1455
+ $maxDistance = this._$maxDistance.asObservable();
1456
+ _maxDistance = null;
1420
1457
  set maxDistance(v) {
1421
- this._maxDistance = (v !== null || v !== undefined) ? Number(v) : DEFAULT_MAX_DISTANCE;
1458
+ const value = (v !== null || v !== undefined) ? Number(v) : null;
1459
+ this._maxDistance = value;
1460
+ this._$maxDistance.next(value);
1422
1461
  }
1423
1462
  onVirtualClick = output();
1463
+ onVirtualClickPress = output();
1464
+ onVirtualClickCancel = output();
1465
+ _service = inject(NgVirtualListService);
1424
1466
  _elementRef = inject(ElementRef);
1425
1467
  _destroyRef = inject(DestroyRef);
1426
1468
  constructor() {
1469
+ let maxDistance = this._maxDistance ?? DEFAULT_CLICK_DISTANCE;
1470
+ combineLatest([this._service.$clickDistance, this.$maxDistance]).pipe(takeUntilDestroyed(), tap$1(([clickDistance, distance]) => {
1471
+ maxDistance = distance === null ? clickDistance : distance;
1472
+ })).subscribe();
1427
1473
  const $pointerPressed = fromEvent(this._elementRef.nativeElement, 'pointerdown'), $pointerCancel = race([
1428
1474
  fromEvent(window, 'pointerup').pipe(takeUntilDestroyed()),
1429
1475
  fromEvent(window, 'pointerleave').pipe(takeUntilDestroyed()),
1430
1476
  ]), $pointerRelease = fromEvent(this._elementRef.nativeElement, 'pointerup', { passive: false });
1431
1477
  $pointerPressed.pipe(takeUntilDestroyed(), switchMap(e => {
1432
1478
  const x = Math.abs(e.clientX), y = Math.abs(e.clientY);
1479
+ this.onVirtualClickPress.emit(e);
1433
1480
  return $pointerRelease.pipe(takeUntilDestroyed(this._destroyRef), takeUntil(race([
1434
- $pointerCancel,
1481
+ $pointerCancel.pipe(takeUntilDestroyed(this._destroyRef), tap$1(() => {
1482
+ this.onVirtualClickCancel.emit();
1483
+ })),
1435
1484
  fromEvent(window, 'pointermove').pipe(takeUntilDestroyed(this._destroyRef), switchMap(e => {
1436
1485
  const xx = x - Math.abs(e.clientX), yy = y - Math.abs(e.clientY), dist = Math.sqrt(Math.pow(xx, 2) + Math.pow(yy, 2));
1437
- if (dist > this._maxDistance) {
1486
+ if (dist > maxDistance) {
1487
+ this.onVirtualClickCancel.emit();
1438
1488
  return of(true);
1439
1489
  }
1440
1490
  return of(false);
1441
- }), takeUntilDestroyed(this._destroyRef), filter(v => !!v)),
1491
+ }), filter(v => !!v)),
1442
1492
  ])), takeUntilDestroyed(this._destroyRef), tap$1(e => {
1443
1493
  if (e) {
1444
1494
  this.onVirtualClick.emit(e);
@@ -1447,7 +1497,7 @@ class VirtualClickDirective {
1447
1497
  })).subscribe();
1448
1498
  }
1449
1499
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: VirtualClickDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1450
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.0", type: VirtualClickDirective, isStandalone: false, selector: "[virtualClick]", inputs: { maxDistance: ["maxClickDistance", "maxDistance"] }, outputs: { onVirtualClick: "onVirtualClick" }, ngImport: i0 });
1500
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.0", type: VirtualClickDirective, isStandalone: false, selector: "[virtualClick]", inputs: { maxDistance: ["maxClickDistance", "maxDistance"] }, outputs: { onVirtualClick: "onVirtualClick", onVirtualClickPress: "onVirtualClickPress", onVirtualClickCancel: "onVirtualClickCancel" }, ngImport: i0 });
1451
1501
  }
1452
1502
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: VirtualClickDirective, decorators: [{
1453
1503
  type: Directive,
@@ -1458,7 +1508,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
1458
1508
  }], ctorParameters: () => [], propDecorators: { maxDistance: [{
1459
1509
  type: Input,
1460
1510
  args: ['maxClickDistance']
1461
- }], onVirtualClick: [{ type: i0.Output, args: ["onVirtualClick"] }] } });
1511
+ }], onVirtualClick: [{ type: i0.Output, args: ["onVirtualClick"] }], onVirtualClickPress: [{ type: i0.Output, args: ["onVirtualClickPress"] }], onVirtualClickCancel: [{ type: i0.Output, args: ["onVirtualClickCancel"] }] } });
1462
1512
 
1463
1513
  /**
1464
1514
  * Virtual list component.
@@ -1489,12 +1539,12 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1489
1539
  fromEvent(this.element, EVENT_FOCUS_IN).pipe(takeUntilDestroyed(this._destroyRef), tap(e => {
1490
1540
  this._service.focusedId = this.itemId ?? null;
1491
1541
  this.focused.set(true);
1492
- this.updateConfig(this._data);
1542
+ this.updateConfig(this._data, this._service.isGrabbing);
1493
1543
  this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
1494
1544
  })).subscribe(),
1495
1545
  fromEvent(this.element, EVENT_FOCUS_OUT).pipe(takeUntilDestroyed(this._destroyRef), tap(e => {
1496
1546
  this.focused.set(false);
1497
- this.updateConfig(this._data);
1547
+ this.updateConfig(this._data, this._service.isGrabbing);
1498
1548
  this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
1499
1549
  })).subscribe();
1500
1550
  $focused.pipe(takeUntilDestroyed(this._destroyRef), debounceTime(this.getNavigationTimeout()), switchMap$1(v => {
@@ -1527,7 +1577,7 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1527
1577
  const actualIds = collapsedIds, isCollapsed = this.itemId !== undefined && actualIds && actualIds.includes(this.itemId);
1528
1578
  this._isCollapsed = isCollapsed;
1529
1579
  this.updatePartStr(this._data, this._isSelected, isCollapsed);
1530
- this.updateConfig(this._data);
1580
+ this.updateConfig(this._data, this._service.isGrabbing);
1531
1581
  this.updateMeasures(this._data);
1532
1582
  })).subscribe();
1533
1583
  }
@@ -1630,23 +1680,29 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
1630
1680
  }
1631
1681
  return Number.MIN_SAFE_INTEGER;
1632
1682
  }
1633
- updateConfig(v) {
1683
+ updateConfig(v, grabbing) {
1634
1684
  this.config.set({
1635
- ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this.focused(),
1685
+ ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this.focused(), grabbing,
1636
1686
  });
1637
1687
  }
1638
1688
  onClickHandler() {
1639
1689
  this._service.virtualClick(this._data);
1640
1690
  }
1691
+ onClickPressHandler() {
1692
+ this._service.clickPressed = true;
1693
+ }
1694
+ onClickCancelHandler() {
1695
+ this._service.clickPressed = false;
1696
+ }
1641
1697
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: NgVirtualListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1642
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.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 });
1698
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.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 });
1643
1699
  }
1644
1700
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
1645
1701
  type: Component,
1646
1702
  args: [{ selector: 'ng-virtual-list-item', host: {
1647
1703
  'class': 'ngvl__item',
1648
1704
  'role': 'listitem',
1649
- }, 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"] }]
1705
+ }, 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"] }]
1650
1706
  }], ctorParameters: () => [] });
1651
1707
 
1652
1708
  /**
@@ -3206,7 +3262,7 @@ class TrackBox extends CacheMap {
3206
3262
  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 = [];
3207
3263
  if (items.length) {
3208
3264
  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;
3209
- let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0;
3265
+ let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, nexstStickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0;
3210
3266
  const li = layoutIndexOffset + actualItems.length - 1;
3211
3267
  if (stickyEnabled) {
3212
3268
  for (let i = Math.min(itemsFromStartToScrollEnd > 0 ? (divides > 1 ? (itemsFromStartToScrollEnd - 1) : itemsFromStartToScrollEnd) : 0, totalLength - 1); i >= 0; i--) {
@@ -3466,6 +3522,7 @@ class TrackBox extends CacheMap {
3466
3522
  item.measures.x = isVertical ? 0 : snapped ? actualSnippedPosition : pos;
3467
3523
  item.measures.y = isVertical ? snapped ? actualSnippedPosition : pos : 0;
3468
3524
  nextSticky = item;
3525
+ nexstStickyItemIndex = displayItems.length;
3469
3526
  nextSticky.config.snapped = snapped;
3470
3527
  nextSticky.measures.delta = (isVertical ? item.measures.y : item.measures.x) - scrollSize;
3471
3528
  nextSticky.config.zIndex = Z_INDEX_3;
@@ -3488,10 +3545,10 @@ class TrackBox extends CacheMap {
3488
3545
  }
3489
3546
  i++;
3490
3547
  }
3491
- const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME;
3548
+ const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME, transformedAxis = isVertical ? TRANSFORMED_Y_PROP_NAME : TRANSFORMED_X_PROP_NAME;
3492
3549
  if (!!nextSticky && !!stickyItem && nextSticky.measures[axis] <= actualSnippedPosition + stickyItem.measures[sizeProperty]) {
3493
3550
  if (nextSticky.measures[axis] > actualSnippedPosition) {
3494
- stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3551
+ stickyItem.measures[axis] = stickyItem.measures[transformedAxis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3495
3552
  stickyItem.config.snapped = nextSticky.config.snapped = false;
3496
3553
  stickyItem.config.snappedOut = true;
3497
3554
  stickyItem.config.sticky = 1;
@@ -3500,14 +3557,35 @@ class TrackBox extends CacheMap {
3500
3557
  else {
3501
3558
  nextSticky.config.snapped = true;
3502
3559
  nextSticky.measures.delta = (isVertical ? nextSticky.measures.y : nextSticky.measures.x) - scrollSize;
3503
- stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3560
+ stickyItem.measures[axis] = stickyItem.measures[transformedAxis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
3504
3561
  stickyItem.measures.delta = (isVertical ? stickyItem.measures.y : stickyItem.measures.x) - scrollSize;
3562
+ const lastStickyItem = displayItems?.[nexstStickyItemIndex + 1];
3563
+ if (lastStickyItem?.config?.sticky === 1 && displayItems?.[nexstStickyItemIndex + 2]?.config?.sticky !== 1) {
3564
+ nextSticky.config.snapped = nextSticky.config.snappedOut = false;
3565
+ stickyItem.config.snappedOut = true;
3566
+ nextSticky.measures.delta = this._scrollStartOffset;
3567
+ if (lastStickyItem.measures[axis] <= actualSnippedPosition) {
3568
+ lastStickyItem.config.snapped = lastStickyItem.config.snappedOut = true;
3569
+ lastStickyItem.measures[axis] = lastStickyItem.measures[transformedAxis] = lastStickyItem.measures.position = actualSnippedPosition;
3570
+ lastStickyItem.measures.delta = this._scrollStartOffset;
3571
+ }
3572
+ }
3573
+ else if (lastStickyItem?.config?.sticky !== 1 && displayItems?.[nexstStickyItemIndex + 2]?.config?.sticky !== 1) {
3574
+ if (nextSticky.measures[axis] <= actualSnippedPosition) {
3575
+ nextSticky.config.snapped = nextSticky.config.snappedOut = true;
3576
+ nextSticky.measures[axis] = nextSticky.measures[transformedAxis] = nextSticky.measures.position = actualSnippedPosition;
3577
+ nextSticky.measures.delta = this._scrollStartOffset;
3578
+ }
3579
+ }
3580
+ else {
3581
+ nextSticky.config.snapped = nextSticky.config.snappedOut = false;
3582
+ }
3505
3583
  }
3506
3584
  }
3507
3585
  if (!!nextEndSticky && !!endStickyItem &&
3508
3586
  (nextEndSticky.measures[axis] >= actualEndSnippedPosition - endStickyItemSize - nextEndSticky.measures[sizeProperty])) {
3509
3587
  if (nextEndSticky.measures[axis] < actualEndSnippedPosition - nextEndSticky.measures[sizeProperty]) {
3510
- endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3588
+ endStickyItem.measures[axis] = endStickyItem.measures[transformedAxis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3511
3589
  endStickyItem.config.snapped = nextEndSticky.config.snapped = false;
3512
3590
  endStickyItem.config.snappedOut = true;
3513
3591
  endStickyItem.config.sticky = 2;
@@ -3515,9 +3593,9 @@ class TrackBox extends CacheMap {
3515
3593
  }
3516
3594
  else {
3517
3595
  nextEndSticky.config.snapped = true;
3518
- nextEndSticky.measures[axis] = actualEndSnippedPosition - nextEndSticky.measures[sizeProperty];
3596
+ nextEndSticky.measures[axis] = nextEndSticky.measures[transformedAxis] = actualEndSnippedPosition - nextEndSticky.measures[sizeProperty];
3519
3597
  nextEndSticky.measures.delta = (isVertical ? nextEndSticky.measures.y : nextEndSticky.measures.x) - scrollSize;
3520
- endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3598
+ endStickyItem.measures[axis] = endStickyItem.measures[transformedAxis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
3521
3599
  endStickyItem.measures.delta = (isVertical ? endStickyItem.measures.y : endStickyItem.measures.x) - scrollSize;
3522
3600
  }
3523
3601
  }
@@ -3981,18 +4059,34 @@ const easeLinear = (t) => {
3981
4059
  class Animator {
3982
4060
  static _nextId = 0;
3983
4061
  _animationId = 0;
4062
+ get animated() { return this._animationId > -1; }
4063
+ get isAnimated() { return this.hasAnimation(this._currentId); }
3984
4064
  _currentId = Animator._nextId;
4065
+ get id() { return this._currentId; }
3985
4066
  generateId() {
3986
4067
  return Animator._nextId = Animator._nextId === Number.MAX_SAFE_INTEGER
3987
4068
  ? 0 : Animator._nextId + 1;
3988
4069
  }
4070
+ _diff = 0;
4071
+ _startValue = 0;
4072
+ _endValue = 0;
4073
+ _prevPos = 0;
4074
+ updateTo(end) {
4075
+ this._endValue = end;
4076
+ this._diff = this._endValue - this._startValue;
4077
+ return this.hasAnimation();
4078
+ }
3989
4079
  animate(params) {
3990
4080
  this.stop();
3991
4081
  const id = this.generateId();
3992
4082
  this._currentId = id;
3993
4083
  const { withDelta = DEFAULT_WITH_DELTA, startValue, endValue, duration = DEFAULT_ANIMATION_DURATION, getPropValue, easingFunction = easeLinear, onUpdate, onComplete, } = params;
4084
+ this._startValue = startValue;
4085
+ this._endValue = endValue;
3994
4086
  const startTime = performance.now();
3995
- let isCanceled = false, prevPos = startValue, start = startValue, startPosDelta = 0, delta = 0, prevTime = startTime, diff = endValue - start, isFinished = false;
4087
+ let isCanceled = false, startPosDelta = 0, delta = 0, prevTime = startTime, isFinished = false;
4088
+ this._prevPos = startValue;
4089
+ this._diff = this._endValue - this._startValue;
3996
4090
  const step = (currentTime) => {
3997
4091
  if (id !== this._currentId) {
3998
4092
  isCanceled = true;
@@ -4002,34 +4096,35 @@ class Animator {
4002
4096
  }
4003
4097
  const cPos = getPropValue?.() || 0;
4004
4098
  let startDelta = 0;
4005
- if (cPos !== prevPos) {
4006
- startDelta = cPos - prevPos;
4099
+ if (cPos !== this._prevPos) {
4100
+ startDelta = cPos - this._prevPos;
4007
4101
  startPosDelta += startDelta;
4008
4102
  }
4009
- 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();
4103
+ 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();
4010
4104
  isFinished = progress === 1;
4011
- delta = currentValue - startDelta - prevPos;
4012
- const ts = t - prevTime, timestamp = ts < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : ts;
4105
+ delta = currentValue - startDelta - this._prevPos;
4106
+ const frameTimestamp = t - prevTime, actualFrameTimestamp = frameTimestamp < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : frameTimestamp;
4013
4107
  prevTime = t;
4014
- prevPos = currentValue;
4108
+ this._prevPos = currentValue;
4015
4109
  if (onUpdate !== undefined) {
4016
4110
  const data = {
4017
4111
  id,
4018
4112
  delta,
4019
4113
  elapsed,
4020
- value: !withDelta && isFinished ? endValue : currentValue,
4021
- timestamp,
4114
+ value: currentValue,
4115
+ timestamp: actualFrameTimestamp,
4022
4116
  };
4023
4117
  onUpdate(data);
4024
4118
  }
4025
4119
  if (isFinished) {
4120
+ this._animationId = -1;
4026
4121
  if (onComplete !== undefined) {
4027
4122
  const data = {
4028
4123
  id,
4029
4124
  delta,
4030
4125
  elapsed,
4031
- value: withDelta ? currentValue : endValue,
4032
- timestamp,
4126
+ value: currentValue,
4127
+ timestamp: actualFrameTimestamp,
4033
4128
  };
4034
4129
  onComplete(data);
4035
4130
  }
@@ -4039,9 +4134,17 @@ class Animator {
4039
4134
  }
4040
4135
  };
4041
4136
  this._animationId = requestAnimationFrame(step);
4137
+ return this._currentId;
4138
+ }
4139
+ hasAnimation(id = -1) {
4140
+ if ((this._currentId === id || id === -1) && this.animated) {
4141
+ return true;
4142
+ }
4143
+ return false;
4042
4144
  }
4043
- stop() {
4044
- cancelAnimationFrame(this._animationId);
4145
+ stop(id = -1) {
4146
+ cancelAnimationFrame(id === -1 ? this._animationId : id);
4147
+ this._animationId = -1;
4045
4148
  }
4046
4149
  dispose() {
4047
4150
  this.stop();
@@ -4498,6 +4601,7 @@ class NgScrollView extends BaseScrollView {
4498
4601
  get startLayoutOffset() { return this._startLayoutOffset; }
4499
4602
  _intersectionComponentId = null;
4500
4603
  _isAlignmentAnimation = false;
4604
+ get animated() { return this._animator?.isAnimated ?? false; }
4501
4605
  constructor() {
4502
4606
  super();
4503
4607
  let mouseCanceled = false, touchCanceled = false;
@@ -4689,6 +4793,7 @@ class NgScrollView extends BaseScrollView {
4689
4793
  }));
4690
4794
  })).subscribe();
4691
4795
  }
4796
+ hasAnimation(id = -1) { return this._animator?.hasAnimation(id) ?? false; }
4692
4797
  updateDirection(position, prePosition) {
4693
4798
  const delta = (position - this._delta) - prePosition;
4694
4799
  this._scrollDirection.add(delta > 0 ? 1 : delta < 0 ? -1 : 0);
@@ -4851,7 +4956,7 @@ class NgScrollView extends BaseScrollView {
4851
4956
  moveWithAcceleration(isVertical, position, v0, v, a0, timestamp) {
4852
4957
  if (a0 !== 0 && timestamp < MAX_VELOCITY_TIMESTAMP) {
4853
4958
  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;
4854
- this.animate(startPosition, Math.round(positionWithVelocity), aDuration, easeOutQuad, true);
4959
+ this.animate(startPosition, Math.round(positionWithVelocity), aDuration, easeOutQuad, false, true);
4855
4960
  }
4856
4961
  else {
4857
4962
  this.alignPosition(true, true);
@@ -4864,11 +4969,17 @@ class NgScrollView extends BaseScrollView {
4864
4969
  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;
4865
4970
  return result;
4866
4971
  }
4867
- animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
4972
+ animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, blending = false, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
4868
4973
  const isVertical = this.isVertical();
4869
4974
  let position = startValue;
4870
4975
  this._isAlignmentAnimation = !alignmentAtComplete;
4871
- this._animator.animate({
4976
+ if (this.hasAnimation() && blending) {
4977
+ const updatable = this._animator.updateTo(endValue);
4978
+ if (updatable) {
4979
+ return this._animator.id;
4980
+ }
4981
+ }
4982
+ return this._animator.animate({
4872
4983
  withDelta: this._service.dynamic && !this.isInfinity(),
4873
4984
  startValue,
4874
4985
  endValue,
@@ -4880,7 +4991,7 @@ class NgScrollView extends BaseScrollView {
4880
4991
  if (this._isCoordinatesOverrided && !skipOverridedCoordinates) {
4881
4992
  this._isCoordinatesOverrided = false;
4882
4993
  const currentCoordinate = isVertical ? this._y : this._x, delta = endValue - value;
4883
- this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, userAction, alignmentAtComplete);
4994
+ this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, blending, userAction, alignmentAtComplete);
4884
4995
  return;
4885
4996
  }
4886
4997
  const v0 = calculateVelocity(position, value - this._delta, timestamp) ?? this.averageVelocity;
@@ -5012,7 +5123,7 @@ class NgScrollView extends BaseScrollView {
5012
5123
  const cPos = (isVertical ? this.scrollTop : this.scrollLeft);
5013
5124
  if (position !== null && position !== cPos) {
5014
5125
  this.stopScrolling(true);
5015
- this.animate(cPos, position, animated ? this.animationParams().snapToItem : 1, easeOutQuad, false, false, true);
5126
+ this.animate(cPos, position, animated ? this.animationParams().snapToItem : 1, easeOutQuad, false, false, false, true);
5016
5127
  return true;
5017
5128
  }
5018
5129
  return false;
@@ -5098,21 +5209,18 @@ class NgScrollView extends BaseScrollView {
5098
5209
  if (behavior === AUTO || behavior === SMOOTH) {
5099
5210
  if (isVertical) {
5100
5211
  if (prevY !== y) {
5101
- this.animate(prevY, y, duration, ease, userAction);
5212
+ return this.animate(prevY, y, duration, ease, blending, userAction);
5102
5213
  }
5103
5214
  }
5104
5215
  else {
5105
5216
  if (prevX !== x) {
5106
- this.animate(prevX, x, duration, ease, userAction);
5217
+ return this.animate(prevX, x, duration, ease, blending, userAction);
5107
5218
  }
5108
5219
  }
5109
5220
  }
5110
5221
  else {
5111
5222
  if (isVertical) {
5112
5223
  if (this._y !== y || force) {
5113
- if (!blending) {
5114
- this.stopScrolling(force);
5115
- }
5116
5224
  this.setY(y, snap, normalize);
5117
5225
  this.emitScrollableEvent();
5118
5226
  if (fireUpdate) {
@@ -5122,9 +5230,6 @@ class NgScrollView extends BaseScrollView {
5122
5230
  }
5123
5231
  else {
5124
5232
  if (this._x !== x || force) {
5125
- if (!blending) {
5126
- this.stopScrolling(force);
5127
- }
5128
5233
  this.setX(x, snap, normalize);
5129
5234
  this.emitScrollableEvent();
5130
5235
  if (fireUpdate) {
@@ -5133,6 +5238,7 @@ class NgScrollView extends BaseScrollView {
5133
5238
  }
5134
5239
  }
5135
5240
  }
5241
+ return -1;
5136
5242
  }
5137
5243
  emitScrollableEvent() {
5138
5244
  if (!!this.cdkScrollable) {
@@ -5151,6 +5257,9 @@ class NgScrollView extends BaseScrollView {
5151
5257
  this.stopScrolling();
5152
5258
  this.move(this.isVertical(), offset);
5153
5259
  }
5260
+ stopAnimation(id) {
5261
+ this._animator.stop(id);
5262
+ }
5154
5263
  ngOnDestroy() {
5155
5264
  if (this._animator) {
5156
5265
  this._animator.dispose();
@@ -5573,6 +5682,10 @@ class NgScrollerComponent extends NgScrollView {
5573
5682
  $updateScrollBar.pipe(takeUntilDestroyed(this._destroyRef), debounceTime(0), tap(() => {
5574
5683
  this.updateScrollBarHandler(!this._isScrollbarUserAction);
5575
5684
  })).subscribe();
5685
+ effect(() => {
5686
+ const grabbing = this.grabbing();
5687
+ this._service.grabbing = grabbing;
5688
+ });
5576
5689
  this.actualClasses = computed(() => {
5577
5690
  const classes = this.classes(), direction = this.direction(), filtered = this.motionBlurEnabled();
5578
5691
  return { ...classes, [direction]: true, grabbing: this.grabbing(), filtered };
@@ -5712,7 +5825,7 @@ class NgScrollerComponent extends NgScrollView {
5712
5825
  this._isScrollbarUserAction = false;
5713
5826
  this.scrollBar?.stopScrolling();
5714
5827
  }
5715
- this.scroll({ ...params, userAction: userAction });
5828
+ return this.scroll({ ...params, userAction: userAction });
5716
5829
  }
5717
5830
  stopScrollbar() {
5718
5831
  if (!!this.scrollBar) {
@@ -6081,14 +6194,14 @@ class NgPrerenderVirtualListItemComponent extends NgVirtualListItemComponent {
6081
6194
  }
6082
6195
  }
6083
6196
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: NgPrerenderVirtualListItemComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
6084
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.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 });
6197
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.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 });
6085
6198
  }
6086
6199
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: NgPrerenderVirtualListItemComponent, decorators: [{
6087
6200
  type: Component,
6088
6201
  args: [{ selector: 'ng-prerender-virtual-list-item', host: {
6089
6202
  'class': 'ngvl__item',
6090
6203
  'role': 'listitem',
6091
- }, 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"] }]
6204
+ }, 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"] }]
6092
6205
  }] });
6093
6206
 
6094
6207
  /**
@@ -7146,7 +7259,7 @@ class NgVirtualListComponent {
7146
7259
  },
7147
7260
  };
7148
7261
  /**
7149
- * Animation parameters. The default value is "{ scrollToItem: 50, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
7262
+ * Animation parameters. The default value is "{ scrollToItem: 150, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
7150
7263
  */
7151
7264
  animationParams = input(DEFAULT_ANIMATION_PARAMS, { ...(ngDevMode ? { debugName: "animationParams" } : /* istanbul ignore next */ {}), ...this._animationParamsOptions });
7152
7265
  _overscrollEnabledOptions = {
@@ -7640,6 +7753,7 @@ class NgVirtualListComponent {
7640
7753
  _readyForShow = false;
7641
7754
  _cached = false;
7642
7755
  _isLoading = false;
7756
+ _animationId = -1;
7643
7757
  get cachable() {
7644
7758
  return this._prerender()?.active ?? false;
7645
7759
  }
@@ -7654,6 +7768,7 @@ class NgVirtualListComponent {
7654
7768
  NgVirtualListComponent.__nextId = NgVirtualListComponent.__nextId + 1 === Number.MAX_SAFE_INTEGER
7655
7769
  ? 0 : NgVirtualListComponent.__nextId + 1;
7656
7770
  this._id = NgVirtualListComponent.__nextId;
7771
+ let readyForAnimations = false;
7657
7772
  const _$created = new BehaviorSubject(false), $created = _$created.asObservable();
7658
7773
  combineLatest([$created, this.$show]).pipe(takeUntilDestroyed(), filter$1(([created, shown]) => created && shown), debounceTime(1), tap(v => {
7659
7774
  this._$initialized.next(true);
@@ -7895,6 +8010,7 @@ class NgVirtualListComponent {
7895
8010
  }), tap(items => {
7896
8011
  this._trackBox.resetCollection(items, this._actualItemSize());
7897
8012
  }), switchMap$1(i => of((i ?? []).length > 0)), distinctUntilChanged(), tap(v => {
8013
+ readyForAnimations = false;
7898
8014
  if (!v) {
7899
8015
  this.cacheClean();
7900
8016
  this.cleanup();
@@ -8238,12 +8354,22 @@ class NgVirtualListComponent {
8238
8354
  }), debounceTime(100), tap(() => {
8239
8355
  this._isLoading = false;
8240
8356
  })).subscribe();
8357
+ let prevCacheVersion = -1, prevScrollable = false;
8358
+ $viewInit.pipe(takeUntilDestroyed(), filter$1(v => !!v), switchMap$1(() => {
8359
+ return this.$show.pipe(takeUntilDestroyed(this._destroyRef), debounceTime(Math.max(500, this.animationParams().scrollToItem)), tap(() => {
8360
+ if (this._readyForShow || (this.cachable && this._cached)) {
8361
+ readyForAnimations = true;
8362
+ }
8363
+ }));
8364
+ })).subscribe();
8241
8365
  const update = (params) => {
8242
- const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, itemTransform, } = params;
8366
+ const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, cacheVersion, itemTransform, } = params;
8367
+ const cacheChanged = prevCacheVersion !== cacheVersion;
8368
+ prevCacheVersion = cacheVersion;
8243
8369
  const scroller = this._scrollerComponent();
8244
8370
  let totalSize = 0;
8245
8371
  if (!!scroller) {
8246
- 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;
8372
+ 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;
8247
8373
  if (this._readyForShow || (cachable && cached)) {
8248
8374
  const currentScrollSize = (isVertical ? scroller.scrollTop : scroller.scrollLeft);
8249
8375
  let actualScrollSize = !this._readyForShow && snapScrollToEnd ? (isVertical ? scroller.scrollHeight : scroller.scrollWidth) :
@@ -8287,12 +8413,13 @@ class NgVirtualListComponent {
8287
8413
  if (!_$created.getValue()) {
8288
8414
  _$created.next(true);
8289
8415
  }
8290
- const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.scrollHeight : scroller.scrollWidth;
8416
+ const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.actualScrollHeight : scroller.actualScrollWidth;
8291
8417
  if (this._isSnappingMethodAdvanced) {
8292
8418
  this.updateRegularRenderer();
8293
8419
  }
8294
8420
  this.updateOffsetsByAllignment();
8295
8421
  scroller.delta = delta;
8422
+ prevScrollable = scroller.scrollable;
8296
8423
  if ((snapScrollToStart && this._trackBox.isSnappedToStart && scroller.scrollable) ||
8297
8424
  (snapScrollToStart && currentScrollSize <= MIN_PIXELS_FOR_PREVENT_SNAPPING)) {
8298
8425
  if (currentScrollSize !== roundedScrollPositionAfterUpdate) {
@@ -8303,10 +8430,16 @@ class NgVirtualListComponent {
8303
8430
  this._trackBox.isScrollEnd;
8304
8431
  const params = {
8305
8432
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: 0, userAction,
8306
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT,
8307
- blending: false, duration: this.animationParams().scrollToItem,
8433
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams().scrollToItem > 0 && this.scrollBehavior() !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT),
8434
+ blending: useAnimations && scroller.hasAnimation(this._animationId), duration: this.animationParams().scrollToItem,
8308
8435
  };
8309
- scroller?.scrollTo?.(params);
8436
+ const animationId = scroller?.scrollTo?.(params);
8437
+ if (animationId > -1) {
8438
+ this._animationId = animationId;
8439
+ }
8440
+ else {
8441
+ scroller.stopAnimation(this._animationId);
8442
+ }
8310
8443
  if (emitUpdate) {
8311
8444
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
8312
8445
  }
@@ -8326,10 +8459,16 @@ class NgVirtualListComponent {
8326
8459
  }
8327
8460
  const params = {
8328
8461
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: roundedMaxPositionAfterUpdate,
8329
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT, userAction: false,
8330
- blending: false, duration: this.animationParams().scrollToItem,
8462
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams().scrollToItem > 0 && this.scrollBehavior() !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT), userAction: false,
8463
+ blending: useAnimations && scroller.hasAnimation(this._animationId) || cacheChanged, duration: this.animationParams().scrollToItem,
8331
8464
  };
8332
- scroller?.scrollTo?.(params);
8465
+ const animationId = scroller?.scrollTo?.(params);
8466
+ if (animationId > -1) {
8467
+ this._animationId = animationId;
8468
+ }
8469
+ else {
8470
+ scroller.stopAnimation(this._animationId);
8471
+ }
8333
8472
  if (emitUpdate) {
8334
8473
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
8335
8474
  }
@@ -8342,9 +8481,13 @@ class NgVirtualListComponent {
8342
8481
  if (this._readyForShow) {
8343
8482
  this.emitScrollEvent(true, false, userAction);
8344
8483
  }
8484
+ if (this._animationId > -1) {
8485
+ scroller.stopAnimation(this._animationId);
8486
+ this._animationId = -1;
8487
+ }
8345
8488
  const params = {
8346
8489
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollPositionAfterUpdate, blending: true, userAction,
8347
- fireUpdate, behavior: BEHAVIOR_INSTANT, duration: this.animationParams().scrollToItem,
8490
+ fireUpdate, behavior: BEHAVIOR_INSTANT, duration: 0,
8348
8491
  };
8349
8492
  scroller.scrollTo(params);
8350
8493
  if (emitUpdate) {
@@ -9031,7 +9174,7 @@ class NgVirtualListComponent {
9031
9174
  this._isScrollStart.set(false);
9032
9175
  this._isScrollEnd.set(false);
9033
9176
  this._trackBox.preventScrollSnapping(true);
9034
- if (scroller) {
9177
+ if (!!scroller) {
9035
9178
  scroller.stopScrolling();
9036
9179
  }
9037
9180
  }
@@ -9057,7 +9200,7 @@ class NgVirtualListComponent {
9057
9200
  comp?.destroy();
9058
9201
  }
9059
9202
  }
9060
- if (this._displayComponents) {
9203
+ if (!!this._displayComponents) {
9061
9204
  while (this._displayComponents.length > 0) {
9062
9205
  const comp = this._displayComponents.shift();
9063
9206
  comp?.destroy();