ng-virtual-list 19.3.7-beta-1 → 19.4.0

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.
package/README.md CHANGED
@@ -25,7 +25,7 @@ npm i ng-virtual-list
25
25
 
26
26
  Template:
27
27
  ```html
28
- <ng-virtual-list class="list" direction="horizontal" [items]="horizontalItems" [itemsOffset]="50"
28
+ <ng-virtual-list class="list" direction="horizontal" [items]="horizontalItems" [bufferSize]="50"
29
29
  [itemRenderer]="horizontalItemRenderer" [itemSize]="64"></ng-virtual-list>
30
30
 
31
31
  <ng-template #horizontalItemRenderer let-data="data">
@@ -64,7 +64,7 @@ export class AppComponent {
64
64
  Template:
65
65
  ```html
66
66
  <ng-virtual-list class="list" direction="horizontal" [items]="horizontalGroupItems" [itemRenderer]="horizontalGroupItemRenderer"
67
- [itemsOffset]="50" [stickyMap]="horizontalGroupItemsStickyMap" [itemSize]="54" [snap]="true"></ng-virtual-list>
67
+ [bufferSize]="50" [stickyMap]="horizontalGroupItemsStickyMap" [itemSize]="54" [snap]="true"></ng-virtual-list>
68
68
 
69
69
  <ng-template #horizontalGroupItemRenderer let-data="data">
70
70
  @if (data) {
@@ -121,7 +121,7 @@ export class AppComponent {
121
121
 
122
122
  Template:
123
123
  ```html
124
- <ng-virtual-list class="list simple" [items]="items" [itemsOffset]="50" [itemRenderer]="itemRenderer"
124
+ <ng-virtual-list class="list simple" [items]="items" [bufferSize]="50" [itemRenderer]="itemRenderer"
125
125
  [itemSize]="40"></ng-virtual-list>
126
126
 
127
127
  <ng-template #itemRenderer let-data="data">
@@ -162,7 +162,7 @@ export class AppComponent {
162
162
 
163
163
  Template:
164
164
  ```html
165
- <ng-virtual-list class="list simple" [items]="groupItems" [itemsOffset]="50" [itemRenderer]="groupItemRenderer"
165
+ <ng-virtual-list class="list simple" [items]="groupItems" [bufferSize]="50" [itemRenderer]="groupItemRenderer"
166
166
  [stickyMap]="groupItemsStickyMap" [itemSize]="40" [snap]="false"></ng-virtual-list>
167
167
 
168
168
  <ng-template #groupItemRenderer let-data="data">
@@ -189,7 +189,7 @@ Template:
189
189
 
190
190
  Template (with snapping):
191
191
  ```html
192
- <ng-virtual-list class="list simple" [items]="groupItems" [itemsOffset]="50" [itemRenderer]="groupItemRenderer"
192
+ <ng-virtual-list class="list simple" [items]="groupItems" [bufferSize]="50" [itemRenderer]="groupItemRenderer"
193
193
  [stickyMap]="groupItemsStickyMap" [itemSize]="40" [snap]="true"></ng-virtual-list>
194
194
 
195
195
  <ng-template #groupItemRenderer let-data="data">
@@ -254,7 +254,7 @@ Template
254
254
  <button class="scroll-to__button" (click)="onButtonScrollToIdClickHandler($event)">Scroll</button>
255
255
  </div>
256
256
 
257
- <ng-virtual-list #virtualList class="list" [items]="items" [itemRenderer]="itemRenderer" [itemsOffset]="50"
257
+ <ng-virtual-list #virtualList class="list" [items]="items" [itemRenderer]="itemRenderer" [bufferSize]="50"
258
258
  [itemSize]="40"></ng-virtual-list>
259
259
 
260
260
  <ng-template #itemRenderer let-data="data">
@@ -308,7 +308,7 @@ Virtual list with height-adjustable elements.
308
308
 
309
309
  Template
310
310
  ```html
311
- <ng-virtual-list #dynamicList class="list" [items]="groupDynamicItems" [itemRenderer]="groupItemRenderer" [itemsOffset]="10"
311
+ <ng-virtual-list #dynamicList class="list" [items]="groupDynamicItems" [itemRenderer]="groupItemRenderer" [bufferSize]="10"
312
312
  [stickyMap]="groupDynamicItemsStickyMap" [dynamicSize]="true" [snap]="true"></ng-virtual-list>
313
313
 
314
314
  <ng-template #groupItemRenderer let-data="data">
@@ -453,7 +453,8 @@ Inputs
453
453
  | id | number | Readonly. Returns the unique identifier of the component. |
454
454
  | items | [IVirtualListCollection](https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/models/collection.model.ts) | Collection of list items. The collection of elements must be immutable. |
455
455
  | itemSize | number? = 24 | If direction = 'vertical', then the height of a typical element. If direction = 'horizontal', then the width of a typical element. Ignored if the dynamicSize property is true. |
456
- | itemsOffset | number? = 2 | Number of elements outside the scope of visibility. Default value is 2. |
456
+ | bufferSize | number? = 2 | Number of elements outside the scope of visibility. Default value is 2. |
457
+ | maxBufferSize | number? = 100 | Maximum number of elements outside the scope of visibility. Default value is 100. If maxBufferSize is set to be greater than bufferSize, then adaptive buffer mode is enabled. The greater the scroll size, the more elements are allocated for rendering. |
457
458
  | itemRenderer | TemplateRef | Rendering element template. |
458
459
  | stickyMap | [IVirtualListStickyMap?](https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/models/sticky-map.model.ts) | Dictionary zIndex by id of the list element. If the value is not set or equal to 0, then a simple element is displayed, if the value is greater than 0, then the sticky position mode is enabled for the element. 1 - position start, 2 - position end. |
459
460
  | snap | boolean? = false | Determines whether elements will snap. Default value is "false". |
@@ -42,7 +42,8 @@ var SnappingMethods;
42
42
  })(SnappingMethods || (SnappingMethods = {}));
