ng-virtual-list 17.4.0 → 17.4.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 (64) hide show
  1. package/README.md +34 -1
  2. package/esm2020/lib/components/ng-virtual-list-item.component.mjs +131 -0
  3. package/esm2020/lib/const/index.mjs +44 -0
  4. package/esm2020/lib/enums/direction.mjs +2 -0
  5. package/esm2020/lib/enums/directions.mjs +18 -0
  6. package/esm2020/lib/enums/index.mjs +4 -0
  7. package/esm2020/lib/enums/snapping-method.mjs +2 -0
  8. package/esm2020/lib/enums/snapping-methods.mjs +18 -0
  9. package/esm2020/lib/models/base-virtual-list-item-component.mjs +9 -0
  10. package/esm2020/lib/models/collection.model.mjs +3 -0
  11. package/esm2020/lib/models/component.model.mjs +2 -0
  12. package/esm2020/lib/models/index.mjs +2 -0
  13. package/esm2020/lib/models/item.model.mjs +2 -0
  14. package/esm2020/lib/models/render-collection.model.mjs +3 -0
  15. package/esm2020/lib/models/render-item-config.model.mjs +2 -0
  16. package/esm2020/lib/models/render-item.model.mjs +3 -0
  17. package/esm2020/lib/models/scroll-direction.model.mjs +2 -0
  18. package/esm2020/lib/models/scroll-event.model.mjs +2 -0
  19. package/esm2020/lib/models/sticky-map.model.mjs +2 -0
  20. package/esm2020/lib/ng-virtual-list.component.mjs +675 -0
  21. package/esm2020/lib/ng-virtual-list.module.mjs +20 -0
  22. package/esm2020/lib/types/id.mjs +2 -0
  23. package/esm2020/lib/types/index.mjs +2 -0
  24. package/esm2020/lib/types/rect.mjs +2 -0
  25. package/esm2020/lib/types/size.mjs +2 -0
  26. package/esm2020/lib/utils/browser.mjs +3 -0
  27. package/esm2020/lib/utils/buffer-interpolation.mjs +27 -0
  28. package/esm2020/lib/utils/cacheMap.mjs +167 -0
  29. package/esm2020/lib/utils/debounce.mjs +31 -0
  30. package/esm2020/lib/utils/disposableComponent.mjs +29 -0
  31. package/esm2020/lib/utils/eventEmitter.mjs +106 -0
  32. package/esm2020/lib/utils/index.mjs +5 -0
  33. package/esm2020/lib/utils/isDirection.mjs +15 -0
  34. package/esm2020/lib/utils/scrollEvent.mjs +42 -0
  35. package/esm2020/lib/utils/snapping-method.mjs +9 -0
  36. package/esm2020/lib/utils/toggleClassName.mjs +15 -0
  37. package/esm2020/lib/utils/trackBox.mjs +756 -0
  38. package/esm2020/lib/utils/tracker.mjs +134 -0
  39. package/esm2020/ng-virtual-list.mjs +5 -0
  40. package/esm2020/public-api.mjs +10 -0
  41. package/esm2022/lib/components/ng-virtual-list-item.component.mjs +2 -2
  42. package/esm2022/lib/models/base-virtual-list-item-component.mjs +1 -1
  43. package/esm2022/lib/models/index.mjs +2 -3
  44. package/esm2022/lib/ng-virtual-list.component.mjs +4 -6
  45. package/esm2022/lib/utils/index.mjs +2 -6
  46. package/esm2022/lib/utils/trackBox.mjs +12 -4
  47. package/esm2022/lib/utils/tracker.mjs +1 -1
  48. package/esm2022/public-api.mjs +2 -1
  49. package/fesm2015/ng-virtual-list.mjs +2224 -0
  50. package/fesm2015/ng-virtual-list.mjs.map +1 -0
  51. package/fesm2020/ng-virtual-list.mjs +2229 -0
  52. package/fesm2020/ng-virtual-list.mjs.map +1 -0
  53. package/fesm2022/ng-virtual-list.mjs +195 -190
  54. package/fesm2022/ng-virtual-list.mjs.map +1 -1
  55. package/lib/components/ng-virtual-list-item.component.d.ts +9 -9
  56. package/lib/models/base-virtual-list-item-component.d.ts +0 -1
  57. package/lib/models/index.d.ts +1 -4
  58. package/lib/ng-virtual-list.component.d.ts +47 -50
  59. package/lib/utils/disposableComponent.d.ts +15 -0
  60. package/lib/utils/index.d.ts +3 -6
  61. package/lib/utils/trackBox.d.ts +4 -1
  62. package/lib/utils/tracker.d.ts +11 -4
  63. package/package.json +1 -1
  64. package/public-api.d.ts +1 -0
