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;
@@ -210,12 +211,12 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
210
211
  }
211
212
  NgVirtualListItemComponent.__nextId = 0;
212
213
  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 });
213
- 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 });
214
+ 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 });
214
215
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
215
216
  type: Component,
216
217
  args: [{ selector: 'ng-virtual-list-item', host: {
217
218
  'class': 'ngvl__item',
218
- }, 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"] }]
219
+ }, 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"] }]
219
220
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; } });
220
221
 
221
222
  const HORIZONTAL_ALIASES = [Directions.HORIZONTAL, 'horizontal'], VERTICAL_ALIASES = [Directions.VERTICAL, 'vertical'];
@@ -684,6 +685,33 @@ class CacheMap extends EventEmitter {
684
685
  }
685
686
  }
686
687
 
688
+ const DEFAULT_EXTRA = {
689
+ extremumThreshold: 2,
690
+ bufferSize: 10,
691
+ };
692
+ const bufferInterpolation = (currentBufferValue, array, value, extra) => {
693
+ const { extremumThreshold = DEFAULT_EXTRA.extremumThreshold, bufferSize = DEFAULT_EXTRA.bufferSize, } = extra !== null && extra !== void 0 ? extra : DEFAULT_EXTRA;
694
+ if (currentBufferValue < value) {
695
+ let i = 0;
696
+ while (i < extremumThreshold) {
697
+ array.push(value);
698
+ i++;
699
+ }
700
+ }
701
+ else {
702
+ array.push(value);
703
+ }
704
+ while (array.length >= bufferSize) {
705
+ array.shift();
706
+ }
707
+ const l = array.length;
708
+ let buffer = 0;
709
+ for (let i = 0; i < l; i++) {
710
+ buffer += array[i];
711
+ }
712
+ return Math.ceil(buffer / l);
713
+ };
714
+
687
715
  const TRACK_BOX_CHANGE_EVENT_NAME = 'change';
688
716
  var ItemDisplayMethods;
689
717
  (function (ItemDisplayMethods) {
@@ -692,6 +720,7 @@ var ItemDisplayMethods;
692
720
  ItemDisplayMethods[ItemDisplayMethods["DELETE"] = 2] = "DELETE";
693
721
  ItemDisplayMethods[ItemDisplayMethods["NOT_CHANGED"] = 3] = "NOT_CHANGED";
694
722
  })(ItemDisplayMethods || (ItemDisplayMethods = {}));
723
+ const DEFAULT_BUFFER_EXTREMUM_THRESHOLD = 15, DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH = 30, DEFAULT_RESET_BUFFER_SIZE_TIMEOUT = 10000;
695
724
  /**
696
725
  * An object that performs tracking, calculations and caching.
697
726
  * @link https://github.com/DjonnyX/ng-virtual-list/blob/14.x/projects/ng-virtual-list/src/lib/utils/trackBox.ts
@@ -706,6 +735,15 @@ class TrackBox extends CacheMap {
706
735
  this._crudDetected = false;
707
736
  this._previousTotalSize = 0;
708
737
  this._scrollDelta = 0;
738
+ this.isAdaptiveBuffer = true;
739
+ this._bufferSequenceExtraThreshold = DEFAULT_BUFFER_EXTREMUM_THRESHOLD;
740
+ this._maxBufferSequenceLength = DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH;
741
+ this._bufferSizeSequence = [];
742
+ this._bufferSize = 0;
743
+ this._defaultBufferSize = 0;
744
+ this._maxBufferSize = this._defaultBufferSize;
745
+ this._resetBufferSizeTimeout = DEFAULT_RESET_BUFFER_SIZE_TIMEOUT;
746
+ this._previousScrollSize = 0;
709
747
  this._tracker = new Tracker(trackingPropertyName);
710
748
  }
711
749
  set items(v) {
@@ -756,6 +794,7 @@ class TrackBox extends CacheMap {
756
794
  }
757
795
  }
758
796
  get scrollDelta() { return this._scrollDelta; }
797
+ get bufferSize() { return this._bufferSize; }
759
798
  lifeCircle() {
760
799
  this.fireChangeIfNeed();
761
800
  this.lifeCircleDo();
@@ -849,6 +888,8 @@ class TrackBox extends CacheMap {
849
888
  */
850
889
  getItemPosition(id, stickyMap, options) {
851
890
  const opt = Object.assign({ fromItemId: id, stickyMap }, options);
891
+ this._defaultBufferSize = opt.bufferSize;
892
+ this._maxBufferSize = opt.maxBufferSize;
852
893
  const { scrollSize, isFromItemIdFound } = this.recalculateMetrics(Object.assign(Object.assign({}, opt), { dynamicSize: this._crudDetected || opt.dynamicSize, previousTotalSize: this._previousTotalSize, crudDetected: this._crudDetected, deletedItemsMap: this._deletedItemsMap }));
853
894
  return isFromItemIdFound ? scrollSize : -1;
854
895
  }
