ng-virtual-list 21.12.2 → 21.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,32 @@ 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
+ updateTo(value) {
4061
+ this._endValue = value;
4062
+ this._diff = this._endValue - this._startValue;
4063
+ return this.hasAnimation();
4064
+ }
3976
4065
  animate(params) {
3977
4066
  this.stop();
3978
4067
  const id = this.generateId();
3979
4068
  this._currentId = id;
3980
4069
  const { withDelta = DEFAULT_WITH_DELTA, startValue, endValue, duration = DEFAULT_ANIMATION_DURATION, getPropValue, easingFunction = easeLinear, onUpdate, onComplete, } = params;
4070
+ this._startValue = startValue;
4071
+ this._endValue = endValue;
3981
4072
  const startTime = performance.now();
3982
- let isCanceled = false, prevPos = startValue, start = startValue, startPosDelta = 0, delta = 0, prevTime = startTime, diff = endValue - start, isFinished = false;
4073
+ let isCanceled = false, prevPos = startValue, startPosDelta = 0, delta = 0, prevTime = startTime, isFinished = false;
4074
+ this._diff = this._endValue - this._startValue;
3983
4075
  const step = (currentTime) => {
3984
4076
  if (id !== this._currentId) {
3985
4077
  isCanceled = true;
@@ -3993,10 +4085,10 @@ class Animator {
3993
4085
  startDelta = cPos - prevPos;
3994
4086
  startPosDelta += startDelta;
3995
4087
  }
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();
4088
+ const elapsed = currentTime - startTime, progress = this._startValue === endValue ? 1 : Math.min(duration > 0 ? elapsed / duration : 0, 1), easedProgress = easingFunction(progress), val = (withDelta ? startPosDelta : 0) + this._startValue + this._diff * easedProgress, currentValue = val, t = performance.now();
3997
4089
  isFinished = progress === 1;
3998
4090
  delta = currentValue - startDelta - prevPos;
3999
- const ts = t - prevTime, timestamp = ts < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : ts;
4091
+ const frameTimestamp = t - prevTime, actualFrameTimestamp = frameTimestamp < ANIMATOR_MIN_TIMESTAMP ? ANIMATOR_MIN_TIMESTAMP : frameTimestamp;
4000
4092
  prevTime = t;
4001
4093
  prevPos = currentValue;
4002
4094
  if (onUpdate !== undefined) {
@@ -4005,18 +4097,19 @@ class Animator {
4005
4097
  delta,
4006
4098
  elapsed,
4007
4099
  value: !withDelta && isFinished ? endValue : currentValue,
4008
- timestamp,
4100
+ timestamp: actualFrameTimestamp,
4009
4101
  };
4010
4102
  onUpdate(data);
4011
4103
  }
4012
4104
  if (isFinished) {
4105
+ this._animationId = -1;
4013
4106
  if (onComplete !== undefined) {
4014
4107
  const data = {
4015
4108
  id,
4016
4109
  delta,
4017
4110
  elapsed,
4018
4111
  value: withDelta ? currentValue : endValue,
4019
- timestamp,
4112
+ timestamp: actualFrameTimestamp,
4020
4113
  };
4021
4114
  onComplete(data);
4022
4115
  }
@@ -4026,9 +4119,17 @@ class Animator {
4026
4119
  }
4027
4120
  };
4028
4121
  this._animationId = requestAnimationFrame(step);
4122
+ return this._currentId;
4123
+ }
4124
+ hasAnimation(id = -1) {
4125
+ if ((this._currentId === id || id === -1) && this.animated) {
4126
+ return true;
4127
+ }
4128
+ return false;
4029
4129
  }
4030
- stop() {
4031
- cancelAnimationFrame(this._animationId);
4130
+ stop(id = -1) {
4131
+ cancelAnimationFrame(id === -1 ? this._animationId : id);
4132
+ this._animationId = -1;
4032
4133
  }
4033
4134
  dispose() {
4034
4135
  this.stop();
@@ -4465,6 +4566,7 @@ class NgScrollView extends BaseScrollView {
4465
4566
  get startLayoutOffset() { return this._startLayoutOffset; }
4466
4567
  _intersectionComponentId = null;
4467
4568
  _isAlignmentAnimation = false;
4569
+ get animated() { return this._animator?.isAnimated ?? false; }
4468
4570
  constructor() {
4469
4571
  super();
4470
4572
  let mouseCanceled = false, touchCanceled = false;
@@ -4656,6 +4758,7 @@ class NgScrollView extends BaseScrollView {
4656
4758
  }));
4657
4759
  })).subscribe();
4658
4760
  }