@@ -219,20 +219,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
219
219
  }, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (data(); as item) {\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': item.config.snapped,\r\n 'snapped-out': item.config.snappedOut}\">\r\n @if (itemRenderer(); as renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\"\r\n [ngTemplateOutletContext]=\"{data: item.data || {}, config: item.config}\" />\r\n }\r\n </li>\r\n}", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden}.ngvl-item__container{margin:0;padding:0;overflow:hidden;background-color:#fff;width:inherit;height:inherit}\n"] }]
220
220
  }], ctorParameters: () => [] });
221
221
 
222
- const HORIZONTAL_ALIASES = [Directions.HORIZONTAL, 'horizontal'], VERTICAL_ALIASES = [Directions.VERTICAL, 'vertical'];
223
- /**
224
- * Determines the axis membership of a virtual list
225
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/17.x/projects/ng-virtual-list/src/lib/utils/isDirection.ts
226
- * @author Evgenii Grebennikov
227
- * @email djonnyx@gmail.com
228
- */
229
- const isDirection = (src, expected) => {
230
- if (HORIZONTAL_ALIASES.includes(expected)) {
231
- return HORIZONTAL_ALIASES.includes(src);
232
- }
233
- return VERTICAL_ALIASES.includes(src);
234
- };
235
-
236
222
  /**
237
223
  * Simple debounce function.
238
224
  * @link https://github.com/DjonnyX/ng-virtual-list/blob/17.x/projects/ng-virtual-list/src/lib/utils/debounce.ts
@@ -280,137 +266,44 @@ const toggleClassName = (el, className, removeClassName) => {
280
266
  };
281
267
 
282
268
  /**
283
- * Tracks display items by property
284
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/17.x/projects/ng-virtual-list/src/lib/utils/tracker.ts
269
+ * Scroll event.
270
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/17.x/projects/ng-virtual-list/src/lib/utils/scrollEvent.ts
285
271
  * @author Evgenii Grebennikov
286
272
  * @email djonnyx@gmail.com
287
273
  */
