ng-virtual-list 16.7.11 → 16.7.13

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 (34) hide show
  1. package/README.md +28 -9
  2. package/esm2022/lib/components/ng-virtual-list-item.component.mjs +43 -27
  3. package/esm2022/lib/const/index.mjs +3 -2
  4. package/esm2022/lib/enums/collection-mode.mjs +2 -0
  5. package/esm2022/lib/enums/collection-modes.mjs +18 -0
  6. package/esm2022/lib/enums/focus-alignments.mjs +14 -0
  7. package/esm2022/lib/enums/index.mjs +4 -2
  8. package/esm2022/lib/models/display-object-config.model.mjs +2 -0
  9. package/esm2022/lib/models/display-object-measures.model.mjs +2 -0
  10. package/esm2022/lib/models/index.mjs +1 -1
  11. package/esm2022/lib/ng-virtual-list.component.mjs +108 -19
  12. package/esm2022/lib/ng-virtual-list.service.mjs +4 -3
  13. package/esm2022/lib/types/focus-alignment.mjs +2 -0
  14. package/esm2022/lib/types/index.mjs +1 -1
  15. package/esm2022/lib/utils/isCollectionMode.mjs +15 -0
  16. package/esm2022/lib/utils/trackBox.mjs +45 -16
  17. package/fesm2022/ng-virtual-list.mjs +237 -59
  18. package/fesm2022/ng-virtual-list.mjs.map +1 -1
  19. package/lib/components/ng-virtual-list-item.component.d.ts +9 -39
  20. package/lib/const/index.d.ts +2 -1
  21. package/lib/enums/collection-mode.d.ts +8 -0
  22. package/lib/enums/collection-modes.d.ts +16 -0
  23. package/lib/enums/focus-alignments.d.ts +12 -0
  24. package/lib/enums/index.d.ts +5 -2
  25. package/lib/models/display-object-config.model.d.ts +35 -0
  26. package/lib/models/display-object-measures.model.d.ts +13 -0
  27. package/lib/models/index.d.ts +3 -1
  28. package/lib/ng-virtual-list.component.d.ts +19 -3
  29. package/lib/ng-virtual-list.service.d.ts +4 -4
  30. package/lib/types/focus-alignment.d.ts +8 -0
  31. package/lib/types/index.d.ts +2 -1
  32. package/lib/utils/isCollectionMode.d.ts +8 -0
  33. package/lib/utils/trackBox.d.ts +17 -9
  34. package/package.json +1 -1
@@ -1,12 +1,30 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, Component, ChangeDetectionStrategy, EventEmitter as EventEmitter$1, ViewContainerRef, ElementRef, ViewEncapsulation, ViewChild, Output, Input, NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
3
- import { takeUntil, tap as tap$1, map } from 'rxjs/operators';
4
- import { Subject, tap, BehaviorSubject as BehaviorSubject$1, fromEvent, combineLatest, filter, distinctUntilChanged, skip, map as map$1, debounceTime, switchMap, of } from 'rxjs';
5
- import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
3
+ import { tap as tap$1, map } from 'rxjs/operators';
4
+ import { Subject, tap, BehaviorSubject as BehaviorSubject$1, fromEvent, combineLatest, filter, distinctUntilChanged, map as map$1, debounceTime, switchMap, of } from 'rxjs';
6
5
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
+ import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
7
7
  import * as i2 from '@angular/common';
8
8
  import { CommonModule } from '@angular/common';
9
9
 
10
+ /**
11
+ * Action modes for collection elements.
12
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/enums/collection-modes.ts
13
+ * @author Evgenii Grebennikov
14
+ * @email djonnyx@gmail.com
15
+ */
16
+ var CollectionModes;
17
+ (function (CollectionModes) {
18
+ /**
19
+ * When adding elements to the beginning of the collection, the scroll remains at the current position.
20
+ */
21
+ CollectionModes["NORMAL"] = "normal";
22
+ /**
23
+ * When adding elements to the beginning of the collection, the scroll is shifted by the sum of the sizes of the new elements.
24
+ */
25
+ CollectionModes["LAZY"] = "lazy";
26
+ })(CollectionModes || (CollectionModes = {}));
27
+
10
28
  /**
11
29
  * Axis of the arrangement of virtual list elements.
12
30
  * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/enums/directions.ts
@@ -65,6 +83,20 @@ var SnappingMethods;
65
83
  SnappingMethods["ADVANCED"] = "advanced";
66
84
  })(SnappingMethods || (SnappingMethods = {}));
67
85
 
86
+ /**
87
+ * Focus Alignments.
88
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/enums/focus-alignments.ts
89
+ * @author Evgenii Grebennikov
90
+ * @email djonnyx@gmail.com
91
+ */
92
+ var FocusAlignments;
93
+ (function (FocusAlignments) {
94
+ FocusAlignments["NONE"] = "none";
95
+ FocusAlignments["START"] = "start";
96
+ FocusAlignments["CENTER"] = "center";
97
+ FocusAlignments["END"] = "end";
98
+ })(FocusAlignments || (FocusAlignments = {}));
99
+
68
100
  const DEFAULT_ITEM_SIZE = 24;
69
101
  const DEFAULT_BUFFER_SIZE = 2;
70
102
  const DEFAULT_MAX_BUFFER_SIZE = 10;
@@ -76,6 +108,7 @@ const DEFAULT_ENABLED_BUFFER_OPTIMIZATION = false;
76
108
  const DEFAULT_DYNAMIC_SIZE = false;
77
109
  const TRACK_BY_PROPERTY_NAME = 'id';
78
110
  const DEFAULT_DIRECTION = Directions.VERTICAL;
111
+ const DEFAULT_COLLECTION_MODE = CollectionModes.NORMAL;
79
112
  const DISPLAY_OBJECTS_LENGTH_MESUREMENT_ERROR = 1;
80
113
  const MAX_SCROLL_TO_ITERATIONS = 5;