43
43
 
44
44
  const DEFAULT_ITEM_SIZE = 24;
45
- const DEFAULT_ITEMS_OFFSET = 2;
45
+ const DEFAULT_BUFFER_SIZE = 2;
46
+ const DEFAULT_MAX_BUFFER_SIZE = 100;
46
47
  const DEFAULT_LIST_SIZE = 400;
47
48
  const DEFAULT_SNAP = false;
48
49
  const DEFAULT_ENABLED_BUFFER_OPTIMIZATION = false;
@@ -205,13 +206,13 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
205
206
  styles.zIndex = HIDDEN_ZINDEX;
206
207
  }
207
208
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
208
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: NgVirtualListItemComponent, isStandalone: true, selector: "ng-virtual-list-item", host: { classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let item = data();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': item.config.snapped,\r\n 'snapped-out': item.config.snappedOut}\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\"\r\n [ngTemplateOutletContext]=\"{data: item.data || {}, config: item.config}\" />\r\n }\r\n </li>\r\n}", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;will-change:scroll-position}.ngvl-item__container{margin:0;padding:0;overflow:hidden;background-color:#fff;width:inherit;height:inherit}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
209
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: NgVirtualListItemComponent, isStandalone: true, selector: "ng-virtual-list-item", host: { classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let item = data();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': item.config.snapped,\r\n 'snapped-out': item.config.snappedOut}\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\"\r\n [ngTemplateOutletContext]=\"{data: item.data || {}, config: item.config}\" />\r\n }\r\n </li>\r\n}", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden}.ngvl-item__container{margin:0;padding:0;overflow:hidden;background-color:#fff;width:inherit;height:inherit}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
209
210
  }
210
211
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
211
212
  type: Component,
212
213
  args: [{ selector: 'ng-virtual-list-item', imports: [CommonModule], host: {
213
214
  'class': 'ngvl__item',
214
- }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let item = data();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': item.config.snapped,\r\n 'snapped-out': item.config.snappedOut}\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\"\r\n [ngTemplateOutletContext]=\"{data: item.data || {}, config: item.config}\" />\r\n }\r\n </li>\r\n}", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;will-change:scroll-position}.ngvl-item__container{margin:0;padding:0;overflow:hidden;background-color:#fff;width:inherit;height:inherit}\n"] }]
215
+ }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let item = data();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': item.config.snapped,\r\n 'snapped-out': item.config.snappedOut}\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\"\r\n [ngTemplateOutletContext]=\"{data: item.data || {}, config: item.config}\" />\r\n }\r\n </li>\r\n}", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden}.ngvl-item__container{margin:0;padding:0;overflow:hidden;background-color:#fff;width:inherit;height:inherit}\n"] }]
215
216
  }], ctorParameters: () => [] });
216
217
 
