ng-virtual-list 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,16 +4,18 @@ Fast, optimized rendering of extremely large numbers of list items
4
4
 
5
5
  Angular version 19.X.X.
6
6
 
7
- ## Examples
8
-
9
- ### Simple virtual list
10
- ![VirtualList-GoogleChrome2025-06-1323-32-48-ezgif com-video-to-gif-converter](https://github.com/user-attachments/assets/225fabf8-46da-43ec-bef1-41bb295af5d8)
11
-
7
+ ## Installation
12
8
 
13
9
  ```bash
14
10
  npm i ng-virtual-list
15
11
  ```
16
12
 
13
+ ## Examples
14
+
15
+ ### Simple virtual list
16
+
17
+ ![VirtualList-GoogleChrome2025-06-1420-49-35-ezgif com-video-to-gif-converter](https://github.com/user-attachments/assets/2d120a77-7715-4d6a-ba8d-bb5030d48947)
18
+
17
19
  Template:
18
20
  ```html
19
21
  <ng-virtual-list class="list simple" [items]="items" [itemRenderer]="itemRenderer" [itemHeight]="40"></ng-virtual-list>
@@ -27,49 +29,6 @@ Template:
27
29
  </ng-template>
28
30
  ```
29
31
 
30
- Styles:
31
- ```css
32
- // reset ng-virtual-list-item styles
33
- .ngvl-item__container {
34
- background-color: unset;
35
- }
36
-
37
- .vl-section {
38
- padding: 20px;
39
- margin-bottom: 8px;
40
-
41
- &>h1 {
42
- margin-bottom: 0;
43
- }
44
- }
45
-
46
- .list {
47
- border-radius: 3px;
48
- box-shadow: 1px 2px 8px 4px rgba(0, 0, 0, 0.075);
49
- border: 1px solid rgba(0, 0, 0, 0.1);
50
-
51
- &__container {
52
- width: 100%;
53
- padding: 0 12px;
54
- background-color: rgb(255, 255, 255);
55
- }
56
-
57
- &__group-container {
58
- width: 100%;
59
- padding: 0 12px;
60
- background-color: rgb(230, 234, 238);
61
- font-weight: 600;
62
- font-size: 14px;
63
- text-transform: uppercase;
64
- display: flex;
65
- }
66
-
67
- &.simple {
68
- height: 500px;
69
- }
70
- }
71
- ```
72
-
73
32
  Component:
74
33
  ```ts
75
34
  import { NgVirtualListComponent, IVirtualListCollection } from 'ng-virtual-list';
@@ -92,13 +51,14 @@ export class AppComponent {
92
51
  ```
93
52
 
94
53
  ### Grouped virtual list
95
- ![VirtualList-GoogleChrome2025-06-1416-32-30-ezgif com-crop](https://github.com/user-attachments/assets/72014e35-4e31-4531-8a45-831534301afb)
96
54
 
55
+ #### Without snapping
56
+ ![VirtualList-GoogleChrome2025-06-1420-49-35-ezgif com-video-to-gif-converter (1)](https://github.com/user-attachments/assets/eb1e1709-4feb-489a-82fd-7fc0ff1211cb)
97
57
 
98
58
  Template:
99
59
  ```html
100
60
  <ng-virtual-list class="list simple" [items]="groupItems" [itemRenderer]="groupItemRenderer"
101
- [stickyMap]="groupItemsStickyMap" [itemHeight]="40"></ng-virtual-list>
61
+ [stickyMap]="groupItemsStickyMap" [itemHeight]="40" [snap]="false"></ng-virtual-list>
102
62
 
103
63
  <ng-template #groupItemRenderer let-data="data">
104
64
  @if (data) {
@@ -118,47 +78,31 @@ Template:
118
78
  </ng-template>
119
79
  ```
120
80
 
121
- Styles:
122
- ```css
123
- // reset ng-virtual-list-item styles
124
- .ngvl-item__container {
125
- background-color: unset;
126
- }
81
+ #### With snapping
127
82
 
128
- .vl-section {
129
- padding: 20px;
130
- margin-bottom: 8px;
83
+ ![VirtualList-GoogleChrome2025-06-1420-49-35-ezgif com-video-to-gif-converter (2)](https://github.com/user-attachments/assets/a92e63aa-971d-42ff-a3f8-8811e1731f72)
131
84
 
132
- &>h1 {
133
- margin-bottom: 0;
134
- }
135
- }
136
-
137
- .list {
138
- border-radius: 3px;
139
- box-shadow: 1px 2px 8px 4px rgba(0, 0, 0, 0.075);
140
- border: 1px solid rgba(0, 0, 0, 0.1);
141
-
142
- &__container {
143
- width: 100%;
144
- padding: 0 12px;
145
- background-color: rgb(255, 255, 255);
146
- }
147
-
148
- &__group-container {
149
- width: 100%;
150
- padding: 0 12px;
151
- background-color: rgb(230, 234, 238);
152
- font-weight: 600;
153
- font-size: 14px;
154
- text-transform: uppercase;
155
- display: flex;
156
- }
85
+ Template (with snapping):
86
+ ```html
87
+ <ng-virtual-list class="list simple" [items]="groupItems" [itemRenderer]="groupItemRenderer"
88
+ [stickyMap]="groupItemsStickyMap" [itemHeight]="40" [snap]="true"></ng-virtual-list>
157
89
 
158
- &.simple {
159
- height: 500px;
90
+ <ng-template #groupItemRenderer let-data="data">
91
+ @if (data) {
92
+ @switch (data.type) {
93
+ @case ("group-header") {
94
+ <div class="list__group-container">
95
+ <p>{{data.name}}</p>
96
+ </div>
97
+ }
98
+ @default {
99
+ <div class="list__container">
100
+ <p>{{data.name}}</p>
101
+ </div>
102
+ }
160
103
  }
161
- }
104
+ }
105
+ </ng-template>
162
106
  ```
163
107
 
164
108
  Component:
@@ -197,19 +141,19 @@ export class AppComponent {
197
141
 
198
142
  Inputs
199
143
 
200
- | Property | type | Description |
144
+ | Property | Type | Description |
201
145
  |---|---|---|
202
146
  | items | [IVirtualListCollection](https://github.com/DjonnyX/ng-virtual-list/blob/main/projects/ng-virtual-list/src/lib/models/collection.model.ts) | Collection of list items |
203
147
  | itemHeight | number | Height of a typical list item |
204
148
  | itemRenderer | TemplateRef | Rendering element template |
205
149
  | stickyMap | [IVirtualListStickyMap](https://github.com/DjonnyX/ng-virtual-list/blob/main/projects/ng-virtual-list/src/lib/models/sticky-map.model.ts) | Dictionary zIndex by id of the list element. If the value is not set or equal to 0, then a simple element is displayed, if the value is greater than 0, then the sticky position mode is enabled for the element |
150
+ | snap | boolean? | Determines whether elements will snap. Default value is "true" |
206
151
 
207
152
  <br/>
208
153
 
209
154
  Outputs
210
155
 
211
- | event | type | Description |
156
+ | Event | Type | Description |
212
157
  |---|---|---|
213
158
  | onScroll | (e: Event) => void | Fires when the list has been scrolled |
214
- | onScrollEnd | (e: Event) => void | Fires when the list has completed scrolling. |
215
-
159
+ | onScrollEnd | (e: Event) => void | Fires when the list has completed scrolling. |
@@ -20,13 +20,20 @@ class NgVirtualListItemComponent {
20
20
  toObservable(this.data).pipe(takeUntilDestroyed(), filter(data => !!data), tap(data => {
21
21
  const styles = this._elementRef.nativeElement.style;
22
22
  if (data.config.sticky > 1) {
23
- styles.position = 'sticky';
23
+ if (data.config.snap) {
24
+ styles.position = 'sticky';
25
+ }
24
26
  styles.zIndex = String(data.config.sticky);
25
27
  }
26
28
  else {
27
- styles.position = 'absolute';
29
+ if (data.config.snap) {
30
+ styles.position = 'absolute';
31
+ }
28
32
  styles.zIndex = String(data.config.sticky ?? 1);
29
33
  }
34
+ if (!data.config.snap) {
35
+ styles.position = 'absolute';
36
+ }
30
37
  styles.transform = `translate3d(0, ${data.measures.y}px , 0)`;
31
38
  styles.height = `${data.measures.height}px`;
32
39
  })).subscribe();
@@ -49,6 +56,7 @@ class NgVirtualListComponent {
49
56
  onScroll = output();
50
57
  onScrollEnd = output();
51
58
  items = input.required();
59
+ snap = input(true);
52
60
  itemRenderer = input.required();
53
61
  stickyMap = input({});
54
62
  itemHeight = input(DEFAULT_ITEM_HEIGHT);
@@ -71,34 +79,37 @@ class NgVirtualListComponent {
71
79
  };
72
80
  _sizeCacheMap = new Map();
73
81
  constructor() {
74
- const $bounds = toObservable(this._bounds).pipe(filter(b => !!b)), $items = toObservable(this.items).pipe(map(i => !i ? [] : i)), $scrollSize = toObservable(this._scrollSize), $itemHeight = toObservable(this.itemHeight), $itemsOffset = toObservable(this._itemsOffset), $stickyMap = toObservable(this.stickyMap);
75
- combineLatest([$bounds, $items, $stickyMap, $scrollSize, $itemHeight, $itemsOffset]).pipe(takeUntilDestroyed(), switchMap(([bounds, items, stickyMap, scrollSize, itemHeight, itemsOffset]) => {
82
+ const $bounds = toObservable(this._bounds).pipe(filter(b => !!b)), $items = toObservable(this.items).pipe(map(i => !i ? [] : i)), $scrollSize = toObservable(this._scrollSize), $itemHeight = toObservable(this.itemHeight), $itemsOffset = toObservable(this._itemsOffset), $stickyMap = toObservable(this.stickyMap), $snap = toObservable(this.snap);
83
+ combineLatest([$bounds, $items, $stickyMap, $scrollSize, $itemHeight, $itemsOffset, $snap]).pipe(takeUntilDestroyed(), switchMap(([bounds, items, stickyMap, scrollSize, itemHeight, itemsOffset, snap]) => {
76
84
  const { width, height } = bounds;
77
85
  const itemsFromStartToScrollEnd = Math.floor(scrollSize / itemHeight), itemsFromStartToDisplayEnd = Math.ceil((scrollSize + height) / itemHeight), leftHiddenItemsWeight = itemsFromStartToScrollEnd * itemHeight, totalItemsToDisplayEndWeight = itemsFromStartToDisplayEnd * itemHeight, totalItems = items.length, totalSize = totalItems * itemHeight, itemsOnDisplay = totalItemsToDisplayEndWeight - leftHiddenItemsWeight;
78
86
  return of({
79
87
  items, stickyMap, itemsOffset, width, scrollSize, itemsFromStartToScrollEnd, itemsFromStartToDisplayEnd,
80
- itemsOnDisplay, leftHiddenItemsWeight, itemHeight, totalSize
88
+ itemsOnDisplay, leftHiddenItemsWeight, itemHeight, totalSize, snap
81
89
  });
82
- }), tap(({ items, stickyMap, itemsOffset, width, scrollSize, itemsFromStartToScrollEnd, itemsFromStartToDisplayEnd, itemsOnDisplay, leftHiddenItemsWeight, itemHeight, totalSize }) => {
90
+ }), tap(({ items, stickyMap, itemsOffset, width, scrollSize, itemsFromStartToScrollEnd, itemsFromStartToDisplayEnd, itemsOnDisplay, leftHiddenItemsWeight, itemHeight, totalSize, snap }) => {
83
91
  const displayItems = [], totalItems = items.length, leftItemLength = itemsFromStartToScrollEnd - itemsOffset < Math.min(itemsFromStartToScrollEnd, itemsOffset) ? 0 : itemsOffset, rightItemLength = itemsFromStartToDisplayEnd + itemsOffset > totalItems
84
92
  ? totalItems - itemsFromStartToDisplayEnd : itemsOffset, leftItemsWeight = leftItemLength * itemHeight, rightItemsWeight = rightItemLength * itemHeight, startIndex = itemsFromStartToScrollEnd - leftItemLength;
85
93
  let y = leftHiddenItemsWeight - leftItemsWeight, renderWeight = itemsOnDisplay + leftItemsWeight + rightItemsWeight, stickyItem;
86
- for (let i = startIndex; i >= 0; i--) {
87
- const id = items[i].id, sticky = stickyMap[id];
88
- if (sticky > 0) {
89
- const measures = {
90
- x: 0,
91
- y: scrollSize,
92
- width,
93
- height: itemHeight,
94
- }, config = {
95
- sticky,
96
- };
97
- const itemData = { ...items[i] };
98
- delete itemData.id;
99
- stickyItem = { id, measures, data: itemData, config };
100
- displayItems.push(stickyItem);
101
- break;
94
+ if (snap) {
95
+ for (let i = startIndex; i >= 0; i--) {
96
+ const id = items[i].id, sticky = stickyMap[id];
97
+ if (sticky > 0) {
98
+ const measures = {
99
+ x: 0,
100
+ y: scrollSize,
101
+ width,
102
+ height: itemHeight,
103
+ }, config = {
104
+ sticky,
105
+ snap,
106
+ };
107
+ const itemData = { ...items[i] };
108
+ delete itemData.id;
109
+ stickyItem = { id, measures, data: itemData, config };
110
+ displayItems.push(stickyItem);
111
+ break;
112
+ }
102
113
  }
103
114
  }
104
115
  let i = startIndex, nextSticky;
@@ -106,13 +117,14 @@ class NgVirtualListComponent {
106
117
  if (i >= totalItems) {
107
118
  break;
108
119
  }
109
- const id = items[i].id, snapen = stickyMap[id] > 0 && y <= scrollSize, measures = {
120
+ const id = items[i].id, snaped = snap && stickyMap[id] > 0 && y <= scrollSize, measures = {
110
121
  x: 0,
111
- y: snapen ? scrollSize : y,
122
+ y: snaped ? scrollSize : y,
112
123
  width,
113
124
  height: itemHeight,
114
125
  }, config = {
115
- sticky: snapen ? stickyMap[id] : 0,
126
+ sticky: snaped ? stickyMap[id] : 0,
127
+ snap,
116
128
  };
117
129
  const itemData = { ...items[i] };
118
130
  delete itemData.id;
@@ -192,7 +204,7 @@ class NgVirtualListComponent {
192
204
  }
193
205
  }
194
206
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
195
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.14", type: NgVirtualListComponent, isStandalone: true, selector: "ng-virtual-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, itemRenderer: { classPropertyName: "itemRenderer", publicName: "itemRenderer", isSignal: true, isRequired: true, transformFunction: null }, stickyMap: { classPropertyName: "stickyMap", publicName: "stickyMap", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd" }, viewQueries: [{ propertyName: "_container", first: true, predicate: ["container"], descendants: true, isSignal: true }, { propertyName: "_list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "_listContainerRef", first: true, predicate: ["renderersContainer"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div #container class=\"ngvl__container\">\r\n <ul #list class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{display:block;height:400px;width:100%;max-height:100%;overflow:hidden}.ngvl__container{overflow:auto;width:100%;height:100%}.ngvl__list{position:relative;list-style:none;padding:0;margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
207
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.14", type: NgVirtualListComponent, isStandalone: true, selector: "ng-virtual-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, snap: { classPropertyName: "snap", publicName: "snap", isSignal: true, isRequired: false, transformFunction: null }, itemRenderer: { classPropertyName: "itemRenderer", publicName: "itemRenderer", isSignal: true, isRequired: true, transformFunction: null }, stickyMap: { classPropertyName: "stickyMap", publicName: "stickyMap", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd" }, viewQueries: [{ propertyName: "_container", first: true, predicate: ["container"], descendants: true, isSignal: true }, { propertyName: "_list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "_listContainerRef", first: true, predicate: ["renderersContainer"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div #container class=\"ngvl__container\">\r\n <ul #list class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{display:block;height:400px;width:100%;max-height:100%;overflow:hidden}.ngvl__container{overflow:auto;width:100%;height:100%}.ngvl__list{position:relative;list-style:none;padding:0;margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
196
208
  }
197
209
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgVirtualListComponent, decorators: [{
198
210
  type: Component,
@@ -1 +1 @@
1
- {"version":3,"file":"ng-virtual-list.mjs","sources":["../../../projects/ng-virtual-list/src/lib/components/ng-virtual-list-item.component.ts","../../../projects/ng-virtual-list/src/lib/components/ng-virtual-list-item.component.html","../../../projects/ng-virtual-list/src/lib/const/index.ts","../../../projects/ng-virtual-list/src/lib/ng-virtual-list.component.ts","../../../projects/ng-virtual-list/src/lib/ng-virtual-list.component.html","../../../projects/ng-virtual-list/src/public-api.ts","../../../projects/ng-virtual-list/src/ng-virtual-list.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\r\nimport { Component, ElementRef, signal, TemplateRef } from '@angular/core';\r\nimport { IRenderVirtualListItem } from '../models/render-item.model';\r\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\r\nimport { filter, tap } from 'rxjs';\r\n\r\n@Component({\r\n selector: 'ng-virtual-list-item',\r\n imports: [CommonModule],\r\n templateUrl: './ng-virtual-list-item.component.html',\r\n styleUrl: './ng-virtual-list-item.component.scss'\r\n})\r\nexport class NgVirtualListItemComponent {\r\n data = signal<IRenderVirtualListItem | undefined>(undefined);\r\n\r\n set item(v: IRenderVirtualListItem | undefined) {\r\n this.data.set(v);\r\n }\r\n\r\n itemRenderer = signal<TemplateRef<any> | undefined>(undefined);\r\n\r\n set renderer(v: TemplateRef<any> | undefined) {\r\n this.itemRenderer.set(v);\r\n }\r\n\r\n constructor(private _elementRef: ElementRef<HTMLElement>) {\r\n toObservable(this.data).pipe(\r\n takeUntilDestroyed(),\r\n filter(data => !!data),\r\n tap(data => {\r\n const styles = this._elementRef.nativeElement.style;\r\n if (data.config.sticky > 1) {\r\n styles.position = 'sticky';\r\n styles.zIndex = String(data.config.sticky);\r\n } else {\r\n styles.position = 'absolute';\r\n styles.zIndex = String(data.config.sticky ?? 1);\r\n }\r\n styles.transform = `translate3d(0, ${data.measures.y}px , 0)`;\r\n styles.height = `${data.measures.height}px`;\r\n })\r\n ).subscribe();\r\n }\r\n}\r\n","@let item = data();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n<li #listItem class=\"ngvl-item__container\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"{data: item.data || {}}\" />\r\n }\r\n</li>\r\n}","export const DEFAULT_ITEM_HEIGHT = 24;\r\n\r\nexport const DEFAULT_ITEMS_OFFSET = 1;","import {\r\n AfterViewInit, ChangeDetectionStrategy, Component, ComponentRef, ElementRef, input,\r\n OnDestroy, output, signal, TemplateRef, ViewChild, viewChild, ViewContainerRef, ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\r\nimport { combineLatest, filter, map, of, switchMap, tap } from 'rxjs';\r\nimport { NgVirtualListItemComponent } from './components/ng-virtual-list-item.component';\r\nimport { DEFAULT_ITEM_HEIGHT, DEFAULT_ITEMS_OFFSET } from './const';\r\nimport { IVirtualListCollection, IVirtualListStickyMap } from './models';\r\nimport { Id, IRect } from './types';\r\nimport { IRenderVirtualListCollection } from './models/render-collection.model';\r\nimport { IRenderVirtualListItem } from './models/render-item.model';\r\n\r\n@Component({\r\n selector: 'ng-virtual-list',\r\n imports: [CommonModule],\r\n templateUrl: './ng-virtual-list.component.html',\r\n styleUrl: './ng-virtual-list.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.ShadowDom,\r\n})\r\nexport class NgVirtualListComponent implements AfterViewInit, OnDestroy {\r\n @ViewChild('renderersContainer', { read: ViewContainerRef })\r\n protected _listContainerRef: ViewContainerRef | undefined;\r\n\r\n protected _container = viewChild<ElementRef<HTMLDivElement>>('container');\r\n\r\n protected _list = viewChild<ElementRef<HTMLUListElement>>('list');\r\n\r\n onScroll = output<Event>();\r\n\r\n onScrollEnd = output<Event>();\r\n\r\n items = input.required<IVirtualListCollection>();\r\n\r\n itemRenderer = input.required<TemplateRef<any>>();\r\n\r\n stickyMap = input<IVirtualListStickyMap>({});\r\n\r\n itemHeight = input(DEFAULT_ITEM_HEIGHT);\r\n\r\n protected _itemsOffset = signal<number>(DEFAULT_ITEMS_OFFSET);\r\n\r\n protected _displayItems = signal<IRenderVirtualListCollection | null>(null);\r\n\r\n protected _displayComponents: Array<ComponentRef<NgVirtualListItemComponent>> = [];\r\n\r\n protected _bounds = signal<DOMRect | null>(null);\r\n\r\n protected _scrollSize = signal<number>(0);\r\n\r\n private _resizeObserver: ResizeObserver | null = null;\r\n\r\n private _onResizeHandler = () => {\r\n this._bounds.set(this._container()?.nativeElement?.getBoundingClientRect() ?? null);\r\n }\r\n\r\n private _onScrollHandler = (e: Event) => {\r\n const target = e.target as HTMLDivElement;\r\n this._scrollSize.set(target.scrollTop);\r\n\r\n this.onScroll.emit(e);\r\n }\r\n\r\n private _onScrollEndHandler = (e: Event) => {\r\n this.onScrollEnd.emit(e);\r\n }\r\n\r\n private _sizeCacheMap = new Map<Id, IRect>();\r\n\r\n constructor() {\r\n const $bounds = toObservable(this._bounds).pipe(\r\n filter(b => !!b),\r\n ), $items = toObservable(this.items).pipe(\r\n map(i => !i ? [] : i),\r\n ), $scrollSize = toObservable(this._scrollSize),\r\n $itemHeight = toObservable(this.itemHeight),\r\n $itemsOffset = toObservable(this._itemsOffset),\r\n $stickyMap = toObservable(this.stickyMap);\r\n\r\n combineLatest([$bounds, $items, $stickyMap, $scrollSize, $itemHeight, $itemsOffset]).pipe(\r\n takeUntilDestroyed(),\r\n switchMap(([bounds, items, stickyMap, scrollSize, itemHeight, itemsOffset]) => {\r\n const { width, height } = bounds;\r\n const itemsFromStartToScrollEnd = Math.floor(scrollSize / itemHeight),\r\n itemsFromStartToDisplayEnd = Math.ceil((scrollSize + height) / itemHeight),\r\n leftHiddenItemsWeight = itemsFromStartToScrollEnd * itemHeight,\r\n totalItemsToDisplayEndWeight = itemsFromStartToDisplayEnd * itemHeight,\r\n totalItems = items.length,\r\n totalSize = totalItems * itemHeight,\r\n itemsOnDisplay = totalItemsToDisplayEndWeight - leftHiddenItemsWeight;\r\n return of({\r\n items, stickyMap, itemsOffset, width, scrollSize, itemsFromStartToScrollEnd, itemsFromStartToDisplayEnd,\r\n itemsOnDisplay, leftHiddenItemsWeight, itemHeight, totalSize\r\n });\r\n }),\r\n tap(({ items, stickyMap, itemsOffset, width, scrollSize, itemsFromStartToScrollEnd, itemsFromStartToDisplayEnd,\r\n itemsOnDisplay, leftHiddenItemsWeight, itemHeight, totalSize }) => {\r\n const displayItems: IRenderVirtualListCollection = [], totalItems = items.length,\r\n leftItemLength = itemsFromStartToScrollEnd - itemsOffset < Math.min(itemsFromStartToScrollEnd, itemsOffset) ? 0 : itemsOffset,\r\n rightItemLength = itemsFromStartToDisplayEnd + itemsOffset > totalItems\r\n ? totalItems - itemsFromStartToDisplayEnd : itemsOffset,\r\n leftItemsWeight = leftItemLength * itemHeight, rightItemsWeight = rightItemLength * itemHeight,\r\n startIndex = itemsFromStartToScrollEnd - leftItemLength;\r\n let y = leftHiddenItemsWeight - leftItemsWeight,\r\n renderWeight = itemsOnDisplay + leftItemsWeight + rightItemsWeight, stickyItem: IRenderVirtualListItem | undefined;\r\n\r\n for (let i = startIndex; i >= 0; i--) {\r\n const id = items[i].id, sticky = stickyMap[id];\r\n if (sticky > 0) {\r\n const measures = {\r\n x: 0,\r\n y: scrollSize,\r\n width,\r\n height: itemHeight,\r\n }, config = {\r\n sticky,\r\n };\r\n\r\n const itemData: any = { ...items[i] };\r\n delete itemData.id;\r\n\r\n stickyItem = { id, measures, data: itemData, config };\r\n\r\n displayItems.push(stickyItem);\r\n break;\r\n }\r\n }\r\n\r\n let i = startIndex, nextSticky: IRenderVirtualListItem | undefined;\r\n\r\n while (renderWeight > 0) {\r\n if (i >= totalItems) {\r\n break;\r\n }\r\n\r\n const id = items[i].id, snapen = stickyMap[id] > 0 && y <= scrollSize, measures = {\r\n x: 0,\r\n y: snapen ? scrollSize : y,\r\n width,\r\n height: itemHeight,\r\n }, config = {\r\n sticky: snapen ? stickyMap[id] : 0,\r\n };\r\n\r\n const itemData: any = { ...items[i] };\r\n delete itemData.id;\r\n\r\n const item: IRenderVirtualListItem = { id, measures, data: itemData, config };\r\n if (!nextSticky && stickyMap[id] > 0) {\r\n nextSticky = item;\r\n }\r\n\r\n displayItems.push(item);\r\n\r\n this._sizeCacheMap.set(id, measures);\r\n\r\n renderWeight -= itemHeight;\r\n y += itemHeight;\r\n i++;\r\n }\r\n\r\n if (i < totalItems) {\r\n if (nextSticky && stickyItem && nextSticky.measures.y <= leftHiddenItemsWeight + itemHeight) {\r\n stickyItem.measures.y = nextSticky.measures.y - itemHeight;\r\n stickyItem.config.sticky = 1;\r\n }\r\n }\r\n\r\n this._displayItems.set(displayItems);\r\n\r\n const l = this._list();\r\n if (l) {\r\n l.nativeElement.style.height = `${totalSize}px`;\r\n }\r\n\r\n })\r\n ).subscribe();\r\n\r\n toObservable(this._displayItems).pipe(\r\n takeUntilDestroyed(),\r\n tap(displayItems => {\r\n this.createdisplayComponentsIfNeed(displayItems);\r\n this.refresh(displayItems);\r\n }),\r\n ).subscribe();\r\n }\r\n\r\n private createdisplayComponentsIfNeed(displayItems: IRenderVirtualListCollection | null) {\r\n if (!displayItems || !this._listContainerRef) {\r\n return;\r\n }\r\n const _listContainerRef = this._listContainerRef;\r\n\r\n while (this._displayComponents.length < displayItems.length) {\r\n if (_listContainerRef) {\r\n const comp = _listContainerRef.createComponent(NgVirtualListItemComponent);\r\n this._displayComponents.push(comp);\r\n }\r\n }\r\n\r\n if (this._displayComponents.length > displayItems.length) {\r\n while (this._displayComponents.length > displayItems.length) {\r\n const comp = this._displayComponents.pop();\r\n comp?.destroy();\r\n }\r\n }\r\n }\r\n\r\n protected refresh(displayItems: IRenderVirtualListCollection | null) {\r\n if (!displayItems) {\r\n return;\r\n }\r\n\r\n for (let i = 0, l = displayItems.length; i < l; i++) {\r\n const el = this._displayComponents[i];\r\n el.instance.item = displayItems[i];\r\n el.instance.renderer = this.itemRenderer();\r\n }\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n const containerEl = this._container();\r\n if (containerEl) {\r\n containerEl.nativeElement.addEventListener('scroll', this._onScrollHandler);\r\n containerEl.nativeElement.addEventListener('scrollend', this._onScrollEndHandler);\r\n\r\n this._resizeObserver = new ResizeObserver(this._onResizeHandler);\r\n this._resizeObserver.observe(containerEl.nativeElement);\r\n\r\n this._onResizeHandler();\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n const containerEl = this._container();\r\n if (containerEl) {\r\n containerEl.nativeElement.removeEventListener('scroll', this._onScrollHandler);\r\n containerEl.nativeElement.removeEventListener('scrollend', this._onScrollEndHandler);\r\n\r\n if (this._resizeObserver) {\r\n this._resizeObserver.unobserve(containerEl.nativeElement);\r\n }\r\n }\r\n }\r\n}\r\n","<div #container class=\"ngvl__container\">\r\n <ul #list class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>","/*\r\n * Public API Surface of ng-virtual-list\r\n */\r\n\r\nexport * from './lib/ng-virtual-list.component';\r\nexport * from './lib/models';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ng-virtual-list.mjs","sources":["../../../projects/ng-virtual-list/src/lib/components/ng-virtual-list-item.component.ts","../../../projects/ng-virtual-list/src/lib/components/ng-virtual-list-item.component.html","../../../projects/ng-virtual-list/src/lib/const/index.ts","../../../projects/ng-virtual-list/src/lib/ng-virtual-list.component.ts","../../../projects/ng-virtual-list/src/lib/ng-virtual-list.component.html","../../../projects/ng-virtual-list/src/public-api.ts","../../../projects/ng-virtual-list/src/ng-virtual-list.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\r\nimport { Component, ElementRef, signal, TemplateRef } from '@angular/core';\r\nimport { IRenderVirtualListItem } from '../models/render-item.model';\r\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\r\nimport { filter, tap } from 'rxjs';\r\n\r\n@Component({\r\n selector: 'ng-virtual-list-item',\r\n imports: [CommonModule],\r\n templateUrl: './ng-virtual-list-item.component.html',\r\n styleUrl: './ng-virtual-list-item.component.scss'\r\n})\r\nexport class NgVirtualListItemComponent {\r\n data = signal<IRenderVirtualListItem | undefined>(undefined);\r\n\r\n set item(v: IRenderVirtualListItem | undefined) {\r\n this.data.set(v);\r\n }\r\n\r\n itemRenderer = signal<TemplateRef<any> | undefined>(undefined);\r\n\r\n set renderer(v: TemplateRef<any> | undefined) {\r\n this.itemRenderer.set(v);\r\n }\r\n\r\n constructor(private _elementRef: ElementRef<HTMLElement>) {\r\n toObservable(this.data).pipe(\r\n takeUntilDestroyed(),\r\n filter(data => !!data),\r\n tap(data => {\r\n const styles = this._elementRef.nativeElement.style;\r\n if (data.config.sticky > 1) {\r\n if (data.config.snap) {\r\n styles.position = 'sticky';\r\n }\r\n styles.zIndex = String(data.config.sticky);\r\n } else {\r\n if (data.config.snap) {\r\n styles.position = 'absolute';\r\n }\r\n styles.zIndex = String(data.config.sticky ?? 1);\r\n }\r\n if (!data.config.snap) {\r\n styles.position = 'absolute';\r\n }\r\n styles.transform = `translate3d(0, ${data.measures.y}px , 0)`;\r\n styles.height = `${data.measures.height}px`;\r\n })\r\n ).subscribe();\r\n }\r\n}\r\n","@let item = data();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n<li #listItem class=\"ngvl-item__container\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"{data: item.data || {}}\" />\r\n }\r\n</li>\r\n}","export const DEFAULT_ITEM_HEIGHT = 24;\r\n\r\nexport const DEFAULT_ITEMS_OFFSET = 1;","import {\r\n AfterViewInit, ChangeDetectionStrategy, Component, ComponentRef, ElementRef, input,\r\n OnDestroy, output, signal, TemplateRef, ViewChild, viewChild, ViewContainerRef, ViewEncapsulation,\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\r\nimport { combineLatest, filter, map, of, switchMap, tap } from 'rxjs';\r\nimport { NgVirtualListItemComponent } from './components/ng-virtual-list-item.component';\r\nimport { DEFAULT_ITEM_HEIGHT, DEFAULT_ITEMS_OFFSET } from './const';\r\nimport { IVirtualListCollection, IVirtualListStickyMap } from './models';\r\nimport { Id, IRect } from './types';\r\nimport { IRenderVirtualListCollection } from './models/render-collection.model';\r\nimport { IRenderVirtualListItem } from './models/render-item.model';\r\n\r\n@Component({\r\n selector: 'ng-virtual-list',\r\n imports: [CommonModule],\r\n templateUrl: './ng-virtual-list.component.html',\r\n styleUrl: './ng-virtual-list.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.ShadowDom,\r\n})\r\nexport class NgVirtualListComponent implements AfterViewInit, OnDestroy {\r\n @ViewChild('renderersContainer', { read: ViewContainerRef })\r\n protected _listContainerRef: ViewContainerRef | undefined;\r\n\r\n protected _container = viewChild<ElementRef<HTMLDivElement>>('container');\r\n\r\n protected _list = viewChild<ElementRef<HTMLUListElement>>('list');\r\n\r\n onScroll = output<Event>();\r\n\r\n onScrollEnd = output<Event>();\r\n\r\n items = input.required<IVirtualListCollection>();\r\n\r\n snap = input<boolean>(true);\r\n\r\n itemRenderer = input.required<TemplateRef<any>>();\r\n\r\n stickyMap = input<IVirtualListStickyMap>({});\r\n\r\n itemHeight = input(DEFAULT_ITEM_HEIGHT);\r\n\r\n protected _itemsOffset = signal<number>(DEFAULT_ITEMS_OFFSET);\r\n\r\n protected _displayItems = signal<IRenderVirtualListCollection | null>(null);\r\n\r\n protected _displayComponents: Array<ComponentRef<NgVirtualListItemComponent>> = [];\r\n\r\n protected _bounds = signal<DOMRect | null>(null);\r\n\r\n protected _scrollSize = signal<number>(0);\r\n\r\n private _resizeObserver: ResizeObserver | null = null;\r\n\r\n private _onResizeHandler = () => {\r\n this._bounds.set(this._container()?.nativeElement?.getBoundingClientRect() ?? null);\r\n }\r\n\r\n private _onScrollHandler = (e: Event) => {\r\n const target = e.target as HTMLDivElement;\r\n this._scrollSize.set(target.scrollTop);\r\n\r\n this.onScroll.emit(e);\r\n }\r\n\r\n private _onScrollEndHandler = (e: Event) => {\r\n this.onScrollEnd.emit(e);\r\n }\r\n\r\n private _sizeCacheMap = new Map<Id, IRect>();\r\n\r\n constructor() {\r\n const $bounds = toObservable(this._bounds).pipe(\r\n filter(b => !!b),\r\n ), $items = toObservable(this.items).pipe(\r\n map(i => !i ? [] : i),\r\n ), $scrollSize = toObservable(this._scrollSize),\r\n $itemHeight = toObservable(this.itemHeight),\r\n $itemsOffset = toObservable(this._itemsOffset),\r\n $stickyMap = toObservable(this.stickyMap),\r\n $snap = toObservable(this.snap);\r\n\r\n combineLatest([$bounds, $items, $stickyMap, $scrollSize, $itemHeight, $itemsOffset, $snap]).pipe(\r\n takeUntilDestroyed(),\r\n switchMap(([bounds, items, stickyMap, scrollSize, itemHeight, itemsOffset, snap]) => {\r\n const { width, height } = bounds;\r\n const itemsFromStartToScrollEnd = Math.floor(scrollSize / itemHeight),\r\n itemsFromStartToDisplayEnd = Math.ceil((scrollSize + height) / itemHeight),\r\n leftHiddenItemsWeight = itemsFromStartToScrollEnd * itemHeight,\r\n totalItemsToDisplayEndWeight = itemsFromStartToDisplayEnd * itemHeight,\r\n totalItems = items.length,\r\n totalSize = totalItems * itemHeight,\r\n itemsOnDisplay = totalItemsToDisplayEndWeight - leftHiddenItemsWeight;\r\n return of({\r\n items, stickyMap, itemsOffset, width, scrollSize, itemsFromStartToScrollEnd, itemsFromStartToDisplayEnd,\r\n itemsOnDisplay, leftHiddenItemsWeight, itemHeight, totalSize, snap\r\n });\r\n }),\r\n tap(({ items, stickyMap, itemsOffset, width, scrollSize, itemsFromStartToScrollEnd, itemsFromStartToDisplayEnd,\r\n itemsOnDisplay, leftHiddenItemsWeight, itemHeight, totalSize, snap }) => {\r\n const displayItems: IRenderVirtualListCollection = [], totalItems = items.length,\r\n leftItemLength = itemsFromStartToScrollEnd - itemsOffset < Math.min(itemsFromStartToScrollEnd, itemsOffset) ? 0 : itemsOffset,\r\n rightItemLength = itemsFromStartToDisplayEnd + itemsOffset > totalItems\r\n ? totalItems - itemsFromStartToDisplayEnd : itemsOffset,\r\n leftItemsWeight = leftItemLength * itemHeight, rightItemsWeight = rightItemLength * itemHeight,\r\n startIndex = itemsFromStartToScrollEnd - leftItemLength;\r\n let y = leftHiddenItemsWeight - leftItemsWeight,\r\n renderWeight = itemsOnDisplay + leftItemsWeight + rightItemsWeight, stickyItem: IRenderVirtualListItem | undefined;\r\n\r\n if (snap) {\r\n for (let i = startIndex; i >= 0; i--) {\r\n const id = items[i].id, sticky = stickyMap[id];\r\n if (sticky > 0) {\r\n const measures = {\r\n x: 0,\r\n y: scrollSize,\r\n width,\r\n height: itemHeight,\r\n }, config = {\r\n sticky,\r\n snap,\r\n };\r\n\r\n const itemData: any = { ...items[i] };\r\n delete itemData.id;\r\n\r\n stickyItem = { id, measures, data: itemData, config };\r\n\r\n displayItems.push(stickyItem);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n let i = startIndex, nextSticky: IRenderVirtualListItem | undefined;\r\n\r\n while (renderWeight > 0) {\r\n if (i >= totalItems) {\r\n break;\r\n }\r\n\r\n const id = items[i].id, snaped = snap && stickyMap[id] > 0 && y <= scrollSize, measures = {\r\n x: 0,\r\n y: snaped ? scrollSize : y,\r\n width,\r\n height: itemHeight,\r\n }, config = {\r\n sticky: snaped ? stickyMap[id] : 0,\r\n snap,\r\n };\r\n\r\n const itemData: any = { ...items[i] };\r\n delete itemData.id;\r\n\r\n const item: IRenderVirtualListItem = { id, measures, data: itemData, config };\r\n if (!nextSticky && stickyMap[id] > 0) {\r\n nextSticky = item;\r\n }\r\n\r\n displayItems.push(item);\r\n\r\n this._sizeCacheMap.set(id, measures);\r\n\r\n renderWeight -= itemHeight;\r\n y += itemHeight;\r\n i++;\r\n }\r\n\r\n if (i < totalItems) {\r\n if (nextSticky && stickyItem && nextSticky.measures.y <= leftHiddenItemsWeight + itemHeight) {\r\n stickyItem.measures.y = nextSticky.measures.y - itemHeight;\r\n stickyItem.config.sticky = 1;\r\n }\r\n }\r\n\r\n this._displayItems.set(displayItems);\r\n\r\n const l = this._list();\r\n if (l) {\r\n l.nativeElement.style.height = `${totalSize}px`;\r\n }\r\n\r\n })\r\n ).subscribe();\r\n\r\n toObservable(this._displayItems).pipe(\r\n takeUntilDestroyed(),\r\n tap(displayItems => {\r\n this.createdisplayComponentsIfNeed(displayItems);\r\n this.refresh(displayItems);\r\n }),\r\n ).subscribe();\r\n }\r\n\r\n private createdisplayComponentsIfNeed(displayItems: IRenderVirtualListCollection | null) {\r\n if (!displayItems || !this._listContainerRef) {\r\n return;\r\n }\r\n const _listContainerRef = this._listContainerRef;\r\n\r\n while (this._displayComponents.length < displayItems.length) {\r\n if (_listContainerRef) {\r\n const comp = _listContainerRef.createComponent(NgVirtualListItemComponent);\r\n this._displayComponents.push(comp);\r\n }\r\n }\r\n\r\n if (this._displayComponents.length > displayItems.length) {\r\n while (this._displayComponents.length > displayItems.length) {\r\n const comp = this._displayComponents.pop();\r\n comp?.destroy();\r\n }\r\n }\r\n }\r\n\r\n protected refresh(displayItems: IRenderVirtualListCollection | null) {\r\n if (!displayItems) {\r\n return;\r\n }\r\n\r\n for (let i = 0, l = displayItems.length; i < l; i++) {\r\n const el = this._displayComponents[i];\r\n el.instance.item = displayItems[i];\r\n el.instance.renderer = this.itemRenderer();\r\n }\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n const containerEl = this._container();\r\n if (containerEl) {\r\n containerEl.nativeElement.addEventListener('scroll', this._onScrollHandler);\r\n containerEl.nativeElement.addEventListener('scrollend', this._onScrollEndHandler);\r\n\r\n this._resizeObserver = new ResizeObserver(this._onResizeHandler);\r\n this._resizeObserver.observe(containerEl.nativeElement);\r\n\r\n this._onResizeHandler();\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n const containerEl = this._container();\r\n if (containerEl) {\r\n containerEl.nativeElement.removeEventListener('scroll', this._onScrollHandler);\r\n containerEl.nativeElement.removeEventListener('scrollend', this._onScrollEndHandler);\r\n\r\n if (this._resizeObserver) {\r\n this._resizeObserver.unobserve(containerEl.nativeElement);\r\n }\r\n }\r\n }\r\n}\r\n","<div #container class=\"ngvl__container\">\r\n <ul #list class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>","/*\r\n * Public API Surface of ng-virtual-list\r\n */\r\n\r\nexport * from './lib/ng-virtual-list.component';\r\nexport * from './lib/models';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export interface IRenderVirtualListItemConfig {
2
2
  sticky: number;
3
+ snap?: boolean;
3
4
  }
@@ -10,6 +10,7 @@ export declare class NgVirtualListComponent implements AfterViewInit, OnDestroy
10
10
  onScroll: import("@angular/core").OutputEmitterRef<Event>;
11
11
  onScrollEnd: import("@angular/core").OutputEmitterRef<Event>;
12
12
  items: import("@angular/core").InputSignal<IVirtualListCollection>;
13
+ snap: import("@angular/core").InputSignal<boolean>;
13
14
  itemRenderer: import("@angular/core").InputSignal<TemplateRef<any>>;
14
15
  stickyMap: import("@angular/core").InputSignal<IVirtualListStickyMap>;
15
16
  itemHeight: import("@angular/core").InputSignal<number>;
@@ -29,5 +30,5 @@ export declare class NgVirtualListComponent implements AfterViewInit, OnDestroy
29
30
  ngAfterViewInit(): void;
30
31
  ngOnDestroy(): void;
31
32
  static ɵfac: i0.ɵɵFactoryDeclaration<NgVirtualListComponent, never>;
32
- static ɵcmp: i0.ɵɵComponentDeclaration<NgVirtualListComponent, "ng-virtual-list", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "itemRenderer": { "alias": "itemRenderer"; "required": true; "isSignal": true; }; "stickyMap": { "alias": "stickyMap"; "required": false; "isSignal": true; }; "itemHeight": { "alias": "itemHeight"; "required": false; "isSignal": true; }; }, { "onScroll": "onScroll"; "onScrollEnd": "onScrollEnd"; }, never, never, true, never>;
33
+ static ɵcmp: i0.ɵɵComponentDeclaration<NgVirtualListComponent, "ng-virtual-list", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "snap": { "alias": "snap"; "required": false; "isSignal": true; }; "itemRenderer": { "alias": "itemRenderer"; "required": true; "isSignal": true; }; "stickyMap": { "alias": "stickyMap"; "required": false; "isSignal": true; }; "itemHeight": { "alias": "itemHeight"; "required": false; "isSignal": true; }; }, { "onScroll": "onScroll"; "onScrollEnd": "onScrollEnd"; }, never, never, true, never>;
33
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ng-virtual-list",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "author": {
5
5
  "name": "Evgenii Grebennikov",
6
6
  "email": "djonnyx@gmail.com"