ng-virtual-list 14.3.2 → 14.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.
@@ -41,7 +41,8 @@ var SnappingMethods;
41
41
  })(SnappingMethods || (SnappingMethods = {}));
42
42
 
43
43
  const DEFAULT_ITEM_SIZE = 24;
44
- const DEFAULT_ITEMS_OFFSET = 2;
44
+ const DEFAULT_BUFFER_SIZE = 2;
45
+ const DEFAULT_MAX_BUFFER_SIZE = 100;
45
46
  const DEFAULT_LIST_SIZE = 400;
46
47
  const DEFAULT_SNAP = false;
47
48
  const DEFAULT_ENABLED_BUFFER_OPTIMIZATION = false;
@@ -208,12 +209,12 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
208
209
  }
209
210
  NgVirtualListItemComponent.__nextId = 0;
210
211
  NgVirtualListItemComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgVirtualListItemComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
211
- NgVirtualListItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: NgVirtualListItemComponent, selector: "ng-virtual-list-item", host: { classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"data\">\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut}\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, config: data.config}\"></ng-container>\r\n </ng-container>\r\n </li>\r\n</ng-container>", 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: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
212
+ NgVirtualListItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: NgVirtualListItemComponent, selector: "ng-virtual-list-item", host: { classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"data\">\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut}\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, config: data.config}\"></ng-container>\r\n </ng-container>\r\n </li>\r\n</ng-container>", 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: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
212
213
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
213
214
  type: Component,
214
215
  args: [{ selector: 'ng-virtual-list-item', host: {
215
216
  'class': 'ngvl__item',
216
- }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"data\">\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut}\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, config: data.config}\"></ng-container>\r\n </ng-container>\r\n </li>\r\n</ng-container>", 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"] }]
217
+ }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"data\">\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut}\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, config: data.config}\"></ng-container>\r\n </ng-container>\r\n </li>\r\n</ng-container>", 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"] }]
217
218
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; } });
218
219
 
219
220
  const HORIZONTAL_ALIASES = [Directions.HORIZONTAL, 'horizontal'], VERTICAL_ALIASES = [Directions.VERTICAL, 'vertical'];
@@ -681,6 +682,33 @@ class CacheMap extends EventEmitter {
681
682
  }
682
683
  }
683
684
 
685
+ const DEFAULT_EXTRA = {
686
+ extremumThreshold: 2,
687
+ bufferSize: 10,
688
+ };
689
+ const bufferInterpolation = (currentBufferValue, array, value, extra) => {
690
+ const { extremumThreshold = DEFAULT_EXTRA.extremumThreshold, bufferSize = DEFAULT_EXTRA.bufferSize, } = extra ?? DEFAULT_EXTRA;
691
+ if (currentBufferValue < value) {
692
+ let i = 0;
693
+ while (i < extremumThreshold) {
694
+ array.push(value);
695
+ i++;
696
+ }
697
+ }
698
+ else {
699
+ array.push(value);
700
+ }
701
+ while (array.length >= bufferSize) {
702
+ array.shift();
703
+ }
704
+ const l = array.length;
705
+ let buffer = 0;
706
+ for (let i = 0; i < l; i++) {
707
+ buffer += array[i];
708
+ }
709
+ return Math.ceil(buffer / l);
710
+ };
711
+
684
712
  const TRACK_BOX_CHANGE_EVENT_NAME = 'change';
685
713
  var ItemDisplayMethods;
686
714
  (function (ItemDisplayMethods) {
@@ -689,6 +717,7 @@ var ItemDisplayMethods;
689
717
  ItemDisplayMethods[ItemDisplayMethods["DELETE"] = 2] = "DELETE";
690
718
  ItemDisplayMethods[ItemDisplayMethods["NOT_CHANGED"] = 3] = "NOT_CHANGED";
691
719
  })(ItemDisplayMethods || (ItemDisplayMethods = {}));