288
- class Tracker {
289
- /**
290
- * display objects dictionary of indexes by id
291
- */
292
- _displayObjectIndexMapById = {};
293
- set displayObjectIndexMapById(v) {
294
- if (this._displayObjectIndexMapById === v) {
295
- return;
296
- }
297
- this._displayObjectIndexMapById = v;
298
- }
299
- get displayObjectIndexMapById() {
300
- return this._displayObjectIndexMapById;
301
- }
302
- /**
303
- * Dictionary displayItems propertyNameId by items propertyNameId
304
- */
305
- _trackMap = {};
306
- get trackMap() {
307
- return this._trackMap;
308
- }
309
- _trackingPropertyName;
310
- set trackingPropertyName(v) {
311
- this._trackingPropertyName = v;
312
- }
313
- constructor(trackingPropertyName) {
314
- this._trackingPropertyName = trackingPropertyName;
315
- }
316
- /**
317
- * tracking by propName
318
- */
319
- track(items, components, snapedComponent, direction) {
320
- if (!items) {
321
- return;
322
- }
323
- const idPropName = this._trackingPropertyName, untrackedItems = [...components], isDown = direction === 0 || direction === 1;
324
- let isRegularSnapped = false;
325
- for (let i = isDown ? 0 : items.length - 1, l = isDown ? items.length : 0; isDown ? i < l : i >= l; isDown ? i++ : i--) {
326
- const item = items[i], itemTrackingProperty = item[idPropName];
327
- if (this._trackMap) {
328
- if (this._trackMap.hasOwnProperty(itemTrackingProperty)) {
329
- const diId = this._trackMap[itemTrackingProperty], compIndex = this._displayObjectIndexMapById[diId], comp = components[compIndex];
330
- const compId = comp?.instance?.id;
331
- if (comp !== undefined && compId === diId) {
332
- const indexByUntrackedItems = untrackedItems.findIndex(v => {
333
- return v.instance.id === compId;
334
- });
335
- if (indexByUntrackedItems > -1) {
336
- if (snapedComponent) {
337
- if (item['config']['snapped'] || item['config']['snappedOut']) {
338
- isRegularSnapped = true;
339
- snapedComponent.instance.item = item;
340
- snapedComponent.instance.show();
341
- }
342
- }
343
- comp.instance.item = item;
344
- if (snapedComponent) {
345
- if (item['config']['snapped'] || item['config']['snappedOut']) {
346
- comp.instance.hide();
347
- }
348
- else {
349
- comp.instance.show();
350
- }
351
- }
352
- else {
353
- comp.instance.show();
354
- }
355
- untrackedItems.splice(indexByUntrackedItems, 1);
356
- continue;
357
- }
358
- }
359
- delete this._trackMap[itemTrackingProperty];
360
- }
361
- }
362
- if (untrackedItems.length > 0) {
363
- const comp = untrackedItems.shift(), item = items[i];
364
- if (comp) {
365
- if (snapedComponent) {
366
- if (item['config']['snapped'] || item['config']['snappedOut']) {
367
- isRegularSnapped = true;
368
- snapedComponent.instance.item = item;
369
- snapedComponent.instance.show();
370
- }
371
- }
372
- comp.instance.item = item;
373
- if (snapedComponent) {
374
- if (item['config']['snapped'] || item['config']['snappedOut']) {
375
- comp.instance.hide();
376
- }
377
- else {
378
- comp.instance.show();
379
- }
380
- }
381
- else {
382
- comp.instance.show();
383
- }
384
- if (this._trackMap) {
385
- this._trackMap[itemTrackingProperty] = comp.instance.id;
386
- }
387
- }
388
- }
389
- }
390
- if (untrackedItems.length) {
391
- for (let i = 0, l = untrackedItems.length; i < l; i++) {
392
- const comp = untrackedItems[i];
393
- comp.instance.hide();
394
- }
395
- }
396
- if (!isRegularSnapped) {
397
- if (snapedComponent) {
398
- snapedComponent.instance.item = null;
399
- snapedComponent.instance.hide();
400
- }
401
- }
402
- }
403
- untrackComponentByIdProperty(component) {
404
- if (!component) {
405
- return;
406
- }
407
- const propertyIdName = this._trackingPropertyName;
408
- if (this._trackMap && component[propertyIdName] !== undefined) {
409
- delete this._trackMap[propertyIdName];
410
- }
411
- }
412
- dispose() {
413
- this._trackMap = null;
274
+ class ScrollEvent {
275
+ _direction = 1;
276
+ get direction() { return this._direction; }
277
+ _scrollSize = 0;
278
+ get scrollSize() { return this._scrollSize; }
279
+ _scrollWeight = 0;
280
+ get scrollWeight() { return this._scrollWeight; }
281
+ _isVertical = true;
282
+ get isVertical() { return this._isVertical; }
283
+ _listSize = 0;
284
+ get listSize() { return this._listSize; }
285
+ _size = 0;
286
+ get size() { return this._size; }
287
+ _isStart = true;
288
+ get isStart() { return this._isStart; }
289
+ _isEnd = false;
290
+ get isEnd() { return this._isEnd; }
291
+ _delta = 0;
292
+ get delta() { return this._delta; }
293
+ _scrollDelta = 0;
294
+ get scrollDelta() { return this._scrollDelta; }
295
+ constructor(params) {
296
+ const { direction, isVertical, container, list, delta, scrollDelta } = params;
297
+ this._direction = direction;
298
+ this._isVertical = isVertical;
299
+ this._scrollSize = isVertical ? container.scrollTop : container.scrollLeft;
300
+ this._scrollWeight = isVertical ? container.scrollHeight : container.scrollWidth;
301
+ this._listSize = isVertical ? list.offsetHeight : list.offsetWidth;
302
+ this._size = isVertical ? container.offsetHeight : container.offsetWidth;
303
+ this._isEnd = (this._scrollSize + this._size) === this._scrollWeight;
304
+ this._delta = delta;
305
+ this._scrollDelta = scrollDelta;
306
+ this._isStart = this._scrollSize === 0;
414
307
  }
415
308
  }
416
309
 
@@ -685,6 +578,141 @@ class CacheMap extends EventEmitter {
685
578
  }
686
579
  }
687
580
 
581
+ /**
582
+ * Tracks display items by property
583
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/17.x/projects/ng-virtual-list/src/lib/utils/tracker.ts
584
+ * @author Evgenii Grebennikov
585
+ * @email djonnyx@gmail.com
586
+ */
587
+ class Tracker {
588
+ /**
589
+ * display objects dictionary of indexes by id
590
+ */
591
+ _displayObjectIndexMapById = {};
592
+ set displayObjectIndexMapById(v) {
593
+ if (this._displayObjectIndexMapById === v) {
594
+ return;
595
+ }
596
+ this._displayObjectIndexMapById = v;
597
+ }
598
+ get displayObjectIndexMapById() {
599
+ return this._displayObjectIndexMapById;
600
+ }
601
+ /**
602
+ * Dictionary displayItems propertyNameId by items propertyNameId
603
+ */
604
+ _trackMap = {};
605
+ get trackMap() {
606
+ return this._trackMap;
607
+ }
608
+ _trackingPropertyName;
609
+ set trackingPropertyName(v) {
610
+ this._trackingPropertyName = v;
611
+ }
612
+ constructor(trackingPropertyName) {
613
+ this._trackingPropertyName = trackingPropertyName;
614
+ }
615
+ /**
616
+ * tracking by propName
617
+ */
618
+ track(items, components, snapedComponent, direction) {
619
+ if (!items) {
620
+ return;
621
+ }
622
+ const idPropName = this._trackingPropertyName, untrackedItems = [...components], isDown = direction === 0 || direction === 1;
623
+ let isRegularSnapped = false;
624
+ for (let i = isDown ? 0 : items.length - 1, l = isDown ? items.length : 0; isDown ? i < l : i >= l; isDown ? i++ : i--) {
625
+ const item = items[i], itemTrackingProperty = item[idPropName];
626
+ if (this._trackMap) {
627
+ if (this._trackMap.hasOwnProperty(itemTrackingProperty)) {
628
+ const diId = this._trackMap[itemTrackingProperty], compIndex = this._displayObjectIndexMapById[diId], comp = components[compIndex];
629
+ const compId = comp?.instance?.id;
630
+ if (comp !== undefined && compId === diId) {
631
+ const indexByUntrackedItems = untrackedItems.findIndex(v => {
632
+ return v.instance.id === compId;
633
+ });
634
+ if (indexByUntrackedItems > -1) {
635
+ if (snapedComponent) {
636
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
637
+ isRegularSnapped = true;
638
+ snapedComponent.instance.item = item;
639
+ snapedComponent.instance.show();
640
+ }
641
+ }
642
+ comp.instance.item = item;
643
+ if (snapedComponent) {
644
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
645
+ comp.instance.hide();
646
+ }
647
+ else {
648
+ comp.instance.show();
649
+ }
650
+ }
651
+ else {
652
+ comp.instance.show();
653
+ }
654
+ untrackedItems.splice(indexByUntrackedItems, 1);
655
+ continue;
656
+ }
657
+ }
658
+ delete this._trackMap[itemTrackingProperty];
659
+ }
660
+ }
661
+ if (untrackedItems.length > 0) {
662
+ const comp = untrackedItems.shift(), item = items[i];
663
+ if (comp) {
664
+ if (snapedComponent) {
665
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
666
+ isRegularSnapped = true;
667
+ snapedComponent.instance.item = item;
668
+ snapedComponent.instance.show();
669
+ }
670
+ }
671
+ comp.instance.item = item;
672
+ if (snapedComponent) {
673
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
674
+ comp.instance.hide();
675
+ }
676
+ else {
677
+ comp.instance.show();
678
+ }
679
+ }
680
+ else {
681
+ comp.instance.show();
682
+ }
683
+ if (this._trackMap) {
684
+ this._trackMap[itemTrackingProperty] = comp.instance.id;
685
+ }
686
+ }
687
+ }
688
+ }
689
+ if (untrackedItems.length) {
690
+ for (let i = 0, l = untrackedItems.length; i < l; i++) {
691
+ const comp = untrackedItems[i];
692
+ comp.instance.hide();
693
+ }
694
+ }
695
+ if (!isRegularSnapped) {
696
+ if (snapedComponent) {
697
+ snapedComponent.instance.item = null;
698
+ snapedComponent.instance.hide();
699
+ }
700
+ }
701
+ }
702
+ untrackComponentByIdProperty(component) {
703
+ if (!component) {
704
+ return;
705
+ }
706
+ const propertyIdName = this._trackingPropertyName;
707
+ if (this._trackMap && component[propertyIdName] !== undefined) {
708
+ delete this._trackMap[propertyIdName];
709
+ }
710
+ }
711
+ dispose() {
712
+ this._trackMap = null;
713
+ }
714
+ }
715
+
688
716
  const DEFAULT_EXTRA = {
689
717
  extremumThreshold: 2,
690
718
  bufferSize: 10,
@@ -761,11 +789,16 @@ class TrackBox extends CacheMap {
761
789
  * Set the trackBy property
762
790
  */
763
791
  set trackingPropertyName(v) {
764
- this._tracker.trackingPropertyName = v;
792
+ this._trackingPropertyName = this._tracker.trackingPropertyName = v;
765
793
  }
794
+ _trackingPropertyName = TRACK_BY_PROPERTY_NAME;
766
795
  constructor(trackingPropertyName) {
767
796
  super();
768
- this._tracker = new Tracker(trackingPropertyName);
797
+ this._trackingPropertyName = trackingPropertyName;
798
+ this.initialize();
799
+ }
800
+ initialize() {
801
+ this._tracker = new Tracker(this._trackingPropertyName);
769
802
  }
770
803
  set(id, bounds) {
771
804
  if (this._map.has(id)) {
@@ -1344,6 +1377,9 @@ class TrackBox extends CacheMap {
1344
1377
  if (i >= totalLength) {
1345
1378
  break;
1346
1379
  }
1380
+ if (!items[i]) {
1381
+ continue;
1382
+ }
1347
1383
  const id = items[i].id, size = dynamicSize ? this.get(id)?.[sizeProperty] || typicalItemSize : typicalItemSize;
1348
1384
  if (id !== stickyItem?.id && id !== endStickyItem?.id) {
1349
1385
  const snapped = snap && (stickyMap[id] === 1 && pos <= scrollSize || stickyMap[id] === 2 && pos >= scrollSize + boundsSize - size), measures = {
@@ -1462,48 +1498,6 @@ class TrackBox extends CacheMap {
1462
1498
  }
1463
1499
  }
1464
1500
 
1465
- /**
1466
- * Scroll event.
1467
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/17.x/projects/ng-virtual-list/src/lib/utils/scrollEvent.ts
1468
- * @author Evgenii Grebennikov
1469
- * @email djonnyx@gmail.com
1470
- */
1471
- class ScrollEvent {
1472
- _direction = 1;
1473
- get direction() { return this._direction; }
1474
- _scrollSize = 0;
1475
- get scrollSize() { return this._scrollSize; }
1476
- _scrollWeight = 0;
1477
- get scrollWeight() { return this._scrollWeight; }
1478
- _isVertical = true;
1479
- get isVertical() { return this._isVertical; }
1480
- _listSize = 0;
1481
- get listSize() { return this._listSize; }
1482
- _size = 0;
1483
- get size() { return this._size; }
1484
- _isStart = true;
1485
- get isStart() { return this._isStart; }
1486
- _isEnd = false;
1487
- get isEnd() { return this._isEnd; }
1488
- _delta = 0;
1489
- get delta() { return this._delta; }
1490
- _scrollDelta = 0;
1491
- get scrollDelta() { return this._scrollDelta; }
1492
- constructor(params) {
1493
- const { direction, isVertical, container, list, delta, scrollDelta } = params;
1494
- this._direction = direction;
1495
- this._isVertical = isVertical;
1496
- this._scrollSize = isVertical ? container.scrollTop : container.scrollLeft;
1497
- this._scrollWeight = isVertical ? container.scrollHeight : container.scrollWidth;
1498
- this._listSize = isVertical ? list.offsetHeight : list.offsetWidth;
1499
- this._size = isVertical ? container.offsetHeight : container.offsetWidth;
1500
- this._isEnd = (this._scrollSize + this._size) === this._scrollWeight;
1501
- this._delta = delta;
1502
- this._scrollDelta = scrollDelta;
1503
- this._isStart = this._scrollSize === 0;
1504
- }
1505
- }
1506
-
1507
1501
  const ADVANCED_PATTERNS = [SnappingMethods.ADVANCED, 'advanced'], DEFAULT_PATTERN = [SnappingMethods.NORMAL, 'normal'];
1508
1502
  const isSnappingMethodAdvenced = (method) => {
1509
1503
  return ADVANCED_PATTERNS.includes(method);
@@ -1515,6 +1509,20 @@ const isSnappingMethodDefault = (method) => {
1515
1509
  const IS_FIREFOX = navigator.userAgent.toLowerCase().includes('firefox');
1516
1510
  const FIREFOX_SCROLLBAR_OVERLAP_SIZE = 12;
1517
1511
 
1512
+ const HORIZONTAL_ALIASES = [Directions.HORIZONTAL, 'horizontal'], VERTICAL_ALIASES = [Directions.VERTICAL, 'vertical'];
1513
+ /**
1514
+ * Determines the axis membership of a virtual list
1515
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/17.x/projects/ng-virtual-list/src/lib/utils/isDirection.ts
1516
+ * @author Evgenii Grebennikov
1517
+ * @email djonnyx@gmail.com
1518
+ */
1519
+ const isDirection = (src, expected) => {
1520
+ if (HORIZONTAL_ALIASES.includes(expected)) {
1521
+ return HORIZONTAL_ALIASES.includes(src);
1522
+ }
1523
+ return VERTICAL_ALIASES.includes(src);
1524
+ };
1525
+
1518
1526
  /**
1519
1527
  * Virtual list component.
1520
1528
  * Maximum performance for extremely large lists.
@@ -1772,9 +1780,6 @@ class NgVirtualListComponent {
1772
1780
  }
1773
1781
  return of(displayItems);
1774
1782
  })).subscribe();
1775
- this.setupRenderer();
1776
- }
1777
- setupRenderer() {
1778
1783
  const $itemRenderer = toObservable(this.itemRenderer);
1779
1784
  $itemRenderer.pipe(takeUntilDestroyed(), distinctUntilChanged(), filter(v => !!v), tap(v => {
1780
1785
  this._itemRenderer.set(v);
@@ -2064,5 +2069,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
2064
2069
  * Generated bundle index. Do not edit.
2065
2070
  */
2066
2071
 
2067
- export { BaseVirtualListItemComponent, Directions, NgVirtualListComponent, NgVirtualListItemComponent, NgVirtualListModule, SnappingMethods };
2072
+ export { Directions, NgVirtualListComponent, NgVirtualListItemComponent, NgVirtualListModule, ScrollEvent, SnappingMethods, debounce, toggleClassName };
2068
2073
  //# sourceMappingURL=ng-virtual-list.mjs.map