@ceriousdevtech/ngx-cerious-scroll 1.0.1 → 1.0.3
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 +28 -2
- 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 +7 -3
- package/LICENSE-COMMERCIAL +0 -71
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# @ceriousdevtech/ngx-cerious-scroll
|
|
2
2
|
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
[](https://ceriousdevtech.github.io/ngx-cerious-scroll/)
|
|
5
|
+
|
|
3
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.
|
|
4
7
|
|
|
5
8
|
## Features
|
|
@@ -219,6 +222,29 @@ export class LargeListComponent {
|
|
|
219
222
|
- `ceriousScrollMeasuredViewport: EventEmitter<MeasuredViewportRange>` - Render metrics
|
|
220
223
|
- `ceriousScrollReady: EventEmitter<CeriousScroll>` - Scroller instance
|
|
221
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
|
+
|
|
222
248
|
### Template Context
|
|
223
249
|
|
|
224
250
|
Templates receive the following context:
|
|
@@ -259,9 +285,9 @@ const options = {
|
|
|
259
285
|
|
|
260
286
|
## License
|
|
261
287
|
|
|
262
|
-
|
|
288
|
+
Licensed under the MIT License.
|
|
263
289
|
|
|
264
|
-
See [LICENSE-MIT](./LICENSE-MIT)
|
|
290
|
+
See [LICENSE-MIT](./LICENSE-MIT) for details.
|
|
265
291
|
|
|
266
292
|
## Related Packages
|
|
267
293
|
|
|
@@ -35,7 +35,13 @@ export class CeriousScrollDirective {
|
|
|
35
35
|
this.ceriousScrollReady = new EventEmitter();
|
|
36
36
|
this.hostRef = null;
|
|
37
37
|
this.viewportSub = null;
|
|
38
|
+
this.scheduledRenderFrame = null;
|
|
38
39
|
this.viewByContainer = new Map();
|
|
40
|
+
// Pool of views detached because their container left the viewport. Reusing
|
|
41
|
+
// them on subsequent renders avoids destroying + recreating the entire row
|
|
42
|
+
// component tree on fast scrolls (where the engine's element pool wipes
|
|
43
|
+
// textContent on reused containers, so view rootNodes get orphaned).
|
|
44
|
+
this.freeViews = [];
|
|
39
45
|
}
|
|
40
46
|
ngAfterViewInit() {
|
|
41
47
|
this.ensureInitialized();
|
|
@@ -45,10 +51,33 @@ export class CeriousScrollDirective {
|
|
|
45
51
|
return;
|
|
46
52
|
if (changes['ceriousScrollItems'] || changes['ceriousScrollTotalElements']) {
|
|
47
53
|
const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);
|
|
48
|
-
this.hostRef.scroller.totalElements
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
const countChanged = this.hostRef.scroller.totalElements !== total;
|
|
55
|
+
if (countChanged) {
|
|
56
|
+
// The dataset size changed: the ViewportRenderer stores its own copy of
|
|
57
|
+
// totalElements (set by value at construction) so patching the engine's
|
|
58
|
+
// public property alone leaves the renderer's internal bound stale. The
|
|
59
|
+
// renderer would then use the old count for its viewport-fill loop and
|
|
60
|
+
// bottom-boundary scan, producing phantom renders at out-of-bounds
|
|
61
|
+
// indices (undefined items → 0-height rows → the fill loop never
|
|
62
|
+
// satisfies its height condition → hundreds of renderer callbacks).
|
|
63
|
+
// Recreating the engine gives both the engine and the renderer a fresh,
|
|
64
|
+
// consistent count. ensureInitialized() schedules the first render via
|
|
65
|
+
// queueMicrotask, which runs after the current CD cycle completes.
|
|
66
|
+
this.recreate();
|
|
67
|
+
}
|
|
68
|
+
else if (this.ceriousScrollAutoRender) {
|
|
69
|
+
// Same count, new data reference (e.g. an immutable edit or a sort that
|
|
70
|
+
// happens to keep the same length). The engine reuses the DOM element it
|
|
71
|
+
// already rendered for each overlapping index without re-invoking the
|
|
72
|
+
// renderer, so update the content of every currently-visible row IN
|
|
73
|
+
// PLACE before calling render(). This preserves each row's embedded
|
|
74
|
+
// view (so a focused textbox keeps focus/caret) and does NOT discard
|
|
75
|
+
// cached heights. If a row's height actually changes the engine's
|
|
76
|
+
// ResizeObserver keeps the cache correct on its own; for a wholesale
|
|
77
|
+
// height change across all rows, call recalculate() instead.
|
|
78
|
+
this.refreshRenderedContent();
|
|
51
79
|
this.render();
|
|
80
|
+
}
|
|
52
81
|
}
|
|
53
82
|
if (changes['ceriousScrollOptions'] && !changes['ceriousScrollOptions'].firstChange) {
|
|
54
83
|
// Options are consumed primarily at construction time.
|
|
@@ -56,6 +85,10 @@ export class CeriousScrollDirective {
|
|
|
56
85
|
}
|
|
57
86
|
}
|
|
58
87
|
ngOnDestroy() {
|
|
88
|
+
if (this.scheduledRenderFrame != null) {
|
|
89
|
+
cancelAnimationFrame(this.scheduledRenderFrame);
|
|
90
|
+
this.scheduledRenderFrame = null;
|
|
91
|
+
}
|
|
59
92
|
this.viewportSub?.unsubscribe();
|
|
60
93
|
this.viewportSub = null;
|
|
61
94
|
this.destroyAllViews();
|
|
@@ -72,16 +105,122 @@ export class CeriousScrollDirective {
|
|
|
72
105
|
const hostContainer = this.host.nativeElement;
|
|
73
106
|
const height = hostContainer.clientHeight || hostContainer.offsetHeight;
|
|
74
107
|
const contentContainer = this.hostRef.contentElement;
|
|
108
|
+
// Track whether the engine asked us to bind any row this pass. Pure scroll
|
|
109
|
+
// frames where the visible row set doesn't change still drive render() via
|
|
110
|
+
// the rAF coalescer — there's no point in walking the prune map or
|
|
111
|
+
// emitting the viewport range when nothing was touched.
|
|
112
|
+
let rendererInvocations = 0;
|
|
75
113
|
const renderer = (index, elementContainer) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
114
|
+
rendererInvocations++;
|
|
115
|
+
// Render each row's embedded view with LOCAL change detection
|
|
116
|
+
// (`view.detectChanges()` inside `renderTemplateIntoContainer`) so the
|
|
117
|
+
// engine can measure its height during this pass. Do NOT wrap each row in
|
|
118
|
+
// its own `ngZone.run` — that fires a full `ApplicationRef` tick *per row*
|
|
119
|
+
// (O(newRows × visibleRows) work, janky drags). The single coalesced tick
|
|
120
|
+
// for the whole pass is handled by the caller (`scheduleRender`).
|
|
121
|
+
this.renderTemplateIntoContainer(template, index, elementContainer);
|
|
80
122
|
};
|
|
81
123
|
const range = this.hostRef.scroller.renderViewport(height, contentContainer, renderer);
|
|
82
|
-
|
|
124
|
+
if (rendererInvocations === 0) {
|
|
125
|
+
// Viewport didn't change — skip the prune walk and the (potentially
|
|
126
|
+
// zone-entering) emit.
|
|
127
|
+
return range;
|
|
128
|
+
}
|
|
129
|
+
// Destroy views whose container the engine no longer renders. Without this,
|
|
130
|
+
// every container the engine recycles into its element pool leaves its
|
|
131
|
+
// embedded view attached to ApplicationRef forever — so the attached-view
|
|
132
|
+
// list (and every O(n) `detachView`) grows without bound and scrolling gets
|
|
133
|
+
// progressively slower. Mirrors the React/Vue wrappers, which drop rows that
|
|
134
|
+
// fall out of `getRenderedIndices()`.
|
|
135
|
+
this.pruneDetachedViews();
|
|
136
|
+
// Only re-enter the zone (a global tick) if someone is actually listening.
|
|
137
|
+
if (this.ceriousScrollMeasuredViewport.observed) {
|
|
138
|
+
this.ngZone.run(() => this.ceriousScrollMeasuredViewport.emit(range));
|
|
139
|
+
}
|
|
83
140
|
return range;
|
|
84
141
|
}
|
|
142
|
+
/** Tear down embedded views whose container is no longer part of the viewport. */
|
|
143
|
+
pruneDetachedViews() {
|
|
144
|
+
if (!this.hostRef || this.viewByContainer.size === 0)
|
|
145
|
+
return;
|
|
146
|
+
const scroller = this.hostRef.scroller;
|
|
147
|
+
const active = new Set();
|
|
148
|
+
for (const index of scroller.getRenderedIndices()) {
|
|
149
|
+
const el = scroller.getRenderedElement(index);
|
|
150
|
+
if (el)
|
|
151
|
+
active.add(el);
|
|
152
|
+
}
|
|
153
|
+
for (const [container, view] of this.viewByContainer) {
|
|
154
|
+
if (!active.has(container)) {
|
|
155
|
+
// Detach DOM but keep the view alive in the pool for future reuse.
|
|
156
|
+
// Destroying + recreating views per scroll step dominates frame time.
|
|
157
|
+
for (const node of view.rootNodes) {
|
|
158
|
+
if (node.parentNode)
|
|
159
|
+
node.parentNode.removeChild(node);
|
|
160
|
+
}
|
|
161
|
+
this.viewByContainer.delete(container);
|
|
162
|
+
this.freeViews.push(view);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** Auto-render coalesced to at most once per animation frame. */
|
|
167
|
+
scheduleRender() {
|
|
168
|
+
if (this.scheduledRenderFrame != null)
|
|
169
|
+
return;
|
|
170
|
+
this.scheduledRenderFrame = requestAnimationFrame(() => {
|
|
171
|
+
this.scheduledRenderFrame = null;
|
|
172
|
+
// Run render() OUTSIDE Angular's zone. A full ApplicationRef.tick() on
|
|
173
|
+
// every scroll frame is the primary FPS bottleneck: even when no rows
|
|
174
|
+
// change (pure translation), ngZone.run() causes Angular to walk the
|
|
175
|
+
// entire component tree. Instead we call view.detectChanges() locally
|
|
176
|
+
// inside renderTemplateIntoContainer for each affected row. Zone entry is
|
|
177
|
+
// only needed when creating a brand-new embedded view (to zone-patch its
|
|
178
|
+
// event listeners) — recycled and pooled views were already created inside
|
|
179
|
+
// zone and their listeners remain zone-aware.
|
|
180
|
+
this.render();
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Discard all cached row heights and re-measure the viewport.
|
|
185
|
+
*
|
|
186
|
+
* Call this only when the heights of rows you've *already rendered* may have
|
|
187
|
+
* changed without their indices changing — e.g. a global font/density change,
|
|
188
|
+
* or swapping every row to a different layout. This forces a synchronous
|
|
189
|
+
* re-measure (one `offsetHeight` read per visible row), so do NOT call it on
|
|
190
|
+
* routine edits: a single cell edit keeps its row's size, and the engine's
|
|
191
|
+
* ResizeObserver picks up any incidental resize on its own.
|
|
192
|
+
*/
|
|
193
|
+
recalculate() {
|
|
194
|
+
if (!this.hostRef)
|
|
195
|
+
return null;
|
|
196
|
+
// Discard the cached heights, then re-render. The engine re-measures and
|
|
197
|
+
// re-caches the rendered rows during the pass and refreshes the scroll
|
|
198
|
+
// percentage, so an in-place height change (e.g. expand/collapse) is
|
|
199
|
+
// reflected in the total content height and scrollbar immediately.
|
|
200
|
+
this.hostRef.scroller.clearAllCaches();
|
|
201
|
+
return this.render();
|
|
202
|
+
}
|
|
203
|
+
/** Jump directly to an element index, then render. */
|
|
204
|
+
jumpToElement(index) {
|
|
205
|
+
if (!this.hostRef)
|
|
206
|
+
return null;
|
|
207
|
+
this.hostRef.scroller.jumpToElement(index);
|
|
208
|
+
return this.render();
|
|
209
|
+
}
|
|
210
|
+
/** Scroll to a percentage (0..100), then render. */
|
|
211
|
+
scrollToPercentage(percentage) {
|
|
212
|
+
if (!this.hostRef)
|
|
213
|
+
return null;
|
|
214
|
+
this.hostRef.scroller.handleScrollPercentage(percentage);
|
|
215
|
+
return this.render();
|
|
216
|
+
}
|
|
217
|
+
/** Reset to the top, then render. */
|
|
218
|
+
reset() {
|
|
219
|
+
if (!this.hostRef)
|
|
220
|
+
return null;
|
|
221
|
+
this.hostRef.scroller.reset();
|
|
222
|
+
return this.render();
|
|
223
|
+
}
|
|
85
224
|
recreate() {
|
|
86
225
|
this.viewportSub?.unsubscribe();
|
|
87
226
|
this.viewportSub = null;
|
|
@@ -96,11 +235,16 @@ export class CeriousScrollDirective {
|
|
|
96
235
|
const container = this.host.nativeElement;
|
|
97
236
|
const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);
|
|
98
237
|
this.hostRef = this.cerious.createHost(container, total, this.ceriousScrollOptions, this.ngZone, () => {
|
|
238
|
+
// Coalesce scroll-driven renders to one per frame (the native scrollbar
|
|
239
|
+
// can fire many scroll events between paints).
|
|
99
240
|
if (this.ceriousScrollAutoRender)
|
|
100
|
-
this.
|
|
241
|
+
this.scheduleRender();
|
|
101
242
|
});
|
|
102
243
|
this.viewportSub = this.hostRef.viewportChanges$.subscribe((detail) => {
|
|
103
|
-
|
|
244
|
+
// Skip the global tick when nobody is bound to the output.
|
|
245
|
+
if (this.ceriousScrollViewportChange.observed) {
|
|
246
|
+
this.ngZone.run(() => this.ceriousScrollViewportChange.emit(detail));
|
|
247
|
+
}
|
|
104
248
|
});
|
|
105
249
|
this.ceriousScrollReady.emit(this.hostRef.scroller);
|
|
106
250
|
if (this.ceriousScrollAutoRender) {
|
|
@@ -119,27 +263,96 @@ export class CeriousScrollDirective {
|
|
|
119
263
|
renderTemplateIntoContainer(template, index, elementContainer) {
|
|
120
264
|
const previous = this.viewByContainer.get(elementContainer);
|
|
121
265
|
if (previous) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
this.
|
|
266
|
+
// Recycle: update the bound context and run local CD instead of
|
|
267
|
+
// destroying the embedded view and rebuilding the entire row tree.
|
|
268
|
+
const item = this.getItemForIndex(index);
|
|
269
|
+
previous.context.$implicit = item;
|
|
270
|
+
previous.context.item = item;
|
|
271
|
+
previous.context.index = index;
|
|
272
|
+
// The core engine wipes elementContainer.textContent when reusing it from
|
|
273
|
+
// its pool, orphaning the view's root nodes. Re-append them defensively.
|
|
274
|
+
if (previous.rootNodes.length && previous.rootNodes[0].parentNode !== elementContainer) {
|
|
275
|
+
for (const node of previous.rootNodes) {
|
|
276
|
+
elementContainer.appendChild(node);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
previous.detectChanges();
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
// Try to reuse a pooled view from a container that scrolled out of viewport.
|
|
283
|
+
const pooled = this.freeViews.pop();
|
|
284
|
+
if (pooled) {
|
|
285
|
+
const item = this.getItemForIndex(index);
|
|
286
|
+
pooled.context.$implicit = item;
|
|
287
|
+
pooled.context.item = item;
|
|
288
|
+
pooled.context.index = index;
|
|
289
|
+
elementContainer.textContent = '';
|
|
290
|
+
for (const node of pooled.rootNodes) {
|
|
291
|
+
elementContainer.appendChild(node);
|
|
292
|
+
}
|
|
293
|
+
pooled.detectChanges();
|
|
294
|
+
this.viewByContainer.set(elementContainer, pooled);
|
|
295
|
+
return;
|
|
125
296
|
}
|
|
126
|
-
//
|
|
297
|
+
// No prior view for this container: create one.
|
|
298
|
+
// Enter the Angular zone so the new view's template event listeners
|
|
299
|
+
// ((click), (input), etc.) are zone-patched. This path runs at most
|
|
300
|
+
// once per visible row (after that, the view is recycled from the pool).
|
|
127
301
|
elementContainer.textContent = '';
|
|
128
302
|
const item = this.getItemForIndex(index);
|
|
129
|
-
const view =
|
|
130
|
-
|
|
131
|
-
|
|
303
|
+
const view = this.ngZone.run(() => {
|
|
304
|
+
const v = template.createEmbeddedView({ $implicit: item, item, index });
|
|
305
|
+
this.appRef.attachView(v);
|
|
306
|
+
v.detectChanges();
|
|
307
|
+
return v;
|
|
308
|
+
});
|
|
132
309
|
for (const node of view.rootNodes) {
|
|
133
310
|
elementContainer.appendChild(node);
|
|
134
311
|
}
|
|
135
312
|
this.viewByContainer.set(elementContainer, view);
|
|
136
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Update the bound item/index on every currently-rendered row's embedded view
|
|
316
|
+
* and run change detection, without recreating the views. Used when the data
|
|
317
|
+
* reference changes but the visible indices (and their heights) do not, so row
|
|
318
|
+
* state (focus, selection, open dropdowns) survives the update.
|
|
319
|
+
*/
|
|
320
|
+
/**
|
|
321
|
+
* Re-bind each currently rendered row's context (from the current items/getter)
|
|
322
|
+
* and run change detection on its embedded view. Use this after mutating row
|
|
323
|
+
* state in place (e.g. selection flags) or column-level state read by the row
|
|
324
|
+
* template, when row identity and visible indices have not changed. Cheap
|
|
325
|
+
* relative to `render()` — does not invoke the engine's measurement pass.
|
|
326
|
+
*/
|
|
327
|
+
refreshRenderedContent() {
|
|
328
|
+
if (!this.hostRef)
|
|
329
|
+
return;
|
|
330
|
+
const scroller = this.hostRef.scroller;
|
|
331
|
+
for (const index of scroller.getRenderedIndices()) {
|
|
332
|
+
const container = scroller.getRenderedElement(index);
|
|
333
|
+
if (!container)
|
|
334
|
+
continue;
|
|
335
|
+
const view = this.viewByContainer.get(container);
|
|
336
|
+
if (!view)
|
|
337
|
+
continue;
|
|
338
|
+
const item = this.getItemForIndex(index);
|
|
339
|
+
view.context.$implicit = item;
|
|
340
|
+
view.context.item = item;
|
|
341
|
+
view.context.index = index;
|
|
342
|
+
view.detectChanges();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
137
345
|
destroyAllViews() {
|
|
138
346
|
for (const view of this.viewByContainer.values()) {
|
|
139
347
|
this.appRef.detachView(view);
|
|
140
348
|
view.destroy();
|
|
141
349
|
}
|
|
142
350
|
this.viewByContainer.clear();
|
|
351
|
+
for (const view of this.freeViews) {
|
|
352
|
+
this.appRef.detachView(view);
|
|
353
|
+
view.destroy();
|
|
354
|
+
}
|
|
355
|
+
this.freeViews.length = 0;
|
|
143
356
|
}
|
|
144
357
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CeriousScrollDirective, deps: [{ token: i0.ElementRef }, { token: i0.ApplicationRef }, { token: i0.NgZone }, { token: i1.CeriousScrollService }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
145
358
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: CeriousScrollDirective, isStandalone: true, selector: "[ceriousScroll]", inputs: { ceriousScrollTotalElements: "ceriousScrollTotalElements", ceriousScrollItems: "ceriousScrollItems", ceriousScrollGetItem: "ceriousScrollGetItem", ceriousScrollItemTemplate: "ceriousScrollItemTemplate", ceriousScrollOptions: "ceriousScrollOptions", ceriousScrollAutoRender: "ceriousScrollAutoRender" }, outputs: { ceriousScrollViewportChange: "ceriousScrollViewportChange", ceriousScrollMeasuredViewport: "ceriousScrollMeasuredViewport", ceriousScrollReady: "ceriousScrollReady" }, usesOnChanges: true, ngImport: i0 }); }
|
|
@@ -169,4 +382,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
169
382
|
}], ceriousScrollReady: [{
|
|
170
383
|
type: Output
|
|
171
384
|
}] } });
|
|
172
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VyaW91cy1zY3JvbGwuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWNlcmlvdXMtc2Nyb2xsL3NyYy9saWIvY2VyaW91cy1zY3JvbGwuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFHTCxTQUFTLEVBR1QsWUFBWSxFQUNaLEtBQUssRUFJTCxNQUFNLEdBR1AsTUFBTSxlQUFlLENBQUM7OztBQWF2QixTQUFTLG1CQUFtQixDQUFDLGFBQXdDLEVBQUUsUUFBbUM7SUFDeEcsTUFBTSxTQUFTLEdBQUcsT0FBTyxhQUFhLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLE9BQU8sUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDMUgsSUFBSSxTQUFTLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUN2RCxNQUFNLElBQUksS0FBSyxDQUFDLHVGQUF1RixDQUFDLENBQUM7SUFDM0csQ0FBQztJQUNELHdDQUF3QztJQUN4QyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ2hDLENBQUM7QUFNRCxNQUFNLE9BQU8sc0JBQXNCO0lBaUNqQyxZQUNtQixJQUE2QixFQUM3QixNQUFzQixFQUN0QixNQUFjLEVBQ2QsT0FBNkI7UUFIN0IsU0FBSSxHQUFKLElBQUksQ0FBeUI7UUFDN0IsV0FBTSxHQUFOLE1BQU0sQ0FBZ0I7UUFDdEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFlBQU8sR0FBUCxPQUFPLENBQXNCO1FBcENoRCxtRkFBbUY7UUFDMUUsK0JBQTBCLEdBQWtCLElBQUksQ0FBQztRQUUxRCxpREFBaUQ7UUFDeEMsdUJBQWtCLEdBQTRCLElBQUksQ0FB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LG9CQUFvQjtzQkFBNUIsS0FBSztnQkFHRyx1QkFBdUI7c0JBQS9CLEtBQUs7Z0JBR0ksMkJBQTJCO3NCQUFwQyxNQUFNO2dCQUdHLDZCQUE2QjtzQkFBdEMsTUFBTTtnQkFHRyxrQkFBa0I7c0JBQTNCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBBcHBsaWNhdGlvblJlZixcbiAgRGlyZWN0aXZlLFxuICBFbGVtZW50UmVmLFxuICBFbWJlZGRlZFZpZXdSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVGVtcGxhdGVSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQge1xuICB0eXBlIENlcmlvdXNTY3JvbGxPcHRpb25zLFxuICB0eXBlIEVsZW1lbnRSZW5kZXJlcixcbiAgdHlwZSBNZWFzdXJlZFZpZXdwb3J0UmFuZ2UsXG59IGZyb20gJ0BjZXJpb3VzZGV2dGVjaC9jZXJpb3VzLXNjcm9sbCc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHR5cGUgeyBDZXJpb3VzVmlld3BvcnRDaGFuZ2VEZXRhaWwgfSBmcm9tICcuL2NlcmlvdXMtc2Nyb2xsLnR5cGVzJztcbmltcG9ydCB0eXBlIHsgQ2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZUNvbnRleHQgfSBmcm9tICcuL2NlcmlvdXMtc2Nyb2xsLWl0ZW0tdGVtcGxhdGUuZGlyZWN0aXZlJztcbmltcG9ydCB7IHR5cGUgQ2VyaW91c1Njcm9sbEhvc3RSZWYsIENlcmlvdXNTY3JvbGxTZXJ2aWNlIH0gZnJvbSAnLi9jZXJpb3VzLXNjcm9sbC5zZXJ2aWNlJztcblxuZnVuY3Rpb24gY29lcmNlVG90YWxFbGVtZW50cyhleHBsaWNpdFRvdGFsOiBudW1iZXIgfCBudWxsIHwgdW5kZWZpbmVkLCBpdGVtc0xlbjogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCk6IG51bWJlciB7XG4gIGNvbnN0IGNhbmRpZGF0ZSA9IHR5cGVvZiBleHBsaWNpdFRvdGFsID09PSAnbnVtYmVyJyA/IGV4cGxpY2l0VG90YWwgOiB0eXBlb2YgaXRlbXNMZW4gPT09ICdudW1iZXInID8gaXRlbXNMZW4gOiB1bmRlZmluZWQ7XG4gIGlmIChjYW5kaWRhdGUgPT09IHVuZGVmaW5lZCB8fCBOdW1iZXIuaXNOYU4oY2FuZGlkYXRlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2VyaW91c1Njcm9sbERpcmVjdGl2ZTogcHJvdmlkZSBgY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHNgIG9yIGBjZXJpb3VzU2Nyb2xsSXRlbXNgLicpO1xuICB9XG4gIC8vIENlcmlvdXNTY3JvbGwgY3VycmVudGx5IHJlcXVpcmVzID49IDFcbiAgcmV0dXJuIE1hdGgubWF4KDEsIGNhbmRpZGF0ZSk7XG59XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tjZXJpb3VzU2Nyb2xsXScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIENlcmlvdXNTY3JvbGxEaXJlY3RpdmU8VEl0ZW0gPSB1bmtub3duPiBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgLyoqIFRvdGFsIG51bWJlciBvZiBpdGVtcy4gSWYgb21pdHRlZCwgZGVyaXZlZCBmcm9tIGBjZXJpb3VzU2Nyb2xsSXRlbXMubGVuZ3RoYC4gKi9cbiAgQElucHV0KCkgY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHM6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBPcHRpb25hbCBpdGVtcyBhcnJheSAoZW5hYmxlcyBgbGV0LWl0ZW1gKS4gKi9cbiAgQElucHV0KCkgY2VyaW91c1Njcm9sbEl0ZW1zOiByZWFkb25seSBUSXRlbVtdIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIE9wdGlvbmFsIGdldHRlciBmb3IgbGFyZ2UgZGF0YXNldHMgKGFsdGVybmF0aXZlIHRvIHBhc3NpbmcgZnVsbCBgaXRlbXNgKS4gKi9cbiAgQElucHV0KCkgY2VyaW91c1Njcm9sbEdldEl0ZW06ICgoaW5kZXg6IG51bWJlcikgPT4gVEl0ZW0pIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIFRlbXBsYXRlIHVzZWQgdG8gcmVuZGVyIGVhY2ggcm93LiAqL1xuICBASW5wdXQoKSBjZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlQ29udGV4dDxUSXRlbT4+IHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIE9wdGlvbnMgcGFzc2VkIHRvIGBuZXcgQ2VyaW91c1Njcm9sbCguLi4pYC4gKi9cbiAgQElucHV0KCkgY2VyaW91c1Njcm9sbE9wdGlvbnM6IENlcmlvdXNTY3JvbGxPcHRpb25zID0ge307XG5cbiAgLyoqIEF1dG9tYXRpY2FsbHkgY2FsbCByZW5kZXIgYWZ0ZXIgZWFjaCBzY3JvbGwgZXZlbnQuIERlZmF1bHQ6IHRydWUgKi9cbiAgQElucHV0KCkgY2VyaW91c1Njcm9sbEF1dG9SZW5kZXIgPSB0cnVlO1xuXG4gIC8qKiBFbWl0cyBgY2VyaW91cy12aWV3cG9ydC1jaGFuZ2VgIGRldGFpbC4gKi9cbiAgQE91dHB1dCgpIGNlcmlvdXNTY3JvbGxWaWV3cG9ydENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8Q2VyaW91c1ZpZXdwb3J0Q2hhbmdlRGV0YWlsPigpO1xuXG4gIC8qKiBFbWl0cyB0aGUgbGFzdCBtZWFzdXJlZCB2aWV3cG9ydCBhZnRlciBlYWNoIHJlbmRlciBwYXNzLiAqL1xuICBAT3V0cHV0KCkgY2VyaW91c1Njcm9sbE1lYXN1cmVkVmlld3BvcnQgPSBuZXcgRXZlbnRFbWl0dGVyPE1lYXN1cmVkVmlld3BvcnRSYW5nZT4oKTtcblxuICAvKiogRW1pdHMgb25jZSB0aGUgdW5kZXJseWluZyBgQ2VyaW91c1Njcm9sbGAgaW5zdGFuY2UgaXMgcmVhZHkuICovXG4gIEBPdXRwdXQoKSBjZXJpb3VzU2Nyb2xsUmVhZHkgPSBuZXcgRXZlbnRFbWl0dGVyPENlcmlvdXNTY3JvbGxIb3N0UmVmWydzY3JvbGxlciddPigpO1xuXG4gIHByaXZhdGUgaG9zdFJlZjogQ2VyaW91c1Njcm9sbEhvc3RSZWYgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSB2aWV3cG9ydFN1YjogU3Vic2NyaXB0aW9uIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSByZWFkb25seSB2aWV3QnlDb250YWluZXIgPSBuZXcgTWFwPEhUTUxFbGVtZW50LCBFbWJlZGRlZFZpZXdSZWY8Q2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZUNvbnRleHQ8VEl0ZW0+Pj4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGhvc3Q6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgYXBwUmVmOiBBcHBsaWNhdGlvblJlZixcbiAgICBwcml2YXRlIHJlYWRvbmx5IG5nWm9uZTogTmdab25lLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY2VyaW91czogQ2VyaW91c1Njcm9sbFNlcnZpY2VcbiAgKSB7fVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYpIHJldHVybjtcblxuICAgIGlmIChjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsSXRlbXMnXSB8fCBjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsVG90YWxFbGVtZW50cyddKSB7XG4gICAgICBjb25zdCB0b3RhbCA9IGNvZXJjZVRvdGFsRWxlbWVudHModGhpcy5jZXJpb3VzU2Nyb2xsVG90YWxFbGVtZW50cywgdGhpcy5jZXJpb3VzU2Nyb2xsSXRlbXM/Lmxlbmd0aCA/PyBudWxsKTtcbiAgICAgIHRoaXMuaG9zdFJlZi5zY3JvbGxlci50b3RhbEVsZW1lbnRzID0gdG90YWw7XG4gICAgICB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIuY2xlYXJBbGxDYWNoZXMoKTtcbiAgICAgIGlmICh0aGlzLmNlcmlvdXNTY3JvbGxBdXRvUmVuZGVyKSB0aGlzLnJlbmRlcigpO1xuICAgIH1cblxuICAgIGlmIChjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsT3B0aW9ucyddICYmICFjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsT3B0aW9ucyddLmZpcnN0Q2hhbmdlKSB7XG4gICAgICAvLyBPcHRpb25zIGFyZSBjb25zdW1lZCBwcmltYXJpbHkgYXQgY29uc3RydWN0aW9uIHRpbWUuXG4gICAgICB0aGlzLnJlY3JlYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy52aWV3cG9ydFN1Yj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnZpZXdwb3J0U3ViID0gbnVsbDtcblxuICAgIHRoaXMuZGVzdHJveUFsbFZpZXdzKCk7XG5cbiAgICB0aGlzLmhvc3RSZWY/LmRlc3Ryb3koKTtcbiAgICB0aGlzLmhvc3RSZWYgPSBudWxsO1xuICB9XG5cbiAgLyoqIEltcGVyYXRpdmVseSB0cmlnZ2VyIGEgcmVuZGVyIHBhc3MgKHVzZXMgYGNlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGVgKS4gKi9cbiAgcmVuZGVyKCk6IE1lYXN1cmVkVmlld3BvcnRSYW5nZSB8IG51bGwge1xuICAgIGlmICghdGhpcy5ob3N0UmVmKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCB0ZW1wbGF0ZSA9IHRoaXMuY2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZTtcbiAgICBpZiAoIXRlbXBsYXRlKSByZXR1cm4gbnVsbDtcblxuICAgIGNvbnN0IGhvc3RDb250YWluZXIgPSB0aGlzLmhvc3QubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCBoZWlnaHQgPSBob3N0Q29udGFpbmVyLmNsaWVudEhlaWdodCB8fCBob3N0Q29udGFpbmVyLm9mZnNldEhlaWdodDtcbiAgICBjb25zdCBjb250ZW50Q29udGFpbmVyID0gdGhpcy5ob3N0UmVmLmNvbnRlbnRFbGVtZW50O1xuXG4gICAgY29uc3QgcmVuZGVyZXI6IEVsZW1lbnRSZW5kZXJlciA9IChpbmRleCwgZWxlbWVudENvbnRhaW5lcikgPT4ge1xuICAgICAgLy8gUmVuZGVyaW5nIG11c3QgY3JlYXRlIEFuZ3VsYXIgdmlld3MgaW5zaWRlIHRoZSBBbmd1bGFyIHpvbmUuXG4gICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnJlbmRlclRlbXBsYXRlSW50b0NvbnRhaW5lcih0ZW1wbGF0ZSwgaW5kZXgsIGVsZW1lbnRDb250YWluZXIpO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIGNvbnN0IHJhbmdlID0gdGhpcy5ob3N0UmVmLnNjcm9sbGVyLnJlbmRlclZpZXdwb3J0KGhlaWdodCwgY29udGVudENvbnRhaW5lciwgcmVuZGVyZXIpO1xuICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB0aGlzLmNlcmlvdXNTY3JvbGxNZWFzdXJlZFZpZXdwb3J0LmVtaXQocmFuZ2UpKTtcbiAgICByZXR1cm4gcmFuZ2U7XG4gIH1cblxuICBwcml2YXRlIHJlY3JlYXRlKCk6IHZvaWQge1xuICAgIHRoaXMudmlld3BvcnRTdWI/LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy52aWV3cG9ydFN1YiA9IG51bGw7XG5cbiAgICB0aGlzLmRlc3Ryb3lBbGxWaWV3cygpO1xuXG4gICAgdGhpcy5ob3N0UmVmPy5kZXN0cm95KCk7XG4gICAgdGhpcy5ob3N0UmVmID0gbnVsbDtcblxuICAgIHRoaXMuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcbiAgfVxuXG4gIHByaXZhdGUgZW5zdXJlSW5pdGlhbGl6ZWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaG9zdFJlZikgcmV0dXJuO1xuXG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5ob3N0Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3QgdG90YWwgPSBjb2VyY2VUb3RhbEVsZW1lbnRzKHRoaXMuY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHMsIHRoaXMuY2VyaW91c1Njcm9sbEl0ZW1zPy5sZW5ndGggPz8gbnVsbCk7XG5cbiAgICB0aGlzLmhvc3RSZWYgPSB0aGlzLmNlcmlvdXMuY3JlYXRlSG9zdChjb250YWluZXIsIHRvdGFsLCB0aGlzLmNlcmlvdXNTY3JvbGxPcHRpb25zLCB0aGlzLm5nWm9uZSwgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuY2VyaW91c1Njcm9sbEF1dG9SZW5kZXIpIHRoaXMucmVuZGVyKCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnZpZXdwb3J0U3ViID0gdGhpcy5ob3N0UmVmLnZpZXdwb3J0Q2hhbmdlcyQuc3Vic2NyaWJlKChkZXRhaWw6IENlcmlvdXNWaWV3cG9ydENoYW5nZURldGFpbCkgPT4ge1xuICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHRoaXMuY2VyaW91c1Njcm9sbFZpZXdwb3J0Q2hhbmdlLmVtaXQoZGV0YWlsKSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmNlcmlvdXNTY3JvbGxSZWFkeS5lbWl0KHRoaXMuaG9zdFJlZi5zY3JvbGxlcik7XG5cbiAgICBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcikge1xuICAgICAgcXVldWVNaWNyb3Rhc2soKCkgPT4gdGhpcy5yZW5kZXIoKSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRJdGVtRm9ySW5kZXgoaW5kZXg6IG51bWJlcik6IFRJdGVtIHtcbiAgICBjb25zdCBnZXR0ZXIgPSB0aGlzLmNlcmlvdXNTY3JvbGxHZXRJdGVtO1xuICAgIGlmIChnZXR0ZXIpIHJldHVybiBnZXR0ZXIoaW5kZXgpO1xuXG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLmNlcmlvdXNTY3JvbGxJdGVtcztcbiAgICBpZiAoIWl0ZW1zKSByZXR1cm4gdW5kZWZpbmVkIGFzIFRJdGVtO1xuXG4gICAgcmV0dXJuIGl0ZW1zW2luZGV4XTtcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyVGVtcGxhdGVJbnRvQ29udGFpbmVyKFxuICAgIHRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlQ29udGV4dDxUSXRlbT4+LFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgZWxlbWVudENvbnRhaW5lcjogSFRNTEVsZW1lbnRcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgcHJldmlvdXMgPSB0aGlzLnZpZXdCeUNvbnRhaW5lci5nZXQoZWxlbWVudENvbnRhaW5lcik7XG4gICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICB0aGlzLmFwcFJlZi5kZXRhY2hWaWV3KHByZXZpb3VzKTtcbiAgICAgIHByZXZpb3VzLmRlc3Ryb3koKTtcbiAgICAgIHRoaXMudmlld0J5Q29udGFpbmVyLmRlbGV0ZShlbGVtZW50Q29udGFpbmVyKTtcbiAgICB9XG5cbiAgICAvLyBDbGVhciBwcmlvciBET00gKENlcmlvdXNTY3JvbGwgbWF5IHJlY3ljbGUgY29udGFpbmVycykuXG4gICAgZWxlbWVudENvbnRhaW5lci50ZXh0Q29udGVudCA9ICcnO1xuXG4gICAgY29uc3QgaXRlbSA9IHRoaXMuZ2V0SXRlbUZvckluZGV4KGluZGV4KTtcbiAgICBjb25zdCB2aWV3ID0gdGVtcGxhdGUuY3JlYXRlRW1iZWRkZWRWaWV3KHsgJGltcGxpY2l0OiBpdGVtLCBpdGVtLCBpbmRleCB9KTtcbiAgICB0aGlzLmFwcFJlZi5hdHRhY2hWaWV3KHZpZXcpO1xuICAgIHZpZXcuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgZm9yIChjb25zdCBub2RlIG9mIHZpZXcucm9vdE5vZGVzKSB7XG4gICAgICBlbGVtZW50Q29udGFpbmVyLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgIH1cblxuICAgIHRoaXMudmlld0J5Q29udGFpbmVyLnNldChlbGVtZW50Q29udGFpbmVyLCB2aWV3KTtcbiAgfVxuXG4gIHByaXZhdGUgZGVzdHJveUFsbFZpZXdzKCk6IHZvaWQge1xuICAgIGZvciAoY29uc3QgdmlldyBvZiB0aGlzLnZpZXdCeUNvbnRhaW5lci52YWx1ZXMoKSkge1xuICAgICAgdGhpcy5hcHBSZWYuZGV0YWNoVmlldyh2aWV3KTtcbiAgICAgIHZpZXcuZGVzdHJveSgpO1xuICAgIH1cbiAgICB0aGlzLnZpZXdCeUNvbnRhaW5lci5jbGVhcigpO1xuICB9XG59XG4iXX0=
|
|
385
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VyaW91cy1zY3JvbGwuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWNlcmlvdXMtc2Nyb2xsL3NyYy9saWIvY2VyaW91cy1zY3JvbGwuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFHTCxTQUFTLEVBR1QsWUFBWSxFQUNaLEtBQUssRUFJTCxNQUFNLEdBR1AsTUFBTSxlQUFlLENBQUM7OztBQWF2QixTQUFTLG1CQUFtQixDQUFDLGFBQXdDLEVBQUUsUUFBbUM7SUFDeEcsTUFBTSxTQUFTLEdBQUcsT0FBTyxhQUFhLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLE9BQU8sUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDMUgsSUFBSSxTQUFTLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUN2RCxNQUFNLElBQUksS0FBSyxDQUFDLHVGQUF1RixDQUFDLENBQUM7SUFDM0csQ0FBQztJQUNELHdDQUF3QztJQUN4QyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ2hDLENBQUM7QUFNRCxNQUFNLE9BQU8sc0JBQXNCO0lBdUNqQyxZQUNtQixJQUE2QixFQUM3QixNQUFzQixFQUN0QixNQUFjLEVBQ2QsT0FBNkI7UUFIN0IsU0FBSSxHQUFKLElBQUksQ0FBeUI7UUFDN0IsV0FBTSxHQUFOLE1BQU0sQ0FBZ0I7UUFDdEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFlBQU8sR0FBUCxPQUFPLENBQXNCO1FBMUNoRCxtRkFBbUY7UUFDMUUsK0JBQTBCLEdBQWtCLElBQUksQ0FBQztRQUUxRCxpREFBaUQ7UUFDeEMsdUJBQWtCLEdBQTRCLElBQUksQ0FB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UyxFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDN0IsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pCLENBQUM7UUFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDNUIsQ0FBQzsrR0FsWVUsc0JBQXNCO21HQUF0QixzQkFBc0I7OzRGQUF0QixzQkFBc0I7a0JBSmxDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGlCQUFpQjtvQkFDM0IsVUFBVSxFQUFFLElBQUk7aUJBQ2pCO29LQUdVLDBCQUEwQjtzQkFBbEMsS0FBSztnQkFHRyxrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBR0csb0JBQW9CO3NCQUE1QixLQUFLO2dCQUdHLHlCQUF5QjtzQkFBakMsS0FBSztnQkFHRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBR0csdUJBQXVCO3NCQUEvQixLQUFLO2dCQUdJLDJCQUEyQjtzQkFBcEMsTUFBTTtnQkFHRyw2QkFBNkI7c0JBQXRDLE1BQU07Z0JBR0csa0JBQWtCO3NCQUEzQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQXBwbGljYXRpb25SZWYsXG4gIERpcmVjdGl2ZSxcbiAgRWxlbWVudFJlZixcbiAgRW1iZWRkZWRWaWV3UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBOZ1pvbmUsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFRlbXBsYXRlUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtcbiAgdHlwZSBDZXJpb3VzU2Nyb2xsT3B0aW9ucyxcbiAgdHlwZSBFbGVtZW50UmVuZGVyZXIsXG4gIHR5cGUgTWVhc3VyZWRWaWV3cG9ydFJhbmdlLFxufSBmcm9tICdAY2VyaW91c2RldnRlY2gvY2VyaW91cy1zY3JvbGwnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB0eXBlIHsgQ2VyaW91c1ZpZXdwb3J0Q2hhbmdlRGV0YWlsIH0gZnJvbSAnLi9jZXJpb3VzLXNjcm9sbC50eXBlcyc7XG5pbXBvcnQgdHlwZSB7IENlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGVDb250ZXh0IH0gZnJvbSAnLi9jZXJpb3VzLXNjcm9sbC1pdGVtLXRlbXBsYXRlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyB0eXBlIENlcmlvdXNTY3JvbGxIb3N0UmVmLCBDZXJpb3VzU2Nyb2xsU2VydmljZSB9IGZyb20gJy4vY2VyaW91cy1zY3JvbGwuc2VydmljZSc7XG5cbmZ1bmN0aW9uIGNvZXJjZVRvdGFsRWxlbWVudHMoZXhwbGljaXRUb3RhbDogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCwgaXRlbXNMZW46IG51bWJlciB8IG51bGwgfCB1bmRlZmluZWQpOiBudW1iZXIge1xuICBjb25zdCBjYW5kaWRhdGUgPSB0eXBlb2YgZXhwbGljaXRUb3RhbCA9PT0gJ251bWJlcicgPyBleHBsaWNpdFRvdGFsIDogdHlwZW9mIGl0ZW1zTGVuID09PSAnbnVtYmVyJyA/IGl0ZW1zTGVuIDogdW5kZWZpbmVkO1xuICBpZiAoY2FuZGlkYXRlID09PSB1bmRlZmluZWQgfHwgTnVtYmVyLmlzTmFOKGNhbmRpZGF0ZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NlcmlvdXNTY3JvbGxEaXJlY3RpdmU6IHByb3ZpZGUgYGNlcmlvdXNTY3JvbGxUb3RhbEVsZW1lbnRzYCBvciBgY2VyaW91c1Njcm9sbEl0ZW1zYC4nKTtcbiAgfVxuICAvLyBDZXJpb3VzU2Nyb2xsIGN1cnJlbnRseSByZXF1aXJlcyA+PSAxXG4gIHJldHVybiBNYXRoLm1heCgxLCBjYW5kaWRhdGUpO1xufVxuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbY2VyaW91c1Njcm9sbF0nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxufSlcbmV4cG9ydCBjbGFzcyBDZXJpb3VzU2Nyb2xsRGlyZWN0aXZlPFRJdGVtID0gdW5rbm93bj4gaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG4gIC8qKiBUb3RhbCBudW1iZXIgb2YgaXRlbXMuIElmIG9taXR0ZWQsIGRlcml2ZWQgZnJvbSBgY2VyaW91c1Njcm9sbEl0ZW1zLmxlbmd0aGAuICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxUb3RhbEVsZW1lbnRzOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICAvKiogT3B0aW9uYWwgaXRlbXMgYXJyYXkgKGVuYWJsZXMgYGxldC1pdGVtYCkuICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxJdGVtczogcmVhZG9ubHkgVEl0ZW1bXSB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBPcHRpb25hbCBnZXR0ZXIgZm9yIGxhcmdlIGRhdGFzZXRzIChhbHRlcm5hdGl2ZSB0byBwYXNzaW5nIGZ1bGwgYGl0ZW1zYCkuICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxHZXRJdGVtOiAoKGluZGV4OiBudW1iZXIpID0+IFRJdGVtKSB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBUZW1wbGF0ZSB1c2VkIHRvIHJlbmRlciBlYWNoIHJvdy4gKi9cbiAgQElucHV0KCkgY2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZTogVGVtcGxhdGVSZWY8Q2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZUNvbnRleHQ8VEl0ZW0+PiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBPcHRpb25zIHBhc3NlZCB0byBgbmV3IENlcmlvdXNTY3JvbGwoLi4uKWAuICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxPcHRpb25zOiBDZXJpb3VzU2Nyb2xsT3B0aW9ucyA9IHt9O1xuXG4gIC8qKiBBdXRvbWF0aWNhbGx5IGNhbGwgcmVuZGVyIGFmdGVyIGVhY2ggc2Nyb2xsIGV2ZW50LiBEZWZhdWx0OiB0cnVlICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxBdXRvUmVuZGVyID0gdHJ1ZTtcblxuICAvKiogRW1pdHMgYGNlcmlvdXMtdmlld3BvcnQtY2hhbmdlYCBkZXRhaWwuICovXG4gIEBPdXRwdXQoKSBjZXJpb3VzU2Nyb2xsVmlld3BvcnRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPENlcmlvdXNWaWV3cG9ydENoYW5nZURldGFpbD4oKTtcblxuICAvKiogRW1pdHMgdGhlIGxhc3QgbWVhc3VyZWQgdmlld3BvcnQgYWZ0ZXIgZWFjaCByZW5kZXIgcGFzcy4gKi9cbiAgQE91dHB1dCgpIGNlcmlvdXNTY3JvbGxNZWFzdXJlZFZpZXdwb3J0ID0gbmV3IEV2ZW50RW1pdHRlcjxNZWFzdXJlZFZpZXdwb3J0UmFuZ2U+KCk7XG5cbiAgLyoqIEVtaXRzIG9uY2UgdGhlIHVuZGVybHlpbmcgYENlcmlvdXNTY3JvbGxgIGluc3RhbmNlIGlzIHJlYWR5LiAqL1xuICBAT3V0cHV0KCkgY2VyaW91c1Njcm9sbFJlYWR5ID0gbmV3IEV2ZW50RW1pdHRlcjxDZXJpb3VzU2Nyb2xsSG9zdFJlZlsnc2Nyb2xsZXInXT4oKTtcblxuICBwcml2YXRlIGhvc3RSZWY6IENlcmlvdXNTY3JvbGxIb3N0UmVmIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgdmlld3BvcnRTdWI6IFN1YnNjcmlwdGlvbiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHNjaGVkdWxlZFJlbmRlckZyYW1lOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIHJlYWRvbmx5IHZpZXdCeUNvbnRhaW5lciA9IG5ldyBNYXA8SFRNTEVsZW1lbnQsIEVtYmVkZGVkVmlld1JlZjxDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlQ29udGV4dDxUSXRlbT4+PigpO1xuICAvLyBQb29sIG9mIHZpZXdzIGRldGFjaGVkIGJlY2F1c2UgdGhlaXIgY29udGFpbmVyIGxlZnQgdGhlIHZpZXdwb3J0LiBSZXVzaW5nXG4gIC8vIHRoZW0gb24gc3Vic2VxdWVudCByZW5kZXJzIGF2b2lkcyBkZXN0cm95aW5nICsgcmVjcmVhdGluZyB0aGUgZW50aXJlIHJvd1xuICAvLyBjb21wb25lbnQgdHJlZSBvbiBmYXN0IHNjcm9sbHMgKHdoZXJlIHRoZSBlbmdpbmUncyBlbGVtZW50IHBvb2wgd2lwZXNcbiAgLy8gdGV4dENvbnRlbnQgb24gcmV1c2VkIGNvbnRhaW5lcnMsIHNvIHZpZXcgcm9vdE5vZGVzIGdldCBvcnBoYW5lZCkuXG4gIHByaXZhdGUgcmVhZG9ubHkgZnJlZVZpZXdzOiBFbWJlZGRlZFZpZXdSZWY8Q2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZUNvbnRleHQ8VEl0ZW0+PltdID0gW107XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFwcFJlZjogQXBwbGljYXRpb25SZWYsXG4gICAgcHJpdmF0ZSByZWFkb25seSBuZ1pvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNlcmlvdXM6IENlcmlvdXNTY3JvbGxTZXJ2aWNlXG4gICkge31cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmICghdGhpcy5ob3N0UmVmKSByZXR1cm47XG5cbiAgICBpZiAoY2hhbmdlc1snY2VyaW91c1Njcm9sbEl0ZW1zJ10gfHwgY2hhbmdlc1snY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHMnXSkge1xuICAgICAgY29uc3QgdG90YWwgPSBjb2VyY2VUb3RhbEVsZW1lbnRzKHRoaXMuY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHMsIHRoaXMuY2VyaW91c1Njcm9sbEl0ZW1zPy5sZW5ndGggPz8gbnVsbCk7XG4gICAgICBjb25zdCBjb3VudENoYW5nZWQgPSB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIudG90YWxFbGVtZW50cyAhPT0gdG90YWw7XG5cbiAgICAgIGlmIChjb3VudENoYW5nZWQpIHtcbiAgICAgICAgLy8gVGhlIGRhdGFzZXQgc2l6ZSBjaGFuZ2VkOiB0aGUgVmlld3BvcnRSZW5kZXJlciBzdG9yZXMgaXRzIG93biBjb3B5IG9mXG4gICAgICAgIC8vIHRvdGFsRWxlbWVudHMgKHNldCBieSB2YWx1ZSBhdCBjb25zdHJ1Y3Rpb24pIHNvIHBhdGNoaW5nIHRoZSBlbmdpbmUnc1xuICAgICAgICAvLyBwdWJsaWMgcHJvcGVydHkgYWxvbmUgbGVhdmVzIHRoZSByZW5kZXJlcidzIGludGVybmFsIGJvdW5kIHN0YWxlLiAgVGhlXG4gICAgICAgIC8vIHJlbmRlcmVyIHdvdWxkIHRoZW4gdXNlIHRoZSBvbGQgY291bnQgZm9yIGl0cyB2aWV3cG9ydC1maWxsIGxvb3AgYW5kXG4gICAgICAgIC8vIGJvdHRvbS1ib3VuZGFyeSBzY2FuLCBwcm9kdWNpbmcgcGhhbnRvbSByZW5kZXJzIGF0IG91dC1vZi1ib3VuZHNcbiAgICAgICAgLy8gaW5kaWNlcyAodW5kZWZpbmVkIGl0ZW1zIOKGkiAwLWhlaWdodCByb3dzIOKGkiB0aGUgZmlsbCBsb29wIG5ldmVyXG4gICAgICAgIC8vIHNhdGlzZmllcyBpdHMgaGVpZ2h0IGNvbmRpdGlvbiDihpIgaHVuZHJlZHMgb2YgcmVuZGVyZXIgY2FsbGJhY2tzKS5cbiAgICAgICAgLy8gUmVjcmVhdGluZyB0aGUgZW5naW5lIGdpdmVzIGJvdGggdGhlIGVuZ2luZSBhbmQgdGhlIHJlbmRlcmVyIGEgZnJlc2gsXG4gICAgICAgIC8vIGNvbnNpc3RlbnQgY291bnQuICBlbnN1cmVJbml0aWFsaXplZCgpIHNjaGVkdWxlcyB0aGUgZmlyc3QgcmVuZGVyIHZpYVxuICAgICAgICAvLyBxdWV1ZU1pY3JvdGFzaywgd2hpY2ggcnVucyBhZnRlciB0aGUgY3VycmVudCBDRCBjeWNsZSBjb21wbGV0ZXMuXG4gICAgICAgIHRoaXMucmVjcmVhdGUoKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcikge1xuICAgICAgICAvLyBTYW1lIGNvdW50LCBuZXcgZGF0YSByZWZlcmVuY2UgKGUuZy4gYW4gaW1tdXRhYmxlIGVkaXQgb3IgYSBzb3J0IHRoYXRcbiAgICAgICAgLy8gaGFwcGVucyB0byBrZWVwIHRoZSBzYW1lIGxlbmd0aCkuIFRoZSBlbmdpbmUgcmV1c2VzIHRoZSBET00gZWxlbWVudCBpdFxuICAgICAgICAvLyBhbHJlYWR5IHJlbmRlcmVkIGZvciBlYWNoIG92ZXJsYXBwaW5nIGluZGV4IHdpdGhvdXQgcmUtaW52b2tpbmcgdGhlXG4gICAgICAgIC8vIHJlbmRlcmVyLCBzbyB1cGRhdGUgdGhlIGNvbnRlbnQgb2YgZXZlcnkgY3VycmVudGx5LXZpc2libGUgcm93IElOXG4gICAgICAgIC8vIFBMQUNFIGJlZm9yZSBjYWxsaW5nIHJlbmRlcigpLiAgVGhpcyBwcmVzZXJ2ZXMgZWFjaCByb3cncyBlbWJlZGRlZFxuICAgICAgICAvLyB2aWV3IChzbyBhIGZvY3VzZWQgdGV4dGJveCBrZWVwcyBmb2N1cy9jYXJldCkgYW5kIGRvZXMgTk9UIGRpc2NhcmRcbiAgICAgICAgLy8gY2FjaGVkIGhlaWdodHMuIElmIGEgcm93J3MgaGVpZ2h0IGFjdHVhbGx5IGNoYW5nZXMgdGhlIGVuZ2luZSdzXG4gICAgICAgIC8vIFJlc2l6ZU9ic2VydmVyIGtlZXBzIHRoZSBjYWNoZSBjb3JyZWN0IG9uIGl0cyBvd247IGZvciBhIHdob2xlc2FsZVxuICAgICAgICAvLyBoZWlnaHQgY2hhbmdlIGFjcm9zcyBhbGwgcm93cywgY2FsbCByZWNhbGN1bGF0ZSgpIGluc3RlYWQuXG4gICAgICAgIHRoaXMucmVmcmVzaFJlbmRlcmVkQ29udGVudCgpO1xuICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsT3B0aW9ucyddICYmICFjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsT3B0aW9ucyddLmZpcnN0Q2hhbmdlKSB7XG4gICAgICAvLyBPcHRpb25zIGFyZSBjb25zdW1lZCBwcmltYXJpbHkgYXQgY29uc3RydWN0aW9uIHRpbWUuXG4gICAgICB0aGlzLnJlY3JlYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2NoZWR1bGVkUmVuZGVyRnJhbWUgIT0gbnVsbCkge1xuICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5zY2hlZHVsZWRSZW5kZXJGcmFtZSk7XG4gICAgICB0aGlzLnNjaGVkdWxlZFJlbmRlckZyYW1lID0gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLnZpZXdwb3J0U3ViPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMudmlld3BvcnRTdWIgPSBudWxsO1xuXG4gICAgdGhpcy5kZXN0cm95QWxsVmlld3MoKTtcblxuICAgIHRoaXMuaG9zdFJlZj8uZGVzdHJveSgpO1xuICAgIHRoaXMuaG9zdFJlZiA9IG51bGw7XG4gIH1cblxuICAvKiogSW1wZXJhdGl2ZWx5IHRyaWdnZXIgYSByZW5kZXIgcGFzcyAodXNlcyBgY2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZWApLiAqL1xuICByZW5kZXIoKTogTWVhc3VyZWRWaWV3cG9ydFJhbmdlIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHRlbXBsYXRlID0gdGhpcy5jZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlO1xuICAgIGlmICghdGVtcGxhdGUpIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgaG9zdENvbnRhaW5lciA9IHRoaXMuaG9zdC5uYXRpdmVFbGVtZW50O1xuICAgIGNvbnN0IGhlaWdodCA9IGhvc3RDb250YWluZXIuY2xpZW50SGVpZ2h0IHx8IGhvc3RDb250YWluZXIub2Zmc2V0SGVpZ2h0O1xuICAgIGNvbnN0IGNvbnRlbnRDb250YWluZXIgPSB0aGlzLmhvc3RSZWYuY29udGVudEVsZW1lbnQ7XG5cbiAgICAvLyBUcmFjayB3aGV0aGVyIHRoZSBlbmdpbmUgYXNrZWQgdXMgdG8gYmluZCBhbnkgcm93IHRoaXMgcGFzcy4gUHVyZSBzY3JvbGxcbiAgICAvLyBmcmFtZXMgd2hlcmUgdGhlIHZpc2libGUgcm93IHNldCBkb2Vzbid0IGNoYW5nZSBzdGlsbCBkcml2ZSByZW5kZXIoKSB2aWFcbiAgICAvLyB0aGUgckFGIGNvYWxlc2NlciDigJQgdGhlcmUncyBubyBwb2ludCBpbiB3YWxraW5nIHRoZSBwcnVuZSBtYXAgb3JcbiAgICAvLyBlbWl0dGluZyB0aGUgdmlld3BvcnQgcmFuZ2Ugd2hlbiBub3RoaW5nIHdhcyB0b3VjaGVkLlxuICAgIGxldCByZW5kZXJlckludm9jYXRpb25zID0gMDtcbiAgICBjb25zdCByZW5kZXJlcjogRWxlbWVudFJlbmRlcmVyID0gKGluZGV4LCBlbGVtZW50Q29udGFpbmVyKSA9PiB7XG4gICAgICByZW5kZXJlckludm9jYXRpb25zKys7XG4gICAgICAvLyBSZW5kZXIgZWFjaCByb3cncyBlbWJlZGRlZCB2aWV3IHdpdGggTE9DQUwgY2hhbmdlIGRldGVjdGlvblxuICAgICAgLy8gKGB2aWV3LmRldGVjdENoYW5nZXMoKWAgaW5zaWRlIGByZW5kZXJUZW1wbGF0ZUludG9Db250YWluZXJgKSBzbyB0aGVcbiAgICAgIC8vIGVuZ2luZSBjYW4gbWVhc3VyZSBpdHMgaGVpZ2h0IGR1cmluZyB0aGlzIHBhc3MuIERvIE5PVCB3cmFwIGVhY2ggcm93IGluXG4gICAgICAvLyBpdHMgb3duIGBuZ1pvbmUucnVuYCDigJQgdGhhdCBmaXJlcyBhIGZ1bGwgYEFwcGxpY2F0aW9uUmVmYCB0aWNrICpwZXIgcm93KlxuICAgICAgLy8gKE8obmV3Um93cyDDlyB2aXNpYmxlUm93cykgd29yaywgamFua3kgZHJhZ3MpLiBUaGUgc2luZ2xlIGNvYWxlc2NlZCB0aWNrXG4gICAgICAvLyBmb3IgdGhlIHdob2xlIHBhc3MgaXMgaGFuZGxlZCBieSB0aGUgY2FsbGVyIChgc2NoZWR1bGVSZW5kZXJgKS5cbiAgICAgIHRoaXMucmVuZGVyVGVtcGxhdGVJbnRvQ29udGFpbmVyKHRlbXBsYXRlLCBpbmRleCwgZWxlbWVudENvbnRhaW5lcik7XG4gICAgfTtcblxuICAgIGNvbnN0IHJhbmdlID0gdGhpcy5ob3N0UmVmLnNjcm9sbGVyLnJlbmRlclZpZXdwb3J0KGhlaWdodCwgY29udGVudENvbnRhaW5lciwgcmVuZGVyZXIpO1xuXG4gICAgaWYgKHJlbmRlcmVySW52b2NhdGlvbnMgPT09IDApIHtcbiAgICAgIC8vIFZpZXdwb3J0IGRpZG4ndCBjaGFuZ2Ug4oCUIHNraXAgdGhlIHBydW5lIHdhbGsgYW5kIHRoZSAocG90ZW50aWFsbHlcbiAgICAgIC8vIHpvbmUtZW50ZXJpbmcpIGVtaXQuXG4gICAgICByZXR1cm4gcmFuZ2U7XG4gICAgfVxuXG4gICAgLy8gRGVzdHJveSB2aWV3cyB3aG9zZSBjb250YWluZXIgdGhlIGVuZ2luZSBubyBsb25nZXIgcmVuZGVycy4gV2l0aG91dCB0aGlzLFxuICAgIC8vIGV2ZXJ5IGNvbnRhaW5lciB0aGUgZW5naW5lIHJlY3ljbGVzIGludG8gaXRzIGVsZW1lbnQgcG9vbCBsZWF2ZXMgaXRzXG4gICAgLy8gZW1iZWRkZWQgdmlldyBhdHRhY2hlZCB0byBBcHBsaWNhdGlvblJlZiBmb3JldmVyIOKAlCBzbyB0aGUgYXR0YWNoZWQtdmlld1xuICAgIC8vIGxpc3QgKGFuZCBldmVyeSBPKG4pIGBkZXRhY2hWaWV3YCkgZ3Jvd3Mgd2l0aG91dCBib3VuZCBhbmQgc2Nyb2xsaW5nIGdldHNcbiAgICAvLyBwcm9ncmVzc2l2ZWx5IHNsb3dlci4gTWlycm9ycyB0aGUgUmVhY3QvVnVlIHdyYXBwZXJzLCB3aGljaCBkcm9wIHJvd3MgdGhhdFxuICAgIC8vIGZhbGwgb3V0IG9mIGBnZXRSZW5kZXJlZEluZGljZXMoKWAuXG4gICAgdGhpcy5wcnVuZURldGFjaGVkVmlld3MoKTtcblxuICAgIC8vIE9ubHkgcmUtZW50ZXIgdGhlIHpvbmUgKGEgZ2xvYmFsIHRpY2spIGlmIHNvbWVvbmUgaXMgYWN0dWFsbHkgbGlzdGVuaW5nLlxuICAgIGlmICh0aGlzLmNlcmlvdXNTY3JvbGxNZWFzdXJlZFZpZXdwb3J0Lm9ic2VydmVkKSB7XG4gICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4gdGhpcy5jZXJpb3VzU2Nyb2xsTWVhc3VyZWRWaWV3cG9ydC5lbWl0KHJhbmdlKSk7XG4gICAgfVxuICAgIHJldHVybiByYW5nZTtcbiAgfVxuXG4gIC8qKiBUZWFyIGRvd24gZW1iZWRkZWQgdmlld3Mgd2hvc2UgY29udGFpbmVyIGlzIG5vIGxvbmdlciBwYXJ0IG9mIHRoZSB2aWV3cG9ydC4gKi9cbiAgcHJpdmF0ZSBwcnVuZURldGFjaGVkVmlld3MoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYgfHwgdGhpcy52aWV3QnlDb250YWluZXIuc2l6ZSA9PT0gMCkgcmV0dXJuO1xuICAgIGNvbnN0IHNjcm9sbGVyID0gdGhpcy5ob3N0UmVmLnNjcm9sbGVyO1xuICAgIGNvbnN0IGFjdGl2ZSA9IG5ldyBTZXQ8SFRNTEVsZW1lbnQ+KCk7XG4gICAgZm9yIChjb25zdCBpbmRleCBvZiBzY3JvbGxlci5nZXRSZW5kZXJlZEluZGljZXMoKSkge1xuICAgICAgY29uc3QgZWwgPSBzY3JvbGxlci5nZXRSZW5kZXJlZEVsZW1lbnQoaW5kZXgpO1xuICAgICAgaWYgKGVsKSBhY3RpdmUuYWRkKGVsKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBbY29udGFpbmVyLCB2aWV3XSBvZiB0aGlzLnZpZXdCeUNvbnRhaW5lcikge1xuICAgICAgaWYgKCFhY3RpdmUuaGFzKGNvbnRhaW5lcikpIHtcbiAgICAgICAgLy8gRGV0YWNoIERPTSBidXQga2VlcCB0aGUgdmlldyBhbGl2ZSBpbiB0aGUgcG9vbCBmb3IgZnV0dXJlIHJldXNlLlxuICAgICAgICAvLyBEZXN0cm95aW5nICsgcmVjcmVhdGluZyB2aWV3cyBwZXIgc2Nyb2xsIHN0ZXAgZG9taW5hdGVzIGZyYW1lIHRpbWUuXG4gICAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiB2aWV3LnJvb3ROb2Rlcykge1xuICAgICAgICAgIGlmIChub2RlLnBhcmVudE5vZGUpIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZpZXdCeUNvbnRhaW5lci5kZWxldGUoY29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5mcmVlVmlld3MucHVzaCh2aWV3KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKiogQXV0by1yZW5kZXIgY29hbGVzY2VkIHRvIGF0IG1vc3Qgb25jZSBwZXIgYW5pbWF0aW9uIGZyYW1lLiAqL1xuICBwcml2YXRlIHNjaGVkdWxlUmVuZGVyKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnNjaGVkdWxlZFJlbmRlckZyYW1lICE9IG51bGwpIHJldHVybjtcbiAgICB0aGlzLnNjaGVkdWxlZFJlbmRlckZyYW1lID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgIHRoaXMuc2NoZWR1bGVkUmVuZGVyRnJhbWUgPSBudWxsO1xuICAgICAgLy8gUnVuIHJlbmRlcigpIE9VVFNJREUgQW5ndWxhcidzIHpvbmUuIEEgZnVsbCBBcHBsaWNhdGlvblJlZi50aWNrKCkgb25cbiAgICAgIC8vIGV2ZXJ5IHNjcm9sbCBmcmFtZSBpcyB0aGUgcHJpbWFyeSBGUFMgYm90dGxlbmVjazogZXZlbiB3aGVuIG5vIHJvd3NcbiAgICAgIC8vIGNoYW5nZSAocHVyZSB0cmFuc2xhdGlvbiksIG5nWm9uZS5ydW4oKSBjYXVzZXMgQW5ndWxhciB0byB3YWxrIHRoZVxuICAgICAgLy8gZW50aXJlIGNvbXBvbmVudCB0cmVlLiBJbnN0ZWFkIHdlIGNhbGwgdmlldy5kZXRlY3RDaGFuZ2VzKCkgbG9jYWxseVxuICAgICAgLy8gaW5zaWRlIHJlbmRlclRlbXBsYXRlSW50b0NvbnRhaW5lciBmb3IgZWFjaCBhZmZlY3RlZCByb3cuIFpvbmUgZW50cnkgaXNcbiAgICAgIC8vIG9ubHkgbmVlZGVkIHdoZW4gY3JlYXRpbmcgYSBicmFuZC1uZXcgZW1iZWRkZWQgdmlldyAodG8gem9uZS1wYXRjaCBpdHNcbiAgICAgIC8vIGV2ZW50IGxpc3RlbmVycykg4oCUIHJlY3ljbGVkIGFuZCBwb29sZWQgdmlld3Mgd2VyZSBhbHJlYWR5IGNyZWF0ZWQgaW5zaWRlXG4gICAgICAvLyB6b25lIGFuZCB0aGVpciBsaXN0ZW5lcnMgcmVtYWluIHpvbmUtYXdhcmUuXG4gICAgICB0aGlzLnJlbmRlcigpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc2NhcmQgYWxsIGNhY2hlZCByb3cgaGVpZ2h0cyBhbmQgcmUtbWVhc3VyZSB0aGUgdmlld3BvcnQuXG4gICAqXG4gICAqIENhbGwgdGhpcyBvbmx5IHdoZW4gdGhlIGhlaWdodHMgb2Ygcm93cyB5b3UndmUgKmFscmVhZHkgcmVuZGVyZWQqIG1heSBoYXZlXG4gICAqIGNoYW5nZWQgd2l0aG91dCB0aGVpciBpbmRpY2VzIGNoYW5naW5nIOKAlCBlLmcuIGEgZ2xvYmFsIGZvbnQvZGVuc2l0eSBjaGFuZ2UsXG4gICAqIG9yIHN3YXBwaW5nIGV2ZXJ5IHJvdyB0byBhIGRpZmZlcmVudCBsYXlvdXQuIFRoaXMgZm9yY2VzIGEgc3luY2hyb25vdXNcbiAgICogcmUtbWVhc3VyZSAob25lIGBvZmZzZXRIZWlnaHRgIHJlYWQgcGVyIHZpc2libGUgcm93KSwgc28gZG8gTk9UIGNhbGwgaXQgb25cbiAgICogcm91dGluZSBlZGl0czogYSBzaW5nbGUgY2VsbCBlZGl0IGtlZXBzIGl0cyByb3cncyBzaXplLCBhbmQgdGhlIGVuZ2luZSdzXG4gICAqIFJlc2l6ZU9ic2VydmVyIHBpY2tzIHVwIGFueSBpbmNpZGVudGFsIHJlc2l6ZSBvbiBpdHMgb3duLlxuICAgKi9cbiAgcmVjYWxjdWxhdGUoKTogTWVhc3VyZWRWaWV3cG9ydFJhbmdlIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYpIHJldHVybiBudWxsO1xuICAgIC8vIERpc2NhcmQgdGhlIGNhY2hlZCBoZWlnaHRzLCB0aGVuIHJlLXJlbmRlci4gVGhlIGVuZ2luZSByZS1tZWFzdXJlcyBhbmRcbiAgICAvLyByZS1jYWNoZXMgdGhlIHJlbmRlcmVkIHJvd3MgZHVyaW5nIHRoZSBwYXNzIGFuZCByZWZyZXNoZXMgdGhlIHNjcm9sbFxuICAgIC8vIHBlcmNlbnRhZ2UsIHNvIGFuIGluLXBsYWNlIGhlaWdodCBjaGFuZ2UgKGUuZy4gZXhwYW5kL2NvbGxhcHNlKSBpc1xuICAgIC8vIHJlZmxlY3RlZCBpbiB0aGUgdG90YWwgY29udGVudCBoZWlnaHQgYW5kIHNjcm9sbGJhciBpbW1lZGlhdGVseS5cbiAgICB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIuY2xlYXJBbGxDYWNoZXMoKTtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXIoKTtcbiAgfVxuXG4gIC8qKiBKdW1wIGRpcmVjdGx5IHRvIGFuIGVsZW1lbnQgaW5kZXgsIHRoZW4gcmVuZGVyLiAqL1xuICBqdW1wVG9FbGVtZW50KGluZGV4OiBudW1iZXIpOiBNZWFzdXJlZFZpZXdwb3J0UmFuZ2UgfCBudWxsIHtcbiAgICBpZiAoIXRoaXMuaG9zdFJlZikgcmV0dXJuIG51bGw7XG4gICAgdGhpcy5ob3N0UmVmLnNjcm9sbGVyLmp1bXBUb0VsZW1lbnQoaW5kZXgpO1xuICAgIHJldHVybiB0aGlzLnJlbmRlcigpO1xuICB9XG5cbiAgLyoqIFNjcm9sbCB0byBhIHBlcmNlbnRhZ2UgKDAuLjEwMCksIHRoZW4gcmVuZGVyLiAqL1xuICBzY3JvbGxUb1BlcmNlbnRhZ2UocGVyY2VudGFnZTogbnVtYmVyKTogTWVhc3VyZWRWaWV3cG9ydFJhbmdlIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYpIHJldHVybiBudWxsO1xuICAgIHRoaXMuaG9zdFJlZi5zY3JvbGxlci5oYW5kbGVTY3JvbGxQZXJjZW50YWdlKHBlcmNlbnRhZ2UpO1xuICAgIHJldHVybiB0aGlzLnJlbmRlcigpO1xuICB9XG5cbiAgLyoqIFJlc2V0IHRvIHRoZSB0b3AsIHRoZW4gcmVuZGVyLiAqL1xuICByZXNldCgpOiBNZWFzdXJlZFZpZXdwb3J0UmFuZ2UgfCBudWxsIHtcbiAgICBpZiAoIXRoaXMuaG9zdFJlZikgcmV0dXJuIG51bGw7XG4gICAgdGhpcy5ob3N0UmVmLnNjcm9sbGVyLnJlc2V0KCk7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICBwcml2YXRlIHJlY3JlYXRlKCk6IHZvaWQge1xuICAgIHRoaXMudmlld3BvcnRTdWI/LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy52aWV3cG9ydFN1YiA9IG51bGw7XG5cbiAgICB0aGlzLmRlc3Ryb3lBbGxWaWV3cygpO1xuXG4gICAgdGhpcy5ob3N0UmVmPy5kZXN0cm95KCk7XG4gICAgdGhpcy5ob3N0UmVmID0gbnVsbDtcblxuICAgIHRoaXMuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcbiAgfVxuXG4gIHByaXZhdGUgZW5zdXJlSW5pdGlhbGl6ZWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaG9zdFJlZikgcmV0dXJuO1xuXG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5ob3N0Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3QgdG90YWwgPSBjb2VyY2VUb3RhbEVsZW1lbnRzKHRoaXMuY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHMsIHRoaXMuY2VyaW91c1Njcm9sbEl0ZW1zPy5sZW5ndGggPz8gbnVsbCk7XG5cbiAgICB0aGlzLmhvc3RSZWYgPSB0aGlzLmNlcmlvdXMuY3JlYXRlSG9zdChjb250YWluZXIsIHRvdGFsLCB0aGlzLmNlcmlvdXNTY3JvbGxPcHRpb25zLCB0aGlzLm5nWm9uZSwgKCkgPT4ge1xuICAgICAgLy8gQ29hbGVzY2Ugc2Nyb2xsLWRyaXZlbiByZW5kZXJzIHRvIG9uZSBwZXIgZnJhbWUgKHRoZSBuYXRpdmUgc2Nyb2xsYmFyXG4gICAgICAvLyBjYW4gZmlyZSBtYW55IHNjcm9sbCBldmVudHMgYmV0d2VlbiBwYWludHMpLlxuICAgICAgaWYgKHRoaXMuY2VyaW91c1Njcm9sbEF1dG9SZW5kZXIpIHRoaXMuc2NoZWR1bGVSZW5kZXIoKTtcbiAgICB9KTtcblxuICAgIHRoaXMudmlld3BvcnRTdWIgPSB0aGlzLmhvc3RSZWYudmlld3BvcnRDaGFuZ2VzJC5zdWJzY3JpYmUoKGRldGFpbDogQ2VyaW91c1ZpZXdwb3J0Q2hhbmdlRGV0YWlsKSA9PiB7XG4gICAgICAvLyBTa2lwIHRoZSBnbG9iYWwgdGljayB3aGVuIG5vYm9keSBpcyBib3VuZCB0byB0aGUgb3V0cHV0LlxuICAgICAgaWYgKHRoaXMuY2VyaW91c1Njcm9sbFZpZXdwb3J0Q2hhbmdlLm9ic2VydmVkKSB7XG4gICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB0aGlzLmNlcmlvdXNTY3JvbGxWaWV3cG9ydENoYW5nZS5lbWl0KGRldGFpbCkpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5jZXJpb3VzU2Nyb2xsUmVhZHkuZW1pdCh0aGlzLmhvc3RSZWYuc2Nyb2xsZXIpO1xuXG4gICAgaWYgKHRoaXMuY2VyaW91c1Njcm9sbEF1dG9SZW5kZXIpIHtcbiAgICAgIHF1ZXVlTWljcm90YXNrKCgpID0+IHRoaXMucmVuZGVyKCkpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0SXRlbUZvckluZGV4KGluZGV4OiBudW1iZXIpOiBUSXRlbSB7XG4gICAgY29uc3QgZ2V0dGVyID0gdGhpcy5jZXJpb3VzU2Nyb2xsR2V0SXRlbTtcbiAgICBpZiAoZ2V0dGVyKSByZXR1cm4gZ2V0dGVyKGluZGV4KTtcblxuICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5jZXJpb3VzU2Nyb2xsSXRlbXM7XG4gICAgaWYgKCFpdGVtcykgcmV0dXJuIHVuZGVmaW5lZCBhcyBUSXRlbTtcblxuICAgIHJldHVybiBpdGVtc1tpbmRleF07XG4gIH1cblxuICBwcml2YXRlIHJlbmRlclRlbXBsYXRlSW50b0NvbnRhaW5lcihcbiAgICB0ZW1wbGF0ZTogVGVtcGxhdGVSZWY8Q2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZUNvbnRleHQ8VEl0ZW0+PixcbiAgICBpbmRleDogbnVtYmVyLFxuICAgIGVsZW1lbnRDb250YWluZXI6IEhUTUxFbGVtZW50XG4gICk6IHZvaWQge1xuICAgIGNvbnN0IHByZXZpb3VzID0gdGhpcy52aWV3QnlDb250YWluZXIuZ2V0KGVsZW1lbnRDb250YWluZXIpO1xuICAgIGlmIChwcmV2aW91cykge1xuICAgICAgLy8gUmVjeWNsZTogdXBkYXRlIHRoZSBib3VuZCBjb250ZXh0IGFuZCBydW4gbG9jYWwgQ0QgaW5zdGVhZCBvZlxuICAgICAgLy8gZGVzdHJveWluZyB0aGUgZW1iZWRkZWQgdmlldyBhbmQgcmVidWlsZGluZyB0aGUgZW50aXJlIHJvdyB0cmVlLlxuICAgICAgY29uc3QgaXRlbSA9IHRoaXMuZ2V0SXRlbUZvckluZGV4KGluZGV4KTtcbiAgICAgIHByZXZpb3VzLmNvbnRleHQuJGltcGxpY2l0ID0gaXRlbTtcbiAgICAgIHByZXZpb3VzLmNvbnRleHQuaXRlbSA9IGl0ZW07XG4gICAgICBwcmV2aW91cy5jb250ZXh0LmluZGV4ID0gaW5kZXg7XG4gICAgICAvLyBUaGUgY29yZSBlbmdpbmUgd2lwZXMgZWxlbWVudENvbnRhaW5lci50ZXh0Q29udGVudCB3aGVuIHJldXNpbmcgaXQgZnJvbVxuICAgICAgLy8gaXRzIHBvb2wsIG9ycGhhbmluZyB0aGUgdmlldydzIHJvb3Qgbm9kZXMuIFJlLWFwcGVuZCB0aGVtIGRlZmVuc2l2ZWx5LlxuICAgICAgaWYgKHByZXZpb3VzLnJvb3ROb2Rlcy5sZW5ndGggJiYgcHJldmlvdXMucm9vdE5vZGVzWzBdLnBhcmVudE5vZGUgIT09IGVsZW1lbnRDb250YWluZXIpIHtcbiAgICAgICAgZm9yIChjb25zdCBub2RlIG9mIHByZXZpb3VzLnJvb3ROb2Rlcykge1xuICAgICAgICAgIGVsZW1lbnRDb250YWluZXIuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHByZXZpb3VzLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBUcnkgdG8gcmV1c2UgYSBwb29sZWQgdmlldyBmcm9tIGEgY29udGFpbmVyIHRoYXQgc2Nyb2xsZWQgb3V0IG9mIHZpZXdwb3J0LlxuICAgIGNvbnN0IHBvb2xlZCA9IHRoaXMuZnJlZVZpZXdzLnBvcCgpO1xuICAgIGlmIChwb29sZWQpIHtcbiAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLmdldEl0ZW1Gb3JJbmRleChpbmRleCk7XG4gICAgICBwb29sZWQuY29udGV4dC4kaW1wbGljaXQgPSBpdGVtO1xuICAgICAgcG9vbGVkLmNvbnRleHQuaXRlbSA9IGl0ZW07XG4gICAgICBwb29sZWQuY29udGV4dC5pbmRleCA9IGluZGV4O1xuICAgICAgZWxlbWVudENvbnRhaW5lci50ZXh0Q29udGVudCA9ICcnO1xuICAgICAgZm9yIChjb25zdCBub2RlIG9mIHBvb2xlZC5yb290Tm9kZXMpIHtcbiAgICAgICAgZWxlbWVudENvbnRhaW5lci5hcHBlbmRDaGlsZChub2RlKTtcbiAgICAgIH1cbiAgICAgIHBvb2xlZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB0aGlzLnZpZXdCeUNvbnRhaW5lci5zZXQoZWxlbWVudENvbnRhaW5lciwgcG9vbGVkKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBObyBwcmlvciB2aWV3IGZvciB0aGlzIGNvbnRhaW5lcjogY3JlYXRlIG9uZS5cbiAgICAvLyBFbnRlciB0aGUgQW5ndWxhciB6b25lIHNvIHRoZSBuZXcgdmlldydzIHRlbXBsYXRlIGV2ZW50IGxpc3RlbmVyc1xuICAgIC8vICgoY2xpY2spLCAoaW5wdXQpLCBldGMuKSBhcmUgem9uZS1wYXRjaGVkLiBUaGlzIHBhdGggcnVucyBhdCBtb3N0XG4gICAgLy8gb25jZSBwZXIgdmlzaWJsZSByb3cgKGFmdGVyIHRoYXQsIHRoZSB2aWV3IGlzIHJlY3ljbGVkIGZyb20gdGhlIHBvb2wpLlxuICAgIGVsZW1lbnRDb250YWluZXIudGV4dENvbnRlbnQgPSAnJztcblxuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLmdldEl0ZW1Gb3JJbmRleChpbmRleCk7XG4gICAgY29uc3QgdmlldyA9IHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICBjb25zdCB2ID0gdGVtcGxhdGUuY3JlYXRlRW1iZWRkZWRWaWV3KHsgJGltcGxpY2l0OiBpdGVtLCBpdGVtLCBpbmRleCB9KTtcbiAgICAgIHRoaXMuYXBwUmVmLmF0dGFjaFZpZXcodik7XG4gICAgICB2LmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHJldHVybiB2O1xuICAgIH0pO1xuXG4gICAgZm9yIChjb25zdCBub2RlIG9mIHZpZXcucm9vdE5vZGVzKSB7XG4gICAgICBlbGVtZW50Q29udGFpbmVyLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgIH1cblxuICAgIHRoaXMudmlld0J5Q29udGFpbmVyLnNldChlbGVtZW50Q29udGFpbmVyLCB2aWV3KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgdGhlIGJvdW5kIGl0ZW0vaW5kZXggb24gZXZlcnkgY3VycmVudGx5LXJlbmRlcmVkIHJvdydzIGVtYmVkZGVkIHZpZXdcbiAgICogYW5kIHJ1biBjaGFuZ2UgZGV0ZWN0aW9uLCB3aXRob3V0IHJlY3JlYXRpbmcgdGhlIHZpZXdzLiBVc2VkIHdoZW4gdGhlIGRhdGFcbiAgICogcmVmZXJlbmNlIGNoYW5nZXMgYnV0IHRoZSB2aXNpYmxlIGluZGljZXMgKGFuZCB0aGVpciBoZWlnaHRzKSBkbyBub3QsIHNvIHJvd1xuICAgKiBzdGF0ZSAoZm9jdXMsIHNlbGVjdGlvbiwgb3BlbiBkcm9wZG93bnMpIHN1cnZpdmVzIHRoZSB1cGRhdGUuXG4gICAqL1xuICAvKipcbiAgICogUmUtYmluZCBlYWNoIGN1cnJlbnRseSByZW5kZXJlZCByb3cncyBjb250ZXh0IChmcm9tIHRoZSBjdXJyZW50IGl0ZW1zL2dldHRlcilcbiAgICogYW5kIHJ1biBjaGFuZ2UgZGV0ZWN0aW9uIG9uIGl0cyBlbWJlZGRlZCB2aWV3LiBVc2UgdGhpcyBhZnRlciBtdXRhdGluZyByb3dcbiAgICogc3RhdGUgaW4gcGxhY2UgKGUuZy4gc2VsZWN0aW9uIGZsYWdzKSBvciBjb2x1bW4tbGV2ZWwgc3RhdGUgcmVhZCBieSB0aGUgcm93XG4gICAqIHRlbXBsYXRlLCB3aGVuIHJvdyBpZGVudGl0eSBhbmQgdmlzaWJsZSBpbmRpY2VzIGhhdmUgbm90IGNoYW5nZWQuIENoZWFwXG4gICAqIHJlbGF0aXZlIHRvIGByZW5kZXIoKWAg4oCUIGRvZXMgbm90IGludm9rZSB0aGUgZW5naW5lJ3MgbWVhc3VyZW1lbnQgcGFzcy5cbiAgICovXG4gIHJlZnJlc2hSZW5kZXJlZENvbnRlbnQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYpIHJldHVybjtcbiAgICBjb25zdCBzY3JvbGxlciA9IHRoaXMuaG9zdFJlZi5zY3JvbGxlcjtcblxuICAgIGZvciAoY29uc3QgaW5kZXggb2Ygc2Nyb2xsZXIuZ2V0UmVuZGVyZWRJbmRpY2VzKCkpIHtcbiAgICAgIGNvbnN0IGNvbnRhaW5lciA9IHNjcm9sbGVyLmdldFJlbmRlcmVkRWxlbWVudChpbmRleCk7XG4gICAgICBpZiAoIWNvbnRhaW5lcikgY29udGludWU7XG5cbiAgICAgIGNvbnN0IHZpZXcgPSB0aGlzLnZpZXdCeUNvbnRhaW5lci5nZXQoY29udGFpbmVyKTtcbiAgICAgIGlmICghdmlldykgY29udGludWU7XG5cbiAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLmdldEl0ZW1Gb3JJbmRleChpbmRleCk7XG4gICAgICB2aWV3LmNvbnRleHQuJGltcGxpY2l0ID0gaXRlbTtcbiAgICAgIHZpZXcuY29udGV4dC5pdGVtID0gaXRlbTtcbiAgICAgIHZpZXcuY29udGV4dC5pbmRleCA9IGluZGV4O1xuICAgICAgdmlldy5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBkZXN0cm95QWxsVmlld3MoKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCB2aWV3IG9mIHRoaXMudmlld0J5Q29udGFpbmVyLnZhbHVlcygpKSB7XG4gICAgICB0aGlzLmFwcFJlZi5kZXRhY2hWaWV3KHZpZXcpO1xuICAgICAgdmlldy5kZXN0cm95KCk7XG4gICAgfVxuICAgIHRoaXMudmlld0J5Q29udGFpbmVyLmNsZWFyKCk7XG4gICAgZm9yIChjb25zdCB2aWV3IG9mIHRoaXMuZnJlZVZpZXdzKSB7XG4gICAgICB0aGlzLmFwcFJlZi5kZXRhY2hWaWV3KHZpZXcpO1xuICAgICAgdmlldy5kZXN0cm95KCk7XG4gICAgfVxuICAgIHRoaXMuZnJlZVZpZXdzLmxlbmd0aCA9IDA7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -138,7 +138,13 @@ class CeriousScrollDirective {
|
|
|
138
138
|
this.ceriousScrollReady = new EventEmitter();
|
|
139
139
|
this.hostRef = null;
|
|
140
140
|
this.viewportSub = null;
|
|
141
|
+
this.scheduledRenderFrame = null;
|
|
141
142
|
this.viewByContainer = new Map();
|
|
143
|
+
// Pool of views detached because their container left the viewport. Reusing
|
|
144
|
+
// them on subsequent renders avoids destroying + recreating the entire row
|
|
145
|
+
// component tree on fast scrolls (where the engine's element pool wipes
|
|
146
|
+
// textContent on reused containers, so view rootNodes get orphaned).
|
|
147
|
+
this.freeViews = [];
|
|
142
148
|
}
|
|
143
149
|
ngAfterViewInit() {
|
|
144
150
|
this.ensureInitialized();
|
|
@@ -148,10 +154,33 @@ class CeriousScrollDirective {
|
|
|
148
154
|
return;
|
|
149
155
|
if (changes['ceriousScrollItems'] || changes['ceriousScrollTotalElements']) {
|
|
150
156
|
const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);
|
|
151
|
-
this.hostRef.scroller.totalElements
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
const countChanged = this.hostRef.scroller.totalElements !== total;
|
|
158
|
+
if (countChanged) {
|
|
159
|
+
// The dataset size changed: the ViewportRenderer stores its own copy of
|
|
160
|
+
// totalElements (set by value at construction) so patching the engine's
|
|
161
|
+
// public property alone leaves the renderer's internal bound stale. The
|
|
162
|
+
// renderer would then use the old count for its viewport-fill loop and
|
|
163
|
+
// bottom-boundary scan, producing phantom renders at out-of-bounds
|
|
164
|
+
// indices (undefined items → 0-height rows → the fill loop never
|
|
165
|
+
// satisfies its height condition → hundreds of renderer callbacks).
|
|
166
|
+
// Recreating the engine gives both the engine and the renderer a fresh,
|
|
167
|
+
// consistent count. ensureInitialized() schedules the first render via
|
|
168
|
+
// queueMicrotask, which runs after the current CD cycle completes.
|
|
169
|
+
this.recreate();
|
|
170
|
+
}
|
|
171
|
+
else if (this.ceriousScrollAutoRender) {
|
|
172
|
+
// Same count, new data reference (e.g. an immutable edit or a sort that
|
|
173
|
+
// happens to keep the same length). The engine reuses the DOM element it
|
|
174
|
+
// already rendered for each overlapping index without re-invoking the
|
|
175
|
+
// renderer, so update the content of every currently-visible row IN
|
|
176
|
+
// PLACE before calling render(). This preserves each row's embedded
|
|
177
|
+
// view (so a focused textbox keeps focus/caret) and does NOT discard
|
|
178
|
+
// cached heights. If a row's height actually changes the engine's
|
|
179
|
+
// ResizeObserver keeps the cache correct on its own; for a wholesale
|
|
180
|
+
// height change across all rows, call recalculate() instead.
|
|
181
|
+
this.refreshRenderedContent();
|
|
154
182
|
this.render();
|
|
183
|
+
}
|
|
155
184
|
}
|
|
156
185
|
if (changes['ceriousScrollOptions'] && !changes['ceriousScrollOptions'].firstChange) {
|
|
157
186
|
// Options are consumed primarily at construction time.
|
|
@@ -159,6 +188,10 @@ class CeriousScrollDirective {
|
|
|
159
188
|
}
|
|
160
189
|
}
|
|
161
190
|
ngOnDestroy() {
|
|
191
|
+
if (this.scheduledRenderFrame != null) {
|
|
192
|
+
cancelAnimationFrame(this.scheduledRenderFrame);
|
|
193
|
+
this.scheduledRenderFrame = null;
|
|
194
|
+
}
|
|
162
195
|
this.viewportSub?.unsubscribe();
|
|
163
196
|
this.viewportSub = null;
|
|
164
197
|
this.destroyAllViews();
|
|
@@ -175,16 +208,122 @@ class CeriousScrollDirective {
|
|
|
175
208
|
const hostContainer = this.host.nativeElement;
|
|
176
209
|
const height = hostContainer.clientHeight || hostContainer.offsetHeight;
|
|
177
210
|
const contentContainer = this.hostRef.contentElement;
|
|
211
|
+
// Track whether the engine asked us to bind any row this pass. Pure scroll
|
|
212
|
+
// frames where the visible row set doesn't change still drive render() via
|
|
213
|
+
// the rAF coalescer — there's no point in walking the prune map or
|
|
214
|
+
// emitting the viewport range when nothing was touched.
|
|
215
|
+
let rendererInvocations = 0;
|
|
178
216
|
const renderer = (index, elementContainer) => {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
217
|
+
rendererInvocations++;
|
|
218
|
+
// Render each row's embedded view with LOCAL change detection
|
|
219
|
+
// (`view.detectChanges()` inside `renderTemplateIntoContainer`) so the
|
|
220
|
+
// engine can measure its height during this pass. Do NOT wrap each row in
|
|
221
|
+
// its own `ngZone.run` — that fires a full `ApplicationRef` tick *per row*
|
|
222
|
+
// (O(newRows × visibleRows) work, janky drags). The single coalesced tick
|
|
223
|
+
// for the whole pass is handled by the caller (`scheduleRender`).
|
|
224
|
+
this.renderTemplateIntoContainer(template, index, elementContainer);
|
|
183
225
|
};
|
|
184
226
|
const range = this.hostRef.scroller.renderViewport(height, contentContainer, renderer);
|
|
185
|
-
|
|
227
|
+
if (rendererInvocations === 0) {
|
|
228
|
+
// Viewport didn't change — skip the prune walk and the (potentially
|
|
229
|
+
// zone-entering) emit.
|
|
230
|
+
return range;
|
|
231
|
+
}
|
|
232
|
+
// Destroy views whose container the engine no longer renders. Without this,
|
|
233
|
+
// every container the engine recycles into its element pool leaves its
|
|
234
|
+
// embedded view attached to ApplicationRef forever — so the attached-view
|
|
235
|
+
// list (and every O(n) `detachView`) grows without bound and scrolling gets
|
|
236
|
+
// progressively slower. Mirrors the React/Vue wrappers, which drop rows that
|
|
237
|
+
// fall out of `getRenderedIndices()`.
|
|
238
|
+
this.pruneDetachedViews();
|
|
239
|
+
// Only re-enter the zone (a global tick) if someone is actually listening.
|
|
240
|
+
if (this.ceriousScrollMeasuredViewport.observed) {
|
|
241
|
+
this.ngZone.run(() => this.ceriousScrollMeasuredViewport.emit(range));
|
|
242
|
+
}
|
|
186
243
|
return range;
|
|
187
244
|
}
|
|
245
|
+
/** Tear down embedded views whose container is no longer part of the viewport. */
|
|
246
|
+
pruneDetachedViews() {
|
|
247
|
+
if (!this.hostRef || this.viewByContainer.size === 0)
|
|
248
|
+
return;
|
|
249
|
+
const scroller = this.hostRef.scroller;
|
|
250
|
+
const active = new Set();
|
|
251
|
+
for (const index of scroller.getRenderedIndices()) {
|
|
252
|
+
const el = scroller.getRenderedElement(index);
|
|
253
|
+
if (el)
|
|
254
|
+
active.add(el);
|
|
255
|
+
}
|
|
256
|
+
for (const [container, view] of this.viewByContainer) {
|
|
257
|
+
if (!active.has(container)) {
|
|
258
|
+
// Detach DOM but keep the view alive in the pool for future reuse.
|
|
259
|
+
// Destroying + recreating views per scroll step dominates frame time.
|
|
260
|
+
for (const node of view.rootNodes) {
|
|
261
|
+
if (node.parentNode)
|
|
262
|
+
node.parentNode.removeChild(node);
|
|
263
|
+
}
|
|
264
|
+
this.viewByContainer.delete(container);
|
|
265
|
+
this.freeViews.push(view);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/** Auto-render coalesced to at most once per animation frame. */
|
|
270
|
+
scheduleRender() {
|
|
271
|
+
if (this.scheduledRenderFrame != null)
|
|
272
|
+
return;
|
|
273
|
+
this.scheduledRenderFrame = requestAnimationFrame(() => {
|
|
274
|
+
this.scheduledRenderFrame = null;
|
|
275
|
+
// Run render() OUTSIDE Angular's zone. A full ApplicationRef.tick() on
|
|
276
|
+
// every scroll frame is the primary FPS bottleneck: even when no rows
|
|
277
|
+
// change (pure translation), ngZone.run() causes Angular to walk the
|
|
278
|
+
// entire component tree. Instead we call view.detectChanges() locally
|
|
279
|
+
// inside renderTemplateIntoContainer for each affected row. Zone entry is
|
|
280
|
+
// only needed when creating a brand-new embedded view (to zone-patch its
|
|
281
|
+
// event listeners) — recycled and pooled views were already created inside
|
|
282
|
+
// zone and their listeners remain zone-aware.
|
|
283
|
+
this.render();
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Discard all cached row heights and re-measure the viewport.
|
|
288
|
+
*
|
|
289
|
+
* Call this only when the heights of rows you've *already rendered* may have
|
|
290
|
+
* changed without their indices changing — e.g. a global font/density change,
|
|
291
|
+
* or swapping every row to a different layout. This forces a synchronous
|
|
292
|
+
* re-measure (one `offsetHeight` read per visible row), so do NOT call it on
|
|
293
|
+
* routine edits: a single cell edit keeps its row's size, and the engine's
|
|
294
|
+
* ResizeObserver picks up any incidental resize on its own.
|
|
295
|
+
*/
|
|
296
|
+
recalculate() {
|
|
297
|
+
if (!this.hostRef)
|
|
298
|
+
return null;
|
|
299
|
+
// Discard the cached heights, then re-render. The engine re-measures and
|
|
300
|
+
// re-caches the rendered rows during the pass and refreshes the scroll
|
|
301
|
+
// percentage, so an in-place height change (e.g. expand/collapse) is
|
|
302
|
+
// reflected in the total content height and scrollbar immediately.
|
|
303
|
+
this.hostRef.scroller.clearAllCaches();
|
|
304
|
+
return this.render();
|
|
305
|
+
}
|
|
306
|
+
/** Jump directly to an element index, then render. */
|
|
307
|
+
jumpToElement(index) {
|
|
308
|
+
if (!this.hostRef)
|
|
309
|
+
return null;
|
|
310
|
+
this.hostRef.scroller.jumpToElement(index);
|
|
311
|
+
return this.render();
|
|
312
|
+
}
|
|
313
|
+
/** Scroll to a percentage (0..100), then render. */
|
|
314
|
+
scrollToPercentage(percentage) {
|
|
315
|
+
if (!this.hostRef)
|
|
316
|
+
return null;
|
|
317
|
+
this.hostRef.scroller.handleScrollPercentage(percentage);
|
|
318
|
+
return this.render();
|
|
319
|
+
}
|
|
320
|
+
/** Reset to the top, then render. */
|
|
321
|
+
reset() {
|
|
322
|
+
if (!this.hostRef)
|
|
323
|
+
return null;
|
|
324
|
+
this.hostRef.scroller.reset();
|
|
325
|
+
return this.render();
|
|
326
|
+
}
|
|
188
327
|
recreate() {
|
|
189
328
|
this.viewportSub?.unsubscribe();
|
|
190
329
|
this.viewportSub = null;
|
|
@@ -199,11 +338,16 @@ class CeriousScrollDirective {
|
|
|
199
338
|
const container = this.host.nativeElement;
|
|
200
339
|
const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);
|
|
201
340
|
this.hostRef = this.cerious.createHost(container, total, this.ceriousScrollOptions, this.ngZone, () => {
|
|
341
|
+
// Coalesce scroll-driven renders to one per frame (the native scrollbar
|
|
342
|
+
// can fire many scroll events between paints).
|
|
202
343
|
if (this.ceriousScrollAutoRender)
|
|
203
|
-
this.
|
|
344
|
+
this.scheduleRender();
|
|
204
345
|
});
|
|
205
346
|
this.viewportSub = this.hostRef.viewportChanges$.subscribe((detail) => {
|
|
206
|
-
|
|
347
|
+
// Skip the global tick when nobody is bound to the output.
|
|
348
|
+
if (this.ceriousScrollViewportChange.observed) {
|
|
349
|
+
this.ngZone.run(() => this.ceriousScrollViewportChange.emit(detail));
|
|
350
|
+
}
|
|
207
351
|
});
|
|
208
352
|
this.ceriousScrollReady.emit(this.hostRef.scroller);
|
|
209
353
|
if (this.ceriousScrollAutoRender) {
|
|
@@ -222,27 +366,96 @@ class CeriousScrollDirective {
|
|
|
222
366
|
renderTemplateIntoContainer(template, index, elementContainer) {
|
|
223
367
|
const previous = this.viewByContainer.get(elementContainer);
|
|
224
368
|
if (previous) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this.
|
|
369
|
+
// Recycle: update the bound context and run local CD instead of
|
|
370
|
+
// destroying the embedded view and rebuilding the entire row tree.
|
|
371
|
+
const item = this.getItemForIndex(index);
|
|
372
|
+
previous.context.$implicit = item;
|
|
373
|
+
previous.context.item = item;
|
|
374
|
+
previous.context.index = index;
|
|
375
|
+
// The core engine wipes elementContainer.textContent when reusing it from
|
|
376
|
+
// its pool, orphaning the view's root nodes. Re-append them defensively.
|
|
377
|
+
if (previous.rootNodes.length && previous.rootNodes[0].parentNode !== elementContainer) {
|
|
378
|
+
for (const node of previous.rootNodes) {
|
|
379
|
+
elementContainer.appendChild(node);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
previous.detectChanges();
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
// Try to reuse a pooled view from a container that scrolled out of viewport.
|
|
386
|
+
const pooled = this.freeViews.pop();
|
|
387
|
+
if (pooled) {
|
|
388
|
+
const item = this.getItemForIndex(index);
|
|
389
|
+
pooled.context.$implicit = item;
|
|
390
|
+
pooled.context.item = item;
|
|
391
|
+
pooled.context.index = index;
|
|
392
|
+
elementContainer.textContent = '';
|
|
393
|
+
for (const node of pooled.rootNodes) {
|
|
394
|
+
elementContainer.appendChild(node);
|
|
395
|
+
}
|
|
396
|
+
pooled.detectChanges();
|
|
397
|
+
this.viewByContainer.set(elementContainer, pooled);
|
|
398
|
+
return;
|
|
228
399
|
}
|
|
229
|
-
//
|
|
400
|
+
// No prior view for this container: create one.
|
|
401
|
+
// Enter the Angular zone so the new view's template event listeners
|
|
402
|
+
// ((click), (input), etc.) are zone-patched. This path runs at most
|
|
403
|
+
// once per visible row (after that, the view is recycled from the pool).
|
|
230
404
|
elementContainer.textContent = '';
|
|
231
405
|
const item = this.getItemForIndex(index);
|
|
232
|
-
const view =
|
|
233
|
-
|
|
234
|
-
|
|
406
|
+
const view = this.ngZone.run(() => {
|
|
407
|
+
const v = template.createEmbeddedView({ $implicit: item, item, index });
|
|
408
|
+
this.appRef.attachView(v);
|
|
409
|
+
v.detectChanges();
|
|
410
|
+
return v;
|
|
411
|
+
});
|
|
235
412
|
for (const node of view.rootNodes) {
|
|
236
413
|
elementContainer.appendChild(node);
|
|
237
414
|
}
|
|
238
415
|
this.viewByContainer.set(elementContainer, view);
|
|
239
416
|
}
|
|
417
|
+
/**
|
|
418
|
+
* Update the bound item/index on every currently-rendered row's embedded view
|
|
419
|
+
* and run change detection, without recreating the views. Used when the data
|
|
420
|
+
* reference changes but the visible indices (and their heights) do not, so row
|
|
421
|
+
* state (focus, selection, open dropdowns) survives the update.
|
|
422
|
+
*/
|
|
423
|
+
/**
|
|
424
|
+
* Re-bind each currently rendered row's context (from the current items/getter)
|
|
425
|
+
* and run change detection on its embedded view. Use this after mutating row
|
|
426
|
+
* state in place (e.g. selection flags) or column-level state read by the row
|
|
427
|
+
* template, when row identity and visible indices have not changed. Cheap
|
|
428
|
+
* relative to `render()` — does not invoke the engine's measurement pass.
|
|
429
|
+
*/
|
|
430
|
+
refreshRenderedContent() {
|
|
431
|
+
if (!this.hostRef)
|
|
432
|
+
return;
|
|
433
|
+
const scroller = this.hostRef.scroller;
|
|
434
|
+
for (const index of scroller.getRenderedIndices()) {
|
|
435
|
+
const container = scroller.getRenderedElement(index);
|
|
436
|
+
if (!container)
|
|
437
|
+
continue;
|
|
438
|
+
const view = this.viewByContainer.get(container);
|
|
439
|
+
if (!view)
|
|
440
|
+
continue;
|
|
441
|
+
const item = this.getItemForIndex(index);
|
|
442
|
+
view.context.$implicit = item;
|
|
443
|
+
view.context.item = item;
|
|
444
|
+
view.context.index = index;
|
|
445
|
+
view.detectChanges();
|
|
446
|
+
}
|
|
447
|
+
}
|
|
240
448
|
destroyAllViews() {
|
|
241
449
|
for (const view of this.viewByContainer.values()) {
|
|
242
450
|
this.appRef.detachView(view);
|
|
243
451
|
view.destroy();
|
|
244
452
|
}
|
|
245
453
|
this.viewByContainer.clear();
|
|
454
|
+
for (const view of this.freeViews) {
|
|
455
|
+
this.appRef.detachView(view);
|
|
456
|
+
view.destroy();
|
|
457
|
+
}
|
|
458
|
+
this.freeViews.length = 0;
|
|
246
459
|
}
|
|
247
460
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CeriousScrollDirective, deps: [{ token: i0.ElementRef }, { token: i0.ApplicationRef }, { token: i0.NgZone }, { token: CeriousScrollService }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
248
461
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: CeriousScrollDirective, isStandalone: true, selector: "[ceriousScroll]", inputs: { ceriousScrollTotalElements: "ceriousScrollTotalElements", ceriousScrollItems: "ceriousScrollItems", ceriousScrollGetItem: "ceriousScrollGetItem", ceriousScrollItemTemplate: "ceriousScrollItemTemplate", ceriousScrollOptions: "ceriousScrollOptions", ceriousScrollAutoRender: "ceriousScrollAutoRender" }, outputs: { ceriousScrollViewportChange: "ceriousScrollViewportChange", ceriousScrollMeasuredViewport: "ceriousScrollMeasuredViewport", ceriousScrollReady: "ceriousScrollReady" }, usesOnChanges: true, ngImport: i0 }); }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ceriousdevtech-ngx-cerious-scroll.mjs","sources":["../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll.observable.ts","../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll-item-template.directive.ts","../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll.service.ts","../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll.directive.ts","../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll.component.ts","../../../projects/ngx-cerious-scroll/src/public-api.ts","../../../projects/ngx-cerious-scroll/src/ceriousdevtech-ngx-cerious-scroll.ts"],"sourcesContent":["import { fromEvent, map, merge, Observable, share } from 'rxjs';\n\nimport type { ScrollResult } from '@ceriousdevtech/cerious-scroll';\n\nimport {\n CeriousNativeScrollbarViewportChangeEvent,\n CeriousViewportChangeDetail,\n CeriousViewportChangeEvent,\n} from './cerious-scroll.types';\n\n/**\n * Observable wrapper around the `cerious-viewport-change` CustomEvent emitted by `@ceriousdevtech/cerious-scroll`.\n *\n * Note: this event is emitted when wheel/touch/keyboard handlers are enabled (defaults are enabled).\n */\nexport function ceriousViewportChange$(container: HTMLElement): Observable<CeriousViewportChangeDetail> {\n const fromCerious = fromEvent<CeriousViewportChangeEvent>(container, 'cerious-viewport-change').pipe(\n map((evt) => evt.detail)\n );\n\n // Native scrollbar integration in the upstream package dispatches `viewport-change`.\n // Normalize it into the same shape as `cerious-viewport-change`.\n const fromScrollbar = fromEvent<CeriousNativeScrollbarViewportChangeEvent>(container, 'viewport-change').pipe(\n map((evt) => {\n const result: ScrollResult = { element: evt.detail.element, offset: evt.detail.scrollOffset };\n return {\n percentage: evt.detail.percentage,\n currentElement: evt.detail.element,\n scrollOffset: evt.detail.scrollOffset,\n result,\n } satisfies CeriousViewportChangeDetail;\n })\n );\n\n return merge(fromCerious, fromScrollbar).pipe(share());\n}\n","import { Directive, TemplateRef } from '@angular/core';\n\nexport interface CeriousScrollItemTemplateContext<TItem = unknown> {\n /** The item for this row (also available as `$implicit`). */\n $implicit: TItem;\n /** Row index. */\n index: number;\n /** Same as `$implicit` for named access. */\n item: TItem;\n}\n\n/**\n * Marks an `ng-template` as the row template for `CeriousScrollComponent`.\n *\n * Usage:\n * ```html\n * <cerious-scroll [items]=\"items\">\n * <ng-template ceriousScrollItem let-item let-index=\"index\">\n * {{ index }} - {{ item.name }}\n * </ng-template>\n * </cerious-scroll>\n * ```\n */\n@Directive({\n selector: 'ng-template[ceriousScrollItem]',\n standalone: true,\n})\nexport class CeriousScrollItemTemplateDirective<TItem = unknown> {\n constructor(public readonly templateRef: TemplateRef<CeriousScrollItemTemplateContext<TItem>>) {}\n}\n","import { Injectable, NgZone } from '@angular/core';\n\nimport { CeriousScroll, type CeriousScrollOptions } from '@ceriousdevtech/cerious-scroll';\nimport { Observable } from 'rxjs';\n\nimport { ceriousViewportChange$ } from './cerious-scroll.observable';\nimport type { CeriousViewportChangeDetail } from './cerious-scroll.types';\n\nconst CONTENT_ATTR = 'data-cerious-scroll-content';\n\nfunction ensureContentElement(container: HTMLElement): HTMLElement {\n const existing = container.querySelector<HTMLElement>(`[${CONTENT_ATTR}]`);\n if (existing) return existing;\n\n const el = document.createElement('div');\n el.setAttribute(CONTENT_ATTR, '');\n el.style.position = 'relative';\n el.style.width = '100%';\n el.style.height = '100%';\n el.style.overflow = 'hidden';\n container.appendChild(el);\n return el;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class CeriousScrollService {\n createHost(\n container: HTMLElement,\n totalElements: number,\n options: CeriousScrollOptions,\n ngZone: NgZone,\n onScrollHook?: () => void\n ): CeriousScrollHostRef {\n const contentElement = ensureContentElement(container);\n let scroller!: CeriousScroll;\n\n ngZone.runOutsideAngular(() => {\n const userOnScroll = options?.onScroll;\n const mergedOptions: CeriousScrollOptions = {\n ...options,\n onScroll: () => {\n userOnScroll?.();\n onScrollHook?.();\n },\n };\n\n scroller = new CeriousScroll(container, totalElements, mergedOptions);\n });\n\n const viewportChanges$ = ceriousViewportChange$(container);\n\n return {\n scroller,\n contentElement,\n viewportChanges$,\n destroy: () => {\n // Remove rendered rows content first; keep container stable.\n contentElement.textContent = '';\n scroller.detachScrollbar(container);\n scroller.dispose();\n },\n };\n }\n}\n\nexport interface CeriousScrollHostRef {\n readonly scroller: CeriousScroll;\n /** Dedicated element used for row rendering (prevents scrollbar DOM from being cleared). */\n readonly contentElement: HTMLElement;\n readonly viewportChanges$: Observable<CeriousViewportChangeDetail>;\n destroy(): void;\n}\n","import {\n AfterViewInit,\n ApplicationRef,\n Directive,\n ElementRef,\n EmbeddedViewRef,\n EventEmitter,\n Input,\n NgZone,\n OnChanges,\n OnDestroy,\n Output,\n SimpleChanges,\n TemplateRef,\n} from '@angular/core';\n\nimport {\n type CeriousScrollOptions,\n type ElementRenderer,\n type MeasuredViewportRange,\n} from '@ceriousdevtech/cerious-scroll';\nimport { Subscription } from 'rxjs';\n\nimport type { CeriousViewportChangeDetail } from './cerious-scroll.types';\nimport type { CeriousScrollItemTemplateContext } from './cerious-scroll-item-template.directive';\nimport { type CeriousScrollHostRef, CeriousScrollService } from './cerious-scroll.service';\n\nfunction coerceTotalElements(explicitTotal: number | null | undefined, itemsLen: number | null | undefined): number {\n const candidate = typeof explicitTotal === 'number' ? explicitTotal : typeof itemsLen === 'number' ? itemsLen : undefined;\n if (candidate === undefined || Number.isNaN(candidate)) {\n throw new Error('CeriousScrollDirective: provide `ceriousScrollTotalElements` or `ceriousScrollItems`.');\n }\n // CeriousScroll currently requires >= 1\n return Math.max(1, candidate);\n}\n\n@Directive({\n selector: '[ceriousScroll]',\n standalone: true,\n})\nexport class CeriousScrollDirective<TItem = unknown> implements AfterViewInit, OnChanges, OnDestroy {\n /** Total number of items. If omitted, derived from `ceriousScrollItems.length`. */\n @Input() ceriousScrollTotalElements: number | null = null;\n\n /** Optional items array (enables `let-item`). */\n @Input() ceriousScrollItems: readonly TItem[] | null = null;\n\n /** Optional getter for large datasets (alternative to passing full `items`). */\n @Input() ceriousScrollGetItem: ((index: number) => TItem) | null = null;\n\n /** Template used to render each row. */\n @Input() ceriousScrollItemTemplate: TemplateRef<CeriousScrollItemTemplateContext<TItem>> | null = null;\n\n /** Options passed to `new CeriousScroll(...)`. */\n @Input() ceriousScrollOptions: CeriousScrollOptions = {};\n\n /** Automatically call render after each scroll event. Default: true */\n @Input() ceriousScrollAutoRender = true;\n\n /** Emits `cerious-viewport-change` detail. */\n @Output() ceriousScrollViewportChange = new EventEmitter<CeriousViewportChangeDetail>();\n\n /** Emits the last measured viewport after each render pass. */\n @Output() ceriousScrollMeasuredViewport = new EventEmitter<MeasuredViewportRange>();\n\n /** Emits once the underlying `CeriousScroll` instance is ready. */\n @Output() ceriousScrollReady = new EventEmitter<CeriousScrollHostRef['scroller']>();\n\n private hostRef: CeriousScrollHostRef | null = null;\n private viewportSub: Subscription | null = null;\n\n private readonly viewByContainer = new Map<HTMLElement, EmbeddedViewRef<CeriousScrollItemTemplateContext<TItem>>>();\n\n constructor(\n private readonly host: ElementRef<HTMLElement>,\n private readonly appRef: ApplicationRef,\n private readonly ngZone: NgZone,\n private readonly cerious: CeriousScrollService\n ) {}\n\n ngAfterViewInit(): void {\n this.ensureInitialized();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (!this.hostRef) return;\n\n if (changes['ceriousScrollItems'] || changes['ceriousScrollTotalElements']) {\n const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);\n this.hostRef.scroller.totalElements = total;\n this.hostRef.scroller.clearAllCaches();\n if (this.ceriousScrollAutoRender) this.render();\n }\n\n if (changes['ceriousScrollOptions'] && !changes['ceriousScrollOptions'].firstChange) {\n // Options are consumed primarily at construction time.\n this.recreate();\n }\n }\n\n ngOnDestroy(): void {\n this.viewportSub?.unsubscribe();\n this.viewportSub = null;\n\n this.destroyAllViews();\n\n this.hostRef?.destroy();\n this.hostRef = null;\n }\n\n /** Imperatively trigger a render pass (uses `ceriousScrollItemTemplate`). */\n render(): MeasuredViewportRange | null {\n if (!this.hostRef) return null;\n const template = this.ceriousScrollItemTemplate;\n if (!template) return null;\n\n const hostContainer = this.host.nativeElement;\n const height = hostContainer.clientHeight || hostContainer.offsetHeight;\n const contentContainer = this.hostRef.contentElement;\n\n const renderer: ElementRenderer = (index, elementContainer) => {\n // Rendering must create Angular views inside the Angular zone.\n this.ngZone.run(() => {\n this.renderTemplateIntoContainer(template, index, elementContainer);\n });\n };\n\n const range = this.hostRef.scroller.renderViewport(height, contentContainer, renderer);\n this.ngZone.run(() => this.ceriousScrollMeasuredViewport.emit(range));\n return range;\n }\n\n private recreate(): void {\n this.viewportSub?.unsubscribe();\n this.viewportSub = null;\n\n this.destroyAllViews();\n\n this.hostRef?.destroy();\n this.hostRef = null;\n\n this.ensureInitialized();\n }\n\n private ensureInitialized(): void {\n if (this.hostRef) return;\n\n const container = this.host.nativeElement;\n const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);\n\n this.hostRef = this.cerious.createHost(container, total, this.ceriousScrollOptions, this.ngZone, () => {\n if (this.ceriousScrollAutoRender) this.render();\n });\n\n this.viewportSub = this.hostRef.viewportChanges$.subscribe((detail: CeriousViewportChangeDetail) => {\n this.ngZone.run(() => this.ceriousScrollViewportChange.emit(detail));\n });\n\n this.ceriousScrollReady.emit(this.hostRef.scroller);\n\n if (this.ceriousScrollAutoRender) {\n queueMicrotask(() => this.render());\n }\n }\n\n private getItemForIndex(index: number): TItem {\n const getter = this.ceriousScrollGetItem;\n if (getter) return getter(index);\n\n const items = this.ceriousScrollItems;\n if (!items) return undefined as TItem;\n\n return items[index];\n }\n\n private renderTemplateIntoContainer(\n template: TemplateRef<CeriousScrollItemTemplateContext<TItem>>,\n index: number,\n elementContainer: HTMLElement\n ): void {\n const previous = this.viewByContainer.get(elementContainer);\n if (previous) {\n this.appRef.detachView(previous);\n previous.destroy();\n this.viewByContainer.delete(elementContainer);\n }\n\n // Clear prior DOM (CeriousScroll may recycle containers).\n elementContainer.textContent = '';\n\n const item = this.getItemForIndex(index);\n const view = template.createEmbeddedView({ $implicit: item, item, index });\n this.appRef.attachView(view);\n view.detectChanges();\n\n for (const node of view.rootNodes) {\n elementContainer.appendChild(node);\n }\n\n this.viewByContainer.set(elementContainer, view);\n }\n\n private destroyAllViews(): void {\n for (const view of this.viewByContainer.values()) {\n this.appRef.detachView(view);\n view.destroy();\n }\n this.viewByContainer.clear();\n }\n}\n","import {\n AfterContentInit,\n ChangeDetectionStrategy,\n Component,\n ContentChild,\n TemplateRef,\n} from '@angular/core';\n\nimport { CeriousScrollDirective } from './cerious-scroll.directive';\nimport {\n CeriousScrollItemTemplateDirective,\n type CeriousScrollItemTemplateContext,\n} from './cerious-scroll-item-template.directive';\n\n@Component({\n selector: 'cerious-scroll',\n standalone: true,\n imports: [],\n hostDirectives: [\n {\n directive: CeriousScrollDirective,\n inputs: [\n 'ceriousScrollTotalElements: totalElements',\n 'ceriousScrollItems: items',\n 'ceriousScrollGetItem: getItem',\n 'ceriousScrollItemTemplate: itemTemplate',\n 'ceriousScrollOptions: options',\n 'ceriousScrollAutoRender: autoRender',\n ],\n outputs: [\n 'ceriousScrollViewportChange: viewportChange',\n 'ceriousScrollMeasuredViewport: measuredViewport',\n 'ceriousScrollReady: scrollerReady',\n ],\n },\n ],\n template: `<ng-content />`,\n styles: `\n :host {\n display: block;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class CeriousScrollComponent<TItem = unknown> implements AfterContentInit {\n /** Optional convenience template marker: <ng-template ceriousScrollItem let-item let-index=\"index\">...</ng-template> */\n @ContentChild(CeriousScrollItemTemplateDirective)\n private readonly projectedItemTemplate?: CeriousScrollItemTemplateDirective<TItem>;\n\n constructor(private readonly ceriousScroll: CeriousScrollDirective<TItem>) {}\n\n ngAfterContentInit(): void {\n if (this.ceriousScroll.ceriousScrollItemTemplate) return;\n if (!this.projectedItemTemplate) return;\n\n this.ceriousScroll.ceriousScrollItemTemplate =\n this.projectedItemTemplate.templateRef as TemplateRef<CeriousScrollItemTemplateContext<TItem>>;\n\n if (this.ceriousScroll.ceriousScrollAutoRender) {\n queueMicrotask(() => this.ceriousScroll.render());\n }\n }\n}\n","/*\n * Public API Surface of ngx-cerious-scroll\n */\n\nexport * from './lib/cerious-scroll.types';\nexport * from './lib/cerious-scroll.observable';\nexport * from './lib/cerious-scroll-item-template.directive';\nexport * from './lib/cerious-scroll.directive';\nexport * from './lib/cerious-scroll.component';\nexport * from './lib/cerious-scroll.service';\n\n// Re-export upstream types/classes for convenience\nexport * from '@ceriousdevtech/cerious-scroll';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.CeriousScrollService","i1.CeriousScrollDirective"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ceriousdevtech-ngx-cerious-scroll.mjs","sources":["../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll.observable.ts","../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll-item-template.directive.ts","../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll.service.ts","../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll.directive.ts","../../../projects/ngx-cerious-scroll/src/lib/cerious-scroll.component.ts","../../../projects/ngx-cerious-scroll/src/public-api.ts","../../../projects/ngx-cerious-scroll/src/ceriousdevtech-ngx-cerious-scroll.ts"],"sourcesContent":["import { fromEvent, map, merge, Observable, share } from 'rxjs';\n\nimport type { ScrollResult } from '@ceriousdevtech/cerious-scroll';\n\nimport {\n CeriousNativeScrollbarViewportChangeEvent,\n CeriousViewportChangeDetail,\n CeriousViewportChangeEvent,\n} from './cerious-scroll.types';\n\n/**\n * Observable wrapper around the `cerious-viewport-change` CustomEvent emitted by `@ceriousdevtech/cerious-scroll`.\n *\n * Note: this event is emitted when wheel/touch/keyboard handlers are enabled (defaults are enabled).\n */\nexport function ceriousViewportChange$(container: HTMLElement): Observable<CeriousViewportChangeDetail> {\n const fromCerious = fromEvent<CeriousViewportChangeEvent>(container, 'cerious-viewport-change').pipe(\n map((evt) => evt.detail)\n );\n\n // Native scrollbar integration in the upstream package dispatches `viewport-change`.\n // Normalize it into the same shape as `cerious-viewport-change`.\n const fromScrollbar = fromEvent<CeriousNativeScrollbarViewportChangeEvent>(container, 'viewport-change').pipe(\n map((evt) => {\n const result: ScrollResult = { element: evt.detail.element, offset: evt.detail.scrollOffset };\n return {\n percentage: evt.detail.percentage,\n currentElement: evt.detail.element,\n scrollOffset: evt.detail.scrollOffset,\n result,\n } satisfies CeriousViewportChangeDetail;\n })\n );\n\n return merge(fromCerious, fromScrollbar).pipe(share());\n}\n","import { Directive, TemplateRef } from '@angular/core';\n\nexport interface CeriousScrollItemTemplateContext<TItem = unknown> {\n /** The item for this row (also available as `$implicit`). */\n $implicit: TItem;\n /** Row index. */\n index: number;\n /** Same as `$implicit` for named access. */\n item: TItem;\n}\n\n/**\n * Marks an `ng-template` as the row template for `CeriousScrollComponent`.\n *\n * Usage:\n * ```html\n * <cerious-scroll [items]=\"items\">\n * <ng-template ceriousScrollItem let-item let-index=\"index\">\n * {{ index }} - {{ item.name }}\n * </ng-template>\n * </cerious-scroll>\n * ```\n */\n@Directive({\n selector: 'ng-template[ceriousScrollItem]',\n standalone: true,\n})\nexport class CeriousScrollItemTemplateDirective<TItem = unknown> {\n constructor(public readonly templateRef: TemplateRef<CeriousScrollItemTemplateContext<TItem>>) {}\n}\n","import { Injectable, NgZone } from '@angular/core';\n\nimport { CeriousScroll, type CeriousScrollOptions } from '@ceriousdevtech/cerious-scroll';\nimport { Observable } from 'rxjs';\n\nimport { ceriousViewportChange$ } from './cerious-scroll.observable';\nimport type { CeriousViewportChangeDetail } from './cerious-scroll.types';\n\nconst CONTENT_ATTR = 'data-cerious-scroll-content';\n\nfunction ensureContentElement(container: HTMLElement): HTMLElement {\n const existing = container.querySelector<HTMLElement>(`[${CONTENT_ATTR}]`);\n if (existing) return existing;\n\n const el = document.createElement('div');\n el.setAttribute(CONTENT_ATTR, '');\n el.style.position = 'relative';\n el.style.width = '100%';\n el.style.height = '100%';\n el.style.overflow = 'hidden';\n container.appendChild(el);\n return el;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class CeriousScrollService {\n createHost(\n container: HTMLElement,\n totalElements: number,\n options: CeriousScrollOptions,\n ngZone: NgZone,\n onScrollHook?: () => void\n ): CeriousScrollHostRef {\n const contentElement = ensureContentElement(container);\n let scroller!: CeriousScroll;\n\n ngZone.runOutsideAngular(() => {\n const userOnScroll = options?.onScroll;\n const mergedOptions: CeriousScrollOptions = {\n ...options,\n onScroll: () => {\n userOnScroll?.();\n onScrollHook?.();\n },\n };\n\n scroller = new CeriousScroll(container, totalElements, mergedOptions);\n });\n\n const viewportChanges$ = ceriousViewportChange$(container);\n\n return {\n scroller,\n contentElement,\n viewportChanges$,\n destroy: () => {\n // Remove rendered rows content first; keep container stable.\n contentElement.textContent = '';\n scroller.detachScrollbar(container);\n scroller.dispose();\n },\n };\n }\n}\n\nexport interface CeriousScrollHostRef {\n readonly scroller: CeriousScroll;\n /** Dedicated element used for row rendering (prevents scrollbar DOM from being cleared). */\n readonly contentElement: HTMLElement;\n readonly viewportChanges$: Observable<CeriousViewportChangeDetail>;\n destroy(): void;\n}\n","import {\n AfterViewInit,\n ApplicationRef,\n Directive,\n ElementRef,\n EmbeddedViewRef,\n EventEmitter,\n Input,\n NgZone,\n OnChanges,\n OnDestroy,\n Output,\n SimpleChanges,\n TemplateRef,\n} from '@angular/core';\n\nimport {\n type CeriousScrollOptions,\n type ElementRenderer,\n type MeasuredViewportRange,\n} from '@ceriousdevtech/cerious-scroll';\nimport { Subscription } from 'rxjs';\n\nimport type { CeriousViewportChangeDetail } from './cerious-scroll.types';\nimport type { CeriousScrollItemTemplateContext } from './cerious-scroll-item-template.directive';\nimport { type CeriousScrollHostRef, CeriousScrollService } from './cerious-scroll.service';\n\nfunction coerceTotalElements(explicitTotal: number | null | undefined, itemsLen: number | null | undefined): number {\n const candidate = typeof explicitTotal === 'number' ? explicitTotal : typeof itemsLen === 'number' ? itemsLen : undefined;\n if (candidate === undefined || Number.isNaN(candidate)) {\n throw new Error('CeriousScrollDirective: provide `ceriousScrollTotalElements` or `ceriousScrollItems`.');\n }\n // CeriousScroll currently requires >= 1\n return Math.max(1, candidate);\n}\n\n@Directive({\n selector: '[ceriousScroll]',\n standalone: true,\n})\nexport class CeriousScrollDirective<TItem = unknown> implements AfterViewInit, OnChanges, OnDestroy {\n /** Total number of items. If omitted, derived from `ceriousScrollItems.length`. */\n @Input() ceriousScrollTotalElements: number | null = null;\n\n /** Optional items array (enables `let-item`). */\n @Input() ceriousScrollItems: readonly TItem[] | null = null;\n\n /** Optional getter for large datasets (alternative to passing full `items`). */\n @Input() ceriousScrollGetItem: ((index: number) => TItem) | null = null;\n\n /** Template used to render each row. */\n @Input() ceriousScrollItemTemplate: TemplateRef<CeriousScrollItemTemplateContext<TItem>> | null = null;\n\n /** Options passed to `new CeriousScroll(...)`. */\n @Input() ceriousScrollOptions: CeriousScrollOptions = {};\n\n /** Automatically call render after each scroll event. Default: true */\n @Input() ceriousScrollAutoRender = true;\n\n /** Emits `cerious-viewport-change` detail. */\n @Output() ceriousScrollViewportChange = new EventEmitter<CeriousViewportChangeDetail>();\n\n /** Emits the last measured viewport after each render pass. */\n @Output() ceriousScrollMeasuredViewport = new EventEmitter<MeasuredViewportRange>();\n\n /** Emits once the underlying `CeriousScroll` instance is ready. */\n @Output() ceriousScrollReady = new EventEmitter<CeriousScrollHostRef['scroller']>();\n\n private hostRef: CeriousScrollHostRef | null = null;\n private viewportSub: Subscription | null = null;\n private scheduledRenderFrame: number | null = null;\n\n private readonly viewByContainer = new Map<HTMLElement, EmbeddedViewRef<CeriousScrollItemTemplateContext<TItem>>>();\n // Pool of views detached because their container left the viewport. Reusing\n // them on subsequent renders avoids destroying + recreating the entire row\n // component tree on fast scrolls (where the engine's element pool wipes\n // textContent on reused containers, so view rootNodes get orphaned).\n private readonly freeViews: EmbeddedViewRef<CeriousScrollItemTemplateContext<TItem>>[] = [];\n\n constructor(\n private readonly host: ElementRef<HTMLElement>,\n private readonly appRef: ApplicationRef,\n private readonly ngZone: NgZone,\n private readonly cerious: CeriousScrollService\n ) {}\n\n ngAfterViewInit(): void {\n this.ensureInitialized();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (!this.hostRef) return;\n\n if (changes['ceriousScrollItems'] || changes['ceriousScrollTotalElements']) {\n const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);\n const countChanged = this.hostRef.scroller.totalElements !== total;\n\n if (countChanged) {\n // The dataset size changed: the ViewportRenderer stores its own copy of\n // totalElements (set by value at construction) so patching the engine's\n // public property alone leaves the renderer's internal bound stale. The\n // renderer would then use the old count for its viewport-fill loop and\n // bottom-boundary scan, producing phantom renders at out-of-bounds\n // indices (undefined items → 0-height rows → the fill loop never\n // satisfies its height condition → hundreds of renderer callbacks).\n // Recreating the engine gives both the engine and the renderer a fresh,\n // consistent count. ensureInitialized() schedules the first render via\n // queueMicrotask, which runs after the current CD cycle completes.\n this.recreate();\n } else if (this.ceriousScrollAutoRender) {\n // Same count, new data reference (e.g. an immutable edit or a sort that\n // happens to keep the same length). The engine reuses the DOM element it\n // already rendered for each overlapping index without re-invoking the\n // renderer, so update the content of every currently-visible row IN\n // PLACE before calling render(). This preserves each row's embedded\n // view (so a focused textbox keeps focus/caret) and does NOT discard\n // cached heights. If a row's height actually changes the engine's\n // ResizeObserver keeps the cache correct on its own; for a wholesale\n // height change across all rows, call recalculate() instead.\n this.refreshRenderedContent();\n this.render();\n }\n }\n\n if (changes['ceriousScrollOptions'] && !changes['ceriousScrollOptions'].firstChange) {\n // Options are consumed primarily at construction time.\n this.recreate();\n }\n }\n\n ngOnDestroy(): void {\n if (this.scheduledRenderFrame != null) {\n cancelAnimationFrame(this.scheduledRenderFrame);\n this.scheduledRenderFrame = null;\n }\n\n this.viewportSub?.unsubscribe();\n this.viewportSub = null;\n\n this.destroyAllViews();\n\n this.hostRef?.destroy();\n this.hostRef = null;\n }\n\n /** Imperatively trigger a render pass (uses `ceriousScrollItemTemplate`). */\n render(): MeasuredViewportRange | null {\n if (!this.hostRef) return null;\n const template = this.ceriousScrollItemTemplate;\n if (!template) return null;\n\n const hostContainer = this.host.nativeElement;\n const height = hostContainer.clientHeight || hostContainer.offsetHeight;\n const contentContainer = this.hostRef.contentElement;\n\n // Track whether the engine asked us to bind any row this pass. Pure scroll\n // frames where the visible row set doesn't change still drive render() via\n // the rAF coalescer — there's no point in walking the prune map or\n // emitting the viewport range when nothing was touched.\n let rendererInvocations = 0;\n const renderer: ElementRenderer = (index, elementContainer) => {\n rendererInvocations++;\n // Render each row's embedded view with LOCAL change detection\n // (`view.detectChanges()` inside `renderTemplateIntoContainer`) so the\n // engine can measure its height during this pass. Do NOT wrap each row in\n // its own `ngZone.run` — that fires a full `ApplicationRef` tick *per row*\n // (O(newRows × visibleRows) work, janky drags). The single coalesced tick\n // for the whole pass is handled by the caller (`scheduleRender`).\n this.renderTemplateIntoContainer(template, index, elementContainer);\n };\n\n const range = this.hostRef.scroller.renderViewport(height, contentContainer, renderer);\n\n if (rendererInvocations === 0) {\n // Viewport didn't change — skip the prune walk and the (potentially\n // zone-entering) emit.\n return range;\n }\n\n // Destroy views whose container the engine no longer renders. Without this,\n // every container the engine recycles into its element pool leaves its\n // embedded view attached to ApplicationRef forever — so the attached-view\n // list (and every O(n) `detachView`) grows without bound and scrolling gets\n // progressively slower. Mirrors the React/Vue wrappers, which drop rows that\n // fall out of `getRenderedIndices()`.\n this.pruneDetachedViews();\n\n // Only re-enter the zone (a global tick) if someone is actually listening.\n if (this.ceriousScrollMeasuredViewport.observed) {\n this.ngZone.run(() => this.ceriousScrollMeasuredViewport.emit(range));\n }\n return range;\n }\n\n /** Tear down embedded views whose container is no longer part of the viewport. */\n private pruneDetachedViews(): void {\n if (!this.hostRef || this.viewByContainer.size === 0) return;\n const scroller = this.hostRef.scroller;\n const active = new Set<HTMLElement>();\n for (const index of scroller.getRenderedIndices()) {\n const el = scroller.getRenderedElement(index);\n if (el) active.add(el);\n }\n for (const [container, view] of this.viewByContainer) {\n if (!active.has(container)) {\n // Detach DOM but keep the view alive in the pool for future reuse.\n // Destroying + recreating views per scroll step dominates frame time.\n for (const node of view.rootNodes) {\n if (node.parentNode) node.parentNode.removeChild(node);\n }\n this.viewByContainer.delete(container);\n this.freeViews.push(view);\n }\n }\n }\n\n /** Auto-render coalesced to at most once per animation frame. */\n private scheduleRender(): void {\n if (this.scheduledRenderFrame != null) return;\n this.scheduledRenderFrame = requestAnimationFrame(() => {\n this.scheduledRenderFrame = null;\n // Run render() OUTSIDE Angular's zone. A full ApplicationRef.tick() on\n // every scroll frame is the primary FPS bottleneck: even when no rows\n // change (pure translation), ngZone.run() causes Angular to walk the\n // entire component tree. Instead we call view.detectChanges() locally\n // inside renderTemplateIntoContainer for each affected row. Zone entry is\n // only needed when creating a brand-new embedded view (to zone-patch its\n // event listeners) — recycled and pooled views were already created inside\n // zone and their listeners remain zone-aware.\n this.render();\n });\n }\n\n /**\n * Discard all cached row heights and re-measure the viewport.\n *\n * Call this only when the heights of rows you've *already rendered* may have\n * changed without their indices changing — e.g. a global font/density change,\n * or swapping every row to a different layout. This forces a synchronous\n * re-measure (one `offsetHeight` read per visible row), so do NOT call it on\n * routine edits: a single cell edit keeps its row's size, and the engine's\n * ResizeObserver picks up any incidental resize on its own.\n */\n recalculate(): MeasuredViewportRange | null {\n if (!this.hostRef) return null;\n // Discard the cached heights, then re-render. The engine re-measures and\n // re-caches the rendered rows during the pass and refreshes the scroll\n // percentage, so an in-place height change (e.g. expand/collapse) is\n // reflected in the total content height and scrollbar immediately.\n this.hostRef.scroller.clearAllCaches();\n return this.render();\n }\n\n /** Jump directly to an element index, then render. */\n jumpToElement(index: number): MeasuredViewportRange | null {\n if (!this.hostRef) return null;\n this.hostRef.scroller.jumpToElement(index);\n return this.render();\n }\n\n /** Scroll to a percentage (0..100), then render. */\n scrollToPercentage(percentage: number): MeasuredViewportRange | null {\n if (!this.hostRef) return null;\n this.hostRef.scroller.handleScrollPercentage(percentage);\n return this.render();\n }\n\n /** Reset to the top, then render. */\n reset(): MeasuredViewportRange | null {\n if (!this.hostRef) return null;\n this.hostRef.scroller.reset();\n return this.render();\n }\n\n private recreate(): void {\n this.viewportSub?.unsubscribe();\n this.viewportSub = null;\n\n this.destroyAllViews();\n\n this.hostRef?.destroy();\n this.hostRef = null;\n\n this.ensureInitialized();\n }\n\n private ensureInitialized(): void {\n if (this.hostRef) return;\n\n const container = this.host.nativeElement;\n const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);\n\n this.hostRef = this.cerious.createHost(container, total, this.ceriousScrollOptions, this.ngZone, () => {\n // Coalesce scroll-driven renders to one per frame (the native scrollbar\n // can fire many scroll events between paints).\n if (this.ceriousScrollAutoRender) this.scheduleRender();\n });\n\n this.viewportSub = this.hostRef.viewportChanges$.subscribe((detail: CeriousViewportChangeDetail) => {\n // Skip the global tick when nobody is bound to the output.\n if (this.ceriousScrollViewportChange.observed) {\n this.ngZone.run(() => this.ceriousScrollViewportChange.emit(detail));\n }\n });\n\n this.ceriousScrollReady.emit(this.hostRef.scroller);\n\n if (this.ceriousScrollAutoRender) {\n queueMicrotask(() => this.render());\n }\n }\n\n private getItemForIndex(index: number): TItem {\n const getter = this.ceriousScrollGetItem;\n if (getter) return getter(index);\n\n const items = this.ceriousScrollItems;\n if (!items) return undefined as TItem;\n\n return items[index];\n }\n\n private renderTemplateIntoContainer(\n template: TemplateRef<CeriousScrollItemTemplateContext<TItem>>,\n index: number,\n elementContainer: HTMLElement\n ): void {\n const previous = this.viewByContainer.get(elementContainer);\n if (previous) {\n // Recycle: update the bound context and run local CD instead of\n // destroying the embedded view and rebuilding the entire row tree.\n const item = this.getItemForIndex(index);\n previous.context.$implicit = item;\n previous.context.item = item;\n previous.context.index = index;\n // The core engine wipes elementContainer.textContent when reusing it from\n // its pool, orphaning the view's root nodes. Re-append them defensively.\n if (previous.rootNodes.length && previous.rootNodes[0].parentNode !== elementContainer) {\n for (const node of previous.rootNodes) {\n elementContainer.appendChild(node);\n }\n }\n previous.detectChanges();\n return;\n }\n\n // Try to reuse a pooled view from a container that scrolled out of viewport.\n const pooled = this.freeViews.pop();\n if (pooled) {\n const item = this.getItemForIndex(index);\n pooled.context.$implicit = item;\n pooled.context.item = item;\n pooled.context.index = index;\n elementContainer.textContent = '';\n for (const node of pooled.rootNodes) {\n elementContainer.appendChild(node);\n }\n pooled.detectChanges();\n this.viewByContainer.set(elementContainer, pooled);\n return;\n }\n\n // No prior view for this container: create one.\n // Enter the Angular zone so the new view's template event listeners\n // ((click), (input), etc.) are zone-patched. This path runs at most\n // once per visible row (after that, the view is recycled from the pool).\n elementContainer.textContent = '';\n\n const item = this.getItemForIndex(index);\n const view = this.ngZone.run(() => {\n const v = template.createEmbeddedView({ $implicit: item, item, index });\n this.appRef.attachView(v);\n v.detectChanges();\n return v;\n });\n\n for (const node of view.rootNodes) {\n elementContainer.appendChild(node);\n }\n\n this.viewByContainer.set(elementContainer, view);\n }\n\n /**\n * Update the bound item/index on every currently-rendered row's embedded view\n * and run change detection, without recreating the views. Used when the data\n * reference changes but the visible indices (and their heights) do not, so row\n * state (focus, selection, open dropdowns) survives the update.\n */\n /**\n * Re-bind each currently rendered row's context (from the current items/getter)\n * and run change detection on its embedded view. Use this after mutating row\n * state in place (e.g. selection flags) or column-level state read by the row\n * template, when row identity and visible indices have not changed. Cheap\n * relative to `render()` — does not invoke the engine's measurement pass.\n */\n refreshRenderedContent(): void {\n if (!this.hostRef) return;\n const scroller = this.hostRef.scroller;\n\n for (const index of scroller.getRenderedIndices()) {\n const container = scroller.getRenderedElement(index);\n if (!container) continue;\n\n const view = this.viewByContainer.get(container);\n if (!view) continue;\n\n const item = this.getItemForIndex(index);\n view.context.$implicit = item;\n view.context.item = item;\n view.context.index = index;\n view.detectChanges();\n }\n }\n\n private destroyAllViews(): void {\n for (const view of this.viewByContainer.values()) {\n this.appRef.detachView(view);\n view.destroy();\n }\n this.viewByContainer.clear();\n for (const view of this.freeViews) {\n this.appRef.detachView(view);\n view.destroy();\n }\n this.freeViews.length = 0;\n }\n}\n","import {\n AfterContentInit,\n ChangeDetectionStrategy,\n Component,\n ContentChild,\n TemplateRef,\n} from '@angular/core';\n\nimport { CeriousScrollDirective } from './cerious-scroll.directive';\nimport {\n CeriousScrollItemTemplateDirective,\n type CeriousScrollItemTemplateContext,\n} from './cerious-scroll-item-template.directive';\n\n@Component({\n selector: 'cerious-scroll',\n standalone: true,\n imports: [],\n hostDirectives: [\n {\n directive: CeriousScrollDirective,\n inputs: [\n 'ceriousScrollTotalElements: totalElements',\n 'ceriousScrollItems: items',\n 'ceriousScrollGetItem: getItem',\n 'ceriousScrollItemTemplate: itemTemplate',\n 'ceriousScrollOptions: options',\n 'ceriousScrollAutoRender: autoRender',\n ],\n outputs: [\n 'ceriousScrollViewportChange: viewportChange',\n 'ceriousScrollMeasuredViewport: measuredViewport',\n 'ceriousScrollReady: scrollerReady',\n ],\n },\n ],\n template: `<ng-content />`,\n styles: `\n :host {\n display: block;\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class CeriousScrollComponent<TItem = unknown> implements AfterContentInit {\n /** Optional convenience template marker: <ng-template ceriousScrollItem let-item let-index=\"index\">...</ng-template> */\n @ContentChild(CeriousScrollItemTemplateDirective)\n private readonly projectedItemTemplate?: CeriousScrollItemTemplateDirective<TItem>;\n\n constructor(private readonly ceriousScroll: CeriousScrollDirective<TItem>) {}\n\n ngAfterContentInit(): void {\n if (this.ceriousScroll.ceriousScrollItemTemplate) return;\n if (!this.projectedItemTemplate) return;\n\n this.ceriousScroll.ceriousScrollItemTemplate =\n this.projectedItemTemplate.templateRef as TemplateRef<CeriousScrollItemTemplateContext<TItem>>;\n\n if (this.ceriousScroll.ceriousScrollAutoRender) {\n queueMicrotask(() => this.ceriousScroll.render());\n }\n }\n}\n","/*\n * Public API Surface of ngx-cerious-scroll\n */\n\nexport * from './lib/cerious-scroll.types';\nexport * from './lib/cerious-scroll.observable';\nexport * from './lib/cerious-scroll-item-template.directive';\nexport * from './lib/cerious-scroll.directive';\nexport * from './lib/cerious-scroll.component';\nexport * from './lib/cerious-scroll.service';\n\n// Re-export upstream types/classes for convenience\nexport * from '@ceriousdevtech/cerious-scroll';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.CeriousScrollService","i1.CeriousScrollDirective"],"mappings":"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"}
|
|
@@ -29,17 +29,54 @@ export declare class CeriousScrollDirective<TItem = unknown> implements AfterVie
|
|
|
29
29
|
ceriousScrollReady: EventEmitter<import("@ceriousdevtech/cerious-scroll").CeriousScroll>;
|
|
30
30
|
private hostRef;
|
|
31
31
|
private viewportSub;
|
|
32
|
+
private scheduledRenderFrame;
|
|
32
33
|
private readonly viewByContainer;
|
|
34
|
+
private readonly freeViews;
|
|
33
35
|
constructor(host: ElementRef<HTMLElement>, appRef: ApplicationRef, ngZone: NgZone, cerious: CeriousScrollService);
|
|
34
36
|
ngAfterViewInit(): void;
|
|
35
37
|
ngOnChanges(changes: SimpleChanges): void;
|
|
36
38
|
ngOnDestroy(): void;
|
|
37
39
|
/** Imperatively trigger a render pass (uses `ceriousScrollItemTemplate`). */
|
|
38
40
|
render(): MeasuredViewportRange | null;
|
|
41
|
+
/** Tear down embedded views whose container is no longer part of the viewport. */
|
|
42
|
+
private pruneDetachedViews;
|
|
43
|
+
/** Auto-render coalesced to at most once per animation frame. */
|
|
44
|
+
private scheduleRender;
|
|
45
|
+
/**
|
|
46
|
+
* Discard all cached row heights and re-measure the viewport.
|
|
47
|
+
*
|
|
48
|
+
* Call this only when the heights of rows you've *already rendered* may have
|
|
49
|
+
* changed without their indices changing — e.g. a global font/density change,
|
|
50
|
+
* or swapping every row to a different layout. This forces a synchronous
|
|
51
|
+
* re-measure (one `offsetHeight` read per visible row), so do NOT call it on
|
|
52
|
+
* routine edits: a single cell edit keeps its row's size, and the engine's
|
|
53
|
+
* ResizeObserver picks up any incidental resize on its own.
|
|
54
|
+
*/
|
|
55
|
+
recalculate(): MeasuredViewportRange | null;
|
|
56
|
+
/** Jump directly to an element index, then render. */
|
|
57
|
+
jumpToElement(index: number): MeasuredViewportRange | null;
|
|
58
|
+
/** Scroll to a percentage (0..100), then render. */
|
|
59
|
+
scrollToPercentage(percentage: number): MeasuredViewportRange | null;
|
|
60
|
+
/** Reset to the top, then render. */
|
|
61
|
+
reset(): MeasuredViewportRange | null;
|
|
39
62
|
private recreate;
|
|
40
63
|
private ensureInitialized;
|
|
41
64
|
private getItemForIndex;
|
|
42
65
|
private renderTemplateIntoContainer;
|
|
66
|
+
/**
|
|
67
|
+
* Update the bound item/index on every currently-rendered row's embedded view
|
|
68
|
+
* and run change detection, without recreating the views. Used when the data
|
|
69
|
+
* reference changes but the visible indices (and their heights) do not, so row
|
|
70
|
+
* state (focus, selection, open dropdowns) survives the update.
|
|
71
|
+
*/
|
|
72
|
+
/**
|
|
73
|
+
* Re-bind each currently rendered row's context (from the current items/getter)
|
|
74
|
+
* and run change detection on its embedded view. Use this after mutating row
|
|
75
|
+
* state in place (e.g. selection flags) or column-level state read by the row
|
|
76
|
+
* template, when row identity and visible indices have not changed. Cheap
|
|
77
|
+
* relative to `render()` — does not invoke the engine's measurement pass.
|
|
78
|
+
*/
|
|
79
|
+
refreshRenderedContent(): void;
|
|
43
80
|
private destroyAllViews;
|
|
44
81
|
static ɵfac: i0.ɵɵFactoryDeclaration<CeriousScrollDirective<any>, never>;
|
|
45
82
|
static ɵdir: i0.ɵɵDirectiveDeclaration<CeriousScrollDirective<any>, "[ceriousScroll]", never, { "ceriousScrollTotalElements": { "alias": "ceriousScrollTotalElements"; "required": false; }; "ceriousScrollItems": { "alias": "ceriousScrollItems"; "required": false; }; "ceriousScrollGetItem": { "alias": "ceriousScrollGetItem"; "required": false; }; "ceriousScrollItemTemplate": { "alias": "ceriousScrollItemTemplate"; "required": false; }; "ceriousScrollOptions": { "alias": "ceriousScrollOptions"; "required": false; }; "ceriousScrollAutoRender": { "alias": "ceriousScrollAutoRender"; "required": false; }; }, { "ceriousScrollViewportChange": "ceriousScrollViewportChange"; "ceriousScrollMeasuredViewport": "ceriousScrollMeasuredViewport"; "ceriousScrollReady": "ceriousScrollReady"; }, never, never, true, never>;
|
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ceriousdevtech/ngx-cerious-scroll",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"license": "
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/ceriousdevtech/ngx-cerious-scroll"
|
|
8
|
+
},
|
|
5
9
|
"peerDependencies": {
|
|
6
10
|
"@angular/common": ">=16.0.0",
|
|
7
11
|
"@angular/core": ">=16.0.0",
|
|
8
|
-
"@ceriousdevtech/cerious-scroll": "^1.0.
|
|
12
|
+
"@ceriousdevtech/cerious-scroll": "^1.0.3"
|
|
9
13
|
},
|
|
10
14
|
"dependencies": {
|
|
11
15
|
"tslib": "^2.3.0"
|
package/LICENSE-COMMERCIAL
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
ngx-cerious-scroll Commercial License
|
|
2
|
-
|
|
3
|
-
Copyright © 2024–2026 Cerious DevTech LLC.
|
|
4
|
-
All rights reserved.
|
|
5
|
-
|
|
6
|
-
This Commercial License governs use of ngx-cerious-scroll only when you have
|
|
7
|
-
entered into a separately executed commercial agreement with Cerious DevTech LLC.
|
|
8
|
-
|
|
9
|
-
If you do not have such an agreement, you may use this software under the
|
|
10
|
-
MIT license (see LICENSE).
|
|
11
|
-
|
|
12
|
-
A commercial agreement is commonly used when ngx-cerious-scroll is:
|
|
13
|
-
|
|
14
|
-
- Redistributed as part of a commercial product
|
|
15
|
-
- Bundled with a proprietary SDK, framework, or component library
|
|
16
|
-
- Integrated into a low-code / no-code platform
|
|
17
|
-
- Used in OEM, white-label, or downstream resale offerings
|
|
18
|
-
- Included in internal frameworks or platforms sold or licensed to third parties
|
|
19
|
-
|
|
20
|
-
This license grants the Licensee a non-exclusive, non-transferable,
|
|
21
|
-
non-sublicensable right to use, modify, and distribute ngx-cerious-scroll
|
|
22
|
-
solely under the terms of that commercial agreement.
|
|
23
|
-
|
|
24
|
-
### Restrictions
|
|
25
|
-
|
|
26
|
-
Except as explicitly permitted in a written commercial agreement, the Licensee
|
|
27
|
-
may not:
|
|
28
|
-
|
|
29
|
-
- Redistribute ngx-cerious-scroll as a standalone product
|
|
30
|
-
- Offer ngx-cerious-scroll as part of a competing scrolling, virtualization,
|
|
31
|
-
or UI infrastructure library
|
|
32
|
-
- Remove or obscure copyright, trademark, or patent notices
|
|
33
|
-
- Grant sublicenses or derivative commercial licenses
|
|
34
|
-
|
|
35
|
-
### Ownership
|
|
36
|
-
|
|
37
|
-
ngx-cerious-scroll and all associated intellectual property rights, including
|
|
38
|
-
but not limited to copyrights, patents, and trademarks, remain the exclusive
|
|
39
|
-
property of Cerious DevTech LLC.
|
|
40
|
-
|
|
41
|
-
No rights are granted except those expressly stated in this license.
|
|
42
|
-
|
|
43
|
-
### Patent Rights
|
|
44
|
-
|
|
45
|
-
ngx-cerious-scroll includes technology covered by one or more pending patent
|
|
46
|
-
applications owned by Cerious DevTech LLC.
|
|
47
|
-
|
|
48
|
-
This license grants only those patent rights explicitly provided in a
|
|
49
|
-
commercial agreement. No implied patent licenses are granted.
|
|
50
|
-
|
|
51
|
-
### Termination
|
|
52
|
-
|
|
53
|
-
Any violation of this license immediately terminates the rights granted herein
|
|
54
|
-
without notice.
|
|
55
|
-
|
|
56
|
-
Upon termination, the Licensee must cease all use and distribution of
|
|
57
|
-
ngx-cerious-scroll.
|
|
58
|
-
|
|
59
|
-
### Warranty Disclaimer
|
|
60
|
-
|
|
61
|
-
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
62
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
63
|
-
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
64
|
-
|
|
65
|
-
### Limitation of Liability
|
|
66
|
-
|
|
67
|
-
IN NO EVENT SHALL CERIOUS DEVTECH LLC BE LIABLE FOR ANY CLAIM, DAMAGES, OR
|
|
68
|
-
OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE.
|
|
69
|
-
|
|
70
|
-
For commercial licensing inquiries, contact:
|
|
71
|
-
info@ceriousdevtech.com
|