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.
Files changed (96) hide show
  1. package/README.md +17 -16
  2. package/fesm2022/ng-virtual-list.mjs +44 -32
  3. package/fesm2022/ng-virtual-list.mjs.map +1 -1
  4. package/lib/components/ng-virtual-list-item.component.d.ts +5 -3
  5. package/lib/models/index.d.ts +2 -2
  6. package/lib/models/item-config-map.model.d.ts +23 -0
  7. package/lib/models/render-item-config.model.d.ts +5 -1
  8. package/lib/ng-virtual-list.component.d.ts +15 -6
  9. package/lib/utils/trackBox.d.ts +4 -4
  10. package/package.json +1 -1
  11. package/esm2020/lib/components/ng-virtual-list-item.component.mjs +0 -166
  12. package/esm2020/lib/const/index.mjs +0 -49
  13. package/esm2020/lib/enums/direction.mjs +0 -2
  14. package/esm2020/lib/enums/directions.mjs +0 -18
  15. package/esm2020/lib/enums/index.mjs +0 -4
  16. package/esm2020/lib/enums/snapping-method.mjs +0 -2
  17. package/esm2020/lib/enums/snapping-methods.mjs +0 -18
  18. package/esm2020/lib/models/base-virtual-list-item-component.mjs +0 -9
  19. package/esm2020/lib/models/collection.model.mjs +0 -3
  20. package/esm2020/lib/models/component.model.mjs +0 -2
  21. package/esm2020/lib/models/index.mjs +0 -2
  22. package/esm2020/lib/models/item.model.mjs +0 -2
  23. package/esm2020/lib/models/render-collection.model.mjs +0 -3
  24. package/esm2020/lib/models/render-item-config.model.mjs +0 -2
  25. package/esm2020/lib/models/render-item.model.mjs +0 -3
  26. package/esm2020/lib/models/scroll-direction.model.mjs +0 -2
  27. package/esm2020/lib/models/scroll-event.model.mjs +0 -2
  28. package/esm2020/lib/models/sticky-map.model.mjs +0 -2
  29. package/esm2020/lib/ng-virtual-list.component.mjs +0 -700
  30. package/esm2020/lib/ng-virtual-list.module.mjs +0 -20
  31. package/esm2020/lib/ng-virtual-list.service.mjs +0 -29
  32. package/esm2020/lib/types/id.mjs +0 -2
  33. package/esm2020/lib/types/index.mjs +0 -2
  34. package/esm2020/lib/types/rect.mjs +0 -2
  35. package/esm2020/lib/types/size.mjs +0 -2
  36. package/esm2020/lib/utils/browser.mjs +0 -3
  37. package/esm2020/lib/utils/buffer-interpolation.mjs +0 -27
  38. package/esm2020/lib/utils/cacheMap.mjs +0 -167
  39. package/esm2020/lib/utils/debounce.mjs +0 -31
  40. package/esm2020/lib/utils/disposableComponent.mjs +0 -29
  41. package/esm2020/lib/utils/eventEmitter.mjs +0 -106
  42. package/esm2020/lib/utils/index.mjs +0 -5
  43. package/esm2020/lib/utils/isDirection.mjs +0 -15
  44. package/esm2020/lib/utils/scrollEvent.mjs +0 -42
  45. package/esm2020/lib/utils/snapping-method.mjs +0 -9
  46. package/esm2020/lib/utils/toggleClassName.mjs +0 -15
  47. package/esm2020/lib/utils/trackBox.mjs +0 -762
  48. package/esm2020/lib/utils/tracker.mjs +0 -143
  49. package/esm2020/ng-virtual-list.mjs +0 -5
  50. package/esm2020/public-api.mjs +0 -10
  51. package/esm2022/lib/components/ng-virtual-list-item.component.mjs +0 -158
  52. package/esm2022/lib/const/index.mjs +0 -49
  53. package/esm2022/lib/enums/direction.mjs +0 -2
  54. package/esm2022/lib/enums/directions.mjs +0 -18
  55. package/esm2022/lib/enums/index.mjs +0 -4
  56. package/esm2022/lib/enums/snapping-method.mjs +0 -2
  57. package/esm2022/lib/enums/snapping-methods.mjs +0 -18
  58. package/esm2022/lib/models/base-virtual-list-item-component.mjs +0 -9
  59. package/esm2022/lib/models/collection.model.mjs +0 -3
  60. package/esm2022/lib/models/component.model.mjs +0 -2
  61. package/esm2022/lib/models/index.mjs +0 -2
  62. package/esm2022/lib/models/item.model.mjs +0 -2
  63. package/esm2022/lib/models/render-collection.model.mjs +0 -3
  64. package/esm2022/lib/models/render-item-config.model.mjs +0 -2
  65. package/esm2022/lib/models/render-item.model.mjs +0 -3
  66. package/esm2022/lib/models/scroll-direction.model.mjs +0 -2
  67. package/esm2022/lib/models/scroll-event.model.mjs +0 -2
  68. package/esm2022/lib/models/sticky-map.model.mjs +0 -2
  69. package/esm2022/lib/ng-virtual-list.component.mjs +0 -555
  70. package/esm2022/lib/ng-virtual-list.module.mjs +0 -20
  71. package/esm2022/lib/ng-virtual-list.service.mjs +0 -29
  72. package/esm2022/lib/types/id.mjs +0 -2
  73. package/esm2022/lib/types/index.mjs +0 -2
  74. package/esm2022/lib/types/rect.mjs +0 -2
  75. package/esm2022/lib/types/size.mjs +0 -2
  76. package/esm2022/lib/utils/browser.mjs +0 -3
  77. package/esm2022/lib/utils/buffer-interpolation.mjs +0 -27
  78. package/esm2022/lib/utils/cacheMap.mjs +0 -168
  79. package/esm2022/lib/utils/debounce.mjs +0 -31
  80. package/esm2022/lib/utils/eventEmitter.mjs +0 -105
  81. package/esm2022/lib/utils/index.mjs +0 -5
  82. package/esm2022/lib/utils/isDirection.mjs +0 -15
  83. package/esm2022/lib/utils/scrollEvent.mjs +0 -42
  84. package/esm2022/lib/utils/snapping-method.mjs +0 -9
  85. package/esm2022/lib/utils/toggleClassName.mjs +0 -15
  86. package/esm2022/lib/utils/trackBox.mjs +0 -768
  87. package/esm2022/lib/utils/tracker.mjs +0 -144
  88. package/esm2022/ng-virtual-list.mjs +0 -5
  89. package/esm2022/public-api.mjs +0 -11
  90. package/fesm2015/ng-virtual-list.mjs +0 -2325
  91. package/fesm2015/ng-virtual-list.mjs.map +0 -1
  92. package/fesm2020/ng-virtual-list.mjs +0 -2330
  93. package/fesm2020/ng-virtual-list.mjs.map +0 -1
  94. package/lib/models/sticky-map.model.d.ts +0 -14
  95. package/lib/ng-virtual-list.module.d.ts +0 -9
  96. 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" [stickyMap]="horizontalGroupItemsStickyMap" [itemSize]="54" [snap]="true" (onItemClick)="onItemClick($event)"></ng-virtual-list>
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, IVirtualListStickyMap, IRenderVirtualListItem } from 'ng-virtual-list';
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
- HORIZONTAL_GROUP_ITEMS_STICKY_MAP: IVirtualListStickyMap = {};
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
- HORIZONTAL_GROUP_ITEMS_STICKY_MAP[id] = type === 'group-header' ? 1 : 0;
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
- horizontalGroupItemsStickyMap = HORIZONTAL_GROUP_ITEMS_STICKY_MAP;
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
- [stickyMap]="groupItemsStickyMap" [itemSize]="40" [snap]="false"></ng-virtual-list>
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
- [stickyMap]="groupItemsStickyMap" [itemSize]="40" [snap]="true"></ng-virtual-list>
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, IVirtualListStickyMap } from 'ng-virtual-list';
271
+ import { NgVirtualListComponent, IVirtualListCollection, IVirtualListItemConfigMap } from 'ng-virtual-list';
272
272
 