217
218
  const HORIZONTAL_ALIASES = [Directions.HORIZONTAL, 'horizontal'], VERTICAL_ALIASES = [Directions.VERTICAL, 'vertical'];
@@ -680,6 +681,33 @@ class CacheMap extends EventEmitter {
680
681
  }
681
682
  }
682
683
 
684
+ const DEFAULT_EXTRA = {
685
+ extremumThreshold: 2,
686
+ bufferSize: 10,
687
+ };
688
+ const bufferInterpolation = (currentBufferValue, array, value, extra) => {
689
+ const { extremumThreshold = DEFAULT_EXTRA.extremumThreshold, bufferSize = DEFAULT_EXTRA.bufferSize, } = extra ?? DEFAULT_EXTRA;
690
+ if (currentBufferValue < value) {
691
+ let i = 0;
692
+ while (i < extremumThreshold) {
693
+ array.push(value);
694
+ i++;
695
+ }
696
+ }
697
+ else {
698
+ array.push(value);
699
+ }
700
+ while (array.length >= bufferSize) {
701
+ array.shift();
702
+ }
703
+ const l = array.length;
704
+ let buffer = 0;
705
+ for (let i = 0; i < l; i++) {
706
+ buffer += array[i];
707
+ }
708
+ return Math.ceil(buffer / l);
709
+ };
710
+
683
711
  const TRACK_BOX_CHANGE_EVENT_NAME = 'change';
684
712
  var ItemDisplayMethods;
685
713
  (function (ItemDisplayMethods) {
@@ -688,6 +716,7 @@ var ItemDisplayMethods;
688
716
  ItemDisplayMethods[ItemDisplayMethods["DELETE"] = 2] = "DELETE";
689
717
  ItemDisplayMethods[ItemDisplayMethods["NOT_CHANGED"] = 3] = "NOT_CHANGED";
690
718
  })(ItemDisplayMethods || (ItemDisplayMethods = {}));
719
+ const DEFAULT_BUFFER_EXTREMUM_THRESHOLD = 15, DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH = 30, DEFAULT_RESET_BUFFER_SIZE_TIMEOUT = 10000;
691
720
  /**
692
721
  * An object that performs tracking, calculations and caching.
693
722
  * @link https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/utils/trackBox.ts
@@ -758,12 +787,15 @@ class TrackBox extends CacheMap {
758
787
  _scrollDelta = 0;
759
788
  get scrollDelta() { return this._scrollDelta; }
760
789
  isAdaptiveBuffer = true;
761
- _maxBufferSize = 200;
762
- _maxBufferSizeSequenceLength = 100;
790
+ _bufferSequenceExtraThreshold = DEFAULT_BUFFER_EXTREMUM_THRESHOLD;
791
+ _maxBufferSequenceLength = DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH;
763
792
  _bufferSizeSequence = [];
764
793
  _bufferSize = 0;
765
794
  get bufferSize() { return this._bufferSize; }
766
795
  _defaultBufferSize = 0;
796
+ _maxBufferSize = this._defaultBufferSize;
797
+ _resetBufferSizeTimeout = DEFAULT_RESET_BUFFER_SIZE_TIMEOUT;
798
+ _resetBufferSizeTimer;
767
799
  lifeCircle() {
768
800
  this.fireChangeIfNeed();
769
801
  this.lifeCircleDo();
@@ -857,7 +889,8 @@ class TrackBox extends CacheMap {
857
889
  */
