ng-virtual-list 19.7.20 → 19.7.22
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
|
@@ -115,7 +115,7 @@ items = Array.from({ length: 100000 }, (_, i) => ({ id: i, name: `Item #${i}` })
|
|
|
115
115
|
|
|
116
116
|
Template:
|
|
117
117
|
```html
|
|
118
|
-
<ng-virtual-list class="list" direction="horizontal" [items]="horizontalItems" [bufferSize]="
|
|
118
|
+
<ng-virtual-list class="list" direction="horizontal" [items]="horizontalItems" [bufferSize]="5" [maxBufferSize]="20"
|
|
119
119
|
[itemRenderer]="horizontalItemRenderer" [itemSize]="64" [methodForSelecting]="'select'"
|
|
120
120
|
[selectedIds]="2" (onSelect)="onSelect($event)" (onItemClick)="onItemClick($event)"></ng-virtual-list>
|
|
121
121
|
|
|
@@ -166,8 +166,8 @@ export class AppComponent {
|
|
|
166
166
|
Template:
|
|
167
167
|
```html
|
|
168
168
|
<ng-virtual-list class="list" direction="horizontal" [items]="horizontalGroupItems" [itemRenderer]="horizontalGroupItemRenderer"
|
|
169
|
-
[bufferSize]="
|
|
170
|
-
[selectedIds]="[3,2]" (onSelect)="onSelect($event)" (onItemClick)="onItemClick($event)"></ng-virtual-list>
|
|
169
|
+
[bufferSize]="5" [maxBufferSize]="20" [itemConfigMap]="horizontalGroupItemConfigMap" [itemSize]="54" [snap]="true"
|
|
170
|
+
methodForSelecting="multi-select" [selectedIds]="[3,2]" (onSelect)="onSelect($event)" (onItemClick)="onItemClick($event)"></ng-virtual-list>
|
|
171
171
|
|
|
172
172
|
<ng-template #horizontalGroupItemRenderer let-data="data" let-config="config">
|
|
173
173
|
@if (data) {
|
|
@@ -239,7 +239,7 @@ export class AppComponent {
|
|
|
239
239
|
|
|
240
240
|
Template:
|
|
241
241
|
```html
|
|
242
|
-
<ng-virtual-list class="list simple" [items]="items" [bufferSize]="
|
|
242
|
+
<ng-virtual-list class="list simple" [items]="items" [bufferSize]="5" [maxBufferSize]="20" [itemRenderer]="itemRenderer"
|
|
243
243
|
[itemSize]="40"></ng-virtual-list>
|
|
244
244
|
|
|
245
245
|
<ng-template #itemRenderer let-data="data">
|
|
@@ -280,7 +280,7 @@ export class AppComponent {
|
|
|
280
280
|
|
|
281
281
|
Template:
|
|
282
282
|
```html
|
|
283
|
-
<ng-virtual-list class="list simple" [items]="groupItems" [bufferSize]="
|
|
283
|
+
<ng-virtual-list class="list simple" [items]="groupItems" [bufferSize]="5" [maxBufferSize]="20" [itemRenderer]="groupItemRenderer"
|
|
284
284
|
[itemConfigMap]="groupItemConfigMap" [itemSize]="40" [snap]="false"></ng-virtual-list>
|
|
285
285
|
|
|
286
286
|
<ng-template #groupItemRenderer let-data="data">
|
|
@@ -307,7 +307,7 @@ Template:
|
|
|
307
307
|
|
|
308
308
|
Template (with snapping):
|
|
309
309
|
```html
|
|
310
|
-
<ng-virtual-list class="list simple" [items]="groupItems" [bufferSize]="
|
|
310
|
+
<ng-virtual-list class="list simple" [items]="groupItems" [bufferSize]="5" [maxBufferSize]="20" [itemRenderer]="groupItemRenderer"
|
|
311
311
|
[itemConfigMap]="groupItemConfigMap" [itemSize]="40" [snap]="true"></ng-virtual-list>
|
|
312
312
|
|
|
313
313
|
<ng-template #groupItemRenderer let-data="data">
|
|
@@ -372,7 +372,7 @@ Template
|
|
|
372
372
|
<button class="scroll-to__button" (click)="onButtonScrollToIdClickHandler($event)">Scroll</button>
|
|
373
373
|
</div>
|
|
374
374
|
|
|
375
|
-
<ng-virtual-list #virtualList class="list" [items]="items" [itemRenderer]="itemRenderer" [bufferSize]="
|
|
375
|
+
<ng-virtual-list #virtualList class="list" [items]="items" [itemRenderer]="itemRenderer" [bufferSize]="5" [maxBufferSize]="20"
|
|
376
376
|
[itemSize]="40"></ng-virtual-list>
|
|
377
377
|
|
|
378
378
|
<ng-template #itemRenderer let-data="data">
|
|
@@ -426,7 +426,7 @@ Virtual list with height-adjustable elements.
|
|
|
426
426
|
|
|
427
427
|
Template
|
|
428
428
|
```html
|
|
429
|
-
<ng-virtual-list #dynamicList class="list" [items]="groupDynamicItems" [itemRenderer]="groupItemRenderer" [bufferSize]="
|
|
429
|
+
<ng-virtual-list #dynamicList class="list" [items]="groupDynamicItems" [itemRenderer]="groupItemRenderer" [bufferSize]="5" [maxBufferSize]="20"
|
|
430
430
|
[itemConfigMap]="groupDynamicItemConfigMap" [dynamicSize]="true" [snap]="true"></ng-virtual-list>
|
|
431
431
|
|
|
432
432
|
<ng-template #groupItemRenderer let-data="data">
|
|
@@ -565,7 +565,7 @@ List items are encapsulated in shadowDOM, so to override default styles you need
|
|
|
565
565
|
Selecting even elements:
|
|
566
566
|
|
|
567
567
|
```html
|
|
568
|
-
<ng-virtual-list class="list" direction="horizontal" [items]="horizontalItems" [bufferSize]="5"
|
|
568
|
+
<ng-virtual-list class="list" direction="horizontal" [items]="horizontalItems" [bufferSize]="5" [maxBufferSize]="20"
|
|
569
569
|
[itemRenderer]="horizontalItemRenderer" [itemSize]="54"></ng-virtual-list>
|
|
570
570
|
|
|
571
571
|
<ng-template #horizontalItemRenderer let-data="data" let-config="config">
|
|
@@ -2,7 +2,7 @@ import * as i1 from '@angular/common';
|
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { Injectable, inject, signal, ElementRef, ChangeDetectionStrategy, Component, viewChild, output, input, ViewContainerRef, ViewChild, ViewEncapsulation } from '@angular/core';
|
|
5
|
-
import { Subject, tap, fromEvent, combineLatest, map, filter, distinctUntilChanged,
|
|
5
|
+
import { Subject, tap, fromEvent, combineLatest, map, filter, distinctUntilChanged, switchMap, of } from 'rxjs';
|
|
6
6
|
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
|
7
7
|
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
|
|
8
8
|
|
|
@@ -1259,7 +1259,11 @@ const bufferInterpolation = (currentBufferValue, array, value, extra) => {
|
|
|
1259
1259
|
return Math.ceil(buffer / l);
|
|
1260
1260
|
};
|
|
1261
1261
|
|
|
1262
|
-
|
|
1262
|
+
var TrackBoxEvents;
|
|
1263
|
+
(function (TrackBoxEvents) {
|
|
1264
|
+
TrackBoxEvents["CHANGE"] = "change";
|
|
1265
|
+
TrackBoxEvents["RESET"] = "reset";
|
|
1266
|
+
})(TrackBoxEvents || (TrackBoxEvents = {}));
|
|
1263
1267
|
var ItemDisplayMethods;
|
|
1264
1268
|
(function (ItemDisplayMethods) {
|
|
1265
1269
|
ItemDisplayMethods[ItemDisplayMethods["CREATE"] = 0] = "CREATE";
|
|
@@ -1267,7 +1271,7 @@ var ItemDisplayMethods;
|
|
|
1267
1271
|
ItemDisplayMethods[ItemDisplayMethods["DELETE"] = 2] = "DELETE";
|
|
1268
1272
|
ItemDisplayMethods[ItemDisplayMethods["NOT_CHANGED"] = 3] = "NOT_CHANGED";
|
|
1269
1273
|
})(ItemDisplayMethods || (ItemDisplayMethods = {}));
|
|
1270
|
-
const DEFAULT_BUFFER_EXTREMUM_THRESHOLD = 15, DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH = 30, DEFAULT_RESET_BUFFER_SIZE_TIMEOUT = 10000;
|
|
1274
|
+
const DEFAULT_BUFFER_EXTREMUM_THRESHOLD = 15, DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH = 30, DEFAULT_RESET_BUFFER_SIZE_TIMEOUT = 10000, IS_NEW = 'isNew';
|
|
1271
1275
|
/**
|
|
1272
1276
|
* An object that performs tracking, calculations and caching.
|
|
1273
1277
|
* @link https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/utils/trackBox.ts
|
|
@@ -1343,7 +1347,7 @@ class TrackBox extends CacheMap {
|
|
|
1343
1347
|
get crudDetected() { return this._crudDetected; }
|
|
1344
1348
|
fireChangeIfNeed() {
|
|
1345
1349
|
if (this.changesDetected()) {
|
|
1346
|
-
this.dispatch(
|
|
1350
|
+
this.dispatch(TrackBoxEvents.CHANGE, this._version);
|
|
1347
1351
|
}
|
|
1348
1352
|
}
|
|
1349
1353
|
_previousTotalSize = 0;
|
|
@@ -1359,7 +1363,7 @@ class TrackBox extends CacheMap {
|
|
|
1359
1363
|
_maxBufferSize = this._defaultBufferSize;
|
|
1360
1364
|
_resetBufferSizeTimeout = DEFAULT_RESET_BUFFER_SIZE_TIMEOUT;
|
|
1361
1365
|
_resetBufferSizeTimer;
|
|
1362
|
-
|
|
1366
|
+
isReseted = true;
|
|
1363
1367
|
lifeCircle() {
|
|
1364
1368
|
this.fireChangeIfNeed();
|
|
1365
1369
|
this.lifeCircleDo();
|
|
@@ -1372,11 +1376,19 @@ class TrackBox extends CacheMap {
|
|
|
1372
1376
|
console.warn('Attention! The collection must be immutable.');
|
|
1373
1377
|
return;
|
|
1374
1378
|
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1379
|
+
let reseted = this.isReseted;
|
|
1380
|
+
if (reseted) {
|
|
1381
|
+
if (!(!this._previousCollection || this._previousCollection.length === 0)) {
|
|
1382
|
+
reseted = false;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
if (!reseted && (!currentCollection || currentCollection.length === 0)) {
|
|
1386
|
+
reseted = true;
|
|
1377
1387
|
}
|
|
1388
|
+
this.isReseted = reseted;
|
|
1389
|
+
this.dispatch(TrackBoxEvents.RESET, reseted);
|
|
1378
1390
|
this.updateCache(this._previousCollection, currentCollection, itemSize);
|
|
1379
|
-
this._previousCollection = currentCollection;
|
|
1391
|
+
this._previousCollection = [...(currentCollection || [])];
|
|
1380
1392
|
}
|
|
1381
1393
|
/**
|
|
1382
1394
|
* Update the cache of items from the list
|
|
@@ -1599,7 +1611,7 @@ class TrackBox extends CacheMap {
|
|
|
1599
1611
|
leftItemsOffset = rightItemsOffset = bufferSize;
|
|
1600
1612
|
}
|
|
1601
1613
|
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, deltaFromStartCreation = 0;
|
|
1602
|
-
let isNew = !this.
|
|
1614
|
+
let isNew = !this.isReseted && (scrollSize === 0);
|
|
1603
1615
|
// If the list is dynamic or there are new elements in the collection, then it switches to the long algorithm.
|
|
1604
1616
|
if (dynamicSize) {
|
|
1605
1617
|
let y = 0, stickyCollectionItem = undefined, stickyComponentSize = 0;
|
|
@@ -1610,7 +1622,7 @@ class TrackBox extends CacheMap {
|
|
|
1610
1622
|
const bounds = map.get(id) || { width: typicalItemSize, height: typicalItemSize };
|
|
1611
1623
|
componentSize = bounds[sizeProperty];
|
|
1612
1624
|
itemDisplayMethod = bounds?.method ?? ItemDisplayMethods.UPDATE;
|
|
1613
|
-
const isItemNew = bounds
|
|
1625
|
+
const isItemNew = bounds?.[IS_NEW] ?? this._isLazy;
|
|
1614
1626
|
if (!isItemNew && (!this._isLazy || !itemConfigMap[collection[0].id]?.sticky)) {
|
|
1615
1627
|
isNew = false;
|
|
1616
1628
|
}
|
|
@@ -1748,7 +1760,7 @@ class TrackBox extends CacheMap {
|
|
|
1748
1760
|
if (map.has(id)) {
|
|
1749
1761
|
const bounds = map.get(id);
|
|
1750
1762
|
itemDisplayMethod = bounds?.method ?? ItemDisplayMethods.UPDATE;
|
|
1751
|
-
const isItemNew = bounds
|
|
1763
|
+
const isItemNew = bounds?.[IS_NEW] ?? this._isLazy;
|
|
1752
1764
|
if (!isItemNew && (!this._isLazy || !itemConfigMap[collection[0].id]?.sticky)) {
|
|
1753
1765
|
isNew = false;
|
|
1754
1766
|
}
|
|
@@ -1866,7 +1878,7 @@ class TrackBox extends CacheMap {
|
|
|
1866
1878
|
height: isVertical ? size : normalizedItemHeight,
|
|
1867
1879
|
delta: 0,
|
|
1868
1880
|
}, config = {
|
|
1869
|
-
new: cache
|
|
1881
|
+
new: cache?.[IS_NEW] === true,
|
|
1870
1882
|
odd: isOdd,
|
|
1871
1883
|
even: !isOdd,
|
|
1872
1884
|
isVertical,
|
|
@@ -1908,7 +1920,7 @@ class TrackBox extends CacheMap {
|
|
|
1908
1920
|
height: h,
|
|
1909
1921
|
delta: 0,
|
|
1910
1922
|
}, config = {
|
|
1911
|
-
new: cache
|
|
1923
|
+
new: cache?.[IS_NEW] === true,
|
|
1912
1924
|
odd: isOdd,
|
|
1913
1925
|
even: !isOdd,
|
|
1914
1926
|
isVertical,
|
|
@@ -1949,7 +1961,7 @@ class TrackBox extends CacheMap {
|
|
|
1949
1961
|
height: isVertical ? size : normalizedItemHeight,
|
|
1950
1962
|
delta: 0,
|
|
1951
1963
|
}, config = {
|
|
1952
|
-
new: cache
|
|
1964
|
+
new: cache?.[IS_NEW] === true,
|
|
1953
1965
|
odd: isOdd,
|
|
1954
1966
|
even: !isOdd,
|
|
1955
1967
|
isVertical,
|
|
@@ -2658,10 +2670,25 @@ class NgVirtualListComponent {
|
|
|
2658
2670
|
this._cacheVersion.set(v);
|
|
2659
2671
|
};
|
|
2660
2672
|
_cacheVersion = signal(-1);
|
|
2673
|
+
_isResetedReachStart = true;
|
|
2674
|
+
_onTrackBoxResetHandler = (v) => {
|
|
2675
|
+
if (v) {
|
|
2676
|
+
this._isResetedReachStart = true;
|
|
2677
|
+
const container = this._container()?.nativeElement;
|
|
2678
|
+
if (container) {
|
|
2679
|
+
const params = {
|
|
2680
|
+
[this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: 0,
|
|
2681
|
+
behavior: BEHAVIOR_INSTANT,
|
|
2682
|
+
};
|
|
2683
|
+
container.scrollTo(params);
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
};
|
|
2661
2687
|
constructor() {
|
|
2662
2688
|
NgVirtualListComponent.__nextId = NgVirtualListComponent.__nextId + 1 === Number.MAX_SAFE_INTEGER
|
|
2663
2689
|
? 0 : NgVirtualListComponent.__nextId + 1;
|
|
2664
2690
|
this._id = NgVirtualListComponent.__nextId;
|
|
2691
|
+
this._trackBox.addEventListener(TrackBoxEvents.RESET, this._onTrackBoxResetHandler);
|
|
2665
2692
|
this._service.initialize(this._trackBox);
|
|
2666
2693
|
this._service.itemToFocus = this.itemToFocus;
|
|
2667
2694
|
this._initialized = signal(false);
|
|
@@ -2674,12 +2701,13 @@ class NgVirtualListComponent {
|
|
|
2674
2701
|
this._service.listElement = v.nativeElement;
|
|
2675
2702
|
})).subscribe();
|
|
2676
2703
|
const $trackBy = toObservable(this.trackBy), $selectByClick = toObservable(this.selectByClick), $collapseByClick = toObservable(this.collapseByClick), $isScrollStart = toObservable(this._isScrollStart), $isScrollFinished = toObservable(this._isScrollFinished);
|
|
2677
|
-
$isScrollStart.pipe(takeUntilDestroyed(), distinctUntilChanged(),
|
|
2678
|
-
if (v) {
|
|
2704
|
+
$isScrollStart.pipe(takeUntilDestroyed(), distinctUntilChanged(), tap(v => {
|
|
2705
|
+
if (v && !this._isResetedReachStart) {
|
|
2679
2706
|
this.onScrollReachStart.emit();
|
|
2680
2707
|
}
|
|
2708
|
+
this._isResetedReachStart = false;
|
|
2681
2709
|
})).subscribe();
|
|
2682
|
-
$isScrollFinished.pipe(takeUntilDestroyed(), distinctUntilChanged(),
|
|
2710
|
+
$isScrollFinished.pipe(takeUntilDestroyed(), distinctUntilChanged(), tap(v => {
|
|
2683
2711
|
if (v) {
|
|
2684
2712
|
this.onScrollReachEnd.emit();
|
|
2685
2713
|
}
|
|
@@ -2774,9 +2802,11 @@ class NgVirtualListComponent {
|
|
|
2774
2802
|
this.resetBoundsSize(isVertical, totalSize);
|
|
2775
2803
|
this.createDisplayComponentsIfNeed(displayItems);
|
|
2776
2804
|
this.tracking();
|
|
2777
|
-
const scrollLength = (this._isVertical ? this._container()?.nativeElement.scrollHeight ?? 0 : this._container()?.nativeElement.scrollWidth) ?? 0, actualScrollLength = scrollLength === 0 ? 0 : scrollLength - (this._isVertical ? height : width), scrollPosition = actualScrollSize + this._trackBox.delta;
|
|
2778
|
-
|
|
2779
|
-
|
|
2805
|
+
const scrollLength = (this._isVertical ? this._container()?.nativeElement.scrollHeight ?? 0 : this._container()?.nativeElement.scrollWidth) ?? 0, actualScrollLength = scrollLength === 0 ? 0 : Math.round(scrollLength - (this._isVertical ? height : width)), scrollPosition = actualScrollSize + this._trackBox.delta;
|
|
2806
|
+
if (actualScrollLength > 0) {
|
|
2807
|
+
this._isScrollStart.set(scrollPosition === 0);
|
|
2808
|
+
this._isScrollFinished.set(scrollPosition === actualScrollLength);
|
|
2809
|
+
}
|
|
2780
2810
|
if (this._isSnappingMethodAdvanced) {
|
|
2781
2811
|
this.updateRegularRenderer();
|
|
2782
2812
|
}
|
|
@@ -2845,13 +2875,13 @@ class NgVirtualListComponent {
|
|
|
2845
2875
|
}
|
|
2846
2876
|
listenCacheChangesIfNeed(value) {
|
|
2847
2877
|
if (value) {
|
|
2848
|
-
if (!this._trackBox.hasEventListener(
|
|
2849
|
-
this._trackBox.addEventListener(
|
|
2878
|
+
if (!this._trackBox.hasEventListener(TrackBoxEvents.CHANGE, this._onTrackBoxChangeHandler)) {
|
|
2879
|
+
this._trackBox.addEventListener(TrackBoxEvents.CHANGE, this._onTrackBoxChangeHandler);
|
|
2850
2880
|
}
|
|
2851
2881
|
}
|
|
2852
2882
|
else {
|
|
2853
|
-
if (this._trackBox.hasEventListener(
|
|
2854
|
-
this._trackBox.removeEventListener(
|
|
2883
|
+
if (this._trackBox.hasEventListener(TrackBoxEvents.CHANGE, this._onTrackBoxChangeHandler)) {
|
|
2884
|
+
this._trackBox.removeEventListener(TrackBoxEvents.CHANGE, this._onTrackBoxChangeHandler);
|
|
2855
2885
|
}
|
|
2856
2886
|
}
|
|
2857
2887
|
}
|