ng-virtual-list 19.1.44 → 19.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -427,6 +427,13 @@ List items are encapsulated in shadowDOM, so to override default styles you need
427
427
  }
428
428
  ```
429
429
 
430
+ - Set up the snapped item (Only SnappingMethod.ADVANCED)
431
+ ```css
432
+ .list::part(snapped-item) {
433
+ color: #71718c;
434
+ }
435
+ ```
436
+
430
437
  - Set up the list item
431
438
  ```css
432
439
  .list::part(item) {
@@ -23,6 +23,24 @@ var Directions;
23
23
  Directions["VERTICAL"] = "vertical";
24
24
  })(Directions || (Directions = {}));
25
25
 
26
+ /**
27
+ * Snapping method.
28
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/19.x/projects/ng-virtual-list/src/lib/enums/snapping-method.ts
29
+ * @author Evgenii Grebennikov
30
+ * @email djonnyx@gmail.com
31
+ */
32
+ var SnappingMethods;
33
+ (function (SnappingMethods) {
34
+ /**
35
+ * Normal group rendering.
36
+ */
37
+ SnappingMethods["NORMAL"] = "normal";
38
+ /**
39
+ * The group is rendered on a transparent background. List items below the group are not rendered.
40
+ */
41
+ SnappingMethods["ADVANCED"] = "advanced";
42
+ })(SnappingMethods || (SnappingMethods = {}));
43
+
26
44
  const DEFAULT_ITEM_SIZE = 24;
27
45
  const DEFAULT_ITEMS_OFFSET = 2;
28
46
  const DEFAULT_LIST_SIZE = 400;
@@ -33,10 +51,15 @@ const TRACK_BY_PROPERTY_NAME = 'id';
33
51
  const DEFAULT_DIRECTION = Directions.VERTICAL;
34
52
  const DISPLAY_OBJECTS_LENGTH_MESUREMENT_ERROR = 1;
35
53
  const MAX_SCROLL_TO_ITERATIONS = 5;
54
+ const DEFAULT_SNAPPING_METHOD = SnappingMethods.NORMAL;
36
55
  // presets
37
56
  const BEHAVIOR_AUTO = 'auto';
38
57
  const BEHAVIOR_INSTANT = 'instant';
39
58
  const BEHAVIOR_SMOOTH = 'smooth';
59
+ const DISPLAY_BLOCK = 'block';
60
+ const DISPLAY_NONE = 'none';
61
+ const OPACITY_0 = '0';
62
+ const OPACITY_100 = '100';
40
63
  const VISIBILITY_VISIBLE = 'visible';
41
64
  const VISIBILITY_HIDDEN = 'hidden';
42
65
  const SIZE_100_PERSENT = '100%';