81
114
  const DEFAULT_SNAPPING_METHOD = SnappingMethods.NORMAL;
@@ -368,11 +401,11 @@ class NgVirtualListService {
368
401
  this._trackBox = trackBox;
369
402
  }
370
403
  itemToFocus;
371
- focus(element) {
404
+ focus(element, align = FocusAlignments.CENTER) {
372
405
  element.focus({ preventScroll: true });
373
406
  if (element.parentElement) {
374
407
  const pos = parseFloat(element.parentElement?.getAttribute('position') ?? '0');
375
- this.itemToFocus?.(element, pos);
408
+ this.itemToFocus?.(element, pos, align);
376
409
  }
377
410
  }
378
411
  areaFocus(id) {
@@ -392,7 +425,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
392
425
  }]
393
426
  }], ctorParameters: function () { return []; } });
394
427
 
395
- const ATTR_AREA_SELECTED = 'area-selected', TABINDEX = 'ng-vl-index', KEY_SPACE = " ", KEY_ARR_LEFT = "ArrowLeft", KEY_ARR_UP = "ArrowUp", KEY_ARR_RIGHT = "ArrowRight", KEY_ARR_DOWN = "ArrowDown", EVENT_FOCUS_IN = 'focusin', EVENT_FOCUS_OUT = 'focusout', EVENT_KEY_DOWN = 'keydown';
428
+ const ATTR_AREA_SELECTED = 'area-selected', TABINDEX = 'ng-vl-index', POSITION = 'position', POSITION_ZERO = '0', ID = 'item-id', KEY_SPACE = " ", KEY_ARR_LEFT = "ArrowLeft", KEY_ARR_UP = "ArrowUp", KEY_ARR_RIGHT = "ArrowRight", KEY_ARR_DOWN = "ArrowDown", EVENT_FOCUS_IN = 'focusin', EVENT_FOCUS_OUT = 'focusout', EVENT_KEY_DOWN = 'keydown';
396
429
  const getElementByIndex = (index) => {
397
430
  return `[${TABINDEX}="${index}"]`;
398
431
  };
@@ -406,7 +439,6 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
406
439
  _cdr;
407
440
  _elementRef;
408
441
  _service;
409
- _$unsubscribe = new Subject();
410
442
  _id;
411
443
  get id() {
412
444
  return this._id;
@@ -418,12 +450,12 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
418
450
  _$config = new BehaviorSubject$1({});
419
451
  $config = this._$config.asObservable();
420
452
  measures = new BehaviorSubject$1(undefined);
421
- _$focus = new BehaviorSubject$1(false);
422
- $focus = this._$focus.asObservable();
453
+ _$focused = new BehaviorSubject$1(false);
454
+ $focused = this._$focused.asObservable();
423
455
  _$part = new BehaviorSubject$1(PART_DEFAULT_ITEM);
424
456
  $part = this._$part.asObservable();
425
457
  regular = false;
426
- data = undefined;
458
+ data;
427
459
  _$data = new BehaviorSubject$1(this.data);
428
460
  $data = this._$data.asObservable();
429
461
  set item(v) {
@@ -490,28 +522,35 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
490
522
  }
491
523
  this._service.collapse(data, collapsed);
492
524
  };
