ng-virtual-list 16.4.0 → 16.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.
@@ -223,20 +223,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
223
223
  }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"data\">\r\n <li #listItem part=\"item\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut}\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, config: data.config}\" />\r\n </ng-container>\r\n </li>\r\n</ng-container>", 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"] }]
224
224
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; } });
225
225
 
226
- const HORIZONTAL_ALIASES = [Directions.HORIZONTAL, 'horizontal'], VERTICAL_ALIASES = [Directions.VERTICAL, 'vertical'];
227
- /**
228
- * Determines the axis membership of a virtual list
229
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/utils/isDirection.ts
230
- * @author Evgenii Grebennikov
231
- * @email djonnyx@gmail.com
232
- */
233
- const isDirection = (src, expected) => {
234
- if (HORIZONTAL_ALIASES.includes(expected)) {
235
- return HORIZONTAL_ALIASES.includes(src);
236
- }
237
- return VERTICAL_ALIASES.includes(src);
238
- };
239
-
240
226
  /**
241
227
  * Simple debounce function.
242
228
  * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/utils/debounce.ts
@@ -284,137 +270,44 @@ const toggleClassName = (el, className, removeClassName) => {
284
270
  };
285
271
 
286
272
  /**
287
- * Tracks display items by property
288
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/utils/tracker.ts
273
+ * Scroll event.
274
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/utils/scrollEvent.ts
289
275
  * @author Evgenii Grebennikov
290
276
  * @email djonnyx@gmail.com
291
277
  */
