ng-virtual-list 16.7.0 → 16.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +19 -16
  2. package/esm2022/lib/components/ng-virtual-list-item.component.mjs +28 -8
  3. package/esm2022/lib/const/index.mjs +2 -1
  4. package/esm2022/lib/models/index.mjs +1 -1
  5. package/esm2022/lib/models/item-config-map.model.mjs +2 -0
  6. package/esm2022/lib/models/render-item-config.model.mjs +1 -1
  7. package/esm2022/lib/ng-virtual-list.component.mjs +63 -26
  8. package/esm2022/lib/ng-virtual-list.service.mjs +46 -9
  9. package/esm2022/lib/utils/trackBox.mjs +22 -19
  10. package/fesm2022/ng-virtual-list.mjs +154 -56
  11. package/fesm2022/ng-virtual-list.mjs.map +1 -1
  12. package/lib/components/ng-virtual-list-item.component.d.ts +25 -5
  13. package/lib/const/index.d.ts +1 -0
  14. package/lib/models/index.d.ts +2 -2
  15. package/lib/models/item-config-map.model.d.ts +23 -0
  16. package/lib/models/render-item-config.model.d.ts +5 -1
  17. package/lib/ng-virtual-list.component.d.ts +25 -8
  18. package/lib/ng-virtual-list.service.d.ts +7 -0
  19. package/lib/utils/trackBox.d.ts +4 -4
  20. package/package.json +1 -1
  21. package/esm2020/lib/components/ng-virtual-list-item.component.mjs +0 -198
  22. package/esm2020/lib/const/index.mjs +0 -51
  23. package/esm2020/lib/enums/direction.mjs +0 -2
  24. package/esm2020/lib/enums/directions.mjs +0 -18
  25. package/esm2020/lib/enums/index.mjs +0 -5
  26. package/esm2020/lib/enums/method-for-selecting-types.mjs +0 -22
  27. package/esm2020/lib/enums/method-for-selecting.mjs +0 -2
  28. package/esm2020/lib/enums/methods-for-selecting.mjs +0 -22
  29. package/esm2020/lib/enums/snapping-method.mjs +0 -2
  30. package/esm2020/lib/enums/snapping-methods.mjs +0 -18
  31. package/esm2020/lib/models/base-virtual-list-item-component.mjs +0 -9
  32. package/esm2020/lib/models/collection.model.mjs +0 -3
  33. package/esm2020/lib/models/component.model.mjs +0 -2
  34. package/esm2020/lib/models/index.mjs +0 -2
  35. package/esm2020/lib/models/item.model.mjs +0 -2
  36. package/esm2020/lib/models/render-collection.model.mjs +0 -3
  37. package/esm2020/lib/models/render-item-config.model.mjs +0 -2
  38. package/esm2020/lib/models/render-item.model.mjs +0 -3
  39. package/esm2020/lib/models/scroll-direction.model.mjs +0 -2
  40. package/esm2020/lib/models/scroll-event.model.mjs +0 -2
  41. package/esm2020/lib/models/sticky-map.model.mjs +0 -2
  42. package/esm2020/lib/ng-virtual-list.component.mjs +0 -800
  43. package/esm2020/lib/ng-virtual-list.module.mjs +0 -20
  44. package/esm2020/lib/ng-virtual-list.service.mjs +0 -94
  45. package/esm2020/lib/types/id.mjs +0 -2
  46. package/esm2020/lib/types/index.mjs +0 -2
  47. package/esm2020/lib/types/rect.mjs +0 -2
  48. package/esm2020/lib/types/size.mjs +0 -2
  49. package/esm2020/lib/utils/browser.mjs +0 -3
  50. package/esm2020/lib/utils/buffer-interpolation.mjs +0 -27
  51. package/esm2020/lib/utils/cacheMap.mjs +0 -167
  52. package/esm2020/lib/utils/debounce.mjs +0 -31
  53. package/esm2020/lib/utils/disposableComponent.mjs +0 -29
  54. package/esm2020/lib/utils/eventEmitter.mjs +0 -106
  55. package/esm2020/lib/utils/index.mjs +0 -5
  56. package/esm2020/lib/utils/isDirection.mjs +0 -15
  57. package/esm2020/lib/utils/isMethodForSelecting.mjs +0 -18
  58. package/esm2020/lib/utils/scrollEvent.mjs +0 -42
  59. package/esm2020/lib/utils/snapping-method.mjs +0 -9
  60. package/esm2020/lib/utils/toggleClassName.mjs +0 -15
  61. package/esm2020/lib/utils/trackBox.mjs +0 -762
  62. package/esm2020/lib/utils/tracker.mjs +0 -143
  63. package/esm2020/ng-virtual-list.mjs +0 -5
  64. package/esm2020/public-api.mjs +0 -10
  65. package/esm2022/lib/models/sticky-map.model.mjs +0 -2
  66. package/fesm2015/ng-virtual-list.mjs +0 -2582
  67. package/fesm2015/ng-virtual-list.mjs.map +0 -1
  68. package/fesm2020/ng-virtual-list.mjs +0 -2586
  69. package/fesm2020/ng-virtual-list.mjs.map +0 -1
  70. package/lib/models/sticky-map.model.d.ts +0 -14
  71. package/lib/utils/disposableComponent.d.ts +0 -15