858
890
  getItemPosition(id, stickyMap, options) {
859
891
  const opt = { fromItemId: id, stickyMap, ...options };
860
- this._defaultBufferSize = opt.itemsOffset;
892
+ this._defaultBufferSize = opt.bufferSize;
893
+ this._maxBufferSize = opt.maxBufferSize;
861
894
  const { scrollSize, isFromItemIdFound } = this.recalculateMetrics({
862
895
  ...opt,
863
896
  dynamicSize: this._crudDetected || opt.dynamicSize,
@@ -875,7 +908,8 @@ class TrackBox extends CacheMap {
875
908
  if (opt.dynamicSize) {
876
909
  this.cacheElements();
877
910
  }
878
- this._defaultBufferSize = opt.itemsOffset;
911
+ this._defaultBufferSize = opt.bufferSize;
912
+ this._maxBufferSize = opt.maxBufferSize;
879
913
  const metrics = this.recalculateMetrics({
880
914
  ...opt,
881
915
  collection: items,
@@ -902,19 +936,24 @@ class TrackBox extends CacheMap {
902
936
  }
903
937
  _previousScrollSize = 0;
904
938
  updateAdaptiveBufferParams(metrics, totalItemsLength) {
939
+ this.disposeClearBufferSizeTimer();
905
940
  const scrollSize = metrics.scrollSize + this._delta, delta = Math.abs(this._previousScrollSize - scrollSize);
906
941
  this._previousScrollSize = scrollSize;
907
- const bufferSize = Math.min(Math.floor(delta / metrics.typicalItemSize) * 5, totalItemsLength), actualBufferSize = bufferSize < this._defaultBufferSize ? this._defaultBufferSize : bufferSize, buff = actualBufferSize > this._maxBufferSize ? this._maxBufferSize : actualBufferSize;
908
- this._bufferSizeSequence.push(buff);
909
- while (this._bufferSizeSequence.length >= this._maxBufferSizeSequenceLength) {
910
- this._bufferSizeSequence.shift();
911
- }
912
- const l = this._bufferSizeSequence.length;
913
- let buffer = 0;
914
- for (let i = 0; i < l; i++) {
915
- buffer += this._bufferSizeSequence[i];
916
- }
917
- this._bufferSize = Math.ceil(buffer / l);
942
+ const bufferRawSize = Math.min(Math.floor(delta / metrics.typicalItemSize) * 5, totalItemsLength), minBufferSize = bufferRawSize < this._defaultBufferSize ? this._defaultBufferSize : bufferRawSize, bufferValue = minBufferSize > this._maxBufferSize ? this._maxBufferSize : minBufferSize;
943
+ this._bufferSize = bufferInterpolation(this._bufferSize, this._bufferSizeSequence, bufferValue, {
944
+ extremumThreshold: this._bufferSequenceExtraThreshold,
945
+ bufferSize: this._maxBufferSequenceLength,
946
+ });
947
+ this.startResetBufferSizeTimer();
948
+ }
949
+ startResetBufferSizeTimer() {
950
+ this._resetBufferSizeTimer = setTimeout(() => {
951
+ this._bufferSize = this._defaultBufferSize;
952
+ this._bufferSizeSequence = [];
953
+ }, this._resetBufferSizeTimeout);
954
+ }
955
+ disposeClearBufferSizeTimer() {
956
+ clearTimeout(this._resetBufferSizeTimer);
918
957
  }
919
958
  /**
920
959
  * Calculates the position of an element based on the given scrollSize
@@ -967,9 +1006,8 @@ class TrackBox extends CacheMap {
967
1006
  * Calculates list metrics
968
1007
  */
969
1008
  recalculateMetrics(options) {
970
- const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, itemsOffset, scrollSize, snap, stickyMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options;
971
- const bufferSize = Math.max(itemsOffset, this._bufferSize);
972
- const { width, height } = bounds, sizeProperty = isVertical ? HEIGHT_PROP_NAME : WIDTH_PROP_NAME, size = isVertical ? height : width, totalLength = collection.length, typicalItemSize = itemSize, w = isVertical ? width : typicalItemSize, h = isVertical ? typicalItemSize : height, map = this._map, snapshot = this._snapshot, checkOverscrollItemsLimit = Math.ceil(size / typicalItemSize), snippedPos = Math.floor(scrollSize), leftItemsWeights = [], isFromId = fromItemId !== undefined && (typeof fromItemId === 'number' && fromItemId > -1)
1009
+ const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, bufferSize: minBufferSize, scrollSize, snap, stickyMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options;
1010
+ const bufferSize = Math.max(minBufferSize, this._bufferSize), { width, height } = bounds, sizeProperty = isVertical ? HEIGHT_PROP_NAME : WIDTH_PROP_NAME, size = isVertical ? height : width, totalLength = collection.length, typicalItemSize = itemSize, w = isVertical ? width : typicalItemSize, h = isVertical ? typicalItemSize : height, map = this._map, snapshot = this._snapshot, checkOverscrollItemsLimit = Math.ceil(size / typicalItemSize), snippedPos = Math.floor(scrollSize), leftItemsWeights = [], isFromId = fromItemId !== undefined && (typeof fromItemId === 'number' && fromItemId > -1)
973
1011
  || (typeof fromItemId === 'string' && fromItemId > '-1');
974
1012
  let leftItemsOffset = 0, rightItemsOffset = 0;
975
1013
  if (enabledBufferOptimization) {
@@ -1410,6 +1448,7 @@ class TrackBox extends CacheMap {
1410
1448
  }
1411
1449
  dispose() {
1412
1450
  super.dispose();
1451
+ this.disposeClearBufferSizeTimer();
1413
1452
  if (this._tracker) {
1414
1453
  this._tracker.dispose();
1415
1454
  }
@@ -1553,10 +1592,35 @@ class NgVirtualListComponent {
1553
1592
  * Determines the direction in which elements are placed. Default value is "vertical".
1554
1593
  */
1555
1594
  direction = input(DEFAULT_DIRECTION);
1595
+ _itemOffsetTransform = {
1596
+ transform: (v) => {
1597
+ throw Error('"itemOffset" parameter is deprecated. Use "bufferSize" and "maxBufferSize".');
1598
+ }
1599
+ };
1556
1600
  /**
1557
1601
  * Number of elements outside the scope of visibility. Default value is 2.
1602
+ * @deprecated "itemOffset" parameter is deprecated. Use "bufferSize" and "maxBufferSize".
1603
+ */
1604
+ itemsOffset = input(DEFAULT_BUFFER_SIZE, { ...this._itemOffsetTransform });
1605
+ /**
1606
+ * Number of elements outside the scope of visibility. Default value is 2.
1607
+ */
1608
+ bufferSize = input(DEFAULT_BUFFER_SIZE);
1609
+ _maxBufferSizeTransform = {
1610
+ transform: (v) => {
1611
+ const bufferSize = this.bufferSize();
1612
+ if (v === undefined || v <= bufferSize) {
1613
+ return bufferSize;
1614
+ }
1615
+ return v;
1616
+ }
1617
+ };
1618
+ /**
1619
+ * Maximum number of elements outside the scope of visibility. Default value is 100.
1620
+ * If maxBufferSize is set to be greater than bufferSize, then adaptive buffer mode is enabled.
1621
+ * The greater the scroll size, the more elements are allocated for rendering.
1558
1622
  */
1559
- itemsOffset = input(DEFAULT_ITEMS_OFFSET);
1623
+ maxBufferSize = input(DEFAULT_MAX_BUFFER_SIZE, { ...this._maxBufferSizeTransform });
1560
1624
  /**
1561
1625
  * Snapping method.
1562
1626
  * 'default' - Normal group rendering.
@@ -1660,7 +1724,7 @@ class NgVirtualListComponent {
1660
1724
  $trackBy.pipe(takeUntilDestroyed(), tap(v => {
1661
1725
  this._trackBox.trackingPropertyName = v;
1662
1726
  })).subscribe();
1663
- const $bounds = toObservable(this._bounds).pipe(filter(b => !!b)), $items = toObservable(this.items).pipe(map(i => !i ? [] : i)), $scrollSize = toObservable(this._scrollSize), $itemSize = toObservable(this.itemSize).pipe(map(v => v <= 0 ? DEFAULT_ITEM_SIZE : v)), $itemsOffset = toObservable(this.itemsOffset).pipe(map(v => v < 0 ? DEFAULT_ITEMS_OFFSET : v)), $stickyMap = toObservable(this.stickyMap).pipe(map(v => !v ? {} : v)), $snap = toObservable(this.snap), $isVertical = toObservable(this.direction).pipe(map(v => this.getIsVertical(v || DEFAULT_DIRECTION))), $dynamicSize = toObservable(this.dynamicSize), $enabledBufferOptimization = toObservable(this.enabledBufferOptimization), $snappingMethod = toObservable(this.snappingMethod).pipe(map(v => this.getIsSnappingMethodAdvanced(v || DEFAULT_SNAPPING_METHOD))), $cacheVersion = toObservable(this._cacheVersion);
1727
+ const $bounds = toObservable(this._bounds).pipe(filter(b => !!b)), $items = toObservable(this.items).pipe(map(i => !i ? [] : i)), $scrollSize = toObservable(this._scrollSize), $itemSize = toObservable(this.itemSize).pipe(map(v => v <= 0 ? DEFAULT_ITEM_SIZE : v)), $bufferSize = toObservable(this.bufferSize).pipe(map(v => v < 0 ? DEFAULT_BUFFER_SIZE : v)), $maxBufferSize = toObservable(this.maxBufferSize).pipe(map(v => v < 0 ? DEFAULT_BUFFER_SIZE : v)), $stickyMap = toObservable(this.stickyMap).pipe(map(v => !v ? {} : v)), $snap = toObservable(this.snap), $isVertical = toObservable(this.direction).pipe(map(v => this.getIsVertical(v || DEFAULT_DIRECTION))), $dynamicSize = toObservable(this.dynamicSize), $enabledBufferOptimization = toObservable(this.enabledBufferOptimization), $snappingMethod = toObservable(this.snappingMethod).pipe(map(v => this.getIsSnappingMethodAdvanced(v || DEFAULT_SNAPPING_METHOD))), $cacheVersion = toObservable(this._cacheVersion);
1664
1728
  $isVertical.pipe(takeUntilDestroyed(), tap(v => {
1665
1729
  this._isVertical = v;
1666
1730
  const el = this._elementRef.nativeElement;
@@ -1673,12 +1737,12 @@ class NgVirtualListComponent {
1673
1737
  this.listenCacheChangesIfNeed(dynamicSize);
1674
1738
  })).subscribe();
1675
1739
  combineLatest([this.$initialized, $bounds, $items, $stickyMap, $scrollSize, $itemSize,
1676
- $itemsOffset, $snap, $isVertical, $dynamicSize, $enabledBufferOptimization, $cacheVersion,
1677
- ]).pipe(takeUntilDestroyed(), distinctUntilChanged(), filter(([initialized]) => !!initialized), switchMap(([, bounds, items, stickyMap, scrollSize, itemSize, itemsOffset, snap, isVertical, dynamicSize, enabledBufferOptimization, cacheVersion,]) => {
1740
+ $bufferSize, $maxBufferSize, $snap, $isVertical, $dynamicSize, $enabledBufferOptimization, $cacheVersion,
1741
+ ]).pipe(takeUntilDestroyed(), distinctUntilChanged(), filter(([initialized]) => !!initialized), switchMap(([, bounds, items, stickyMap, scrollSize, itemSize, bufferSize, maxBufferSize, snap, isVertical, dynamicSize, enabledBufferOptimization, cacheVersion,]) => {
1678
1742
  let actualScrollSize = (this._isVertical ? this._container()?.nativeElement.scrollTop ?? 0 : this._container()?.nativeElement.scrollLeft) ?? 0;
1679
1743
  const { width, height } = bounds, opts = {
1680
1744
  bounds: { width, height }, dynamicSize, isVertical, itemSize,
1681
- itemsOffset, scrollSize: actualScrollSize, snap, enabledBufferOptimization,
1745
+ bufferSize, maxBufferSize, scrollSize: actualScrollSize, snap, enabledBufferOptimization,
1682
1746
  }, { displayItems, totalSize } = this._trackBox.updateCollection(items, stickyMap, opts);
1683
1747
  this.resetBoundsSize(isVertical, totalSize);
1684
1748
  this.createDisplayComponentsIfNeed(displayItems);
@@ -1825,7 +1889,8 @@ class NgVirtualListComponent {
1825
1889
  }
1826
1890
  const { width, height } = this._bounds() || { width: DEFAULT_LIST_SIZE, height: DEFAULT_LIST_SIZE }, stickyMap = this.stickyMap(), items = this.items(), isVertical = this._isVertical, delta = this._trackBox.delta, opts = {
1827
1891
  bounds: { width, height }, collection: items, dynamicSize, isVertical: this._isVertical, itemSize,
1828
- itemsOffset: this.itemsOffset(), scrollSize: (isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft) + delta,
1892
+ bufferSize: this.bufferSize(), maxBufferSize: this.maxBufferSize(),
1893
+ scrollSize: (isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft) + delta,
1829
1894
  snap: this.snap(), fromItemId: id, enabledBufferOptimization: this.enabledBufferOptimization(),
1830
1895
  }, scrollSize = this._trackBox.getItemPosition(id, stickyMap, opts), params = { [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior };
1831
1896
  if (scrollSize === -1) {
@@ -1956,7 +2021,7 @@ class NgVirtualListComponent {
1956
2021
  }
1957
2022
  }
1958
2023
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1959
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: NgVirtualListComponent, isStandalone: true, selector: "ng-virtual-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, snap: { classPropertyName: "snap", publicName: "snap", isSignal: true, isRequired: false, transformFunction: null }, enabledBufferOptimization: { classPropertyName: "enabledBufferOptimization", publicName: "enabledBufferOptimization", isSignal: true, isRequired: false, transformFunction: null }, itemRenderer: { classPropertyName: "itemRenderer", publicName: "itemRenderer", isSignal: true, isRequired: true, transformFunction: null }, stickyMap: { classPropertyName: "stickyMap", publicName: "stickyMap", isSignal: true, isRequired: false, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null }, dynamicSize: { classPropertyName: "dynamicSize", publicName: "dynamicSize", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, itemsOffset: { classPropertyName: "itemsOffset", publicName: "itemsOffset", isSignal: true, isRequired: false, transformFunction: null }, snappingMethod: { classPropertyName: "snappingMethod", publicName: "snappingMethod", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd" }, viewQueries: [{ propertyName: "_snappedContainer", first: true, predicate: ["snapped"], descendants: true, isSignal: true }, { propertyName: "_container", first: true, predicate: ["container"], descendants: true, isSignal: true }, { propertyName: "_list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "_listContainerRef", first: true, predicate: ["renderersContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_snapContainerRef", first: true, predicate: ["snapRendererContainer"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "@if (snap()) {\r\n<div #snapped part=\"snapped-item\" class=\"ngvl__list-snapper\">\r\n <ng-container #snapRendererContainer></ng-container>\r\n</div>\r\n}\r\n<div #container part=\"scroller\" class=\"ngvl__scroller\">\r\n <ul #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{position:relative;display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.horizontal) .ngvl__list{display:inline-flex}:host(.horizontal) .ngvl__scroller{overflow:auto hidden}:host(.vertical) .ngvl__scroller{overflow:hidden auto}:host(.vertical){height:320px}.ngvl__scroller{overflow:auto;width:100%;height:100%}.ngvl__list-snapper{pointer-events:none;position:absolute;list-style:none;left:0;top:0;z-index:1}.ngvl__list{position:relative;list-style:none;padding:0;margin:0;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
2024
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: NgVirtualListComponent, isStandalone: true, selector: "ng-virtual-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, snap: { classPropertyName: "snap", publicName: "snap", isSignal: true, isRequired: false, transformFunction: null }, enabledBufferOptimization: { classPropertyName: "enabledBufferOptimization", publicName: "enabledBufferOptimization", isSignal: true, isRequired: false, transformFunction: null }, itemRenderer: { classPropertyName: "itemRenderer", publicName: "itemRenderer", isSignal: true, isRequired: true, transformFunction: null }, stickyMap: { classPropertyName: "stickyMap", publicName: "stickyMap", isSignal: true, isRequired: false, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null }, dynamicSize: { classPropertyName: "dynamicSize", publicName: "dynamicSize", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, itemsOffset: { classPropertyName: "itemsOffset", publicName: "itemsOffset", isSignal: true, isRequired: false, transformFunction: null }, bufferSize: { classPropertyName: "bufferSize", publicName: "bufferSize", isSignal: true, isRequired: false, transformFunction: null }, maxBufferSize: { classPropertyName: "maxBufferSize", publicName: "maxBufferSize", isSignal: true, isRequired: false, transformFunction: null }, snappingMethod: { classPropertyName: "snappingMethod", publicName: "snappingMethod", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd" }, viewQueries: [{ propertyName: "_snappedContainer", first: true, predicate: ["snapped"], descendants: true, isSignal: true }, { propertyName: "_container", first: true, predicate: ["container"], descendants: true, isSignal: true }, { propertyName: "_list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "_listContainerRef", first: true, predicate: ["renderersContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_snapContainerRef", first: true, predicate: ["snapRendererContainer"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "@if (snap()) {\r\n<div #snapped part=\"snapped-item\" class=\"ngvl__list-snapper\">\r\n <ng-container #snapRendererContainer></ng-container>\r\n</div>\r\n}\r\n<div #container part=\"scroller\" class=\"ngvl__scroller\">\r\n <ul #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{position:relative;display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.horizontal) .ngvl__list{display:inline-flex}:host(.horizontal) .ngvl__scroller{overflow:auto hidden}:host(.vertical) .ngvl__scroller{overflow:hidden auto}:host(.vertical){height:320px}.ngvl__scroller{overflow:auto;width:100%;height:100%}.ngvl__list-snapper{pointer-events:none;position:absolute;list-style:none;left:0;top:0;z-index:1}.ngvl__list{position:relative;list-style:none;padding:0;margin:0;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
1960
2025
  }
1961
2026
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListComponent, decorators: [{
1962
2027
  type: Component,