292
- class Tracker {
293
- /**
294
- * display objects dictionary of indexes by id
295
- */
296
- _displayObjectIndexMapById = {};
297
- set displayObjectIndexMapById(v) {
298
- if (this._displayObjectIndexMapById === v) {
299
- return;
300
- }
301
- this._displayObjectIndexMapById = v;
302
- }
303
- get displayObjectIndexMapById() {
304
- return this._displayObjectIndexMapById;
305
- }
306
- /**
307
- * Dictionary displayItems propertyNameId by items propertyNameId
308
- */
309
- _trackMap = {};
310
- get trackMap() {
311
- return this._trackMap;
312
- }
313
- _trackingPropertyName;
314
- set trackingPropertyName(v) {
315
- this._trackingPropertyName = v;
316
- }
317
- constructor(trackingPropertyName) {
318
- this._trackingPropertyName = trackingPropertyName;
319
- }
320
- /**
321
- * tracking by propName
322
- */
323
- track(items, components, snapedComponent, direction) {
324
- if (!items) {
325
- return;
326
- }
327
- const idPropName = this._trackingPropertyName, untrackedItems = [...components], isDown = direction === 0 || direction === 1;
328
- let isRegularSnapped = false;
329
- for (let i = isDown ? 0 : items.length - 1, l = isDown ? items.length : 0; isDown ? i < l : i >= l; isDown ? i++ : i--) {
330
- const item = items[i], itemTrackingProperty = item[idPropName];
331
- if (this._trackMap) {
332
- if (this._trackMap.hasOwnProperty(itemTrackingProperty)) {
333
- const diId = this._trackMap[itemTrackingProperty], compIndex = this._displayObjectIndexMapById[diId], comp = components[compIndex];
334
- const compId = comp?.instance?.id;
335
- if (comp !== undefined && compId === diId) {
336
- const indexByUntrackedItems = untrackedItems.findIndex(v => {
337
- return v.instance.id === compId;
338
- });
339
- if (indexByUntrackedItems > -1) {
340
- if (snapedComponent) {
341
- if (item['config']['snapped'] || item['config']['snappedOut']) {
342
- isRegularSnapped = true;
343
- snapedComponent.instance.item = item;
344
- snapedComponent.instance.show();
345
- }
346
- }
347
- comp.instance.item = item;
348
- if (snapedComponent) {
349
- if (item['config']['snapped'] || item['config']['snappedOut']) {
350
- comp.instance.hide();
351
- }
352
- else {
353
- comp.instance.show();
354
- }
355
- }
356
- else {
357
- comp.instance.show();
358
- }
359
- untrackedItems.splice(indexByUntrackedItems, 1);
360
- continue;
361
- }
362
- }
363
- delete this._trackMap[itemTrackingProperty];
364
- }
365
- }
366
- if (untrackedItems.length > 0) {
367
- const comp = untrackedItems.shift(), item = items[i];
368
- if (comp) {
369
- if (snapedComponent) {
370
- if (item['config']['snapped'] || item['config']['snappedOut']) {
371
- isRegularSnapped = true;
372
- snapedComponent.instance.item = item;
373
- snapedComponent.instance.show();
374
- }
375
- }
376
- comp.instance.item = item;
377
- if (snapedComponent) {
378
- if (item['config']['snapped'] || item['config']['snappedOut']) {
379
- comp.instance.hide();
380
- }
381
- else {
382
- comp.instance.show();
383
- }
384
- }
385
- else {
386
- comp.instance.show();
387
- }
388
- if (this._trackMap) {
389
- this._trackMap[itemTrackingProperty] = comp.instance.id;
390
- }
391
- }
392
- }
393
- }
394
- if (untrackedItems.length) {
395
- for (let i = 0, l = untrackedItems.length; i < l; i++) {
396
- const comp = untrackedItems[i];
397
- comp.instance.hide();
398
- }
399
- }
400
- if (!isRegularSnapped) {
401
- if (snapedComponent) {
402
- snapedComponent.instance.item = null;
403
- snapedComponent.instance.hide();
404
- }
405
- }
406
- }
407
- untrackComponentByIdProperty(component) {
408
- if (!component) {
409
- return;
410
- }
411
- const propertyIdName = this._trackingPropertyName;
412
- if (this._trackMap && component[propertyIdName] !== undefined) {
413
- delete this._trackMap[propertyIdName];
414
- }
415
- }
416
- dispose() {
417
- this._trackMap = null;
278
+ class ScrollEvent {
279
+ _direction = 1;
280
+ get direction() { return this._direction; }
281
+ _scrollSize = 0;
282
+ get scrollSize() { return this._scrollSize; }
283
+ _scrollWeight = 0;
284
+ get scrollWeight() { return this._scrollWeight; }
285
+ _isVertical = true;
286
+ get isVertical() { return this._isVertical; }
287
+ _listSize = 0;
288
+ get listSize() { return this._listSize; }
289
+ _size = 0;
290
+ get size() { return this._size; }
291
+ _isStart = true;
292
+ get isStart() { return this._isStart; }
293
+ _isEnd = false;
294
+ get isEnd() { return this._isEnd; }
295
+ _delta = 0;
296
+ get delta() { return this._delta; }
297
+ _scrollDelta = 0;
298
+ get scrollDelta() { return this._scrollDelta; }
299
+ constructor(params) {
300
+ const { direction, isVertical, container, list, delta, scrollDelta } = params;
301
+ this._direction = direction;
302
+ this._isVertical = isVertical;
303
+ this._scrollSize = isVertical ? container.scrollTop : container.scrollLeft;
304
+ this._scrollWeight = isVertical ? container.scrollHeight : container.scrollWidth;
305
+ this._listSize = isVertical ? list.offsetHeight : list.offsetWidth;
306
+ this._size = isVertical ? container.offsetHeight : container.offsetWidth;
307
+ this._isEnd = (this._scrollSize + this._size) === this._scrollWeight;
308
+ this._delta = delta;
309
+ this._scrollDelta = scrollDelta;
310
+ this._isStart = this._scrollSize === 0;
418
311
  }
419
312
  }
420
313
 
@@ -689,6 +582,141 @@ class CacheMap extends EventEmitter {
689
582
  }
690
583
  }
691
584
 
585
+ /**
586
+ * Tracks display items by property
587
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/utils/tracker.ts
588
+ * @author Evgenii Grebennikov
589
+ * @email djonnyx@gmail.com
590
+ */
591
+ class Tracker {
592
+ /**
593
+ * display objects dictionary of indexes by id
594
+ */
595
+ _displayObjectIndexMapById = {};
596
+ set displayObjectIndexMapById(v) {
597
+ if (this._displayObjectIndexMapById === v) {
598
+ return;
599
+ }
600
+ this._displayObjectIndexMapById = v;
601
+ }
602
+ get displayObjectIndexMapById() {
603
+ return this._displayObjectIndexMapById;
604
+ }
605
+ /**
606
+ * Dictionary displayItems propertyNameId by items propertyNameId
607
+ */
608
+ _trackMap = {};
609
+ get trackMap() {
610
+ return this._trackMap;
611
+ }
612
+ _trackingPropertyName;
613
+ set trackingPropertyName(v) {
614
+ this._trackingPropertyName = v;
615
+ }
616
+ constructor(trackingPropertyName) {
617
+ this._trackingPropertyName = trackingPropertyName;
618
+ }
619
+ /**
620
+ * tracking by propName
621
+ */
622
+ track(items, components, snapedComponent, direction) {
623
+ if (!items) {
624
+ return;
625
+ }
626
+ const idPropName = this._trackingPropertyName, untrackedItems = [...components], isDown = direction === 0 || direction === 1;
627
+ let isRegularSnapped = false;
628
+ for (let i = isDown ? 0 : items.length - 1, l = isDown ? items.length : 0; isDown ? i < l : i >= l; isDown ? i++ : i--) {
629
+ const item = items[i], itemTrackingProperty = item[idPropName];
630
+ if (this._trackMap) {
631
+ if (this._trackMap.hasOwnProperty(itemTrackingProperty)) {
632
+ const diId = this._trackMap[itemTrackingProperty], compIndex = this._displayObjectIndexMapById[diId], comp = components[compIndex];
633
+ const compId = comp?.instance?.id;
634
+ if (comp !== undefined && compId === diId) {
635
+ const indexByUntrackedItems = untrackedItems.findIndex(v => {
636
+ return v.instance.id === compId;
637
+ });
638
+ if (indexByUntrackedItems > -1) {
639
+ if (snapedComponent) {
640
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
641
+ isRegularSnapped = true;
642
+ snapedComponent.instance.item = item;
643
+ snapedComponent.instance.show();
644
+ }
645
+ }
646
+ comp.instance.item = item;
647
+ if (snapedComponent) {
648
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
649
+ comp.instance.hide();
650
+ }
651
+ else {
652
+ comp.instance.show();
653
+ }
654
+ }
655
+ else {
656
+ comp.instance.show();
657
+ }
658
+ untrackedItems.splice(indexByUntrackedItems, 1);
659
+ continue;
660
+ }
661
+ }
662
+ delete this._trackMap[itemTrackingProperty];
663
+ }
664
+ }
665
+ if (untrackedItems.length > 0) {
666
+ const comp = untrackedItems.shift(), item = items[i];
667
+ if (comp) {
668
+ if (snapedComponent) {
669
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
670
+ isRegularSnapped = true;
671
+ snapedComponent.instance.item = item;
672
+ snapedComponent.instance.show();
673
+ }
674
+ }
675
+ comp.instance.item = item;
676
+ if (snapedComponent) {
677
+ if (item['config']['snapped'] || item['config']['snappedOut']) {
678
+ comp.instance.hide();
679
+ }
680
+ else {
681
+ comp.instance.show();
682
+ }
683
+ }
684
+ else {
685
+ comp.instance.show();
686
+ }
687
+ if (this._trackMap) {
688
+ this._trackMap[itemTrackingProperty] = comp.instance.id;
689
+ }
690
+ }
691
+ }
692
+ }
693
+ if (untrackedItems.length) {
694
+ for (let i = 0, l = untrackedItems.length; i < l; i++) {
695
+ const comp = untrackedItems[i];
696
+ comp.instance.hide();
697
+ }
698
+ }
699
+ if (!isRegularSnapped) {
700
+ if (snapedComponent) {
701
+ snapedComponent.instance.item = null;
702
+ snapedComponent.instance.hide();
703
+ }
704
+ }
705
+ }
706
+ untrackComponentByIdProperty(component) {
707
+ if (!component) {
708
+ return;
709
+ }
710
+ const propertyIdName = this._trackingPropertyName;
711
+ if (this._trackMap && component[propertyIdName] !== undefined) {
712
+ delete this._trackMap[propertyIdName];
713
+ }
714
+ }
715
+ dispose() {
716
+ this._trackMap = null;
717
+ }
718
+ }
719
+
692
720
  const DEFAULT_EXTRA = {
693
721
  extremumThreshold: 2,
694
722
  bufferSize: 10,
@@ -765,11 +793,16 @@ class TrackBox extends CacheMap {
765
793
  * Set the trackBy property
766
794
  */
767
795
  set trackingPropertyName(v) {
768
- this._tracker.trackingPropertyName = v;
796
+ this._trackingPropertyName = this._tracker.trackingPropertyName = v;
769
797
  }
798
+ _trackingPropertyName = TRACK_BY_PROPERTY_NAME;
770
799
  constructor(trackingPropertyName) {
771
800
  super();
772
- this._tracker = new Tracker(trackingPropertyName);
801
+ this._trackingPropertyName = trackingPropertyName;
802
+ this.initialize();
803
+ }
804
+ initialize() {
805
+ this._tracker = new Tracker(this._trackingPropertyName);
773
806
  }
774
807
  set(id, bounds) {
775
808
  if (this._map.has(id)) {
@@ -1311,6 +1344,9 @@ class TrackBox extends CacheMap {
1311
1344
  if (snap) {
1312
1345
  const startIndex = itemsFromStartToScrollEnd + itemsOnDisplayLength - 1;
1313
1346
  for (let i = Math.min(startIndex, totalLength > 0 ? totalLength - 1 : 0), l = totalLength; i < l; i++) {
1347
+ if (!items[i]) {
1348
+ continue;
1349
+ }
1314
1350
  const id = items[i].id, sticky = stickyMap[id], size = dynamicSize
1315
1351
  ? this.get(id)?.[sizeProperty] || typicalItemSize
1316
1352
  : typicalItemSize;
@@ -1345,6 +1381,9 @@ class TrackBox extends CacheMap {
1345
1381
  if (i >= totalLength) {
1346
1382
  break;
1347
1383
  }
1384
+ if (!items[i]) {
1385
+ continue;
1386
+ }
1348
1387
  const id = items[i].id, size = dynamicSize ? this.get(id)?.[sizeProperty] || typicalItemSize : typicalItemSize;
1349
1388
  if (id !== stickyItem?.id && id !== endStickyItem?.id) {
1350
1389
  const snapped = snap && (stickyMap[id] === 1 && pos <= scrollSize || stickyMap[id] === 2 && pos >= scrollSize + boundsSize - size), measures = {
@@ -1463,48 +1502,6 @@ class TrackBox extends CacheMap {
1463
1502
  }
1464
1503
  }
1465
1504
 
1466
- /**
1467
- * Scroll event.
1468
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/utils/scrollEvent.ts
1469
- * @author Evgenii Grebennikov
1470
- * @email djonnyx@gmail.com
1471
- */
1472
- class ScrollEvent {
1473
- _direction = 1;
1474
- get direction() { return this._direction; }
1475
- _scrollSize = 0;
1476
- get scrollSize() { return this._scrollSize; }
1477
- _scrollWeight = 0;
1478
- get scrollWeight() { return this._scrollWeight; }
1479
- _isVertical = true;
1480
- get isVertical() { return this._isVertical; }
1481
- _listSize = 0;
1482
- get listSize() { return this._listSize; }
1483
- _size = 0;
1484
- get size() { return this._size; }
1485
- _isStart = true;
1486
- get isStart() { return this._isStart; }
1487
- _isEnd = false;
1488
- get isEnd() { return this._isEnd; }
1489
- _delta = 0;
1490
- get delta() { return this._delta; }
1491
- _scrollDelta = 0;
1492
- get scrollDelta() { return this._scrollDelta; }
1493
- constructor(params) {
1494
- const { direction, isVertical, container, list, delta, scrollDelta } = params;
1495
- this._direction = direction;
1496
- this._isVertical = isVertical;
1497
- this._scrollSize = isVertical ? container.scrollTop : container.scrollLeft;
1498
- this._scrollWeight = isVertical ? container.scrollHeight : container.scrollWidth;
1499
- this._listSize = isVertical ? list.offsetHeight : list.offsetWidth;
1500
- this._size = isVertical ? container.offsetHeight : container.offsetWidth;
1501
- this._isEnd = (this._scrollSize + this._size) === this._scrollWeight;
1502
- this._delta = delta;
1503
- this._scrollDelta = scrollDelta;
1504
- this._isStart = this._scrollSize === 0;
1505
- }
1506
- }
1507
-
1508
1505
  const ADVANCED_PATTERNS = [SnappingMethods.ADVANCED, 'advanced'], DEFAULT_PATTERN = [SnappingMethods.NORMAL, 'normal'];
1509
1506
  const isSnappingMethodAdvenced = (method) => {
1510
1507
  return ADVANCED_PATTERNS.includes(method);
@@ -1516,6 +1513,20 @@ const isSnappingMethodDefault = (method) => {
1516
1513
  const IS_FIREFOX = navigator.userAgent.toLowerCase().includes('firefox');
1517
1514
  const FIREFOX_SCROLLBAR_OVERLAP_SIZE = 12;
1518
1515
 
1516
+ const HORIZONTAL_ALIASES = [Directions.HORIZONTAL, 'horizontal'], VERTICAL_ALIASES = [Directions.VERTICAL, 'vertical'];
1517
+ /**
1518
+ * Determines the axis membership of a virtual list
1519
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/utils/isDirection.ts
1520
+ * @author Evgenii Grebennikov
1521
+ * @email djonnyx@gmail.com
1522
+ */
1523
+ const isDirection = (src, expected) => {
1524
+ if (HORIZONTAL_ALIASES.includes(expected)) {
1525
+ return HORIZONTAL_ALIASES.includes(src);
1526
+ }
1527
+ return VERTICAL_ALIASES.includes(src);
1528
+ };
1529
+
1519
1530
  /**
1520
1531
  * Virtual list component.
1521
1532
  * Maximum performance for extremely large lists.
@@ -1882,9 +1893,6 @@ class NgVirtualListComponent {
1882
1893
  }
1883
1894
  return of(displayItems);
1884
1895
  })).subscribe();
1885
- this.setupRenderer();
1886
- }
1887
- setupRenderer() {
1888
1896
  const $itemRenderer = this.$itemRenderer;
1889
1897
  $itemRenderer.pipe(takeUntilDestroyed(), distinctUntilChanged(), filter(v => !!v), tap(v => {
1890
1898
  this._$renderer.next(v);
@@ -2212,5 +2220,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
2212
2220
  * Generated bundle index. Do not edit.
2213
2221
  */
2214
2222
 
2215
- export { BaseVirtualListItemComponent, Directions, NgVirtualListComponent, NgVirtualListItemComponent, NgVirtualListModule, SnappingMethods };
2223
+ export { Directions, NgVirtualListComponent, NgVirtualListItemComponent, NgVirtualListModule, ScrollEvent, SnappingMethods, debounce, toggleClassName };
2216
2224
  //# sourceMappingURL=ng-virtual-list.mjs.map