@@ -1,2582 +0,0 @@
1
- import * as i0 from '@angular/core';
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 as takeUntil$1, map, tap as tap$1 } from 'rxjs/operators';
4
- import { Subject, takeUntil, tap, BehaviorSubject as BehaviorSubject$1, combineLatest, filter, map as map$1, debounceTime, distinctUntilChanged, switchMap, of } from 'rxjs';
5
- import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
6
- import * as i2 from '@angular/common';
7
- import { CommonModule } from '@angular/common';
8
-
9
- /**
10
- * Axis of the arrangement of virtual list elements.
11
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/enums/directions.ts
12
- * @author Evgenii Grebennikov
13
- * @email djonnyx@gmail.com
14
- */
15
- var Directions;
16
- (function (Directions) {
17
- /**
18
- * Horizontal axis.
19
- */
20
- Directions["HORIZONTAL"] = "horizontal";
21
- /**
22
- * Vertical axis.
23
- */
24
- Directions["VERTICAL"] = "vertical";
25
- })(Directions || (Directions = {}));
26
-
27
- /**
28
- * Methods for selecting list items.
29
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/enums/methods-for-selecting.ts
30
- * @author Evgenii Grebennikov
31
- * @email djonnyx@gmail.com
32
- */
33
- var MethodsForSelecting;
34
- (function (MethodsForSelecting) {
35
- /**
36
- * List items are not selectable.
37
- */
38
- MethodsForSelecting["NONE"] = "none";
39
- /**
40
- * List items are selected one by one.
41
- */
42
- MethodsForSelecting["SELECT"] = "select";
43
- /**
44
- * Multiple selection of list items.
45
- */
46
- MethodsForSelecting["MULTI_SELECT"] = "multi-select";
47
- })(MethodsForSelecting || (MethodsForSelecting = {}));
48
-
49
- /**
50
- * Snapping method.
51
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/enums/snapping-method.ts
52
- * @author Evgenii Grebennikov
53
- * @email djonnyx@gmail.com
54
- */
55
- var SnappingMethods;
56
- (function (SnappingMethods) {
57
- /**
58
- * Normal group rendering.
59
- */
60
- SnappingMethods["NORMAL"] = "normal";
61
- /**
62
- * The group is rendered on a transparent background. List items below the group are not rendered.
63
- */
64
- SnappingMethods["ADVANCED"] = "advanced";
65
- })(SnappingMethods || (SnappingMethods = {}));
66
-
67
- const DEFAULT_ITEM_SIZE = 24;
68
- const DEFAULT_BUFFER_SIZE = 2;
69
- const DEFAULT_MAX_BUFFER_SIZE = 100;
70
- const DEFAULT_LIST_SIZE = 400;
71
- const DEFAULT_SNAP = false;
72
- const DEFAULT_ENABLED_BUFFER_OPTIMIZATION = false;
73
- const DEFAULT_DYNAMIC_SIZE = false;
74
- const TRACK_BY_PROPERTY_NAME = 'id';
75
- const DEFAULT_DIRECTION = Directions.VERTICAL;
76
- const DISPLAY_OBJECTS_LENGTH_MESUREMENT_ERROR = 1;
77
- const MAX_SCROLL_TO_ITERATIONS = 5;
78
- const DEFAULT_SNAPPING_METHOD = SnappingMethods.NORMAL;
79
- const DEFAULT_SELECT_METHOD = MethodsForSelecting.NONE;
80
- // presets
81
- const BEHAVIOR_AUTO = 'auto';
82
- const BEHAVIOR_INSTANT = 'instant';
83
- const BEHAVIOR_SMOOTH = 'smooth';
84
- const DISPLAY_BLOCK = 'block';
85
- const DISPLAY_NONE = 'none';
86
- const OPACITY_0 = '0';
87
- const OPACITY_100 = '100';
88
- const VISIBILITY_VISIBLE = 'visible';
89
- const VISIBILITY_HIDDEN = 'hidden';
90
- const SIZE_100_PERSENT = '100%';
91
- const SIZE_AUTO = 'auto';
92
- const POSITION_ABSOLUTE = 'absolute';
93
- const POSITION_STICKY = 'sticky';
94
- const TRANSLATE_3D = 'translate3d';
95
- const ZEROS_TRANSLATE_3D = `${TRANSLATE_3D}(0,0,0)`;
96
- const HIDDEN_ZINDEX = '-1';
97
- const DEFAULT_ZINDEX = '0';
98
- const TOP_PROP_NAME = 'top';
99
- const LEFT_PROP_NAME = 'left';
100
- const X_PROP_NAME = 'x';
101
- const Y_PROP_NAME = 'y';
102
- const WIDTH_PROP_NAME = 'width';
103
- const HEIGHT_PROP_NAME = 'height';
104
- const PX = 'px';
105
- const SCROLL = 'scroll';
106
- const SCROLL_END = 'scrollend';
107
- const CLASS_LIST_VERTICAL = 'vertical';
108
- const CLASS_LIST_HORIZONTAL = 'horizontal';
109
- // styles
110
- const PART_DEFAULT_ITEM = 'item';
111
- const PART_ITEM_ODD = ' odd';
112
- const PART_ITEM_EVEN = ' even';
113
- const PART_ITEM_SNAPPED = ' snapped';
114
- const PART_ITEM_SELECTED = ' selected';
115
-
116
- /**
117
- * Virtual List Item Interface
118
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/models/base-virtual-list-item-component.ts
119
- * @author Evgenii Grebennikov
120
- * @email djonnyx@gmail.com
121
- */
122
- class BaseVirtualListItemComponent {
123
- }
124
-
125
- /**
126
- * Methods for selecting list items.
127
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/enums/method-for-selecting-types.ts
128
- * @author Evgenii Grebennikov
129
- * @email djonnyx@gmail.com
130
- */
131
- var MethodsForSelectingTypes;
132
- (function (MethodsForSelectingTypes) {
133
- /**
134
- * List items are not selectable.
135
- */
136
- MethodsForSelectingTypes[MethodsForSelectingTypes["NONE"] = 0] = "NONE";
137
- /**
138
- * List items are selected one by one.
139
- */
140
- MethodsForSelectingTypes[MethodsForSelectingTypes["SELECT"] = 1] = "SELECT";
141
- /**
142
- * Multiple selection of list items.
143
- */
144
- MethodsForSelectingTypes[MethodsForSelectingTypes["MULTI_SELECT"] = 2] = "MULTI_SELECT";
145
- })(MethodsForSelectingTypes || (MethodsForSelectingTypes = {}));
146
-
147
- class NgVirtualListService {
148
- set methodOfSelecting(v) {
149
- this._$methodOfSelecting.next(v);
150
- }
151
- constructor() {
152
- this._$unsubscribe = new Subject();
153
- this._nextComponentId = 0;
154
- this._$itemClick = new Subject();
155
- this.$itemClick = this._$itemClick.asObservable();
156
- this._$selectedIds = new BehaviorSubject(undefined);
157
- this.$selectedIds = this._$selectedIds.asObservable();
158
- this._$methodOfSelecting = new BehaviorSubject(0);
159
- this.$methodOfSelecting = this._$methodOfSelecting.asObservable();
160
- this._$methodOfSelecting.pipe(takeUntil(this._$unsubscribe), tap(v => {
161
- switch (v) {
162
- case MethodsForSelectingTypes.SELECT: {
163
- const curr = this._$selectedIds.getValue();
164
- if (typeof curr !== 'number' && typeof curr !== 'string') {
165
- this._$selectedIds.next(undefined);
166
- }
167
- break;
168
- }
169
- case MethodsForSelectingTypes.MULTI_SELECT: {
170
- if (!Array.isArray(this._$selectedIds.getValue())) {
171
- this._$selectedIds.next([]);
172
- }
173
- break;
174
- }
175
- case MethodsForSelectingTypes.NONE:
176
- default: {
177
- this._$selectedIds.next(undefined);
178
- break;
179
- }
180
- }
181
- })).subscribe();
182
- }
183
- setSelectedIds(ids) {
184
- this._$selectedIds.next(ids);
185
- }
186
- itemClick(data) {
187
- this._$itemClick.next(data);
188
- if (data) {
189
- switch (this._$methodOfSelecting.getValue()) {
190
- case MethodsForSelectingTypes.SELECT: {
191
- const curr = this._$selectedIds.getValue();
192
- this._$selectedIds.next(curr !== (data === null || data === void 0 ? void 0 : data.id) ? data === null || data === void 0 ? void 0 : data.id : undefined);
193
- break;
194
- }
195
- case MethodsForSelectingTypes.MULTI_SELECT: {
196
- const curr = [...(this._$selectedIds.getValue() || [])], index = curr.indexOf(data.id);
197
- if (index > -1) {
198
- curr.splice(index, 1);
199
- this._$selectedIds.next(curr);
200
- }
201
- else {
202
- this._$selectedIds.next([...curr, data.id]);
203
- }
204
- break;
205
- }
206
- case MethodsForSelectingTypes.NONE:
207
- default: {
208
- this._$selectedIds.next(undefined);
209
- }
210
- }
211
- }
212
- }
213
- initialize(trackBox) {
214
- this._trackBox = trackBox;
215
- }
216
- generateComponentId() {
217
- return this._nextComponentId = this._nextComponentId === Number.MAX_SAFE_INTEGER
218
- ? 0 : this._nextComponentId + 1;
219
- }
220
- destroy() {
221
- if (this._$unsubscribe) {
222
- this._$unsubscribe.next();
223
- this._$unsubscribe.complete();
224
- }
225
- }
226
- }
227
- NgVirtualListService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
228
- NgVirtualListService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListService, providedIn: 'root' });
229
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListService, decorators: [{
230
- type: Injectable,
231
- args: [{
232
- providedIn: 'root'
233
- }]
234
- }], ctorParameters: function () { return []; } });
235
-
236
- const ATTR_AREA_SELECTED = 'area-selected';
237
- /**
238
- * Virtual list item component
239
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/components/ng-virtual-list-item.component.ts
240
- * @author Evgenii Grebennikov
241
- * @email djonnyx@gmail.com
242
- */
243
- class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
244
- get id() {
245
- return this._id;
246
- }
247
- get part() { return this._part; }
248
- set item(v) {
249
- if (this.data === v) {
250
- return;
251
- }
252
- this.data = v;
253
- this.updatePartStr(v, this._isSelected);
254
- this.updateConfig(v);
255
- this.update();
256
- this._$data.next(v);
257
- this._cdr.detectChanges();
258
- }
259
- set regularLength(v) {
260
- if (this._regularLength === v) {
261
- return;
262
- }
263
- this._regularLength = v;
264
- this.update();
265
- this._cdr.detectChanges();
266
- }
267
- get item() {
268
- return this.data;
269
- }
270
- get itemId() {
271
- var _a;
272
- return (_a = this.data) === null || _a === void 0 ? void 0 : _a.id;
273
- }
274
- set renderer(v) {
275
- if (this.itemRenderer === v) {
276
- return;
277
- }
278
- this.itemRenderer = v;
279
- this._cdr.markForCheck();
280
- }
281
- get element() {
282
- return this._elementRef.nativeElement;
283
- }
284
- constructor(_cdr, _elementRef, _service) {
285
- super();
286
- this._cdr = _cdr;
287
- this._elementRef = _elementRef;
288
- this._service = _service;
289
- this._$unsubscribe = new Subject();
290
- this._part = PART_DEFAULT_ITEM;
291
- this._isSelected = false;
292
- this.config = new BehaviorSubject$1({});
293
- this.regular = false;
294
- this._$data = new BehaviorSubject$1(this.data);
295
- this.$data = this._$data.asObservable();
296
- this._regularLength = SIZE_100_PERSENT;
297
- this._id = this._service.generateComponentId();
298
- const $data = this.$data;
299
- combineLatest([$data, this._service.$methodOfSelecting, this._service.$selectedIds]).pipe(takeUntil$1(this._$unsubscribe), map(([, m, ids]) => ({ method: m, ids })), tap$1(({ method, ids }) => {
300
- switch (method) {
301
- case MethodsForSelectingTypes.SELECT: {
302
- const id = ids, isSelected = id === this.itemId;
303
- this._elementRef.nativeElement.setAttribute(ATTR_AREA_SELECTED, String(isSelected));
304
- this._isSelected = isSelected;
305
- break;
306
- }
307
- case MethodsForSelectingTypes.MULTI_SELECT: {
308
- const actualIds = ids, isSelected = this.itemId !== undefined && actualIds && actualIds.includes(this.itemId);
309
- this._elementRef.nativeElement.setAttribute(ATTR_AREA_SELECTED, String(isSelected));
310
- this._isSelected = isSelected;
311
- break;
312
- }
313
- case MethodsForSelectingTypes.NONE:
314
- default: {
315
- this._elementRef.nativeElement.removeAttribute(ATTR_AREA_SELECTED);
316
- this._isSelected = false;
317
- break;
318
- }
319
- }
320
- this.updatePartStr(this.data, this._isSelected);
321
- this.updateConfig(this.data);
322
- })).subscribe();
323
- }
324
- updateConfig(v) {
325
- this.config.next(Object.assign(Object.assign({}, (v === null || v === void 0 ? void 0 : v.config) || {}), { selected: this._isSelected }));
326
- }
327
- update() {
328
- const data = this.data, regular = this.regular, length = this._regularLength;
329
- if (data) {
330
- const styles = this._elementRef.nativeElement.style;
331
- styles.zIndex = data.config.zIndex;
332
- if (data.config.snapped) {
333
- styles.transform = data.config.sticky === 1 ? ZEROS_TRANSLATE_3D : `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.x}${PX}, ${data.config.isVertical ? data.measures.y : 0}${PX} , 0)`;
334
- ;
335
- if (!data.config.isSnappingMethodAdvanced) {
336
- styles.position = POSITION_STICKY;
337
- }
338
- }
339
- else {
340
- styles.position = POSITION_ABSOLUTE;
341
- if (regular) {
342
- styles.transform = `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.delta}${PX}, ${data.config.isVertical ? data.measures.delta : 0}${PX} , 0)`;
343
- }
344
- else {
345
- styles.transform = `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.x}${PX}, ${data.config.isVertical ? data.measures.y : 0}${PX} , 0)`;
346
- }
347
- }
348
- styles.height = data.config.isVertical ? data.config.dynamic ? SIZE_AUTO : `${data.measures.height}${PX}` : regular ? length : SIZE_100_PERSENT;
349
- styles.width = data.config.isVertical ? regular ? length : SIZE_100_PERSENT : data.config.dynamic ? SIZE_AUTO : `${data.measures.width}${PX}`;
350
- }
351
- this._cdr.markForCheck();
352
- }
353
- updatePartStr(v, isSelected) {
354
- let odd = false;
355
- if ((v === null || v === void 0 ? void 0 : v.index) !== undefined) {
356
- odd = v.index % 2 === 0;
357
- }
358
- let part = PART_DEFAULT_ITEM;
359
- part += odd ? PART_ITEM_ODD : PART_ITEM_EVEN;
360
- if (v ? v.config.snapped : false) {
361
- part += PART_ITEM_SNAPPED;
362
- }
363
- if (isSelected) {
364
- part += PART_ITEM_SELECTED;
365
- }
366
- this._part = part;
367
- }
368
- getBounds() {
369
- const el = this._elementRef.nativeElement, { width, height } = el.getBoundingClientRect();
370
- return { width, height };
371
- }
372
- show() {
373
- var _a, _b, _c;
374
- const styles = this._elementRef.nativeElement.style;
375
- if (this.regular) {
376
- if (styles.display === DISPLAY_BLOCK) {
377
- return;
378
- }
379
- styles.display = DISPLAY_BLOCK;
380
- }
381
- else {
382
- if (styles.visibility === VISIBILITY_VISIBLE) {
383
- return;
384
- }
385
- styles.visibility = VISIBILITY_VISIBLE;
386
- }
387
- styles.zIndex = (_c = (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.zIndex) !== null && _c !== void 0 ? _c : DEFAULT_ZINDEX;
388
- }
389
- hide() {
390
- const styles = this._elementRef.nativeElement.style;
391
- if (this.regular) {
392
- if (styles.display === DISPLAY_NONE) {
393
- return;
394
- }
395
- styles.display = DISPLAY_NONE;
396
- }
397
- else {
398
- if (styles.visibility === VISIBILITY_HIDDEN) {
399
- return;
400
- }
401
- styles.visibility = VISIBILITY_HIDDEN;
402
- }
403
- styles.position = POSITION_ABSOLUTE;
404
- styles.transform = ZEROS_TRANSLATE_3D;
405
- styles.zIndex = HIDDEN_ZINDEX;
406
- }
407
- onClickHandler() {
408
- this._service.itemClick(this.data);
409
- }
410
- ngOnDestroy() {
411
- if (this._$unsubscribe) {
412
- this._$unsubscribe.next();
413
- this._$unsubscribe.complete();
414
- }
415
- }
416
- }
417
- NgVirtualListItemComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListItemComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: NgVirtualListService }], target: i0.ɵɵFactoryTarget.Component });
418
- NgVirtualListItemComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", 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\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut}\" (click)=\"onClickHandler()\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, 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}\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 });
419
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
420
- type: Component,
421
- args: [{ selector: 'ng-virtual-list-item', host: {
422
- 'class': 'ngvl__item',
423
- 'role': 'listitem',
424
- }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"data\">\r\n <div #listItem [part]=\"part\" class=\"ngvl-item__container\" [ngClass]=\"{'snapped': data.config.snapped,\r\n 'snapped-out': data.config.snappedOut}\" (click)=\"onClickHandler()\">\r\n <ng-container *ngIf=\"itemRenderer\">\r\n <ng-container [ngTemplateOutlet]=\"itemRenderer\"\r\n [ngTemplateOutletContext]=\"{data: data.data || {}, 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}\n"] }]
425
- }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: NgVirtualListService }]; } });
426
-
427
- /**
428
- * Simple debounce function.
429
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/debounce.ts
430
- * @author Evgenii Grebennikov
431
- * @email djonnyx@gmail.com
432
- */
433
- const debounce = (cb, debounceTime = 0) => {
434
- let timeout;
435
- const dispose = () => {
436
- if (timeout !== undefined) {
437
- clearTimeout(timeout);
438
- }
439
- };
440
- const execute = (...args) => {
441
- dispose();
442
- timeout = setTimeout(() => {
443
- cb(...args);
444
- }, debounceTime);
445
- };
446
- return {
447
- /**
448
- * Call handling method
449
- */
450
- execute,
451
- /**
452
- * Method of destroying handlers
453
- */
454
- dispose,
455
- };
456
- };
457
-
458
- /**
459
- * Switch css classes
460
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/toggleClassName.ts
461
- * @author Evgenii Grebennikov
462
- * @email djonnyx@gmail.com
463
- */
464
- const toggleClassName = (el, className, removeClassName) => {
465
- if (!el.classList.contains(className)) {
466
- el.classList.add(className);
467
- }
468
- if (removeClassName) {
469
- el.classList.remove(removeClassName);
470
- }
471
- };
472
-
473
- /**
474
- * Scroll event.
475
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/scrollEvent.ts
476
- * @author Evgenii Grebennikov
477
- * @email djonnyx@gmail.com
478
- */
479
- class ScrollEvent {
480
- get direction() { return this._direction; }
481
- get scrollSize() { return this._scrollSize; }
482
- get scrollWeight() { return this._scrollWeight; }
483
- get isVertical() { return this._isVertical; }
484
- get listSize() { return this._listSize; }
485
- get size() { return this._size; }
486
- get isStart() { return this._isStart; }
487
- get isEnd() { return this._isEnd; }
488
- get delta() { return this._delta; }
489
- get scrollDelta() { return this._scrollDelta; }
490
- constructor(params) {
491
- this._direction = 1;
492
- this._scrollSize = 0;
493
- this._scrollWeight = 0;
494
- this._isVertical = true;
495
- this._listSize = 0;
496
- this._size = 0;
497
- this._isStart = true;
498
- this._isEnd = false;
499
- this._delta = 0;
500
- this._scrollDelta = 0;
501
- const { direction, isVertical, container, list, delta, scrollDelta } = params;
502
- this._direction = direction;
503
- this._isVertical = isVertical;
504
- this._scrollSize = isVertical ? container.scrollTop : container.scrollLeft;
505
- this._scrollWeight = isVertical ? container.scrollHeight : container.scrollWidth;
506
- this._listSize = isVertical ? list.offsetHeight : list.offsetWidth;
507
- this._size = isVertical ? container.offsetHeight : container.offsetWidth;
508
- this._isEnd = (this._scrollSize + this._size) === this._scrollWeight;
509
- this._delta = delta;
510
- this._scrollDelta = scrollDelta;
511
- this._isStart = this._scrollSize === 0;
512
- }
513
- }
514
-
515
- /**
516
- * Simple event emitter
517
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/eventEmitter.ts
518
- * @author Evgenii Grebennikov
519
- * @email djonnyx@gmail.com
520
- */
521
- class EventEmitter {
522
- constructor() {
523
- this._listeners = {};
524
- this._disposed = false;
525
- }
526
- /**
527
- * Emits the event
528
- */
529
- dispatch(event, ...args) {
530
- const ctx = this;
531
- const listeners = this._listeners[event];
532
- if (Array.isArray(listeners)) {
533
- for (let i = 0, l = listeners.length; i < l; i++) {
534
- const listener = listeners[i];
535
- if (listener) {
536
- listener.apply(ctx, args);
537
- }
538
- }
539
- }
540
- }
541
- /**
542
- * Emits the event async
543
- */
544
- dispatchAsync(event, ...args) {
545
- queueMicrotask(() => {
546
- if (this._disposed) {
547
- return;
548
- }
549
- this.dispatch(event, ...args);
550
- });
551
- }
552
- /**
553
- * Returns true if the event listener is already subscribed.
554
- */
555
- hasEventListener(eventName, handler) {
556
- const event = eventName;
557
- if (this._listeners.hasOwnProperty(event)) {
558
- const listeners = this._listeners[event];
559
- const index = listeners.findIndex(v => v === handler);
560
- if (index > -1) {
561
- return true;
562
- }
563
- }
564
- return false;
565
- }
566
- /**
567
- * Add event listener
568
- */
569
- addEventListener(eventName, handler) {
570
- const event = eventName;
571
- if (!this._listeners.hasOwnProperty(event)) {
572
- this._listeners[event] = [];
573
- }
574
- this._listeners[event].push(handler);
575
- }
576
- /**
577
- * Remove event listener
578
- */
579
- removeEventListener(eventName, handler) {
580
- const event = eventName;
581
- if (!this._listeners.hasOwnProperty(event)) {
582
- return;
583
- }
584
- const listeners = this._listeners[event], index = listeners.findIndex(v => v === handler);
585
- if (index > -1) {
586
- listeners.splice(index, 1);
587
- if (listeners.length === 0) {
588
- delete this._listeners[event];
589
- }
590
- }
591
- }
592
- /**
593
- * Remove all listeners
594
- */
595
- removeAllListeners() {
596
- const events = Object.keys(this._listeners);
597
- while (events.length > 0) {
598
- const event = events.pop();
599
- if (event) {
600
- const listeners = this._listeners[event];
601
- if (Array.isArray(listeners)) {
602
- while (listeners.length > 0) {
603
- const listener = listeners.pop();
604
- if (listener) {
605
- this.removeEventListener(event, listener);
606
- }
607
- }
608
- }
609
- }
610
- }
611
- }
612
- /**
613
- * Method of destroying handlers
614
- */
615
- dispose() {
616
- this._disposed = true;
617
- this.removeAllListeners();
618
- }
619
- }
620
-
621
- class CMap {
622
- constructor(dict) {
623
- this._dict = {};
624
- if (dict) {
625
- this._dict = Object.assign({}, dict._dict);
626
- }
627
- }
628
- get(key) {
629
- const k = String(key);
630
- return this._dict[k];
631
- }
632
- set(key, value) {
633
- const k = String(key);
634
- this._dict[k] = value;
635
- return this;
636
- }
637
- has(key) {
638
- return this._dict.hasOwnProperty(String(key));
639
- }
640
- delete(key) {
641
- const k = String(key);
642
- delete this._dict[k];
643
- }
644
- clear() {
645
- this._dict = {};
646
- }
647
- }
648
- const CACHE_BOX_CHANGE_EVENT_NAME = 'change';
649
- const MAX_SCROLL_DIRECTION_POOL = 50, CLEAR_SCROLL_DIRECTION_TO = 10, DIR_BACK = '-1', DIR_NONE = '0', DIR_FORWARD = '1';
650
- /**
651
- * Cache map.
652
- * Emits a change event on each mutation.
653
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/cacheMap.ts
654
- * @author Evgenii Grebennikov
655
- * @email djonnyx@gmail.com
656
- */
657
- class CacheMap extends EventEmitter {
658
- get delta() {
659
- return this._delta;
660
- }
661
- set deltaDirection(v) {
662
- this._deltaDirection = v;
663
- this._scrollDirection = this.calcScrollDirection(v);
664
- }
665
- get deltaDirection() {
666
- return this._deltaDirection;
667
- }
668
- get scrollDirection() {
669
- return this._scrollDirection;
670
- }
671
- get version() {
672
- return this._version;
673
- }
674
- constructor() {
675
- super();
676
- this._map = new CMap();
677
- this._snapshot = new CMap();
678
- this._version = 0;
679
- this._previousVersion = this._version;
680
- this._delta = 0;
681
- this._deltaDirection = 0;
682
- this._scrollDirectionCache = [];
683
- this._scrollDirection = 0;
684
- this._clearScrollDirectionDebounce = debounce(() => {
685
- while (this._scrollDirectionCache.length > CLEAR_SCROLL_DIRECTION_TO) {
686
- this._scrollDirectionCache.shift();
687
- }
688
- }, 10);
689
- this.lifeCircle();
690
- }
691
- changesDetected() {
692
- return this._version !== this._previousVersion;
693
- }
694
- stopLifeCircle() {
695
- clearTimeout(this._lifeCircleTimeout);
696
- }
697
- nextTick(cb) {
698
- if (this._disposed) {
699
- return;
700
- }
701
- this._lifeCircleTimeout = setTimeout(() => {
702
- cb();
703
- });
704
- return this._lifeCircleTimeout;
705
- }
706
- lifeCircle() {
707
- this.fireChangeIfNeed();
708
- this.lifeCircleDo();
709
- }
710
- lifeCircleDo() {
711
- this._previousVersion = this._version;
712
- this.nextTick(() => {
713
- this.lifeCircle();
714
- });
715
- }
716
- clearScrollDirectionCache() {
717
- this._clearScrollDirectionDebounce.execute();
718
- }
719
- calcScrollDirection(v) {
720
- while (this._scrollDirectionCache.length >= MAX_SCROLL_DIRECTION_POOL) {
721
- this._scrollDirectionCache.shift();
722
- }
723
- this._scrollDirectionCache.push(v);
724
- const dict = { [DIR_BACK]: 0, [DIR_NONE]: 0, [DIR_FORWARD]: 0 };
725
- for (let i = 0, l = this._scrollDirectionCache.length, li = l - 1; i < l; i++) {
726
- const dir = String(this._scrollDirectionCache[i]);
727
- dict[dir] += 1;
728
- if (i === li) {
729
- for (let d in dict) {
730
- if (d === String(v)) {
731
- continue;
732
- }
733
- dict[d] -= 1;
734
- }
735
- }
736
- }
737
- if (dict[DIR_BACK] > dict[DIR_NONE] && dict[DIR_BACK] > dict[DIR_FORWARD]) {
738
- return -1;
739
- }
740
- else if (dict[DIR_FORWARD] > dict[DIR_BACK] && dict[DIR_FORWARD] > dict[DIR_NONE]) {
741
- return 1;
742
- }
743
- return 0;
744
- }
745
- bumpVersion() {
746
- if (this.changesDetected()) {
747
- return;
748
- }
749
- const v = this._version === Number.MAX_SAFE_INTEGER ? 0 : this._version + 1;
750
- this._version = v;
751
- }
752
- fireChangeIfNeed() {
753
- if (this.changesDetected()) {
754
- this.dispatch(CACHE_BOX_CHANGE_EVENT_NAME, this.version);
755
- }
756
- }
757
- set(id, bounds) {
758
- if (this._map.has(id)) {
759
- const b = this._map.get(id), bb = bounds;
760
- if (b.width === bb.width && b.height === bb.height) {
761
- return this._map;
762
- }
763
- return this._map;
764
- }
765
- const v = this._map.set(id, bounds);
766
- this.bumpVersion();
767
- return v;
768
- }
769
- has(id) {
770
- return this._map.has(id);
771
- }
772
- get(id) {
773
- return this._map.get(id);
774
- }
775
- snapshot() {
776
- this._snapshot = new CMap(this._map);
777
- }
778
- dispose() {
779
- super.dispose();
780
- this.stopLifeCircle();
781
- this._snapshot.clear();
782
- this._map.clear();
783
- }
784
- }
785
-
786
- /**
787
- * Tracks display items by property
788
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/tracker.ts
789
- * @author Evgenii Grebennikov
790
- * @email djonnyx@gmail.com
791
- */
792
- class Tracker {
793
- set displayObjectIndexMapById(v) {
794
- if (this._displayObjectIndexMapById === v) {
795
- return;
796
- }
797
- this._displayObjectIndexMapById = v;
798
- }
799
- get displayObjectIndexMapById() {
800
- return this._displayObjectIndexMapById;
801
- }
802
- get trackMap() {
803
- return this._trackMap;
804
- }
805
- set trackingPropertyName(v) {
806
- this._trackingPropertyName = v;
807
- }
808
- constructor(trackingPropertyName) {
809
- /**
810
- * display objects dictionary of indexes by id
811
- */
812
- this._displayObjectIndexMapById = {};
813
- /**
814
- * Dictionary displayItems propertyNameId by items propertyNameId
815
- */
816
- this._trackMap = new CMap();
817
- this._trackingPropertyName = trackingPropertyName;
818
- }
819
- /**
820
- * tracking by propName
821
- */
822
- track(items, components, snapedComponent, direction) {
823
- var _a;
824
- if (!items) {
825
- return;
826
- }
827
- const idPropName = this._trackingPropertyName, untrackedItems = [...components], newTrackItems = [], isDown = direction === 0 || direction === 1;
828
- let isRegularSnapped = false;
829
- for (let i = isDown ? 0 : items.length - 1, l = isDown ? items.length : 0; isDown ? i < l : i >= l; isDown ? i++ : i--) {
830
- const item = items[i], itemTrackingProperty = item[idPropName];
831
- if (this._trackMap) {
832
- if (this._trackMap.has(itemTrackingProperty)) {
833
- const diId = this._trackMap.get(itemTrackingProperty), compIndex = this._displayObjectIndexMapById[diId], comp = components[compIndex];
834
- const compId = (_a = comp === null || comp === void 0 ? void 0 : comp.instance) === null || _a === void 0 ? void 0 : _a.id;
835
- if (comp !== undefined && compId === diId) {
836
- const indexByUntrackedItems = untrackedItems.findIndex(v => {
837
- return v.instance.id === compId;
838
- });
839
- if (indexByUntrackedItems > -1) {
840
- if (snapedComponent) {
841
- if (item['config']['snapped'] || item['config']['snappedOut']) {
842
- isRegularSnapped = true;
843
- snapedComponent.instance.item = item;
844
- snapedComponent.instance.show();
845
- }
846
- }
847
- comp.instance.item = item;
848
- if (snapedComponent) {
849
- if (item['config']['snapped'] || item['config']['snappedOut']) {
850
- comp.instance.hide();
851
- }
852
- else {
853
- comp.instance.show();
854
- }
855
- }
856
- else {
857
- comp.instance.show();
858
- }
859
- untrackedItems.splice(indexByUntrackedItems, 1);
860
- continue;
861
- }
862
- }
863
- this._trackMap.delete(itemTrackingProperty);
864
- }
865
- }
866
- if (untrackedItems.length > 0) {
867
- newTrackItems.push(item);
868
- }
869
- }
870
- for (let i = 0, l = newTrackItems.length; i < l; i++) {
871
- const item = newTrackItems[i], itemTrackingProperty = item[idPropName];
872
- if (untrackedItems.length > 0) {
873
- const comp = untrackedItems.shift(), item = items[i];
874
- if (comp) {
875
- if (snapedComponent) {
876
- if (item['config']['snapped'] || item['config']['snappedOut']) {
877
- isRegularSnapped = true;
878
- snapedComponent.instance.item = item;
879
- snapedComponent.instance.show();
880
- }
881
- }
882
- comp.instance.item = item;
883
- if (snapedComponent) {
884
- if (item['config']['snapped'] || item['config']['snappedOut']) {
885
- comp.instance.hide();
886
- }
887
- else {
888
- comp.instance.show();
889
- }
890
- }
891
- else {
892
- comp.instance.show();
893
- }
894
- if (this._trackMap) {
895
- this._trackMap.set(itemTrackingProperty, comp.instance.id);
896
- }
897
- }
898
- }
899
- }
900
- if (untrackedItems.length) {
901
- for (let i = 0, l = untrackedItems.length; i < l; i++) {
902
- const comp = untrackedItems[i];
903
- comp.instance.hide();
904
- }
905
- }
906
- if (!isRegularSnapped) {
907
- if (snapedComponent) {
908
- snapedComponent.instance.item = null;
909
- snapedComponent.instance.hide();
910
- }
911
- }
912
- }
913
- untrackComponentByIdProperty(component) {
914
- if (!component) {
915
- return;
916
- }
917
- const propertyIdName = this._trackingPropertyName;
918
- if (this._trackMap && component[propertyIdName] !== undefined) {
919
- this._trackMap.delete(propertyIdName);
920
- }
921
- }
922
- dispose() {
923
- if (this._trackMap) {
924
- this._trackMap.clear();
925
- }
926
- }
927
- }
928
-
929
- const DEFAULT_EXTRA = {
930
- extremumThreshold: 2,
931
- bufferSize: 10,
932
- };
933
- const bufferInterpolation = (currentBufferValue, array, value, extra) => {
934
- const { extremumThreshold = DEFAULT_EXTRA.extremumThreshold, bufferSize = DEFAULT_EXTRA.bufferSize, } = extra !== null && extra !== void 0 ? extra : DEFAULT_EXTRA;
935
- if (currentBufferValue < value) {
936
- let i = 0;
937
- while (i < extremumThreshold) {
938
- array.push(value);
939
- i++;
940
- }
941
- }
942
- else {
943
- array.push(value);
944
- }
945
- while (array.length >= bufferSize) {
946
- array.shift();
947
- }
948
- const l = array.length;
949
- let buffer = 0;
950
- for (let i = 0; i < l; i++) {
951
- buffer += array[i];
952
- }
953
- return Math.ceil(buffer / l);
954
- };
955
-
956
- const TRACK_BOX_CHANGE_EVENT_NAME = 'change';
957
- var ItemDisplayMethods;
958
- (function (ItemDisplayMethods) {
959
- ItemDisplayMethods[ItemDisplayMethods["CREATE"] = 0] = "CREATE";
960
- ItemDisplayMethods[ItemDisplayMethods["UPDATE"] = 1] = "UPDATE";
961
- ItemDisplayMethods[ItemDisplayMethods["DELETE"] = 2] = "DELETE";
962
- ItemDisplayMethods[ItemDisplayMethods["NOT_CHANGED"] = 3] = "NOT_CHANGED";
963
- })(ItemDisplayMethods || (ItemDisplayMethods = {}));
964
- const DEFAULT_BUFFER_EXTREMUM_THRESHOLD = 15, DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH = 30, DEFAULT_RESET_BUFFER_SIZE_TIMEOUT = 10000;
965
- /**
966
- * An object that performs tracking, calculations and caching.
967
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/trackBox.ts
968
- * @author Evgenii Grebennikov
969
- * @email djonnyx@gmail.com
970
- */
971
- class TrackBox extends CacheMap {
972
- set items(v) {
973
- if (this._items === v) {
974
- return;
975
- }
976
- this._items = v;
977
- }
978
- set displayComponents(v) {
979
- if (this._displayComponents === v) {
980
- return;
981
- }
982
- this._displayComponents = v;
983
- }
984
- set snapedDisplayComponent(v) {
985
- if (this._snapedDisplayComponent === v) {
986
- return;
987
- }
988
- this._snapedDisplayComponent = v;
989
- }
990
- set isSnappingMethodAdvanced(v) {
991
- if (this._isSnappingMethodAdvanced === v) {
992
- return;
993
- }
994
- this._isSnappingMethodAdvanced = v;
995
- }
996
- /**
997
- * Set the trackBy property
998
- */
999
- set trackingPropertyName(v) {
1000
- this._trackingPropertyName = this._tracker.trackingPropertyName = v;
1001
- }
1002
- constructor(trackingPropertyName) {
1003
- super();
1004
- this._isSnappingMethodAdvanced = false;
1005
- this._trackingPropertyName = TRACK_BY_PROPERTY_NAME;
1006
- this._deletedItemsMap = {};
1007
- this._crudDetected = false;
1008
- this._previousTotalSize = 0;
1009
- this._scrollDelta = 0;
1010
- this.isAdaptiveBuffer = true;
1011
- this._bufferSequenceExtraThreshold = DEFAULT_BUFFER_EXTREMUM_THRESHOLD;
1012
- this._maxBufferSequenceLength = DEFAULT_MAX_BUFFER_SEQUENCE_LENGTH;
1013
- this._bufferSizeSequence = [];
1014
- this._bufferSize = 0;
1015
- this._defaultBufferSize = 0;
1016
- this._maxBufferSize = this._defaultBufferSize;
1017
- this._resetBufferSizeTimeout = DEFAULT_RESET_BUFFER_SIZE_TIMEOUT;
1018
- this._previousScrollSize = 0;
1019
- this._trackingPropertyName = trackingPropertyName;
1020
- this.initialize();
1021
- }
1022
- initialize() {
1023
- this._tracker = new Tracker(this._trackingPropertyName);
1024
- }
1025
- set(id, bounds) {
1026
- if (this._map.has(id)) {
1027
- const b = this._map.get(id);
1028
- if ((b === null || b === void 0 ? void 0 : b.width) === bounds.width && b.height === bounds.height) {
1029
- return this._map;
1030
- }
1031
- }
1032
- const v = this._map.set(id, bounds);
1033
- this.bumpVersion();
1034
- return v;
1035
- }
1036
- get crudDetected() { return this._crudDetected; }
1037
- fireChangeIfNeed() {
1038
- if (this.changesDetected()) {
1039
- this.dispatch(TRACK_BOX_CHANGE_EVENT_NAME, this._version);
1040
- }
1041
- }
1042
- get scrollDelta() { return this._scrollDelta; }
1043
- get bufferSize() { return this._bufferSize; }
1044
- lifeCircle() {
1045
- this.fireChangeIfNeed();
1046
- this.lifeCircleDo();
1047
- }
1048
- /**
1049
- * Scans the collection for deleted items and flushes the deleted item cache.
1050
- */
1051
- resetCollection(currentCollection, itemSize) {
1052
- if (currentCollection !== undefined && currentCollection !== null && currentCollection === this._previousCollection) {
1053
- console.warn('Attention! The collection must be immutable.');
1054
- return;
1055
- }
1056
- this.updateCache(this._previousCollection, currentCollection, itemSize);
1057
- this._previousCollection = currentCollection;
1058
- }
1059
- /**
1060
- * Update the cache of items from the list
1061
- */
1062
- updateCache(previousCollection, currentCollection, itemSize) {
1063
- let crudDetected = false;
1064
- if (!currentCollection || currentCollection.length === 0) {
1065
- if (previousCollection) {
1066
- // deleted
1067
- for (let i = 0, l = previousCollection.length; i < l; i++) {
1068
- const item = previousCollection[i], id = item.id;
1069
- crudDetected = true;
1070
- if (this._map.has(id)) {
1071
- this._map.delete(id);
1072
- }
1073
- }
1074
- }
1075
- return;
1076
- }
1077
- if (!previousCollection || previousCollection.length === 0) {
1078
- if (currentCollection) {
1079
- // added
1080
- for (let i = 0, l = currentCollection.length; i < l; i++) {
1081
- crudDetected = true;
1082
- const item = currentCollection[i], id = item.id;
1083
- this._map.set(id, { width: itemSize, height: itemSize, method: ItemDisplayMethods.CREATE });
1084
- }
1085
- }
1086
- return;
1087
- }
1088
- const collectionDict = {};
1089
- for (let i = 0, l = currentCollection.length; i < l; i++) {
1090
- const item = currentCollection[i];
1091
- if (item) {
1092
- collectionDict[item.id] = item;
1093
- }
1094
- }
1095
- const notChangedMap = {}, deletedMap = {}, deletedItemsMap = {}, updatedMap = {};
1096
- for (let i = 0, l = previousCollection.length; i < l; i++) {
1097
- const item = previousCollection[i], id = item.id;
1098
- if (item) {
1099
- if (collectionDict.hasOwnProperty(id)) {
1100
- if (item === collectionDict[id]) {
1101
- // not changed
1102
- notChangedMap[item.id] = item;
1103
- this._map.set(id, Object.assign(Object.assign({}, (this._map.get(id) || { width: itemSize, height: itemSize })), { method: ItemDisplayMethods.NOT_CHANGED }));
1104
- continue;
1105
- }
1106
- else {
1107
- // updated
1108
- crudDetected = true;
1109
- updatedMap[item.id] = item;
1110
- this._map.set(id, Object.assign(Object.assign({}, (this._map.get(id) || { width: itemSize, height: itemSize })), { method: ItemDisplayMethods.UPDATE }));
1111
- continue;
1112
- }
1113
- }
1114
- // deleted
1115
- crudDetected = true;
1116
- deletedMap[item.id] = item;
1117
- deletedItemsMap[i] = this._map.get(item.id);
1118
- this._map.delete(id);
1119
- }
1120
- }
1121
- for (let i = 0, l = currentCollection.length; i < l; i++) {
1122
- const item = currentCollection[i], id = item.id;
1123
- if (item && !deletedMap.hasOwnProperty(id) && !updatedMap.hasOwnProperty(id) && !notChangedMap.hasOwnProperty(id)) {
1124
- // added
1125
- crudDetected = true;
1126
- this._map.set(id, { width: itemSize, height: itemSize, method: ItemDisplayMethods.CREATE });
1127
- }
1128
- }
1129
- this._crudDetected = crudDetected;
1130
- this._deletedItemsMap = deletedItemsMap;
1131
- }
1132
- /**
1133
- * Finds the position of a collection element by the given Id
1134
- */
1135
- getItemPosition(id, stickyMap, options) {
1136
- const opt = Object.assign({ fromItemId: id, stickyMap }, options);
1137
- this._defaultBufferSize = opt.bufferSize;
1138
- this._maxBufferSize = opt.maxBufferSize;
1139
- const { scrollSize, isFromItemIdFound } = this.recalculateMetrics(Object.assign(Object.assign({}, opt), { dynamicSize: this._crudDetected || opt.dynamicSize, previousTotalSize: this._previousTotalSize, crudDetected: this._crudDetected, deletedItemsMap: this._deletedItemsMap }));
1140
- return isFromItemIdFound ? scrollSize : -1;
1141
- }
1142
- /**
1143
- * Updates the collection of display objects
1144
- */
1145
- updateCollection(items, stickyMap, options) {
1146
- const opt = Object.assign({ stickyMap }, options), crudDetected = this._crudDetected, deletedItemsMap = this._deletedItemsMap;
1147
- if (opt.dynamicSize) {
1148
- this.cacheElements();
1149
- }
1150
- this._defaultBufferSize = opt.bufferSize;
1151
- this._maxBufferSize = opt.maxBufferSize;
1152
- const metrics = this.recalculateMetrics(Object.assign(Object.assign({}, opt), { collection: items, previousTotalSize: this._previousTotalSize, crudDetected: this._crudDetected, deletedItemsMap }));
1153
- this._delta += metrics.delta;
1154
- this.updateAdaptiveBufferParams(metrics, items.length);
1155
- this._previousTotalSize = metrics.totalSize;
1156
- this._deletedItemsMap = {};
1157
- this._crudDetected = false;
1158
- if (opt.dynamicSize) {
1159
- this.snapshot();
1160
- }
1161
- const displayItems = this.generateDisplayCollection(items, stickyMap, Object.assign({}, metrics));
1162
- return { displayItems, totalSize: metrics.totalSize, delta: metrics.delta, crudDetected };
1163
- }
1164
- /**
1165
- * Finds the closest element in the collection by scrollSize
1166
- */
1167
- getNearestItem(scrollSize, items, itemSize, isVertical) {
1168
- return this.getElementFromStart(scrollSize, items, this._map, itemSize, isVertical);
1169
- }
1170
- updateAdaptiveBufferParams(metrics, totalItemsLength) {
1171
- this.disposeClearBufferSizeTimer();
1172
- const scrollSize = metrics.scrollSize + this._delta, delta = Math.abs(this._previousScrollSize - scrollSize);
1173
- this._previousScrollSize = scrollSize;
1174
- const bufferRawSize = Math.min(Math.floor(delta / metrics.typicalItemSize) * 5, totalItemsLength), minBufferSize = bufferRawSize < this._defaultBufferSize ? this._defaultBufferSize : bufferRawSize, bufferValue = minBufferSize > this._maxBufferSize ? this._maxBufferSize : minBufferSize;
1175
- this._bufferSize = bufferInterpolation(this._bufferSize, this._bufferSizeSequence, bufferValue, {
1176
- extremumThreshold: this._bufferSequenceExtraThreshold,
1177
- bufferSize: this._maxBufferSequenceLength,
1178
- });
1179
- this.startResetBufferSizeTimer();
1180
- }
1181
- startResetBufferSizeTimer() {
1182
- this._resetBufferSizeTimer = setTimeout(() => {
1183
- this._bufferSize = this._defaultBufferSize;
1184
- this._bufferSizeSequence = [];
1185
- }, this._resetBufferSizeTimeout);
1186
- }
1187
- disposeClearBufferSizeTimer() {
1188
- clearTimeout(this._resetBufferSizeTimer);
1189
- }
1190
- /**
1191
- * Calculates the position of an element based on the given scrollSize
1192
- */
1193
- getElementFromStart(scrollSize, collection, map, typicalItemSize, isVertical) {
1194
- const sizeProperty = isVertical ? HEIGHT_PROP_NAME : WIDTH_PROP_NAME;
1195
- let offset = 0;
1196
- for (let i = 0, l = collection.length; i < l; i++) {
1197
- const item = collection[i];
1198
- let itemSize = 0;
1199
- if (map.has(item.id)) {
1200
- const bounds = map.get(item.id);
1201
- itemSize = bounds ? bounds[sizeProperty] : typicalItemSize;
1202
- }
1203
- else {
1204
- itemSize = typicalItemSize;
1205
- }
1206
- if (offset > scrollSize) {
1207
- return item;
1208
- }
1209
- offset += itemSize;
1210
- }
1211
- return undefined;
1212
- }
1213
- /**
1214
- * Calculates the entry into the overscroll area and returns the number of overscroll elements
1215
- */
1216
- getElementNumToEnd(i, collection, map, typicalItemSize, size, isVertical, indexOffset = 0) {
1217
- const sizeProperty = isVertical ? HEIGHT_PROP_NAME : WIDTH_PROP_NAME;
1218
- let offset = 0, num = 0;
1219
- for (let j = collection.length - indexOffset - 1; j >= i; j--) {
1220
- const item = collection[j];
1221
- let itemSize = 0;
1222
- if (map.has(item.id)) {
1223
- const bounds = map.get(item.id);
1224
- itemSize = bounds ? bounds[sizeProperty] : typicalItemSize;
1225
- }
1226
- else {
1227
- itemSize = typicalItemSize;
1228
- }
1229
- offset += itemSize;
1230
- num++;
1231
- if (offset > size) {
1232
- return { num: 0, offset };
1233
- }
1234
- }
1235
- return { num, offset };
1236
- }
1237
- /**
1238
- * Calculates list metrics
1239
- */
1240
- recalculateMetrics(options) {
1241
- var _a, _b, _c, _d;
1242
- const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, bufferSize: minBufferSize, scrollSize, snap, stickyMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options;
1243
- const bufferSize = Math.max(minBufferSize, this._bufferSize), { width, height } = bounds, sizeProperty = isVertical ? HEIGHT_PROP_NAME : WIDTH_PROP_NAME, size = isVertical ? height : width, totalLength = collection.length, typicalItemSize = itemSize, w = isVertical ? width : typicalItemSize, h = isVertical ? typicalItemSize : height, map = this._map, snapshot = this._snapshot, checkOverscrollItemsLimit = Math.ceil(size / typicalItemSize), snippedPos = Math.floor(scrollSize), leftItemsWeights = [], isFromId = fromItemId !== undefined && (typeof fromItemId === 'number' && fromItemId > -1)
1244
- || (typeof fromItemId === 'string' && fromItemId > '-1');
1245
- let leftItemsOffset = 0, rightItemsOffset = 0;
1246
- if (enabledBufferOptimization) {
1247
- switch (this.scrollDirection) {
1248
- case 1: {
1249
- leftItemsOffset = 0;
1250
- rightItemsOffset = bufferSize;
1251
- break;
1252
- }
1253
- case -1: {
1254
- leftItemsOffset = bufferSize;
1255
- rightItemsOffset = 0;
1256
- break;
1257
- }
1258
- case 0:
1259
- default: {
1260
- leftItemsOffset = rightItemsOffset = bufferSize;
1261
- }
1262
- }
1263
- }
1264
- else {
1265
- leftItemsOffset = rightItemsOffset = bufferSize;
1266
- }
1267
- 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;
1268
- // If the list is dynamic or there are new elements in the collection, then it switches to the long algorithm.
1269
- if (dynamicSize) {
1270
- let y = 0, stickyCollectionItem = undefined, stickyComponentSize = 0;
1271
- for (let i = 0, l = collection.length; i < l; i++) {
1272
- const ii = i + 1, collectionItem = collection[i], id = collectionItem.id;
1273
- let componentSize = 0, componentSizeDelta = 0, itemDisplayMethod = ItemDisplayMethods.NOT_CHANGED;
1274
- if (map.has(id)) {
1275
- const bounds = map.get(id) || { width: typicalItemSize, height: typicalItemSize };
1276
- componentSize = bounds[sizeProperty];
1277
- itemDisplayMethod = (_a = bounds === null || bounds === void 0 ? void 0 : bounds.method) !== null && _a !== void 0 ? _a : ItemDisplayMethods.UPDATE;
1278
- switch (itemDisplayMethod) {
1279
- case ItemDisplayMethods.UPDATE: {
1280
- const snapshotBounds = snapshot.get(id);
1281
- const componentSnapshotSize = componentSize - (snapshotBounds ? snapshotBounds[sizeProperty] : typicalItemSize);
1282
- componentSizeDelta = componentSnapshotSize;
1283
- map.set(id, Object.assign(Object.assign({}, bounds), { method: ItemDisplayMethods.NOT_CHANGED }));
1284
- break;
1285
- }
1286
- case ItemDisplayMethods.CREATE: {
1287
- componentSizeDelta = typicalItemSize;
1288
- map.set(id, Object.assign(Object.assign({}, bounds), { method: ItemDisplayMethods.NOT_CHANGED }));
1289
- break;
1290
- }
1291
- }
1292
- }
1293
- if (deletedItemsMap.hasOwnProperty(i)) {
1294
- const bounds = deletedItemsMap[i], size = (_b = bounds === null || bounds === void 0 ? void 0 : bounds[sizeProperty]) !== null && _b !== void 0 ? _b : typicalItemSize;
1295
- if (y < scrollSize - size) {
1296
- leftSizeOfDeletedItems += size;
1297
- }
1298
- }
1299
- totalSize += componentSize;
1300
- if (isFromId) {
1301
- if (itemById === undefined) {
1302
- if (id !== fromItemId && stickyMap && stickyMap[id] === 1) {
1303
- stickyComponentSize = componentSize;
1304
- stickyCollectionItem = collectionItem;
1305
- }
1306
- if (id === fromItemId) {
1307
- isFromItemIdFound = true;
1308
- targetDisplayItemIndex = i;
1309
- if (stickyCollectionItem && stickyMap) {
1310
- const { num } = this.getElementNumToEnd(i, collection, map, typicalItemSize, size, isVertical);
1311
- if (num > 0) {
1312
- isTargetInOverscroll = true;
1313
- y -= size - componentSize;
1314
- }
1315
- else {
1316
- if (stickyMap && !stickyMap[collectionItem.id] && y >= scrollSize && y < scrollSize + stickyComponentSize) {
1317
- const snappedY = scrollSize - stickyComponentSize;
1318
- leftHiddenItemsWeight -= (snappedY - y);
1319
- y = snappedY;
1320
- }
1321
- else {
1322
- y -= stickyComponentSize;
1323
- leftHiddenItemsWeight -= stickyComponentSize;
1324
- }
1325
- }
1326
- }
1327
- itemById = collectionItem;
1328
- itemByIdPos = y;
1329
- }
1330
- else {
1331
- leftItemsWeights.push(componentSize);
1332
- leftHiddenItemsWeight += componentSize;
1333
- itemsFromStartToScrollEnd = ii;
1334
- }
1335
- }
1336
- }
1337
- else if (y <= scrollSize - componentSize) {
1338
- leftItemsWeights.push(componentSize);
1339
- leftHiddenItemsWeight += componentSize;
1340
- itemsFromStartToScrollEnd = ii;
1341
- }
1342
- if (isFromId) {
1343
- if (itemById === undefined || y < itemByIdPos + size + componentSize) {
1344
- itemsFromStartToDisplayEnd = ii;
1345
- totalItemsToDisplayEndWeight += componentSize;
1346
- itemsFromDisplayEndToOffsetEnd = itemsFromStartToDisplayEnd + rightItemsOffset;
1347
- }
1348
- }
1349
- else if (y <= scrollSize + size + componentSize) {
1350
- itemsFromStartToDisplayEnd = ii;
1351
- totalItemsToDisplayEndWeight += componentSize;
1352
- itemsFromDisplayEndToOffsetEnd = itemsFromStartToDisplayEnd + rightItemsOffset;
1353
- if (y <= scrollSize - componentSize) {
1354
- switch (itemDisplayMethod) {
1355
- case ItemDisplayMethods.CREATE: {
1356
- leftSizeOfAddedItems += componentSizeDelta;
1357
- break;
1358
- }
1359
- case ItemDisplayMethods.UPDATE: {
1360
- leftSizeOfUpdatedItems += componentSizeDelta;
1361
- break;
1362
- }
1363
- case ItemDisplayMethods.DELETE: {
1364
- leftSizeOfDeletedItems += componentSizeDelta;
1365
- break;
1366
- }
1367
- }
1368
- }
1369
- }
1370
- else {
1371
- if (i < itemsFromDisplayEndToOffsetEnd) {
1372
- rightItemsWeight += componentSize;
1373
- }
1374
- }
1375
- y += componentSize;
1376
- }
1377
- if (isTargetInOverscroll) {
1378
- const { num } = this.getElementNumToEnd(collection.length - (checkOverscrollItemsLimit < 0 ? 0 : collection.length - checkOverscrollItemsLimit), collection, map, typicalItemSize, size, isVertical, collection.length - (collection.length - (targetDisplayItemIndex + 1)));
1379
- if (num > 0) {
1380
- itemsFromStartToScrollEnd -= num;
1381
- }
1382
- }
1383
- if (itemsFromStartToScrollEnd <= -1) {
1384
- itemsFromStartToScrollEnd = 0;
1385
- }
1386
- if (itemsFromStartToDisplayEnd <= -1) {
1387
- itemsFromStartToDisplayEnd = 0;
1388
- }
1389
- actualScrollSize = isFromId ? itemByIdPos : scrollSize;
1390
- leftItemsWeights.splice(0, leftItemsWeights.length - leftItemsOffset);
1391
- leftItemsWeights.forEach(v => {
1392
- leftItemsWeight += v;
1393
- });
1394
- leftItemLength = Math.min(itemsFromStartToScrollEnd, leftItemsOffset);
1395
- rightItemLength = itemsFromStartToDisplayEnd + rightItemsOffset > totalLength
1396
- ? totalLength - itemsFromStartToDisplayEnd : rightItemsOffset;
1397
- }
1398
- else
1399
- // Buffer optimization does not work on fast linear algorithm
1400
- {
1401
- if (crudDetected) {
1402
- let y = 0;
1403
- for (let i = 0, l = collection.length; i < l; i++) {
1404
- const collectionItem = collection[i], id = collectionItem.id;
1405
- let componentSize = typicalItemSize, itemDisplayMethod = ItemDisplayMethods.NOT_CHANGED;
1406
- if (map.has(id)) {
1407
- const bounds = map.get(id);
1408
- itemDisplayMethod = (_c = bounds === null || bounds === void 0 ? void 0 : bounds.method) !== null && _c !== void 0 ? _c : ItemDisplayMethods.UPDATE;
1409
- if (itemDisplayMethod === ItemDisplayMethods.CREATE) {
1410
- map.set(id, Object.assign(Object.assign({}, bounds), { method: ItemDisplayMethods.NOT_CHANGED }));
1411
- }
1412
- }
1413
- if (deletedItemsMap.hasOwnProperty(i)) {
1414
- const bounds = deletedItemsMap[i], size = (_d = bounds === null || bounds === void 0 ? void 0 : bounds[sizeProperty]) !== null && _d !== void 0 ? _d : typicalItemSize;
1415
- if (y < scrollSize - size) {
1416
- leftSizeOfDeletedItems += size;
1417
- }
1418
- }
1419
- if (y < scrollSize - componentSize) {
1420
- switch (itemDisplayMethod) {
1421
- case ItemDisplayMethods.CREATE: {
1422
- leftSizeOfUpdatedItems += componentSize;
1423
- break;
1424
- }
1425
- case ItemDisplayMethods.UPDATE: {
1426
- leftSizeOfUpdatedItems += componentSize;
1427
- break;
1428
- }
1429
- case ItemDisplayMethods.DELETE: {
1430
- leftSizeOfDeletedItems += componentSize;
1431
- break;
1432
- }
1433
- }
1434
- }
1435
- y += componentSize;
1436
- }
1437
- }
1438
- itemsFromStartToScrollEnd = Math.floor(scrollSize / typicalItemSize);
1439
- itemsFromStartToDisplayEnd = Math.ceil((scrollSize + size) / typicalItemSize);
1440
- leftItemLength = Math.min(itemsFromStartToScrollEnd, bufferSize);
1441
- rightItemLength = itemsFromStartToDisplayEnd + bufferSize > totalLength
1442
- ? totalLength - itemsFromStartToDisplayEnd : bufferSize;
1443
- leftItemsWeight = leftItemLength * typicalItemSize;
1444
- rightItemsWeight = rightItemLength * typicalItemSize;
1445
- leftHiddenItemsWeight = itemsFromStartToScrollEnd * typicalItemSize;
1446
- totalItemsToDisplayEndWeight = itemsFromStartToDisplayEnd * typicalItemSize;
1447
- totalSize = totalLength * typicalItemSize;
1448
- const k = totalSize !== 0 ? previousTotalSize / totalSize : 0;
1449
- actualScrollSize = scrollSize * k;
1450
- }
1451
- startIndex = Math.min(itemsFromStartToScrollEnd - leftItemLength, totalLength > 0 ? totalLength - 1 : 0);
1452
- const itemsOnDisplayWeight = totalItemsToDisplayEndWeight - leftItemsWeight, itemsOnDisplayLength = itemsFromStartToDisplayEnd - itemsFromStartToScrollEnd, startPosition = leftHiddenItemsWeight - leftItemsWeight, renderItems = itemsOnDisplayLength + leftItemLength + rightItemLength, delta = leftSizeOfUpdatedItems + leftSizeOfAddedItems - leftSizeOfDeletedItems;
1453
- const metrics = {
1454
- delta,
1455
- normalizedItemWidth: w,
1456
- normalizedItemHeight: h,
1457
- width,
1458
- height,
1459
- dynamicSize,
1460
- itemSize,
1461
- itemsFromStartToScrollEnd,
1462
- itemsFromStartToDisplayEnd,
1463
- itemsOnDisplayWeight,
1464
- itemsOnDisplayLength,
1465
- isVertical,
1466
- leftHiddenItemsWeight,
1467
- leftItemLength,
1468
- leftItemsWeight,
1469
- renderItems,
1470
- rightItemLength,
1471
- rightItemsWeight,
1472
- scrollSize: actualScrollSize,
1473
- leftSizeOfAddedItems,
1474
- sizeProperty,
1475
- snap,
1476
- snippedPos,
1477
- startIndex,
1478
- startPosition,
1479
- totalItemsToDisplayEndWeight,
1480
- totalLength,
1481
- totalSize,
1482
- typicalItemSize,
1483
- isFromItemIdFound,
1484
- };
1485
- return metrics;
1486
- }
1487
- clearDeltaDirection() {
1488
- this.clearScrollDirectionCache();
1489
- }
1490
- clearDelta(clearDirectionDetector = false) {
1491
- this._delta = 0;
1492
- if (clearDirectionDetector) {
1493
- this.clearScrollDirectionCache();
1494
- }
1495
- }
1496
- changes() {
1497
- this.bumpVersion();
1498
- }
1499
- generateDisplayCollection(items, stickyMap, metrics) {
1500
- var _a, _b, _c;
1501
- const { width, height, normalizedItemWidth, normalizedItemHeight, dynamicSize, itemsOnDisplayLength, itemsFromStartToScrollEnd, isVertical, renderItems: renderItemsLength, scrollSize, sizeProperty, snap, snippedPos, startPosition, totalLength, startIndex, typicalItemSize, } = metrics, displayItems = [];
1502
- if (items.length) {
1503
- const actualSnippedPosition = snippedPos, isSnappingMethodAdvanced = this.isSnappingMethodAdvanced, boundsSize = isVertical ? height : width, actualEndSnippedPosition = boundsSize;
1504
- let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0;
1505
- if (snap) {
1506
- for (let i = Math.min(itemsFromStartToScrollEnd > 0 ? itemsFromStartToScrollEnd : 0, totalLength - 1); i >= 0; i--) {
1507
- if (!items[i]) {
1508
- continue;
1509
- }
1510
- const id = items[i].id, sticky = stickyMap[id], size = dynamicSize ? ((_a = this.get(id)) === null || _a === void 0 ? void 0 : _a[sizeProperty]) || typicalItemSize : typicalItemSize;
1511
- if (sticky === 1) {
1512
- const isOdd = i % 2 != 0, measures = {
1513
- x: isVertical ? 0 : actualSnippedPosition,
1514
- y: isVertical ? actualSnippedPosition : 0,
1515
- width: isVertical ? normalizedItemWidth : size,
1516
- height: isVertical ? size : normalizedItemHeight,
1517
- delta: 0,
1518
- }, config = {
1519
- odd: isOdd,
1520
- even: !isOdd,
1521
- isVertical,
1522
- sticky,
1523
- snap,
1524
- snapped: true,
1525
- snappedOut: false,
1526
- dynamic: dynamicSize,
1527
- isSnappingMethodAdvanced,
1528
- zIndex: '1',
1529
- };
1530
- const itemData = items[i];
1531
- stickyItem = { index: i, id, measures, data: itemData, config };
1532
- stickyItemIndex = i;
1533
- stickyItemSize = size;
1534
- displayItems.push(stickyItem);
1535
- break;
1536
- }
1537
- }
1538
- }
1539
- if (snap) {
1540
- const startIndex = itemsFromStartToScrollEnd + itemsOnDisplayLength - 1;
1541
- for (let i = Math.min(startIndex, totalLength > 0 ? totalLength - 1 : 0), l = totalLength; i < l; i++) {
1542
- if (!items[i]) {
1543
- continue;
1544
- }
1545
- const id = items[i].id, sticky = stickyMap[id], size = dynamicSize
1546
- ? ((_b = this.get(id)) === null || _b === void 0 ? void 0 : _b[sizeProperty]) || typicalItemSize
1547
- : typicalItemSize;
1548
- if (sticky === 2) {
1549
- const isOdd = i % 2 != 0, w = isVertical ? normalizedItemWidth : size, h = isVertical ? size : normalizedItemHeight, measures = {
1550
- x: isVertical ? 0 : actualEndSnippedPosition - w,
1551
- y: isVertical ? actualEndSnippedPosition - h : 0,
1552
- width: w,
1553
- height: h,
1554
- delta: 0,
1555
- }, config = {
1556
- odd: isOdd,
1557
- even: !isOdd,
1558
- isVertical,
1559
- sticky,
1560
- snap,
1561
- snapped: true,
1562
- snappedOut: false,
1563
- dynamic: dynamicSize,
1564
- isSnappingMethodAdvanced,
1565
- zIndex: '1',
1566
- };
1567
- const itemData = items[i];
1568
- endStickyItem = { index: i, id, measures, data: itemData, config };
1569
- endStickyItemIndex = i;
1570
- endStickyItemSize = size;
1571
- displayItems.push(endStickyItem);
1572
- break;
1573
- }
1574
- }
1575
- }
1576
- let i = startIndex;
1577
- while (renderItems > 0) {
1578
- if (i >= totalLength) {
1579
- break;
1580
- }
1581
- if (!items[i]) {
1582
- continue;
1583
- }
1584
- const id = items[i].id, size = dynamicSize ? ((_c = this.get(id)) === null || _c === void 0 ? void 0 : _c[sizeProperty]) || typicalItemSize : typicalItemSize;
1585
- if (id !== (stickyItem === null || stickyItem === void 0 ? void 0 : stickyItem.id) && id !== (endStickyItem === null || endStickyItem === void 0 ? void 0 : endStickyItem.id)) {
1586
- const isOdd = i % 2 != 0, snapped = snap && (stickyMap[id] === 1 && pos <= scrollSize || stickyMap[id] === 2 && pos >= scrollSize + boundsSize - size), measures = {
1587
- x: isVertical ? stickyMap[id] === 1 ? 0 : boundsSize - size : pos,
1588
- y: isVertical ? pos : stickyMap[id] === 2 ? boundsSize - size : 0,
1589
- width: isVertical ? normalizedItemWidth : size,
1590
- height: isVertical ? size : normalizedItemHeight,
1591
- delta: 0,
1592
- }, config = {
1593
- odd: isOdd,
1594
- even: !isOdd,
1595
- isVertical,
1596
- sticky: stickyMap[id],
1597
- snap,
1598
- snapped: false,
1599
- snappedOut: false,
1600
- dynamic: dynamicSize,
1601
- isSnappingMethodAdvanced,
1602
- zIndex: '0',
1603
- };
1604
- if (snapped) {
1605
- config.zIndex = '2';
1606
- }
1607
- const itemData = items[i];
1608
- const item = { index: i, id, measures, data: itemData, config };
1609
- if (!nextSticky && stickyItemIndex < i && stickyMap[id] === 1 && (pos <= scrollSize + size + stickyItemSize)) {
1610
- item.measures.x = isVertical ? 0 : snapped ? actualSnippedPosition : pos;
1611
- item.measures.y = isVertical ? snapped ? actualSnippedPosition : pos : 0;
1612
- nextSticky = item;
1613
- nextSticky.config.snapped = snapped;
1614
- nextSticky.measures.delta = isVertical ? (item.measures.y - scrollSize) : (item.measures.x - scrollSize);
1615
- nextSticky.config.zIndex = '3';
1616
- }
1617
- else if (!nextEndSticky && endStickyItemIndex > i && stickyMap[id] === 2 && (pos >= scrollSize + boundsSize - size - endStickyItemSize)) {
1618
- item.measures.x = isVertical ? 0 : snapped ? actualEndSnippedPosition - size : pos;
1619
- item.measures.y = isVertical ? snapped ? actualEndSnippedPosition - size : pos : 0;
1620
- nextEndSticky = item;
1621
- nextEndSticky.config.zIndex = '3';
1622
- nextEndSticky.config.snapped = snapped;
1623
- nextEndSticky.measures.delta = isVertical ? (item.measures.y - scrollSize) : (item.measures.x - scrollSize);
1624
- }
1625
- displayItems.push(item);
1626
- }
1627
- renderItems -= 1;
1628
- pos += size;
1629
- i++;
1630
- }
1631
- const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME;
1632
- if (nextSticky && stickyItem && nextSticky.measures[axis] <= scrollSize + stickyItemSize) {
1633
- if (nextSticky.measures[axis] > scrollSize) {
1634
- stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItemSize;
1635
- stickyItem.config.snapped = nextSticky.config.snapped = false;
1636
- stickyItem.config.snappedOut = true;
1637
- stickyItem.config.sticky = 1;
1638
- stickyItem.measures.delta = isVertical ? stickyItem.measures.y - scrollSize : stickyItem.measures.x - scrollSize;
1639
- }
1640
- else {
1641
- nextSticky.config.snapped = true;
1642
- nextSticky.measures.delta = isVertical ? nextSticky.measures.y - scrollSize : nextSticky.measures.x - scrollSize;
1643
- }
1644
- }
1645
- if (nextEndSticky && endStickyItem && nextEndSticky.measures[axis] >= scrollSize + boundsSize - endStickyItemSize - nextEndSticky.measures[sizeProperty]) {
1646
- if (nextEndSticky.measures[axis] < scrollSize + boundsSize - endStickyItemSize) {
1647
- endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
1648
- endStickyItem.config.snapped = nextEndSticky.config.snapped = false;
1649
- endStickyItem.config.snappedOut = true;
1650
- endStickyItem.config.sticky = 2;
1651
- endStickyItem.measures.delta = isVertical ? endStickyItem.measures.y - scrollSize : endStickyItem.measures.x - scrollSize;
1652
- }
1653
- else {
1654
- nextEndSticky.config.snapped = true;
1655
- nextEndSticky.measures.delta = isVertical ? nextEndSticky.measures.y - scrollSize : nextEndSticky.measures.x - scrollSize;
1656
- }
1657
- }
1658
- }
1659
- return displayItems;
1660
- }
1661
- /**
1662
- * tracking by propName
1663
- */
1664
- track() {
1665
- if (!this._items || !this._displayComponents) {
1666
- return;
1667
- }
1668
- this._tracker.track(this._items, this._displayComponents, this._snapedDisplayComponent, this.scrollDirection);
1669
- }
1670
- setDisplayObjectIndexMapById(v) {
1671
- this._tracker.displayObjectIndexMapById = v;
1672
- }
1673
- untrackComponentByIdProperty(component) {
1674
- this._tracker.untrackComponentByIdProperty(component);
1675
- }
1676
- getItemBounds(id) {
1677
- if (this.has(id)) {
1678
- return this.get(id);
1679
- }
1680
- return undefined;
1681
- }
1682
- cacheElements() {
1683
- if (!this._displayComponents) {
1684
- return;
1685
- }
1686
- for (let i = 0, l = this._displayComponents.length; i < l; i++) {
1687
- const component = this._displayComponents[i], itemId = component.instance.itemId;
1688
- if (itemId === undefined) {
1689
- continue;
1690
- }
1691
- const bounds = component.instance.getBounds();
1692
- this.set(itemId, bounds);
1693
- }
1694
- }
1695
- dispose() {
1696
- super.dispose();
1697
- this.disposeClearBufferSizeTimer();
1698
- if (this._tracker) {
1699
- this._tracker.dispose();
1700
- }
1701
- }
1702
- }
1703
-
1704
- /**
1705
- * Base disposable component
1706
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/disposableComponent.ts
1707
- * @author Evgenii Grebennikov
1708
- * @email djonnyx@gmail.com
1709
- */
1710
- class DisposableComponent {
1711
- constructor() {
1712
- this._$unsubscribe = new Subject();
1713
- }
1714
- ngOnDestroy() {
1715
- if (this._$unsubscribe) {
1716
- this._$unsubscribe.next();
1717
- this._$unsubscribe.complete();
1718
- }
1719
- }
1720
- }
1721
- DisposableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DisposableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1722
- DisposableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DisposableComponent, selector: "ng-component", ngImport: i0, template: ``, isInline: true });
1723
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DisposableComponent, decorators: [{
1724
- type: Component,
1725
- args: [{
1726
- template: ``,
1727
- }]
1728
- }] });
1729
-
1730
- const ADVANCED_PATTERNS = [SnappingMethods.ADVANCED, 'advanced'], DEFAULT_PATTERN = [SnappingMethods.NORMAL, 'normal'];
1731
- const isSnappingMethodAdvenced = (method) => {
1732
- return ADVANCED_PATTERNS.includes(method);
1733
- };
1734
- const isSnappingMethodDefault = (method) => {
1735
- return DEFAULT_PATTERN.includes(method);
1736
- };
1737
-
1738
- const IS_FIREFOX = navigator.userAgent.toLowerCase().includes('firefox');
1739
- const FIREFOX_SCROLLBAR_OVERLAP_SIZE = 12;
1740
-
1741
- const HORIZONTAL_ALIASES = [Directions.HORIZONTAL, 'horizontal'], VERTICAL_ALIASES = [Directions.VERTICAL, 'vertical'];
1742
- /**
1743
- * Determines the axis membership of a virtual list
1744
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/isDirection.ts
1745
- * @author Evgenii Grebennikov
1746
- * @email djonnyx@gmail.com
1747
- */
1748
- const isDirection = (src, expected) => {
1749
- if (HORIZONTAL_ALIASES.includes(expected)) {
1750
- return HORIZONTAL_ALIASES.includes(src);
1751
- }
1752
- return VERTICAL_ALIASES.includes(src);
1753
- };
1754
-
1755
- const NONE_ALIASES = [MethodsForSelecting.NONE, 'none'], SELECT_ALIASES = [MethodsForSelecting.SELECT, 'select'], MULTI_SELECT_ALIASES = [MethodsForSelecting.MULTI_SELECT, 'multi-select'];
1756
- /**
1757
- * Defines the method for selecting list items.
1758
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/utils/isMethodForSelecting.ts
1759
- * @author Evgenii Grebennikov
1760
- * @email djonnyx@gmail.com
1761
- */
1762
- const isMethodForSelecting = (src, expected) => {
1763
- if (NONE_ALIASES.includes(expected)) {
1764
- return NONE_ALIASES.includes(src);
1765
- }
1766
- else if (SELECT_ALIASES.includes(expected)) {
1767
- return SELECT_ALIASES.includes(src);
1768
- }
1769
- return MULTI_SELECT_ALIASES.includes(src);
1770
- };
1771
-
1772
- const ROLE_LIST = 'list', ROLE_LIST_BOX = 'listbox';
1773
- /**
1774
- * Virtual list component.
1775
- * Maximum performance for extremely large lists.
1776
- * It is based on algorithms for virtualization of screen objects.
1777
- * @link https://github.com/DjonnyX/ng-virtual-list/blob/15.x/projects/ng-virtual-list/src/lib/ng-virtual-list.component.ts
1778
- * @author Evgenii Grebennikov
1779
- * @email djonnyx@gmail.com
1780
- */
1781
- class NgVirtualListComponent extends DisposableComponent {
1782
- /**
1783
- * Readonly. Returns the unique identifier of the component.
1784
- */
1785
- get id() { return this._id; }
1786
- /**
1787
- * Collection of list items.
1788
- */
1789
- set items(v) {
1790
- if (this._$items.getValue() === v) {
1791
- return;
1792
- }
1793
- const transformedValue = this._itemsTransform(v);
1794
- this._$items.next(transformedValue);
1795
- this._cdr.markForCheck();
1796
- }
1797
- ;
1798
- get items() { return this._$items.getValue(); }
1799
- /**
1800
- * Sets the selected items.
1801
- */
1802
- set selectedIds(v) {
1803
- if (this._$selectedIds.getValue() === v) {
1804
- return;
1805
- }
1806
- this._$selectedIds.next(v);
1807
- this._cdr.markForCheck();
1808
- }
1809
- ;
1810
- get selectedIds() { return this._$selectedIds.getValue(); }
1811
- /**
1812
- * Determines whether elements will snap. Default value is "true".
1813
- */
1814
- set snap(v) {
1815
- if (this._$snap.getValue() === v) {
1816
- return;
1817
- }
1818
- this._$snap.next(v);
1819
- this._cdr.markForCheck();
1820
- }
1821
- ;
1822
- get snap() { return this._$snap.getValue(); }
1823
- /**
1824
- * Experimental!
1825
- * Enables buffer optimization.
1826
- * Can only be used if items in the collection are not added or updated. Otherwise, artifacts in the form of twitching of the scroll area are possible.
1827
- * Works only if the property dynamic = true
1828
- */
1829
- set enabledBufferOptimization(v) {
1830
- if (this._$enabledBufferOptimization.getValue() === v) {
1831
- return;
1832
- }
1833
- this._$enabledBufferOptimization.next(v);
1834
- this._cdr.markForCheck();
1835
- }
1836
- ;
1837
- get enabledBufferOptimization() { return this._$enabledBufferOptimization.getValue(); }
1838
- /**
1839
- * Rendering element template.
1840
- */
1841
- set itemRenderer(v) {
1842
- if (this._$itemRenderer.getValue() === v) {
1843
- return;
1844
- }
1845
- this._$itemRenderer.next(v);
1846
- this._cdr.markForCheck();
1847
- }
1848
- ;
1849
- get itemRenderer() { return this._$itemRenderer.getValue(); }
1850
- /**
1851
- * Dictionary zIndex by id of the list element. If the value is not set or equal to 0,
1852
- * then a simple element is displayed, if the value is greater than 0, then the sticky position mode is enabled for the element.
1853
- */
1854
- set stickyMap(v) {
1855
- if (this._$stickyMap.getValue() === v) {
1856
- return;
1857
- }
1858
- this._$stickyMap.next(v);
1859
- this._cdr.markForCheck();
1860
- }
1861
- ;
1862
- get stickyMap() { return this._$stickyMap.getValue(); }
1863
- /**
1864
- * If direction = 'vertical', then the height of a typical element. If direction = 'horizontal', then the width of a typical element.
1865
- * Ignored if the dynamicSize property is true.
1866
- */
1867
- set itemSize(v) {
1868
- if (this._$itemSize.getValue() === v) {
1869
- return;
1870
- }
1871
- this._$itemSize.next(this._itemSizeOptions(v));
1872
- this._cdr.markForCheck();
1873
- }
1874
- ;
1875
- get itemSize() { return this._$itemSize.getValue(); }
1876
- /**
1877
- * If true then the items in the list can have different sizes and the itemSize property is ignored.
1878
- * If false then the items in the list have a fixed size specified by the itemSize property. The default value is false.
1879
- */
1880
- set dynamicSize(v) {
1881
- if (this._$dynamicSize.getValue() === v) {
1882
- return;
1883
- }
1884
- this._$dynamicSize.next(v);
1885
- this._cdr.markForCheck();
1886
- }
1887
- ;
1888
- get dynamicSize() { return this._$dynamicSize.getValue(); }
1889
- /**
1890
- * Determines the direction in which elements are placed. Default value is "vertical".
1891
- */
1892
- set direction(v) {
1893
- if (this._$direction.getValue() === v) {
1894
- return;
1895
- }
1896
- this._$direction.next(v);
1897
- this._cdr.markForCheck();
1898
- }
1899
- ;
1900
- get direction() { return this._$direction.getValue(); }
1901
- /**
1902
- * @deprecated "itemOffset" parameter is deprecated. Use "bufferSize" and "maxBufferSize".
1903
- */
1904
- set itemsOffset(v) {
1905
- throw Error('"itemOffset" parameter is deprecated. Use "bufferSize" and "maxBufferSize".');
1906
- }
1907
- ;
1908
- /**
1909
- * Number of elements outside the scope of visibility. Default value is 2.
1910
- */
1911
- set bufferSize(v) {
1912
- if (this._$bufferSize.getValue() === v) {
1913
- return;
1914
- }
1915
- this._$bufferSize.next(v);
1916
- }
1917
- ;
1918
- get bufferSize() { return this._$bufferSize.getValue(); }
1919
- /**
1920
- * Maximum number of elements outside the scope of visibility. Default value is 100.
1921
- * If maxBufferSize is set to be greater than bufferSize, then adaptive buffer mode is enabled.
1922
- * The greater the scroll size, the more elements are allocated for rendering.
1923
- */
1924
- set maxBufferSize(v) {
1925
- const val = this._maxBufferSizeTransform(v);
1926
- if (this._$maxBufferSize.getValue() === val) {
1927
- return;
1928
- }
1929
- this._$maxBufferSize.next(val);
1930
- }
1931
- ;
1932
- get maxBufferSize() { return this._$maxBufferSize.getValue(); }
1933
- /**
1934
- * The name of the property by which tracking is performed
1935
- */
1936
- set trackBy(v) {
1937
- if (this._$trackBy.getValue() === v) {
1938
- return;
1939
- }
1940
- this._$trackBy.next(v);
1941
- }
1942
- ;
1943
- get trackBy() { return this._$trackBy.getValue(); }
1944
- get orientation() {
1945
- return this._isVertical ? Directions.VERTICAL : Directions.HORIZONTAL;
1946
- }
1947
- /**
1948
- * Snapping method.
1949
- * 'default' - Normal group rendering.
1950
- * 'advanced' - The group is rendered on a transparent background. List items below the group are not rendered.
1951
- */
1952
- set snappingMethod(v) {
1953
- if (this._$snappingMethod.getValue() === v) {
1954
- return;
1955
- }
1956
- this._$snappingMethod.next(v);
1957
- }
1958
- ;
1959
- get snappingMethod() { return this._$snappingMethod.getValue(); }
1960
- get isSnappingMethodAdvanced() { return this._isSnappingMethodAdvanced; }
1961
- /**
1962
- * Method for selecting list items.
1963
- * 'select' - List items are selected one by one.
1964
- * 'multi-select' - Multiple selection of list items.
1965
- * 'none' - List items are not selectable.
1966
- */
1967
- set methodForSelecting(v) {
1968
- if (this._$methodForSelecting.getValue() === v) {
1969
- return;
1970
- }
1971
- this._$methodForSelecting.next(v);
1972
- }
1973
- ;
1974
- get methodForSelecting() { return this._$methodForSelecting.getValue(); }
1975
- get isNotSelecting() { return this._isNotSelecting; }
1976
- get isSingleSelecting() { return this._isSingleSelecting; }
1977
- get isMultiSelecting() { return this._isMultiSelecting; }
1978
- get $cacheVersion() { return this._$cacheVersion.asObservable(); }
1979
- constructor(_cdr, _elementRef, _service) {
1980
- super();
1981
- this._cdr = _cdr;
1982
- this._elementRef = _elementRef;
1983
- this._service = _service;
1984
- this._id = NgVirtualListComponent.__nextId;
1985
- /**
1986
- * Fires when the list has been scrolled.
1987
- */
1988
- this.onScroll = new EventEmitter$1();
1989
- /**
1990
- * Fires when the list has completed scrolling.
1991
- */
1992
- this.onScrollEnd = new EventEmitter$1();
1993
- /**
1994
- * Fires when the viewport size is changed.
1995
- */
1996
- this.onViewportChange = new EventEmitter$1();
1997
- /**
1998
- * Fires when an element is clicked.
1999
- */
2000
- this.onItemClick = new EventEmitter$1();
2001
- /**
2002
- * Fires when an elements are selected.
2003
- */
2004
- this.onSelect = new EventEmitter$1();
2005
- this._$items = new BehaviorSubject$1(undefined);
2006
- this.$items = this._$items.asObservable();
2007
- this._itemsTransform = (v) => {
2008
- this._trackBox.resetCollection(v, this._$itemSize.getValue());
2009
- return v;
2010
- };
2011
- this._$selectedIds = new BehaviorSubject$1(undefined);
2012
- this.$selectedIds = this._$selectedIds.asObservable();
2013
- this._$snap = new BehaviorSubject$1(DEFAULT_SNAP);
2014
- this.$snap = this._$snap.asObservable();
2015
- this._$enabledBufferOptimization = new BehaviorSubject$1(DEFAULT_ENABLED_BUFFER_OPTIMIZATION);
2016
- this.$enabledBufferOptimization = this._$enabledBufferOptimization.asObservable();
2017
- this._$itemRenderer = new BehaviorSubject$1(undefined);
2018
- this.$itemRenderer = this._$itemRenderer.asObservable();
2019
- this._$renderer = new BehaviorSubject$1(undefined);
2020
- this._$stickyMap = new BehaviorSubject$1({});
2021
- this.$stickyMap = this._$stickyMap.asObservable();
2022
- this._itemSizeOptions = (v) => {
2023
- if (v === undefined) {
2024
- return DEFAULT_ITEM_SIZE;
2025
- }
2026
- const val = Number(v);
2027
- return Number.isNaN(val) || val <= 0 ? DEFAULT_ITEM_SIZE : val;
2028
- };
2029
- this._$itemSize = new BehaviorSubject$1(DEFAULT_ITEM_SIZE);
2030
- this.$itemSize = this._$itemSize.asObservable();
2031
- this._$dynamicSize = new BehaviorSubject$1(DEFAULT_DYNAMIC_SIZE);
2032
- this.$dynamicSize = this._$dynamicSize.asObservable();
2033
- this._$direction = new BehaviorSubject$1(DEFAULT_DIRECTION);
2034
- this.$direction = this._$direction.asObservable();
2035
- this._$bufferSize = new BehaviorSubject$1(DEFAULT_BUFFER_SIZE);
2036
- this.$bufferSize = this._$bufferSize.asObservable();
2037
- this._maxBufferSizeTransform = (v) => {
2038
- const bufferSize = this._$bufferSize.getValue();
2039
- if (v === undefined || v <= bufferSize) {
2040
- return bufferSize;
2041
- }
2042
- return v;
2043
- };
2044
- this._$maxBufferSize = new BehaviorSubject$1(DEFAULT_MAX_BUFFER_SIZE);
2045
- this.$maxBufferSize = this._$maxBufferSize.asObservable();
2046
- this._$trackBy = new BehaviorSubject$1(TRACK_BY_PROPERTY_NAME);
2047
- this.$trackBy = this._$trackBy.asObservable();
2048
- this._isVertical = this.getIsVertical();
2049
- this._$snappingMethod = new BehaviorSubject$1(DEFAULT_SNAPPING_METHOD);
2050
- this.$snappingMethod = this._$snappingMethod.asObservable();
2051
- this._isSnappingMethodAdvanced = this.getIsSnappingMethodAdvanced();
2052
- this._$methodForSelecting = new BehaviorSubject$1(DEFAULT_SELECT_METHOD);
2053
- this.$methodForSelecting = this._$methodForSelecting.asObservable();
2054
- this._isNotSelecting = this.getIsNotSelecting();
2055
- this._isSingleSelecting = this.getIsSingleSelecting();
2056
- this._isMultiSelecting = this.getIsMultiSelecting();
2057
- this._displayComponents = [];
2058
- this._$bounds = new BehaviorSubject$1(null);
2059
- this._$scrollSize = new BehaviorSubject$1(0);
2060
- this._resizeObserver = null;
2061
- this._resizeSnappedComponentHandler = () => {
2062
- var _a, _b, _c, _d, _e, _f;
2063
- const list = this._list, container = this._container, snappedComponent = (_a = this._snapedDisplayComponent) === null || _a === void 0 ? void 0 : _a.instance;
2064
- if (list && container && snappedComponent) {
2065
- const isVertical = this._isVertical, listBounds = list.nativeElement.getBoundingClientRect(), listElement = list === null || list === void 0 ? void 0 : list.nativeElement, { width: lWidth, height: lHeight } = (_b = listElement === null || listElement === void 0 ? void 0 : listElement.getBoundingClientRect()) !== null && _b !== void 0 ? _b : { width: 0, height: 0 }, { width, height } = (_c = this._$bounds.getValue()) !== null && _c !== void 0 ? _c : { width: 0, height: 0 }, isScrollable = isVertical ? container.nativeElement.scrollHeight > 0 : container.nativeElement.scrollWidth > 0;
2066
- let scrollBarSize = isVertical ? width - lWidth : height - lHeight, isScrollBarOverlap = true, overlapScrollBarSize = 0;
2067
- if (scrollBarSize === 0 && isScrollable) {
2068
- isScrollBarOverlap = true;
2069
- }
2070
- if (isScrollBarOverlap && IS_FIREFOX) {
2071
- scrollBarSize = overlapScrollBarSize = FIREFOX_SCROLLBAR_OVERLAP_SIZE;
2072
- }
2073
- const { width: sWidth, height: sHeight } = (_d = snappedComponent.getBounds()) !== null && _d !== void 0 ? _d : { width: 0, height: 0 };
2074
- snappedComponent.element.style.clipPath = `path("M 0 0 L 0 ${sHeight} L ${sWidth - overlapScrollBarSize} ${sHeight} L ${sWidth - overlapScrollBarSize} 0 Z")`;
2075
- snappedComponent.regularLength = `${isVertical ? listBounds.width : listBounds.height}${PX}`;
2076
- const containerElement = container.nativeElement, delta = (_f = (_e = snappedComponent.item) === null || _e === void 0 ? void 0 : _e.measures.delta) !== null && _f !== void 0 ? _f : 0;
2077
- let left, right, top, bottom;
2078
- if (isVertical) {
2079
- left = 0;
2080
- right = width - scrollBarSize;
2081
- top = sHeight;
2082
- bottom = height;
2083
- 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")`;
2084
- }
2085
- else {
2086
- left = sWidth;
2087
- right = width;
2088
- top = 0;
2089
- bottom = height - scrollBarSize;
2090
- 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")`;
2091
- }
2092
- }
2093
- };
2094
- this._resizeSnappedObserver = null;
2095
- this._onResizeHandler = () => {
2096
- var _a, _b;
2097
- const bounds = (_b = (_a = this._container) === null || _a === void 0 ? void 0 : _a.nativeElement) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
2098
- if (bounds) {
2099
- this._$bounds.next({ width: bounds.width, height: bounds.height });
2100
- }
2101
- else {
2102
- this._$bounds.next({ width: DEFAULT_LIST_SIZE, height: DEFAULT_LIST_SIZE });
2103
- }
2104
- if (this._isSnappingMethodAdvanced) {
2105
- this.updateRegularRenderer();
2106
- }
2107
- };
2108
- this._onScrollHandler = (e) => {
2109
- var _a;
2110
- this.clearScrollToRepeatExecutionTimeout();
2111
- const container = (_a = this._container) === null || _a === void 0 ? void 0 : _a.nativeElement;
2112
- if (container) {
2113
- const scrollSize = (this._isVertical ? container.scrollTop : container.scrollLeft);
2114
- this._$scrollSize.next(scrollSize);
2115
- }
2116
- };
2117
- this._$initialized = new BehaviorSubject$1(false);
2118
- /**
2119
- * Base class of the element component
2120
- */
2121
- this._itemComponentClass = NgVirtualListItemComponent;
2122
- /**
2123
- * Base class trackBox
2124
- */
2125
- this._trackBoxClass = TrackBox;
2126
- /**
2127
- * Dictionary of element sizes by their id
2128
- */
2129
- this._trackBox = new this._trackBoxClass(this.trackBy);
2130
- this._onTrackBoxChangeHandler = (v) => {
2131
- this._$cacheVersion.next(v);
2132
- };
2133
- this._$cacheVersion = new BehaviorSubject$1(-1);
2134
- this._componentsResizeObserver = new ResizeObserver(() => {
2135
- this._trackBox.changes();
2136
- });
2137
- this._onContainerScrollHandler = (e) => {
2138
- const containerEl = this._container;
2139
- if (containerEl) {
2140
- const scrollSize = (this._isVertical ? containerEl.nativeElement.scrollTop : containerEl.nativeElement.scrollLeft);
2141
- this._trackBox.deltaDirection = this._$scrollSize.getValue() > scrollSize ? -1 : this._$scrollSize.getValue() < scrollSize ? 1 : 0;
2142
- const event = new ScrollEvent({
2143
- direction: this._trackBox.scrollDirection, container: containerEl.nativeElement,
2144
- list: this._list.nativeElement, delta: this._trackBox.delta,
2145
- scrollDelta: this._trackBox.scrollDelta, isVertical: this._isVertical,
2146
- });
2147
- this.onScroll.emit(event);
2148
- }
2149
- };
2150
- this._onContainerScrollEndHandler = (e) => {
2151
- const containerEl = this._container;
2152
- if (containerEl) {
2153
- const scrollSize = (this._isVertical ? containerEl.nativeElement.scrollTop : containerEl.nativeElement.scrollLeft);
2154
- this._trackBox.deltaDirection = this._$scrollSize.getValue() > scrollSize ? -1 : 0;
2155
- const event = new ScrollEvent({
2156
- direction: this._trackBox.scrollDirection, container: containerEl.nativeElement,
2157
- list: this._list.nativeElement, delta: this._trackBox.delta,
2158
- scrollDelta: this._trackBox.scrollDelta, isVertical: this._isVertical,
2159
- });
2160
- this.onScrollEnd.emit(event);
2161
- }
2162
- };
2163
- NgVirtualListComponent.__nextId = NgVirtualListComponent.__nextId + 1 === Number.MAX_SAFE_INTEGER
2164
- ? 0 : NgVirtualListComponent.__nextId + 1;
2165
- this._id = NgVirtualListComponent.__nextId;
2166
- this._service.initialize(this._trackBox);
2167
- this._$initialized = new BehaviorSubject$1(false);
2168
- this.$initialized = this._$initialized.asObservable();
2169
- this._trackBox.displayComponents = this._displayComponents;
2170
- const $trackBy = this.$trackBy;
2171
- $trackBy.pipe(takeUntil(this._$unsubscribe), tap(v => {
2172
- this._trackBox.trackingPropertyName = v;
2173
- })).subscribe();
2174
- 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)), $stickyMap = this.$stickyMap.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, $cacheVersion = this.$cacheVersion;
2175
- $isVertical.pipe(takeUntil(this._$unsubscribe), tap(v => {
2176
- this._isVertical = v;
2177
- const el = this._elementRef.nativeElement;
2178
- toggleClassName(el, v ? CLASS_LIST_VERTICAL : CLASS_LIST_HORIZONTAL, v ? CLASS_LIST_HORIZONTAL : CLASS_LIST_VERTICAL);
2179
- })).subscribe();
2180
- $snappingMethod.pipe(takeUntil(this._$unsubscribe), tap(v => {
2181
- this._isSnappingMethodAdvanced = this._trackBox.isSnappingMethodAdvanced = v;
2182
- })).subscribe();
2183
- combineLatest([$methodForSelecting, this.$initialized]).pipe(takeUntil(this._$unsubscribe), debounceTime(0), filter(([, init]) => init === true), map$1(([v]) => (v)), tap(v => {
2184
- var _a;
2185
- const el = (_a = this._list) === null || _a === void 0 ? void 0 : _a.nativeElement;
2186
- if (this.getIsMultiSelecting(v || DEFAULT_SNAPPING_METHOD)) {
2187
- this._isMultiSelecting = true;
2188
- this._isNotSelecting = this._isSingleSelecting = false;
2189
- if (el) {
2190
- console.log('set role', ROLE_LIST_BOX);
2191
- el.setAttribute('role', ROLE_LIST_BOX);
2192
- }
2193
- this._service.methodOfSelecting = MethodsForSelectingTypes.MULTI_SELECT;
2194
- }
2195
- else if (this.getIsSingleSelecting(v || DEFAULT_SNAPPING_METHOD)) {
2196
- this._isSingleSelecting = true;
2197
- this._isNotSelecting = this._isMultiSelecting = false;
2198
- if (el) {
2199
- console.log('set role', ROLE_LIST_BOX);
2200
- el.setAttribute('role', ROLE_LIST_BOX);
2201
- }
2202
- this._service.methodOfSelecting = MethodsForSelectingTypes.SELECT;
2203
- }
2204
- else if (this.getIsNotSelecting(v || DEFAULT_SNAPPING_METHOD)) {
2205
- this._isNotSelecting = true;
2206
- this._isSingleSelecting = this._isMultiSelecting = false;
2207
- if (el) {
2208
- console.log('set role', ROLE_LIST);
2209
- el.setAttribute('role', ROLE_LIST);
2210
- }
2211
- this._service.methodOfSelecting = MethodsForSelectingTypes.NONE;
2212
- }
2213
- })).subscribe();
2214
- $dynamicSize.pipe(takeUntil(this._$unsubscribe), tap(dynamicSize => {
2215
- this.listenCacheChangesIfNeed(dynamicSize);
2216
- })).subscribe();
2217
- combineLatest([this.$initialized, $bounds, $items, $stickyMap, $scrollSize, $itemSize,
2218
- $bufferSize, $maxBufferSize, $snap, $isVertical, $dynamicSize, $enabledBufferOptimization, $cacheVersion,
2219
- ]).pipe(takeUntil(this._$unsubscribe), distinctUntilChanged(), filter(([initialized]) => !!initialized), switchMap(([, bounds, items, stickyMap, scrollSize, itemSize, bufferSize, maxBufferSize, snap, isVertical, dynamicSize, enabledBufferOptimization, cacheVersion,]) => {
2220
- var _a, _b, _c, _d;
2221
- let actualScrollSize = (_d = (this._isVertical ? (_b = (_a = this._container) === null || _a === void 0 ? void 0 : _a.nativeElement.scrollTop) !== null && _b !== void 0 ? _b : 0 : (_c = this._container) === null || _c === void 0 ? void 0 : _c.nativeElement.scrollLeft)) !== null && _d !== void 0 ? _d : 0;
2222
- const { width, height } = bounds, opts = {
2223
- bounds: { width, height }, dynamicSize, isVertical, itemSize,
2224
- bufferSize, maxBufferSize, scrollSize: actualScrollSize, snap, enabledBufferOptimization,
2225
- }, { displayItems, totalSize } = this._trackBox.updateCollection(items, stickyMap, opts);
2226
- this.resetBoundsSize(isVertical, totalSize);
2227
- this.createDisplayComponentsIfNeed(displayItems);
2228
- this.tracking();
2229
- if (this._isSnappingMethodAdvanced) {
2230
- this.updateRegularRenderer();
2231
- }
2232
- const container = this._container;
2233
- if (container) {
2234
- const delta = this._trackBox.delta;
2235
- actualScrollSize = actualScrollSize + delta;
2236
- this._trackBox.clearDelta();
2237
- if (scrollSize !== actualScrollSize) {
2238
- const params = {
2239
- [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: actualScrollSize,
2240
- behavior: BEHAVIOR_INSTANT
2241
- };
2242
- container.nativeElement.scrollTo(params);
2243
- }
2244
- }
2245
- return of(displayItems);
2246
- })).subscribe();
2247
- const $itemRenderer = this.$itemRenderer;
2248
- $itemRenderer.pipe(takeUntil(this._$unsubscribe), distinctUntilChanged(), filter(v => !!v), tap(v => {
2249
- this._$renderer.next(v);
2250
- })).subscribe();
2251
- $bounds.pipe(takeUntil(this._$unsubscribe), distinctUntilChanged(), tap(value => {
2252
- this.onViewportChange.emit(value !== null && value !== void 0 ? value : undefined);
2253
- })).subscribe();
2254
- this._service.$itemClick.pipe(takeUntil(this._$unsubscribe), tap(v => {
2255
- this.onItemClick.emit(v !== null && v !== void 0 ? v : undefined);
2256
- })).subscribe();
2257
- this._service.$selectedIds.pipe(takeUntil(this._$unsubscribe), tap(v => {
2258
- this.onSelect.emit(v);
2259
- })).subscribe();
2260
- $selectedIds.pipe(takeUntil(this._$unsubscribe), tap(v => {
2261
- this._service.setSelectedIds(v);
2262
- })).subscribe();
2263
- }
2264
- /** @internal */
2265
- ngOnInit() {
2266
- this.onInit();
2267
- }
2268
- onInit() {
2269
- this._$initialized.next(true);
2270
- }
2271
- listenCacheChangesIfNeed(value) {
2272
- if (value) {
2273
- if (!this._trackBox.hasEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler)) {
2274
- this._trackBox.addEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler);
2275
- }
2276
- }
2277
- else {
2278
- if (this._trackBox.hasEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler)) {
2279
- this._trackBox.removeEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler);
2280
- }
2281
- }
2282
- }
2283
- getIsSnappingMethodAdvanced(m) {
2284
- const method = m || this._$snappingMethod.getValue();
2285
- return isSnappingMethodAdvenced(method);
2286
- }
2287
- getIsNotSelecting(m) {
2288
- const method = m || this.methodForSelecting;
2289
- return isMethodForSelecting(method, MethodsForSelecting.NONE);
2290
- }
2291
- getIsSingleSelecting(m) {
2292
- const method = m || this.methodForSelecting;
2293
- return isMethodForSelecting(method, MethodsForSelecting.SELECT);
2294
- }
2295
- getIsMultiSelecting(m) {
2296
- const method = m || this.methodForSelecting;
2297
- return isMethodForSelecting(method, MethodsForSelecting.MULTI_SELECT);
2298
- }
2299
- getIsVertical(d) {
2300
- const dir = d || this.direction;
2301
- return isDirection(dir, Directions.VERTICAL);
2302
- }
2303
- createDisplayComponentsIfNeed(displayItems) {
2304
- if (!displayItems || !this._listContainerRef) {
2305
- this._trackBox.setDisplayObjectIndexMapById({});
2306
- return;
2307
- }
2308
- if (this._isSnappingMethodAdvanced && this.snap) {
2309
- if (!this._snapedDisplayComponent && this._snapContainerRef) {
2310
- const comp = this._snapContainerRef.createComponent(this._itemComponentClass);
2311
- comp.instance.regular = true;
2312
- this._snapedDisplayComponent = comp;
2313
- this._trackBox.snapedDisplayComponent = this._snapedDisplayComponent;
2314
- this._resizeSnappedObserver = new ResizeObserver(this._resizeSnappedComponentHandler);
2315
- this._resizeSnappedObserver.observe(comp.instance.element);
2316
- }
2317
- }
2318
- this._trackBox.items = displayItems;
2319
- const _listContainerRef = this._listContainerRef;
2320
- const maxLength = displayItems.length, components = this._displayComponents;
2321
- while (components.length < maxLength) {
2322
- if (_listContainerRef) {
2323
- const comp = _listContainerRef.createComponent(this._itemComponentClass);
2324
- components.push(comp);
2325
- this._componentsResizeObserver.observe(comp.instance.element);
2326
- }
2327
- }
2328
- this.resetRenderers();
2329
- }
2330
- updateRegularRenderer() {
2331
- this._resizeSnappedComponentHandler();
2332
- }
2333
- resetRenderers(itemRenderer) {
2334
- const doMap = {};
2335
- for (let i = 0, l = this._displayComponents.length; i < l; i++) {
2336
- const item = this._displayComponents[i];
2337
- item.instance.renderer = itemRenderer || this.itemRenderer;
2338
- doMap[item.instance.id] = i;
2339
- }
2340
- if (this._isSnappingMethodAdvanced && this.snap && this._snapedDisplayComponent && this._snapContainerRef) {
2341
- const comp = this._snapedDisplayComponent;
2342
- comp.instance.renderer = itemRenderer || this.itemRenderer;
2343
- }
2344
- this._trackBox.setDisplayObjectIndexMapById(doMap);
2345
- }
2346
- /**
2347
- * Tracking by id
2348
- */
2349
- tracking() {
2350
- this._trackBox.track();
2351
- }
2352
- resetBoundsSize(isVertical, totalSize) {
2353
- const l = this._list;
2354
- if (l) {
2355
- l.nativeElement.style[isVertical ? HEIGHT_PROP_NAME : WIDTH_PROP_NAME] = `${totalSize}${PX}`;
2356
- }
2357
- }
2358
- /**
2359
- * Returns the bounds of an element with a given id
2360
- */
2361
- getItemBounds(id) {
2362
- return this._trackBox.getItemBounds(id);
2363
- }
2364
- /**
2365
- * The method scrolls the list to the element with the given id and returns the value of the scrolled area.
2366
- * Behavior accepts the values ​​"auto", "instant" and "smooth".
2367
- */
2368
- scrollTo(id, behavior = BEHAVIOR_AUTO) {
2369
- this.scrollToExecutor(id, behavior);
2370
- }
2371
- clearScrollToRepeatExecutionTimeout() {
2372
- clearTimeout(this._scrollToRepeatExecutionTimeout);
2373
- }
2374
- scrollToExecutor(id, behavior, iteration = 0, isLastIteration = false) {
2375
- const items = this.items;
2376
- if (!items || !items.length) {
2377
- return;
2378
- }
2379
- const dynamicSize = this.dynamicSize, container = this._container, itemSize = this.itemSize;
2380
- if (container) {
2381
- this.clearScrollToRepeatExecutionTimeout();
2382
- if (dynamicSize) {
2383
- if (container) {
2384
- container.nativeElement.removeEventListener(SCROLL, this._onScrollHandler);
2385
- }
2386
- const { width, height } = this._$bounds.getValue() || { width: 0, height: 0 }, stickyMap = this.stickyMap, items = this.items, isVertical = this._isVertical, delta = this._trackBox.delta, opts = {
2387
- bounds: { width, height }, collection: items, dynamicSize, isVertical: this._isVertical, itemSize,
2388
- bufferSize: this.bufferSize, maxBufferSize: this.maxBufferSize, scrollSize: (isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft) + delta,
2389
- snap: this.snap, fromItemId: id, enabledBufferOptimization: this.enabledBufferOptimization,
2390
- }, scrollSize = this._trackBox.getItemPosition(id, stickyMap, opts), params = { [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior };
2391
- if (scrollSize === -1) {
2392
- container.nativeElement.addEventListener(SCROLL, this._onScrollHandler);
2393
- return;
2394
- }
2395
- this._trackBox.clearDelta();
2396
- if (container) {
2397
- const { displayItems, totalSize } = this._trackBox.updateCollection(items, stickyMap, Object.assign(Object.assign({}, opts), { scrollSize, fromItemId: isLastIteration ? undefined : id })), delta = this._trackBox.delta;
2398
- this._trackBox.clearDelta();
2399
- let actualScrollSize = scrollSize + delta;
2400
- this.resetBoundsSize(isVertical, totalSize);
2401
- this.createDisplayComponentsIfNeed(displayItems);
2402
- this.tracking();
2403
- const _scrollSize = this._trackBox.getItemPosition(id, stickyMap, Object.assign(Object.assign({}, opts), { scrollSize: actualScrollSize, fromItemId: id }));
2404
- if (_scrollSize === -1) {
2405
- container.nativeElement.addEventListener(SCROLL, this._onScrollHandler);
2406
- return;
2407
- }
2408
- const notChanged = actualScrollSize === _scrollSize;
2409
- if (!notChanged || iteration < MAX_SCROLL_TO_ITERATIONS) {
2410
- this.clearScrollToRepeatExecutionTimeout();
2411
- this._scrollToRepeatExecutionTimeout = setTimeout(() => {
2412
- this.scrollToExecutor(id, BEHAVIOR_INSTANT, iteration + 1, notChanged);
2413
- });
2414
- }
2415
- else {
2416
- this._$scrollSize.next(actualScrollSize);
2417
- container.nativeElement.addEventListener(SCROLL, this._onScrollHandler);
2418
- }
2419
- }
2420
- container.nativeElement.scrollTo(params);
2421
- this._$scrollSize.next(scrollSize);
2422
- }
2423
- else {
2424
- const index = items.findIndex(item => item.id === id);
2425
- if (index > -1) {
2426
- const scrollSize = index * this.itemSize;
2427
- const params = { [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior };
2428
- container.nativeElement.scrollTo(params);
2429
- }
2430
- }
2431
- }
2432
- }
2433
- /**
2434
- * Scrolls the scroll area to the desired element with the specified ID.
2435
- */
2436
- scrollToEnd(behavior = BEHAVIOR_INSTANT) {
2437
- const items = this.items, latItem = items[items.length > 0 ? items.length - 1 : 0];
2438
- this.scrollTo(latItem.id, behavior);
2439
- }
2440
- /** @internal */
2441
- ngAfterViewInit() {
2442
- this.afterViewInit();
2443
- }
2444
- afterViewInit() {
2445
- const containerEl = this._container;
2446
- if (containerEl) {
2447
- // for direction calculation
2448
- containerEl.nativeElement.addEventListener(SCROLL, this._onContainerScrollHandler);
2449
- containerEl.nativeElement.addEventListener(SCROLL_END, this._onContainerScrollEndHandler);
2450
- containerEl.nativeElement.addEventListener(SCROLL, this._onScrollHandler);
2451
- this._resizeObserver = new ResizeObserver(this._onResizeHandler);
2452
- this._resizeObserver.observe(containerEl.nativeElement);
2453
- this._onResizeHandler();
2454
- }
2455
- }
2456
- /** @internal */
2457
- ngOnDestroy() {
2458
- super.ngOnDestroy();
2459
- this.dispose();
2460
- }
2461
- dispose() {
2462
- this.clearScrollToRepeatExecutionTimeout();
2463
- if (this._trackBox) {
2464
- this._trackBox.dispose();
2465
- }
2466
- if (this._componentsResizeObserver) {
2467
- this._componentsResizeObserver.disconnect();
2468
- }
2469
- if (this._resizeObserver) {
2470
- this._resizeObserver.disconnect();
2471
- }
2472
- if (this._resizeSnappedObserver) {
2473
- this._resizeSnappedObserver.disconnect();
2474
- }
2475
- const containerEl = this._container;
2476
- if (containerEl) {
2477
- containerEl.nativeElement.removeEventListener(SCROLL, this._onScrollHandler);
2478
- containerEl.nativeElement.removeEventListener(SCROLL, this._onContainerScrollHandler);
2479
- containerEl.nativeElement.removeEventListener(SCROLL_END, this._onContainerScrollEndHandler);
2480
- }
2481
- if (this._snapedDisplayComponent) {
2482
- this._snapedDisplayComponent.destroy();
2483
- }
2484
- if (this._displayComponents) {
2485
- while (this._displayComponents.length > 0) {
2486
- const comp = this._displayComponents.pop();
2487
- comp === null || comp === void 0 ? void 0 : comp.destroy();
2488
- }
2489
- }
2490
- if (this._service) {
2491
- this._service.destroy();
2492
- }
2493
- }
2494
- }
2495
- NgVirtualListComponent.__nextId = 0;
2496
- NgVirtualListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: NgVirtualListService }], target: i0.ɵɵFactoryTarget.Component });
2497
- NgVirtualListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NgVirtualListComponent, selector: "ng-virtual-list", inputs: { items: "items", selectedIds: "selectedIds", snap: "snap", enabledBufferOptimization: "enabledBufferOptimization", itemRenderer: "itemRenderer", stickyMap: "stickyMap", itemSize: "itemSize", dynamicSize: "dynamicSize", direction: "direction", itemsOffset: "itemsOffset", bufferSize: "bufferSize", maxBufferSize: "maxBufferSize", trackBy: "trackBy", snappingMethod: "snappingMethod", methodForSelecting: "methodForSelecting" }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd", onViewportChange: "onViewportChange", onItemClick: "onItemClick", onSelect: "onSelect" }, 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 }], usesInheritance: true, 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\" #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </div>\r\n</div>", styles: [":host{position:relative;display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.horizontal) .ngvl__list{display:inline-flex}:host(.horizontal) .ngvl__scroller{overflow:auto hidden}:host(.vertical) .ngvl__scroller{overflow:hidden auto}:host(.vertical){height:320px}.ngvl__scroller{overflow:auto;width:100%;height:100%}.ngvl__list-snapper{pointer-events:none;position:absolute;list-style:none;left:0;top:0;z-index:1}.ngvl__list{position:relative;list-style:none;padding:0;margin:0;width:100%;height:100%}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
2498
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListComponent, decorators: [{
2499
- type: Component,
2500
- args: [{ selector: 'ng-virtual-list', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, providers: [NgVirtualListService], 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\" #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </div>\r\n</div>", styles: [":host{position:relative;display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.horizontal) .ngvl__list{display:inline-flex}:host(.horizontal) .ngvl__scroller{overflow:auto hidden}:host(.vertical) .ngvl__scroller{overflow:hidden auto}:host(.vertical){height:320px}.ngvl__scroller{overflow:auto;width:100%;height:100%}.ngvl__list-snapper{pointer-events:none;position:absolute;list-style:none;left:0;top:0;z-index:1}.ngvl__list{position:relative;list-style:none;padding:0;margin:0;width:100%;height:100%}\n"] }]
2501
- }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: NgVirtualListService }]; }, propDecorators: { _listContainerRef: [{
2502
- type: ViewChild,
2503
- args: ['renderersContainer', { read: ViewContainerRef }]
2504
- }], _container: [{
2505
- type: ViewChild,
2506
- args: ['container', { read: (ElementRef) }]
2507
- }], _list: [{
2508
- type: ViewChild,
2509
- args: ['list', { read: (ElementRef) }]
2510
- }], _snapContainerRef: [{
2511
- type: ViewChild,
2512
- args: ['snapRendererContainer', { read: ViewContainerRef }]
2513
- }], _snappedContainer: [{
2514
- type: ViewChild,
2515
- args: ['snapped', { read: ViewContainerRef }]
2516
- }], onScroll: [{
2517
- type: Output
2518
- }], onScrollEnd: [{
2519
- type: Output
2520
- }], onViewportChange: [{
2521
- type: Output
2522
- }], onItemClick: [{
2523
- type: Output
2524
- }], onSelect: [{
2525
- type: Output
2526
- }], items: [{
2527
- type: Input
2528
- }], selectedIds: [{
2529
- type: Input
2530
- }], snap: [{
2531
- type: Input
2532
- }], enabledBufferOptimization: [{
2533
- type: Input
2534
- }], itemRenderer: [{
2535
- type: Input
2536
- }], stickyMap: [{
2537
- type: Input
2538
- }], itemSize: [{
2539
- type: Input
2540
- }], dynamicSize: [{
2541
- type: Input
2542
- }], direction: [{
2543
- type: Input
2544
- }], itemsOffset: [{
2545
- type: Input
2546
- }], bufferSize: [{
2547
- type: Input
2548
- }], maxBufferSize: [{
2549
- type: Input
2550
- }], trackBy: [{
2551
- type: Input
2552
- }], snappingMethod: [{
2553
- type: Input
2554
- }], methodForSelecting: [{
2555
- type: Input
2556
- }] } });
2557
-
2558
- class NgVirtualListModule {
2559
- }
2560
- NgVirtualListModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2561
- NgVirtualListModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListModule, declarations: [NgVirtualListComponent, NgVirtualListItemComponent], imports: [CommonModule], exports: [NgVirtualListComponent] });
2562
- NgVirtualListModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListModule, imports: [CommonModule] });
2563
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgVirtualListModule, decorators: [{
2564
- type: NgModule,
2565
- args: [{
2566
- declarations: [NgVirtualListComponent, NgVirtualListItemComponent],
2567
- exports: [NgVirtualListComponent],
2568
- imports: [CommonModule],
2569
- schemas: [NO_ERRORS_SCHEMA],
2570
- }]
2571
- }] });
2572
-
2573
- /*
2574
- * Public API Surface of ng-virtual-list
2575
- */
2576
-
2577
- /**
2578
- * Generated bundle index. Do not edit.
2579
- */
2580
-
2581
- export { Directions, MethodsForSelecting, NgVirtualListComponent, NgVirtualListItemComponent, NgVirtualListModule, SnappingMethods };
2582
- //# sourceMappingURL=ng-virtual-list.mjs.map