@ceriousdevtech/ngx-cerious-scroll 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,6 +9,7 @@ Angular wrapper for [@ceriousdevtech/cerious-scroll](https://www.npmjs.com/packa
9
9
 
10
10
  - 🚀 **High Performance** - Handles millions of items with smooth scrolling
11
11
  - 📏 **Variable Heights** - Full support for dynamic and variable row heights
12
+ - 🧮 **Native Table Layout** - Opt-in `layout: 'table'` renders real `<tr>`/`<td>` rows with a frozen header and auto-sized columns (see [Table Layout](#table-layout))
12
13
  - 🎯 **Angular Integration** - Seamless integration with Angular templates and change detection
13
14
  - 🎨 **Flexible Templates** - Use Angular templates with full data binding
14
15
  - 📦 **Standalone Components** - Built with Angular standalone components
@@ -199,6 +200,7 @@ export class LargeListComponent {
199
200
  - `items: any[]` - Array of items to render
200
201
  - `totalElements: number` - Optional explicit total count (defaults to items.length)
201
202
  - `itemTemplate: TemplateRef` - Template for rendering each item
203
+ - `headerTemplate: TemplateRef` - Table mode only: `<tr>` of `<th>`s rendered into the engine's `<thead>` (see [Table Layout](#table-layout))
202
204
  - `options: CeriousScrollOptions` - Configuration options
203
205
  - `autoRender: boolean` - Auto-render on scroll (default: true)
204
206
 
@@ -214,6 +216,7 @@ export class LargeListComponent {
214
216
  - `ceriousScrollTotalElements: number` - Total element count
215
217
  - `ceriousScrollGetItem: (index: number) => any` - Function to retrieve item by index
216
218
  - `ceriousScrollItemTemplate: TemplateRef` - Template for rendering
219
+ - `ceriousScrollHeaderTemplate: TemplateRef` - Table mode only: header `<tr>` rendered into the engine's `<thead>` (see [Table Layout](#table-layout))
217
220
  - `ceriousScrollOptions: CeriousScrollOptions` - Configuration options
218
221
  - `ceriousScrollAutoRender: boolean` - Auto-render on scroll (default: true)
219
222
 
@@ -264,6 +267,42 @@ Usage in templates:
264
267
  </ng-template>
265
268
  ```
266
269
 
270
+ ## Table Layout
271
+
272
+ Pass `[ceriousScrollOptions]="{ layout: 'table' }"` to render **real `<table>` / `<tr>` / `<td>` rows** with a frozen header and native column alignment — while keeping O(1) virtualization. The row template returns the row's `<td>` cells; `[ceriousScrollHeaderTemplate]` provides the `<thead>` row (it updates via change detection):
273
+
274
+ ```html
275
+ <div
276
+ class="grid"
277
+ ceriousScroll
278
+ [ceriousScrollTotalElements]="100000"
279
+ [ceriousScrollGetItem]="getItem"
280
+ [ceriousScrollItemTemplate]="rowTpl"
281
+ [ceriousScrollHeaderTemplate]="headerTpl"
282
+ [ceriousScrollOptions]="{ layout: 'table', table: { tableClassName: 'grid-table', autoSizeColumns: true } }"
283
+ ></div>
284
+
285
+ <ng-template #headerTpl>
286
+ <tr>
287
+ @for (c of columns; track c.key) { <th>{{ c.label }}</th> }
288
+ </tr>
289
+ </ng-template>
290
+
291
+ <!-- Row template root nodes must be <td>s (no structural directive at the root). -->
292
+ <ng-template #rowTpl let-index>
293
+ <td>{{ row(index).id }}</td>
294
+ <td>{{ row(index).name }}</td>
295
+ <td>{{ row(index).email }}</td>
296
+ </ng-template>
297
+ ```
298
+
299
+ `<cerious-scroll>` exposes the same inputs (`[headerTemplate]`, `<ng-template ceriousScrollItem>`).
300
+
301
+ - The header template renders into the engine's `<thead>` (same `<table>` as the rows → native column alignment; the header is frozen because only the `<tbody>` transforms).
302
+ - The row template's **root nodes must be `<td>`s** — a structural directive at the root would hide the cells from the directive's recycle re-append.
303
+ - **`table.autoSizeColumns: true`** measures column widths once from the first window and pins them: auto-sized but stable (no scroll jitter, no manual widths). Or pass `table.columnWidths`. Variable row heights are measured per row, same as the default mode.
304
+ - **CSS:** use `border-collapse: separate` (collapsed borders are painted by the untransformed `<table>` and would not move with the rows), and give the `<thead>` an opaque background.
305
+
267
306
  ## Options
268
307
 
269
308
  Configure scrolling behavior with `CeriousScrollOptions`:
@@ -19,7 +19,7 @@ export class CeriousScrollComponent {
19
19
  }
20
20
  }
21
21
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CeriousScrollComponent, deps: [{ token: i1.CeriousScrollDirective }], target: i0.ɵɵFactoryTarget.Component }); }
22
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CeriousScrollComponent, isStandalone: true, selector: "cerious-scroll", queries: [{ propertyName: "projectedItemTemplate", first: true, predicate: CeriousScrollItemTemplateDirective, descendants: true }], hostDirectives: [{ directive: i1.CeriousScrollDirective, inputs: ["ceriousScrollTotalElements", "totalElements", "ceriousScrollItems", "items", "ceriousScrollGetItem", "getItem", "ceriousScrollItemTemplate", "itemTemplate", "ceriousScrollOptions", "options", "ceriousScrollAutoRender", "autoRender"], outputs: ["ceriousScrollViewportChange", "viewportChange", "ceriousScrollMeasuredViewport", "measuredViewport", "ceriousScrollReady", "scrollerReady"] }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
22
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CeriousScrollComponent, isStandalone: true, selector: "cerious-scroll", queries: [{ propertyName: "projectedItemTemplate", first: true, predicate: CeriousScrollItemTemplateDirective, descendants: true }], hostDirectives: [{ directive: i1.CeriousScrollDirective, inputs: ["ceriousScrollTotalElements", "totalElements", "ceriousScrollItems", "items", "ceriousScrollGetItem", "getItem", "ceriousScrollItemTemplate", "itemTemplate", "ceriousScrollHeaderTemplate", "headerTemplate", "ceriousScrollOptions", "options", "ceriousScrollAutoRender", "autoRender"], outputs: ["ceriousScrollViewportChange", "viewportChange", "ceriousScrollMeasuredViewport", "measuredViewport", "ceriousScrollReady", "scrollerReady"] }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
23
23
  }
24
24
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CeriousScrollComponent, decorators: [{
25
25
  type: Component,
@@ -31,6 +31,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
31
31
  'ceriousScrollItems: items',
32
32
  'ceriousScrollGetItem: getItem',
33
33
  'ceriousScrollItemTemplate: itemTemplate',
34
+ 'ceriousScrollHeaderTemplate: headerTemplate',
34
35
  'ceriousScrollOptions: options',
35
36
  'ceriousScrollAutoRender: autoRender',
36
37
  ],
@@ -45,4 +46,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
45
46
  type: ContentChild,
46
47
  args: [CeriousScrollItemTemplateDirective]
47
48
  }] } });
48
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VyaW91cy1zY3JvbGwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWNlcmlvdXMtc2Nyb2xsL3NyYy9saWIvY2VyaW91cy1zY3JvbGwuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksR0FFYixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNwRSxPQUFPLEVBQ0wsa0NBQWtDLEdBRW5DLE1BQU0sMENBQTBDLENBQUM7OztBQWdDbEQsTUFBTSxPQUFPLHNCQUFzQjtJQUtqQyxZQUE2QixhQUE0QztRQUE1QyxrQkFBYSxHQUFiLGFBQWEsQ0FBK0I7SUFBRyxDQUFDO0lBRTdFLGtCQUFrQjtRQUNoQixJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMseUJBQXlCO1lBQUUsT0FBTztRQUN6RCxJQUFJLENBQUMsSUFBSSxDQUFDLHFCQUFxQjtZQUFFLE9BQU87UUFFeEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyx5QkFBeUI7WUFDMUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFdBQW1FLENBQUM7UUFFakcsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLHVCQUF1QixFQUFFLENBQUM7WUFDL0MsY0FBYyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNwRCxDQUFDO0lBQ0gsQ0FBQzsrR0FqQlUsc0JBQXNCO21HQUF0QixzQkFBc0IsNkhBRW5CLGtDQUFrQyx3ZkFWdEMsZ0JBQWdCOzs0RkFRZixzQkFBc0I7a0JBOUJsQyxTQUFTOytCQUNFLGdCQUFnQixjQUNkLElBQUksV0FDUCxFQUFFLGtCQUNLO3dCQUNkOzRCQUNFLFNBQVMsRUFBRSxzQkFBc0I7NEJBQ2pDLE1BQU0sRUFBRTtnQ0FDTiwyQ0FBMkM7Z0NBQzNDLDJCQUEyQjtnQ0FDM0IsK0JBQStCO2dDQUMvQix5Q0FBeUM7Z0NBQ3pDLCtCQUErQjtnQ0FDL0IscUNBQXFDOzZCQUN0Qzs0QkFDRCxPQUFPLEVBQUU7Z0NBQ1AsNkNBQTZDO2dDQUM3QyxpREFBaUQ7Z0NBQ2pELG1DQUFtQzs2QkFDcEM7eUJBQ0Y7cUJBQ0YsWUFDUyxnQkFBZ0IsbUJBTVQsdUJBQXVCLENBQUMsTUFBTTsyRkFLOUIscUJBQXFCO3NCQURyQyxZQUFZO3VCQUFDLGtDQUFrQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIENvbnRlbnRDaGlsZCxcbiAgVGVtcGxhdGVSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBDZXJpb3VzU2Nyb2xsRGlyZWN0aXZlIH0gZnJvbSAnLi9jZXJpb3VzLXNjcm9sbC5kaXJlY3RpdmUnO1xuaW1wb3J0IHtcbiAgQ2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZURpcmVjdGl2ZSxcbiAgdHlwZSBDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlQ29udGV4dCxcbn0gZnJvbSAnLi9jZXJpb3VzLXNjcm9sbC1pdGVtLXRlbXBsYXRlLmRpcmVjdGl2ZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2NlcmlvdXMtc2Nyb2xsJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW10sXG4gIGhvc3REaXJlY3RpdmVzOiBbXG4gICAge1xuICAgICAgZGlyZWN0aXZlOiBDZXJpb3VzU2Nyb2xsRGlyZWN0aXZlLFxuICAgICAgaW5wdXRzOiBbXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsVG90YWxFbGVtZW50czogdG90YWxFbGVtZW50cycsXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsSXRlbXM6IGl0ZW1zJyxcbiAgICAgICAgJ2NlcmlvdXNTY3JvbGxHZXRJdGVtOiBnZXRJdGVtJyxcbiAgICAgICAgJ2NlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGU6IGl0ZW1UZW1wbGF0ZScsXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsT3B0aW9uczogb3B0aW9ucycsXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcjogYXV0b1JlbmRlcicsXG4gICAgICBdLFxuICAgICAgb3V0cHV0czogW1xuICAgICAgICAnY2VyaW91c1Njcm9sbFZpZXdwb3J0Q2hhbmdlOiB2aWV3cG9ydENoYW5nZScsXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsTWVhc3VyZWRWaWV3cG9ydDogbWVhc3VyZWRWaWV3cG9ydCcsXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsUmVhZHk6IHNjcm9sbGVyUmVhZHknLFxuICAgICAgXSxcbiAgICB9LFxuICBdLFxuICB0ZW1wbGF0ZTogYDxuZy1jb250ZW50IC8+YCxcbiAgc3R5bGVzOiBgXG4gICAgOmhvc3Qge1xuICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgfVxuICBgLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgQ2VyaW91c1Njcm9sbENvbXBvbmVudDxUSXRlbSA9IHVua25vd24+IGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCB7XG4gIC8qKiBPcHRpb25hbCBjb252ZW5pZW5jZSB0ZW1wbGF0ZSBtYXJrZXI6IDxuZy10ZW1wbGF0ZSBjZXJpb3VzU2Nyb2xsSXRlbSBsZXQtaXRlbSBsZXQtaW5kZXg9XCJpbmRleFwiPi4uLjwvbmctdGVtcGxhdGU+ICovXG4gIEBDb250ZW50Q2hpbGQoQ2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZURpcmVjdGl2ZSlcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9qZWN0ZWRJdGVtVGVtcGxhdGU/OiBDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlRGlyZWN0aXZlPFRJdGVtPjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGNlcmlvdXNTY3JvbGw6IENlcmlvdXNTY3JvbGxEaXJlY3RpdmU8VEl0ZW0+KSB7fVxuXG4gIG5nQWZ0ZXJDb250ZW50SW5pdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsLmNlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGUpIHJldHVybjtcbiAgICBpZiAoIXRoaXMucHJvamVjdGVkSXRlbVRlbXBsYXRlKSByZXR1cm47XG5cbiAgICB0aGlzLmNlcmlvdXNTY3JvbGwuY2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZSA9XG4gICAgICB0aGlzLnByb2plY3RlZEl0ZW1UZW1wbGF0ZS50ZW1wbGF0ZVJlZiBhcyBUZW1wbGF0ZVJlZjxDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlQ29udGV4dDxUSXRlbT4+O1xuXG4gICAgaWYgKHRoaXMuY2VyaW91c1Njcm9sbC5jZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcikge1xuICAgICAgcXVldWVNaWNyb3Rhc2soKCkgPT4gdGhpcy5jZXJpb3VzU2Nyb2xsLnJlbmRlcigpKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
49
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VyaW91cy1zY3JvbGwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWNlcmlvdXMtc2Nyb2xsL3NyYy9saWIvY2VyaW91cy1zY3JvbGwuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksR0FFYixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNwRSxPQUFPLEVBQ0wsa0NBQWtDLEdBRW5DLE1BQU0sMENBQTBDLENBQUM7OztBQWlDbEQsTUFBTSxPQUFPLHNCQUFzQjtJQUtqQyxZQUE2QixhQUE0QztRQUE1QyxrQkFBYSxHQUFiLGFBQWEsQ0FBK0I7SUFBRyxDQUFDO0lBRTdFLGtCQUFrQjtRQUNoQixJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMseUJBQXlCO1lBQUUsT0FBTztRQUN6RCxJQUFJLENBQUMsSUFBSSxDQUFDLHFCQUFxQjtZQUFFLE9BQU87UUFFeEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyx5QkFBeUI7WUFDMUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFdBQW1FLENBQUM7UUFFakcsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLHVCQUF1QixFQUFFLENBQUM7WUFDL0MsY0FBYyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNwRCxDQUFDO0lBQ0gsQ0FBQzsrR0FqQlUsc0JBQXNCO21HQUF0QixzQkFBc0IsNkhBRW5CLGtDQUFrQyx5aUJBVnRDLGdCQUFnQjs7NEZBUWYsc0JBQXNCO2tCQS9CbEMsU0FBUzsrQkFDRSxnQkFBZ0IsY0FDZCxJQUFJLFdBQ1AsRUFBRSxrQkFDSzt3QkFDZDs0QkFDRSxTQUFTLEVBQUUsc0JBQXNCOzRCQUNqQyxNQUFNLEVBQUU7Z0NBQ04sMkNBQTJDO2dDQUMzQywyQkFBMkI7Z0NBQzNCLCtCQUErQjtnQ0FDL0IseUNBQXlDO2dDQUN6Qyw2Q0FBNkM7Z0NBQzdDLCtCQUErQjtnQ0FDL0IscUNBQXFDOzZCQUN0Qzs0QkFDRCxPQUFPLEVBQUU7Z0NBQ1AsNkNBQTZDO2dDQUM3QyxpREFBaUQ7Z0NBQ2pELG1DQUFtQzs2QkFDcEM7eUJBQ0Y7cUJBQ0YsWUFDUyxnQkFBZ0IsbUJBTVQsdUJBQXVCLENBQUMsTUFBTTsyRkFLOUIscUJBQXFCO3NCQURyQyxZQUFZO3VCQUFDLGtDQUFrQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIENvbnRlbnRDaGlsZCxcbiAgVGVtcGxhdGVSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBDZXJpb3VzU2Nyb2xsRGlyZWN0aXZlIH0gZnJvbSAnLi9jZXJpb3VzLXNjcm9sbC5kaXJlY3RpdmUnO1xuaW1wb3J0IHtcbiAgQ2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZURpcmVjdGl2ZSxcbiAgdHlwZSBDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlQ29udGV4dCxcbn0gZnJvbSAnLi9jZXJpb3VzLXNjcm9sbC1pdGVtLXRlbXBsYXRlLmRpcmVjdGl2ZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2NlcmlvdXMtc2Nyb2xsJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW10sXG4gIGhvc3REaXJlY3RpdmVzOiBbXG4gICAge1xuICAgICAgZGlyZWN0aXZlOiBDZXJpb3VzU2Nyb2xsRGlyZWN0aXZlLFxuICAgICAgaW5wdXRzOiBbXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsVG90YWxFbGVtZW50czogdG90YWxFbGVtZW50cycsXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsSXRlbXM6IGl0ZW1zJyxcbiAgICAgICAgJ2NlcmlvdXNTY3JvbGxHZXRJdGVtOiBnZXRJdGVtJyxcbiAgICAgICAgJ2NlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGU6IGl0ZW1UZW1wbGF0ZScsXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsSGVhZGVyVGVtcGxhdGU6IGhlYWRlclRlbXBsYXRlJyxcbiAgICAgICAgJ2NlcmlvdXNTY3JvbGxPcHRpb25zOiBvcHRpb25zJyxcbiAgICAgICAgJ2NlcmlvdXNTY3JvbGxBdXRvUmVuZGVyOiBhdXRvUmVuZGVyJyxcbiAgICAgIF0sXG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgICdjZXJpb3VzU2Nyb2xsVmlld3BvcnRDaGFuZ2U6IHZpZXdwb3J0Q2hhbmdlJyxcbiAgICAgICAgJ2NlcmlvdXNTY3JvbGxNZWFzdXJlZFZpZXdwb3J0OiBtZWFzdXJlZFZpZXdwb3J0JyxcbiAgICAgICAgJ2NlcmlvdXNTY3JvbGxSZWFkeTogc2Nyb2xsZXJSZWFkeScsXG4gICAgICBdLFxuICAgIH0sXG4gIF0sXG4gIHRlbXBsYXRlOiBgPG5nLWNvbnRlbnQgLz5gLFxuICBzdHlsZXM6IGBcbiAgICA6aG9zdCB7XG4gICAgICBkaXNwbGF5OiBibG9jaztcbiAgICB9XG4gIGAsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBDZXJpb3VzU2Nyb2xsQ29tcG9uZW50PFRJdGVtID0gdW5rbm93bj4gaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0IHtcbiAgLyoqIE9wdGlvbmFsIGNvbnZlbmllbmNlIHRlbXBsYXRlIG1hcmtlcjogPG5nLXRlbXBsYXRlIGNlcmlvdXNTY3JvbGxJdGVtIGxldC1pdGVtIGxldC1pbmRleD1cImluZGV4XCI+Li4uPC9uZy10ZW1wbGF0ZT4gKi9cbiAgQENvbnRlbnRDaGlsZChDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlRGlyZWN0aXZlKVxuICBwcml2YXRlIHJlYWRvbmx5IHByb2plY3RlZEl0ZW1UZW1wbGF0ZT86IENlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGVEaXJlY3RpdmU8VEl0ZW0+O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgY2VyaW91c1Njcm9sbDogQ2VyaW91c1Njcm9sbERpcmVjdGl2ZTxUSXRlbT4pIHt9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmNlcmlvdXNTY3JvbGwuY2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZSkgcmV0dXJuO1xuICAgIGlmICghdGhpcy5wcm9qZWN0ZWRJdGVtVGVtcGxhdGUpIHJldHVybjtcblxuICAgIHRoaXMuY2VyaW91c1Njcm9sbC5jZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlID1cbiAgICAgIHRoaXMucHJvamVjdGVkSXRlbVRlbXBsYXRlLnRlbXBsYXRlUmVmIGFzIFRlbXBsYXRlUmVmPENlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGVDb250ZXh0PFRJdGVtPj47XG5cbiAgICBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsLmNlcmlvdXNTY3JvbGxBdXRvUmVuZGVyKSB7XG4gICAgICBxdWV1ZU1pY3JvdGFzaygoKSA9PiB0aGlzLmNlcmlvdXNTY3JvbGwucmVuZGVyKCkpO1xuICAgIH1cbiAgfVxufVxuIl19
@@ -23,6 +23,12 @@ export class CeriousScrollDirective {
23
23
  this.ceriousScrollGetItem = null;
24
24
  /** Template used to render each row. */
25
25
  this.ceriousScrollItemTemplate = null;
26
+ /**
27
+ * Table mode only: template rendered into the engine's `<thead>` (a `<tr>` of
28
+ * `<th>`s). It lives in the same `<table>` as the rows, so columns align
29
+ * natively. Updates via change detection like the rows.
30
+ */
31
+ this.ceriousScrollHeaderTemplate = null;
26
32
  /** Options passed to `new CeriousScroll(...)`. */
27
33
  this.ceriousScrollOptions = {};
28
34
  /** Automatically call render after each scroll event. Default: true */
@@ -42,6 +48,9 @@ export class CeriousScrollDirective {
42
48
  // component tree on fast scrolls (where the engine's element pool wipes
43
49
  // textContent on reused containers, so view rootNodes get orphaned).
44
50
  this.freeViews = [];
51
+ // Table mode: the embedded view of the declarative header, rendered into the
52
+ // engine's <thead>.
53
+ this.headerView = null;
45
54
  }
46
55
  ngAfterViewInit() {
47
56
  this.ensureInitialized();
@@ -92,6 +101,8 @@ export class CeriousScrollDirective {
92
101
  this.viewportSub?.unsubscribe();
93
102
  this.viewportSub = null;
94
103
  this.destroyAllViews();
104
+ this.headerView?.destroy();
105
+ this.headerView = null;
95
106
  this.hostRef?.destroy();
96
107
  this.hostRef = null;
97
108
  }
@@ -240,7 +251,23 @@ export class CeriousScrollDirective {
240
251
  return;
241
252
  const container = this.host.nativeElement;
242
253
  const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);
243
- this.hostRef = this.cerious.createHost(container, total, this.ceriousScrollOptions, this.ngZone, () => {
254
+ // Table mode: capture the engine-created <thead> so we can render the
255
+ // declarative header template into it (and still run any user header hook).
256
+ let options = this.ceriousScrollOptions;
257
+ if (options.layout === 'table' && this.ceriousScrollHeaderTemplate) {
258
+ const userHeader = options.table?.header;
259
+ options = {
260
+ ...options,
261
+ table: {
262
+ ...options.table,
263
+ header: (thead) => {
264
+ userHeader?.(thead);
265
+ this.mountHeader(thead);
266
+ },
267
+ },
268
+ };
269
+ }
270
+ this.hostRef = this.cerious.createHost(container, total, options, this.ngZone, () => {
244
271
  // Coalesce scroll-driven renders to one per frame (the native scrollbar
245
272
  // can fire many scroll events between paints).
246
273
  if (this.ceriousScrollAutoRender)
@@ -257,6 +284,25 @@ export class CeriousScrollDirective {
257
284
  queueMicrotask(() => this.render());
258
285
  }
259
286
  }
287
+ /**
288
+ * Render the declarative header template into the engine's <thead>. One
289
+ * embedded view, created inside the zone (so the header's event bindings are
290
+ * zone-patched), its root nodes appended directly into the <thead>.
291
+ */
292
+ mountHeader(thead) {
293
+ if (!this.ceriousScrollHeaderTemplate)
294
+ return;
295
+ this.headerView?.destroy();
296
+ const view = this.ngZone.run(() => {
297
+ const v = this.ceriousScrollHeaderTemplate.createEmbeddedView({});
298
+ this.appRef.attachView(v);
299
+ v.detectChanges();
300
+ return v;
301
+ });
302
+ for (const node of view.rootNodes)
303
+ thead.appendChild(node);
304
+ this.headerView = view;
305
+ }
260
306
  getItemForIndex(index) {
261
307
  const getter = this.ceriousScrollGetItem;
262
308
  if (getter)
@@ -361,7 +407,7 @@ export class CeriousScrollDirective {
361
407
  this.freeViews.length = 0;
362
408
  }
363
409
  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 }); }
364
- 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 }); }
410
+ 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", ceriousScrollHeaderTemplate: "ceriousScrollHeaderTemplate", ceriousScrollOptions: "ceriousScrollOptions", ceriousScrollAutoRender: "ceriousScrollAutoRender" }, outputs: { ceriousScrollViewportChange: "ceriousScrollViewportChange", ceriousScrollMeasuredViewport: "ceriousScrollMeasuredViewport", ceriousScrollReady: "ceriousScrollReady" }, usesOnChanges: true, ngImport: i0 }); }
365
411
  }
366
412
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CeriousScrollDirective, decorators: [{
367
413
  type: Directive,
@@ -377,6 +423,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
377
423
  type: Input
378
424
  }], ceriousScrollItemTemplate: [{
379
425
  type: Input
426
+ }], ceriousScrollHeaderTemplate: [{
427
+ type: Input
380
428
  }], ceriousScrollOptions: [{
381
429
  type: Input
382
430
  }], ceriousScrollAutoRender: [{
@@ -388,4 +436,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
388
436
  }], ceriousScrollReady: [{
389
437
  type: Output
390
438
  }] } });
391
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VyaW91cy1zY3JvbGwuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWNlcmlvdXMtc2Nyb2xsL3NyYy9saWIvY2VyaW91cy1zY3JvbGwuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFHTCxTQUFTLEVBR1QsWUFBWSxFQUNaLEtBQUssRUFJTCxNQUFNLEdBR1AsTUFBTSxlQUFlLENBQUM7OztBQWF2QixTQUFTLG1CQUFtQixDQUFDLGFBQXdDLEVBQUUsUUFBbUM7SUFDeEcsTUFBTSxTQUFTLEdBQUcsT0FBTyxhQUFhLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLE9BQU8sUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDMUgsSUFBSSxTQUFTLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUN2RCxNQUFNLElBQUksS0FBSyxDQUFDLHVGQUF1RixDQUFDLENBQUM7SUFDM0csQ0FBQztJQUNELHdDQUF3QztJQUN4QyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ2hDLENBQUM7QUFNRCxNQUFNLE9BQU8sc0JBQXNCO0lBdUNqQyxZQUNtQixJQUE2QixFQUM3QixNQUFzQixFQUN0QixNQUFjLEVBQ2QsT0FBNkI7UUFIN0IsU0FBSSxHQUFKLElBQUksQ0FBeUI7UUFDN0IsV0FBTSxHQUFOLE1BQU0sQ0FBZ0I7UUFDdEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFlBQU8sR0FBUCxPQUFPLENBQXNCO1FBMUNoRCxtRkFBbUY7UUFDMUUsK0JBQTBCLEdBQWtCLElBQUksQ0FBQztRQUUxRCxpREFBaUQ7UUFDeEMsdUJBQWtCLEdBQTRCLElBQUksQ0FB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QyxlQUFlLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUNqRCxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM3QixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDakIsQ0FBQztRQUNELElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDN0IsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDN0IsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pCLENBQUM7UUFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDNUIsQ0FBQzsrR0F4WVUsc0JBQXNCO21HQUF0QixzQkFBc0I7OzRGQUF0QixzQkFBc0I7a0JBSmxDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGlCQUFpQjtvQkFDM0IsVUFBVSxFQUFFLElBQUk7aUJBQ2pCO29LQUdVLDBCQUEwQjtzQkFBbEMsS0FBSztnQkFHRyxrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBR0csb0JBQW9CO3NCQUE1QixLQUFLO2dCQUdHLHlCQUF5QjtzQkFBakMsS0FBSztnQkFHRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBR0csdUJBQXVCO3NCQUEvQixLQUFLO2dCQUdJLDJCQUEyQjtzQkFBcEMsTUFBTTtnQkFHRyw2QkFBNkI7c0JBQXRDLE1BQU07Z0JBR0csa0JBQWtCO3NCQUEzQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQXBwbGljYXRpb25SZWYsXG4gIERpcmVjdGl2ZSxcbiAgRWxlbWVudFJlZixcbiAgRW1iZWRkZWRWaWV3UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBOZ1pvbmUsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFRlbXBsYXRlUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtcbiAgdHlwZSBDZXJpb3VzU2Nyb2xsT3B0aW9ucyxcbiAgdHlwZSBFbGVtZW50UmVuZGVyZXIsXG4gIHR5cGUgTWVhc3VyZWRWaWV3cG9ydFJhbmdlLFxufSBmcm9tICdAY2VyaW91c2RldnRlY2gvY2VyaW91cy1zY3JvbGwnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB0eXBlIHsgQ2VyaW91c1ZpZXdwb3J0Q2hhbmdlRGV0YWlsIH0gZnJvbSAnLi9jZXJpb3VzLXNjcm9sbC50eXBlcyc7XG5pbXBvcnQgdHlwZSB7IENlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGVDb250ZXh0IH0gZnJvbSAnLi9jZXJpb3VzLXNjcm9sbC1pdGVtLXRlbXBsYXRlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyB0eXBlIENlcmlvdXNTY3JvbGxIb3N0UmVmLCBDZXJpb3VzU2Nyb2xsU2VydmljZSB9IGZyb20gJy4vY2VyaW91cy1zY3JvbGwuc2VydmljZSc7XG5cbmZ1bmN0aW9uIGNvZXJjZVRvdGFsRWxlbWVudHMoZXhwbGljaXRUb3RhbDogbnVtYmVyIHwgbnVsbCB8IHVuZGVmaW5lZCwgaXRlbXNMZW46IG51bWJlciB8IG51bGwgfCB1bmRlZmluZWQpOiBudW1iZXIge1xuICBjb25zdCBjYW5kaWRhdGUgPSB0eXBlb2YgZXhwbGljaXRUb3RhbCA9PT0gJ251bWJlcicgPyBleHBsaWNpdFRvdGFsIDogdHlwZW9mIGl0ZW1zTGVuID09PSAnbnVtYmVyJyA/IGl0ZW1zTGVuIDogdW5kZWZpbmVkO1xuICBpZiAoY2FuZGlkYXRlID09PSB1bmRlZmluZWQgfHwgTnVtYmVyLmlzTmFOKGNhbmRpZGF0ZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NlcmlvdXNTY3JvbGxEaXJlY3RpdmU6IHByb3ZpZGUgYGNlcmlvdXNTY3JvbGxUb3RhbEVsZW1lbnRzYCBvciBgY2VyaW91c1Njcm9sbEl0ZW1zYC4nKTtcbiAgfVxuICAvLyBDZXJpb3VzU2Nyb2xsIGN1cnJlbnRseSByZXF1aXJlcyA+PSAxXG4gIHJldHVybiBNYXRoLm1heCgxLCBjYW5kaWRhdGUpO1xufVxuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbY2VyaW91c1Njcm9sbF0nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxufSlcbmV4cG9ydCBjbGFzcyBDZXJpb3VzU2Nyb2xsRGlyZWN0aXZlPFRJdGVtID0gdW5rbm93bj4gaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG4gIC8qKiBUb3RhbCBudW1iZXIgb2YgaXRlbXMuIElmIG9taXR0ZWQsIGRlcml2ZWQgZnJvbSBgY2VyaW91c1Njcm9sbEl0ZW1zLmxlbmd0aGAuICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxUb3RhbEVsZW1lbnRzOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICAvKiogT3B0aW9uYWwgaXRlbXMgYXJyYXkgKGVuYWJsZXMgYGxldC1pdGVtYCkuICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxJdGVtczogcmVhZG9ubHkgVEl0ZW1bXSB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBPcHRpb25hbCBnZXR0ZXIgZm9yIGxhcmdlIGRhdGFzZXRzIChhbHRlcm5hdGl2ZSB0byBwYXNzaW5nIGZ1bGwgYGl0ZW1zYCkuICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxHZXRJdGVtOiAoKGluZGV4OiBudW1iZXIpID0+IFRJdGVtKSB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBUZW1wbGF0ZSB1c2VkIHRvIHJlbmRlciBlYWNoIHJvdy4gKi9cbiAgQElucHV0KCkgY2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZTogVGVtcGxhdGVSZWY8Q2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZUNvbnRleHQ8VEl0ZW0+PiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBPcHRpb25zIHBhc3NlZCB0byBgbmV3IENlcmlvdXNTY3JvbGwoLi4uKWAuICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxPcHRpb25zOiBDZXJpb3VzU2Nyb2xsT3B0aW9ucyA9IHt9O1xuXG4gIC8qKiBBdXRvbWF0aWNhbGx5IGNhbGwgcmVuZGVyIGFmdGVyIGVhY2ggc2Nyb2xsIGV2ZW50LiBEZWZhdWx0OiB0cnVlICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxBdXRvUmVuZGVyID0gdHJ1ZTtcblxuICAvKiogRW1pdHMgYGNlcmlvdXMtdmlld3BvcnQtY2hhbmdlYCBkZXRhaWwuICovXG4gIEBPdXRwdXQoKSBjZXJpb3VzU2Nyb2xsVmlld3BvcnRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPENlcmlvdXNWaWV3cG9ydENoYW5nZURldGFpbD4oKTtcblxuICAvKiogRW1pdHMgdGhlIGxhc3QgbWVhc3VyZWQgdmlld3BvcnQgYWZ0ZXIgZWFjaCByZW5kZXIgcGFzcy4gKi9cbiAgQE91dHB1dCgpIGNlcmlvdXNTY3JvbGxNZWFzdXJlZFZpZXdwb3J0ID0gbmV3IEV2ZW50RW1pdHRlcjxNZWFzdXJlZFZpZXdwb3J0UmFuZ2U+KCk7XG5cbiAgLyoqIEVtaXRzIG9uY2UgdGhlIHVuZGVybHlpbmcgYENlcmlvdXNTY3JvbGxgIGluc3RhbmNlIGlzIHJlYWR5LiAqL1xuICBAT3V0cHV0KCkgY2VyaW91c1Njcm9sbFJlYWR5ID0gbmV3IEV2ZW50RW1pdHRlcjxDZXJpb3VzU2Nyb2xsSG9zdFJlZlsnc2Nyb2xsZXInXT4oKTtcblxuICBwcml2YXRlIGhvc3RSZWY6IENlcmlvdXNTY3JvbGxIb3N0UmVmIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgdmlld3BvcnRTdWI6IFN1YnNjcmlwdGlvbiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHNjaGVkdWxlZFJlbmRlckZyYW1lOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIHJlYWRvbmx5IHZpZXdCeUNvbnRhaW5lciA9IG5ldyBNYXA8SFRNTEVsZW1lbnQsIEVtYmVkZGVkVmlld1JlZjxDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlQ29udGV4dDxUSXRlbT4+PigpO1xuICAvLyBQb29sIG9mIHZpZXdzIGRldGFjaGVkIGJlY2F1c2UgdGhlaXIgY29udGFpbmVyIGxlZnQgdGhlIHZpZXdwb3J0LiBSZXVzaW5nXG4gIC8vIHRoZW0gb24gc3Vic2VxdWVudCByZW5kZXJzIGF2b2lkcyBkZXN0cm95aW5nICsgcmVjcmVhdGluZyB0aGUgZW50aXJlIHJvd1xuICAvLyBjb21wb25lbnQgdHJlZSBvbiBmYXN0IHNjcm9sbHMgKHdoZXJlIHRoZSBlbmdpbmUncyBlbGVtZW50IHBvb2wgd2lwZXNcbiAgLy8gdGV4dENvbnRlbnQgb24gcmV1c2VkIGNvbnRhaW5lcnMsIHNvIHZpZXcgcm9vdE5vZGVzIGdldCBvcnBoYW5lZCkuXG4gIHByaXZhdGUgcmVhZG9ubHkgZnJlZVZpZXdzOiBFbWJlZGRlZFZpZXdSZWY8Q2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZUNvbnRleHQ8VEl0ZW0+PltdID0gW107XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFwcFJlZjogQXBwbGljYXRpb25SZWYsXG4gICAgcHJpdmF0ZSByZWFkb25seSBuZ1pvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNlcmlvdXM6IENlcmlvdXNTY3JvbGxTZXJ2aWNlXG4gICkge31cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmICghdGhpcy5ob3N0UmVmKSByZXR1cm47XG5cbiAgICBpZiAoY2hhbmdlc1snY2VyaW91c1Njcm9sbEl0ZW1zJ10gfHwgY2hhbmdlc1snY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHMnXSkge1xuICAgICAgY29uc3QgdG90YWwgPSBjb2VyY2VUb3RhbEVsZW1lbnRzKHRoaXMuY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHMsIHRoaXMuY2VyaW91c1Njcm9sbEl0ZW1zPy5sZW5ndGggPz8gbnVsbCk7XG4gICAgICBjb25zdCBjb3VudENoYW5nZWQgPSB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIudG90YWxFbGVtZW50cyAhPT0gdG90YWw7XG5cbiAgICAgIGlmIChjb3VudENoYW5nZWQpIHtcbiAgICAgICAgLy8gVGhlIGRhdGFzZXQgc2l6ZSBjaGFuZ2VkOiB0aGUgVmlld3BvcnRSZW5kZXJlciBzdG9yZXMgaXRzIG93biBjb3B5IG9mXG4gICAgICAgIC8vIHRvdGFsRWxlbWVudHMgKHNldCBieSB2YWx1ZSBhdCBjb25zdHJ1Y3Rpb24pIHNvIHBhdGNoaW5nIHRoZSBlbmdpbmUnc1xuICAgICAgICAvLyBwdWJsaWMgcHJvcGVydHkgYWxvbmUgbGVhdmVzIHRoZSByZW5kZXJlcidzIGludGVybmFsIGJvdW5kIHN0YWxlLiAgVGhlXG4gICAgICAgIC8vIHJlbmRlcmVyIHdvdWxkIHRoZW4gdXNlIHRoZSBvbGQgY291bnQgZm9yIGl0cyB2aWV3cG9ydC1maWxsIGxvb3AgYW5kXG4gICAgICAgIC8vIGJvdHRvbS1ib3VuZGFyeSBzY2FuLCBwcm9kdWNpbmcgcGhhbnRvbSByZW5kZXJzIGF0IG91dC1vZi1ib3VuZHNcbiAgICAgICAgLy8gaW5kaWNlcyAodW5kZWZpbmVkIGl0ZW1zIOKGkiAwLWhlaWdodCByb3dzIOKGkiB0aGUgZmlsbCBsb29wIG5ldmVyXG4gICAgICAgIC8vIHNhdGlzZmllcyBpdHMgaGVpZ2h0IGNvbmRpdGlvbiDihpIgaHVuZHJlZHMgb2YgcmVuZGVyZXIgY2FsbGJhY2tzKS5cbiAgICAgICAgLy8gUmVjcmVhdGluZyB0aGUgZW5naW5lIGdpdmVzIGJvdGggdGhlIGVuZ2luZSBhbmQgdGhlIHJlbmRlcmVyIGEgZnJlc2gsXG4gICAgICAgIC8vIGNvbnNpc3RlbnQgY291bnQuICBlbnN1cmVJbml0aWFsaXplZCgpIHNjaGVkdWxlcyB0aGUgZmlyc3QgcmVuZGVyIHZpYVxuICAgICAgICAvLyBxdWV1ZU1pY3JvdGFzaywgd2hpY2ggcnVucyBhZnRlciB0aGUgY3VycmVudCBDRCBjeWNsZSBjb21wbGV0ZXMuXG4gICAgICAgIHRoaXMucmVjcmVhdGUoKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcikge1xuICAgICAgICAvLyBTYW1lIGNvdW50LCBuZXcgZGF0YSByZWZlcmVuY2UgKGUuZy4gYW4gaW1tdXRhYmxlIGVkaXQgb3IgYSBzb3J0IHRoYXRcbiAgICAgICAgLy8gaGFwcGVucyB0byBrZWVwIHRoZSBzYW1lIGxlbmd0aCkuIFRoZSBlbmdpbmUgcmV1c2VzIHRoZSBET00gZWxlbWVudCBpdFxuICAgICAgICAvLyBhbHJlYWR5IHJlbmRlcmVkIGZvciBlYWNoIG92ZXJsYXBwaW5nIGluZGV4IHdpdGhvdXQgcmUtaW52b2tpbmcgdGhlXG4gICAgICAgIC8vIHJlbmRlcmVyLCBzbyB1cGRhdGUgdGhlIGNvbnRlbnQgb2YgZXZlcnkgY3VycmVudGx5LXZpc2libGUgcm93IElOXG4gICAgICAgIC8vIFBMQUNFIGJlZm9yZSBjYWxsaW5nIHJlbmRlcigpLiAgVGhpcyBwcmVzZXJ2ZXMgZWFjaCByb3cncyBlbWJlZGRlZFxuICAgICAgICAvLyB2aWV3IChzbyBhIGZvY3VzZWQgdGV4dGJveCBrZWVwcyBmb2N1cy9jYXJldCkgYW5kIGRvZXMgTk9UIGRpc2NhcmRcbiAgICAgICAgLy8gY2FjaGVkIGhlaWdodHMuIElmIGEgcm93J3MgaGVpZ2h0IGFjdHVhbGx5IGNoYW5nZXMgdGhlIGVuZ2luZSdzXG4gICAgICAgIC8vIFJlc2l6ZU9ic2VydmVyIGtlZXBzIHRoZSBjYWNoZSBjb3JyZWN0IG9uIGl0cyBvd247IGZvciBhIHdob2xlc2FsZVxuICAgICAgICAvLyBoZWlnaHQgY2hhbmdlIGFjcm9zcyBhbGwgcm93cywgY2FsbCByZWNhbGN1bGF0ZSgpIGluc3RlYWQuXG4gICAgICAgIHRoaXMucmVmcmVzaFJlbmRlcmVkQ29udGVudCgpO1xuICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsT3B0aW9ucyddICYmICFjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsT3B0aW9ucyddLmZpcnN0Q2hhbmdlKSB7XG4gICAgICAvLyBPcHRpb25zIGFyZSBjb25zdW1lZCBwcmltYXJpbHkgYXQgY29uc3RydWN0aW9uIHRpbWUuXG4gICAgICB0aGlzLnJlY3JlYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2NoZWR1bGVkUmVuZGVyRnJhbWUgIT0gbnVsbCkge1xuICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5zY2hlZHVsZWRSZW5kZXJGcmFtZSk7XG4gICAgICB0aGlzLnNjaGVkdWxlZFJlbmRlckZyYW1lID0gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLnZpZXdwb3J0U3ViPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMudmlld3BvcnRTdWIgPSBudWxsO1xuXG4gICAgdGhpcy5kZXN0cm95QWxsVmlld3MoKTtcblxuICAgIHRoaXMuaG9zdFJlZj8uZGVzdHJveSgpO1xuICAgIHRoaXMuaG9zdFJlZiA9IG51bGw7XG4gIH1cblxuICAvKiogSW1wZXJhdGl2ZWx5IHRyaWdnZXIgYSByZW5kZXIgcGFzcyAodXNlcyBgY2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZWApLiAqL1xuICByZW5kZXIoKTogTWVhc3VyZWRWaWV3cG9ydFJhbmdlIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHRlbXBsYXRlID0gdGhpcy5jZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlO1xuICAgIGlmICghdGVtcGxhdGUpIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgaG9zdENvbnRhaW5lciA9IHRoaXMuaG9zdC5uYXRpdmVFbGVtZW50O1xuICAgIGNvbnN0IGhlaWdodCA9IGhvc3RDb250YWluZXIuY2xpZW50SGVpZ2h0IHx8IGhvc3RDb250YWluZXIub2Zmc2V0SGVpZ2h0O1xuICAgIGNvbnN0IGNvbnRlbnRDb250YWluZXIgPSB0aGlzLmhvc3RSZWYuY29udGVudEVsZW1lbnQ7XG5cbiAgICAvLyBUcmFjayB3aGV0aGVyIHRoZSBlbmdpbmUgYXNrZWQgdXMgdG8gYmluZCBhbnkgcm93IHRoaXMgcGFzcy4gUHVyZSBzY3JvbGxcbiAgICAvLyBmcmFtZXMgd2hlcmUgdGhlIHZpc2libGUgcm93IHNldCBkb2Vzbid0IGNoYW5nZSBzdGlsbCBkcml2ZSByZW5kZXIoKSB2aWFcbiAgICAvLyB0aGUgckFGIGNvYWxlc2NlciDigJQgdGhlcmUncyBubyBwb2ludCBpbiB3YWxraW5nIHRoZSBwcnVuZSBtYXAgb3JcbiAgICAvLyBlbWl0dGluZyB0aGUgdmlld3BvcnQgcmFuZ2Ugd2hlbiBub3RoaW5nIHdhcyB0b3VjaGVkLlxuICAgIGxldCByZW5kZXJlckludm9jYXRpb25zID0gMDtcbiAgICBjb25zdCByZW5kZXJlcjogRWxlbWVudFJlbmRlcmVyID0gKGluZGV4LCBlbGVtZW50Q29udGFpbmVyKSA9PiB7XG4gICAgICByZW5kZXJlckludm9jYXRpb25zKys7XG4gICAgICAvLyBSZW5kZXIgZWFjaCByb3cncyBlbWJlZGRlZCB2aWV3IHdpdGggTE9DQUwgY2hhbmdlIGRldGVjdGlvblxuICAgICAgLy8gKGB2aWV3LmRldGVjdENoYW5nZXMoKWAgaW5zaWRlIGByZW5kZXJUZW1wbGF0ZUludG9Db250YWluZXJgKSBzbyB0aGVcbiAgICAgIC8vIGVuZ2luZSBjYW4gbWVhc3VyZSBpdHMgaGVpZ2h0IGR1cmluZyB0aGlzIHBhc3MuIERvIE5PVCB3cmFwIGVhY2ggcm93IGluXG4gICAgICAvLyBpdHMgb3duIGBuZ1pvbmUucnVuYCDigJQgdGhhdCBmaXJlcyBhIGZ1bGwgYEFwcGxpY2F0aW9uUmVmYCB0aWNrICpwZXIgcm93KlxuICAgICAgLy8gKE8obmV3Um93cyDDlyB2aXNpYmxlUm93cykgd29yaywgamFua3kgZHJhZ3MpLiBUaGUgc2luZ2xlIGNvYWxlc2NlZCB0aWNrXG4gICAgICAvLyBmb3IgdGhlIHdob2xlIHBhc3MgaXMgaGFuZGxlZCBieSB0aGUgY2FsbGVyIChgc2NoZWR1bGVSZW5kZXJgKS5cbiAgICAgIHRoaXMucmVuZGVyVGVtcGxhdGVJbnRvQ29udGFpbmVyKHRlbXBsYXRlLCBpbmRleCwgZWxlbWVudENvbnRhaW5lcik7XG4gICAgfTtcblxuICAgIGNvbnN0IHJhbmdlID0gdGhpcy5ob3N0UmVmLnNjcm9sbGVyLnJlbmRlclZpZXdwb3J0KGhlaWdodCwgY29udGVudENvbnRhaW5lciwgcmVuZGVyZXIpO1xuXG4gICAgaWYgKHJlbmRlcmVySW52b2NhdGlvbnMgPT09IDApIHtcbiAgICAgIC8vIFZpZXdwb3J0IGRpZG4ndCBjaGFuZ2Ug4oCUIHNraXAgdGhlIHBydW5lIHdhbGsgYW5kIHRoZSAocG90ZW50aWFsbHlcbiAgICAgIC8vIHpvbmUtZW50ZXJpbmcpIGVtaXQuXG4gICAgICByZXR1cm4gcmFuZ2U7XG4gICAgfVxuXG4gICAgLy8gRGVzdHJveSB2aWV3cyB3aG9zZSBjb250YWluZXIgdGhlIGVuZ2luZSBubyBsb25nZXIgcmVuZGVycy4gV2l0aG91dCB0aGlzLFxuICAgIC8vIGV2ZXJ5IGNvbnRhaW5lciB0aGUgZW5naW5lIHJlY3ljbGVzIGludG8gaXRzIGVsZW1lbnQgcG9vbCBsZWF2ZXMgaXRzXG4gICAgLy8gZW1iZWRkZWQgdmlldyBhdHRhY2hlZCB0byBBcHBsaWNhdGlvblJlZiBmb3JldmVyIOKAlCBzbyB0aGUgYXR0YWNoZWQtdmlld1xuICAgIC8vIGxpc3QgKGFuZCBldmVyeSBPKG4pIGBkZXRhY2hWaWV3YCkgZ3Jvd3Mgd2l0aG91dCBib3VuZCBhbmQgc2Nyb2xsaW5nIGdldHNcbiAgICAvLyBwcm9ncmVzc2l2ZWx5IHNsb3dlci4gTWlycm9ycyB0aGUgUmVhY3QvVnVlIHdyYXBwZXJzLCB3aGljaCBkcm9wIHJvd3MgdGhhdFxuICAgIC8vIGZhbGwgb3V0IG9mIGBnZXRSZW5kZXJlZEluZGljZXMoKWAuXG4gICAgdGhpcy5wcnVuZURldGFjaGVkVmlld3MoKTtcblxuICAgIC8vIE9ubHkgcmUtZW50ZXIgdGhlIHpvbmUgKGEgZ2xvYmFsIHRpY2spIGlmIHNvbWVvbmUgaXMgYWN0dWFsbHkgbGlzdGVuaW5nLlxuICAgIGlmICh0aGlzLmNlcmlvdXNTY3JvbGxNZWFzdXJlZFZpZXdwb3J0Lm9ic2VydmVkKSB7XG4gICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4gdGhpcy5jZXJpb3VzU2Nyb2xsTWVhc3VyZWRWaWV3cG9ydC5lbWl0KHJhbmdlKSk7XG4gICAgfVxuICAgIHJldHVybiByYW5nZTtcbiAgfVxuXG4gIC8qKiBUZWFyIGRvd24gZW1iZWRkZWQgdmlld3Mgd2hvc2UgY29udGFpbmVyIGlzIG5vIGxvbmdlciBwYXJ0IG9mIHRoZSB2aWV3cG9ydC4gKi9cbiAgcHJpdmF0ZSBwcnVuZURldGFjaGVkVmlld3MoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYgfHwgdGhpcy52aWV3QnlDb250YWluZXIuc2l6ZSA9PT0gMCkgcmV0dXJuO1xuICAgIGNvbnN0IHNjcm9sbGVyID0gdGhpcy5ob3N0UmVmLnNjcm9sbGVyO1xuICAgIGNvbnN0IGFjdGl2ZSA9IG5ldyBTZXQ8SFRNTEVsZW1lbnQ+KCk7XG4gICAgZm9yIChjb25zdCBpbmRleCBvZiBzY3JvbGxlci5nZXRSZW5kZXJlZEluZGljZXMoKSkge1xuICAgICAgY29uc3QgZWwgPSBzY3JvbGxlci5nZXRSZW5kZXJlZEVsZW1lbnQoaW5kZXgpO1xuICAgICAgaWYgKGVsKSBhY3RpdmUuYWRkKGVsKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBbY29udGFpbmVyLCB2aWV3XSBvZiB0aGlzLnZpZXdCeUNvbnRhaW5lcikge1xuICAgICAgaWYgKCFhY3RpdmUuaGFzKGNvbnRhaW5lcikpIHtcbiAgICAgICAgLy8gRGV0YWNoIERPTSBidXQga2VlcCB0aGUgdmlldyBhbGl2ZSBpbiB0aGUgcG9vbCBmb3IgZnV0dXJlIHJldXNlLlxuICAgICAgICAvLyBEZXN0cm95aW5nICsgcmVjcmVhdGluZyB2aWV3cyBwZXIgc2Nyb2xsIHN0ZXAgZG9taW5hdGVzIGZyYW1lIHRpbWUuXG4gICAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiB2aWV3LnJvb3ROb2Rlcykge1xuICAgICAgICAgIGlmIChub2RlLnBhcmVudE5vZGUpIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZpZXdCeUNvbnRhaW5lci5kZWxldGUoY29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5mcmVlVmlld3MucHVzaCh2aWV3KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKiogQXV0by1yZW5kZXIgY29hbGVzY2VkIHRvIGF0IG1vc3Qgb25jZSBwZXIgYW5pbWF0aW9uIGZyYW1lLiAqL1xuICBwcml2YXRlIHNjaGVkdWxlUmVuZGVyKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnNjaGVkdWxlZFJlbmRlckZyYW1lICE9IG51bGwpIHJldHVybjtcbiAgICB0aGlzLnNjaGVkdWxlZFJlbmRlckZyYW1lID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgIHRoaXMuc2NoZWR1bGVkUmVuZGVyRnJhbWUgPSBudWxsO1xuICAgICAgLy8gUnVuIHJlbmRlcigpIE9VVFNJREUgQW5ndWxhcidzIHpvbmUuIEEgZnVsbCBBcHBsaWNhdGlvblJlZi50aWNrKCkgb25cbiAgICAgIC8vIGV2ZXJ5IHNjcm9sbCBmcmFtZSBpcyB0aGUgcHJpbWFyeSBGUFMgYm90dGxlbmVjazogZXZlbiB3aGVuIG5vIHJvd3NcbiAgICAgIC8vIGNoYW5nZSAocHVyZSB0cmFuc2xhdGlvbiksIG5nWm9uZS5ydW4oKSBjYXVzZXMgQW5ndWxhciB0byB3YWxrIHRoZVxuICAgICAgLy8gZW50aXJlIGNvbXBvbmVudCB0cmVlLiBJbnN0ZWFkIHdlIGNhbGwgdmlldy5kZXRlY3RDaGFuZ2VzKCkgbG9jYWxseVxuICAgICAgLy8gaW5zaWRlIHJlbmRlclRlbXBsYXRlSW50b0NvbnRhaW5lciBmb3IgZWFjaCBhZmZlY3RlZCByb3cuIFpvbmUgZW50cnkgaXNcbiAgICAgIC8vIG9ubHkgbmVlZGVkIHdoZW4gY3JlYXRpbmcgYSBicmFuZC1uZXcgZW1iZWRkZWQgdmlldyAodG8gem9uZS1wYXRjaCBpdHNcbiAgICAgIC8vIGV2ZW50IGxpc3RlbmVycykg4oCUIHJlY3ljbGVkIGFuZCBwb29sZWQgdmlld3Mgd2VyZSBhbHJlYWR5IGNyZWF0ZWQgaW5zaWRlXG4gICAgICAvLyB6b25lIGFuZCB0aGVpciBsaXN0ZW5lcnMgcmVtYWluIHpvbmUtYXdhcmUuXG4gICAgICB0aGlzLnJlbmRlcigpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc2NhcmQgYWxsIGNhY2hlZCByb3cgaGVpZ2h0cyBhbmQgcmUtbWVhc3VyZSB0aGUgdmlld3BvcnQuXG4gICAqXG4gICAqIENhbGwgdGhpcyBvbmx5IHdoZW4gdGhlIGhlaWdodHMgb2Ygcm93cyB5b3UndmUgKmFscmVhZHkgcmVuZGVyZWQqIG1heSBoYXZlXG4gICAqIGNoYW5nZWQgd2l0aG91dCB0aGVpciBpbmRpY2VzIGNoYW5naW5nIOKAlCBlLmcuIGEgZ2xvYmFsIGZvbnQvZGVuc2l0eSBjaGFuZ2UsXG4gICAqIG9yIHN3YXBwaW5nIGV2ZXJ5IHJvdyB0byBhIGRpZmZlcmVudCBsYXlvdXQuIFRoaXMgZm9yY2VzIGEgc3luY2hyb25vdXNcbiAgICogcmUtbWVhc3VyZSAob25lIGBvZmZzZXRIZWlnaHRgIHJlYWQgcGVyIHZpc2libGUgcm93KSwgc28gZG8gTk9UIGNhbGwgaXQgb25cbiAgICogcm91dGluZSBlZGl0czogYSBzaW5nbGUgY2VsbCBlZGl0IGtlZXBzIGl0cyByb3cncyBzaXplLCBhbmQgdGhlIGVuZ2luZSdzXG4gICAqIFJlc2l6ZU9ic2VydmVyIHBpY2tzIHVwIGFueSBpbmNpZGVudGFsIHJlc2l6ZSBvbiBpdHMgb3duLlxuICAgKi9cbiAgcmVjYWxjdWxhdGUoKTogTWVhc3VyZWRWaWV3cG9ydFJhbmdlIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHRlbXBsYXRlID0gdGhpcy5jZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlO1xuICAgIGlmICh0ZW1wbGF0ZSkge1xuICAgICAgLy8gUmUtaW52b2tlIHRoZSByZW5kZXJlciBmb3IgZXZlcnkgY3VycmVudGx5LXJlbmRlcmVkIHJvdyBzbyBwZW5kaW5nXG4gICAgICAvLyBBbmd1bGFyIGJpbmRpbmdzIGZsdXNoIGludG8gdGhlIERPTSBhbmQgdGhlIGVuZ2luZSByZS1tZWFzdXJlcyBlYWNoXG4gICAgICAvLyByb3cncyBuZXcgaGVpZ2h0IGludG8gaXRzIGNhY2hlLiBXaXRob3V0IHRoaXMsIHRoZSBlbmdpbmUncyByZW5kZXJcbiAgICAgIC8vIHBhc3Mgc2tpcHMgdGhlIHJlbmRlcmVyIGZvciBhbHJlYWR5LXJlbmRlcmVkIGluZGljZXMgYW5kIGZhbGxzXG4gICAgICAvLyB0aHJvdWdoIHRvIHJlYWRpbmcgc3RhbGUgb2Zmc2V0SGVpZ2h0LlxuICAgICAgdGhpcy5ob3N0UmVmLnNjcm9sbGVyLnJlZnJlc2hWaXNpYmxlKChpbmRleCwgZWxlbWVudENvbnRhaW5lcikgPT4ge1xuICAgICAgICB0aGlzLnJlbmRlclRlbXBsYXRlSW50b0NvbnRhaW5lcih0ZW1wbGF0ZSwgaW5kZXgsIGVsZW1lbnRDb250YWluZXIpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnJlbmRlcigpO1xuICB9XG5cbiAgLyoqIEp1bXAgZGlyZWN0bHkgdG8gYW4gZWxlbWVudCBpbmRleCwgdGhlbiByZW5kZXIuICovXG4gIGp1bXBUb0VsZW1lbnQoaW5kZXg6IG51bWJlcik6IE1lYXN1cmVkVmlld3BvcnRSYW5nZSB8IG51bGwge1xuICAgIGlmICghdGhpcy5ob3N0UmVmKSByZXR1cm4gbnVsbDtcbiAgICB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIuanVtcFRvRWxlbWVudChpbmRleCk7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICAvKiogU2Nyb2xsIHRvIGEgcGVyY2VudGFnZSAoMC4uMTAwKSwgdGhlbiByZW5kZXIuICovXG4gIHNjcm9sbFRvUGVyY2VudGFnZShwZXJjZW50YWdlOiBudW1iZXIpOiBNZWFzdXJlZFZpZXdwb3J0UmFuZ2UgfCBudWxsIHtcbiAgICBpZiAoIXRoaXMuaG9zdFJlZikgcmV0dXJuIG51bGw7XG4gICAgdGhpcy5ob3N0UmVmLnNjcm9sbGVyLmhhbmRsZVNjcm9sbFBlcmNlbnRhZ2UocGVyY2VudGFnZSk7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICAvKiogUmVzZXQgdG8gdGhlIHRvcCwgdGhlbiByZW5kZXIuICovXG4gIHJlc2V0KCk6IE1lYXN1cmVkVmlld3BvcnRSYW5nZSB8IG51bGwge1xuICAgIGlmICghdGhpcy5ob3N0UmVmKSByZXR1cm4gbnVsbDtcbiAgICB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIucmVzZXQoKTtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXIoKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVjcmVhdGUoKTogdm9pZCB7XG4gICAgdGhpcy52aWV3cG9ydFN1Yj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnZpZXdwb3J0U3ViID0gbnVsbDtcblxuICAgIHRoaXMuZGVzdHJveUFsbFZpZXdzKCk7XG5cbiAgICB0aGlzLmhvc3RSZWY/LmRlc3Ryb3koKTtcbiAgICB0aGlzLmhvc3RSZWYgPSBudWxsO1xuXG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbnN1cmVJbml0aWFsaXplZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5ob3N0UmVmKSByZXR1cm47XG5cbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmhvc3QubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCB0b3RhbCA9IGNvZXJjZVRvdGFsRWxlbWVudHModGhpcy5jZXJpb3VzU2Nyb2xsVG90YWxFbGVtZW50cywgdGhpcy5jZXJpb3VzU2Nyb2xsSXRlbXM/Lmxlbmd0aCA/PyBudWxsKTtcblxuICAgIHRoaXMuaG9zdFJlZiA9IHRoaXMuY2VyaW91cy5jcmVhdGVIb3N0KGNvbnRhaW5lciwgdG90YWwsIHRoaXMuY2VyaW91c1Njcm9sbE9wdGlvbnMsIHRoaXMubmdab25lLCAoKSA9PiB7XG4gICAgICAvLyBDb2FsZXNjZSBzY3JvbGwtZHJpdmVuIHJlbmRlcnMgdG8gb25lIHBlciBmcmFtZSAodGhlIG5hdGl2ZSBzY3JvbGxiYXJcbiAgICAgIC8vIGNhbiBmaXJlIG1hbnkgc2Nyb2xsIGV2ZW50cyBiZXR3ZWVuIHBhaW50cykuXG4gICAgICBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcikgdGhpcy5zY2hlZHVsZVJlbmRlcigpO1xuICAgIH0pO1xuXG4gICAgdGhpcy52aWV3cG9ydFN1YiA9IHRoaXMuaG9zdFJlZi52aWV3cG9ydENoYW5nZXMkLnN1YnNjcmliZSgoZGV0YWlsOiBDZXJpb3VzVmlld3BvcnRDaGFuZ2VEZXRhaWwpID0+IHtcbiAgICAgIC8vIFNraXAgdGhlIGdsb2JhbCB0aWNrIHdoZW4gbm9ib2R5IGlzIGJvdW5kIHRvIHRoZSBvdXRwdXQuXG4gICAgICBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsVmlld3BvcnRDaGFuZ2Uub2JzZXJ2ZWQpIHtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHRoaXMuY2VyaW91c1Njcm9sbFZpZXdwb3J0Q2hhbmdlLmVtaXQoZGV0YWlsKSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmNlcmlvdXNTY3JvbGxSZWFkeS5lbWl0KHRoaXMuaG9zdFJlZi5zY3JvbGxlcik7XG5cbiAgICBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcikge1xuICAgICAgcXVldWVNaWNyb3Rhc2soKCkgPT4gdGhpcy5yZW5kZXIoKSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRJdGVtRm9ySW5kZXgoaW5kZXg6IG51bWJlcik6IFRJdGVtIHtcbiAgICBjb25zdCBnZXR0ZXIgPSB0aGlzLmNlcmlvdXNTY3JvbGxHZXRJdGVtO1xuICAgIGlmIChnZXR0ZXIpIHJldHVybiBnZXR0ZXIoaW5kZXgpO1xuXG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLmNlcmlvdXNTY3JvbGxJdGVtcztcbiAgICBpZiAoIWl0ZW1zKSByZXR1cm4gdW5kZWZpbmVkIGFzIFRJdGVtO1xuXG4gICAgcmV0dXJuIGl0ZW1zW2luZGV4XTtcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyVGVtcGxhdGVJbnRvQ29udGFpbmVyKFxuICAgIHRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlQ29udGV4dDxUSXRlbT4+LFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgZWxlbWVudENvbnRhaW5lcjogSFRNTEVsZW1lbnRcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgcHJldmlvdXMgPSB0aGlzLnZpZXdCeUNvbnRhaW5lci5nZXQoZWxlbWVudENvbnRhaW5lcik7XG4gICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAvLyBSZWN5Y2xlOiB1cGRhdGUgdGhlIGJvdW5kIGNvbnRleHQgYW5kIHJ1biBsb2NhbCBDRCBpbnN0ZWFkIG9mXG4gICAgICAvLyBkZXN0cm95aW5nIHRoZSBlbWJlZGRlZCB2aWV3IGFuZCByZWJ1aWxkaW5nIHRoZSBlbnRpcmUgcm93IHRyZWUuXG4gICAgICBjb25zdCBpdGVtID0gdGhpcy5nZXRJdGVtRm9ySW5kZXgoaW5kZXgpO1xuICAgICAgcHJldmlvdXMuY29udGV4dC4kaW1wbGljaXQgPSBpdGVtO1xuICAgICAgcHJldmlvdXMuY29udGV4dC5pdGVtID0gaXRlbTtcbiAgICAgIHByZXZpb3VzLmNvbnRleHQuaW5kZXggPSBpbmRleDtcbiAgICAgIC8vIFRoZSBjb3JlIGVuZ2luZSB3aXBlcyBlbGVtZW50Q29udGFpbmVyLnRleHRDb250ZW50IHdoZW4gcmV1c2luZyBpdCBmcm9tXG4gICAgICAvLyBpdHMgcG9vbCwgb3JwaGFuaW5nIHRoZSB2aWV3J3Mgcm9vdCBub2Rlcy4gUmUtYXBwZW5kIHRoZW0gZGVmZW5zaXZlbHkuXG4gICAgICBpZiAocHJldmlvdXMucm9vdE5vZGVzLmxlbmd0aCAmJiBwcmV2aW91cy5yb290Tm9kZXNbMF0ucGFyZW50Tm9kZSAhPT0gZWxlbWVudENvbnRhaW5lcikge1xuICAgICAgICBmb3IgKGNvbnN0IG5vZGUgb2YgcHJldmlvdXMucm9vdE5vZGVzKSB7XG4gICAgICAgICAgZWxlbWVudENvbnRhaW5lci5hcHBlbmRDaGlsZChub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcHJldmlvdXMuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFRyeSB0byByZXVzZSBhIHBvb2xlZCB2aWV3IGZyb20gYSBjb250YWluZXIgdGhhdCBzY3JvbGxlZCBvdXQgb2Ygdmlld3BvcnQuXG4gICAgY29uc3QgcG9vbGVkID0gdGhpcy5mcmVlVmlld3MucG9wKCk7XG4gICAgaWYgKHBvb2xlZCkge1xuICAgICAgY29uc3QgaXRlbSA9IHRoaXMuZ2V0SXRlbUZvckluZGV4KGluZGV4KTtcbiAgICAgIHBvb2xlZC5jb250ZXh0LiRpbXBsaWNpdCA9IGl0ZW07XG4gICAgICBwb29sZWQuY29udGV4dC5pdGVtID0gaXRlbTtcbiAgICAgIHBvb2xlZC5jb250ZXh0LmluZGV4ID0gaW5kZXg7XG4gICAgICBlbGVtZW50Q29udGFpbmVyLnRleHRDb250ZW50ID0gJyc7XG4gICAgICBmb3IgKGNvbnN0IG5vZGUgb2YgcG9vbGVkLnJvb3ROb2Rlcykge1xuICAgICAgICBlbGVtZW50Q29udGFpbmVyLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgICAgfVxuICAgICAgcG9vbGVkLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHRoaXMudmlld0J5Q29udGFpbmVyLnNldChlbGVtZW50Q29udGFpbmVyLCBwb29sZWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIE5vIHByaW9yIHZpZXcgZm9yIHRoaXMgY29udGFpbmVyOiBjcmVhdGUgb25lLlxuICAgIC8vIEVudGVyIHRoZSBBbmd1bGFyIHpvbmUgc28gdGhlIG5ldyB2aWV3J3MgdGVtcGxhdGUgZXZlbnQgbGlzdGVuZXJzXG4gICAgLy8gKChjbGljayksIChpbnB1dCksIGV0Yy4pIGFyZSB6b25lLXBhdGNoZWQuIFRoaXMgcGF0aCBydW5zIGF0IG1vc3RcbiAgICAvLyBvbmNlIHBlciB2aXNpYmxlIHJvdyAoYWZ0ZXIgdGhhdCwgdGhlIHZpZXcgaXMgcmVjeWNsZWQgZnJvbSB0aGUgcG9vbCkuXG4gICAgZWxlbWVudENvbnRhaW5lci50ZXh0Q29udGVudCA9ICcnO1xuXG4gICAgY29uc3QgaXRlbSA9IHRoaXMuZ2V0SXRlbUZvckluZGV4KGluZGV4KTtcbiAgICBjb25zdCB2aWV3ID0gdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgIGNvbnN0IHYgPSB0ZW1wbGF0ZS5jcmVhdGVFbWJlZGRlZFZpZXcoeyAkaW1wbGljaXQ6IGl0ZW0sIGl0ZW0sIGluZGV4IH0pO1xuICAgICAgdGhpcy5hcHBSZWYuYXR0YWNoVmlldyh2KTtcbiAgICAgIHYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgcmV0dXJuIHY7XG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygdmlldy5yb290Tm9kZXMpIHtcbiAgICAgIGVsZW1lbnRDb250YWluZXIuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgfVxuXG4gICAgdGhpcy52aWV3QnlDb250YWluZXIuc2V0KGVsZW1lbnRDb250YWluZXIsIHZpZXcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgYm91bmQgaXRlbS9pbmRleCBvbiBldmVyeSBjdXJyZW50bHktcmVuZGVyZWQgcm93J3MgZW1iZWRkZWQgdmlld1xuICAgKiBhbmQgcnVuIGNoYW5nZSBkZXRlY3Rpb24sIHdpdGhvdXQgcmVjcmVhdGluZyB0aGUgdmlld3MuIFVzZWQgd2hlbiB0aGUgZGF0YVxuICAgKiByZWZlcmVuY2UgY2hhbmdlcyBidXQgdGhlIHZpc2libGUgaW5kaWNlcyAoYW5kIHRoZWlyIGhlaWdodHMpIGRvIG5vdCwgc28gcm93XG4gICAqIHN0YXRlIChmb2N1cywgc2VsZWN0aW9uLCBvcGVuIGRyb3Bkb3ducykgc3Vydml2ZXMgdGhlIHVwZGF0ZS5cbiAgICovXG4gIC8qKlxuICAgKiBSZS1iaW5kIGVhY2ggY3VycmVudGx5IHJlbmRlcmVkIHJvdydzIGNvbnRleHQgKGZyb20gdGhlIGN1cnJlbnQgaXRlbXMvZ2V0dGVyKVxuICAgKiBhbmQgcnVuIGNoYW5nZSBkZXRlY3Rpb24gb24gaXRzIGVtYmVkZGVkIHZpZXcuIFVzZSB0aGlzIGFmdGVyIG11dGF0aW5nIHJvd1xuICAgKiBzdGF0ZSBpbiBwbGFjZSAoZS5nLiBzZWxlY3Rpb24gZmxhZ3MpIG9yIGNvbHVtbi1sZXZlbCBzdGF0ZSByZWFkIGJ5IHRoZSByb3dcbiAgICogdGVtcGxhdGUsIHdoZW4gcm93IGlkZW50aXR5IGFuZCB2aXNpYmxlIGluZGljZXMgaGF2ZSBub3QgY2hhbmdlZC4gQ2hlYXBcbiAgICogcmVsYXRpdmUgdG8gYHJlbmRlcigpYCDigJQgZG9lcyBub3QgaW52b2tlIHRoZSBlbmdpbmUncyBtZWFzdXJlbWVudCBwYXNzLlxuICAgKi9cbiAgcmVmcmVzaFJlbmRlcmVkQ29udGVudCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaG9zdFJlZikgcmV0dXJuO1xuICAgIGNvbnN0IHNjcm9sbGVyID0gdGhpcy5ob3N0UmVmLnNjcm9sbGVyO1xuXG4gICAgZm9yIChjb25zdCBpbmRleCBvZiBzY3JvbGxlci5nZXRSZW5kZXJlZEluZGljZXMoKSkge1xuICAgICAgY29uc3QgY29udGFpbmVyID0gc2Nyb2xsZXIuZ2V0UmVuZGVyZWRFbGVtZW50KGluZGV4KTtcbiAgICAgIGlmICghY29udGFpbmVyKSBjb250aW51ZTtcblxuICAgICAgY29uc3QgdmlldyA9IHRoaXMudmlld0J5Q29udGFpbmVyLmdldChjb250YWluZXIpO1xuICAgICAgaWYgKCF2aWV3KSBjb250aW51ZTtcblxuICAgICAgY29uc3QgaXRlbSA9IHRoaXMuZ2V0SXRlbUZvckluZGV4KGluZGV4KTtcbiAgICAgIHZpZXcuY29udGV4dC4kaW1wbGljaXQgPSBpdGVtO1xuICAgICAgdmlldy5jb250ZXh0Lml0ZW0gPSBpdGVtO1xuICAgICAgdmlldy5jb250ZXh0LmluZGV4ID0gaW5kZXg7XG4gICAgICB2aWV3LmRldGVjdENoYW5nZXMoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGRlc3Ryb3lBbGxWaWV3cygpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IHZpZXcgb2YgdGhpcy52aWV3QnlDb250YWluZXIudmFsdWVzKCkpIHtcbiAgICAgIHRoaXMuYXBwUmVmLmRldGFjaFZpZXcodmlldyk7XG4gICAgICB2aWV3LmRlc3Ryb3koKTtcbiAgICB9XG4gICAgdGhpcy52aWV3QnlDb250YWluZXIuY2xlYXIoKTtcbiAgICBmb3IgKGNvbnN0IHZpZXcgb2YgdGhpcy5mcmVlVmlld3MpIHtcbiAgICAgIHRoaXMuYXBwUmVmLmRldGFjaFZpZXcodmlldyk7XG4gICAgICB2aWV3LmRlc3Ryb3koKTtcbiAgICB9XG4gICAgdGhpcy5mcmVlVmlld3MubGVuZ3RoID0gMDtcbiAgfVxufVxuIl19
439
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VyaW91cy1zY3JvbGwuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWNlcmlvdXMtc2Nyb2xsL3NyYy9saWIvY2VyaW91cy1zY3JvbGwuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFHTCxTQUFTLEVBR1QsWUFBWSxFQUNaLEtBQUssRUFJTCxNQUFNLEdBR1AsTUFBTSxlQUFlLENBQUM7OztBQWF2QixTQUFTLG1CQUFtQixDQUFDLGFBQXdDLEVBQUUsUUFBbUM7SUFDeEcsTUFBTSxTQUFTLEdBQUcsT0FBTyxhQUFhLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLE9BQU8sUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDMUgsSUFBSSxTQUFTLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUN2RCxNQUFNLElBQUksS0FBSyxDQUFDLHVGQUF1RixDQUFDLENBQUM7SUFDM0csQ0FBQztJQUNELHdDQUF3QztJQUN4QyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ2hDLENBQUM7QUFNRCxNQUFNLE9BQU8sc0JBQXNCO0lBa0RqQyxZQUNtQixJQUE2QixFQUM3QixNQUFzQixFQUN0QixNQUFjLEVBQ2QsT0FBNkI7UUFIN0IsU0FBSSxHQUFKLElBQUksQ0FBeUI7UUFDN0IsV0FBTSxHQUFOLE1BQU0sQ0FBZ0I7UUFDdEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFlBQU8sR0FBUCxPQUFPLENBQXNCO1FBckRoRCxtRkFBbUY7UUFDMUUsK0JBQTBCLEdBQWtCLElBQUksQ0FBQztRQUUxRCxpREFBaUQ7UUFDeEMsdUJBQWtCLEdBQTRCLElBQUksQ0FB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TSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIEFwcGxpY2F0aW9uUmVmLFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIEVtYmVkZGVkVmlld1JlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgTmdab25lLFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzLFxuICBUZW1wbGF0ZVJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7XG4gIHR5cGUgQ2VyaW91c1Njcm9sbE9wdGlvbnMsXG4gIHR5cGUgRWxlbWVudFJlbmRlcmVyLFxuICB0eXBlIE1lYXN1cmVkVmlld3BvcnRSYW5nZSxcbn0gZnJvbSAnQGNlcmlvdXNkZXZ0ZWNoL2NlcmlvdXMtc2Nyb2xsJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgdHlwZSB7IENlcmlvdXNWaWV3cG9ydENoYW5nZURldGFpbCB9IGZyb20gJy4vY2VyaW91cy1zY3JvbGwudHlwZXMnO1xuaW1wb3J0IHR5cGUgeyBDZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlQ29udGV4dCB9IGZyb20gJy4vY2VyaW91cy1zY3JvbGwtaXRlbS10ZW1wbGF0ZS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgdHlwZSBDZXJpb3VzU2Nyb2xsSG9zdFJlZiwgQ2VyaW91c1Njcm9sbFNlcnZpY2UgfSBmcm9tICcuL2NlcmlvdXMtc2Nyb2xsLnNlcnZpY2UnO1xuXG5mdW5jdGlvbiBjb2VyY2VUb3RhbEVsZW1lbnRzKGV4cGxpY2l0VG90YWw6IG51bWJlciB8IG51bGwgfCB1bmRlZmluZWQsIGl0ZW1zTGVuOiBudW1iZXIgfCBudWxsIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcbiAgY29uc3QgY2FuZGlkYXRlID0gdHlwZW9mIGV4cGxpY2l0VG90YWwgPT09ICdudW1iZXInID8gZXhwbGljaXRUb3RhbCA6IHR5cGVvZiBpdGVtc0xlbiA9PT0gJ251bWJlcicgPyBpdGVtc0xlbiA6IHVuZGVmaW5lZDtcbiAgaWYgKGNhbmRpZGF0ZSA9PT0gdW5kZWZpbmVkIHx8IE51bWJlci5pc05hTihjYW5kaWRhdGUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDZXJpb3VzU2Nyb2xsRGlyZWN0aXZlOiBwcm92aWRlIGBjZXJpb3VzU2Nyb2xsVG90YWxFbGVtZW50c2Agb3IgYGNlcmlvdXNTY3JvbGxJdGVtc2AuJyk7XG4gIH1cbiAgLy8gQ2VyaW91c1Njcm9sbCBjdXJyZW50bHkgcmVxdWlyZXMgPj0gMVxuICByZXR1cm4gTWF0aC5tYXgoMSwgY2FuZGlkYXRlKTtcbn1cblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2NlcmlvdXNTY3JvbGxdJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgQ2VyaW91c1Njcm9sbERpcmVjdGl2ZTxUSXRlbSA9IHVua25vd24+IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICAvKiogVG90YWwgbnVtYmVyIG9mIGl0ZW1zLiBJZiBvbWl0dGVkLCBkZXJpdmVkIGZyb20gYGNlcmlvdXNTY3JvbGxJdGVtcy5sZW5ndGhgLiAqL1xuICBASW5wdXQoKSBjZXJpb3VzU2Nyb2xsVG90YWxFbGVtZW50czogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIE9wdGlvbmFsIGl0ZW1zIGFycmF5IChlbmFibGVzIGBsZXQtaXRlbWApLiAqL1xuICBASW5wdXQoKSBjZXJpb3VzU2Nyb2xsSXRlbXM6IHJlYWRvbmx5IFRJdGVtW10gfCBudWxsID0gbnVsbDtcblxuICAvKiogT3B0aW9uYWwgZ2V0dGVyIGZvciBsYXJnZSBkYXRhc2V0cyAoYWx0ZXJuYXRpdmUgdG8gcGFzc2luZyBmdWxsIGBpdGVtc2ApLiAqL1xuICBASW5wdXQoKSBjZXJpb3VzU2Nyb2xsR2V0SXRlbTogKChpbmRleDogbnVtYmVyKSA9PiBUSXRlbSkgfCBudWxsID0gbnVsbDtcblxuICAvKiogVGVtcGxhdGUgdXNlZCB0byByZW5kZXIgZWFjaCByb3cuICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGU6IFRlbXBsYXRlUmVmPENlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGVDb250ZXh0PFRJdGVtPj4gfCBudWxsID0gbnVsbDtcblxuICAvKipcbiAgICogVGFibGUgbW9kZSBvbmx5OiB0ZW1wbGF0ZSByZW5kZXJlZCBpbnRvIHRoZSBlbmdpbmUncyBgPHRoZWFkPmAgKGEgYDx0cj5gIG9mXG4gICAqIGA8dGg+YHMpLiBJdCBsaXZlcyBpbiB0aGUgc2FtZSBgPHRhYmxlPmAgYXMgdGhlIHJvd3MsIHNvIGNvbHVtbnMgYWxpZ25cbiAgICogbmF0aXZlbHkuIFVwZGF0ZXMgdmlhIGNoYW5nZSBkZXRlY3Rpb24gbGlrZSB0aGUgcm93cy5cbiAgICovXG4gIEBJbnB1dCgpIGNlcmlvdXNTY3JvbGxIZWFkZXJUZW1wbGF0ZTogVGVtcGxhdGVSZWY8dW5rbm93bj4gfCBudWxsID0gbnVsbDtcblxuICAvKiogT3B0aW9ucyBwYXNzZWQgdG8gYG5ldyBDZXJpb3VzU2Nyb2xsKC4uLilgLiAqL1xuICBASW5wdXQoKSBjZXJpb3VzU2Nyb2xsT3B0aW9uczogQ2VyaW91c1Njcm9sbE9wdGlvbnMgPSB7fTtcblxuICAvKiogQXV0b21hdGljYWxseSBjYWxsIHJlbmRlciBhZnRlciBlYWNoIHNjcm9sbCBldmVudC4gRGVmYXVsdDogdHJ1ZSAqL1xuICBASW5wdXQoKSBjZXJpb3VzU2Nyb2xsQXV0b1JlbmRlciA9IHRydWU7XG5cbiAgLyoqIEVtaXRzIGBjZXJpb3VzLXZpZXdwb3J0LWNoYW5nZWAgZGV0YWlsLiAqL1xuICBAT3V0cHV0KCkgY2VyaW91c1Njcm9sbFZpZXdwb3J0Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxDZXJpb3VzVmlld3BvcnRDaGFuZ2VEZXRhaWw+KCk7XG5cbiAgLyoqIEVtaXRzIHRoZSBsYXN0IG1lYXN1cmVkIHZpZXdwb3J0IGFmdGVyIGVhY2ggcmVuZGVyIHBhc3MuICovXG4gIEBPdXRwdXQoKSBjZXJpb3VzU2Nyb2xsTWVhc3VyZWRWaWV3cG9ydCA9IG5ldyBFdmVudEVtaXR0ZXI8TWVhc3VyZWRWaWV3cG9ydFJhbmdlPigpO1xuXG4gIC8qKiBFbWl0cyBvbmNlIHRoZSB1bmRlcmx5aW5nIGBDZXJpb3VzU2Nyb2xsYCBpbnN0YW5jZSBpcyByZWFkeS4gKi9cbiAgQE91dHB1dCgpIGNlcmlvdXNTY3JvbGxSZWFkeSA9IG5ldyBFdmVudEVtaXR0ZXI8Q2VyaW91c1Njcm9sbEhvc3RSZWZbJ3Njcm9sbGVyJ10+KCk7XG5cbiAgcHJpdmF0ZSBob3N0UmVmOiBDZXJpb3VzU2Nyb2xsSG9zdFJlZiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHZpZXdwb3J0U3ViOiBTdWJzY3JpcHRpb24gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBzY2hlZHVsZWRSZW5kZXJGcmFtZTogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSByZWFkb25seSB2aWV3QnlDb250YWluZXIgPSBuZXcgTWFwPEhUTUxFbGVtZW50LCBFbWJlZGRlZFZpZXdSZWY8Q2VyaW91c1Njcm9sbEl0ZW1UZW1wbGF0ZUNvbnRleHQ8VEl0ZW0+Pj4oKTtcbiAgLy8gUG9vbCBvZiB2aWV3cyBkZXRhY2hlZCBiZWNhdXNlIHRoZWlyIGNvbnRhaW5lciBsZWZ0IHRoZSB2aWV3cG9ydC4gUmV1c2luZ1xuICAvLyB0aGVtIG9uIHN1YnNlcXVlbnQgcmVuZGVycyBhdm9pZHMgZGVzdHJveWluZyArIHJlY3JlYXRpbmcgdGhlIGVudGlyZSByb3dcbiAgLy8gY29tcG9uZW50IHRyZWUgb24gZmFzdCBzY3JvbGxzICh3aGVyZSB0aGUgZW5naW5lJ3MgZWxlbWVudCBwb29sIHdpcGVzXG4gIC8vIHRleHRDb250ZW50IG9uIHJldXNlZCBjb250YWluZXJzLCBzbyB2aWV3IHJvb3ROb2RlcyBnZXQgb3JwaGFuZWQpLlxuICBwcml2YXRlIHJlYWRvbmx5IGZyZWVWaWV3czogRW1iZWRkZWRWaWV3UmVmPENlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGVDb250ZXh0PFRJdGVtPj5bXSA9IFtdO1xuXG4gIC8vIFRhYmxlIG1vZGU6IHRoZSBlbWJlZGRlZCB2aWV3IG9mIHRoZSBkZWNsYXJhdGl2ZSBoZWFkZXIsIHJlbmRlcmVkIGludG8gdGhlXG4gIC8vIGVuZ2luZSdzIDx0aGVhZD4uXG4gIHByaXZhdGUgaGVhZGVyVmlldzogRW1iZWRkZWRWaWV3UmVmPHVua25vd24+IHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFwcFJlZjogQXBwbGljYXRpb25SZWYsXG4gICAgcHJpdmF0ZSByZWFkb25seSBuZ1pvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNlcmlvdXM6IENlcmlvdXNTY3JvbGxTZXJ2aWNlXG4gICkge31cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5lbnN1cmVJbml0aWFsaXplZCgpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmICghdGhpcy5ob3N0UmVmKSByZXR1cm47XG5cbiAgICBpZiAoY2hhbmdlc1snY2VyaW91c1Njcm9sbEl0ZW1zJ10gfHwgY2hhbmdlc1snY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHMnXSkge1xuICAgICAgY29uc3QgdG90YWwgPSBjb2VyY2VUb3RhbEVsZW1lbnRzKHRoaXMuY2VyaW91c1Njcm9sbFRvdGFsRWxlbWVudHMsIHRoaXMuY2VyaW91c1Njcm9sbEl0ZW1zPy5sZW5ndGggPz8gbnVsbCk7XG4gICAgICBjb25zdCBjb3VudENoYW5nZWQgPSB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIudG90YWxFbGVtZW50cyAhPT0gdG90YWw7XG5cbiAgICAgIGlmIChjb3VudENoYW5nZWQpIHtcbiAgICAgICAgLy8gVGhlIGRhdGFzZXQgc2l6ZSBjaGFuZ2VkOiB0aGUgVmlld3BvcnRSZW5kZXJlciBzdG9yZXMgaXRzIG93biBjb3B5IG9mXG4gICAgICAgIC8vIHRvdGFsRWxlbWVudHMgKHNldCBieSB2YWx1ZSBhdCBjb25zdHJ1Y3Rpb24pIHNvIHBhdGNoaW5nIHRoZSBlbmdpbmUnc1xuICAgICAgICAvLyBwdWJsaWMgcHJvcGVydHkgYWxvbmUgbGVhdmVzIHRoZSByZW5kZXJlcidzIGludGVybmFsIGJvdW5kIHN0YWxlLiAgVGhlXG4gICAgICAgIC8vIHJlbmRlcmVyIHdvdWxkIHRoZW4gdXNlIHRoZSBvbGQgY291bnQgZm9yIGl0cyB2aWV3cG9ydC1maWxsIGxvb3AgYW5kXG4gICAgICAgIC8vIGJvdHRvbS1ib3VuZGFyeSBzY2FuLCBwcm9kdWNpbmcgcGhhbnRvbSByZW5kZXJzIGF0IG91dC1vZi1ib3VuZHNcbiAgICAgICAgLy8gaW5kaWNlcyAodW5kZWZpbmVkIGl0ZW1zIOKGkiAwLWhlaWdodCByb3dzIOKGkiB0aGUgZmlsbCBsb29wIG5ldmVyXG4gICAgICAgIC8vIHNhdGlzZmllcyBpdHMgaGVpZ2h0IGNvbmRpdGlvbiDihpIgaHVuZHJlZHMgb2YgcmVuZGVyZXIgY2FsbGJhY2tzKS5cbiAgICAgICAgLy8gUmVjcmVhdGluZyB0aGUgZW5naW5lIGdpdmVzIGJvdGggdGhlIGVuZ2luZSBhbmQgdGhlIHJlbmRlcmVyIGEgZnJlc2gsXG4gICAgICAgIC8vIGNvbnNpc3RlbnQgY291bnQuICBlbnN1cmVJbml0aWFsaXplZCgpIHNjaGVkdWxlcyB0aGUgZmlyc3QgcmVuZGVyIHZpYVxuICAgICAgICAvLyBxdWV1ZU1pY3JvdGFzaywgd2hpY2ggcnVucyBhZnRlciB0aGUgY3VycmVudCBDRCBjeWNsZSBjb21wbGV0ZXMuXG4gICAgICAgIHRoaXMucmVjcmVhdGUoKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcikge1xuICAgICAgICAvLyBTYW1lIGNvdW50LCBuZXcgZGF0YSByZWZlcmVuY2UgKGUuZy4gYW4gaW1tdXRhYmxlIGVkaXQgb3IgYSBzb3J0IHRoYXRcbiAgICAgICAgLy8gaGFwcGVucyB0byBrZWVwIHRoZSBzYW1lIGxlbmd0aCkuIFRoZSBlbmdpbmUgcmV1c2VzIHRoZSBET00gZWxlbWVudCBpdFxuICAgICAgICAvLyBhbHJlYWR5IHJlbmRlcmVkIGZvciBlYWNoIG92ZXJsYXBwaW5nIGluZGV4IHdpdGhvdXQgcmUtaW52b2tpbmcgdGhlXG4gICAgICAgIC8vIHJlbmRlcmVyLCBzbyB1cGRhdGUgdGhlIGNvbnRlbnQgb2YgZXZlcnkgY3VycmVudGx5LXZpc2libGUgcm93IElOXG4gICAgICAgIC8vIFBMQUNFIGJlZm9yZSBjYWxsaW5nIHJlbmRlcigpLiAgVGhpcyBwcmVzZXJ2ZXMgZWFjaCByb3cncyBlbWJlZGRlZFxuICAgICAgICAvLyB2aWV3IChzbyBhIGZvY3VzZWQgdGV4dGJveCBrZWVwcyBmb2N1cy9jYXJldCkgYW5kIGRvZXMgTk9UIGRpc2NhcmRcbiAgICAgICAgLy8gY2FjaGVkIGhlaWdodHMuIElmIGEgcm93J3MgaGVpZ2h0IGFjdHVhbGx5IGNoYW5nZXMgdGhlIGVuZ2luZSdzXG4gICAgICAgIC8vIFJlc2l6ZU9ic2VydmVyIGtlZXBzIHRoZSBjYWNoZSBjb3JyZWN0IG9uIGl0cyBvd247IGZvciBhIHdob2xlc2FsZVxuICAgICAgICAvLyBoZWlnaHQgY2hhbmdlIGFjcm9zcyBhbGwgcm93cywgY2FsbCByZWNhbGN1bGF0ZSgpIGluc3RlYWQuXG4gICAgICAgIHRoaXMucmVmcmVzaFJlbmRlcmVkQ29udGVudCgpO1xuICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsT3B0aW9ucyddICYmICFjaGFuZ2VzWydjZXJpb3VzU2Nyb2xsT3B0aW9ucyddLmZpcnN0Q2hhbmdlKSB7XG4gICAgICAvLyBPcHRpb25zIGFyZSBjb25zdW1lZCBwcmltYXJpbHkgYXQgY29uc3RydWN0aW9uIHRpbWUuXG4gICAgICB0aGlzLnJlY3JlYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2NoZWR1bGVkUmVuZGVyRnJhbWUgIT0gbnVsbCkge1xuICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5zY2hlZHVsZWRSZW5kZXJGcmFtZSk7XG4gICAgICB0aGlzLnNjaGVkdWxlZFJlbmRlckZyYW1lID0gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLnZpZXdwb3J0U3ViPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMudmlld3BvcnRTdWIgPSBudWxsO1xuXG4gICAgdGhpcy5kZXN0cm95QWxsVmlld3MoKTtcbiAgICB0aGlzLmhlYWRlclZpZXc/LmRlc3Ryb3koKTtcbiAgICB0aGlzLmhlYWRlclZpZXcgPSBudWxsO1xuXG4gICAgdGhpcy5ob3N0UmVmPy5kZXN0cm95KCk7XG4gICAgdGhpcy5ob3N0UmVmID0gbnVsbDtcbiAgfVxuXG4gIC8qKiBJbXBlcmF0aXZlbHkgdHJpZ2dlciBhIHJlbmRlciBwYXNzICh1c2VzIGBjZXJpb3VzU2Nyb2xsSXRlbVRlbXBsYXRlYCkuICovXG4gIHJlbmRlcigpOiBNZWFzdXJlZFZpZXdwb3J0UmFuZ2UgfCBudWxsIHtcbiAgICBpZiAoIXRoaXMuaG9zdFJlZikgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgdGVtcGxhdGUgPSB0aGlzLmNlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGU7XG4gICAgaWYgKCF0ZW1wbGF0ZSkgcmV0dXJuIG51bGw7XG5cbiAgICBjb25zdCBob3N0Q29udGFpbmVyID0gdGhpcy5ob3N0Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3QgaGVpZ2h0ID0gaG9zdENvbnRhaW5lci5jbGllbnRIZWlnaHQgfHwgaG9zdENvbnRhaW5lci5vZmZzZXRIZWlnaHQ7XG4gICAgY29uc3QgY29udGVudENvbnRhaW5lciA9IHRoaXMuaG9zdFJlZi5jb250ZW50RWxlbWVudDtcblxuICAgIC8vIFRyYWNrIHdoZXRoZXIgdGhlIGVuZ2luZSBhc2tlZCB1cyB0byBiaW5kIGFueSByb3cgdGhpcyBwYXNzLiBQdXJlIHNjcm9sbFxuICAgIC8vIGZyYW1lcyB3aGVyZSB0aGUgdmlzaWJsZSByb3cgc2V0IGRvZXNuJ3QgY2hhbmdlIHN0aWxsIGRyaXZlIHJlbmRlcigpIHZpYVxuICAgIC8vIHRoZSByQUYgY29hbGVzY2VyIOKAlCB0aGVyZSdzIG5vIHBvaW50IGluIHdhbGtpbmcgdGhlIHBydW5lIG1hcCBvclxuICAgIC8vIGVtaXR0aW5nIHRoZSB2aWV3cG9ydCByYW5nZSB3aGVuIG5vdGhpbmcgd2FzIHRvdWNoZWQuXG4gICAgbGV0IHJlbmRlcmVySW52b2NhdGlvbnMgPSAwO1xuICAgIGNvbnN0IHJlbmRlcmVyOiBFbGVtZW50UmVuZGVyZXIgPSAoaW5kZXgsIGVsZW1lbnRDb250YWluZXIpID0+IHtcbiAgICAgIHJlbmRlcmVySW52b2NhdGlvbnMrKztcbiAgICAgIC8vIFJlbmRlciBlYWNoIHJvdydzIGVtYmVkZGVkIHZpZXcgd2l0aCBMT0NBTCBjaGFuZ2UgZGV0ZWN0aW9uXG4gICAgICAvLyAoYHZpZXcuZGV0ZWN0Q2hhbmdlcygpYCBpbnNpZGUgYHJlbmRlclRlbXBsYXRlSW50b0NvbnRhaW5lcmApIHNvIHRoZVxuICAgICAgLy8gZW5naW5lIGNhbiBtZWFzdXJlIGl0cyBoZWlnaHQgZHVyaW5nIHRoaXMgcGFzcy4gRG8gTk9UIHdyYXAgZWFjaCByb3cgaW5cbiAgICAgIC8vIGl0cyBvd24gYG5nWm9uZS5ydW5gIOKAlCB0aGF0IGZpcmVzIGEgZnVsbCBgQXBwbGljYXRpb25SZWZgIHRpY2sgKnBlciByb3cqXG4gICAgICAvLyAoTyhuZXdSb3dzIMOXIHZpc2libGVSb3dzKSB3b3JrLCBqYW5reSBkcmFncykuIFRoZSBzaW5nbGUgY29hbGVzY2VkIHRpY2tcbiAgICAgIC8vIGZvciB0aGUgd2hvbGUgcGFzcyBpcyBoYW5kbGVkIGJ5IHRoZSBjYWxsZXIgKGBzY2hlZHVsZVJlbmRlcmApLlxuICAgICAgdGhpcy5yZW5kZXJUZW1wbGF0ZUludG9Db250YWluZXIodGVtcGxhdGUsIGluZGV4LCBlbGVtZW50Q29udGFpbmVyKTtcbiAgICB9O1xuXG4gICAgY29uc3QgcmFuZ2UgPSB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIucmVuZGVyVmlld3BvcnQoaGVpZ2h0LCBjb250ZW50Q29udGFpbmVyLCByZW5kZXJlcik7XG5cbiAgICBpZiAocmVuZGVyZXJJbnZvY2F0aW9ucyA9PT0gMCkge1xuICAgICAgLy8gVmlld3BvcnQgZGlkbid0IGNoYW5nZSDigJQgc2tpcCB0aGUgcHJ1bmUgd2FsayBhbmQgdGhlIChwb3RlbnRpYWxseVxuICAgICAgLy8gem9uZS1lbnRlcmluZykgZW1pdC5cbiAgICAgIHJldHVybiByYW5nZTtcbiAgICB9XG5cbiAgICAvLyBEZXN0cm95IHZpZXdzIHdob3NlIGNvbnRhaW5lciB0aGUgZW5naW5lIG5vIGxvbmdlciByZW5kZXJzLiBXaXRob3V0IHRoaXMsXG4gICAgLy8gZXZlcnkgY29udGFpbmVyIHRoZSBlbmdpbmUgcmVjeWNsZXMgaW50byBpdHMgZWxlbWVudCBwb29sIGxlYXZlcyBpdHNcbiAgICAvLyBlbWJlZGRlZCB2aWV3IGF0dGFjaGVkIHRvIEFwcGxpY2F0aW9uUmVmIGZvcmV2ZXIg4oCUIHNvIHRoZSBhdHRhY2hlZC12aWV3XG4gICAgLy8gbGlzdCAoYW5kIGV2ZXJ5IE8obikgYGRldGFjaFZpZXdgKSBncm93cyB3aXRob3V0IGJvdW5kIGFuZCBzY3JvbGxpbmcgZ2V0c1xuICAgIC8vIHByb2dyZXNzaXZlbHkgc2xvd2VyLiBNaXJyb3JzIHRoZSBSZWFjdC9WdWUgd3JhcHBlcnMsIHdoaWNoIGRyb3Agcm93cyB0aGF0XG4gICAgLy8gZmFsbCBvdXQgb2YgYGdldFJlbmRlcmVkSW5kaWNlcygpYC5cbiAgICB0aGlzLnBydW5lRGV0YWNoZWRWaWV3cygpO1xuXG4gICAgLy8gT25seSByZS1lbnRlciB0aGUgem9uZSAoYSBnbG9iYWwgdGljaykgaWYgc29tZW9uZSBpcyBhY3R1YWxseSBsaXN0ZW5pbmcuXG4gICAgaWYgKHRoaXMuY2VyaW91c1Njcm9sbE1lYXN1cmVkVmlld3BvcnQub2JzZXJ2ZWQpIHtcbiAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB0aGlzLmNlcmlvdXNTY3JvbGxNZWFzdXJlZFZpZXdwb3J0LmVtaXQocmFuZ2UpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJhbmdlO1xuICB9XG5cbiAgLyoqIFRlYXIgZG93biBlbWJlZGRlZCB2aWV3cyB3aG9zZSBjb250YWluZXIgaXMgbm8gbG9uZ2VyIHBhcnQgb2YgdGhlIHZpZXdwb3J0LiAqL1xuICBwcml2YXRlIHBydW5lRGV0YWNoZWRWaWV3cygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaG9zdFJlZiB8fCB0aGlzLnZpZXdCeUNvbnRhaW5lci5zaXplID09PSAwKSByZXR1cm47XG4gICAgY29uc3Qgc2Nyb2xsZXIgPSB0aGlzLmhvc3RSZWYuc2Nyb2xsZXI7XG4gICAgY29uc3QgYWN0aXZlID0gbmV3IFNldDxIVE1MRWxlbWVudD4oKTtcbiAgICBmb3IgKGNvbnN0IGluZGV4IG9mIHNjcm9sbGVyLmdldFJlbmRlcmVkSW5kaWNlcygpKSB7XG4gICAgICBjb25zdCBlbCA9IHNjcm9sbGVyLmdldFJlbmRlcmVkRWxlbWVudChpbmRleCk7XG4gICAgICBpZiAoZWwpIGFjdGl2ZS5hZGQoZWwpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IFtjb250YWluZXIsIHZpZXddIG9mIHRoaXMudmlld0J5Q29udGFpbmVyKSB7XG4gICAgICBpZiAoIWFjdGl2ZS5oYXMoY29udGFpbmVyKSkge1xuICAgICAgICAvLyBEZXRhY2ggRE9NIGJ1dCBrZWVwIHRoZSB2aWV3IGFsaXZlIGluIHRoZSBwb29sIGZvciBmdXR1cmUgcmV1c2UuXG4gICAgICAgIC8vIERlc3Ryb3lpbmcgKyByZWNyZWF0aW5nIHZpZXdzIHBlciBzY3JvbGwgc3RlcCBkb21pbmF0ZXMgZnJhbWUgdGltZS5cbiAgICAgICAgZm9yIChjb25zdCBub2RlIG9mIHZpZXcucm9vdE5vZGVzKSB7XG4gICAgICAgICAgaWYgKG5vZGUucGFyZW50Tm9kZSkgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudmlld0J5Q29udGFpbmVyLmRlbGV0ZShjb250YWluZXIpO1xuICAgICAgICB0aGlzLmZyZWVWaWV3cy5wdXNoKHZpZXcpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKiBBdXRvLXJlbmRlciBjb2FsZXNjZWQgdG8gYXQgbW9zdCBvbmNlIHBlciBhbmltYXRpb24gZnJhbWUuICovXG4gIHByaXZhdGUgc2NoZWR1bGVSZW5kZXIoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2NoZWR1bGVkUmVuZGVyRnJhbWUgIT0gbnVsbCkgcmV0dXJuO1xuICAgIHRoaXMuc2NoZWR1bGVkUmVuZGVyRnJhbWUgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgdGhpcy5zY2hlZHVsZWRSZW5kZXJGcmFtZSA9IG51bGw7XG4gICAgICAvLyBSdW4gcmVuZGVyKCkgT1VUU0lERSBBbmd1bGFyJ3Mgem9uZS4gQSBmdWxsIEFwcGxpY2F0aW9uUmVmLnRpY2soKSBvblxuICAgICAgLy8gZXZlcnkgc2Nyb2xsIGZyYW1lIGlzIHRoZSBwcmltYXJ5IEZQUyBib3R0bGVuZWNrOiBldmVuIHdoZW4gbm8gcm93c1xuICAgICAgLy8gY2hhbmdlIChwdXJlIHRyYW5zbGF0aW9uKSwgbmdab25lLnJ1bigpIGNhdXNlcyBBbmd1bGFyIHRvIHdhbGsgdGhlXG4gICAgICAvLyBlbnRpcmUgY29tcG9uZW50IHRyZWUuIEluc3RlYWQgd2UgY2FsbCB2aWV3LmRldGVjdENoYW5nZXMoKSBsb2NhbGx5XG4gICAgICAvLyBpbnNpZGUgcmVuZGVyVGVtcGxhdGVJbnRvQ29udGFpbmVyIGZvciBlYWNoIGFmZmVjdGVkIHJvdy4gWm9uZSBlbnRyeSBpc1xuICAgICAgLy8gb25seSBuZWVkZWQgd2hlbiBjcmVhdGluZyBhIGJyYW5kLW5ldyBlbWJlZGRlZCB2aWV3ICh0byB6b25lLXBhdGNoIGl0c1xuICAgICAgLy8gZXZlbnQgbGlzdGVuZXJzKSDigJQgcmVjeWNsZWQgYW5kIHBvb2xlZCB2aWV3cyB3ZXJlIGFscmVhZHkgY3JlYXRlZCBpbnNpZGVcbiAgICAgIC8vIHpvbmUgYW5kIHRoZWlyIGxpc3RlbmVycyByZW1haW4gem9uZS1hd2FyZS5cbiAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRGlzY2FyZCBhbGwgY2FjaGVkIHJvdyBoZWlnaHRzIGFuZCByZS1tZWFzdXJlIHRoZSB2aWV3cG9ydC5cbiAgICpcbiAgICogQ2FsbCB0aGlzIG9ubHkgd2hlbiB0aGUgaGVpZ2h0cyBvZiByb3dzIHlvdSd2ZSAqYWxyZWFkeSByZW5kZXJlZCogbWF5IGhhdmVcbiAgICogY2hhbmdlZCB3aXRob3V0IHRoZWlyIGluZGljZXMgY2hhbmdpbmcg4oCUIGUuZy4gYSBnbG9iYWwgZm9udC9kZW5zaXR5IGNoYW5nZSxcbiAgICogb3Igc3dhcHBpbmcgZXZlcnkgcm93IHRvIGEgZGlmZmVyZW50IGxheW91dC4gVGhpcyBmb3JjZXMgYSBzeW5jaHJvbm91c1xuICAgKiByZS1tZWFzdXJlIChvbmUgYG9mZnNldEhlaWdodGAgcmVhZCBwZXIgdmlzaWJsZSByb3cpLCBzbyBkbyBOT1QgY2FsbCBpdCBvblxuICAgKiByb3V0aW5lIGVkaXRzOiBhIHNpbmdsZSBjZWxsIGVkaXQga2VlcHMgaXRzIHJvdydzIHNpemUsIGFuZCB0aGUgZW5naW5lJ3NcbiAgICogUmVzaXplT2JzZXJ2ZXIgcGlja3MgdXAgYW55IGluY2lkZW50YWwgcmVzaXplIG9uIGl0cyBvd24uXG4gICAqL1xuICByZWNhbGN1bGF0ZSgpOiBNZWFzdXJlZFZpZXdwb3J0UmFuZ2UgfCBudWxsIHtcbiAgICBpZiAoIXRoaXMuaG9zdFJlZikgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgdGVtcGxhdGUgPSB0aGlzLmNlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGU7XG4gICAgaWYgKHRlbXBsYXRlKSB7XG4gICAgICAvLyBSZS1pbnZva2UgdGhlIHJlbmRlcmVyIGZvciBldmVyeSBjdXJyZW50bHktcmVuZGVyZWQgcm93IHNvIHBlbmRpbmdcbiAgICAgIC8vIEFuZ3VsYXIgYmluZGluZ3MgZmx1c2ggaW50byB0aGUgRE9NIGFuZCB0aGUgZW5naW5lIHJlLW1lYXN1cmVzIGVhY2hcbiAgICAgIC8vIHJvdydzIG5ldyBoZWlnaHQgaW50byBpdHMgY2FjaGUuIFdpdGhvdXQgdGhpcywgdGhlIGVuZ2luZSdzIHJlbmRlclxuICAgICAgLy8gcGFzcyBza2lwcyB0aGUgcmVuZGVyZXIgZm9yIGFscmVhZHktcmVuZGVyZWQgaW5kaWNlcyBhbmQgZmFsbHNcbiAgICAgIC8vIHRocm91Z2ggdG8gcmVhZGluZyBzdGFsZSBvZmZzZXRIZWlnaHQuXG4gICAgICB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIucmVmcmVzaFZpc2libGUoKGluZGV4LCBlbGVtZW50Q29udGFpbmVyKSA9PiB7XG4gICAgICAgIHRoaXMucmVuZGVyVGVtcGxhdGVJbnRvQ29udGFpbmVyKHRlbXBsYXRlLCBpbmRleCwgZWxlbWVudENvbnRhaW5lcik7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICAvKiogSnVtcCBkaXJlY3RseSB0byBhbiBlbGVtZW50IGluZGV4LCB0aGVuIHJlbmRlci4gKi9cbiAganVtcFRvRWxlbWVudChpbmRleDogbnVtYmVyKTogTWVhc3VyZWRWaWV3cG9ydFJhbmdlIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYpIHJldHVybiBudWxsO1xuICAgIHRoaXMuaG9zdFJlZi5zY3JvbGxlci5qdW1wVG9FbGVtZW50KGluZGV4KTtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXIoKTtcbiAgfVxuXG4gIC8qKiBTY3JvbGwgdG8gYSBwZXJjZW50YWdlICgwLi4xMDApLCB0aGVuIHJlbmRlci4gKi9cbiAgc2Nyb2xsVG9QZXJjZW50YWdlKHBlcmNlbnRhZ2U6IG51bWJlcik6IE1lYXN1cmVkVmlld3BvcnRSYW5nZSB8IG51bGwge1xuICAgIGlmICghdGhpcy5ob3N0UmVmKSByZXR1cm4gbnVsbDtcbiAgICB0aGlzLmhvc3RSZWYuc2Nyb2xsZXIuaGFuZGxlU2Nyb2xsUGVyY2VudGFnZShwZXJjZW50YWdlKTtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXIoKTtcbiAgfVxuXG4gIC8qKiBSZXNldCB0byB0aGUgdG9wLCB0aGVuIHJlbmRlci4gKi9cbiAgcmVzZXQoKTogTWVhc3VyZWRWaWV3cG9ydFJhbmdlIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLmhvc3RSZWYpIHJldHVybiBudWxsO1xuICAgIHRoaXMuaG9zdFJlZi5zY3JvbGxlci5yZXNldCgpO1xuICAgIHJldHVybiB0aGlzLnJlbmRlcigpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWNyZWF0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnZpZXdwb3J0U3ViPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMudmlld3BvcnRTdWIgPSBudWxsO1xuXG4gICAgdGhpcy5kZXN0cm95QWxsVmlld3MoKTtcblxuICAgIHRoaXMuaG9zdFJlZj8uZGVzdHJveSgpO1xuICAgIHRoaXMuaG9zdFJlZiA9IG51bGw7XG5cbiAgICB0aGlzLmVuc3VyZUluaXRpYWxpemVkKCk7XG4gIH1cblxuICBwcml2YXRlIGVuc3VyZUluaXRpYWxpemVkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmhvc3RSZWYpIHJldHVybjtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuaG9zdC5uYXRpdmVFbGVtZW50O1xuICAgIGNvbnN0IHRvdGFsID0gY29lcmNlVG90YWxFbGVtZW50cyh0aGlzLmNlcmlvdXNTY3JvbGxUb3RhbEVsZW1lbnRzLCB0aGlzLmNlcmlvdXNTY3JvbGxJdGVtcz8ubGVuZ3RoID8/IG51bGwpO1xuXG4gICAgLy8gVGFibGUgbW9kZTogY2FwdHVyZSB0aGUgZW5naW5lLWNyZWF0ZWQgPHRoZWFkPiBzbyB3ZSBjYW4gcmVuZGVyIHRoZVxuICAgIC8vIGRlY2xhcmF0aXZlIGhlYWRlciB0ZW1wbGF0ZSBpbnRvIGl0IChhbmQgc3RpbGwgcnVuIGFueSB1c2VyIGhlYWRlciBob29rKS5cbiAgICBsZXQgb3B0aW9ucyA9IHRoaXMuY2VyaW91c1Njcm9sbE9wdGlvbnM7XG4gICAgaWYgKG9wdGlvbnMubGF5b3V0ID09PSAndGFibGUnICYmIHRoaXMuY2VyaW91c1Njcm9sbEhlYWRlclRlbXBsYXRlKSB7XG4gICAgICBjb25zdCB1c2VySGVhZGVyID0gb3B0aW9ucy50YWJsZT8uaGVhZGVyO1xuICAgICAgb3B0aW9ucyA9IHtcbiAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgdGFibGU6IHtcbiAgICAgICAgICAuLi5vcHRpb25zLnRhYmxlLFxuICAgICAgICAgIGhlYWRlcjogKHRoZWFkOiBIVE1MVGFibGVTZWN0aW9uRWxlbWVudCkgPT4ge1xuICAgICAgICAgICAgdXNlckhlYWRlcj8uKHRoZWFkKTtcbiAgICAgICAgICAgIHRoaXMubW91bnRIZWFkZXIodGhlYWQpO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHRoaXMuaG9zdFJlZiA9IHRoaXMuY2VyaW91cy5jcmVhdGVIb3N0KGNvbnRhaW5lciwgdG90YWwsIG9wdGlvbnMsIHRoaXMubmdab25lLCAoKSA9PiB7XG4gICAgICAvLyBDb2FsZXNjZSBzY3JvbGwtZHJpdmVuIHJlbmRlcnMgdG8gb25lIHBlciBmcmFtZSAodGhlIG5hdGl2ZSBzY3JvbGxiYXJcbiAgICAgIC8vIGNhbiBmaXJlIG1hbnkgc2Nyb2xsIGV2ZW50cyBiZXR3ZWVuIHBhaW50cykuXG4gICAgICBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcikgdGhpcy5zY2hlZHVsZVJlbmRlcigpO1xuICAgIH0pO1xuXG4gICAgdGhpcy52aWV3cG9ydFN1YiA9IHRoaXMuaG9zdFJlZi52aWV3cG9ydENoYW5nZXMkLnN1YnNjcmliZSgoZGV0YWlsOiBDZXJpb3VzVmlld3BvcnRDaGFuZ2VEZXRhaWwpID0+IHtcbiAgICAgIC8vIFNraXAgdGhlIGdsb2JhbCB0aWNrIHdoZW4gbm9ib2R5IGlzIGJvdW5kIHRvIHRoZSBvdXRwdXQuXG4gICAgICBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsVmlld3BvcnRDaGFuZ2Uub2JzZXJ2ZWQpIHtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHRoaXMuY2VyaW91c1Njcm9sbFZpZXdwb3J0Q2hhbmdlLmVtaXQoZGV0YWlsKSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmNlcmlvdXNTY3JvbGxSZWFkeS5lbWl0KHRoaXMuaG9zdFJlZi5zY3JvbGxlcik7XG5cbiAgICBpZiAodGhpcy5jZXJpb3VzU2Nyb2xsQXV0b1JlbmRlcikge1xuICAgICAgcXVldWVNaWNyb3Rhc2soKCkgPT4gdGhpcy5yZW5kZXIoKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlciB0aGUgZGVjbGFyYXRpdmUgaGVhZGVyIHRlbXBsYXRlIGludG8gdGhlIGVuZ2luZSdzIDx0aGVhZD4uIE9uZVxuICAgKiBlbWJlZGRlZCB2aWV3LCBjcmVhdGVkIGluc2lkZSB0aGUgem9uZSAoc28gdGhlIGhlYWRlcidzIGV2ZW50IGJpbmRpbmdzIGFyZVxuICAgKiB6b25lLXBhdGNoZWQpLCBpdHMgcm9vdCBub2RlcyBhcHBlbmRlZCBkaXJlY3RseSBpbnRvIHRoZSA8dGhlYWQ+LlxuICAgKi9cbiAgcHJpdmF0ZSBtb3VudEhlYWRlcih0aGVhZDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY2VyaW91c1Njcm9sbEhlYWRlclRlbXBsYXRlKSByZXR1cm47XG4gICAgdGhpcy5oZWFkZXJWaWV3Py5kZXN0cm95KCk7XG4gICAgY29uc3QgdmlldyA9IHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICBjb25zdCB2ID0gdGhpcy5jZXJpb3VzU2Nyb2xsSGVhZGVyVGVtcGxhdGUhLmNyZWF0ZUVtYmVkZGVkVmlldyh7fSk7XG4gICAgICB0aGlzLmFwcFJlZi5hdHRhY2hWaWV3KHYpO1xuICAgICAgdi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICByZXR1cm4gdjtcbiAgICB9KTtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygdmlldy5yb290Tm9kZXMpIHRoZWFkLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgIHRoaXMuaGVhZGVyVmlldyA9IHZpZXc7XG4gIH1cblxuICBwcml2YXRlIGdldEl0ZW1Gb3JJbmRleChpbmRleDogbnVtYmVyKTogVEl0ZW0ge1xuICAgIGNvbnN0IGdldHRlciA9IHRoaXMuY2VyaW91c1Njcm9sbEdldEl0ZW07XG4gICAgaWYgKGdldHRlcikgcmV0dXJuIGdldHRlcihpbmRleCk7XG5cbiAgICBjb25zdCBpdGVtcyA9IHRoaXMuY2VyaW91c1Njcm9sbEl0ZW1zO1xuICAgIGlmICghaXRlbXMpIHJldHVybiB1bmRlZmluZWQgYXMgVEl0ZW07XG5cbiAgICByZXR1cm4gaXRlbXNbaW5kZXhdO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJUZW1wbGF0ZUludG9Db250YWluZXIoXG4gICAgdGVtcGxhdGU6IFRlbXBsYXRlUmVmPENlcmlvdXNTY3JvbGxJdGVtVGVtcGxhdGVDb250ZXh0PFRJdGVtPj4sXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBlbGVtZW50Q29udGFpbmVyOiBIVE1MRWxlbWVudFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBwcmV2aW91cyA9IHRoaXMudmlld0J5Q29udGFpbmVyLmdldChlbGVtZW50Q29udGFpbmVyKTtcbiAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgIC8vIFJlY3ljbGU6IHVwZGF0ZSB0aGUgYm91bmQgY29udGV4dCBhbmQgcnVuIGxvY2FsIENEIGluc3RlYWQgb2ZcbiAgICAgIC8vIGRlc3Ryb3lpbmcgdGhlIGVtYmVkZGVkIHZpZXcgYW5kIHJlYnVpbGRpbmcgdGhlIGVudGlyZSByb3cgdHJlZS5cbiAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLmdldEl0ZW1Gb3JJbmRleChpbmRleCk7XG4gICAgICBwcmV2aW91cy5jb250ZXh0LiRpbXBsaWNpdCA9IGl0ZW07XG4gICAgICBwcmV2aW91cy5jb250ZXh0Lml0ZW0gPSBpdGVtO1xuICAgICAgcHJldmlvdXMuY29udGV4dC5pbmRleCA9IGluZGV4O1xuICAgICAgLy8gVGhlIGNvcmUgZW5naW5lIHdpcGVzIGVsZW1lbnRDb250YWluZXIudGV4dENvbnRlbnQgd2hlbiByZXVzaW5nIGl0IGZyb21cbiAgICAgIC8vIGl0cyBwb29sLCBvcnBoYW5pbmcgdGhlIHZpZXcncyByb290IG5vZGVzLiBSZS1hcHBlbmQgdGhlbSBkZWZlbnNpdmVseS5cbiAgICAgIGlmIChwcmV2aW91cy5yb290Tm9kZXMubGVuZ3RoICYmIHByZXZpb3VzLnJvb3ROb2Rlc1swXS5wYXJlbnROb2RlICE9PSBlbGVtZW50Q29udGFpbmVyKSB7XG4gICAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBwcmV2aW91cy5yb290Tm9kZXMpIHtcbiAgICAgICAgICBlbGVtZW50Q29udGFpbmVyLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBwcmV2aW91cy5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVHJ5IHRvIHJldXNlIGEgcG9vbGVkIHZpZXcgZnJvbSBhIGNvbnRhaW5lciB0aGF0IHNjcm9sbGVkIG91dCBvZiB2aWV3cG9ydC5cbiAgICBjb25zdCBwb29sZWQgPSB0aGlzLmZyZWVWaWV3cy5wb3AoKTtcbiAgICBpZiAocG9vbGVkKSB7XG4gICAgICBjb25zdCBpdGVtID0gdGhpcy5nZXRJdGVtRm9ySW5kZXgoaW5kZXgpO1xuICAgICAgcG9vbGVkLmNvbnRleHQuJGltcGxpY2l0ID0gaXRlbTtcbiAgICAgIHBvb2xlZC5jb250ZXh0Lml0ZW0gPSBpdGVtO1xuICAgICAgcG9vbGVkLmNvbnRleHQuaW5kZXggPSBpbmRleDtcbiAgICAgIGVsZW1lbnRDb250YWluZXIudGV4dENvbnRlbnQgPSAnJztcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBwb29sZWQucm9vdE5vZGVzKSB7XG4gICAgICAgIGVsZW1lbnRDb250YWluZXIuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICB9XG4gICAgICBwb29sZWQuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgdGhpcy52aWV3QnlDb250YWluZXIuc2V0KGVsZW1lbnRDb250YWluZXIsIHBvb2xlZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gTm8gcHJpb3IgdmlldyBmb3IgdGhpcyBjb250YWluZXI6IGNyZWF0ZSBvbmUuXG4gICAgLy8gRW50ZXIgdGhlIEFuZ3VsYXIgem9uZSBzbyB0aGUgbmV3IHZpZXcncyB0ZW1wbGF0ZSBldmVudCBsaXN0ZW5lcnNcbiAgICAvLyAoKGNsaWNrKSwgKGlucHV0KSwgZXRjLikgYXJlIHpvbmUtcGF0Y2hlZC4gVGhpcyBwYXRoIHJ1bnMgYXQgbW9zdFxuICAgIC8vIG9uY2UgcGVyIHZpc2libGUgcm93IChhZnRlciB0aGF0LCB0aGUgdmlldyBpcyByZWN5Y2xlZCBmcm9tIHRoZSBwb29sKS5cbiAgICBlbGVtZW50Q29udGFpbmVyLnRleHRDb250ZW50ID0gJyc7XG5cbiAgICBjb25zdCBpdGVtID0gdGhpcy5nZXRJdGVtRm9ySW5kZXgoaW5kZXgpO1xuICAgIGNvbnN0IHZpZXcgPSB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgY29uc3QgdiA9IHRlbXBsYXRlLmNyZWF0ZUVtYmVkZGVkVmlldyh7ICRpbXBsaWNpdDogaXRlbSwgaXRlbSwgaW5kZXggfSk7XG4gICAgICB0aGlzLmFwcFJlZi5hdHRhY2hWaWV3KHYpO1xuICAgICAgdi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICByZXR1cm4gdjtcbiAgICB9KTtcblxuICAgIGZvciAoY29uc3Qgbm9kZSBvZiB2aWV3LnJvb3ROb2Rlcykge1xuICAgICAgZWxlbWVudENvbnRhaW5lci5hcHBlbmRDaGlsZChub2RlKTtcbiAgICB9XG5cbiAgICB0aGlzLnZpZXdCeUNvbnRhaW5lci5zZXQoZWxlbWVudENvbnRhaW5lciwgdmlldyk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIHRoZSBib3VuZCBpdGVtL2luZGV4IG9uIGV2ZXJ5IGN1cnJlbnRseS1yZW5kZXJlZCByb3cncyBlbWJlZGRlZCB2aWV3XG4gICAqIGFuZCBydW4gY2hhbmdlIGRldGVjdGlvbiwgd2l0aG91dCByZWNyZWF0aW5nIHRoZSB2aWV3cy4gVXNlZCB3aGVuIHRoZSBkYXRhXG4gICAqIHJlZmVyZW5jZSBjaGFuZ2VzIGJ1dCB0aGUgdmlzaWJsZSBpbmRpY2VzIChhbmQgdGhlaXIgaGVpZ2h0cykgZG8gbm90LCBzbyByb3dcbiAgICogc3RhdGUgKGZvY3VzLCBzZWxlY3Rpb24sIG9wZW4gZHJvcGRvd25zKSBzdXJ2aXZlcyB0aGUgdXBkYXRlLlxuICAgKi9cbiAgLyoqXG4gICAqIFJlLWJpbmQgZWFjaCBjdXJyZW50bHkgcmVuZGVyZWQgcm93J3MgY29udGV4dCAoZnJvbSB0aGUgY3VycmVudCBpdGVtcy9nZXR0ZXIpXG4gICAqIGFuZCBydW4gY2hhbmdlIGRldGVjdGlvbiBvbiBpdHMgZW1iZWRkZWQgdmlldy4gVXNlIHRoaXMgYWZ0ZXIgbXV0YXRpbmcgcm93XG4gICAqIHN0YXRlIGluIHBsYWNlIChlLmcuIHNlbGVjdGlvbiBmbGFncykgb3IgY29sdW1uLWxldmVsIHN0YXRlIHJlYWQgYnkgdGhlIHJvd1xuICAgKiB0ZW1wbGF0ZSwgd2hlbiByb3cgaWRlbnRpdHkgYW5kIHZpc2libGUgaW5kaWNlcyBoYXZlIG5vdCBjaGFuZ2VkLiBDaGVhcFxuICAgKiByZWxhdGl2ZSB0byBgcmVuZGVyKClgIOKAlCBkb2VzIG5vdCBpbnZva2UgdGhlIGVuZ2luZSdzIG1lYXN1cmVtZW50IHBhc3MuXG4gICAqL1xuICByZWZyZXNoUmVuZGVyZWRDb250ZW50KCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5ob3N0UmVmKSByZXR1cm47XG4gICAgY29uc3Qgc2Nyb2xsZXIgPSB0aGlzLmhvc3RSZWYuc2Nyb2xsZXI7XG5cbiAgICBmb3IgKGNvbnN0IGluZGV4IG9mIHNjcm9sbGVyLmdldFJlbmRlcmVkSW5kaWNlcygpKSB7XG4gICAgICBjb25zdCBjb250YWluZXIgPSBzY3JvbGxlci5nZXRSZW5kZXJlZEVsZW1lbnQoaW5kZXgpO1xuICAgICAgaWYgKCFjb250YWluZXIpIGNvbnRpbnVlO1xuXG4gICAgICBjb25zdCB2aWV3ID0gdGhpcy52aWV3QnlDb250YWluZXIuZ2V0KGNvbnRhaW5lcik7XG4gICAgICBpZiAoIXZpZXcpIGNvbnRpbnVlO1xuXG4gICAgICBjb25zdCBpdGVtID0gdGhpcy5nZXRJdGVtRm9ySW5kZXgoaW5kZXgpO1xuICAgICAgdmlldy5jb250ZXh0LiRpbXBsaWNpdCA9IGl0ZW07XG4gICAgICB2aWV3LmNvbnRleHQuaXRlbSA9IGl0ZW07XG4gICAgICB2aWV3LmNvbnRleHQuaW5kZXggPSBpbmRleDtcbiAgICAgIHZpZXcuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZGVzdHJveUFsbFZpZXdzKCk6IHZvaWQge1xuICAgIGZvciAoY29uc3QgdmlldyBvZiB0aGlzLnZpZXdCeUNvbnRhaW5lci52YWx1ZXMoKSkge1xuICAgICAgdGhpcy5hcHBSZWYuZGV0YWNoVmlldyh2aWV3KTtcbiAgICAgIHZpZXcuZGVzdHJveSgpO1xuICAgIH1cbiAgICB0aGlzLnZpZXdCeUNvbnRhaW5lci5jbGVhcigpO1xuICAgIGZvciAoY29uc3QgdmlldyBvZiB0aGlzLmZyZWVWaWV3cykge1xuICAgICAgdGhpcy5hcHBSZWYuZGV0YWNoVmlldyh2aWV3KTtcbiAgICAgIHZpZXcuZGVzdHJveSgpO1xuICAgIH1cbiAgICB0aGlzLmZyZWVWaWV3cy5sZW5ndGggPSAwO1xuICB9XG59XG4iXX0=
@@ -135,6 +135,12 @@ class CeriousScrollDirective {
135
135
  this.ceriousScrollGetItem = null;
136
136
  /** Template used to render each row. */
137
137
  this.ceriousScrollItemTemplate = null;
138
+ /**
139
+ * Table mode only: template rendered into the engine's `<thead>` (a `<tr>` of
140
+ * `<th>`s). It lives in the same `<table>` as the rows, so columns align
141
+ * natively. Updates via change detection like the rows.
142
+ */
143
+ this.ceriousScrollHeaderTemplate = null;
138
144
  /** Options passed to `new CeriousScroll(...)`. */
139
145
  this.ceriousScrollOptions = {};
140
146
  /** Automatically call render after each scroll event. Default: true */
@@ -154,6 +160,9 @@ class CeriousScrollDirective {
154
160
  // component tree on fast scrolls (where the engine's element pool wipes
155
161
  // textContent on reused containers, so view rootNodes get orphaned).
156
162
  this.freeViews = [];
163
+ // Table mode: the embedded view of the declarative header, rendered into the
164
+ // engine's <thead>.
165
+ this.headerView = null;
157
166
  }
158
167
  ngAfterViewInit() {
159
168
  this.ensureInitialized();
@@ -204,6 +213,8 @@ class CeriousScrollDirective {
204
213
  this.viewportSub?.unsubscribe();
205
214
  this.viewportSub = null;
206
215
  this.destroyAllViews();
216
+ this.headerView?.destroy();
217
+ this.headerView = null;
207
218
  this.hostRef?.destroy();
208
219
  this.hostRef = null;
209
220
  }
@@ -352,7 +363,23 @@ class CeriousScrollDirective {
352
363
  return;
353
364
  const container = this.host.nativeElement;
354
365
  const total = coerceTotalElements(this.ceriousScrollTotalElements, this.ceriousScrollItems?.length ?? null);
355
- this.hostRef = this.cerious.createHost(container, total, this.ceriousScrollOptions, this.ngZone, () => {
366
+ // Table mode: capture the engine-created <thead> so we can render the
367
+ // declarative header template into it (and still run any user header hook).
368
+ let options = this.ceriousScrollOptions;
369
+ if (options.layout === 'table' && this.ceriousScrollHeaderTemplate) {
370
+ const userHeader = options.table?.header;
371
+ options = {
372
+ ...options,
373
+ table: {
374
+ ...options.table,
375
+ header: (thead) => {
376
+ userHeader?.(thead);
377
+ this.mountHeader(thead);
378
+ },
379
+ },
380
+ };
381
+ }
382
+ this.hostRef = this.cerious.createHost(container, total, options, this.ngZone, () => {
356
383
  // Coalesce scroll-driven renders to one per frame (the native scrollbar
357
384
  // can fire many scroll events between paints).
358
385
  if (this.ceriousScrollAutoRender)
@@ -369,6 +396,25 @@ class CeriousScrollDirective {
369
396
  queueMicrotask(() => this.render());
370
397
  }
371
398
  }
399
+ /**
400
+ * Render the declarative header template into the engine's <thead>. One
401
+ * embedded view, created inside the zone (so the header's event bindings are
402
+ * zone-patched), its root nodes appended directly into the <thead>.
403
+ */
404
+ mountHeader(thead) {
405
+ if (!this.ceriousScrollHeaderTemplate)
406
+ return;
407
+ this.headerView?.destroy();
408
+ const view = this.ngZone.run(() => {
409
+ const v = this.ceriousScrollHeaderTemplate.createEmbeddedView({});
410
+ this.appRef.attachView(v);
411
+ v.detectChanges();
412
+ return v;
413
+ });
414
+ for (const node of view.rootNodes)
415
+ thead.appendChild(node);
416
+ this.headerView = view;
417
+ }
372
418
  getItemForIndex(index) {
373
419
  const getter = this.ceriousScrollGetItem;
374
420
  if (getter)
@@ -473,7 +519,7 @@ class CeriousScrollDirective {
473
519
  this.freeViews.length = 0;
474
520
  }
475
521
  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 }); }
476
- 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 }); }
522
+ 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", ceriousScrollHeaderTemplate: "ceriousScrollHeaderTemplate", ceriousScrollOptions: "ceriousScrollOptions", ceriousScrollAutoRender: "ceriousScrollAutoRender" }, outputs: { ceriousScrollViewportChange: "ceriousScrollViewportChange", ceriousScrollMeasuredViewport: "ceriousScrollMeasuredViewport", ceriousScrollReady: "ceriousScrollReady" }, usesOnChanges: true, ngImport: i0 }); }
477
523
  }
478
524
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CeriousScrollDirective, decorators: [{
479
525
  type: Directive,
@@ -489,6 +535,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
489
535
  type: Input
490
536
  }], ceriousScrollItemTemplate: [{
491
537
  type: Input
538
+ }], ceriousScrollHeaderTemplate: [{
539
+ type: Input
492
540
  }], ceriousScrollOptions: [{
493
541
  type: Input
494
542
  }], ceriousScrollAutoRender: [{
@@ -517,7 +565,7 @@ class CeriousScrollComponent {
517
565
  }
518
566
  }
519
567
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CeriousScrollComponent, deps: [{ token: CeriousScrollDirective }], target: i0.ɵɵFactoryTarget.Component }); }
520
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CeriousScrollComponent, isStandalone: true, selector: "cerious-scroll", queries: [{ propertyName: "projectedItemTemplate", first: true, predicate: CeriousScrollItemTemplateDirective, descendants: true }], hostDirectives: [{ directive: CeriousScrollDirective, inputs: ["ceriousScrollTotalElements", "totalElements", "ceriousScrollItems", "items", "ceriousScrollGetItem", "getItem", "ceriousScrollItemTemplate", "itemTemplate", "ceriousScrollOptions", "options", "ceriousScrollAutoRender", "autoRender"], outputs: ["ceriousScrollViewportChange", "viewportChange", "ceriousScrollMeasuredViewport", "measuredViewport", "ceriousScrollReady", "scrollerReady"] }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
568
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CeriousScrollComponent, isStandalone: true, selector: "cerious-scroll", queries: [{ propertyName: "projectedItemTemplate", first: true, predicate: CeriousScrollItemTemplateDirective, descendants: true }], hostDirectives: [{ directive: CeriousScrollDirective, inputs: ["ceriousScrollTotalElements", "totalElements", "ceriousScrollItems", "items", "ceriousScrollGetItem", "getItem", "ceriousScrollItemTemplate", "itemTemplate", "ceriousScrollHeaderTemplate", "headerTemplate", "ceriousScrollOptions", "options", "ceriousScrollAutoRender", "autoRender"], outputs: ["ceriousScrollViewportChange", "viewportChange", "ceriousScrollMeasuredViewport", "measuredViewport", "ceriousScrollReady", "scrollerReady"] }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
521
569
  }
522
570
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CeriousScrollComponent, decorators: [{
523
571
  type: Component,
@@ -529,6 +577,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
529
577
  'ceriousScrollItems: items',
530
578
  'ceriousScrollGetItem: getItem',
531
579
  'ceriousScrollItemTemplate: itemTemplate',
580
+ 'ceriousScrollHeaderTemplate: headerTemplate',
532
581
  'ceriousScrollOptions: options',
533
582
  'ceriousScrollAutoRender: autoRender',
534
583
  ],
@@ -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 // overflow-y: clip + overflow-x: auto: clip vertical row overflow (engine\n // owns vertical) and let the inner element own the native horizontal\n // scrollbar when consumer content (e.g. wide spreadsheet) overflows.\n // Horizontal scroll must NOT move to the outer container or the cerious\n // sibling-driver vertical scrollbar (`position: absolute; right: 0` inside\n // the outer) would translate with the content. The engine reads its\n // viewport height from this element so the bottom row stays clear of the\n // h-scrollbar gutter when it appears.\n el.style.overflowY = 'clip';\n el.style.overflowX = 'auto';\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 const template = this.ceriousScrollItemTemplate;\n if (template) {\n // Re-invoke the renderer for every currently-rendered row so pending\n // Angular bindings flush into the DOM and the engine re-measures each\n // row's new height into its cache. Without this, the engine's render\n // pass skips the renderer for already-rendered indices and falls\n // through to reading stale offsetHeight.\n this.hostRef.scroller.refreshVisible((index, elementContainer) => {\n this.renderTemplateIntoContainer(template, index, elementContainer);\n });\n }\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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"}
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 // overflow-y: clip + overflow-x: auto: clip vertical row overflow (engine\n // owns vertical) and let the inner element own the native horizontal\n // scrollbar when consumer content (e.g. wide spreadsheet) overflows.\n // Horizontal scroll must NOT move to the outer container or the cerious\n // sibling-driver vertical scrollbar (`position: absolute; right: 0` inside\n // the outer) would translate with the content. The engine reads its\n // viewport height from this element so the bottom row stays clear of the\n // h-scrollbar gutter when it appears.\n el.style.overflowY = 'clip';\n el.style.overflowX = 'auto';\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 /**\n * Table mode only: template rendered into the engine's `<thead>` (a `<tr>` of\n * `<th>`s). It lives in the same `<table>` as the rows, so columns align\n * natively. Updates via change detection like the rows.\n */\n @Input() ceriousScrollHeaderTemplate: TemplateRef<unknown> | 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 // Table mode: the embedded view of the declarative header, rendered into the\n // engine's <thead>.\n private headerView: EmbeddedViewRef<unknown> | null = null;\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 this.headerView?.destroy();\n this.headerView = null;\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 const template = this.ceriousScrollItemTemplate;\n if (template) {\n // Re-invoke the renderer for every currently-rendered row so pending\n // Angular bindings flush into the DOM and the engine re-measures each\n // row's new height into its cache. Without this, the engine's render\n // pass skips the renderer for already-rendered indices and falls\n // through to reading stale offsetHeight.\n this.hostRef.scroller.refreshVisible((index, elementContainer) => {\n this.renderTemplateIntoContainer(template, index, elementContainer);\n });\n }\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 // Table mode: capture the engine-created <thead> so we can render the\n // declarative header template into it (and still run any user header hook).\n let options = this.ceriousScrollOptions;\n if (options.layout === 'table' && this.ceriousScrollHeaderTemplate) {\n const userHeader = options.table?.header;\n options = {\n ...options,\n table: {\n ...options.table,\n header: (thead: HTMLTableSectionElement) => {\n userHeader?.(thead);\n this.mountHeader(thead);\n },\n },\n };\n }\n\n this.hostRef = this.cerious.createHost(container, total, options, 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 /**\n * Render the declarative header template into the engine's <thead>. One\n * embedded view, created inside the zone (so the header's event bindings are\n * zone-patched), its root nodes appended directly into the <thead>.\n */\n private mountHeader(thead: HTMLElement): void {\n if (!this.ceriousScrollHeaderTemplate) return;\n this.headerView?.destroy();\n const view = this.ngZone.run(() => {\n const v = this.ceriousScrollHeaderTemplate!.createEmbeddedView({});\n this.appRef.attachView(v);\n v.detectChanges();\n return v;\n });\n for (const node of view.rootNodes) thead.appendChild(node);\n this.headerView = view;\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 'ceriousScrollHeaderTemplate: headerTemplate',\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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"}
@@ -9,5 +9,5 @@ export declare class CeriousScrollComponent<TItem = unknown> implements AfterCon
9
9
  constructor(ceriousScroll: CeriousScrollDirective<TItem>);
10
10
  ngAfterContentInit(): void;
11
11
  static ɵfac: i0.ɵɵFactoryDeclaration<CeriousScrollComponent<any>, never>;
12
- static ɵcmp: i0.ɵɵComponentDeclaration<CeriousScrollComponent<any>, "cerious-scroll", never, {}, {}, ["projectedItemTemplate"], ["*"], true, [{ directive: typeof i1.CeriousScrollDirective; inputs: { "ceriousScrollTotalElements": "totalElements"; "ceriousScrollItems": "items"; "ceriousScrollGetItem": "getItem"; "ceriousScrollItemTemplate": "itemTemplate"; "ceriousScrollOptions": "options"; "ceriousScrollAutoRender": "autoRender"; }; outputs: { "ceriousScrollViewportChange": "viewportChange"; "ceriousScrollMeasuredViewport": "measuredViewport"; "ceriousScrollReady": "scrollerReady"; }; }]>;
12
+ static ɵcmp: i0.ɵɵComponentDeclaration<CeriousScrollComponent<any>, "cerious-scroll", never, {}, {}, ["projectedItemTemplate"], ["*"], true, [{ directive: typeof i1.CeriousScrollDirective; inputs: { "ceriousScrollTotalElements": "totalElements"; "ceriousScrollItems": "items"; "ceriousScrollGetItem": "getItem"; "ceriousScrollItemTemplate": "itemTemplate"; "ceriousScrollHeaderTemplate": "headerTemplate"; "ceriousScrollOptions": "options"; "ceriousScrollAutoRender": "autoRender"; }; outputs: { "ceriousScrollViewportChange": "viewportChange"; "ceriousScrollMeasuredViewport": "measuredViewport"; "ceriousScrollReady": "scrollerReady"; }; }]>;
13
13
  }
@@ -17,6 +17,12 @@ export declare class CeriousScrollDirective<TItem = unknown> implements AfterVie
17
17
  ceriousScrollGetItem: ((index: number) => TItem) | null;
18
18
  /** Template used to render each row. */
19
19
  ceriousScrollItemTemplate: TemplateRef<CeriousScrollItemTemplateContext<TItem>> | null;
20
+ /**
21
+ * Table mode only: template rendered into the engine's `<thead>` (a `<tr>` of
22
+ * `<th>`s). It lives in the same `<table>` as the rows, so columns align
23
+ * natively. Updates via change detection like the rows.
24
+ */
25
+ ceriousScrollHeaderTemplate: TemplateRef<unknown> | null;
20
26
  /** Options passed to `new CeriousScroll(...)`. */
21
27
  ceriousScrollOptions: CeriousScrollOptions;
22
28
  /** Automatically call render after each scroll event. Default: true */
@@ -32,6 +38,7 @@ export declare class CeriousScrollDirective<TItem = unknown> implements AfterVie
32
38
  private scheduledRenderFrame;
33
39
  private readonly viewByContainer;
34
40
  private readonly freeViews;
41
+ private headerView;
35
42
  constructor(host: ElementRef<HTMLElement>, appRef: ApplicationRef, ngZone: NgZone, cerious: CeriousScrollService);
36
43
  ngAfterViewInit(): void;
37
44
  ngOnChanges(changes: SimpleChanges): void;
@@ -61,6 +68,12 @@ export declare class CeriousScrollDirective<TItem = unknown> implements AfterVie
61
68
  reset(): MeasuredViewportRange | null;
62
69
  private recreate;
63
70
  private ensureInitialized;
71
+ /**
72
+ * Render the declarative header template into the engine's <thead>. One
73
+ * embedded view, created inside the zone (so the header's event bindings are
74
+ * zone-patched), its root nodes appended directly into the <thead>.
75
+ */
76
+ private mountHeader;
64
77
  private getItemForIndex;
65
78
  private renderTemplateIntoContainer;
66
79
  /**
@@ -79,5 +92,5 @@ export declare class CeriousScrollDirective<TItem = unknown> implements AfterVie
79
92
  refreshRenderedContent(): void;
80
93
  private destroyAllViews;
81
94
  static ɵfac: i0.ɵɵFactoryDeclaration<CeriousScrollDirective<any>, never>;
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>;
95
+ 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; }; "ceriousScrollHeaderTemplate": { "alias": "ceriousScrollHeaderTemplate"; "required": false; }; "ceriousScrollOptions": { "alias": "ceriousScrollOptions"; "required": false; }; "ceriousScrollAutoRender": { "alias": "ceriousScrollAutoRender"; "required": false; }; }, { "ceriousScrollViewportChange": "ceriousScrollViewportChange"; "ceriousScrollMeasuredViewport": "ceriousScrollMeasuredViewport"; "ceriousScrollReady": "ceriousScrollReady"; }, never, never, true, never>;
83
96
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ceriousdevtech/ngx-cerious-scroll",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,7 +11,7 @@
11
11
  "@angular/core": ">=16.0.0"
12
12
  },
13
13
  "dependencies": {
14
- "@ceriousdevtech/cerious-scroll": "^1.0.5",
14
+ "@ceriousdevtech/cerious-scroll": "^1.0.7",
15
15
  "tslib": "^2.3.0"
16
16
  },
17
17
  "sideEffects": false,