@ceriousdevtech/ngx-cerious-scroll 1.0.0 → 1.0.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.
- package/README.md +287 -13
- package/esm2022/lib/cerious-scroll.directive.mjs +231 -18
- package/fesm2022/ceriousdevtech-ngx-cerious-scroll.mjs +230 -17
- package/fesm2022/ceriousdevtech-ngx-cerious-scroll.mjs.map +1 -1
- package/lib/cerious-scroll.directive.d.ts +37 -0
- package/package.json +9 -5
- package/LICENSE-COMMERCIAL +0 -71
package/README.md
CHANGED
|
@@ -1,24 +1,298 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @ceriousdevtech/ngx-cerious-scroll
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
[](https://ceriousdevtech.github.io/ngx-cerious-scroll/)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Angular wrapper for [@ceriousdevtech/cerious-scroll](https://www.npmjs.com/package/@ceriousdevtech/cerious-scroll), providing high-performance virtual scrolling with variable row heights for Angular applications.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
> Note: Don't forget to add `--project ngx-cerious-scroll` or else it will be added to the default project in your `angular.json` file.
|
|
8
|
+
## Features
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
- 🚀 **High Performance** - Handles millions of items with smooth scrolling
|
|
11
|
+
- 📏 **Variable Heights** - Full support for dynamic and variable row heights
|
|
12
|
+
- 🎯 **Angular Integration** - Seamless integration with Angular templates and change detection
|
|
13
|
+
- 🎨 **Flexible Templates** - Use Angular templates with full data binding
|
|
14
|
+
- 📦 **Standalone Components** - Built with Angular standalone components
|
|
15
|
+
- 🔄 **Reactive** - RxJS observables for viewport change events
|
|
16
|
+
- ⚡ **Auto Render** - Automatic rendering on scroll or manual control
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
## Installation
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
```bash
|
|
21
|
+
npm install @ceriousdevtech/ngx-cerious-scroll @ceriousdevtech/cerious-scroll
|
|
22
|
+
```
|
|
15
23
|
|
|
16
|
-
|
|
24
|
+
## Usage
|
|
17
25
|
|
|
18
|
-
|
|
26
|
+
### Component API
|
|
19
27
|
|
|
20
|
-
|
|
28
|
+
The simplest way to use virtual scrolling with the `<cerious-scroll>` component:
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
```typescript
|
|
31
|
+
import { Component } from '@angular/core';
|
|
32
|
+
import { CeriousScrollComponent } from '@ceriousdevtech/ngx-cerious-scroll';
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
@Component({
|
|
35
|
+
selector: 'app-my-list',
|
|
36
|
+
standalone: true,
|
|
37
|
+
imports: [CeriousScrollComponent],
|
|
38
|
+
template: `
|
|
39
|
+
<cerious-scroll
|
|
40
|
+
[items]="items"
|
|
41
|
+
[options]="scrollOptions"
|
|
42
|
+
(viewportChange)="onViewportChange($event)">
|
|
43
|
+
<ng-template ceriousScrollItem let-item let-index="index">
|
|
44
|
+
<div class="row">
|
|
45
|
+
{{ index }}: {{ item.title }}
|
|
46
|
+
</div>
|
|
47
|
+
</ng-template>
|
|
48
|
+
</cerious-scroll>
|
|
49
|
+
`,
|
|
50
|
+
styles: [`
|
|
51
|
+
cerious-scroll {
|
|
52
|
+
height: 600px;
|
|
53
|
+
display: block;
|
|
54
|
+
}
|
|
55
|
+
.row {
|
|
56
|
+
padding: 16px;
|
|
57
|
+
border-bottom: 1px solid #eee;
|
|
58
|
+
}
|
|
59
|
+
`]
|
|
60
|
+
})
|
|
61
|
+
export class MyListComponent {
|
|
62
|
+
items = Array.from({ length: 10000 }, (_, i) => ({
|
|
63
|
+
id: i,
|
|
64
|
+
title: `Item ${i}`
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
scrollOptions = {
|
|
68
|
+
wheel: { enabled: true },
|
|
69
|
+
touch: { enabled: true },
|
|
70
|
+
keyboard: { enabled: true },
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
onViewportChange(detail: any) {
|
|
74
|
+
console.log('Viewport changed:', detail);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Directive API
|
|
80
|
+
|
|
81
|
+
For more control, use the `[ceriousScroll]` directive on any element:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { Component, TemplateRef, ViewChild } from '@angular/core';
|
|
85
|
+
import { CeriousScrollDirective } from '@ceriousdevtech/ngx-cerious-scroll';
|
|
86
|
+
|
|
87
|
+
@Component({
|
|
88
|
+
selector: 'app-advanced-list',
|
|
89
|
+
standalone: true,
|
|
90
|
+
imports: [CeriousScrollDirective],
|
|
91
|
+
template: `
|
|
92
|
+
<div
|
|
93
|
+
ceriousScroll
|
|
94
|
+
[ceriousScrollItems]="items"
|
|
95
|
+
[ceriousScrollItemTemplate]="rowTemplate"
|
|
96
|
+
[ceriousScrollOptions]="options"
|
|
97
|
+
[ceriousScrollAutoRender]="true"
|
|
98
|
+
(ceriousScrollViewportChange)="onViewportChange($event)"
|
|
99
|
+
(ceriousScrollMeasuredViewport)="onMeasured($event)"
|
|
100
|
+
(ceriousScrollReady)="onReady($event)"
|
|
101
|
+
class="viewport">
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<ng-template #rowTemplate let-item let-index="index">
|
|
105
|
+
<div class="row" [style.height.px]="getRowHeight(index)">
|
|
106
|
+
<strong>#{{ index }}</strong>: {{ item.name }}
|
|
107
|
+
</div>
|
|
108
|
+
</ng-template>
|
|
109
|
+
`,
|
|
110
|
+
styles: [`
|
|
111
|
+
.viewport {
|
|
112
|
+
height: 600px;
|
|
113
|
+
overflow: hidden;
|
|
114
|
+
}
|
|
115
|
+
`]
|
|
116
|
+
})
|
|
117
|
+
export class AdvancedListComponent {
|
|
118
|
+
items = Array.from({ length: 50000 }, (_, i) => ({
|
|
119
|
+
id: i,
|
|
120
|
+
name: `Row ${i}`
|
|
121
|
+
}));
|
|
122
|
+
|
|
123
|
+
options = {
|
|
124
|
+
wheel: { enabled: true },
|
|
125
|
+
touch: { enabled: true },
|
|
126
|
+
keyboard: { enabled: true },
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
getRowHeight(index: number): number {
|
|
130
|
+
// Variable row heights
|
|
131
|
+
return 40 + (index % 5) * 10;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
onViewportChange(detail: any) {
|
|
135
|
+
console.log('Scroll position:', detail);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
onMeasured(range: any) {
|
|
139
|
+
console.log('Rendered range:', range);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
onReady(scroller: any) {
|
|
143
|
+
console.log('Scroller ready:', scroller);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Using with Large Datasets (getItem)
|
|
149
|
+
|
|
150
|
+
For very large datasets, use `getItem` instead of passing the entire array:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { Component } from '@angular/core';
|
|
154
|
+
import { CeriousScrollDirective } from '@ceriousdevtech/ngx-cerious-scroll';
|
|
155
|
+
|
|
156
|
+
@Component({
|
|
157
|
+
selector: 'app-large-list',
|
|
158
|
+
standalone: true,
|
|
159
|
+
imports: [CeriousScrollDirective],
|
|
160
|
+
template: `
|
|
161
|
+
<div
|
|
162
|
+
ceriousScroll
|
|
163
|
+
[ceriousScrollTotalElements]="1000000"
|
|
164
|
+
[ceriousScrollGetItem]="getItem"
|
|
165
|
+
[ceriousScrollItemTemplate]="rowTpl"
|
|
166
|
+
[ceriousScrollOptions]="options"
|
|
167
|
+
class="viewport">
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<ng-template #rowTpl let-item let-index="index">
|
|
171
|
+
<div class="row">{{ item.value }}</div>
|
|
172
|
+
</ng-template>
|
|
173
|
+
`,
|
|
174
|
+
styles: [`
|
|
175
|
+
.viewport { height: 600px; }
|
|
176
|
+
.row { padding: 12px; }
|
|
177
|
+
`]
|
|
178
|
+
})
|
|
179
|
+
export class LargeListComponent {
|
|
180
|
+
options = {
|
|
181
|
+
wheel: { enabled: true },
|
|
182
|
+
touch: { enabled: true },
|
|
183
|
+
keyboard: { enabled: true },
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
getItem = (index: number) => {
|
|
187
|
+
return {
|
|
188
|
+
value: `Dynamic item ${index}`
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## API Reference
|
|
195
|
+
|
|
196
|
+
### Component: `<cerious-scroll>`
|
|
197
|
+
|
|
198
|
+
#### Inputs
|
|
199
|
+
- `items: any[]` - Array of items to render
|
|
200
|
+
- `totalElements: number` - Optional explicit total count (defaults to items.length)
|
|
201
|
+
- `itemTemplate: TemplateRef` - Template for rendering each item
|
|
202
|
+
- `options: CeriousScrollOptions` - Configuration options
|
|
203
|
+
- `autoRender: boolean` - Auto-render on scroll (default: true)
|
|
204
|
+
|
|
205
|
+
#### Outputs
|
|
206
|
+
- `viewportChange: EventEmitter<CeriousViewportChangeDetail>` - Emits on scroll
|
|
207
|
+
- `measuredViewport: EventEmitter<MeasuredViewportRange>` - Emits after each render
|
|
208
|
+
- `scrollerReady: EventEmitter<CeriousScroll>` - Emits when scroller is initialized
|
|
209
|
+
|
|
210
|
+
### Directive: `[ceriousScroll]`
|
|
211
|
+
|
|
212
|
+
#### Inputs
|
|
213
|
+
- `ceriousScrollItems: any[]` - Array of items
|
|
214
|
+
- `ceriousScrollTotalElements: number` - Total element count
|
|
215
|
+
- `ceriousScrollGetItem: (index: number) => any` - Function to retrieve item by index
|
|
216
|
+
- `ceriousScrollItemTemplate: TemplateRef` - Template for rendering
|
|
217
|
+
- `ceriousScrollOptions: CeriousScrollOptions` - Configuration options
|
|
218
|
+
- `ceriousScrollAutoRender: boolean` - Auto-render on scroll (default: true)
|
|
219
|
+
|
|
220
|
+
#### Outputs
|
|
221
|
+
- `ceriousScrollViewportChange: EventEmitter<CeriousViewportChangeDetail>` - Scroll events
|
|
222
|
+
- `ceriousScrollMeasuredViewport: EventEmitter<MeasuredViewportRange>` - Render metrics
|
|
223
|
+
- `ceriousScrollReady: EventEmitter<CeriousScroll>` - Scroller instance
|
|
224
|
+
|
|
225
|
+
### Methods
|
|
226
|
+
|
|
227
|
+
Both the component and directive expose:
|
|
228
|
+
|
|
229
|
+
| Method | Description |
|
|
230
|
+
|--------|-------------|
|
|
231
|
+
| `render()` | Trigger a manual render pass. |
|
|
232
|
+
| `recalculate()` | Discard all cached row heights and re-measure the viewport. |
|
|
233
|
+
|
|
234
|
+
**When to call `recalculate()`:** only when the heights of rows you've *already
|
|
235
|
+
rendered* change without their indices changing — e.g. a global font/density
|
|
236
|
+
switch, or swapping every row to a different layout. It forces a synchronous
|
|
237
|
+
re-measure (one `offsetHeight` read per visible row).
|
|
238
|
+
|
|
239
|
+
**Editable rows / immutable updates:** changing `items` to a new reference with
|
|
240
|
+
the **same length** refreshes the visible rows' content *in place* — focus,
|
|
241
|
+
caret, and open dropdowns are preserved — and does **not** clear cached heights.
|
|
242
|
+
So an editable grid that produces a new `items` array on every keystroke won't
|
|
243
|
+
trigger a full viewport re-measure each time. Changing the item **count** does
|
|
244
|
+
clear caches and re-measure. For an incidental single-row height change, the
|
|
245
|
+
engine's `ResizeObserver` (`observeContentChanges`, on by default) updates that
|
|
246
|
+
row's cached height on its own — no manual call needed.
|
|
247
|
+
|
|
248
|
+
### Template Context
|
|
249
|
+
|
|
250
|
+
Templates receive the following context:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
{
|
|
254
|
+
$implicit: TItem; // The item (default binding)
|
|
255
|
+
item: TItem; // The item (named binding)
|
|
256
|
+
index: number; // Row index
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Usage in templates:
|
|
261
|
+
```html
|
|
262
|
+
<ng-template ceriousScrollItem let-item let-index="index">
|
|
263
|
+
{{ index }}: {{ item.name }}
|
|
264
|
+
</ng-template>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Options
|
|
268
|
+
|
|
269
|
+
Configure scrolling behavior with `CeriousScrollOptions`:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
const options = {
|
|
273
|
+
wheel: {
|
|
274
|
+
enabled: true,
|
|
275
|
+
emitViewportChangeEvent: true,
|
|
276
|
+
coalesceViewportChangeEvent: true
|
|
277
|
+
},
|
|
278
|
+
touch: { enabled: true },
|
|
279
|
+
keyboard: { enabled: true },
|
|
280
|
+
attachScrollbar: true,
|
|
281
|
+
autoResize: true,
|
|
282
|
+
observeContentChanges: true
|
|
283
|
+
};
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## License
|
|
287
|
+
|
|
288
|
+
Licensed under the MIT License.
|
|
289
|
+
|
|
290
|
+
See [LICENSE-MIT](./LICENSE-MIT) for details.
|
|
291
|
+
|
|
292
|
+
## Related Packages
|
|
293
|
+
|
|
294
|
+
- [@ceriousdevtech/cerious-scroll](https://www.npmjs.com/package/@ceriousdevtech/cerious-scroll) - Core virtual scrolling engine
|
|
295
|
+
|
|
296
|
+
## Support
|
|
297
|
+
|
|
298
|
+
For issues and feature requests, please visit the [GitHub repository](https://github.com/ceriousdevtech/ngx-cerious-scroll).
|