ng-virtual-list 19.7.0 → 19.7.2
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 +17 -16
- package/fesm2022/ng-virtual-list.mjs +44 -32
- package/fesm2022/ng-virtual-list.mjs.map +1 -1
- package/lib/components/ng-virtual-list-item.component.d.ts +5 -3
- package/lib/models/index.d.ts +2 -2
- package/lib/models/item-config-map.model.d.ts +23 -0
- package/lib/models/render-item-config.model.d.ts +5 -1
- package/lib/ng-virtual-list.component.d.ts +15 -6
- package/lib/utils/trackBox.d.ts +4 -4
- package/package.json +1 -1
- package/esm2020/lib/components/ng-virtual-list-item.component.mjs +0 -166
- package/esm2020/lib/const/index.mjs +0 -49
- package/esm2020/lib/enums/direction.mjs +0 -2
- package/esm2020/lib/enums/directions.mjs +0 -18
- package/esm2020/lib/enums/index.mjs +0 -4
- package/esm2020/lib/enums/snapping-method.mjs +0 -2
- package/esm2020/lib/enums/snapping-methods.mjs +0 -18
- package/esm2020/lib/models/base-virtual-list-item-component.mjs +0 -9
- package/esm2020/lib/models/collection.model.mjs +0 -3
- package/esm2020/lib/models/component.model.mjs +0 -2
- package/esm2020/lib/models/index.mjs +0 -2
- package/esm2020/lib/models/item.model.mjs +0 -2
- package/esm2020/lib/models/render-collection.model.mjs +0 -3
- package/esm2020/lib/models/render-item-config.model.mjs +0 -2
- package/esm2020/lib/models/render-item.model.mjs +0 -3
- package/esm2020/lib/models/scroll-direction.model.mjs +0 -2
- package/esm2020/lib/models/scroll-event.model.mjs +0 -2
- package/esm2020/lib/models/sticky-map.model.mjs +0 -2
- package/esm2020/lib/ng-virtual-list.component.mjs +0 -700
- package/esm2020/lib/ng-virtual-list.module.mjs +0 -20
- package/esm2020/lib/ng-virtual-list.service.mjs +0 -29
- package/esm2020/lib/types/id.mjs +0 -2
- package/esm2020/lib/types/index.mjs +0 -2
- package/esm2020/lib/types/rect.mjs +0 -2
- package/esm2020/lib/types/size.mjs +0 -2
- package/esm2020/lib/utils/browser.mjs +0 -3
- package/esm2020/lib/utils/buffer-interpolation.mjs +0 -27
- package/esm2020/lib/utils/cacheMap.mjs +0 -167
- package/esm2020/lib/utils/debounce.mjs +0 -31
- package/esm2020/lib/utils/disposableComponent.mjs +0 -29
- package/esm2020/lib/utils/eventEmitter.mjs +0 -106
- package/esm2020/lib/utils/index.mjs +0 -5
- package/esm2020/lib/utils/isDirection.mjs +0 -15
- package/esm2020/lib/utils/scrollEvent.mjs +0 -42
- package/esm2020/lib/utils/snapping-method.mjs +0 -9
- package/esm2020/lib/utils/toggleClassName.mjs +0 -15
- package/esm2020/lib/utils/trackBox.mjs +0 -762
- package/esm2020/lib/utils/tracker.mjs +0 -143
- package/esm2020/ng-virtual-list.mjs +0 -5
- package/esm2020/public-api.mjs +0 -10
- package/esm2022/lib/components/ng-virtual-list-item.component.mjs +0 -158
- package/esm2022/lib/const/index.mjs +0 -49
- package/esm2022/lib/enums/direction.mjs +0 -2
- package/esm2022/lib/enums/directions.mjs +0 -18
- package/esm2022/lib/enums/index.mjs +0 -4
- package/esm2022/lib/enums/snapping-method.mjs +0 -2
- package/esm2022/lib/enums/snapping-methods.mjs +0 -18
- package/esm2022/lib/models/base-virtual-list-item-component.mjs +0 -9
- package/esm2022/lib/models/collection.model.mjs +0 -3
- package/esm2022/lib/models/component.model.mjs +0 -2
- package/esm2022/lib/models/index.mjs +0 -2
- package/esm2022/lib/models/item.model.mjs +0 -2
- package/esm2022/lib/models/render-collection.model.mjs +0 -3
- package/esm2022/lib/models/render-item-config.model.mjs +0 -2
- package/esm2022/lib/models/render-item.model.mjs +0 -3
- package/esm2022/lib/models/scroll-direction.model.mjs +0 -2
- package/esm2022/lib/models/scroll-event.model.mjs +0 -2
- package/esm2022/lib/models/sticky-map.model.mjs +0 -2
- package/esm2022/lib/ng-virtual-list.component.mjs +0 -555
- package/esm2022/lib/ng-virtual-list.module.mjs +0 -20
- package/esm2022/lib/ng-virtual-list.service.mjs +0 -29
- package/esm2022/lib/types/id.mjs +0 -2
- package/esm2022/lib/types/index.mjs +0 -2
- package/esm2022/lib/types/rect.mjs +0 -2
- package/esm2022/lib/types/size.mjs +0 -2
- package/esm2022/lib/utils/browser.mjs +0 -3
- package/esm2022/lib/utils/buffer-interpolation.mjs +0 -27
- package/esm2022/lib/utils/cacheMap.mjs +0 -168
- package/esm2022/lib/utils/debounce.mjs +0 -31
- package/esm2022/lib/utils/eventEmitter.mjs +0 -105
- package/esm2022/lib/utils/index.mjs +0 -5
- package/esm2022/lib/utils/isDirection.mjs +0 -15
- package/esm2022/lib/utils/scrollEvent.mjs +0 -42
- package/esm2022/lib/utils/snapping-method.mjs +0 -9
- package/esm2022/lib/utils/toggleClassName.mjs +0 -15
- package/esm2022/lib/utils/trackBox.mjs +0 -768
- package/esm2022/lib/utils/tracker.mjs +0 -144
- package/esm2022/ng-virtual-list.mjs +0 -5
- package/esm2022/public-api.mjs +0 -11
- package/fesm2015/ng-virtual-list.mjs +0 -2325
- package/fesm2015/ng-virtual-list.mjs.map +0 -1
- package/fesm2020/ng-virtual-list.mjs +0 -2330
- package/fesm2020/ng-virtual-list.mjs.map +0 -1
- package/lib/models/sticky-map.model.d.ts +0 -14
- package/lib/ng-virtual-list.module.d.ts +0 -9
- package/lib/utils/disposableComponent.d.ts +0 -15
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ export class AppComponent {
|
|
|
109
109
|
Template:
|
|
110
110
|
```html
|
|
111
111
|
<ng-virtual-list class="list" direction="horizontal" [items]="horizontalGroupItems" [itemRenderer]="horizontalGroupItemRenderer"
|
|
112
|
-
[bufferSize]="50" [
|
|
112
|
+
[bufferSize]="50" [itemConfigMap]="horizontalGroupItemConfigMap" [itemSize]="54" [snap]="true" (onItemClick)="onItemClick($event)"></ng-virtual-list>
|
|
113
113
|
|
|
114
114
|
<ng-template #horizontalGroupItemRenderer let-data="data">
|
|
115
115
|
@if (data) {
|
|
@@ -131,7 +131,7 @@ Template:
|
|
|
131
131
|
|
|
132
132
|
Component:
|
|
133
133
|
```ts
|
|
134
|
-
import { NgVirtualListComponent, IVirtualListCollection,
|
|
134
|
+
import { NgVirtualListComponent, IVirtualListCollection, IVirtualListItemConfigMap, IRenderVirtualListItem } from 'ng-virtual-list';
|
|
135
135
|
|
|
136
136
|
const GROUP_NAMES = ['A', 'B', 'C', 'D', 'E'];
|
|
137
137
|
|
|
@@ -145,12 +145,12 @@ interface ICollectionItem {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
const HORIZONTAL_GROUP_ITEMS: IVirtualListCollection<ICollectionItem> = [],
|
|
148
|
-
|
|
148
|
+
HORIZONTAL_GROUP_ITEM_CONFIG_MAP: IVirtualListItemConfigMap = {};
|
|
149
149
|
|
|
150
150
|
for (let i = 0, l = 1000000; i < l; i++) {
|
|
151
151
|
const id = i + 1, type = Math.random() > .895 ? 'group-header' : 'item';
|
|
152
152
|
HORIZONTAL_GROUP_ITEMS.push({ id, type, name: type === 'group-header' ? getGroupName() : `${i}` });
|
|
153
|
-
|
|
153
|
+
HORIZONTAL_GROUP_ITEM_CONFIG_MAP[id] = type === 'group-header' ? 1 : 0;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
@Component({
|
|
@@ -161,7 +161,7 @@ for (let i = 0, l = 1000000; i < l; i++) {
|
|
|
161
161
|
})
|
|
162
162
|
export class AppComponent {
|
|
163
163
|
horizontalGroupItems = HORIZONTAL_GROUP_ITEMS;
|
|
164
|
-
|
|
164
|
+
horizontalGroupItemConfigMap = HORIZONTAL_GROUP_ITEM_CONFIG_MAP;
|
|
165
165
|
|
|
166
166
|
onItemClick(item: IRenderVirtualListItem<ICollectionItem> | undefined) {
|
|
167
167
|
if (item) {
|
|
@@ -219,7 +219,7 @@ export class AppComponent {
|
|
|
219
219
|
Template:
|
|
220
220
|
```html
|
|
221
221
|
<ng-virtual-list class="list simple" [items]="groupItems" [bufferSize]="50" [itemRenderer]="groupItemRenderer"
|
|
222
|
-
[
|
|
222
|
+
[itemConfigMap]="groupItemConfigMap" [itemSize]="40" [snap]="false"></ng-virtual-list>
|
|
223
223
|
|
|
224
224
|
<ng-template #groupItemRenderer let-data="data">
|
|
225
225
|
@if (data) {
|
|
@@ -246,7 +246,7 @@ Template:
|
|
|
246
246
|
Template (with snapping):
|
|
247
247
|
```html
|
|
248
248
|
<ng-virtual-list class="list simple" [items]="groupItems" [bufferSize]="50" [itemRenderer]="groupItemRenderer"
|
|
249
|
-
[
|
|
249
|
+
[itemConfigMap]="groupItemConfigMap" [itemSize]="40" [snap]="true"></ng-virtual-list>
|
|
250
250
|
|
|
251
251
|
<ng-template #groupItemRenderer let-data="data">
|
|
252
252
|
@if (data) {
|
|
@@ -268,10 +268,10 @@ Template (with snapping):
|
|
|
268
268
|
|
|
269
269
|
Component:
|
|
270
270
|
```ts
|
|
271
|
-
import { NgVirtualListComponent, IVirtualListCollection,
|
|
271
|
+
import { NgVirtualListComponent, IVirtualListCollection, IVirtualListItemConfigMap } from 'ng-virtual-list';
|
|
272
272
|
|
|
273
273
|
const GROUP_ITEMS: IVirtualListCollection = [],
|
|
274
|
-
|
|
274
|
+
GROUP_ITEM_CONFIG_MAP: IVirtualListItemConfigMap = {};
|
|
275
275
|
|
|
276
276
|
let groupIndex = 0;
|
|
277
277
|
for (let i = 0, l = 10000000; i < l; i++) {
|
|
@@ -280,7 +280,7 @@ for (let i = 0, l = 10000000; i < l; i++) {
|
|
|
280
280
|
groupIndex++;
|
|
281
281
|
}
|
|
282
282
|
GROUP_ITEMS.push({ id, type, name: type === 'group-header' ? `Group ${groupIndex}` : `Item: ${i}` });
|
|
283
|
-
|
|
283
|
+
GROUP_ITEM_CONFIG_MAP[id] = type === 'group-header' ? 1 : 0;
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
@Component({
|
|
@@ -291,7 +291,7 @@ for (let i = 0, l = 10000000; i < l; i++) {
|
|
|
291
291
|
})
|
|
292
292
|
export class AppComponent {
|
|
293
293
|
groupItems = GROUP_ITEMS;
|
|
294
|
-
|
|
294
|
+
groupItemConfigMap = GROUP_ITEM_CONFIG_MAP;
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
```
|
|
@@ -365,7 +365,7 @@ Virtual list with height-adjustable elements.
|
|
|
365
365
|
Template
|
|
366
366
|
```html
|
|
367
367
|
<ng-virtual-list #dynamicList class="list" [items]="groupDynamicItems" [itemRenderer]="groupItemRenderer" [bufferSize]="10"
|
|
368
|
-
[
|
|
368
|
+
[itemConfigMap]="groupDynamicItemConfigMap" [dynamicSize]="true" [snap]="true"></ng-virtual-list>
|
|
369
369
|
|
|
370
370
|
<ng-template #groupItemRenderer let-data="data">
|
|
371
371
|
@if (data) {
|
|
@@ -413,7 +413,7 @@ const generateText = () => {
|
|
|
413
413
|
};
|
|
414
414
|
|
|
415
415
|
const GROUP_DYNAMIC_ITEMS: IVirtualListCollection = [],
|
|
416
|
-
|
|
416
|
+
GROUP_DYNAMIC_ITEM_CONFIG_MAP: IVirtualListItemConfigMap = {};
|
|
417
417
|
|
|
418
418
|
let groupDynamicIndex = 0;
|
|
419
419
|
for (let i = 0, l = 100000; i < l; i++) {
|
|
@@ -422,7 +422,7 @@ for (let i = 0, l = 100000; i < l; i++) {
|
|
|
422
422
|
groupDynamicIndex++;
|
|
423
423
|
}
|
|
424
424
|
GROUP_DYNAMIC_ITEMS.push({ id, type, name: type === 'group-header' ? `Group ${groupDynamicIndex}` : `${id}. ${generateText()}` });
|
|
425
|
-
|
|
425
|
+
GROUP_DYNAMIC_ITEM_CONFIG_MAP[id] = type === 'group-header' ? 1 : 0;
|
|
426
426
|
}
|
|
427
427
|
|
|
428
428
|
@Component({
|
|
@@ -433,7 +433,7 @@ for (let i = 0, l = 100000; i < l; i++) {
|
|
|
433
433
|
})
|
|
434
434
|
export class AppComponent {
|
|
435
435
|
groupDynamicItems = GROUP_DYNAMIC_ITEMS;
|
|
436
|
-
|
|
436
|
+
groupDynamicItemConfigMap = GROUP_DYNAMIC_ITEM_CONFIG_MAP;
|
|
437
437
|
}
|
|
438
438
|
```
|
|
439
439
|
|
|
@@ -535,7 +535,8 @@ Inputs
|
|
|
535
535
|
| bufferSize | number? = 2 | Number of elements outside the scope of visibility. Default value is 2. |
|
|
536
536
|
| 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. |
|
|
537
537
|
| itemRenderer | TemplateRef | Rendering element template. |
|
|
538
|
-
|
|
|
538
|
+
| methodForSelecting | [MethodForSelecting](https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/enums/method-for-selecting.ts) | Method for selecting list items. Default value is 'none'. 'select' - List items are selected one by one. 'multi-select' - Multiple selection of list items. 'none' - List items are not selectable. |
|
|
539
|
+
| itemConfigMap | [IVirtualListItemConfigMap?](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/models/item-config-map.model.ts) | Sets sticky position and selectable for the list item element. If sticky position is greater than 0, then sticky position is applied. If the sticky value is greater than `0`, then the sticky position mode is enabled for the element. `1` - position start, `2` - position end. Default value is `0`. Selectable determines whether an element can be selected or not. Default value is `true`. |
|
|
539
540
|
| snap | boolean? = false | Determines whether elements will snap. Default value is "false". |
|
|
540
541
|
| snappingMethod | [SnappingMethod? = 'normal'](https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/enums/snapping-method.ts) | Snapping method. 'normal' - Normal group rendering. 'advanced' - The group is rendered on a transparent background. List items below the group are not rendered. |
|
|
541
542
|
| direction | [Direction? = 'vertical'](https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/enums/direction.ts) | Determines the direction in which elements are placed. Default value is "vertical". |
|
|
@@ -185,7 +185,7 @@ class NgVirtualListService {
|
|
|
185
185
|
}
|
|
186
186
|
itemClick(data) {
|
|
187
187
|
this._$itemClick.next(data);
|
|
188
|
-
if (data) {
|
|
188
|
+
if (data && data.config.selectable) {
|
|
189
189
|
switch (this._$methodOfSelecting.getValue()) {
|
|
190
190
|
case MethodsForSelectingTypes.SELECT: {
|
|
191
191
|
const curr = this._$selectedIds.getValue();
|
|
@@ -1116,8 +1116,8 @@ class TrackBox extends CacheMap {
|
|
|
1116
1116
|
/**
|
|
1117
1117
|
* Finds the position of a collection element by the given Id
|
|
1118
1118
|
*/
|
|
1119
|
-
getItemPosition(id,
|
|
1120
|
-
const opt = { fromItemId: id,
|
|
1119
|
+
getItemPosition(id, itemConfigMap, options) {
|
|
1120
|
+
const opt = { fromItemId: id, itemConfigMap, ...options };
|
|
1121
1121
|
this._defaultBufferSize = opt.bufferSize;
|
|
1122
1122
|
this._maxBufferSize = opt.maxBufferSize;
|
|
1123
1123
|
const { scrollSize, isFromItemIdFound } = this.recalculateMetrics({
|
|
@@ -1132,8 +1132,8 @@ class TrackBox extends CacheMap {
|
|
|
1132
1132
|
/**
|
|
1133
1133
|
* Updates the collection of display objects
|
|
1134
1134
|
*/
|
|
1135
|
-
updateCollection(items,
|
|
1136
|
-
const opt = {
|
|
1135
|
+
updateCollection(items, itemConfigMap, options) {
|
|
1136
|
+
const opt = { itemConfigMap, ...options }, crudDetected = this._crudDetected, deletedItemsMap = this._deletedItemsMap;
|
|
1137
1137
|
if (opt.dynamicSize) {
|
|
1138
1138
|
this.cacheElements();
|
|
1139
1139
|
}
|
|
@@ -1154,7 +1154,7 @@ class TrackBox extends CacheMap {
|
|
|
1154
1154
|
if (opt.dynamicSize) {
|
|
1155
1155
|
this.snapshot();
|
|
1156
1156
|
}
|
|
1157
|
-
const displayItems = this.generateDisplayCollection(items,
|
|
1157
|
+
const displayItems = this.generateDisplayCollection(items, itemConfigMap, { ...metrics, });
|
|
1158
1158
|
return { displayItems, totalSize: metrics.totalSize, delta: metrics.delta, crudDetected };
|
|
1159
1159
|
}
|
|
1160
1160
|
/**
|
|
@@ -1235,7 +1235,7 @@ class TrackBox extends CacheMap {
|
|
|
1235
1235
|
* Calculates list metrics
|
|
1236
1236
|
*/
|
|
1237
1237
|
recalculateMetrics(options) {
|
|
1238
|
-
const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, bufferSize: minBufferSize, scrollSize, snap,
|
|
1238
|
+
const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, bufferSize: minBufferSize, scrollSize, snap, itemConfigMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options;
|
|
1239
1239
|
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)
|
|
1240
1240
|
|| (typeof fromItemId === 'string' && fromItemId > '-1');
|
|
1241
1241
|
let leftItemsOffset = 0, rightItemsOffset = 0;
|
|
@@ -1295,21 +1295,21 @@ class TrackBox extends CacheMap {
|
|
|
1295
1295
|
totalSize += componentSize;
|
|
1296
1296
|
if (isFromId) {
|
|
1297
1297
|
if (itemById === undefined) {
|
|
1298
|
-
if (id !== fromItemId &&
|
|
1298
|
+
if (id !== fromItemId && itemConfigMap && itemConfigMap[id]?.sticky === 1) {
|
|
1299
1299
|
stickyComponentSize = componentSize;
|
|
1300
1300
|
stickyCollectionItem = collectionItem;
|
|
1301
1301
|
}
|
|
1302
1302
|
if (id === fromItemId) {
|
|
1303
1303
|
isFromItemIdFound = true;
|
|
1304
1304
|
targetDisplayItemIndex = i;
|
|
1305
|
-
if (stickyCollectionItem &&
|
|
1305
|
+
if (stickyCollectionItem && itemConfigMap) {
|
|
1306
1306
|
const { num } = this.getElementNumToEnd(i, collection, map, typicalItemSize, size, isVertical);
|
|
1307
1307
|
if (num > 0) {
|
|
1308
1308
|
isTargetInOverscroll = true;
|
|
1309
1309
|
y -= size - componentSize;
|
|
1310
1310
|
}
|
|
1311
1311
|
else {
|
|
1312
|
-
if (
|
|
1312
|
+
if (itemConfigMap && !itemConfigMap[collectionItem.id] && y >= scrollSize && y < scrollSize + stickyComponentSize) {
|
|
1313
1313
|
const snappedY = scrollSize - stickyComponentSize;
|
|
1314
1314
|
leftHiddenItemsWeight -= (snappedY - y);
|
|
1315
1315
|
y = snappedY;
|
|
@@ -1492,7 +1492,7 @@ class TrackBox extends CacheMap {
|
|
|
1492
1492
|
changes() {
|
|
1493
1493
|
this.bumpVersion();
|
|
1494
1494
|
}
|
|
1495
|
-
generateDisplayCollection(items,
|
|
1495
|
+
generateDisplayCollection(items, itemConfigMap, metrics) {
|
|
1496
1496
|
const { width, height, normalizedItemWidth, normalizedItemHeight, dynamicSize, itemsOnDisplayLength, itemsFromStartToScrollEnd, isVertical, renderItems: renderItemsLength, scrollSize, sizeProperty, snap, snippedPos, startPosition, totalLength, startIndex, typicalItemSize, } = metrics, displayItems = [];
|
|
1497
1497
|
if (items.length) {
|
|
1498
1498
|
const actualSnippedPosition = snippedPos, isSnappingMethodAdvanced = this.isSnappingMethodAdvanced, boundsSize = isVertical ? height : width, actualEndSnippedPosition = boundsSize;
|
|
@@ -1502,7 +1502,7 @@ class TrackBox extends CacheMap {
|
|
|
1502
1502
|
if (!items[i]) {
|
|
1503
1503
|
continue;
|
|
1504
1504
|
}
|
|
1505
|
-
const id = items[i].id, sticky =
|
|
1505
|
+
const id = items[i].id, sticky = itemConfigMap[id]?.sticky ?? 0, selectable = itemConfigMap[id]?.selectable ?? true, size = dynamicSize ? this.get(id)?.[sizeProperty] || typicalItemSize : typicalItemSize;
|
|
1506
1506
|
if (sticky === 1) {
|
|
1507
1507
|
const isOdd = i % 2 != 0, measures = {
|
|
1508
1508
|
x: isVertical ? 0 : actualSnippedPosition,
|
|
@@ -1514,6 +1514,7 @@ class TrackBox extends CacheMap {
|
|
|
1514
1514
|
odd: isOdd,
|
|
1515
1515
|
even: !isOdd,
|
|
1516
1516
|
isVertical,
|
|
1517
|
+
selectable,
|
|
1517
1518
|
sticky,
|
|
1518
1519
|
snap,
|
|
1519
1520
|
snapped: true,
|
|
@@ -1537,7 +1538,7 @@ class TrackBox extends CacheMap {
|
|
|
1537
1538
|
if (!items[i]) {
|
|
1538
1539
|
continue;
|
|
1539
1540
|
}
|
|
1540
|
-
const id = items[i].id, sticky =
|
|
1541
|
+
const id = items[i].id, sticky = itemConfigMap[id]?.sticky ?? 0, selectable = itemConfigMap[id]?.selectable ?? true, size = dynamicSize
|
|
1541
1542
|
? this.get(id)?.[sizeProperty] || typicalItemSize
|
|
1542
1543
|
: typicalItemSize;
|
|
1543
1544
|
if (sticky === 2) {
|
|
@@ -1551,6 +1552,7 @@ class TrackBox extends CacheMap {
|
|
|
1551
1552
|
odd: isOdd,
|
|
1552
1553
|
even: !isOdd,
|
|
1553
1554
|
isVertical,
|
|
1555
|
+
selectable,
|
|
1554
1556
|
sticky,
|
|
1555
1557
|
snap,
|
|
1556
1558
|
snapped: true,
|
|
@@ -1578,9 +1580,9 @@ class TrackBox extends CacheMap {
|
|
|
1578
1580
|
}
|
|
1579
1581
|
const id = items[i].id, size = dynamicSize ? this.get(id)?.[sizeProperty] || typicalItemSize : typicalItemSize;
|
|
1580
1582
|
if (id !== stickyItem?.id && id !== endStickyItem?.id) {
|
|
1581
|
-
const isOdd = i % 2 != 0, snapped = snap && (
|
|
1582
|
-
x: isVertical ?
|
|
1583
|
-
y: isVertical ? pos :
|
|
1583
|
+
const isOdd = i % 2 != 0, sticky = itemConfigMap[id]?.sticky ?? 0, selectable = itemConfigMap[id]?.selectable ?? true, snapped = snap && (sticky === 1 && pos <= scrollSize || sticky === 2 && pos >= scrollSize + boundsSize - size), measures = {
|
|
1584
|
+
x: isVertical ? sticky === 1 ? 0 : boundsSize - size : pos,
|
|
1585
|
+
y: isVertical ? pos : sticky === 2 ? boundsSize - size : 0,
|
|
1584
1586
|
width: isVertical ? normalizedItemWidth : size,
|
|
1585
1587
|
height: isVertical ? size : normalizedItemHeight,
|
|
1586
1588
|
delta: 0,
|
|
@@ -1588,7 +1590,8 @@ class TrackBox extends CacheMap {
|
|
|
1588
1590
|
odd: isOdd,
|
|
1589
1591
|
even: !isOdd,
|
|
1590
1592
|
isVertical,
|
|
1591
|
-
|
|
1593
|
+
selectable,
|
|
1594
|
+
sticky: sticky,
|
|
1592
1595
|
snap,
|
|
1593
1596
|
snapped: false,
|
|
1594
1597
|
snappedOut: false,
|
|
@@ -1601,7 +1604,7 @@ class TrackBox extends CacheMap {
|
|
|
1601
1604
|
}
|
|
1602
1605
|
const itemData = items[i];
|
|
1603
1606
|
const item = { index: i, id, measures, data: itemData, config };
|
|
1604
|
-
if (!nextSticky && stickyItemIndex < i &&
|
|
1607
|
+
if (!nextSticky && stickyItemIndex < i && sticky === 1 && (pos <= scrollSize + size + stickyItemSize)) {
|
|
1605
1608
|
item.measures.x = isVertical ? 0 : snapped ? actualSnippedPosition : pos;
|
|
1606
1609
|
item.measures.y = isVertical ? snapped ? actualSnippedPosition : pos : 0;
|
|
1607
1610
|
nextSticky = item;
|
|
@@ -1609,7 +1612,7 @@ class TrackBox extends CacheMap {
|
|
|
1609
1612
|
nextSticky.measures.delta = isVertical ? (item.measures.y - scrollSize) : (item.measures.x - scrollSize);
|
|
1610
1613
|
nextSticky.config.zIndex = '3';
|
|
1611
1614
|
}
|
|
1612
|
-
else if (!nextEndSticky && endStickyItemIndex > i &&
|
|
1615
|
+
else if (!nextEndSticky && endStickyItemIndex > i && sticky === 2 && (pos >= scrollSize + boundsSize - size - endStickyItemSize)) {
|
|
1613
1616
|
item.measures.x = isVertical ? 0 : snapped ? actualEndSnippedPosition - size : pos;
|
|
1614
1617
|
item.measures.y = isVertical ? snapped ? actualEndSnippedPosition - size : pos : 0;
|
|
1615
1618
|
nextEndSticky = item;
|
|
@@ -1813,10 +1816,19 @@ class NgVirtualListComponent {
|
|
|
1813
1816
|
itemRenderer = input.required();
|
|
1814
1817
|
_itemRenderer = signal(undefined);
|
|
1815
1818
|
/**
|
|
1816
|
-
*
|
|
1817
|
-
*
|
|
1819
|
+
* @deprecated
|
|
1820
|
+
* Use `itemConfigMap` instead.
|
|
1821
|
+
*/
|
|
1822
|
+
stickyMap = input();
|
|
1823
|
+
/**
|
|
1824
|
+
* Sets sticky position and selectable for the list item element. If sticky position is greater than 0, then sticky position is applied.
|
|
1825
|
+
* If the sticky value is greater than `0`, then the sticky position mode is enabled for the element. `1` - position start, `2` - position end. Default value is `0`.
|
|
1826
|
+
* selectable determines whether an element can be selected or not. Default value is `true`.
|
|
1827
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/models/item-config-map.model.ts
|
|
1828
|
+
* @author Evgenii Grebennikov
|
|
1829
|
+
* @email djonnyx@gmail.com
|
|
1818
1830
|
*/
|
|
1819
|
-
|
|
1831
|
+
itemConfigMap = input({});
|
|
1820
1832
|
_itemSizeOptions = {
|
|
1821
1833
|
transform: (v) => {
|
|
1822
1834
|
if (v === undefined) {
|
|
@@ -1876,7 +1888,7 @@ class NgVirtualListComponent {
|
|
|
1876
1888
|
*/
|
|
1877
1889
|
snappingMethod = input(DEFAULT_SNAPPING_METHOD);
|
|
1878
1890
|
/**
|
|
1879
|
-
* Method for selecting list items.
|
|
1891
|
+
* Method for selecting list items. Default value is 'none'.
|
|
1880
1892
|
* 'select' - List items are selected one by one.
|
|
1881
1893
|
* 'multi-select' - Multiple selection of list items.
|
|
1882
1894
|
* 'none' - List items are not selectable.
|
|
@@ -1989,7 +2001,7 @@ class NgVirtualListComponent {
|
|
|
1989
2001
|
$trackBy.pipe(takeUntilDestroyed(), tap(v => {
|
|
1990
2002
|
this._trackBox.trackingPropertyName = v;
|
|
1991
2003
|
})).subscribe();
|
|
1992
|
-
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)), $
|
|
2004
|
+
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)), $itemConfigMap = toObservable(this.itemConfigMap).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))), $methodForSelecting = toObservable(this.methodForSelecting), $selectedIds = toObservable(this.selectedIds), $cacheVersion = toObservable(this._cacheVersion);
|
|
1993
2005
|
$isVertical.pipe(takeUntilDestroyed(), tap(v => {
|
|
1994
2006
|
this._isVertical = v;
|
|
1995
2007
|
const el = this._elementRef.nativeElement;
|
|
@@ -2028,14 +2040,14 @@ class NgVirtualListComponent {
|
|
|
2028
2040
|
$dynamicSize.pipe(takeUntilDestroyed(), tap(dynamicSize => {
|
|
2029
2041
|
this.listenCacheChangesIfNeed(dynamicSize);
|
|
2030
2042
|
})).subscribe();
|
|
2031
|
-
combineLatest([this.$initialized, $bounds, $items, $
|
|
2043
|
+
combineLatest([this.$initialized, $bounds, $items, $itemConfigMap, $scrollSize, $itemSize,
|
|
2032
2044
|
$bufferSize, $maxBufferSize, $snap, $isVertical, $dynamicSize, $enabledBufferOptimization, $cacheVersion,
|
|
2033
|
-
]).pipe(takeUntilDestroyed(), distinctUntilChanged(), filter(([initialized]) => !!initialized), switchMap(([, bounds, items,
|
|
2045
|
+
]).pipe(takeUntilDestroyed(), distinctUntilChanged(), filter(([initialized]) => !!initialized), switchMap(([, bounds, items, itemConfigMap, scrollSize, itemSize, bufferSize, maxBufferSize, snap, isVertical, dynamicSize, enabledBufferOptimization, cacheVersion,]) => {
|
|
2034
2046
|
let actualScrollSize = (this._isVertical ? this._container()?.nativeElement.scrollTop ?? 0 : this._container()?.nativeElement.scrollLeft) ?? 0;
|
|
2035
2047
|
const { width, height } = bounds, opts = {
|
|
2036
2048
|
bounds: { width, height }, dynamicSize, isVertical, itemSize,
|
|
2037
2049
|
bufferSize, maxBufferSize, scrollSize: actualScrollSize, snap, enabledBufferOptimization,
|
|
2038
|
-
}, { displayItems, totalSize } = this._trackBox.updateCollection(items,
|
|
2050
|
+
}, { displayItems, totalSize } = this._trackBox.updateCollection(items, itemConfigMap, opts);
|
|
2039
2051
|
this.resetBoundsSize(isVertical, totalSize);
|
|
2040
2052
|
this.createDisplayComponentsIfNeed(displayItems);
|
|
2041
2053
|
this.tracking();
|
|
@@ -2200,19 +2212,19 @@ class NgVirtualListComponent {
|
|
|
2200
2212
|
if (container) {
|
|
2201
2213
|
container.nativeElement.removeEventListener(SCROLL, this._onScrollHandler);
|
|
2202
2214
|
}
|
|
2203
|
-
const { width, height } = this._bounds() || { width: DEFAULT_LIST_SIZE, height: DEFAULT_LIST_SIZE },
|
|
2215
|
+
const { width, height } = this._bounds() || { width: DEFAULT_LIST_SIZE, height: DEFAULT_LIST_SIZE }, itemConfigMap = this.itemConfigMap(), items = this.items(), isVertical = this._isVertical, delta = this._trackBox.delta, opts = {
|
|
2204
2216
|
bounds: { width, height }, collection: items, dynamicSize, isVertical: this._isVertical, itemSize,
|
|
2205
2217
|
bufferSize: this.bufferSize(), maxBufferSize: this.maxBufferSize(),
|
|
2206
2218
|
scrollSize: (isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft) + delta,
|
|
2207
2219
|
snap: this.snap(), fromItemId: id, enabledBufferOptimization: this.enabledBufferOptimization(),
|
|
2208
|
-
}, scrollSize = this._trackBox.getItemPosition(id,
|
|
2220
|
+
}, scrollSize = this._trackBox.getItemPosition(id, itemConfigMap, opts), params = { [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior };
|
|
2209
2221
|
if (scrollSize === -1) {
|
|
2210
2222
|
container.nativeElement.addEventListener(SCROLL, this._onScrollHandler);
|
|
2211
2223
|
return;
|
|
2212
2224
|
}
|
|
2213
2225
|
this._trackBox.clearDelta();
|
|
2214
2226
|
if (container) {
|
|
2215
|
-
const { displayItems, totalSize } = this._trackBox.updateCollection(items,
|
|
2227
|
+
const { displayItems, totalSize } = this._trackBox.updateCollection(items, itemConfigMap, {
|
|
2216
2228
|
...opts, scrollSize, fromItemId: isLastIteration ? undefined : id,
|
|
2217
2229
|
}), delta = this._trackBox.delta;
|
|
2218
2230
|
this._trackBox.clearDelta();
|
|
@@ -2220,7 +2232,7 @@ class NgVirtualListComponent {
|
|
|
2220
2232
|
this.resetBoundsSize(isVertical, totalSize);
|
|
2221
2233
|
this.createDisplayComponentsIfNeed(displayItems);
|
|
2222
2234
|
this.tracking();
|
|
2223
|
-
const _scrollSize = this._trackBox.getItemPosition(id,
|
|
2235
|
+
const _scrollSize = this._trackBox.getItemPosition(id, itemConfigMap, { ...opts, scrollSize: actualScrollSize, fromItemId: id });
|
|
2224
2236
|
if (_scrollSize === -1) {
|
|
2225
2237
|
container.nativeElement.addEventListener(SCROLL, this._onScrollHandler);
|
|
2226
2238
|
return;
|
|
@@ -2334,7 +2346,7 @@ class NgVirtualListComponent {
|
|
|
2334
2346
|
}
|
|
2335
2347
|
}
|
|
2336
2348
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2337
|
-
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 }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, 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 }, methodForSelecting: { classPropertyName: "methodForSelecting", publicName: "methodForSelecting", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd", onViewportChange: "onViewportChange", onItemClick: "onItemClick", onSelect: "onSelect" }, providers: [NgVirtualListService], 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 <div [attr.aria-orientation]=\"orientation\" #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </div>\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 });
|
|
2349
|
+
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 }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, 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 }, itemConfigMap: { classPropertyName: "itemConfigMap", publicName: "itemConfigMap", 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 }, methodForSelecting: { classPropertyName: "methodForSelecting", publicName: "methodForSelecting", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd", onViewportChange: "onViewportChange", onItemClick: "onItemClick", onSelect: "onSelect" }, providers: [NgVirtualListService], 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 <div [attr.aria-orientation]=\"orientation\" #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </div>\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 });
|
|
2338
2350
|
}
|
|
2339
2351
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListComponent, decorators: [{
|
|
2340
2352
|
type: Component,
|