525
+ _focusHandler = () =>
526
+ /**
527
+ * Focus a list item
528
+ */
529
+ (align = FocusAlignments.CENTER) => {
530
+ this.focus(align);
531
+ };
493
532
  constructor(_cdr, _elementRef, _service) {
494
533
  super();
495
534
  this._cdr = _cdr;
496
535
  this._elementRef = _elementRef;
497
536
  this._service = _service;
498
537
  this._id = this._service.generateComponentId();
499
- const $data = this.$data, $focus = this.$focus;
538
+ const $data = this.$data, $focus = this.$focused;
500
539
  this._elementRef.nativeElement.setAttribute('id', String(this._id));
501
- $focus.pipe(takeUntil(this._$unsubscribe), tap$1(v => {
540
+ $focus.pipe(takeUntilDestroyed(), tap$1(v => {
502
541
  this._service.areaFocus(v ? this._id : this._service.focusedId === this._id ? null : this._service.focusedId);
503
542
  })).subscribe();
504
- fromEvent(this.element, EVENT_FOCUS_IN).pipe(takeUntil(this._$unsubscribe), tap$1(e => {
505
- this._$focus.next(true);
543
+ fromEvent(this.element, EVENT_FOCUS_IN).pipe(takeUntilDestroyed(), tap$1(e => {
544
+ this._$focused.next(true);
506
545
  this.updateConfig(this.data);
507
546
  this.updatePartStr(this.data, this._isSelected, this._isCollapsed);
508
547
  })).subscribe(),
509
- fromEvent(this.element, EVENT_FOCUS_OUT).pipe(takeUntil(this._$unsubscribe), tap$1(e => {
510
- this._$focus.next(false);
548
+ fromEvent(this.element, EVENT_FOCUS_OUT).pipe(takeUntilDestroyed(), tap$1(e => {
549
+ this._$focused.next(false);
511
550
  this.updateConfig(this.data);
512
551
  this.updatePartStr(this.data, this._isSelected, this._isCollapsed);
513
552
  })).subscribe(),
514
- fromEvent(this.element, EVENT_KEY_DOWN).pipe(takeUntil(this._$unsubscribe), tap$1(e => {
553
+ fromEvent(this.element, EVENT_KEY_DOWN).pipe(takeUntilDestroyed(), tap$1(e => {
515
554
  switch (e.key) {
516
555
  case KEY_SPACE: {
517
556
  e.stopImmediatePropagation();
@@ -554,7 +593,7 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
554
593
  break;
555
594
  }
556
595
  })).subscribe();
557
- combineLatest([$data, this._service.$methodOfSelecting, this._service.$selectedIds, this._service.$collapsedIds]).pipe(takeUntil(this._$unsubscribe), map(([, m, selectedIds, collapsedIds]) => ({ method: m, selectedIds, collapsedIds })), tap$1(({ method, selectedIds, collapsedIds }) => {
596
+ combineLatest([$data, this._service.$methodOfSelecting, this._service.$selectedIds, this._service.$collapsedIds]).pipe(takeUntilDestroyed(), map(([, m, selectedIds, collapsedIds]) => ({ method: m, selectedIds, collapsedIds })), tap$1(({ method, selectedIds, collapsedIds }) => {
558
597
  switch (method) {
559
598
  case MethodsForSelectingTypes.SELECT: {
560
599
  const id = selectedIds, isSelected = id === this.itemId;
@@ -610,18 +649,29 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
610
649
  }
611
650
  }
612
651
  }
652
+ focus(align = FocusAlignments.CENTER) {
653
+ if (this._service.listElement) {
654
+ const tabIndex = this.data?.config?.tabIndex ?? 0;
655
+ let index = tabIndex;
656
+ const el = this._service.listElement.querySelector(getElementByIndex(index));
657
+ if (el) {
658
+ this._service.focus(el, align);
659
+ }
660
+ }
661
+ }
613
662
  updateMeasures(v) {
614
663
  this.measures.next(v?.measures ? { ...v.measures } : undefined);
615
664
  }
616
665
  updateConfig(v) {
617
666
  this._$config.next({
618
- ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focus: this._$focus.getValue(),
619
- collapse: this._collapseHandler(v), select: this._selectHandler(v)
667
+ ...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this._$focused.getValue(),
668
+ collapse: this._collapseHandler(v), select: this._selectHandler(v), focus: this._focusHandler(),
620
669
  });
621
670
  }
622
671
  update() {
623
672
  const data = this.data, regular = this.regular, length = this._regularLength;
624
673
  if (data) {
674
+ this._elementRef.nativeElement.setAttribute(ID, `${data.id}`);
625
675
  const styles = this._elementRef.nativeElement.style;
626
676
  styles.zIndex = data.config.zIndex;
627
677
  if (data.config.snapped) {
@@ -645,6 +695,9 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
645
695
  styles.height = data.config.isVertical ? data.config.dynamic ? SIZE_AUTO : `${data.measures.height}${PX}` : regular ? length : SIZE_100_PERSENT;
646
696
  styles.width = data.config.isVertical ? regular ? length : SIZE_100_PERSENT : data.config.dynamic ? SIZE_AUTO : `${data.measures.width}${PX}`;
647
697
  }
698
+ else {
699
+ this._elementRef.nativeElement.removeAttribute(ID);
700
+ }
648
701
  this._cdr.markForCheck();
649
702
  }
650
703
  updatePartStr(v, isSelected, isCollapsed) {
@@ -666,7 +719,7 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
666
719
  if (v ? v.config.new : false) {
667
720
  part += PART_ITEM_NEW;
668
721
  }
669
- if (this._$focus.getValue()) {
722
+ if (this._$focused.getValue()) {
670
723
  part += PART_ITEM_FOCUSED;
671
724
  }
672
725
  this._$part.next(part);
@@ -712,21 +765,15 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
712
765
  onClickHandler() {
713
766
  this._service.itemClick(this.data);
714
767
  }
715
- ngOnDestroy() {
716
- if (this._$unsubscribe) {
717
- this._$unsubscribe.next();
718
- this._$unsubscribe.complete();
719
- }
720
- }
721
768
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NgVirtualListItemComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: NgVirtualListService }], target: i0.ɵɵFactoryTarget.Component });
722
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NgVirtualListItemComponent, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"data\">\r\n <div #listItem [part]=\"$part | async\" [attr.ng-vl-index]=\"data.config.tabIndex || -1\" tabindex=\"0\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut, 'focus': $focus | async}\" (click)=\"onClickHandler()\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, measures: measures | async, config: $config | async}\"></ng-container>\r\n </ng-container>\r\n </div>\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;box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
769
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NgVirtualListItemComponent, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"data\">\r\n <div #listItem [part]=\"$part | async\" [attr.ng-vl-index]=\"data.config.tabIndex || -1\" tabindex=\"0\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut, 'focus': $focused | async}\" (click)=\"onClickHandler()\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, measures: measures | async, config: $config | async}\"></ng-container>\r\n </ng-container>\r\n </div>\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;box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
723
770
  }
724
771
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
725
772
  type: Component,
726
773
  args: [{ selector: 'ng-virtual-list-item', host: {
727
774
  'class': 'ngvl__item',
728
775
  'role': 'listitem',
729
- }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"data\">\r\n <div #listItem [part]=\"$part | async\" [attr.ng-vl-index]=\"data.config.tabIndex || -1\" tabindex=\"0\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut, 'focus': $focus | async}\" (click)=\"onClickHandler()\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, measures: measures | async, config: $config | async}\"></ng-container>\r\n </ng-container>\r\n </div>\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;box-sizing:border-box}\n"] }]
776
+ }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"data\">\r\n <div #listItem [part]=\"$part | async\" [attr.ng-vl-index]=\"data.config.tabIndex || -1\" tabindex=\"0\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut, 'focus': $focused | async}\" (click)=\"onClickHandler()\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, measures: measures | async, config: $config | async}\"></ng-container>\r\n </ng-container>\r\n </div>\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;box-sizing:border-box}\n"] }]
730
777
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: NgVirtualListService }]; } });
731
778
 
732
779
  /**
@@ -1264,7 +1311,11 @@ const bufferInterpolation = (currentBufferValue, array, value, extra) => {
1264
1311
  return Math.ceil(buffer / l);
1265
1312
  };
1266
1313
 
1267
- const TRACK_BOX_CHANGE_EVENT_NAME = 'change';
1314
+ var TrackBoxEvents;
1315
+ (function (TrackBoxEvents) {
1316
+ TrackBoxEvents["CHANGE"] = "change";
1317
+ TrackBoxEvents["RESET"] = "reset";
1318
+ })(TrackBoxEvents || (TrackBoxEvents = {}));
1268
1319
  var ItemDisplayMethods;
1269
1320
  (function (ItemDisplayMethods) {
1270
1321
  ItemDisplayMethods[ItemDisplayMethods["CREATE"] = 0] = "CREATE";
@@ -1272,7 +1323,7 @@ var ItemDisplayMethods;
1272
1323
  ItemDisplayMethods[ItemDisplayMethods["DELETE"] = 2] = "DELETE";
1273
1324
  ItemDisplayMethods[ItemDisplayMethods["NOT_CHANGED"] = 3] = "NOT_CHANGED";
1274
1325
  })(ItemDisplayMethods || (ItemDisplayMethods = {}));
1275
- const DEFAULT_BUFFER_EXTREMUM_THRESHOLD = 15, DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH = 30, DEFAULT_RESET_BUFFER_SIZE_TIMEOUT = 10000;
1326
+ const DEFAULT_BUFFER_EXTREMUM_THRESHOLD = 15, DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH = 30, DEFAULT_RESET_BUFFER_SIZE_TIMEOUT = 10000, IS_NEW = 'isNew';
1276
1327
  /**
1277
1328
  * An object that performs tracking, calculations and caching.
1278
1329
  * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/utils/trackBox.ts
@@ -1309,6 +1360,13 @@ class TrackBox extends CacheMap {
1309
1360
  }
1310
1361
  this._isSnappingMethodAdvanced = v;
1311
1362
  }
1363
+ _isLazy = false;
1364
+ set isLazy(v) {
1365
+ if (this._isLazy === v) {
1366
+ return;
1367
+ }
1368
+ this._isLazy = v;
1369
+ }
1312
1370
  /**
1313
1371
  * Set the trackBy property
1314
1372
  */
@@ -1341,7 +1399,7 @@ class TrackBox extends CacheMap {
1341
1399
  get crudDetected() { return this._crudDetected; }
1342
1400
  fireChangeIfNeed() {
1343
1401
  if (this.changesDetected()) {
1344
- this.dispatch(TRACK_BOX_CHANGE_EVENT_NAME, this._version);
1402
+ this.dispatch(TrackBoxEvents.CHANGE, this._version);
1345
1403
  }
1346
1404
  }
1347
1405
  _previousTotalSize = 0;
@@ -1357,7 +1415,7 @@ class TrackBox extends CacheMap {
1357
1415
  _maxBufferSize = this._defaultBufferSize;
1358
1416
  _resetBufferSizeTimeout = DEFAULT_RESET_BUFFER_SIZE_TIMEOUT;
1359
1417
  _resetBufferSizeTimer;
1360
- isInit = true;
1418
+ isReseted = true;
1361
1419
  lifeCircle() {
1362
1420
  this.fireChangeIfNeed();
1363
1421
  this.lifeCircleDo();
@@ -1370,11 +1428,19 @@ class TrackBox extends CacheMap {
1370
1428
  console.warn('Attention! The collection must be immutable.');
1371
1429
  return;
1372
1430
  }
1373
- if (this.isInit && !(!this._previousCollection || this._previousCollection.length === 0)) {
1374
- this.isInit = false;
1431
+ let reseted = this.isReseted;
1432
+ if (reseted) {
1433
+ if (!(!this._previousCollection || this._previousCollection.length === 0)) {
1434
+ reseted = false;
1435
+ }
1436
+ }
1437
+ if (!reseted && (!currentCollection || currentCollection.length === 0)) {
1438
+ reseted = true;
1375
1439
  }
1440
+ this.isReseted = reseted;
1441
+ this.dispatch(TrackBoxEvents.RESET, reseted);
1376
1442
  this.updateCache(this._previousCollection, currentCollection, itemSize);
1377
- this._previousCollection = currentCollection;
1443
+ this._previousCollection = [...(currentCollection || [])];
1378
1444
  }
1379
1445
  /**
1380
1446
  * Update the cache of items from the list
@@ -1597,9 +1663,10 @@ class TrackBox extends CacheMap {
1597
1663
  leftItemsOffset = rightItemsOffset = bufferSize;
1598
1664
  }
1599
1665
  let itemsFromStartToScrollEnd = -1, itemsFromDisplayEndToOffsetEnd = 0, itemsFromStartToDisplayEnd = -1, leftItemLength = 0, rightItemLength = 0, leftItemsWeight = 0, rightItemsWeight = 0, leftHiddenItemsWeight = 0, totalItemsToDisplayEndWeight = 0, leftSizeOfAddedItems = 0, leftSizeOfUpdatedItems = 0, leftSizeOfDeletedItems = 0, itemById = undefined, itemByIdPos = 0, targetDisplayItemIndex = -1, isTargetInOverscroll = false, actualScrollSize = itemByIdPos, totalSize = 0, startIndex, isFromItemIdFound = false, deltaFromStartCreation = 0;
1666
+ let isNew = !this.isReseted && (scrollSize === 0);
1600
1667
  // If the list is dynamic or there are new elements in the collection, then it switches to the long algorithm.
1601
1668
  if (dynamicSize) {
1602
- let y = 0, stickyCollectionItem = undefined, stickyComponentSize = 0, isNew = true;
1669
+ let y = 0, stickyCollectionItem = undefined, stickyComponentSize = 0;
1603
1670
  for (let i = 0, l = collection.length; i < l; i++) {
1604
1671
  const ii = i + 1, collectionItem = collection[i], id = collectionItem.id;
1605
1672
  let componentSize = 0, componentSizeDelta = 0, itemDisplayMethod = ItemDisplayMethods.NOT_CHANGED;
@@ -1607,8 +1674,8 @@ class TrackBox extends CacheMap {
1607
1674
  const bounds = map.get(id) || { width: typicalItemSize, height: typicalItemSize };
1608
1675
  componentSize = bounds[sizeProperty];
1609
1676
  itemDisplayMethod = bounds?.method ?? ItemDisplayMethods.UPDATE;
1610
- const isItemNew = bounds.isNew ?? true;
1611
- if (isNew && (this.isInit || (!isItemNew && i > 0))) {
1677
+ const isItemNew = bounds?.[IS_NEW] ?? this._isLazy;
1678
+ if (!isItemNew && (!this._isLazy || !itemConfigMap[collection[0].id]?.sticky)) {
1612
1679
  isNew = false;
1613
1680
  }
1614
1681
  switch (itemDisplayMethod) {
@@ -1745,8 +1812,15 @@ class TrackBox extends CacheMap {
1745
1812
  if (map.has(id)) {
1746
1813
  const bounds = map.get(id);
1747
1814
  itemDisplayMethod = bounds?.method ?? ItemDisplayMethods.UPDATE;
1815
+ const isItemNew = bounds?.[IS_NEW] ?? this._isLazy;
1816
+ if (!isItemNew && (!this._isLazy || !itemConfigMap[collection[0].id]?.sticky)) {
1817
+ isNew = false;
1818
+ }
1748
1819
  if (itemDisplayMethod === ItemDisplayMethods.CREATE) {
1749
- map.set(id, { ...bounds, method: ItemDisplayMethods.NOT_CHANGED });
1820
+ if (isNew) {
1821
+ deltaFromStartCreation += componentSize;
1822
+ }
1823
+ map.set(id, { ...bounds, method: ItemDisplayMethods.NOT_CHANGED, isNew });
1750
1824
  }
1751
1825
  }
1752
1826
  if (deletedItemsMap.hasOwnProperty(i)) {
@@ -1758,7 +1832,9 @@ class TrackBox extends CacheMap {
1758
1832
  if (y < scrollSize - componentSize) {
1759
1833
  switch (itemDisplayMethod) {
1760
1834
  case ItemDisplayMethods.CREATE: {
1761
- leftSizeOfUpdatedItems += componentSize;
1835
+ if (!isNew) {
1836
+ leftSizeOfUpdatedItems += componentSize;
1837
+ }
1762
1838
  break;
1763
1839
  }
1764
1840
  case ItemDisplayMethods.UPDATE: {
@@ -1854,7 +1930,7 @@ class TrackBox extends CacheMap {
1854
1930
  height: isVertical ? size : normalizedItemHeight,
1855
1931
  delta: 0,
1856
1932
  }, config = {
1857
- new: cache.isNew === true,
1933
+ new: cache?.[IS_NEW] === true,
1858
1934
  odd: isOdd,
1859
1935
  even: !isOdd,
1860
1936
  isVertical,
@@ -1896,7 +1972,7 @@ class TrackBox extends CacheMap {
1896
1972
  height: h,
1897
1973
  delta: 0,
1898
1974
  }, config = {
1899
- new: cache.isNew === true,
1975
+ new: cache?.[IS_NEW] === true,
1900
1976
  odd: isOdd,
1901
1977
  even: !isOdd,
1902
1978
  isVertical,
@@ -1937,7 +2013,7 @@ class TrackBox extends CacheMap {
1937
2013
  height: isVertical ? size : normalizedItemHeight,
1938
2014
  delta: 0,
1939
2015
  }, config = {
1940
- new: cache.isNew === true,
2016
+ new: cache?.[IS_NEW] === true,
1941
2017
  odd: isOdd,
1942
2018
  even: !isOdd,
1943
2019
  isVertical,
@@ -2123,7 +2199,21 @@ const copyValueAsReadonly = (source) => {
2123
2199
  return source;
2124
2200
  };
2125
2201
 
2126
- const ROLE_LIST = 'list', ROLE_LIST_BOX = 'listbox';
2202
+ const NORMAL_ALIASES = [CollectionModes.NORMAL, 'normal'], LAZY_ALIASES = [CollectionModes.LAZY, 'lazy'];
2203
+ /**
2204
+ * Determines the axis membership of a virtual list
2205
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/16.x/projects/ng-virtual-list/src/lib/utils/isCollectionMode.ts
2206
+ * @author Evgenii Grebennikov
2207
+ * @email djonnyx@gmail.com
2208
+ */
2209
+ const isCollectionMode = (src, expected) => {
2210
+ if (LAZY_ALIASES.includes(expected)) {
2211
+ return LAZY_ALIASES.includes(src);
2212
+ }
2213
+ return NORMAL_ALIASES.includes(src);
2214
+ };
2215
+
2216
+ const ROLE_LIST = 'list', ROLE_LIST_BOX = 'listbox', ITEM_ID = 'item-id', ITEM_CONTAINER = 'ngvl-item__container';
2127
2217
  const validateScrollIteration = (value) => {
2128
2218
  return Number.isNaN(value) || (value < 0) ? 0 : value > MAX_SCROLL_TO_ITERATIONS ? MAX_SCROLL_TO_ITERATIONS : value;
2129
2219
  }, validateId = (id) => {
@@ -2142,6 +2232,11 @@ const validateScrollIteration = (value) => {
2142
2232
  if (!valid) {
2143
2233
  throw Error('The "iteration" parameter must be of type `number`.');
2144
2234
  }
2235
+ }, validateFocusAlignment = (align) => {
2236
+ const valid = validateString(align) && (align === 'none' || align === 'start' || align === 'center' || align === 'end');
2237
+ if (!valid) {
2238
+ throw Error('The "align" parameter must have the value `none`, `start`, `center` or `end`.');
2239
+ }
2145
2240
  };
2146
2241
  /**
2147
2242
  * Virtual list component.
@@ -2541,6 +2636,29 @@ class NgVirtualListComponent {
2541
2636
  }
2542
2637
  ;
2543
2638
  get direction() { return this._$direction.getValue(); }
2639
+ _$collectionMode = new BehaviorSubject$1(DEFAULT_COLLECTION_MODE);
2640
+ $collectionMode = this._$collectionMode.asObservable();
2641
+ _collectionModeTransform = (v) => {
2642
+ const valid = validateString(v) && (v === 'normal' || v === 'lazy');
2643
+ if (!valid) {
2644
+ console.error('The "direction" parameter must have the value `normal` or `lazy`.');
2645
+ return DEFAULT_COLLECTION_MODE;
2646
+ }
2647
+ return v;
2648
+ };
2649
+ /**
2650
+ * Determines the action modes for collection elements. Default value is "normal".
2651
+ */
2652
+ set collectionMode(v) {
2653
+ if (this._$collectionMode.getValue() === v) {
2654
+ return;
2655
+ }
2656
+ const transformedValue = this._collectionModeTransform(v);
2657
+ this._$collectionMode.next(transformedValue);
2658
+ this._cdr.markForCheck();
2659
+ }
2660
+ ;
2661
+ get collectionMode() { return this._$collectionMode.getValue(); }
2544
2662
  _$bufferSize = new BehaviorSubject$1(DEFAULT_BUFFER_SIZE);
2545
2663
  $bufferSize = this._$bufferSize.asObservable();
2546
2664
  _bufferSizeTransform = (v) => {
@@ -2664,6 +2782,7 @@ class NgVirtualListComponent {
2664
2782
  ;
2665
2783
  get trackBy() { return this._$trackBy.getValue(); }
2666
2784
  _isVertical = this.getIsVertical();
2785
+ _isLazy = this.getIsLazy();
2667
2786
  get orientation() {
2668
2787
  return this._isVertical ? Directions.VERTICAL : Directions.HORIZONTAL;
2669
2788
  }
@@ -2739,12 +2858,33 @@ class NgVirtualListComponent {
2739
2858
  this._$scrollSize.next(scrollSize);
2740
2859
  }
2741
2860
  };
2742
- itemToFocus = (element, position) => {
2861
+ itemToFocus = (element, position, align = FocusAlignments.CENTER) => {
2743
2862
  const container = this._container?.nativeElement;
2744
2863
  if (container) {
2745
- const { width, height } = this._$bounds.getValue(), { width: elementWidth, height: elementHeight } = element.getBoundingClientRect(), isVertical = this._isVertical, pos = isVertical ? position - (height - elementHeight) * .5 : position - (width - elementWidth) * .5;
2746
- const params = { [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: pos, behavior: 'instant' };
2747
- container.scrollTo(params);
2864
+ const { width, height } = this._$bounds.getValue(), { width: elementWidth, height: elementHeight } = element.getBoundingClientRect(), isVertical = this._isVertical;
2865
+ let pos = Number.NaN;
2866
+ switch (align) {
2867
+ case FocusAlignments.START: {
2868
+ pos = isVertical ? position : position;
2869
+ break;
2870
+ }
2871
+ case FocusAlignments.CENTER: {
2872
+ pos = isVertical ? position - (height - elementHeight) * .5 : position - (width - elementWidth) * .5;
2873
+ break;
2874
+ }
2875
+ case FocusAlignments.END: {
2876
+ pos = isVertical ? position - (height - elementHeight) : position - (width - elementWidth);
2877
+ break;
2878
+ }
2879
+ case FocusAlignments.NONE:
2880
+ default: {
2881
+ break;
2882
+ }
2883
+ }
2884
+ if (!Number.isNaN(pos)) {
2885
+ const params = { [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: pos, behavior: 'instant' };
2886
+ container.scrollTo(params);
2887
+ }
2748
2888
  }
2749
2889
  };
2750
2890
  _$initialized = new BehaviorSubject$1(false);
@@ -2768,6 +2908,20 @@ class NgVirtualListComponent {
2768
2908
  };
2769
2909
  _$cacheVersion = new BehaviorSubject$1(-1);
2770
2910
  get $cacheVersion() { return this._$cacheVersion.asObservable(); }
2911
+ _isResetedReachStart = true;
2912
+ _onTrackBoxResetHandler = (v) => {
2913
+ if (v) {
2914
+ this._isResetedReachStart = true;
2915
+ const container = this._container?.nativeElement;
2916
+ if (container) {
2917
+ const params = {
2918
+ [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: 0,
2919
+ behavior: BEHAVIOR_INSTANT,
2920
+ };
2921
+ container.scrollTo(params);
2922
+ }
2923
+ }
2924
+ };
2771
2925
  constructor(_cdr, _elementRef, _service) {
2772
2926
  this._cdr = _cdr;
2773
2927
  this._elementRef = _elementRef;
@@ -2785,12 +2939,13 @@ class NgVirtualListComponent {
2785
2939
  })).subscribe();
2786
2940
  this._trackBox.displayComponents = this._displayComponents;
2787
2941
  const $trackBy = this.$trackBy, $selectByClick = this.$selectByClick, $collapseByClick = this.$collapseByClick, $isScrollStart = this._$isScrollStart.asObservable(), $isScrollFinished = this._$isScrollFinished.asObservable();
2788
- $isScrollStart.pipe(takeUntilDestroyed(), distinctUntilChanged(), skip(1), tap(v => {
2789
- if (v) {
2942
+ $isScrollStart.pipe(takeUntilDestroyed(), distinctUntilChanged(), tap(v => {
2943
+ if (v && !this._isResetedReachStart) {
2790
2944
  this.onScrollReachStart.emit();
2791
2945
  }
2946
+ this._isResetedReachStart = false;
2792
2947
  })).subscribe();
2793
- $isScrollFinished.pipe(takeUntilDestroyed(), distinctUntilChanged(), skip(1), tap(v => {
2948
+ $isScrollFinished.pipe(takeUntilDestroyed(), distinctUntilChanged(), tap(v => {
2794
2949
  if (v) {
2795
2950
  this.onScrollReachEnd.emit();
2796
2951
  }
@@ -2804,7 +2959,10 @@ class NgVirtualListComponent {
2804
2959
  $trackBy.pipe(takeUntilDestroyed(), tap(v => {
2805
2960
  this._trackBox.trackingPropertyName = v;
2806
2961
  })).subscribe();
2807
- const $bounds = this._$bounds.asObservable().pipe(filter(b => !!b)), $items = this.$items.pipe(map$1(i => !i ? [] : i)), $scrollSize = this._$scrollSize.asObservable(), $itemSize = this.$itemSize.pipe(map$1(v => v <= 0 ? DEFAULT_ITEM_SIZE : v)), $bufferSize = this.$bufferSize.pipe(map$1(v => v < 0 ? DEFAULT_BUFFER_SIZE : v)), $maxBufferSize = this.$maxBufferSize.pipe(map$1(v => v < 0 ? DEFAULT_MAX_BUFFER_SIZE : v)), $itemConfigMap = this.$itemConfigMap.pipe(map$1(v => !v ? {} : v)), $snap = this.$snap, $isVertical = this.$direction.pipe(map$1(v => this.getIsVertical(v || DEFAULT_DIRECTION))), $dynamicSize = this.$dynamicSize, $enabledBufferOptimization = this.$enabledBufferOptimization, $snappingMethod = this.$snappingMethod.pipe(map$1(v => this.getIsSnappingMethodAdvanced(v || DEFAULT_SNAPPING_METHOD))), $methodForSelecting = this.$methodForSelecting, $selectedIds = this.$selectedIds, $collapsedIds = this.$collapsedIds.pipe(map$1(v => Array.isArray(v) ? v : [])), $collapsedItemIds = this._$collapsedItemIds.asObservable().pipe(map$1(v => Array.isArray(v) ? v : [])), $actualItems = this._$actualItems.asObservable(), $cacheVersion = this.$cacheVersion;
2962
+ const $bounds = this._$bounds.asObservable().pipe(filter(b => !!b)), $items = this.$items.pipe(map$1(i => !i ? [] : i)), $scrollSize = this._$scrollSize.asObservable(), $itemSize = this.$itemSize.pipe(map$1(v => v <= 0 ? DEFAULT_ITEM_SIZE : v)), $bufferSize = this.$bufferSize.pipe(map$1(v => v < 0 ? DEFAULT_BUFFER_SIZE : v)), $maxBufferSize = this.$maxBufferSize.pipe(map$1(v => v < 0 ? DEFAULT_MAX_BUFFER_SIZE : v)), $itemConfigMap = this.$itemConfigMap.pipe(map$1(v => !v ? {} : v)), $snap = this.$snap, $isVertical = this.$direction.pipe(map$1(v => this.getIsVertical(v || DEFAULT_DIRECTION))), $isLazy = this.$collectionMode.pipe(map$1(v => this.getIsLazy(v || DEFAULT_COLLECTION_MODE))), $dynamicSize = this.$dynamicSize, $enabledBufferOptimization = this.$enabledBufferOptimization, $snappingMethod = this.$snappingMethod.pipe(map$1(v => this.getIsSnappingMethodAdvanced(v || DEFAULT_SNAPPING_METHOD))), $methodForSelecting = this.$methodForSelecting, $selectedIds = this.$selectedIds, $collapsedIds = this.$collapsedIds.pipe(map$1(v => Array.isArray(v) ? v : [])), $collapsedItemIds = this._$collapsedItemIds.asObservable().pipe(map$1(v => Array.isArray(v) ? v : [])), $actualItems = this._$actualItems.asObservable(), $cacheVersion = this.$cacheVersion;
2963
+ $isLazy.pipe(takeUntilDestroyed(), tap(v => {
2964
+ this._trackBox.isLazy = v;
2965
+ })).subscribe();
2808
2966
  combineLatest([$items, $itemSize, this.$initialized]).pipe(takeUntilDestroyed(), distinctUntilChanged(), filter(([, , init]) => !!init), map$1(([items, itemSize]) => ({ items, itemSize })), tap(({ items, itemSize }) => {
2809
2967
  this._trackBox.resetCollection(items, itemSize);
2810
2968
  })).subscribe();
@@ -2953,13 +3111,13 @@ class NgVirtualListComponent {
2953
3111
  }
2954
3112
  listenCacheChangesIfNeed(value) {
2955
3113
  if (value) {
2956
- if (!this._trackBox.hasEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler)) {
2957
- this._trackBox.addEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler);
3114
+ if (!this._trackBox.hasEventListener(TrackBoxEvents.CHANGE, this._onTrackBoxChangeHandler)) {
3115
+ this._trackBox.addEventListener(TrackBoxEvents.CHANGE, this._onTrackBoxChangeHandler);
2958
3116
  }
2959
3117
  }
2960
3118
  else {
2961
- if (this._trackBox.hasEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler)) {
2962
- this._trackBox.removeEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler);
3119
+ if (this._trackBox.hasEventListener(TrackBoxEvents.CHANGE, this._onTrackBoxChangeHandler)) {
3120
+ this._trackBox.removeEventListener(TrackBoxEvents.CHANGE, this._onTrackBoxChangeHandler);
2963
3121
  }
2964
3122
  }
2965
3123
  }
@@ -2983,6 +3141,10 @@ class NgVirtualListComponent {
2983
3141
  const dir = d || this.direction;
2984
3142
  return isDirection(dir, Directions.VERTICAL);
2985
3143
  }
3144
+ getIsLazy(m) {
3145
+ const mode = m || this.collectionMode;
3146
+ return isCollectionMode(mode, CollectionModes.LAZY);
3147
+ }
2986
3148
  _componentsResizeObserver = new ResizeObserver(() => {
2987
3149
  this._trackBox.changes();
2988
3150
  });
@@ -3048,6 +3210,20 @@ class NgVirtualListComponent {
3048
3210
  validateId(id);
3049
3211
  return this._trackBox.getItemBounds(id);
3050
3212
  }
3213
+ /**
3214
+ * Focus an list item by a given id.
3215
+ */
3216
+ focus(id, align = FocusAlignments.NONE) {
3217
+ validateId(id);
3218
+ validateFocusAlignment(align);
3219
+ const el = this._list?.nativeElement.querySelector(`[${ITEM_ID}="${id}"]`);
3220
+ if (el) {
3221
+ const focusedEl = el.querySelector(`.${ITEM_CONTAINER}`);
3222
+ if (focusedEl) {
3223
+ this._service.focus(focusedEl, align);
3224
+ }
3225
+ }
3226
+ }
3051
3227
  /**
3052
3228
  * The method scrolls the list to the element with the given id and returns the value of the scrolled area.
3053
3229
  * Behavior accepts the values ​​"auto", "instant" and "smooth".
@@ -3209,7 +3385,7 @@ class NgVirtualListComponent {
3209
3385
  }
3210
3386
  }
3211
3387
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NgVirtualListComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: NgVirtualListService }], target: i0.ɵɵFactoryTarget.Component });
3212
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NgVirtualListComponent, selector: "ng-virtual-list", inputs: { items: "items", selectedIds: "selectedIds", collapsedIds: "collapsedIds", selectByClick: "selectByClick", collapseByClick: "collapseByClick", snap: "snap", enabledBufferOptimization: "enabledBufferOptimization", itemRenderer: "itemRenderer", itemConfigMap: "itemConfigMap", itemSize: "itemSize", dynamicSize: "dynamicSize", direction: "direction", bufferSize: "bufferSize", maxBufferSize: "maxBufferSize", snappingMethod: "snappingMethod", methodForSelecting: "methodForSelecting", trackBy: "trackBy" }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd", onViewportChange: "onViewportChange", onItemClick: "onItemClick", onSelect: "onSelect", onCollapse: "onCollapse", onScrollReachStart: "onScrollReachStart", onScrollReachEnd: "onScrollReachEnd" }, host: { styleAttribute: "position: relative;" }, providers: [NgVirtualListService], viewQueries: [{ propertyName: "_listContainerRef", first: true, predicate: ["renderersContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_container", first: true, predicate: ["container"], descendants: true, read: (ElementRef) }, { propertyName: "_list", first: true, predicate: ["list"], descendants: true, read: (ElementRef) }, { propertyName: "_snapContainerRef", first: true, predicate: ["snapRendererContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_snappedContainer", first: true, predicate: ["snapped"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div *ngIf=\"snap\" #snapped part=\"snapped-item\" class=\"ngvl__list-snapper\">\r\n <ng-container #snapRendererContainer></ng-container>\r\n</div>\r\n<div #container part=\"scroller\" class=\"ngvl__scroller\">\r\n <div [attr.aria-orientation]=\"orientation\" [attr.aria-activedescendant]=\"$focusedElement | async\" #list part=\"list\"\r\n 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: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
3388
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NgVirtualListComponent, selector: "ng-virtual-list", inputs: { items: "items", selectedIds: "selectedIds", collapsedIds: "collapsedIds", selectByClick: "selectByClick", collapseByClick: "collapseByClick", snap: "snap", enabledBufferOptimization: "enabledBufferOptimization", itemRenderer: "itemRenderer", itemConfigMap: "itemConfigMap", itemSize: "itemSize", dynamicSize: "dynamicSize", direction: "direction", collectionMode: "collectionMode", bufferSize: "bufferSize", maxBufferSize: "maxBufferSize", snappingMethod: "snappingMethod", methodForSelecting: "methodForSelecting", trackBy: "trackBy" }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd", onViewportChange: "onViewportChange", onItemClick: "onItemClick", onSelect: "onSelect", onCollapse: "onCollapse", onScrollReachStart: "onScrollReachStart", onScrollReachEnd: "onScrollReachEnd" }, host: { styleAttribute: "position: relative;" }, providers: [NgVirtualListService], viewQueries: [{ propertyName: "_listContainerRef", first: true, predicate: ["renderersContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_container", first: true, predicate: ["container"], descendants: true, read: (ElementRef) }, { propertyName: "_list", first: true, predicate: ["list"], descendants: true, read: (ElementRef) }, { propertyName: "_snapContainerRef", first: true, predicate: ["snapRendererContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_snappedContainer", first: true, predicate: ["snapped"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div *ngIf=\"snap\" #snapped part=\"snapped-item\" class=\"ngvl__list-snapper\">\r\n <ng-container #snapRendererContainer></ng-container>\r\n</div>\r\n<div #container part=\"scroller\" class=\"ngvl__scroller\">\r\n <div [attr.aria-orientation]=\"orientation\" [attr.aria-activedescendant]=\"$focusedElement | async\" #list part=\"list\"\r\n 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: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
3213
3389
  }
3214
3390
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NgVirtualListComponent, decorators: [{
3215
3391
  type: Component,
@@ -3271,6 +3447,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
3271
3447
  type: Input
3272
3448
  }], direction: [{
3273
3449
  type: Input
3450
+ }], collectionMode: [{
3451
+ type: Input
3274
3452
  }], bufferSize: [{
3275
3453
  type: Input
3276
3454
  }], maxBufferSize: [{
@@ -3306,5 +3484,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
3306
3484
  * Generated bundle index. Do not edit.
3307
3485
  */
3308
3486
 
3309
- export { Directions, MethodsForSelecting, NgVirtualListComponent, NgVirtualListItemComponent, NgVirtualListModule, ScrollEvent, SnappingMethods, debounce, toggleClassName };
3487
+ export { CollectionModes, Directions, FocusAlignments, MethodsForSelecting, NgVirtualListComponent, NgVirtualListItemComponent, NgVirtualListModule, ScrollEvent, SnappingMethods, debounce, toggleClassName };
3310
3488
  //# sourceMappingURL=ng-virtual-list.mjs.map