720
+ const DEFAULT_BUFFER_EXTREMUM_THRESHOLD = 15, DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH = 30, DEFAULT_RESET_BUFFER_SIZE_TIMEOUT = 10000;
692
721
  /**
693
722
  * An object that performs tracking, calculations and caching.
694
723
  * @link https://github.com/DjonnyX/ng-virtual-list/blob/14.x/projects/ng-virtual-list/src/lib/utils/trackBox.ts
@@ -703,6 +732,15 @@ class TrackBox extends CacheMap {
703
732
  this._crudDetected = false;
704
733
  this._previousTotalSize = 0;
705
734
  this._scrollDelta = 0;
735
+ this.isAdaptiveBuffer = true;
736
+ this._bufferSequenceExtraThreshold = DEFAULT_BUFFER_EXTREMUM_THRESHOLD;
737
+ this._maxBufferSequenceLength = DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH;
738
+ this._bufferSizeSequence = [];
739
+ this._bufferSize = 0;
740
+ this._defaultBufferSize = 0;
741
+ this._maxBufferSize = this._defaultBufferSize;
742
+ this._resetBufferSizeTimeout = DEFAULT_RESET_BUFFER_SIZE_TIMEOUT;
743
+ this._previousScrollSize = 0;
706
744
  this._tracker = new Tracker(trackingPropertyName);
707
745
  }
708
746
  set items(v) {
@@ -753,6 +791,7 @@ class TrackBox extends CacheMap {
753
791
  }
754
792
  }
755
793
  get scrollDelta() { return this._scrollDelta; }
794
+ get bufferSize() { return this._bufferSize; }
756
795
  lifeCircle() {
757
796
  this.fireChangeIfNeed();
758
797
  this.lifeCircleDo();
@@ -846,6 +885,8 @@ class TrackBox extends CacheMap {
846
885
  */