@@ -71,6 +94,7 @@ class NgVirtualListItemComponent {
71
94
  get id() {
72
95
  return this._id;
73
96
  }
97
+ regular = false;
74
98
  data = signal(undefined);
75
99
  _data = undefined;
76
100
  set item(v) {
@@ -78,22 +102,17 @@ class NgVirtualListItemComponent {
78
102
  return;
79
103
  }
80
104
  const data = this._data = v;
81
- if (data) {
82
- const styles = this._elementRef.nativeElement.style;
83
- styles.zIndex = String(data.config.sticky);
84
- if (data.config.snapped) {
85
- styles.transform = ZEROS_TRANSLATE_3D;
86
- styles.position = POSITION_STICKY;
87
- }
88
- else {
89
- styles.position = POSITION_ABSOLUTE;
90
- styles.transform = `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.x}${PX}, ${data.config.isVertical ? data.measures.y : 0}${PX} , 0)`;
91
- }
92
- styles.height = data.config.isVertical ? data.config.dynamic ? SIZE_AUTO : `${data.measures.height}${PX}` : SIZE_100_PERSENT;
93
- styles.width = data.config.isVertical ? SIZE_100_PERSENT : data.config.dynamic ? SIZE_AUTO : `${data.measures.width}${PX}`;
94
- }
105
+ this.update();
95
106
  this.data.set(v);
96
107
  }
108
+ _regularLength = SIZE_100_PERSENT;
109
+ set regularLength(v) {
110
+ if (this._regularLength === v) {
111
+ return;
112
+ }
113
+ this._regularLength = v;
114
+ this.update();
115
+ }
97
116
  get item() {
98
117
  return this._data;
99
118
  }
@@ -112,25 +131,65 @@ class NgVirtualListItemComponent {
112
131
  this._id = NgVirtualListItemComponent.__nextId = NgVirtualListItemComponent.__nextId === Number.MAX_SAFE_INTEGER
113
132
  ? 0 : NgVirtualListItemComponent.__nextId + 1;
114
133
  }
134
+ update() {
135
+ const data = this._data, regular = this.regular, length = this._regularLength;
136
+ if (data) {
137
+ const styles = this._elementRef.nativeElement.style;
138
+ styles.zIndex = String(data.config.sticky);
139
+ if (data.config.snapped) {
140
+ styles.transform = ZEROS_TRANSLATE_3D;
141
+ if (!data.config.isSnappingMethodAdvanced) {
142
+ styles.position = POSITION_STICKY;
143
+ }
144
+ }
145
+ else {
146
+ styles.position = POSITION_ABSOLUTE;
147
+ if (regular) {
148
+ styles.transform = `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.delta}${PX}, ${data.config.isVertical ? data.measures.delta : 0}${PX} , 0)`;
149
+ }
150
+ else {
151
+ styles.transform = `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.x}${PX}, ${data.config.isVertical ? data.measures.y : 0}${PX} , 0)`;
152
+ }
153
+ }
154
+ styles.height = data.config.isVertical ? data.config.dynamic ? SIZE_AUTO : `${data.measures.height}${PX}` : regular ? length : SIZE_100_PERSENT;
155
+ styles.width = data.config.isVertical ? regular ? length : SIZE_100_PERSENT : data.config.dynamic ? SIZE_AUTO : `${data.measures.width}${PX}`;
156
+ }
157
+ }
115
158
  getBounds() {
116
159
  const el = this._elementRef.nativeElement, { width, height } = el.getBoundingClientRect();
117
160
  return { width, height };
118
161
  }
119
162
  show() {
120
163
  const styles = this._elementRef.nativeElement.style;
121
- if (styles.visibility === VISIBILITY_VISIBLE) {
122
- return;
164
+ if (this.regular) {
165
+ if (styles.display === DISPLAY_BLOCK) {
166
+ return;
167
+ }
168
+ styles.display = DISPLAY_BLOCK;
123
169
  }
124
- styles.visibility = VISIBILITY_VISIBLE;
125
- styles.zIndex = String(this.data()?.config?.sticky ?? DEFAULT_ZINDEX);
170
+ else {
171
+ if (styles.visibility === VISIBILITY_VISIBLE) {
172
+ return;
173
+ }
174
+ styles.visibility = VISIBILITY_VISIBLE;
175
+ }
176
+ styles.zIndex = String(this._data?.config?.sticky ?? DEFAULT_ZINDEX);
126
177
  }
127
178
  hide() {
128
179
  const styles = this._elementRef.nativeElement.style;
129
- if (styles.visibility === VISIBILITY_HIDDEN) {
130
- return;
180
+ if (this.regular) {
181
+ if (styles.display === DISPLAY_NONE) {
182
+ return;
183
+ }
184
+ styles.display = DISPLAY_NONE;
185
+ }
186
+ else {
187
+ if (styles.visibility === VISIBILITY_HIDDEN) {
188
+ return;
189
+ }
190
+ styles.visibility = VISIBILITY_HIDDEN;
131
191
  }
132
192
  styles.position = POSITION_ABSOLUTE;
133
- styles.visibility = VISIBILITY_HIDDEN;
134
193
  styles.transform = ZEROS_TRANSLATE_3D;
135
194
  styles.zIndex = HIDDEN_ZINDEX;
136
195
  }
@@ -241,11 +300,12 @@ class Tracker {
241
300
  /**
242
301
  * tracking by propName
243
302
  */
244
- track(items, components, direction) {
303
+ track(items, components, snapedComponent, direction) {
245
304
  if (!items) {
246
305
  return;
247
306
  }
248
307
  const idPropName = this._trackingPropertyName, untrackedItems = [...components], isDown = direction === 0 || direction === 1;
308
+ let isRegularSnapped = false;
249
309
  for (let i = isDown ? 0 : items.length - 1, l = isDown ? items.length : 0; isDown ? i < l : i >= l; isDown ? i++ : i--) {
250
310
  const item = items[i], itemTrackingProperty = item[idPropName];
251
311
  if (this._trackMap) {
@@ -257,6 +317,13 @@ class Tracker {
257
317
  return v.instance.id === compId;
258
318
  });
259
319
  if (indexByUntrackedItems > -1) {
320
+ if (snapedComponent) {
321
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
322
+ isRegularSnapped = true;
323
+ snapedComponent.instance.item = item;
324
+ snapedComponent.instance.show();
325
+ }
326
+ }
260
327
  comp.instance.item = item;
261
328
  comp.instance.show();
262
329
  untrackedItems.splice(indexByUntrackedItems, 1);
@@ -269,6 +336,13 @@ class Tracker {
269
336
  if (untrackedItems.length > 0) {
270
337
  const comp = untrackedItems.shift(), item = items[i];
271
338
  if (comp) {
339
+ if (snapedComponent) {
340
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
341
+ isRegularSnapped = true;
342
+ snapedComponent.instance.item = item;
343
+ snapedComponent.instance.show();
344
+ }
345
+ }
272
346
  comp.instance.item = item;
273
347
  comp.instance.show();
274
348
  if (this._trackMap) {
@@ -283,6 +357,11 @@ class Tracker {
283
357
  comp.instance.hide();
284
358
  }
285
359
  }
360
+ if (!isRegularSnapped) {
361
+ if (snapedComponent) {
362
+ snapedComponent.instance.hide();
363
+ }
364
+ }
286
365
  }
287
366
  untrackComponentByIdProperty(component) {
288
367
  if (!component) {
@@ -599,6 +678,20 @@ class TrackBox extends CacheMap {
599
678
  }
600
679
  this._displayComponents = v;
601
680
  }
681
+ _snapedDisplayComponent;
682
+ set snapedDisplayComponent(v) {
683
+ if (this._snapedDisplayComponent === v) {
684
+ return;
685
+ }
686
+ this._snapedDisplayComponent = v;
687
+ }
688
+ _isSnappingMethodAdvanced = false;
689
+ set isSnappingMethodAdvanced(v) {
690
+ if (this._isSnappingMethodAdvanced === v) {
691
+ return;
692
+ }
693
+ this._isSnappingMethodAdvanced = v;
694
+ }
602
695
  /**
603
696
  * Set the trackBy property
604
697
  */
@@ -1074,7 +1167,7 @@ class TrackBox extends CacheMap {
1074
1167
  generateDisplayCollection(items, stickyMap, metrics) {
1075
1168
  const { normalizedItemWidth, normalizedItemHeight, dynamicSize, itemsFromStartToScrollEnd, isVertical, renderItems: renderItemsLength, scrollSize, sizeProperty, snap, snippedPos, startPosition, totalLength, startIndex, typicalItemSize, } = metrics, displayItems = [];
1076
1169
  if (items.length) {
1077
- const actualSnippedPosition = snippedPos;
1170
+ const actualSnippedPosition = snippedPos, isSnappingMethodAdvanced = this.isSnappingMethodAdvanced;
1078
1171
  let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, stickyItemSize = 0;
1079
1172
  if (snap) {
1080
1173
  for (let i = Math.min(itemsFromStartToScrollEnd > 0 ? itemsFromStartToScrollEnd : 0, totalLength - 1); i >= 0; i--) {
@@ -1085,6 +1178,7 @@ class TrackBox extends CacheMap {
1085
1178
  y: isVertical ? actualSnippedPosition : 0,
1086
1179
  width: normalizedItemWidth,
1087
1180
  height: normalizedItemHeight,
1181
+ delta: 0,
1088
1182
  }, config = {
1089
1183
  isVertical,
1090
1184
  sticky,
@@ -1092,6 +1186,7 @@ class TrackBox extends CacheMap {
1092
1186
  snapped: true,
1093
1187
  snappedOut: false,
1094
1188
  dynamic: dynamicSize,
1189
+ isSnappingMethodAdvanced,
1095
1190
  };
1096
1191
  const itemData = items[i];
1097
1192
  stickyItem = { id, measures, data: itemData, config };
@@ -1114,6 +1209,7 @@ class TrackBox extends CacheMap {
1114
1209
  y: isVertical ? pos : 0,
1115
1210
  width: normalizedItemWidth,
1116
1211
  height: normalizedItemHeight,
1212
+ delta: 0,
1117
1213
  }, config = {
1118
1214
  isVertical,
1119
1215
  sticky: stickyMap[id],
@@ -1121,6 +1217,7 @@ class TrackBox extends CacheMap {
1121
1217
  snapped: false,
1122
1218
  snappedOut: false,
1123
1219
  dynamic: dynamicSize,
1220
+ isSnappingMethodAdvanced,
1124
1221
  };
1125
1222
  const itemData = items[i];
1126
1223
  const item = { id, measures, data: itemData, config };
@@ -1129,6 +1226,7 @@ class TrackBox extends CacheMap {
1129
1226
  item.measures.y = isVertical ? snapped ? actualSnippedPosition : pos : 0;
1130
1227
  nextSticky = item;
1131
1228
  nextSticky.config.snapped = snapped;
1229
+ nextSticky.measures.delta = isVertical ? item.measures.y - scrollSize : item.measures.x - scrollSize;
1132
1230
  }
1133
1231
  displayItems.push(item);
1134
1232
  }
@@ -1143,9 +1241,11 @@ class TrackBox extends CacheMap {
1143
1241
  stickyItem.config.snapped = nextSticky.config.snapped = false;
1144
1242
  stickyItem.config.snappedOut = true;
1145
1243
  stickyItem.config.sticky = 1;
1244
+ stickyItem.measures.delta = isVertical ? stickyItem.measures.y - scrollSize : stickyItem.measures.x - scrollSize;
1146
1245
  }
1147
1246
  else {
1148
1247
  nextSticky.config.snapped = true;
1248
+ nextSticky.measures.delta = isVertical ? nextSticky.measures.y - scrollSize : nextSticky.measures.x - scrollSize;
1149
1249
  }
1150
1250
  }
1151
1251
  }
@@ -1158,7 +1258,7 @@ class TrackBox extends CacheMap {
1158
1258
  if (!this._items || !this._displayComponents) {
1159
1259
  return;
1160
1260
  }
1161
- this._tracker.track(this._items, this._displayComponents, this.scrollDirection);
1261
+ this._tracker.track(this._items, this._displayComponents, this._snapedDisplayComponent, this.scrollDirection);
1162
1262
  }
1163
1263
  setDisplayObjectIndexMapById(v) {
1164
1264
  this._tracker.displayObjectIndexMapById = v;
@@ -1235,6 +1335,14 @@ class ScrollEvent {
1235
1335
  }
1236
1336
  }
1237
1337
 
1338
+ const ADVANCED_PATTERNS = [SnappingMethods.ADVANCED, 'advanced'], DEFAULT_PATTERN = [SnappingMethods.NORMAL, 'normal'];
1339
+ const isSnappingMethodAdvenced = (method) => {
1340
+ return ADVANCED_PATTERNS.includes(method);
1341
+ };
1342
+ const isSnappingMethodDefault = (method) => {
1343
+ return DEFAULT_PATTERN.includes(method);
1344
+ };
1345
+
1238
1346
  /**
1239
1347
  * Virtual list component.
1240
1348
  * Maximum performance for extremely large lists.
@@ -1251,6 +1359,8 @@ class NgVirtualListComponent {
1251
1359
  */
1252
1360
  get id() { return this._id; }
1253
1361
  _listContainerRef;
1362
+ _snapContainerRef;
1363
+ _snappedContainer = viewChild('snapped');
1254
1364
  _container = viewChild('container');
1255
1365
  _list = viewChild('list');
1256
1366
  /**
@@ -1320,11 +1430,51 @@ class NgVirtualListComponent {
1320
1430
  * Number of elements outside the scope of visibility. Default value is 2.
1321
1431
  */
1322
1432
  itemsOffset = input(DEFAULT_ITEMS_OFFSET);
1433
+ /**
1434
+ * Snapping method.
1435
+ * 'default' - Normal group rendering.
1436
+ * 'advanced' - The group is rendered on a transparent background. List items below the group are not rendered.
1437
+ */
1438
+ snappingMethod = input(DEFAULT_SNAPPING_METHOD);
1439
+ _isSnappingMethodAdvanced = this.getIsSnappingMethodAdvanced();
1323
1440
  _isVertical = this.getIsVertical();
1324
1441
  _displayComponents = [];
1442
+ _snapedDisplayComponent;
1325
1443
  _bounds = signal(null);
1326
1444
  _scrollSize = signal(0);
1327
1445
  _resizeObserver = null;
1446
+ _resizeSnappedComponentHandler = () => {
1447
+ const list = this._list(), container = this._container(), snappedComponent = this._snapedDisplayComponent?.instance;
1448
+ if (list && container && snappedComponent) {
1449
+ const isVertical = this._isVertical;
1450
+ snappedComponent.regularLength = `${isVertical ? list.nativeElement.offsetWidth : list.nativeElement.offsetHeight}${PX}`;
1451
+ const { width: sWidth, height: sHeight } = snappedComponent.getBounds() ?? { width: 0, height: 0 }, containerElement = container.nativeElement, listElement = list?.nativeElement, { width: lWidth, height: lHeight } = listElement?.getBoundingClientRect() ?? { width: 0, height: 0 }, { width, height } = this._bounds() ?? { width: 0, height: 0 };
1452
+ let left, right, top, bottom, scrollBarSize;
1453
+ if (isVertical) {
1454
+ const snappedY = snappedComponent.item?.measures.y ?? 0, scrollSize = container.nativeElement.scrollTop, delta = snappedY - scrollSize;
1455
+ delta;
1456
+ scrollBarSize = width - lWidth;
1457
+ left = 0;
1458
+ right = width - scrollBarSize;
1459
+ top = sHeight;
1460
+ bottom = height;
1461
+ containerElement.style.clipPath = `path("M 0 ${top + delta} L 0 ${height} L ${width} ${height} L ${width} 0 L ${right} 0 L ${right} ${top + delta} Z")`;
1462
+ }
1463
+ else {
1464
+ const snappedX = snappedComponent.item?.measures.x ?? 0, scrollSize = container.nativeElement.scrollLeft, delta = snappedX - scrollSize;
1465
+ scrollBarSize = height - lHeight;
1466
+ left = sWidth;
1467
+ right = width;
1468
+ top = 0;
1469
+ bottom = height - scrollBarSize;
1470
+ containerElement.style.clipPath = `path("M ${left + delta} 0 L ${left + delta} ${bottom} L 0 ${bottom} L 0 ${height} L ${width} ${height} L ${width} 0 Z")`;
1471
+ }
1472
+ }
1473
+ };
1474
+ _resizeSnappedObserver = null;
1475
+ _componentsResizeObserver = new ResizeObserver(() => {
1476
+ this._trackBox.changes();
1477
+ });
1328
1478
  _onResizeHandler = () => {
1329
1479
  const bounds = this._container()?.nativeElement?.getBoundingClientRect();
1330
1480
  if (bounds) {
@@ -1333,6 +1483,9 @@ class NgVirtualListComponent {
1333
1483
  else {
1334
1484
  this._bounds.set({ width: DEFAULT_LIST_SIZE, height: DEFAULT_LIST_SIZE });
1335
1485
  }
1486
+ if (this._isSnappingMethodAdvanced) {
1487
+ this.updateRegularRenderer();
1488
+ }
1336
1489
  };
1337
1490
  _onScrollHandler = (e) => {
1338
1491
  this.clearScrollToRepeatExecutionTimeout();
@@ -1368,12 +1521,15 @@ class NgVirtualListComponent {
1368
1521
  $trackBy.pipe(takeUntilDestroyed(), tap(v => {
1369
1522
  this._trackBox.trackingPropertyName = v;
1370
1523
  })).subscribe();
1371
- 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)), $itemsOffset = toObservable(this.itemsOffset).pipe(map(v => v < 0 ? DEFAULT_ITEMS_OFFSET : 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), $cacheVersion = toObservable(this._cacheVersion);
1524
+ 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)), $itemsOffset = toObservable(this.itemsOffset).pipe(map(v => v < 0 ? DEFAULT_ITEMS_OFFSET : 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))), $cacheVersion = toObservable(this._cacheVersion);
1372
1525
  $isVertical.pipe(takeUntilDestroyed(), tap(v => {
1373
1526
  this._isVertical = v;
1374
1527
  const el = this._elementRef.nativeElement;
1375
1528
  toggleClassName(el, v ? CLASS_LIST_VERTICAL : CLASS_LIST_HORIZONTAL, true);
1376
1529
  })).subscribe();
1530
+ $snappingMethod.pipe(takeUntilDestroyed(), tap(v => {
1531
+ this._isSnappingMethodAdvanced = this._trackBox.isSnappingMethodAdvanced = v;
1532
+ })).subscribe();
1377
1533
  $dynamicSize.pipe(takeUntilDestroyed(), tap(dynamicSize => {
1378
1534
  this.listenCacheChangesIfNeed(dynamicSize);
1379
1535
  })).subscribe();
@@ -1388,6 +1544,9 @@ class NgVirtualListComponent {
1388
1544
  this.resetBoundsSize(isVertical, totalSize);
1389
1545
  this.createDisplayComponentsIfNeed(displayItems);
1390
1546
  this.tracking();
1547
+ if (this._isSnappingMethodAdvanced) {
1548
+ this.updateRegularRenderer();
1549
+ }
1391
1550
  const container = this._container();
1392
1551
  if (container) {
1393
1552
  const delta = this._trackBox.delta;
@@ -1423,18 +1582,29 @@ class NgVirtualListComponent {
1423
1582
  }
1424
1583
  }
1425
1584
  }
1585
+ getIsSnappingMethodAdvanced(m) {
1586
+ const method = m || this.snappingMethod();
1587
+ return isSnappingMethodAdvenced(method);
1588
+ }
1426
1589
  getIsVertical(d) {
1427
1590
  const dir = d || this.direction();
1428
1591
  return isDirection(dir, Directions.VERTICAL);
1429
1592
  }
1430
- _componentsResizeObserver = new ResizeObserver(() => {
1431
- this._trackBox.changes();
1432
- });
1433
1593
  createDisplayComponentsIfNeed(displayItems) {
1434
1594
  if (!displayItems || !this._listContainerRef) {
1435
1595
  this._trackBox.setDisplayObjectIndexMapById({});
1436
1596
  return;
1437
1597
  }
1598
+ if (this._isSnappingMethodAdvanced && this.snap()) {
1599
+ if (!this._snapedDisplayComponent && this._snapContainerRef) {
1600
+ const comp = this._snapContainerRef.createComponent(NgVirtualListItemComponent);
1601
+ comp.instance.regular = true;
1602
+ this._snapedDisplayComponent = comp;
1603
+ this._trackBox.snapedDisplayComponent = this._snapedDisplayComponent;
1604
+ this._resizeSnappedObserver = new ResizeObserver(this._resizeSnappedComponentHandler);
1605
+ this._resizeSnappedObserver.observe(comp.instance.element);
1606
+ }
1607
+ }
1438
1608
  this._trackBox.items = displayItems;
1439
1609
  const _listContainerRef = this._listContainerRef;
1440
1610
  const maxLength = displayItems.length, components = this._displayComponents;
@@ -1447,6 +1617,9 @@ class NgVirtualListComponent {
1447
1617
  }
1448
1618
  this.resetRenderers();
1449
1619
  }
1620
+ updateRegularRenderer() {
1621
+ this._resizeSnappedComponentHandler();
1622
+ }
1450
1623
  resetRenderers(itemRenderer) {
1451
1624
  const doMap = {}, components = this._displayComponents;
1452
1625
  for (let i = 0, l = components.length; i < l; i++) {
@@ -1457,6 +1630,10 @@ class NgVirtualListComponent {
1457
1630
  doMap[id] = i;
1458
1631
  }
1459
1632
  }
1633
+ if (this._isSnappingMethodAdvanced && this.snap() && this._snapedDisplayComponent && this._snapContainerRef) {
1634
+ const comp = this._snapedDisplayComponent;
1635
+ comp.instance.renderer = itemRenderer || this.itemRenderer();
1636
+ }
1460
1637
  this._trackBox.setDisplayObjectIndexMapById(doMap);
1461
1638
  }
1462
1639
  /**
@@ -1598,10 +1775,16 @@ class NgVirtualListComponent {
1598
1775
  if (this._componentsResizeObserver) {
1599
1776
  this._componentsResizeObserver.disconnect();
1600
1777
  }
1778
+ if (this._resizeSnappedObserver) {
1779
+ this._resizeSnappedObserver.disconnect();
1780
+ }
1601
1781
  if (this._resizeObserver) {
1602
1782
  this._resizeObserver.disconnect();
1603
1783
  }
1604
1784
  }
1785
+ if (this._snapedDisplayComponent) {
1786
+ this._snapedDisplayComponent.destroy();
1787
+ }
1605
1788
  if (this._displayComponents) {
1606
1789
  while (this._displayComponents.length > 0) {
1607
1790
  const comp = this._displayComponents.pop();
@@ -1610,14 +1793,17 @@ class NgVirtualListComponent {
1610
1793
  }
1611
1794
  }
1612
1795
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1613
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.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 }, 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 }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd" }, viewQueries: [{ 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 }], ngImport: i0, template: "<div #container part=\"scroller\" class=\"ngvl__container\">\r\n <ul #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.vertical){height:320px}.ngvl__container{overflow:auto;width:100%;height:100%}.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 });
1796
+ 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 }, 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 }, snappingMethod: { classPropertyName: "snappingMethod", publicName: "snappingMethod", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd" }, 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 <ul #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{position:relative;display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.vertical){height:320px}.ngvl__scroller{overflow:auto;width:100%;height:100%}.ngvl__list-snapper{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 });
1614
1797
  }
1615
1798
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListComponent, decorators: [{
1616
1799
  type: Component,
1617
- args: [{ selector: 'ng-virtual-list', imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, template: "<div #container part=\"scroller\" class=\"ngvl__container\">\r\n <ul #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.vertical){height:320px}.ngvl__container{overflow:auto;width:100%;height:100%}.ngvl__list{position:relative;list-style:none;padding:0;margin:0;width:100%;height:100%}\n"] }]
1800
+ args: [{ selector: 'ng-virtual-list', imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, 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 <ul #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{position:relative;display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.vertical){height:320px}.ngvl__scroller{overflow:auto;width:100%;height:100%}.ngvl__list-snapper{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"] }]
1618
1801
  }], ctorParameters: () => [], propDecorators: { _listContainerRef: [{
1619
1802
  type: ViewChild,
1620
1803
  args: ['renderersContainer', { read: ViewContainerRef }]
1804
+ }], _snapContainerRef: [{
1805
+ type: ViewChild,
1806
+ args: ['snapRendererContainer', { read: ViewContainerRef }]
1621
1807
  }] } });
1622
1808
 
1623
1809
  /*
@@ -1628,5 +1814,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
1628
1814
  * Generated bundle index. Do not edit.
1629
1815
  */
1630
1816
 
1631
- export { NgVirtualListComponent };
1817
+ export { Directions, NgVirtualListComponent, SnappingMethods };
1632
1818
  //# sourceMappingURL=ng-virtual-list.mjs.map