4761
+ hasAnimation(id = -1) { return this._animator?.hasAnimation(id) ?? false; }
4659
4762
  updateDirection(position, prePosition) {
4660
4763
  const delta = (position - this._delta) - prePosition;
4661
4764
  this._scrollDirection.add(delta > 0 ? 1 : delta < 0 ? -1 : 0);
@@ -4818,7 +4921,7 @@ class NgScrollView extends BaseScrollView {
4818
4921
  moveWithAcceleration(isVertical, position, v0, v, a0, timestamp) {
4819
4922
  if (a0 !== 0 && timestamp < MAX_VELOCITY_TIMESTAMP) {
4820
4923
  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);
4924
+ this.animate(startPosition, Math.round(positionWithVelocity), aDuration, easeOutQuad, false, true);
4822
4925
  }
4823
4926
  else {
4824
4927
  this.alignPosition(true, true);
@@ -4831,11 +4934,17 @@ class NgScrollView extends BaseScrollView {
4831
4934
  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
4935
  return result;
4833
4936
  }
4834
- animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
4937
+ animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, blending = false, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
4835
4938
  const isVertical = this.isVertical();
4836
4939
  let position = startValue;
4837
4940
  this._isAlignmentAnimation = !alignmentAtComplete;
4838
- this._animator.animate({
4941
+ if (this.hasAnimation() && blending) {
4942
+ const updatable = this._animator.updateTo(endValue);
4943
+ if (updatable) {
4944
+ return this._animator.id;
4945
+ }
4946
+ }
4947
+ return this._animator.animate({
4839
4948
  withDelta: this._service.dynamic && !this.isInfinity(),
4840
4949
  startValue,
4841
4950
  endValue,
@@ -4847,7 +4956,7 @@ class NgScrollView extends BaseScrollView {
4847
4956
  if (this._isCoordinatesOverrided && !skipOverridedCoordinates) {
4848
4957
  this._isCoordinatesOverrided = false;
4849
4958
  const currentCoordinate = isVertical ? this._y : this._x, delta = endValue - value;
4850
- this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, userAction, alignmentAtComplete);
4959
+ this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, blending, userAction, alignmentAtComplete);
4851
4960
  return;
4852
4961
  }
4853
4962
  const v0 = calculateVelocity(position, value - this._delta, timestamp) ?? this.averageVelocity;
@@ -4979,7 +5088,7 @@ class NgScrollView extends BaseScrollView {
4979
5088
  const cPos = (isVertical ? this.scrollTop : this.scrollLeft);
4980
5089
  if (position !== null && position !== cPos) {
4981
5090
  this.stopScrolling(true);
4982
- this.animate(cPos, position, animated ? this.animationParams().snapToItem : 1, easeOutQuad, false, false, true);
5091
+ this.animate(cPos, position, animated ? this.animationParams().snapToItem : 1, easeOutQuad, false, false, false, true);
4983
5092
  return true;
4984
5093
  }
4985
5094
  return false;
@@ -5065,21 +5174,18 @@ class NgScrollView extends BaseScrollView {
5065
5174
  if (behavior === AUTO || behavior === SMOOTH) {
5066
5175
  if (isVertical) {
5067
5176
  if (prevY !== y) {
5068
- this.animate(prevY, y, duration, ease, userAction);
5177
+ return this.animate(prevY, y, duration, ease, blending, userAction);
5069
5178
  }
5070
5179
  }
5071
5180
  else {
5072
5181
  if (prevX !== x) {
5073
- this.animate(prevX, x, duration, ease, userAction);
5182
+ return this.animate(prevX, x, duration, ease, blending, userAction);
5074
5183
  }
5075
5184
  }
5076
5185
  }
5077
5186
  else {
5078
5187
  if (isVertical) {
5079
5188
  if (this._y !== y || force) {
5080
- if (!blending) {
5081
- this.stopScrolling(force);
5082
- }
5083
5189
  this.setY(y, snap, normalize);
5084
5190
  this.emitScrollableEvent();
5085
5191
  if (fireUpdate) {
@@ -5089,9 +5195,6 @@ class NgScrollView extends BaseScrollView {
5089
5195
  }
5090
5196
  else {
5091
5197
  if (this._x !== x || force) {
5092
- if (!blending) {
5093
- this.stopScrolling(force);
5094
- }
5095
5198
  this.setX(x, snap, normalize);
5096
5199
  this.emitScrollableEvent();
5097
5200
  if (fireUpdate) {
@@ -5100,6 +5203,7 @@ class NgScrollView extends BaseScrollView {
5100
5203
  }
5101
5204
  }
5102
5205
  }
5206
+ return -1;
5103
5207
  }
5104
5208
  emitScrollableEvent() {
5105
5209
  if (!!this.cdkScrollable) {
@@ -5118,6 +5222,9 @@ class NgScrollView extends BaseScrollView {
5118
5222
  this.stopScrolling();
5119
5223
  this.move(this.isVertical(), offset);
5120
5224
  }
5225
+ stopAnimation(id) {
5226
+ this._animator.stop(id);
5227
+ }
5121
5228
  ngOnDestroy() {
5122
5229
  if (this._animator) {
5123
5230
  this._animator.dispose();
@@ -5496,6 +5603,10 @@ class NgScrollerComponent extends NgScrollView {
5496
5603
  $updateScrollBar.pipe(takeUntilDestroyed(this._destroyRef), debounceTime(0), tap(() => {
5497
5604
  this.updateScrollBarHandler(!this._isScrollbarUserAction);
5498
5605
  })).subscribe();
5606
+ effect(() => {
5607
+ const grabbing = this.grabbing();
5608
+ this._service.grabbing = grabbing;
5609
+ });
5499
5610
  this.actualClasses = computed(() => {
5500
5611
  const classes = this.classes(), direction = this.direction(), filtered = this.motionBlurEnabled();
5501
5612
  return { ...classes, [direction]: true, grabbing: this.grabbing(), filtered };
@@ -5633,7 +5744,7 @@ class NgScrollerComponent extends NgScrollView {
5633
5744
  this._isScrollbarUserAction = false;
5634
5745
  this.scrollBar?.stopScrolling();
5635
5746
  }
5636
- this.scroll({ ...params, userAction: userAction });
5747
+ return this.scroll({ ...params, userAction: userAction });
5637
5748
  }
5638
5749
  stopScrollbar() {
5639
5750
  if (!!this.scrollBar) {
@@ -6002,14 +6113,14 @@ class NgPrerenderVirtualListItemComponent extends NgVirtualListItemComponent {
6002
6113
  }
6003
6114
  }
6004
6115
  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 });
6116
+ 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
6117
  }
6007
6118
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgPrerenderVirtualListItemComponent, decorators: [{
6008
6119
  type: Component,
6009
6120
  args: [{ selector: 'ng-prerender-virtual-list-item', host: {
6010
6121
  'class': 'ngvl__item',
6011
6122
  '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"] }]
6123
+ }, 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
6124
  }] });
6014
6125
 
6015
6126
  /**
@@ -7029,7 +7140,7 @@ class NgVirtualListComponent {
7029
7140
  },
7030
7141
  };
7031
7142
  /**
7032
- * Animation parameters. The default value is "{ scrollToItem: 50, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
7143
+ * Animation parameters. The default value is "{ scrollToItem: 150, snapToItem: 150, navigateToItem: 150, navigateByKeyboard: 50 }".
7033
7144
  */
7034
7145
  animationParams = input(DEFAULT_ANIMATION_PARAMS, { ...(ngDevMode ? { debugName: "animationParams" } : {}), ...this._animationParamsOptions });
7035
7146
  _overscrollEnabledOptions = {
@@ -7503,6 +7614,7 @@ class NgVirtualListComponent {
7503
7614
  _readyForShow = false;
7504
7615
  _cached = false;
7505
7616
  _isLoading = false;
7617
+ _animationId = -1;
7506
7618
  get cachable() {
7507
7619
  return this._prerender()?.active ?? false;
7508
7620
  }
@@ -7517,6 +7629,7 @@ class NgVirtualListComponent {
7517
7629
  NgVirtualListComponent.__nextId = NgVirtualListComponent.__nextId + 1 === Number.MAX_SAFE_INTEGER
7518
7630
  ? 0 : NgVirtualListComponent.__nextId + 1;
7519
7631
  this._id = NgVirtualListComponent.__nextId;
7632
+ let readyForAnimations = false;
7520
7633
  const _$created = new BehaviorSubject(false), $created = _$created.asObservable();
7521
7634
  combineLatest([$created, this.$show]).pipe(takeUntilDestroyed(), filter$1(([created, shown]) => created && shown), debounceTime(1), tap(v => {
7522
7635
  this._$initialized.next(true);
@@ -7753,6 +7866,7 @@ class NgVirtualListComponent {
7753
7866
  }), tap(items => {
7754
7867
  this._trackBox.resetCollection(items, this._actualItemSize());
7755
7868
  }), switchMap$1(i => of((i ?? []).length > 0)), distinctUntilChanged(), tap(v => {
7869
+ readyForAnimations = false;
7756
7870
  if (!v) {
7757
7871
  this.cacheClean();
7758
7872
  this.cleanup();
@@ -8094,12 +8208,22 @@ class NgVirtualListComponent {
8094
8208
  }), debounceTime(100), tap(() => {
8095
8209
  this._isLoading = false;
8096
8210
  })).subscribe();
8211
+ let prevCacheVersion = -1, prevScrollable = false;
8212
+ $viewInit.pipe(takeUntilDestroyed(), filter$1(v => !!v), switchMap$1(() => {
8213
+ return this.$show.pipe(takeUntilDestroyed(this._destroyRef), debounceTime(Math.max(500, this.animationParams().scrollToItem)), tap(() => {
8214
+ if (this._readyForShow || (this.cachable && this._cached)) {
8215
+ readyForAnimations = true;
8216
+ }
8217
+ }));
8218
+ })).subscribe();
8097
8219
  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;
8220
+ const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, cacheVersion, itemTransform, } = params;
8221
+ const cacheChanged = prevCacheVersion !== cacheVersion;
8222
+ prevCacheVersion = cacheVersion;
8099
8223
  const scroller = this._scrollerComponent();
8100
8224
  let totalSize = 0;
8101
8225
  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;
8226
+ 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
8227
  if (this._readyForShow || (cachable && cached)) {
8104
8228
  const currentScrollSize = (isVertical ? scroller.scrollTop : scroller.scrollLeft);
8105
8229
  let actualScrollSize = !this._readyForShow && snapScrollToEnd ? (isVertical ? scroller.scrollHeight : scroller.scrollWidth) :
@@ -8143,12 +8267,13 @@ class NgVirtualListComponent {
8143
8267
  if (!_$created.getValue()) {
8144
8268
  _$created.next(true);
8145
8269
  }
8146
- const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.scrollHeight : scroller.scrollWidth;
8270
+ const delta = this._trackBox.delta, scrollPositionAfterUpdate = actualScrollSize + delta, roundedScrollPositionAfterUpdate = scrollPositionAfterUpdate, roundedMaxPositionAfterUpdate = isVertical ? scroller.actualScrollHeight : scroller.actualScrollWidth;
8147
8271
  if (this._isSnappingMethodAdvanced) {
8148
8272
  this.updateRegularRenderer();
8149
8273
  }
8150
8274
  this.updateOffsetsByAllignment();
8151
8275
  scroller.delta = delta;
8276
+ prevScrollable = scroller.scrollable;
8152
8277
  if ((snapScrollToStart && this._trackBox.isSnappedToStart && scroller.scrollable) ||
8153
8278
  (snapScrollToStart && currentScrollSize <= MIN_PIXELS_FOR_PREVENT_SNAPPING)) {
8154
8279
  if (currentScrollSize !== roundedScrollPositionAfterUpdate) {
@@ -8159,10 +8284,16 @@ class NgVirtualListComponent {
8159
8284
  this._trackBox.isScrollEnd;
8160
8285
  const params = {
8161
8286
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: 0, userAction,
8162
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT,
8163
- blending: false, duration: this.animationParams().scrollToItem,
8287
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams().scrollToItem > 0 && this.scrollBehavior() !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT),
8288
+ blending: useAnimations && scroller.hasAnimation(this._animationId), duration: this.animationParams().scrollToItem,
8164
8289
  };
8165
- scroller?.scrollTo?.(params);
8290
+ const animationId = scroller?.scrollTo?.(params);
8291
+ if (animationId > -1) {
8292
+ this._animationId = animationId;
8293
+ }
8294
+ else {
8295
+ scroller.stopAnimation(this._animationId);
8296
+ }
8166
8297
  if (emitUpdate) {
8167
8298
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
8168
8299
  }
@@ -8182,10 +8313,16 @@ class NgVirtualListComponent {
8182
8313
  }
8183
8314
  const params = {
8184
8315
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: roundedMaxPositionAfterUpdate,
8185
- fireUpdate: fireUpdateAtEdges, behavior: BEHAVIOR_INSTANT, userAction: false,
8186
- blending: false, duration: this.animationParams().scrollToItem,
8316
+ fireUpdate: fireUpdateAtEdges, behavior: !useAnimations ? BEHAVIOR_INSTANT : ((this.animationParams().scrollToItem > 0 && this.scrollBehavior() !== BEHAVIOR_INSTANT) ? BEHAVIOR_AUTO : BEHAVIOR_INSTANT), userAction: false,
8317
+ blending: useAnimations && scroller.hasAnimation(this._animationId) || cacheChanged, duration: this.animationParams().scrollToItem,
8187
8318
  };
8188
- scroller?.scrollTo?.(params);
8319
+ const animationId = scroller?.scrollTo?.(params);
8320
+ if (animationId > -1) {
8321
+ this._animationId = animationId;
8322
+ }
8323
+ else {
8324
+ scroller.stopAnimation(this._animationId);
8325
+ }
8189
8326
  if (emitUpdate) {
8190
8327
  this._$update.next(getScrollStateVersion(totalSize, this._isVertical ? scroller.scrollTop : scroller.scrollLeft));
8191
8328
  }
@@ -8198,9 +8335,13 @@ class NgVirtualListComponent {
8198
8335
  if (this._readyForShow) {
8199
8336
  this.emitScrollEvent(true, false, userAction);
8200
8337
  }
8338
+ if (this._animationId > -1) {
8339
+ scroller.stopAnimation(this._animationId);
8340
+ this._animationId = -1;
8341
+ }
8201
8342
  const params = {
8202
8343
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollPositionAfterUpdate, blending: true, userAction,
8203
- fireUpdate, behavior: BEHAVIOR_INSTANT, duration: this.animationParams().scrollToItem,
8344
+ fireUpdate, behavior: BEHAVIOR_INSTANT, duration: 0,
8204
8345
  };
8205
8346
  scroller.scrollTo(params);
8206
8347
  if (emitUpdate) {
@@ -8887,7 +9028,7 @@ class NgVirtualListComponent {
8887
9028
  this._isScrollStart.set(false);
8888
9029
  this._isScrollEnd.set(false);
8889
9030
  this._trackBox.preventScrollSnapping(true);
8890
- if (scroller) {
9031
+ if (!!scroller) {
8891
9032
  scroller.stopScrolling();
8892
9033
  }
8893
9034
  }
@@ -8913,7 +9054,7 @@ class NgVirtualListComponent {
8913
9054
  comp?.destroy();
8914
9055
  }
8915
9056
  }
8916
- if (this._displayComponents) {
9057
+ if (!!this._displayComponents) {
8917
9058
  while (this._displayComponents.length > 0) {
8918
9059
  const comp = this._displayComponents.shift();
8919
9060
  comp?.destroy();