273
273
  const GROUP_ITEMS: IVirtualListCollection = [],
274
- GROUP_ITEMS_STICKY_MAP: IVirtualListStickyMap = {};
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
- GROUP_ITEMS_STICKY_MAP[id] = type === 'group-header' ? 1 : 0;
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
- groupItemsStickyMap = GROUP_ITEMS_STICKY_MAP;
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
- [stickyMap]="groupDynamicItemsStickyMap" [dynamicSize]="true" [snap]="true"></ng-virtual-list>
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
- GROUP_DYNAMIC_ITEMS_STICKY_MAP: IVirtualListStickyMap = {};
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
- GROUP_DYNAMIC_ITEMS_STICKY_MAP[id] = type === 'group-header' ? 1 : 0;
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
- groupDynamicItemsStickyMap = GROUP_DYNAMIC_ITEMS_STICKY_MAP;
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
- | stickyMap | [IVirtualListStickyMap?](https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/models/sticky-map.model.ts) | Dictionary zIndex by id of the list element. If the value is not set or equal to 0, then a simple element is displayed, if the value is greater than 0, then the sticky position mode is enabled for the element. 1 - position start, 2 - position end. |
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, stickyMap, options) {
1120
- const opt = { fromItemId: id, stickyMap, ...options };
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, stickyMap, options) {
1136
- const opt = { stickyMap, ...options }, crudDetected = this._crudDetected, deletedItemsMap = this._deletedItemsMap;
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, stickyMap, { ...metrics, });
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, stickyMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options;
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 && stickyMap && stickyMap[id] === 1) {
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 && stickyMap) {
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 (stickyMap && !stickyMap[collectionItem.id] && y >= scrollSize && y < scrollSize + stickyComponentSize) {
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, stickyMap, metrics) {
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 = stickyMap[id], size = dynamicSize ? this.get(id)?.[sizeProperty] || typicalItemSize : typicalItemSize;
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 = stickyMap[id], size = dynamicSize
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 && (stickyMap[id] === 1 && pos <= scrollSize || stickyMap[id] === 2 && pos >= scrollSize + boundsSize - size), measures = {
1582
- x: isVertical ? stickyMap[id] === 1 ? 0 : boundsSize - size : pos,
1583
- y: isVertical ? pos : stickyMap[id] === 2 ? boundsSize - size : 0,
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
- sticky: stickyMap[id],
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 && stickyMap[id] === 1 && (pos <= scrollSize + size + stickyItemSize)) {
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 && stickyMap[id] === 2 && (pos >= scrollSize + boundsSize - size - endStickyItemSize)) {
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
- * Dictionary zIndex by id of the list element. If the value is not set or equal to 0,
1817
- * then a simple element is displayed, if the value is greater than 0, then the sticky position mode is enabled for the element.
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
- stickyMap = input({});
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)), $stickyMap = toObservable(this.stickyMap).pipe(map(v => !v ? {} : v)), $snap = toObservable(this.snap), $isVertical = toObservable(this.direction).pipe(map(v => this.getIsVertical(v || DEFAULT_DIRECTION))), $dynamicSize = toObservable(this.dynamicSize), $enabledBufferOptimization = toObservable(this.enabledBufferOptimization), $snappingMethod = toObservable(this.snappingMethod).pipe(map(v => this.getIsSnappingMethodAdvanced(v || DEFAULT_SNAPPING_METHOD))), $methodForSelecting = toObservable(this.methodForSelecting), $selectedIds = toObservable(this.selectedIds), $cacheVersion = toObservable(this._cacheVersion);
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, $stickyMap, $scrollSize, $itemSize,
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, stickyMap, scrollSize, itemSize, bufferSize, maxBufferSize, snap, isVertical, dynamicSize, enabledBufferOptimization, cacheVersion,]) => {
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, stickyMap, opts);
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 }, stickyMap = this.stickyMap(), items = this.items(), isVertical = this._isVertical, delta = this._trackBox.delta, opts = {
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, stickyMap, opts), params = { [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior };
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, stickyMap, {
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, stickyMap, { ...opts, scrollSize: actualScrollSize, fromItemId: 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,