@@ -860,8 +901,11 @@ class TrackBox extends CacheMap {
860
901
  if (opt.dynamicSize) {
861
902
  this.cacheElements();
862
903
  }
904
+ this._defaultBufferSize = opt.bufferSize;
905
+ this._maxBufferSize = opt.maxBufferSize;
863
906
  const metrics = this.recalculateMetrics(Object.assign(Object.assign({}, opt), { collection: items, previousTotalSize: this._previousTotalSize, crudDetected: this._crudDetected, deletedItemsMap }));
864
907
  this._delta += metrics.delta;
908
+ this.updateAdaptiveBufferParams(metrics, items.length);
865
909
  this._previousTotalSize = metrics.totalSize;
866
910
  this._deletedItemsMap = {};
867
911
  this._crudDetected = false;
@@ -877,6 +921,26 @@ class TrackBox extends CacheMap {
877
921
  getNearestItem(scrollSize, items, itemSize, isVertical) {
878
922
  return this.getElementFromStart(scrollSize, items, this._map, itemSize, isVertical);
879
923
  }
924
+ updateAdaptiveBufferParams(metrics, totalItemsLength) {
925
+ this.disposeClearBufferSizeTimer();
926
+ const scrollSize = metrics.scrollSize + this._delta, delta = Math.abs(this._previousScrollSize - scrollSize);
927
+ this._previousScrollSize = scrollSize;
928
+ 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;
929
+ this._bufferSize = bufferInterpolation(this._bufferSize, this._bufferSizeSequence, bufferValue, {
930
+ extremumThreshold: this._bufferSequenceExtraThreshold,
931
+ bufferSize: this._maxBufferSequenceLength,
932
+ });
933
+ this.startResetBufferSizeTimer();
934
+ }
935
+ startResetBufferSizeTimer() {
936
+ this._resetBufferSizeTimer = setTimeout(() => {
937
+ this._bufferSize = this._defaultBufferSize;
938
+ this._bufferSizeSequence = [];
939
+ }, this._resetBufferSizeTimeout);
940
+ }
941
+ disposeClearBufferSizeTimer() {
942
+ clearTimeout(this._resetBufferSizeTimer);
943
+ }
880
944
  /**
881
945
  * Calculates the position of an element based on the given scrollSize
882
946
  */
@@ -929,30 +993,30 @@ class TrackBox extends CacheMap {
929
993
  */
930
994
  recalculateMetrics(options) {
931
995
  var _a, _b, _c, _d;
932
- const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, itemsOffset, scrollSize, snap, stickyMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options;
933
- 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)
996
+ const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, bufferSize: minBufferSize, scrollSize, snap, stickyMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options;
997
+ 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)
934
998
  || (typeof fromItemId === 'string' && fromItemId > '-1');
935
999
  let leftItemsOffset = 0, rightItemsOffset = 0;
936
1000
  if (enabledBufferOptimization) {
937
1001
  switch (this.scrollDirection) {
938
1002
  case 1: {
939
1003
  leftItemsOffset = 0;
940
- rightItemsOffset = itemsOffset;
1004
+ rightItemsOffset = bufferSize;
941
1005
  break;
942
1006
  }
943
1007
  case -1: {
944
- leftItemsOffset = itemsOffset;
1008
+ leftItemsOffset = bufferSize;
945
1009
  rightItemsOffset = 0;
946
1010
  break;
947
1011
  }
948
1012
  case 0:
949
1013
  default: {
950
- leftItemsOffset = rightItemsOffset = itemsOffset;
1014
+ leftItemsOffset = rightItemsOffset = bufferSize;
951
1015
  }
952
1016
  }
953
1017
  }
954
1018
  else {
955
- leftItemsOffset = rightItemsOffset = itemsOffset;
1019
+ leftItemsOffset = rightItemsOffset = bufferSize;
956
1020
  }
957
1021
  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;
958
1022
  // If the list is dynamic or there are new elements in the collection, then it switches to the long algorithm.
@@ -1127,9 +1191,9 @@ class TrackBox extends CacheMap {
1127
1191
  }
1128
1192
  itemsFromStartToScrollEnd = Math.floor(scrollSize / typicalItemSize);
1129
1193
  itemsFromStartToDisplayEnd = Math.ceil((scrollSize + size) / typicalItemSize);
1130
- leftItemLength = Math.min(itemsFromStartToScrollEnd, itemsOffset);
1131
- rightItemLength = itemsFromStartToDisplayEnd + itemsOffset > totalLength
1132
- ? totalLength - itemsFromStartToDisplayEnd : itemsOffset;
1194
+ leftItemLength = Math.min(itemsFromStartToScrollEnd, bufferSize);
1195
+ rightItemLength = itemsFromStartToDisplayEnd + bufferSize > totalLength
1196
+ ? totalLength - itemsFromStartToDisplayEnd : bufferSize;
1133
1197
  leftItemsWeight = leftItemLength * typicalItemSize;
1134
1198
  rightItemsWeight = rightItemLength * typicalItemSize;
1135
1199
  leftHiddenItemsWeight = itemsFromStartToScrollEnd * typicalItemSize;
@@ -1372,6 +1436,7 @@ class TrackBox extends CacheMap {
1372
1436
  }
1373
1437
  dispose() {
1374
1438
  super.dispose();
1439
+ this.disposeClearBufferSizeTimer();
1375
1440
  if (this._tracker) {
1376
1441
  this._tracker.dispose();
1377
1442
  }
@@ -1507,8 +1572,17 @@ class NgVirtualListComponent extends DisposableComponent {
1507
1572
  this.$dynamicSize = this._$dynamicSize.asObservable();
1508
1573
  this._$direction = new BehaviorSubject(DEFAULT_DIRECTION);
1509
1574
  this.$direction = this._$direction.asObservable();
1510
- this._$itemsOffset = new BehaviorSubject(DEFAULT_ITEMS_OFFSET);
1511
- this.$itemsOffset = this._$itemsOffset.asObservable();
1575
+ this._$bufferSize = new BehaviorSubject(DEFAULT_BUFFER_SIZE);
1576
+ this.$bufferSize = this._$bufferSize.asObservable();
1577
+ this._maxBufferSizeTransform = (v) => {
1578
+ const bufferSize = this._$bufferSize.getValue();
1579
+ if (v === undefined || v <= bufferSize) {
1580
+ return bufferSize;
1581
+ }
1582
+ return v;
1583
+ };
1584
+ this._$maxBufferSize = new BehaviorSubject(DEFAULT_MAX_BUFFER_SIZE);
1585
+ this.$maxBufferSize = this._$maxBufferSize.asObservable();
1512
1586
  this._$trackBy = new BehaviorSubject(TRACK_BY_PROPERTY_NAME);
1513
1587
  this.$trackBy = this._$trackBy.asObservable();
1514
1588
  this._isVertical = this.getIsVertical();
@@ -1631,7 +1705,7 @@ class NgVirtualListComponent extends DisposableComponent {
1631
1705
  $trackBy.pipe(takeUntil(this._$unsubscribe), tap(v => {
1632
1706
  this._trackBox.trackingPropertyName = v;
1633
1707
  })).subscribe();
1634
- 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;
1708
+ 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;
1635
1709
  $isVertical.pipe(takeUntil(this._$unsubscribe), tap(v => {
1636
1710
  this._isVertical = v;
1637
1711
  const el = this._elementRef.nativeElement;
@@ -1644,13 +1718,13 @@ class NgVirtualListComponent extends DisposableComponent {
1644
1718
  this.listenCacheChangesIfNeed(dynamicSize);
1645
1719
  })).subscribe();
1646
1720
  combineLatest([this.$initialized, $bounds, $items, $stickyMap, $scrollSize, $itemSize,
1647
- $itemsOffset, $snap, $isVertical, $dynamicSize, $enabledBufferOptimization, $cacheVersion,
1648
- ]).pipe(takeUntil(this._$unsubscribe), distinctUntilChanged(), filter(([initialized]) => !!initialized), switchMap(([, bounds, items, stickyMap, scrollSize, itemSize, itemsOffset, snap, isVertical, dynamicSize, enabledBufferOptimization, cacheVersion,]) => {
1721
+ $bufferSize, $maxBufferSize, $snap, $isVertical, $dynamicSize, $enabledBufferOptimization, $cacheVersion,
1722
+ ]).pipe(takeUntil(this._$unsubscribe), distinctUntilChanged(), filter(([initialized]) => !!initialized), switchMap(([, bounds, items, stickyMap, scrollSize, itemSize, bufferSize, maxBufferSize, snap, isVertical, dynamicSize, enabledBufferOptimization, cacheVersion,]) => {
1649
1723
  var _a, _b, _c, _d;
1650
1724
  let actualScrollSize = (_d = (this._isVertical ? (_b = (_a = this._container) === null || _a === void 0 ? void 0 : _a.nativeElement.scrollTop) !== null && _b !== void 0 ? _b : 0 : (_c = this._container) === null || _c === void 0 ? void 0 : _c.nativeElement.scrollLeft)) !== null && _d !== void 0 ? _d : 0;
1651
1725
  const { width, height } = bounds, opts = {
1652
1726
  bounds: { width, height }, dynamicSize, isVertical, itemSize,
1653
- itemsOffset, scrollSize: actualScrollSize, snap, enabledBufferOptimization,
1727
+ bufferSize, maxBufferSize, scrollSize: actualScrollSize, snap, enabledBufferOptimization,
1654
1728
  }, { displayItems, totalSize } = this._trackBox.updateCollection(items, stickyMap, opts);
1655
1729
  this.resetBoundsSize(isVertical, totalSize);
1656
1730
  this.createDisplayComponentsIfNeed(displayItems);
@@ -1783,16 +1857,37 @@ class NgVirtualListComponent extends DisposableComponent {
1783
1857
  ;
1784
1858
  get direction() { return this._$direction.getValue(); }
1785
1859
  /**
1786
- * Number of elements outside the scope of visibility. Default value is 2.
1860
+ * @deprecated "itemOffset" parameter is deprecated. Use "bufferSize" and "maxBufferSize".
1787
1861
  */
1788
1862
  set itemsOffset(v) {
1789
- if (this._$itemsOffset.getValue() === v) {
1863
+ throw Error('"itemOffset" parameter is deprecated. Use "bufferSize" and "maxBufferSize".');
1864
+ }
1865
+ ;
1866
+ /**
1867
+ * Number of elements outside the scope of visibility. Default value is 2.
1868
+ */
1869
+ set bufferSize(v) {
1870
+ if (this._$bufferSize.getValue() === v) {
1871
+ return;
1872
+ }
1873
+ this._$bufferSize.next(v);
1874
+ }
1875
+ ;
1876
+ get bufferSize() { return this._$bufferSize.getValue(); }
1877
+ /**
1878
+ * Maximum number of elements outside the scope of visibility. Default value is 100.
1879
+ * If maxBufferSize is set to be greater than bufferSize, then adaptive buffer mode is enabled.
1880
+ * The greater the scroll size, the more elements are allocated for rendering.
1881
+ */
1882
+ set maxBufferSize(v) {
1883
+ const val = this._maxBufferSizeTransform(v);
1884
+ if (this._$maxBufferSize.getValue() === val) {
1790
1885
  return;
1791
1886
  }
1792
- this._$itemsOffset.next(v);
1887
+ this._$maxBufferSize.next(val);
1793
1888
  }
1794
1889
  ;
1795
- get itemsOffset() { return this._$itemsOffset.getValue(); }
1890
+ get maxBufferSize() { return this._$maxBufferSize.getValue(); }
1796
1891
  /**
1797
1892
  * The name of the property by which tracking is performed
1798
1893
  */
@@ -1937,7 +2032,7 @@ class NgVirtualListComponent extends DisposableComponent {
1937
2032
  }
1938
2033
  const { width, height } = this._$bounds.getValue() || { width: 0, height: 0 }, stickyMap = this.stickyMap, items = this.items, isVertical = this._isVertical, delta = this._trackBox.delta, opts = {
1939
2034
  bounds: { width, height }, collection: items, dynamicSize, isVertical: this._isVertical, itemSize,
1940
- itemsOffset: this.itemsOffset, scrollSize: (isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft) + delta,
2035
+ bufferSize: this.bufferSize, maxBufferSize: this.maxBufferSize, scrollSize: (isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft) + delta,
1941
2036
  snap: this.snap, fromItemId: id, enabledBufferOptimization: this.enabledBufferOptimization,
1942
2037
  }, scrollSize = this._trackBox.getItemPosition(id, stickyMap, opts), params = { [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior };
1943
2038
  if (scrollSize === -1) {
@@ -2043,7 +2138,7 @@ class NgVirtualListComponent extends DisposableComponent {
2043
2138
  }
2044
2139
  NgVirtualListComponent.__nextId = 0;
2045
2140
  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 });
2046
- 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 });
2141
+ 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 });
2047
2142
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgVirtualListComponent, decorators: [{
2048
2143
  type: Component,
2049
2144
  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"] }]
@@ -2084,6 +2179,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2084
2179
  type: Input
2085
2180
  }], itemsOffset: [{
2086
2181
  type: Input
2182
+ }], bufferSize: [{
2183
+ type: Input
2184
+ }], maxBufferSize: [{
2185
+ type: Input
2087
2186
  }], trackBy: [{
2088
2187
  type: Input
2089
2188
  }], snappingMethod: [{