847
886
  getItemPosition(id, stickyMap, options) {
848
887
  const opt = { fromItemId: id, stickyMap, ...options };
888
+ this._defaultBufferSize = opt.bufferSize;
889
+ this._maxBufferSize = opt.maxBufferSize;
849
890
  const { scrollSize, isFromItemIdFound } = this.recalculateMetrics({
850
891
  ...opt,
851
892
  dynamicSize: this._crudDetected || opt.dynamicSize,
@@ -863,6 +904,8 @@ class TrackBox extends CacheMap {
863
904
  if (opt.dynamicSize) {
864
905
  this.cacheElements();
865
906
  }
907
+ this._defaultBufferSize = opt.bufferSize;
908
+ this._maxBufferSize = opt.maxBufferSize;
866
909
  const metrics = this.recalculateMetrics({
867
910
  ...opt,
868
911
  collection: items,
@@ -871,6 +914,7 @@ class TrackBox extends CacheMap {
871
914
  deletedItemsMap,
872
915
  });
873
916
  this._delta += metrics.delta;
917
+ this.updateAdaptiveBufferParams(metrics, items.length);
874
918
  this._previousTotalSize = metrics.totalSize;
875
919
  this._deletedItemsMap = {};
876
920
  this._crudDetected = false;
@@ -886,6 +930,26 @@ class TrackBox extends CacheMap {
886
930
  getNearestItem(scrollSize, items, itemSize, isVertical) {
887
931
  return this.getElementFromStart(scrollSize, items, this._map, itemSize, isVertical);
888
932
  }
933
+ updateAdaptiveBufferParams(metrics, totalItemsLength) {
934
+ this.disposeClearBufferSizeTimer();
935
+ const scrollSize = metrics.scrollSize + this._delta, delta = Math.abs(this._previousScrollSize - scrollSize);
936
+ this._previousScrollSize = scrollSize;
937
+ 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;
938
+ this._bufferSize = bufferInterpolation(this._bufferSize, this._bufferSizeSequence, bufferValue, {
939
+ extremumThreshold: this._bufferSequenceExtraThreshold,
940
+ bufferSize: this._maxBufferSequenceLength,
941
+ });
942
+ this.startResetBufferSizeTimer();
943
+ }
944
+ startResetBufferSizeTimer() {
945
+ this._resetBufferSizeTimer = setTimeout(() => {
946
+ this._bufferSize = this._defaultBufferSize;
947
+ this._bufferSizeSequence = [];
948
+ }, this._resetBufferSizeTimeout);
949
+ }
950
+ disposeClearBufferSizeTimer() {
951
+ clearTimeout(this._resetBufferSizeTimer);
952
+ }
889
953
  /**
890
954
  * Calculates the position of an element based on the given scrollSize
891
955
  */
@@ -937,30 +1001,30 @@ class TrackBox extends CacheMap {
937
1001
  * Calculates list metrics
938
1002
  */
939
1003
  recalculateMetrics(options) {
940
- const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, itemsOffset, scrollSize, snap, stickyMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options;
941
- 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)
1004
+ const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, bufferSize: minBufferSize, scrollSize, snap, stickyMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options;
1005
+ 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)
942
1006
  || (typeof fromItemId === 'string' && fromItemId > '-1');
943
1007
  let leftItemsOffset = 0, rightItemsOffset = 0;
944
1008
  if (enabledBufferOptimization) {
945
1009
  switch (this.scrollDirection) {
946
1010
  case 1: {
947
1011
  leftItemsOffset = 0;
948
- rightItemsOffset = itemsOffset;
1012
+ rightItemsOffset = bufferSize;
949
1013
  break;
950
1014
  }
951
1015
  case -1: {
952
- leftItemsOffset = itemsOffset;
1016
+ leftItemsOffset = bufferSize;
953
1017
  rightItemsOffset = 0;
954
1018
  break;
955
1019
  }
956
1020
  case 0:
957
1021
  default: {
958
- leftItemsOffset = rightItemsOffset = itemsOffset;
1022
+ leftItemsOffset = rightItemsOffset = bufferSize;
959
1023
  }
960
1024
  }
961
1025
  }
962
1026
  else {
963
- leftItemsOffset = rightItemsOffset = itemsOffset;
1027
+ leftItemsOffset = rightItemsOffset = bufferSize;
964
1028
  }
965
1029
  let itemsFromStartToScrollEnd = -1, itemsFromDisplayEndToOffsetEnd = 0, itemsFromStartToDisplayEnd = -1, leftItemLength = 0, rightItemLength = 0, leftItemsWeight = 0, rightItemsWeight = 0, leftHiddenItemsWeight = 0, totalItemsToDisplayEndWeight = 0, leftSizeOfAddedItems = 0, leftSizeOfUpdatedItems = 0, leftSizeOfDeletedItems = 0, itemById = undefined, itemByIdPos = 0, targetDisplayItemIndex = -1, isTargetInOverscroll = false, actualScrollSize = itemByIdPos, totalSize = 0, startIndex, isFromItemIdFound = false;
966
1030
  // If the list is dynamic or there are new elements in the collection, then it switches to the long algorithm.
@@ -1135,9 +1199,9 @@ class TrackBox extends CacheMap {
1135
1199
  }
1136
1200
  itemsFromStartToScrollEnd = Math.floor(scrollSize / typicalItemSize);
1137
1201
  itemsFromStartToDisplayEnd = Math.ceil((scrollSize + size) / typicalItemSize);
1138
- leftItemLength = Math.min(itemsFromStartToScrollEnd, itemsOffset);
1139
- rightItemLength = itemsFromStartToDisplayEnd + itemsOffset > totalLength
1140
- ? totalLength - itemsFromStartToDisplayEnd : itemsOffset;
1202
+ leftItemLength = Math.min(itemsFromStartToScrollEnd, bufferSize);
1203
+ rightItemLength = itemsFromStartToDisplayEnd + bufferSize > totalLength
1204
+ ? totalLength - itemsFromStartToDisplayEnd : bufferSize;
1141
1205
  leftItemsWeight = leftItemLength * typicalItemSize;
1142
1206
  rightItemsWeight = rightItemLength * typicalItemSize;
1143
1207
  leftHiddenItemsWeight = itemsFromStartToScrollEnd * typicalItemSize;
@@ -1379,6 +1443,7 @@ class TrackBox extends CacheMap {
1379
1443
  }
1380
1444
  dispose() {
1381
1445
  super.dispose();
1446
+ this.disposeClearBufferSizeTimer();
1382
1447
  if (this._tracker) {
1383
1448
  this._tracker.dispose();
1384
1449
  }
@@ -1514,8 +1579,17 @@ class NgVirtualListComponent extends DisposableComponent {
1514
1579
  this.$dynamicSize = this._$dynamicSize.asObservable();
1515
1580
  this._$direction = new BehaviorSubject(DEFAULT_DIRECTION);
1516
1581
  this.$direction = this._$direction.asObservable();
1517
- this._$itemsOffset = new BehaviorSubject(DEFAULT_ITEMS_OFFSET);
1518
- this.$itemsOffset = this._$itemsOffset.asObservable();
1582
+ this._$bufferSize = new BehaviorSubject(DEFAULT_BUFFER_SIZE);
1583
+ this.$bufferSize = this._$bufferSize.asObservable();
1584
+ this._maxBufferSizeTransform = (v) => {
1585
+ const bufferSize = this._$bufferSize.getValue();
1586
+ if (v === undefined || v <= bufferSize) {
1587
+ return bufferSize;
1588
+ }
1589
+ return v;
1590
+ };
1591
+ this._$maxBufferSize = new BehaviorSubject(DEFAULT_MAX_BUFFER_SIZE);
1592
+ this.$maxBufferSize = this._$maxBufferSize.asObservable();
1519
1593
  this._$trackBy = new BehaviorSubject(TRACK_BY_PROPERTY_NAME);
1520
1594
  this.$trackBy = this._$trackBy.asObservable();
1521
1595
  this._isVertical = this.getIsVertical();
@@ -1635,7 +1709,7 @@ class NgVirtualListComponent extends DisposableComponent {
1635
1709
  $trackBy.pipe(takeUntil(this._$unsubscribe), tap(v => {
1636
1710
  this._trackBox.trackingPropertyName = v;
1637
1711
  })).subscribe();
1638
- const $bounds = this._$bounds.asObservable().pipe(filter(b => !!b)), $items = this.$items.pipe(map(i => !i ? [] : i)), $scrollSize = this._$scrollSize.asObservable(), $itemSize = this.$itemSize.pipe(map(v => v <= 0 ? DEFAULT_ITEM_SIZE : v)), $itemsOffset = this.$itemsOffset.pipe(map(v => v < 0 ? DEFAULT_ITEMS_OFFSET : v)), $stickyMap = this.$stickyMap.pipe(map(v => !v ? {} : v)), $snap = this.$snap, $isVertical = this.$direction.pipe(map(v => this.getIsVertical(v || DEFAULT_DIRECTION))), $dynamicSize = this.$dynamicSize, $enabledBufferOptimization = this.$enabledBufferOptimization, $snappingMethod = this.$snappingMethod.pipe(map(v => this.getIsSnappingMethodAdvanced(v || DEFAULT_SNAPPING_METHOD))), $cacheVersion = this.$cacheVersion;
1712
+ const $bounds = this._$bounds.asObservable().pipe(filter(b => !!b)), $items = this.$items.pipe(map(i => !i ? [] : i)), $scrollSize = this._$scrollSize.asObservable(), $itemSize = this.$itemSize.pipe(map(v => v <= 0 ? DEFAULT_ITEM_SIZE : v)), $bufferSize = this.$bufferSize.pipe(map(v => v < 0 ? DEFAULT_BUFFER_SIZE : v)), $maxBufferSize = this.$maxBufferSize.pipe(map(v => v < 0 ? DEFAULT_MAX_BUFFER_SIZE : v)), $stickyMap = this.$stickyMap.pipe(map(v => !v ? {} : v)), $snap = this.$snap, $isVertical = this.$direction.pipe(map(v => this.getIsVertical(v || DEFAULT_DIRECTION))), $dynamicSize = this.$dynamicSize, $enabledBufferOptimization = this.$enabledBufferOptimization, $snappingMethod = this.$snappingMethod.pipe(map(v => this.getIsSnappingMethodAdvanced(v || DEFAULT_SNAPPING_METHOD))), $cacheVersion = this.$cacheVersion;
1639
1713
  $isVertical.pipe(takeUntil(this._$unsubscribe), tap(v => {
1640
1714
  this._isVertical = v;
1641
1715
  const el = this._elementRef.nativeElement;
@@ -1648,12 +1722,12 @@ class NgVirtualListComponent extends DisposableComponent {
1648
1722
  this.listenCacheChangesIfNeed(dynamicSize);
1649
1723
  })).subscribe();
1650
1724
  combineLatest([this.$initialized, $bounds, $items, $stickyMap, $scrollSize, $itemSize,
1651
- $itemsOffset, $snap, $isVertical, $dynamicSize, $enabledBufferOptimization, $cacheVersion,
1652
- ]).pipe(takeUntil(this._$unsubscribe), distinctUntilChanged(), filter(([initialized]) => !!initialized), switchMap(([, bounds, items, stickyMap, scrollSize, itemSize, itemsOffset, snap, isVertical, dynamicSize, enabledBufferOptimization, cacheVersion,]) => {
1725
+ $bufferSize, $maxBufferSize, $snap, $isVertical, $dynamicSize, $enabledBufferOptimization, $cacheVersion,
1726
+ ]).pipe(takeUntil(this._$unsubscribe), distinctUntilChanged(), filter(([initialized]) => !!initialized), switchMap(([, bounds, items, stickyMap, scrollSize, itemSize, bufferSize, maxBufferSize, snap, isVertical, dynamicSize, enabledBufferOptimization, cacheVersion,]) => {
1653
1727
  let actualScrollSize = (this._isVertical ? this._container?.nativeElement.scrollTop ?? 0 : this._container?.nativeElement.scrollLeft) ?? 0;
1654
1728
  const { width, height } = bounds, opts = {
1655
1729
  bounds: { width, height }, dynamicSize, isVertical, itemSize,
1656
- itemsOffset, scrollSize: actualScrollSize, snap, enabledBufferOptimization,
1730
+ bufferSize, maxBufferSize, scrollSize: actualScrollSize, snap, enabledBufferOptimization,
1657
1731
  }, { displayItems, totalSize } = this._trackBox.updateCollection(items, stickyMap, opts);
1658
1732
  this.resetBoundsSize(isVertical, totalSize);
1659
1733
  this.createDisplayComponentsIfNeed(displayItems);
@@ -1786,16 +1860,37 @@ class NgVirtualListComponent extends DisposableComponent {
1786
1860
  ;
1787
1861
  get direction() { return this._$direction.getValue(); }
1788
1862
  /**
1789
- * Number of elements outside the scope of visibility. Default value is 2.
1863
+ * @deprecated "itemOffset" parameter is deprecated. Use "bufferSize" and "maxBufferSize".
1790
1864
  */
1791
1865
  set itemsOffset(v) {
1792
- if (this._$itemsOffset.getValue() === v) {
1866
+ throw Error('"itemOffset" parameter is deprecated. Use "bufferSize" and "maxBufferSize".');
1867
+ }
1868
+ ;
1869
+ /**
1870
+ * Number of elements outside the scope of visibility. Default value is 2.
1871
+ */
1872
+ set bufferSize(v) {
1873
+ if (this._$bufferSize.getValue() === v) {
1874
+ return;
1875
+ }
1876
+ this._$bufferSize.next(v);
1877
+ }
1878
+ ;
1879
+ get bufferSize() { return this._$bufferSize.getValue(); }
1880
+ /**
1881
+ * Maximum number of elements outside the scope of visibility. Default value is 100.
1882
+ * If maxBufferSize is set to be greater than bufferSize, then adaptive buffer mode is enabled.
1883
+ * The greater the scroll size, the more elements are allocated for rendering.
1884
+ */
1885
+ set maxBufferSize(v) {
1886
+ const val = this._maxBufferSizeTransform(v);
1887
+ if (this._$maxBufferSize.getValue() === val) {
1793
1888
  return;
1794
1889
  }
1795
- this._$itemsOffset.next(v);
1890
+ this._$maxBufferSize.next(val);
1796
1891
  }
1797
1892
  ;
1798
- get itemsOffset() { return this._$itemsOffset.getValue(); }
1893
+ get maxBufferSize() { return this._$maxBufferSize.getValue(); }
1799
1894
  /**
1800
1895
  * The name of the property by which tracking is performed
1801
1896
  */
@@ -1940,7 +2035,7 @@ class NgVirtualListComponent extends DisposableComponent {
1940
2035
  }
1941
2036
  const { width, height } = this._$bounds.getValue() || { width: 0, height: 0 }, stickyMap = this.stickyMap, items = this.items, isVertical = this._isVertical, delta = this._trackBox.delta, opts = {
1942
2037
  bounds: { width, height }, collection: items, dynamicSize, isVertical: this._isVertical, itemSize,
1943
- itemsOffset: this.itemsOffset, scrollSize: (isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft) + delta,
2038
+ bufferSize: this.bufferSize, maxBufferSize: this.maxBufferSize, scrollSize: (isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft) + delta,
1944
2039
  snap: this.snap, fromItemId: id, enabledBufferOptimization: this.enabledBufferOptimization,
1945
2040
  }, scrollSize = this._trackBox.getItemPosition(id, stickyMap, opts), params = { [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior };
1946
2041
  if (scrollSize === -1) {
@@ -2048,7 +2143,7 @@ class NgVirtualListComponent extends DisposableComponent {
2048
2143
  }
2049
2144
  NgVirtualListComponent.__nextId = 0;
2050
2145
  NgVirtualListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgVirtualListComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
2051
- NgVirtualListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: NgVirtualListComponent, selector: "ng-virtual-list", inputs: { items: "items", snap: "snap", enabledBufferOptimization: "enabledBufferOptimization", itemRenderer: "itemRenderer", stickyMap: "stickyMap", itemSize: "itemSize", dynamicSize: "dynamicSize", direction: "direction", itemsOffset: "itemsOffset", trackBy: "trackBy", snappingMethod: "snappingMethod" }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd" }, viewQueries: [{ propertyName: "_listContainerRef", first: true, predicate: ["renderersContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_container", first: true, predicate: ["container"], descendants: true, read: (ElementRef) }, { propertyName: "_list", first: true, predicate: ["list"], descendants: true, read: (ElementRef) }, { propertyName: "_snapContainerRef", first: true, predicate: ["snapRendererContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_snappedContainer", first: true, predicate: ["snapped"], descendants: true, read: ViewContainerRef }], usesInheritance: true, ngImport: i0, template: "<div *ngIf=\"snap\" #snapped part=\"snapped-item\" class=\"ngvl__list-snapper\">\r\n <ng-container #snapRendererContainer></ng-container>\r\n</div>\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: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
2146
+ NgVirtualListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: NgVirtualListComponent, selector: "ng-virtual-list", inputs: { items: "items", snap: "snap", enabledBufferOptimization: "enabledBufferOptimization", itemRenderer: "itemRenderer", stickyMap: "stickyMap", itemSize: "itemSize", dynamicSize: "dynamicSize", direction: "direction", itemsOffset: "itemsOffset", bufferSize: "bufferSize", maxBufferSize: "maxBufferSize", trackBy: "trackBy", snappingMethod: "snappingMethod" }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd" }, viewQueries: [{ propertyName: "_listContainerRef", first: true, predicate: ["renderersContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_container", first: true, predicate: ["container"], descendants: true, read: (ElementRef) }, { propertyName: "_list", first: true, predicate: ["list"], descendants: true, read: (ElementRef) }, { propertyName: "_snapContainerRef", first: true, predicate: ["snapRendererContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_snappedContainer", first: true, predicate: ["snapped"], descendants: true, read: ViewContainerRef }], usesInheritance: true, ngImport: i0, template: "<div *ngIf=\"snap\" #snapped part=\"snapped-item\" class=\"ngvl__list-snapper\">\r\n <ng-container #snapRendererContainer></ng-container>\r\n</div>\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: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
2052
2147
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgVirtualListComponent, decorators: [{
2053
2148
  type: Component,
2054
2149
  args: [{ selector: 'ng-virtual-list', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, template: "<div *ngIf=\"snap\" #snapped part=\"snapped-item\" class=\"ngvl__list-snapper\">\r\n <ng-container #snapRendererContainer></ng-container>\r\n</div>\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"] }]
@@ -2089,6 +2184,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2089
2184
  type: Input
2090
2185
  }], itemsOffset: [{
2091
2186
  type: Input
2187
+ }], bufferSize: [{
2188
+ type: Input
2189
+ }], maxBufferSize: [{
2190
+ type: Input
2092
2191
  }], trackBy: [{
2093
2192
  type: Input
2094
2193
  }], snappingMethod: [{