@sumaris-net/ngx-components 18.22.23 → 18.23.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/doc/changelog.md +9 -0
  2. package/esm2022/src/app/core/table/column/actions-column.component.mjs +1 -1
  3. package/esm2022/src/app/core/table/table.pipes.mjs +6 -7
  4. package/esm2022/src/app/core/table/testing/table.testing.module.mjs +25 -4
  5. package/esm2022/src/app/core/table/testing/table2.testing.mjs +63 -15
  6. package/esm2022/src/app/shared/directives/cell-selection/cell-identifier.directive.mjs +41 -0
  7. package/esm2022/src/app/shared/directives/cell-selection/cell-selection.directive.mjs +201 -0
  8. package/esm2022/src/app/shared/directives/cell-selection/cell-selection.service.mjs +180 -0
  9. package/esm2022/src/app/shared/functions.mjs +1 -1
  10. package/esm2022/src/app/shared/material/datetime/material.date.mjs +4 -2
  11. package/esm2022/src/app/shared/material/datetime/material.datetime.mjs +5 -2
  12. package/esm2022/src/app/social/feed/feed.component.mjs +3 -3
  13. package/fesm2022/sumaris-net.ngx-components.mjs +495 -19
  14. package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
  15. package/package.json +1 -1
  16. package/src/app/core/table/column/actions-column.component.d.ts +1 -1
  17. package/src/app/core/table/table.pipes.d.ts +2 -1
  18. package/src/app/core/table/testing/table.testing.module.d.ts +3 -1
  19. package/src/app/core/table/testing/table2.testing.d.ts +7 -3
  20. package/src/app/shared/directives/cell-selection/cell-identifier.directive.d.ts +15 -0
  21. package/src/app/shared/directives/cell-selection/cell-selection.directive.d.ts +28 -0
  22. package/src/app/shared/directives/cell-selection/cell-selection.service.d.ts +62 -0
  23. package/src/app/shared/functions.d.ts +1 -1
  24. package/src/app/shared/inputs.d.ts +1 -1
  25. package/src/theme/_ngx-components.table.scss +45 -2
@@ -0,0 +1,41 @@
1
+ import { DestroyRef, Directive, inject, input } from '@angular/core';
2
+ import { APP_CELL_SELECTION_SERVICE_TOKEN } from './cell-selection.service';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import * as i0 from "@angular/core";
5
+ export class CellIdentifierDirective {
6
+ cellId = input.required({ alias: 'appCellId' });
7
+ isCellSelected = false;
8
+ isDragging = false;
9
+ service = inject(APP_CELL_SELECTION_SERVICE_TOKEN);
10
+ destroyRef = inject(DestroyRef);
11
+ ngOnInit() {
12
+ // Listen to service selection changes and emit
13
+ this.service.selectionChangeSubject
14
+ .pipe(takeUntilDestroyed(this.destroyRef))
15
+ .subscribe(() => (this.isCellSelected = this.service.isCellSelected(this.cellId())));
16
+ }
17
+ async handleMouseDown(event) {
18
+ await this.service.handleCellMouseDown(event, this.cellId());
19
+ }
20
+ async handleMouseEnter(event) {
21
+ await this.service.handleCellMouseEnter(event, this.cellId());
22
+ }
23
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CellIdentifierDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
24
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.13", type: CellIdentifierDirective, isStandalone: true, selector: "[appCellId]", inputs: { cellId: { classPropertyName: "cellId", publicName: "appCellId", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "mousedown": "handleMouseDown($event)", "mouseenter": "handleMouseEnter($event)" }, properties: { "class.cell-selected": "isCellSelected", "class.cell-dragging": "isDragging", "attr.data-row-id": "cellId().rowId", "attr.data-column-name": "cellId().columnName" } }, ngImport: i0 });
25
+ }
26
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CellIdentifierDirective, decorators: [{
27
+ type: Directive,
28
+ args: [{
29
+ selector: '[appCellId]',
30
+ standalone: true,
31
+ host: {
32
+ '(mousedown)': 'handleMouseDown($event)',
33
+ '(mouseenter)': 'handleMouseEnter($event)',
34
+ '[class.cell-selected]': 'isCellSelected',
35
+ '[class.cell-dragging]': 'isDragging',
36
+ '[attr.data-row-id]': 'cellId().rowId',
37
+ '[attr.data-column-name]': 'cellId().columnName',
38
+ },
39
+ }]
40
+ }] });
41
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VsbC1pZGVudGlmaWVyLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvc2hhcmVkL2RpcmVjdGl2ZXMvY2VsbC1zZWxlY3Rpb24vY2VsbC1pZGVudGlmaWVyLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBQzdFLE9BQU8sRUFBRSxnQ0FBZ0MsRUFBVyxNQUFNLDBCQUEwQixDQUFDO0FBQ3JGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDOztBQWNoRSxNQUFNLE9BQU8sdUJBQXVCO0lBQ2xDLE1BQU0sR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFJLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFFekMsY0FBYyxHQUFHLEtBQUssQ0FBQztJQUN2QixVQUFVLEdBQUcsS0FBSyxDQUFDO0lBRVosT0FBTyxHQUFHLE1BQU0sQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO0lBQ25ELFVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFFakQsUUFBUTtRQUNOLCtDQUErQztRQUMvQyxJQUFJLENBQUMsT0FBTyxDQUFDLHNCQUFzQjthQUNoQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ3pDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFFUyxLQUFLLENBQUMsZUFBZSxDQUFDLEtBQWlCO1FBQy9DLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDL0QsQ0FBQztJQUVTLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFpQjtRQUNoRCxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7d0dBdEJVLHVCQUF1Qjs0RkFBdkIsdUJBQXVCOzs0RkFBdkIsdUJBQXVCO2tCQVpuQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxhQUFhO29CQUN2QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsSUFBSSxFQUFFO3dCQUNKLGFBQWEsRUFBRSx5QkFBeUI7d0JBQ3hDLGNBQWMsRUFBRSwwQkFBMEI7d0JBQzFDLHVCQUF1QixFQUFFLGdCQUFnQjt3QkFDekMsdUJBQXVCLEVBQUUsWUFBWTt3QkFDckMsb0JBQW9CLEVBQUUsZ0JBQWdCO3dCQUN0Qyx5QkFBeUIsRUFBRSxxQkFBcUI7cUJBQ2pEO2lCQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGVzdHJveVJlZiwgRGlyZWN0aXZlLCBpbmplY3QsIGlucHV0LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFQUF9DRUxMX1NFTEVDVElPTl9TRVJWSUNFX1RPS0VOLCBJQ2VsbElkIH0gZnJvbSAnLi9jZWxsLXNlbGVjdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2FwcENlbGxJZF0nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBob3N0OiB7XG4gICAgJyhtb3VzZWRvd24pJzogJ2hhbmRsZU1vdXNlRG93bigkZXZlbnQpJyxcbiAgICAnKG1vdXNlZW50ZXIpJzogJ2hhbmRsZU1vdXNlRW50ZXIoJGV2ZW50KScsXG4gICAgJ1tjbGFzcy5jZWxsLXNlbGVjdGVkXSc6ICdpc0NlbGxTZWxlY3RlZCcsXG4gICAgJ1tjbGFzcy5jZWxsLWRyYWdnaW5nXSc6ICdpc0RyYWdnaW5nJyxcbiAgICAnW2F0dHIuZGF0YS1yb3ctaWRdJzogJ2NlbGxJZCgpLnJvd0lkJyxcbiAgICAnW2F0dHIuZGF0YS1jb2x1bW4tbmFtZV0nOiAnY2VsbElkKCkuY29sdW1uTmFtZScsXG4gIH0sXG59KVxuZXhwb3J0IGNsYXNzIENlbGxJZGVudGlmaWVyRGlyZWN0aXZlPEMgZXh0ZW5kcyBJQ2VsbElkID0gSUNlbGxJZD4gaW1wbGVtZW50cyBPbkluaXQge1xuICBjZWxsSWQgPSBpbnB1dC5yZXF1aXJlZDxDPih7IGFsaWFzOiAnYXBwQ2VsbElkJyB9KTtcblxuICBwcm90ZWN0ZWQgaXNDZWxsU2VsZWN0ZWQgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIGlzRHJhZ2dpbmcgPSBmYWxzZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IHNlcnZpY2UgPSBpbmplY3QoQVBQX0NFTExfU0VMRUNUSU9OX1NFUlZJQ0VfVE9LRU4pO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgLy8gTGlzdGVuIHRvIHNlcnZpY2Ugc2VsZWN0aW9uIGNoYW5nZXMgYW5kIGVtaXRcbiAgICB0aGlzLnNlcnZpY2Uuc2VsZWN0aW9uQ2hhbmdlU3ViamVjdFxuICAgICAgLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZikpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+ICh0aGlzLmlzQ2VsbFNlbGVjdGVkID0gdGhpcy5zZXJ2aWNlLmlzQ2VsbFNlbGVjdGVkKHRoaXMuY2VsbElkKCkpKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaGFuZGxlTW91c2VEb3duKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgYXdhaXQgdGhpcy5zZXJ2aWNlLmhhbmRsZUNlbGxNb3VzZURvd24oZXZlbnQsIHRoaXMuY2VsbElkKCkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGhhbmRsZU1vdXNlRW50ZXIoZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICBhd2FpdCB0aGlzLnNlcnZpY2UuaGFuZGxlQ2VsbE1vdXNlRW50ZXIoZXZlbnQsIHRoaXMuY2VsbElkKCkpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,201 @@
1
+ import { DestroyRef, Directive, ElementRef, inject, input, output, Renderer2 } from '@angular/core';
2
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
+ import { fromEvent } from 'rxjs';
4
+ import { APP_CELL_SELECTION_SERVICE_TOKEN } from './cell-selection.service';
5
+ import { isEmptyArray, isNotEmptyArray } from '../../functions';
6
+ import * as i0 from "@angular/core";
7
+ export class CellSelectionDirective {
8
+ // Inputs
9
+ // eslint-disable-next-line @angular-eslint/no-input-rename
10
+ selectableColumns = input.required({ alias: 'appSelectableColumns' });
11
+ // Outputs
12
+ // eslint-disable-next-line @angular-eslint/no-output-rename
13
+ selectionChange = output({ alias: 'appCellSelectionChange' });
14
+ // eslint-disable-next-line @angular-eslint/no-output-rename
15
+ rightClick = output({ alias: 'appCellRightClick' });
16
+ // Inject service by token
17
+ service = inject(APP_CELL_SELECTION_SERVICE_TOKEN);
18
+ elementRef = inject(ElementRef);
19
+ renderer = inject(Renderer2);
20
+ destroyRef = inject(DestroyRef);
21
+ overlayElements = [];
22
+ constructor() { }
23
+ ngOnInit() {
24
+ // Initialize service with selectable columns
25
+ this.setupServiceConfiguration();
26
+ // Setup global mouseup listener
27
+ this.setupGlobalMouseEvents();
28
+ // Setup keyboard listener for copy (for test)
29
+ // this.setupCopyListener();
30
+ }
31
+ setupServiceConfiguration() {
32
+ // Pass selectable columns to service
33
+ this.service.selectableColumns = this.selectableColumns();
34
+ // Listen to service selection changes and emit
35
+ this.service.selectionChangeSubject
36
+ .pipe(takeUntilDestroyed(this.destroyRef))
37
+ .subscribe((event) => this.selectionChange.emit(event));
38
+ // Listen to right-click event
39
+ this.service.selectionRightClickSubject.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => this.rightClick.emit(event));
40
+ }
41
+ setupGlobalMouseEvents() {
42
+ fromEvent(document, 'mouseup')
43
+ .pipe(takeUntilDestroyed(this.destroyRef))
44
+ .subscribe(() => this.service.endMouseMove());
45
+ }
46
+ // For test purpose only (type CTRL+C)
47
+ setupCopyListener() {
48
+ fromEvent(document, 'keydown')
49
+ .pipe(takeUntilDestroyed(this.destroyRef))
50
+ .subscribe((event) => {
51
+ if ((event.ctrlKey || event.metaKey) && event.key === 'c') {
52
+ const cells = this.service.selectedCells;
53
+ if (isNotEmptyArray(cells)) {
54
+ // Show overlay
55
+ this.addCellsOverlay(cells);
56
+ event.preventDefault();
57
+ // Hide overlay after animation completes (1 second)
58
+ setTimeout(() => {
59
+ this.removeCellsOverlay();
60
+ }, 1000);
61
+ }
62
+ }
63
+ });
64
+ }
65
+ addCellsOverlay(cells) {
66
+ // Remove existing overlays
67
+ this.removeCellsOverlay();
68
+ // Group cells into contiguous regions
69
+ const cellGroups = this.groupContiguousCells(cells);
70
+ // Create and render overlay for each contiguous region
71
+ cellGroups.forEach((group) => {
72
+ const bounds = this.calculateSelectionBounds(group);
73
+ if (bounds) {
74
+ const overlay = this.createOverlayElement(bounds);
75
+ this.renderer.appendChild(this.elementRef.nativeElement, overlay);
76
+ this.overlayElements.push(overlay);
77
+ }
78
+ });
79
+ }
80
+ removeCellsOverlay() {
81
+ this.overlayElements.forEach((overlay) => {
82
+ this.renderer.removeChild(this.elementRef.nativeElement, overlay);
83
+ });
84
+ this.overlayElements = [];
85
+ }
86
+ groupContiguousCells(cells) {
87
+ // Create a map for quick lookup
88
+ const cellMap = new Map();
89
+ cells.forEach((cell) => {
90
+ cellMap.set(this.getCellKey(cell), cell);
91
+ });
92
+ const visited = new Set();
93
+ const groups = [];
94
+ // Process each cell
95
+ cells.forEach((cell) => {
96
+ const key = this.getCellKey(cell);
97
+ if (visited.has(key)) {
98
+ return;
99
+ }
100
+ // Start a new contiguous group with flood-fill
101
+ const group = [];
102
+ const queue = [cell];
103
+ visited.add(key);
104
+ while (queue.length > 0) {
105
+ const current = queue.shift();
106
+ group.push(current);
107
+ // Check all 4 adjacent cells (up, down, left, right)
108
+ const neighbors = this.getAdjacentCells(current);
109
+ neighbors.forEach((neighbor) => {
110
+ const neighborKey = this.getCellKey(neighbor);
111
+ if (cellMap.has(neighborKey) && !visited.has(neighborKey)) {
112
+ visited.add(neighborKey);
113
+ queue.push(neighbor);
114
+ }
115
+ });
116
+ }
117
+ groups.push(group);
118
+ });
119
+ return groups;
120
+ }
121
+ getAdjacentCells(cell) {
122
+ // Returns cells adjacent to the current cell (up, down, left, right)
123
+ // Note: We need to get column order from the actual table structure
124
+ // For now, we'll use a simple approach based on rowId adjacency
125
+ return [
126
+ { rowId: cell.rowId - 1, columnName: cell.columnName }, // up
127
+ { rowId: cell.rowId + 1, columnName: cell.columnName }, // down
128
+ { rowId: cell.rowId, columnName: this.getNextColumnName(cell.columnName, -1) }, // left
129
+ { rowId: cell.rowId, columnName: this.getNextColumnName(cell.columnName, 1) }, // right
130
+ ].filter((c) => c.columnName !== null);
131
+ }
132
+ getNextColumnName(currentColumnName, offset) {
133
+ const columns = this.service.selectableColumns;
134
+ const currentIndex = columns.indexOf(currentColumnName);
135
+ if (currentIndex === -1) {
136
+ return null;
137
+ }
138
+ const newIndex = currentIndex + offset;
139
+ if (newIndex < 0 || newIndex >= columns.length) {
140
+ return null;
141
+ }
142
+ return columns[newIndex];
143
+ }
144
+ getCellKey(cell) {
145
+ return `${cell.rowId}-${cell.columnName}`;
146
+ }
147
+ calculateSelectionBounds(cells) {
148
+ const container = this.elementRef.nativeElement;
149
+ // Find all selected cell elements
150
+ const cellElements = [];
151
+ cells.forEach((cell) => {
152
+ const cellElement = container.querySelector(`[data-row-id="${cell.rowId}"][data-column-name="${cell.columnName}"]`);
153
+ if (cellElement) {
154
+ cellElements.push(cellElement);
155
+ }
156
+ });
157
+ if (isEmptyArray(cellElements)) {
158
+ return null;
159
+ }
160
+ // Get container position
161
+ const containerRect = container.getBoundingClientRect();
162
+ // Calculate bounding box
163
+ let minTop = Infinity;
164
+ let minLeft = Infinity;
165
+ let maxBottom = -Infinity;
166
+ let maxRight = -Infinity;
167
+ cellElements.forEach((element) => {
168
+ const rect = element.getBoundingClientRect();
169
+ minTop = Math.min(minTop, rect.top - containerRect.top);
170
+ minLeft = Math.min(minLeft, rect.left - containerRect.left);
171
+ maxBottom = Math.max(maxBottom, rect.bottom - containerRect.top);
172
+ maxRight = Math.max(maxRight, rect.right - containerRect.left);
173
+ });
174
+ return {
175
+ top: minTop,
176
+ left: minLeft,
177
+ width: maxRight - minLeft,
178
+ height: maxBottom - minTop,
179
+ };
180
+ }
181
+ createOverlayElement(bounds) {
182
+ const overlay = this.renderer.createElement('div');
183
+ this.renderer.addClass(overlay, 'cell-selection-overlay');
184
+ // Set position and size
185
+ this.renderer.setStyle(overlay, 'top', `${bounds.top}px`);
186
+ this.renderer.setStyle(overlay, 'left', `${bounds.left}px`);
187
+ this.renderer.setStyle(overlay, 'width', `${bounds.width}px`);
188
+ this.renderer.setStyle(overlay, 'height', `${bounds.height}px`);
189
+ return overlay;
190
+ }
191
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CellSelectionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
192
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.13", type: CellSelectionDirective, isStandalone: true, selector: "[appCellSelection]", inputs: { selectableColumns: { classPropertyName: "selectableColumns", publicName: "appSelectableColumns", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { selectionChange: "appCellSelectionChange", rightClick: "appCellRightClick" }, ngImport: i0 });
193
+ }
194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CellSelectionDirective, decorators: [{
195
+ type: Directive,
196
+ args: [{
197
+ selector: '[appCellSelection]',
198
+ standalone: true,
199
+ }]
200
+ }], ctorParameters: () => [] });
201
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VsbC1zZWxlY3Rpb24uZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9zaGFyZWQvZGlyZWN0aXZlcy9jZWxsLXNlbGVjdGlvbi9jZWxsLXNlbGVjdGlvbi5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQVUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM1RyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxnQ0FBZ0MsRUFBK0IsTUFBTSwwQkFBMEIsQ0FBQztBQUN6RyxPQUFPLEVBQUUsWUFBWSxFQUFFLGVBQWUsRUFBRSxNQUFNLGlCQUFpQixDQUFDOztBQWFoRSxNQUFNLE9BQU8sc0JBQXNCO0lBQ2pDLFNBQVM7SUFDVCwyREFBMkQ7SUFDM0QsaUJBQWlCLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBVyxFQUFFLEtBQUssRUFBRSxzQkFBc0IsRUFBRSxDQUFDLENBQUM7SUFFaEYsVUFBVTtJQUNWLDREQUE0RDtJQUM1RCxlQUFlLEdBQUcsTUFBTSxDQUF3QixFQUFFLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxDQUFDLENBQUM7SUFDckYsNERBQTREO0lBQzVELFVBQVUsR0FBRyxNQUFNLENBQWEsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQyxDQUFDO0lBRWhFLDBCQUEwQjtJQUNoQixPQUFPLEdBQUcsTUFBTSxDQUFDLGdDQUFnQyxDQUFDLENBQUM7SUFFNUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNoQyxRQUFRLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzdCLFVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDekMsZUFBZSxHQUFrQixFQUFFLENBQUM7SUFFNUMsZ0JBQWUsQ0FBQztJQUVoQixRQUFRO1FBQ04sNkNBQTZDO1FBQzdDLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1FBQ2pDLGdDQUFnQztRQUNoQyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztRQUM5Qiw4Q0FBOEM7UUFDOUMsNEJBQTRCO0lBQzlCLENBQUM7SUFFTyx5QkFBeUI7UUFDL0IscUNBQXFDO1FBQ3JDLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFFMUQsK0NBQStDO1FBQy9DLElBQUksQ0FBQyxPQUFPLENBQUMsc0JBQXNCO2FBQ2hDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDekMsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUE4QixDQUFDLENBQUMsQ0FBQztRQUVuRiw4QkFBOEI7UUFDOUIsSUFBSSxDQUFDLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3RJLENBQUM7SUFFTyxzQkFBc0I7UUFDNUIsU0FBUyxDQUFhLFFBQVEsRUFBRSxTQUFTLENBQUM7YUFDdkMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUN6QyxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCxzQ0FBc0M7SUFDOUIsaUJBQWlCO1FBQ3ZCLFNBQVMsQ0FBZ0IsUUFBUSxFQUFFLFNBQVMsQ0FBQzthQUMxQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ3pDLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ25CLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLEdBQUcsRUFBRSxDQUFDO2dCQUMxRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQW9CLENBQUM7Z0JBQ2hELElBQUksZUFBZSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQzNCLGVBQWU7b0JBQ2YsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFFNUIsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO29CQUV2QixvREFBb0Q7b0JBQ3BELFVBQVUsQ0FBQyxHQUFHLEVBQUU7d0JBQ2QsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7b0JBQzVCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDWCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVELGVBQWUsQ0FBQyxLQUFVO1FBQ3hCLDJCQUEyQjtRQUMzQixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUUxQixzQ0FBc0M7UUFDdEMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXBELHVEQUF1RDtRQUN2RCxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDM0IsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3BELElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQ1gsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUNsRCxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDbEUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDckMsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGtCQUFrQjtRQUNoQixJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ3ZDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3BFLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGVBQWUsR0FBRyxFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVPLG9CQUFvQixDQUFDLEtBQVU7UUFDckMsZ0NBQWdDO1FBQ2hDLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFhLENBQUM7UUFDckMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ3JCLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMzQyxDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDbEMsTUFBTSxNQUFNLEdBQVUsRUFBRSxDQUFDO1FBRXpCLG9CQUFvQjtRQUNwQixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDckIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNsQyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDckIsT0FBTztZQUNULENBQUM7WUFFRCwrQ0FBK0M7WUFDL0MsTUFBTSxLQUFLLEdBQVEsRUFBRSxDQUFDO1lBQ3RCLE1BQU0sS0FBSyxHQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDMUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUVqQixPQUFPLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3hCLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxLQUFLLEVBQUcsQ0FBQztnQkFDL0IsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFFcEIscURBQXFEO2dCQUNyRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2pELFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRTtvQkFDN0IsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztvQkFDOUMsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO3dCQUMxRCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO3dCQUN6QixLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUN2QixDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUVELE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDckIsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sZ0JBQWdCLENBQUMsSUFBTztRQUM5QixxRUFBcUU7UUFDckUsb0VBQW9FO1FBQ3BFLGdFQUFnRTtRQUNoRSxPQUFPO1lBQ0wsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsRUFBRSxLQUFLO1lBQzdELEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsT0FBTztZQUMvRCxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsT0FBTztZQUN2RixFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLFFBQVE7U0FDeEYsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxVQUFVLEtBQUssSUFBSSxDQUFRLENBQUM7SUFDaEQsQ0FBQztJQUVPLGlCQUFpQixDQUFDLGlCQUF5QixFQUFFLE1BQWM7UUFDakUsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQztRQUUvQyxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDeEQsSUFBSSxZQUFZLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN4QixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxZQUFZLEdBQUcsTUFBTSxDQUFDO1FBQ3ZDLElBQUksUUFBUSxHQUFHLENBQUMsSUFBSSxRQUFRLElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQy9DLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE9BQU8sT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFFTyxVQUFVLENBQUMsSUFBTztRQUN4QixPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDNUMsQ0FBQztJQUVPLHdCQUF3QixDQUFDLEtBQVU7UUFDekMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUE0QixDQUFDO1FBRS9ELGtDQUFrQztRQUNsQyxNQUFNLFlBQVksR0FBa0IsRUFBRSxDQUFDO1FBQ3ZDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUNyQixNQUFNLFdBQVcsR0FBRyxTQUFTLENBQUMsYUFBYSxDQUFDLGlCQUFpQixJQUFJLENBQUMsS0FBSyx3QkFBd0IsSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFnQixDQUFDO1lBQ25JLElBQUksV0FBVyxFQUFFLENBQUM7Z0JBQ2hCLFlBQVksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDakMsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxZQUFZLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUMvQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCx5QkFBeUI7UUFDekIsTUFBTSxhQUFhLEdBQUcsU0FBUyxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFFeEQseUJBQXlCO1FBQ3pCLElBQUksTUFBTSxHQUFHLFFBQVEsQ0FBQztRQUN0QixJQUFJLE9BQU8sR0FBRyxRQUFRLENBQUM7UUFDdkIsSUFBSSxTQUFTLEdBQUcsQ0FBQyxRQUFRLENBQUM7UUFDMUIsSUFBSSxRQUFRLEdBQUcsQ0FBQyxRQUFRLENBQUM7UUFFekIsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQy9CLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzdDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsR0FBRyxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN4RCxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLElBQUksR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUQsU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2pFLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsS0FBSyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNqRSxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU87WUFDTCxHQUFHLEVBQUUsTUFBTTtZQUNYLElBQUksRUFBRSxPQUFPO1lBQ2IsS0FBSyxFQUFFLFFBQVEsR0FBRyxPQUFPO1lBQ3pCLE1BQU0sRUFBRSxTQUFTLEdBQUcsTUFBTTtTQUMzQixDQUFDO0lBQ0osQ0FBQztJQUVPLG9CQUFvQixDQUFDLE1BQXVCO1FBQ2xELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSx3QkFBd0IsQ0FBQyxDQUFDO1FBRTFELHdCQUF3QjtRQUN4QixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEdBQUcsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsR0FBRyxNQUFNLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQztRQUM5RCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUM7UUFFaEUsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQzt3R0EvTlUsc0JBQXNCOzRGQUF0QixzQkFBc0I7OzRGQUF0QixzQkFBc0I7a0JBSmxDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLG9CQUFvQjtvQkFDOUIsVUFBVSxFQUFFLElBQUk7aUJBQ2pCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGVzdHJveVJlZiwgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBpbmplY3QsIGlucHV0LCBPbkluaXQsIG91dHB1dCwgUmVuZGVyZXIyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBmcm9tRXZlbnQgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEFQUF9DRUxMX1NFTEVDVElPTl9TRVJWSUNFX1RPS0VOLCBDZWxsU2VsZWN0aW9uRXZlbnQsIElDZWxsSWQgfSBmcm9tICcuL2NlbGwtc2VsZWN0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgaXNFbXB0eUFycmF5LCBpc05vdEVtcHR5QXJyYXkgfSBmcm9tICcuLi8uLi9mdW5jdGlvbnMnO1xuXG5pbnRlcmZhY2UgU2VsZWN0aW9uQm91bmRzIHtcbiAgdG9wOiBudW1iZXI7XG4gIGxlZnQ6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbiAgaGVpZ2h0OiBudW1iZXI7XG59XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1thcHBDZWxsU2VsZWN0aW9uXScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIENlbGxTZWxlY3Rpb25EaXJlY3RpdmU8QyBleHRlbmRzIElDZWxsSWQgPSBJQ2VsbElkPiBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIC8vIElucHV0c1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGFuZ3VsYXItZXNsaW50L25vLWlucHV0LXJlbmFtZVxuICBzZWxlY3RhYmxlQ29sdW1ucyA9IGlucHV0LnJlcXVpcmVkPHN0cmluZ1tdPih7IGFsaWFzOiAnYXBwU2VsZWN0YWJsZUNvbHVtbnMnIH0pO1xuXG4gIC8vIE91dHB1dHNcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9uby1vdXRwdXQtcmVuYW1lXG4gIHNlbGVjdGlvbkNoYW5nZSA9IG91dHB1dDxDZWxsU2VsZWN0aW9uRXZlbnQ8Qz4+KHsgYWxpYXM6ICdhcHBDZWxsU2VsZWN0aW9uQ2hhbmdlJyB9KTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9uby1vdXRwdXQtcmVuYW1lXG4gIHJpZ2h0Q2xpY2sgPSBvdXRwdXQ8TW91c2VFdmVudD4oeyBhbGlhczogJ2FwcENlbGxSaWdodENsaWNrJyB9KTtcblxuICAvLyBJbmplY3Qgc2VydmljZSBieSB0b2tlblxuICBwcm90ZWN0ZWQgc2VydmljZSA9IGluamVjdChBUFBfQ0VMTF9TRUxFQ1RJT05fU0VSVklDRV9UT0tFTik7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBlbGVtZW50UmVmID0gaW5qZWN0KEVsZW1lbnRSZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlbmRlcmVyID0gaW5qZWN0KFJlbmRlcmVyMik7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcbiAgcHJpdmF0ZSBvdmVybGF5RWxlbWVudHM6IEhUTUxFbGVtZW50W10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgLy8gSW5pdGlhbGl6ZSBzZXJ2aWNlIHdpdGggc2VsZWN0YWJsZSBjb2x1bW5zXG4gICAgdGhpcy5zZXR1cFNlcnZpY2VDb25maWd1cmF0aW9uKCk7XG4gICAgLy8gU2V0dXAgZ2xvYmFsIG1vdXNldXAgbGlzdGVuZXJcbiAgICB0aGlzLnNldHVwR2xvYmFsTW91c2VFdmVudHMoKTtcbiAgICAvLyBTZXR1cCBrZXlib2FyZCBsaXN0ZW5lciBmb3IgY29weSAoZm9yIHRlc3QpXG4gICAgLy8gdGhpcy5zZXR1cENvcHlMaXN0ZW5lcigpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cFNlcnZpY2VDb25maWd1cmF0aW9uKCkge1xuICAgIC8vIFBhc3Mgc2VsZWN0YWJsZSBjb2x1bW5zIHRvIHNlcnZpY2VcbiAgICB0aGlzLnNlcnZpY2Uuc2VsZWN0YWJsZUNvbHVtbnMgPSB0aGlzLnNlbGVjdGFibGVDb2x1bW5zKCk7XG5cbiAgICAvLyBMaXN0ZW4gdG8gc2VydmljZSBzZWxlY3Rpb24gY2hhbmdlcyBhbmQgZW1pdFxuICAgIHRoaXMuc2VydmljZS5zZWxlY3Rpb25DaGFuZ2VTdWJqZWN0XG4gICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcbiAgICAgIC5zdWJzY3JpYmUoKGV2ZW50KSA9PiB0aGlzLnNlbGVjdGlvbkNoYW5nZS5lbWl0KGV2ZW50IGFzIENlbGxTZWxlY3Rpb25FdmVudDxDPikpO1xuXG4gICAgLy8gTGlzdGVuIHRvIHJpZ2h0LWNsaWNrIGV2ZW50XG4gICAgdGhpcy5zZXJ2aWNlLnNlbGVjdGlvblJpZ2h0Q2xpY2tTdWJqZWN0LnBpcGUodGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZikpLnN1YnNjcmliZSgoZXZlbnQpID0+IHRoaXMucmlnaHRDbGljay5lbWl0KGV2ZW50KSk7XG4gIH1cblxuICBwcml2YXRlIHNldHVwR2xvYmFsTW91c2VFdmVudHMoKSB7XG4gICAgZnJvbUV2ZW50PE1vdXNlRXZlbnQ+KGRvY3VtZW50LCAnbW91c2V1cCcpXG4gICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5zZXJ2aWNlLmVuZE1vdXNlTW92ZSgpKTtcbiAgfVxuXG4gIC8vIEZvciB0ZXN0IHB1cnBvc2Ugb25seSAodHlwZSBDVFJMK0MpXG4gIHByaXZhdGUgc2V0dXBDb3B5TGlzdGVuZXIoKSB7XG4gICAgZnJvbUV2ZW50PEtleWJvYXJkRXZlbnQ+KGRvY3VtZW50LCAna2V5ZG93bicpXG4gICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcbiAgICAgIC5zdWJzY3JpYmUoKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmICgoZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5KSAmJiBldmVudC5rZXkgPT09ICdjJykge1xuICAgICAgICAgIGNvbnN0IGNlbGxzID0gdGhpcy5zZXJ2aWNlLnNlbGVjdGVkQ2VsbHMgYXMgQ1tdO1xuICAgICAgICAgIGlmIChpc05vdEVtcHR5QXJyYXkoY2VsbHMpKSB7XG4gICAgICAgICAgICAvLyBTaG93IG92ZXJsYXlcbiAgICAgICAgICAgIHRoaXMuYWRkQ2VsbHNPdmVybGF5KGNlbGxzKTtcblxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgLy8gSGlkZSBvdmVybGF5IGFmdGVyIGFuaW1hdGlvbiBjb21wbGV0ZXMgKDEgc2Vjb25kKVxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMucmVtb3ZlQ2VsbHNPdmVybGF5KCk7XG4gICAgICAgICAgICB9LCAxMDAwKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgYWRkQ2VsbHNPdmVybGF5KGNlbGxzOiBDW10pIHtcbiAgICAvLyBSZW1vdmUgZXhpc3Rpbmcgb3ZlcmxheXNcbiAgICB0aGlzLnJlbW92ZUNlbGxzT3ZlcmxheSgpO1xuXG4gICAgLy8gR3JvdXAgY2VsbHMgaW50byBjb250aWd1b3VzIHJlZ2lvbnNcbiAgICBjb25zdCBjZWxsR3JvdXBzID0gdGhpcy5ncm91cENvbnRpZ3VvdXNDZWxscyhjZWxscyk7XG5cbiAgICAvLyBDcmVhdGUgYW5kIHJlbmRlciBvdmVybGF5IGZvciBlYWNoIGNvbnRpZ3VvdXMgcmVnaW9uXG4gICAgY2VsbEdyb3Vwcy5mb3JFYWNoKChncm91cCkgPT4ge1xuICAgICAgY29uc3QgYm91bmRzID0gdGhpcy5jYWxjdWxhdGVTZWxlY3Rpb25Cb3VuZHMoZ3JvdXApO1xuICAgICAgaWYgKGJvdW5kcykge1xuICAgICAgICBjb25zdCBvdmVybGF5ID0gdGhpcy5jcmVhdGVPdmVybGF5RWxlbWVudChib3VuZHMpO1xuICAgICAgICB0aGlzLnJlbmRlcmVyLmFwcGVuZENoaWxkKHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCBvdmVybGF5KTtcbiAgICAgICAgdGhpcy5vdmVybGF5RWxlbWVudHMucHVzaChvdmVybGF5KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHJlbW92ZUNlbGxzT3ZlcmxheSgpIHtcbiAgICB0aGlzLm92ZXJsYXlFbGVtZW50cy5mb3JFYWNoKChvdmVybGF5KSA9PiB7XG4gICAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNoaWxkKHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCBvdmVybGF5KTtcbiAgICB9KTtcbiAgICB0aGlzLm92ZXJsYXlFbGVtZW50cyA9IFtdO1xuICB9XG5cbiAgcHJpdmF0ZSBncm91cENvbnRpZ3VvdXNDZWxscyhjZWxsczogQ1tdKTogQ1tdW10ge1xuICAgIC8vIENyZWF0ZSBhIG1hcCBmb3IgcXVpY2sgbG9va3VwXG4gICAgY29uc3QgY2VsbE1hcCA9IG5ldyBNYXA8c3RyaW5nLCBDPigpO1xuICAgIGNlbGxzLmZvckVhY2goKGNlbGwpID0+IHtcbiAgICAgIGNlbGxNYXAuc2V0KHRoaXMuZ2V0Q2VsbEtleShjZWxsKSwgY2VsbCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB2aXNpdGVkID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgY29uc3QgZ3JvdXBzOiBDW11bXSA9IFtdO1xuXG4gICAgLy8gUHJvY2VzcyBlYWNoIGNlbGxcbiAgICBjZWxscy5mb3JFYWNoKChjZWxsKSA9PiB7XG4gICAgICBjb25zdCBrZXkgPSB0aGlzLmdldENlbGxLZXkoY2VsbCk7XG4gICAgICBpZiAodmlzaXRlZC5oYXMoa2V5KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFN0YXJ0IGEgbmV3IGNvbnRpZ3VvdXMgZ3JvdXAgd2l0aCBmbG9vZC1maWxsXG4gICAgICBjb25zdCBncm91cDogQ1tdID0gW107XG4gICAgICBjb25zdCBxdWV1ZTogQ1tdID0gW2NlbGxdO1xuICAgICAgdmlzaXRlZC5hZGQoa2V5KTtcblxuICAgICAgd2hpbGUgKHF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgY3VycmVudCA9IHF1ZXVlLnNoaWZ0KCkhO1xuICAgICAgICBncm91cC5wdXNoKGN1cnJlbnQpO1xuXG4gICAgICAgIC8vIENoZWNrIGFsbCA0IGFkamFjZW50IGNlbGxzICh1cCwgZG93biwgbGVmdCwgcmlnaHQpXG4gICAgICAgIGNvbnN0IG5laWdoYm9ycyA9IHRoaXMuZ2V0QWRqYWNlbnRDZWxscyhjdXJyZW50KTtcbiAgICAgICAgbmVpZ2hib3JzLmZvckVhY2goKG5laWdoYm9yKSA9PiB7XG4gICAgICAgICAgY29uc3QgbmVpZ2hib3JLZXkgPSB0aGlzLmdldENlbGxLZXkobmVpZ2hib3IpO1xuICAgICAgICAgIGlmIChjZWxsTWFwLmhhcyhuZWlnaGJvcktleSkgJiYgIXZpc2l0ZWQuaGFzKG5laWdoYm9yS2V5KSkge1xuICAgICAgICAgICAgdmlzaXRlZC5hZGQobmVpZ2hib3JLZXkpO1xuICAgICAgICAgICAgcXVldWUucHVzaChuZWlnaGJvcik7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgZ3JvdXBzLnB1c2goZ3JvdXApO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGdyb3VwcztcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QWRqYWNlbnRDZWxscyhjZWxsOiBDKTogQ1tdIHtcbiAgICAvLyBSZXR1cm5zIGNlbGxzIGFkamFjZW50IHRvIHRoZSBjdXJyZW50IGNlbGwgKHVwLCBkb3duLCBsZWZ0LCByaWdodClcbiAgICAvLyBOb3RlOiBXZSBuZWVkIHRvIGdldCBjb2x1bW4gb3JkZXIgZnJvbSB0aGUgYWN0dWFsIHRhYmxlIHN0cnVjdHVyZVxuICAgIC8vIEZvciBub3csIHdlJ2xsIHVzZSBhIHNpbXBsZSBhcHByb2FjaCBiYXNlZCBvbiByb3dJZCBhZGphY2VuY3lcbiAgICByZXR1cm4gW1xuICAgICAgeyByb3dJZDogY2VsbC5yb3dJZCAtIDEsIGNvbHVtbk5hbWU6IGNlbGwuY29sdW1uTmFtZSB9LCAvLyB1cFxuICAgICAgeyByb3dJZDogY2VsbC5yb3dJZCArIDEsIGNvbHVtbk5hbWU6IGNlbGwuY29sdW1uTmFtZSB9LCAvLyBkb3duXG4gICAgICB7IHJvd0lkOiBjZWxsLnJvd0lkLCBjb2x1bW5OYW1lOiB0aGlzLmdldE5leHRDb2x1bW5OYW1lKGNlbGwuY29sdW1uTmFtZSwgLTEpIH0sIC8vIGxlZnRcbiAgICAgIHsgcm93SWQ6IGNlbGwucm93SWQsIGNvbHVtbk5hbWU6IHRoaXMuZ2V0TmV4dENvbHVtbk5hbWUoY2VsbC5jb2x1bW5OYW1lLCAxKSB9LCAvLyByaWdodFxuICAgIF0uZmlsdGVyKChjKSA9PiBjLmNvbHVtbk5hbWUgIT09IG51bGwpIGFzIENbXTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0TmV4dENvbHVtbk5hbWUoY3VycmVudENvbHVtbk5hbWU6IHN0cmluZywgb2Zmc2V0OiBudW1iZXIpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5zZXJ2aWNlLnNlbGVjdGFibGVDb2x1bW5zO1xuXG4gICAgY29uc3QgY3VycmVudEluZGV4ID0gY29sdW1ucy5pbmRleE9mKGN1cnJlbnRDb2x1bW5OYW1lKTtcbiAgICBpZiAoY3VycmVudEluZGV4ID09PSAtMSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgbmV3SW5kZXggPSBjdXJyZW50SW5kZXggKyBvZmZzZXQ7XG4gICAgaWYgKG5ld0luZGV4IDwgMCB8fCBuZXdJbmRleCA+PSBjb2x1bW5zLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbHVtbnNbbmV3SW5kZXhdO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDZWxsS2V5KGNlbGw6IEMpOiBzdHJpbmcge1xuICAgIHJldHVybiBgJHtjZWxsLnJvd0lkfS0ke2NlbGwuY29sdW1uTmFtZX1gO1xuICB9XG5cbiAgcHJpdmF0ZSBjYWxjdWxhdGVTZWxlY3Rpb25Cb3VuZHMoY2VsbHM6IENbXSk6IFNlbGVjdGlvbkJvdW5kcyB8IG51bGwge1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xuXG4gICAgLy8gRmluZCBhbGwgc2VsZWN0ZWQgY2VsbCBlbGVtZW50c1xuICAgIGNvbnN0IGNlbGxFbGVtZW50czogSFRNTEVsZW1lbnRbXSA9IFtdO1xuICAgIGNlbGxzLmZvckVhY2goKGNlbGwpID0+IHtcbiAgICAgIGNvbnN0IGNlbGxFbGVtZW50ID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoYFtkYXRhLXJvdy1pZD1cIiR7Y2VsbC5yb3dJZH1cIl1bZGF0YS1jb2x1bW4tbmFtZT1cIiR7Y2VsbC5jb2x1bW5OYW1lfVwiXWApIGFzIEhUTUxFbGVtZW50O1xuICAgICAgaWYgKGNlbGxFbGVtZW50KSB7XG4gICAgICAgIGNlbGxFbGVtZW50cy5wdXNoKGNlbGxFbGVtZW50KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChpc0VtcHR5QXJyYXkoY2VsbEVsZW1lbnRzKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gR2V0IGNvbnRhaW5lciBwb3NpdGlvblxuICAgIGNvbnN0IGNvbnRhaW5lclJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAvLyBDYWxjdWxhdGUgYm91bmRpbmcgYm94XG4gICAgbGV0IG1pblRvcCA9IEluZmluaXR5O1xuICAgIGxldCBtaW5MZWZ0ID0gSW5maW5pdHk7XG4gICAgbGV0IG1heEJvdHRvbSA9IC1JbmZpbml0eTtcbiAgICBsZXQgbWF4UmlnaHQgPSAtSW5maW5pdHk7XG5cbiAgICBjZWxsRWxlbWVudHMuZm9yRWFjaCgoZWxlbWVudCkgPT4ge1xuICAgICAgY29uc3QgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBtaW5Ub3AgPSBNYXRoLm1pbihtaW5Ub3AsIHJlY3QudG9wIC0gY29udGFpbmVyUmVjdC50b3ApO1xuICAgICAgbWluTGVmdCA9IE1hdGgubWluKG1pbkxlZnQsIHJlY3QubGVmdCAtIGNvbnRhaW5lclJlY3QubGVmdCk7XG4gICAgICBtYXhCb3R0b20gPSBNYXRoLm1heChtYXhCb3R0b20sIHJlY3QuYm90dG9tIC0gY29udGFpbmVyUmVjdC50b3ApO1xuICAgICAgbWF4UmlnaHQgPSBNYXRoLm1heChtYXhSaWdodCwgcmVjdC5yaWdodCAtIGNvbnRhaW5lclJlY3QubGVmdCk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdG9wOiBtaW5Ub3AsXG4gICAgICBsZWZ0OiBtaW5MZWZ0LFxuICAgICAgd2lkdGg6IG1heFJpZ2h0IC0gbWluTGVmdCxcbiAgICAgIGhlaWdodDogbWF4Qm90dG9tIC0gbWluVG9wLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZU92ZXJsYXlFbGVtZW50KGJvdW5kczogU2VsZWN0aW9uQm91bmRzKTogSFRNTEVsZW1lbnQge1xuICAgIGNvbnN0IG92ZXJsYXkgPSB0aGlzLnJlbmRlcmVyLmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3Mob3ZlcmxheSwgJ2NlbGwtc2VsZWN0aW9uLW92ZXJsYXknKTtcblxuICAgIC8vIFNldCBwb3NpdGlvbiBhbmQgc2l6ZVxuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUob3ZlcmxheSwgJ3RvcCcsIGAke2JvdW5kcy50b3B9cHhgKTtcbiAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKG92ZXJsYXksICdsZWZ0JywgYCR7Ym91bmRzLmxlZnR9cHhgKTtcbiAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKG92ZXJsYXksICd3aWR0aCcsIGAke2JvdW5kcy53aWR0aH1weGApO1xuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUob3ZlcmxheSwgJ2hlaWdodCcsIGAke2JvdW5kcy5oZWlnaHR9cHhgKTtcblxuICAgIHJldHVybiBvdmVybGF5O1xuICB9XG59XG4iXX0=
@@ -0,0 +1,180 @@
1
+ import { inject, Injectable, InjectionToken } from '@angular/core';
2
+ import { Subject } from 'rxjs';
3
+ import { isEmptyArray } from '../../functions';
4
+ import * as i0 from "@angular/core";
5
+ export const APP_CELL_SELECTION_SERVICE_TOKEN = new InjectionToken('CellSelectionService');
6
+ export const APP_CELL_SELECTION_SERVICE_CONFIG_TOKEN = new InjectionToken('CellSelectionServiceConfig');
7
+ /**
8
+ * Service to manage cell selection state across multiple directive instances.
9
+ * This service should be provided at the component level (not root) to ensure
10
+ * proper isolation between different table instances.
11
+ */
12
+ export class CellSelectionService {
13
+ // Configuration
14
+ config = inject(APP_CELL_SELECTION_SERVICE_CONFIG_TOKEN, { optional: true });
15
+ selectableColumns = [];
16
+ // Selection state
17
+ selectedCells = [];
18
+ selectionStartCell = null;
19
+ isSelecting = false;
20
+ // Drag state
21
+ draggedCells = [];
22
+ dragStartCell = null;
23
+ isDragging = false;
24
+ // Observables
25
+ selectionChangeSubject = new Subject();
26
+ selectionRightClickSubject = new Subject();
27
+ // Overridable methods
28
+ _equals;
29
+ _new;
30
+ constructor() {
31
+ this._equals = this.config?.equals;
32
+ this._new = this.config?.new;
33
+ }
34
+ // Override method
35
+ equals(cell1, cell2) {
36
+ return this._equals ? this._equals(cell1, cell2) : cell1?.rowId === cell2?.rowId && cell1?.columnName === cell2?.columnName;
37
+ }
38
+ // Override method
39
+ new(cellId) {
40
+ return this._new ? this._new(cellId) : cellId;
41
+ }
42
+ isCellSelected(cellId) {
43
+ return this.selectedCells.some((selectedCell) => this.equals(selectedCell, cellId));
44
+ }
45
+ isCellDragged(cellId) {
46
+ return this.draggedCells.some((selectedCell) => this.equals(selectedCell, cellId));
47
+ }
48
+ // Core selection logic (moved from CellIdentifierDirective)
49
+ async handleCellMouseDown(event, cellId) {
50
+ event.preventDefault();
51
+ if (event.button === 2) {
52
+ event.stopPropagation();
53
+ this.selectionRightClickSubject.next(event);
54
+ return;
55
+ }
56
+ const isCtrlKey = event.ctrlKey || event.metaKey;
57
+ const isShiftKey = event.shiftKey;
58
+ if (!isShiftKey && !isCtrlKey) {
59
+ this.startSelection(cellId);
60
+ // this.startDragSelection(cellId);
61
+ }
62
+ else if (isCtrlKey) {
63
+ this.toggleCellSelection(cellId);
64
+ }
65
+ else if (isShiftKey) {
66
+ this.selectRange(cellId);
67
+ }
68
+ }
69
+ async handleCellMouseEnter(event, cellId) {
70
+ // TODO check if next cell can be selected
71
+ if (this.isSelecting && this.selectionStartCell) {
72
+ this.updateSelection(cellId);
73
+ }
74
+ else if (this.isDragging && this.dragStartCell) {
75
+ this.updateDraggedCells(cellId);
76
+ }
77
+ }
78
+ endMouseMove() {
79
+ if (this.isSelecting) {
80
+ this.resetSelectionState();
81
+ }
82
+ else if (this.isDragging) {
83
+ this.resetDragState();
84
+ }
85
+ }
86
+ // Private helper methods
87
+ startSelection(cellId) {
88
+ this.selectionStartCell = cellId;
89
+ this.isSelecting = true;
90
+ this.emitSelection([cellId], false, false);
91
+ }
92
+ startDragSelection(cellId) {
93
+ this.dragStartCell = cellId;
94
+ this.isDragging = true;
95
+ this.draggedCells = [cellId];
96
+ // this.emitSelection([cellId], false, false);
97
+ }
98
+ toggleCellSelection(cellId) {
99
+ const currentCells = [...this.selectedCells];
100
+ const cellIndex = currentCells.findIndex((c) => this.equals(c, cellId));
101
+ if (cellIndex >= 0) {
102
+ currentCells.splice(cellIndex, 1);
103
+ }
104
+ else {
105
+ currentCells.push(cellId);
106
+ }
107
+ this.emitSelection(currentCells, false, true);
108
+ }
109
+ selectRange(endCell) {
110
+ const rangeCells = this.calculateRangeCells(endCell);
111
+ this.emitSelection(rangeCells, true, false);
112
+ }
113
+ updateSelection(currentCell) {
114
+ const rangeCells = this.calculateRangeBetweenCells(this.selectionStartCell, currentCell);
115
+ this.emitSelection(rangeCells, true, false);
116
+ }
117
+ updateDraggedCells(currentCell) {
118
+ // this.draggedCells.set(rangeCells);
119
+ }
120
+ emitSelection(cells, isRange, isToggle) {
121
+ this.selectedCells = cells;
122
+ this.selectionChangeSubject.next({
123
+ selectedCells: cells,
124
+ isRangeSelection: isRange,
125
+ isToggleSelection: isToggle,
126
+ });
127
+ }
128
+ calculateRangeCells(endCell) {
129
+ if (isEmptyArray(this.selectedCells)) {
130
+ return [endCell];
131
+ }
132
+ const lastSelectedCell = this.findFirstSelectedCell(this.selectedCells);
133
+ return this.calculateRangeBetweenCells(lastSelectedCell, endCell);
134
+ }
135
+ calculateRangeBetweenCells(startCell, endCell) {
136
+ // Get first cell coordinates, then add this cell as a range
137
+ const firstRowId = Math.min(startCell.rowId, endCell.rowId);
138
+ const lastRowId = Math.max(startCell.rowId, endCell.rowId);
139
+ const startColumnIndex = this.selectableColumns.indexOf(startCell.columnName);
140
+ const endColumnIndex = this.selectableColumns.indexOf(endCell.columnName);
141
+ const firstColumnIndex = Math.min(startColumnIndex, endColumnIndex);
142
+ const lastColumnIndex = Math.max(startColumnIndex, endColumnIndex);
143
+ // Iterate columns and rows
144
+ const rangeCells = [];
145
+ for (let i = firstColumnIndex; i <= lastColumnIndex; i++) {
146
+ const columnName = this.selectableColumns[i];
147
+ for (let rowId = firstRowId; rowId <= lastRowId; rowId++) {
148
+ rangeCells.push(this.new({ rowId: rowId, columnName: columnName }));
149
+ }
150
+ }
151
+ return rangeCells;
152
+ }
153
+ resetSelectionState() {
154
+ this.selectionStartCell = null;
155
+ this.isSelecting = false;
156
+ }
157
+ resetDragState() {
158
+ this.dragStartCell = null;
159
+ this.isDragging = false;
160
+ this.draggedCells = [];
161
+ }
162
+ findFirstSelectedCell(selectedCells) {
163
+ // Find the cell with the lowest rowId and columnIndex
164
+ return this.findSelectedCell(selectedCells, Math.min(...selectedCells.map((cell) => cell.rowId)), Math.min(...selectedCells.map((cell) => this.selectableColumns.indexOf(cell.columnName))));
165
+ }
166
+ findLastSelectedCell(selectedCells) {
167
+ // Find the cell with the lowest rowId and columnIndex
168
+ return this.findSelectedCell(selectedCells, Math.max(...selectedCells.map((cell) => cell.rowId)), Math.max(...selectedCells.map((cell) => this.selectableColumns.indexOf(cell.columnName))));
169
+ }
170
+ findSelectedCell(selectedCells, rowId, columnIndex) {
171
+ // Find the cell with the current indexes
172
+ return selectedCells.filter((cell) => cell.rowId === rowId && cell.columnName === this.selectableColumns[columnIndex])[0];
173
+ }
174
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CellSelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
175
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CellSelectionService });
176
+ }
177
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CellSelectionService, decorators: [{
178
+ type: Injectable
179
+ }], ctorParameters: () => [] });
180
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VsbC1zZWxlY3Rpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvc2hhcmVkL2RpcmVjdGl2ZXMvY2VsbC1zZWxlY3Rpb24vY2VsbC1zZWxlY3Rpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7O0FBRy9DLE1BQU0sQ0FBQyxNQUFNLGdDQUFnQyxHQUFHLElBQUksY0FBYyxDQUF1QixzQkFBc0IsQ0FBQyxDQUFDO0FBQ2pILE1BQU0sQ0FBQyxNQUFNLHVDQUF1QyxHQUFHLElBQUksY0FBYyxDQUFrQyw0QkFBNEIsQ0FBQyxDQUFDO0FBa0J6STs7OztHQUlHO0FBRUgsTUFBTSxPQUFPLG9CQUFvQjtJQUMvQixnQkFBZ0I7SUFDaEIsTUFBTSxHQUFHLE1BQU0sQ0FBQyx1Q0FBdUMsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzdFLGlCQUFpQixHQUFhLEVBQUUsQ0FBQztJQUVqQyxrQkFBa0I7SUFDbEIsYUFBYSxHQUFRLEVBQUUsQ0FBQztJQUNoQixrQkFBa0IsR0FBYSxJQUFJLENBQUM7SUFDcEMsV0FBVyxHQUFHLEtBQUssQ0FBQztJQUU1QixhQUFhO0lBQ2IsWUFBWSxHQUFRLEVBQUUsQ0FBQztJQUNmLGFBQWEsR0FBYSxJQUFJLENBQUM7SUFDL0IsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUUzQixjQUFjO0lBQ0wsc0JBQXNCLEdBQUcsSUFBSSxPQUFPLEVBQXlCLENBQUM7SUFDOUQsMEJBQTBCLEdBQUcsSUFBSSxPQUFPLEVBQWMsQ0FBQztJQUVoRSxzQkFBc0I7SUFD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LENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLEtBQUssSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVILENBQUM7d0dBdE1VLG9CQUFvQjs0R0FBcEIsb0JBQW9COzs0RkFBcEIsb0JBQW9CO2tCQURoQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBJbmplY3RhYmxlLCBJbmplY3Rpb25Ub2tlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgaXNFbXB0eUFycmF5IH0gZnJvbSAnLi4vLi4vZnVuY3Rpb25zJztcbmltcG9ydCB7IEVxdWFsc0ZuIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuXG5leHBvcnQgY29uc3QgQVBQX0NFTExfU0VMRUNUSU9OX1NFUlZJQ0VfVE9LRU4gPSBuZXcgSW5qZWN0aW9uVG9rZW48Q2VsbFNlbGVjdGlvblNlcnZpY2U+KCdDZWxsU2VsZWN0aW9uU2VydmljZScpO1xuZXhwb3J0IGNvbnN0IEFQUF9DRUxMX1NFTEVDVElPTl9TRVJWSUNFX0NPTkZJR19UT0tFTiA9IG5ldyBJbmplY3Rpb25Ub2tlbjxDZWxsU2VsZWN0aW9uU2VydmljZUNvbmZpZzxhbnk+PignQ2VsbFNlbGVjdGlvblNlcnZpY2VDb25maWcnKTtcblxuZXhwb3J0IGludGVyZmFjZSBJQ2VsbElkIHtcbiAgcm93SWQ6IG51bWJlcjtcbiAgY29sdW1uTmFtZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENlbGxTZWxlY3Rpb25FdmVudDxDIGV4dGVuZHMgSUNlbGxJZD4ge1xuICBzZWxlY3RlZENlbGxzOiBDW107XG4gIGlzUmFuZ2VTZWxlY3Rpb246IGJvb2xlYW47XG4gIGlzVG9nZ2xlU2VsZWN0aW9uOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENlbGxTZWxlY3Rpb25TZXJ2aWNlQ29uZmlnPEMgZXh0ZW5kcyBJQ2VsbElkPiB7XG4gIGVxdWFsczogRXF1YWxzRm48Qz47XG4gIG5ldzogKGNlbGxJZDogSUNlbGxJZCkgPT4gQztcbn1cblxuLyoqXG4gKiBTZXJ2aWNlIHRvIG1hbmFnZSBjZWxsIHNlbGVjdGlvbiBzdGF0ZSBhY3Jvc3MgbXVsdGlwbGUgZGlyZWN0aXZlIGluc3RhbmNlcy5cbiAqIFRoaXMgc2VydmljZSBzaG91bGQgYmUgcHJvdmlkZWQgYXQgdGhlIGNvbXBvbmVudCBsZXZlbCAobm90IHJvb3QpIHRvIGVuc3VyZVxuICogcHJvcGVyIGlzb2xhdGlvbiBiZXR3ZWVuIGRpZmZlcmVudCB0YWJsZSBpbnN0YW5jZXMuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBDZWxsU2VsZWN0aW9uU2VydmljZTxDIGV4dGVuZHMgSUNlbGxJZCA9IElDZWxsSWQ+IHtcbiAgLy8gQ29uZmlndXJhdGlvblxuICBjb25maWcgPSBpbmplY3QoQVBQX0NFTExfU0VMRUNUSU9OX1NFUlZJQ0VfQ09ORklHX1RPS0VOLCB7IG9wdGlvbmFsOiB0cnVlIH0pO1xuICBzZWxlY3RhYmxlQ29sdW1uczogc3RyaW5nW10gPSBbXTtcblxuICAvLyBTZWxlY3Rpb24gc3RhdGVcbiAgc2VsZWN0ZWRDZWxsczogQ1tdID0gW107XG4gIHByaXZhdGUgc2VsZWN0aW9uU3RhcnRDZWxsOiBDIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgaXNTZWxlY3RpbmcgPSBmYWxzZTtcblxuICAvLyBEcmFnIHN0YXRlXG4gIGRyYWdnZWRDZWxsczogQ1tdID0gW107XG4gIHByaXZhdGUgZHJhZ1N0YXJ0Q2VsbDogQyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGlzRHJhZ2dpbmcgPSBmYWxzZTtcblxuICAvLyBPYnNlcnZhYmxlc1xuICByZWFkb25seSBzZWxlY3Rpb25DaGFuZ2VTdWJqZWN0ID0gbmV3IFN1YmplY3Q8Q2VsbFNlbGVjdGlvbkV2ZW50PEM+PigpO1xuICByZWFkb25seSBzZWxlY3Rpb25SaWdodENsaWNrU3ViamVjdCA9IG5ldyBTdWJqZWN0PE1vdXNlRXZlbnQ+KCk7XG5cbiAgLy8gT3ZlcnJpZGFibGUgbWV0aG9kc1xuICBwcml2YXRlIHJlYWRvbmx5IF9lcXVhbHM6IEVxdWFsc0ZuPEM+O1xuICBwcml2YXRlIHJlYWRvbmx5IF9uZXc6IChjZWxsSWQ6IElDZWxsSWQpID0+IEM7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5fZXF1YWxzID0gdGhpcy5jb25maWc/LmVxdWFscztcbiAgICB0aGlzLl9uZXcgPSB0aGlzLmNvbmZpZz8ubmV3O1xuICB9XG5cbiAgLy8gT3ZlcnJpZGUgbWV0aG9kXG4gIGVxdWFscyhjZWxsMTogQywgY2VsbDI6IEMpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZXF1YWxzID8gdGhpcy5fZXF1YWxzKGNlbGwxLCBjZWxsMikgOiBjZWxsMT8ucm93SWQgPT09IGNlbGwyPy5yb3dJZCAmJiBjZWxsMT8uY29sdW1uTmFtZSA9PT0gY2VsbDI/LmNvbHVtbk5hbWU7XG4gIH1cblxuICAvLyBPdmVycmlkZSBtZXRob2RcbiAgbmV3KGNlbGxJZDogSUNlbGxJZCk6IEMge1xuICAgIHJldHVybiB0aGlzLl9uZXcgPyB0aGlzLl9uZXcoY2VsbElkKSA6IChjZWxsSWQgYXMgQyk7XG4gIH1cblxuICBpc0NlbGxTZWxlY3RlZChjZWxsSWQ6IEMpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZENlbGxzLnNvbWUoKHNlbGVjdGVkQ2VsbCkgPT4gdGhpcy5lcXVhbHMoc2VsZWN0ZWRDZWxsLCBjZWxsSWQpKTtcbiAgfVxuXG4gIGlzQ2VsbERyYWdnZWQoY2VsbElkOiBDKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZHJhZ2dlZENlbGxzLnNvbWUoKHNlbGVjdGVkQ2VsbCkgPT4gdGhpcy5lcXVhbHMoc2VsZWN0ZWRDZWxsLCBjZWxsSWQpKTtcbiAgfVxuXG4gIC8vIENvcmUgc2VsZWN0aW9uIGxvZ2ljIChtb3ZlZCBmcm9tIENlbGxJZGVudGlmaWVyRGlyZWN0aXZlKVxuICBhc3luYyBoYW5kbGVDZWxsTW91c2VEb3duKGV2ZW50OiBNb3VzZUV2ZW50LCBjZWxsSWQ6IEMpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgaWYgKGV2ZW50LmJ1dHRvbiA9PT0gMikge1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICB0aGlzLnNlbGVjdGlvblJpZ2h0Q2xpY2tTdWJqZWN0Lm5leHQoZXZlbnQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGlzQ3RybEtleSA9IGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQubWV0YUtleTtcbiAgICBjb25zdCBpc1NoaWZ0S2V5ID0gZXZlbnQuc2hpZnRLZXk7XG5cbiAgICBpZiAoIWlzU2hpZnRLZXkgJiYgIWlzQ3RybEtleSkge1xuICAgICAgdGhpcy5zdGFydFNlbGVjdGlvbihjZWxsSWQpO1xuICAgICAgLy8gdGhpcy5zdGFydERyYWdTZWxlY3Rpb24oY2VsbElkKTtcbiAgICB9IGVsc2UgaWYgKGlzQ3RybEtleSkge1xuICAgICAgdGhpcy50b2dnbGVDZWxsU2VsZWN0aW9uKGNlbGxJZCk7XG4gICAgfSBlbHNlIGlmIChpc1NoaWZ0S2V5KSB7XG4gICAgICB0aGlzLnNlbGVjdFJhbmdlKGNlbGxJZCk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgaGFuZGxlQ2VsbE1vdXNlRW50ZXIoZXZlbnQ6IE1vdXNlRXZlbnQsIGNlbGxJZDogQykge1xuICAgIC8vIFRPRE8gY2hlY2sgaWYgbmV4dCBjZWxsIGNhbiBiZSBzZWxlY3RlZFxuXG4gICAgaWYgKHRoaXMuaXNTZWxlY3RpbmcgJiYgdGhpcy5zZWxlY3Rpb25TdGFydENlbGwpIHtcbiAgICAgIHRoaXMudXBkYXRlU2VsZWN0aW9uKGNlbGxJZCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmlzRHJhZ2dpbmcgJiYgdGhpcy5kcmFnU3RhcnRDZWxsKSB7XG4gICAgICB0aGlzLnVwZGF0ZURyYWdnZWRDZWxscyhjZWxsSWQpO1xuICAgIH1cbiAgfVxuXG4gIGVuZE1vdXNlTW92ZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc1NlbGVjdGluZykge1xuICAgICAgdGhpcy5yZXNldFNlbGVjdGlvblN0YXRlKCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmlzRHJhZ2dpbmcpIHtcbiAgICAgIHRoaXMucmVzZXREcmFnU3RhdGUoKTtcbiAgICB9XG4gIH1cblxuICAvLyBQcml2YXRlIGhlbHBlciBtZXRob2RzXG4gIHByaXZhdGUgc3RhcnRTZWxlY3Rpb24oY2VsbElkOiBDKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3Rpb25TdGFydENlbGwgPSBjZWxsSWQ7XG4gICAgdGhpcy5pc1NlbGVjdGluZyA9IHRydWU7XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKFtjZWxsSWRdLCBmYWxzZSwgZmFsc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGFydERyYWdTZWxlY3Rpb24oY2VsbElkOiBDKTogdm9pZCB7XG4gICAgdGhpcy5kcmFnU3RhcnRDZWxsID0gY2VsbElkO1xuICAgIHRoaXMuaXNEcmFnZ2luZyA9IHRydWU7XG4gICAgdGhpcy5kcmFnZ2VkQ2VsbHMgPSBbY2VsbElkXTtcbiAgICAvLyB0aGlzLmVtaXRTZWxlY3Rpb24oW2NlbGxJZF0sIGZhbHNlLCBmYWxzZSk7XG4gIH1cblxuICBwcml2YXRlIHRvZ2dsZUNlbGxTZWxlY3Rpb24oY2VsbElkOiBDKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudENlbGxzID0gWy4uLnRoaXMuc2VsZWN0ZWRDZWxsc107XG4gICAgY29uc3QgY2VsbEluZGV4ID0gY3VycmVudENlbGxzLmZpbmRJbmRleCgoYykgPT4gdGhpcy5lcXVhbHMoYywgY2VsbElkKSk7XG5cbiAgICBpZiAoY2VsbEluZGV4ID49IDApIHtcbiAgICAgIGN1cnJlbnRDZWxscy5zcGxpY2UoY2VsbEluZGV4LCAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY3VycmVudENlbGxzLnB1c2goY2VsbElkKTtcbiAgICB9XG5cbiAgICB0aGlzLmVtaXRTZWxlY3Rpb24oY3VycmVudENlbGxzLCBmYWxzZSwgdHJ1ZSk7XG4gIH1cblxuICBwcml2YXRlIHNlbGVjdFJhbmdlKGVuZENlbGw6IEMpOiB2b2lkIHtcbiAgICBjb25zdCByYW5nZUNlbGxzID0gdGhpcy5jYWxjdWxhdGVSYW5nZUNlbGxzKGVuZENlbGwpO1xuICAgIHRoaXMuZW1pdFNlbGVjdGlvbihyYW5nZUNlbGxzLCB0cnVlLCBmYWxzZSk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVNlbGVjdGlvbihjdXJyZW50Q2VsbDogQyk6IHZvaWQge1xuICAgIGNvbnN0IHJhbmdlQ2VsbHMgPSB0aGlzLmNhbGN1bGF0ZVJhbmdlQmV0d2VlbkNlbGxzKHRoaXMuc2VsZWN0aW9uU3RhcnRDZWxsLCBjdXJyZW50Q2VsbCk7XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKHJhbmdlQ2VsbHMsIHRydWUsIGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlRHJhZ2dlZENlbGxzKGN1cnJlbnRDZWxsOiBDKTogdm9pZCB7XG4gICAgLy8gdGhpcy5kcmFnZ2VkQ2VsbHMuc2V0KHJhbmdlQ2VsbHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbWl0U2VsZWN0aW9uKGNlbGxzOiBDW10sIGlzUmFuZ2U6IGJvb2xlYW4sIGlzVG9nZ2xlOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZENlbGxzID0gY2VsbHM7XG4gICAgdGhpcy5zZWxlY3Rpb25DaGFuZ2VTdWJqZWN0Lm5leHQoe1xuICAgICAgc2VsZWN0ZWRDZWxsczogY2VsbHMsXG4gICAgICBpc1JhbmdlU2VsZWN0aW9uOiBpc1JhbmdlLFxuICAgICAgaXNUb2dnbGVTZWxlY3Rpb246IGlzVG9nZ2xlLFxuICAgIH0pO1xuICB9XG5cbiAgY2FsY3VsYXRlUmFuZ2VDZWxscyhlbmRDZWxsOiBDKTogQ1tdIHtcbiAgICBpZiAoaXNFbXB0eUFycmF5KHRoaXMuc2VsZWN0ZWRDZWxscykpIHtcbiAgICAgIHJldHVybiBbZW5kQ2VsbF07XG4gICAgfVxuXG4gICAgY29uc3QgbGFzdFNlbGVjdGVkQ2VsbCA9IHRoaXMuZmluZEZpcnN0U2VsZWN0ZWRDZWxsKHRoaXMuc2VsZWN0ZWRDZWxscyk7XG4gICAgcmV0dXJuIHRoaXMuY2FsY3VsYXRlUmFuZ2VCZXR3ZWVuQ2VsbHMobGFzdFNlbGVjdGVkQ2VsbCwgZW5kQ2VsbCk7XG4gIH1cblxuICBjYWxjdWxhdGVSYW5nZUJldHdlZW5DZWxscyhzdGFydENlbGw6IEMsIGVuZENlbGw6IEMpOiBDW10ge1xuICAgIC8vIEdldCBmaXJzdCBjZWxsIGNvb3JkaW5hdGVzLCB0aGVuIGFkZCB0aGlzIGNlbGwgYXMgYSByYW5nZVxuICAgIGNvbnN0IGZpcnN0Um93SWQgPSBNYXRoLm1pbihzdGFydENlbGwucm93SWQsIGVuZENlbGwucm93SWQpO1xuICAgIGNvbnN0IGxhc3RSb3dJZCA9IE1hdGgubWF4KHN0YXJ0Q2VsbC5yb3dJZCwgZW5kQ2VsbC5yb3dJZCk7XG4gICAgY29uc3Qgc3RhcnRDb2x1bW5JbmRleCA9IHRoaXMuc2VsZWN0YWJsZUNvbHVtbnMuaW5kZXhPZihzdGFydENlbGwuY29sdW1uTmFtZSk7XG4gICAgY29uc3QgZW5kQ29sdW1uSW5kZXggPSB0aGlzLnNlbGVjdGFibGVDb2x1bW5zLmluZGV4T2YoZW5kQ2VsbC5jb2x1bW5OYW1lKTtcbiAgICBjb25zdCBmaXJzdENvbHVtbkluZGV4ID0gTWF0aC5taW4oc3RhcnRDb2x1bW5JbmRleCwgZW5kQ29sdW1uSW5kZXgpO1xuICAgIGNvbnN0IGxhc3RDb2x1bW5JbmRleCA9IE1hdGgubWF4KHN0YXJ0Q29sdW1uSW5kZXgsIGVuZENvbHVtbkluZGV4KTtcbiAgICAvLyBJdGVyYXRlIGNvbHVtbnMgYW5kIHJvd3NcbiAgICBjb25zdCByYW5nZUNlbGxzOiBDW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gZmlyc3RDb2x1bW5JbmRleDsgaSA8PSBsYXN0Q29sdW1uSW5kZXg7IGkrKykge1xuICAgICAgY29uc3QgY29sdW1uTmFtZSA9IHRoaXMuc2VsZWN0YWJsZUNvbHVtbnNbaV07XG4gICAgICBmb3IgKGxldCByb3dJZCA9IGZpcnN0Um93SWQ7IHJvd0lkIDw9IGxhc3RSb3dJZDsgcm93SWQrKykge1xuICAgICAgICByYW5nZUNlbGxzLnB1c2godGhpcy5uZXcoeyByb3dJZDogcm93SWQsIGNvbHVtbk5hbWU6IGNvbHVtbk5hbWUgfSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByYW5nZUNlbGxzO1xuICB9XG5cbiAgcmVzZXRTZWxlY3Rpb25TdGF0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGlvblN0YXJ0Q2VsbCA9IG51bGw7XG4gICAgdGhpcy5pc1NlbGVjdGluZyA9IGZhbHNlO1xuICB9XG5cbiAgcmVzZXREcmFnU3RhdGUoKTogdm9pZCB7XG4gICAgdGhpcy5kcmFnU3RhcnRDZWxsID0gbnVsbDtcbiAgICB0aGlzLmlzRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICB0aGlzLmRyYWdnZWRDZWxscyA9IFtdO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kRmlyc3RTZWxlY3RlZENlbGwoc2VsZWN0ZWRDZWxsczogQ1tdKTogQyB7XG4gICAgLy8gRmluZCB0aGUgY2VsbCB3aXRoIHRoZSBsb3dlc3Qgcm93SWQgYW5kIGNvbHVtbkluZGV4XG4gICAgcmV0dXJuIHRoaXMuZmluZFNlbGVjdGVkQ2VsbChcbiAgICAgIHNlbGVjdGVkQ2VsbHMsXG4gICAgICBNYXRoLm1pbiguLi5zZWxlY3RlZENlbGxzLm1hcCgoY2VsbCkgPT4gY2VsbC5yb3dJZCkpLFxuICAgICAgTWF0aC5taW4oLi4uc2VsZWN0ZWRDZWxscy5tYXAoKGNlbGwpID0+IHRoaXMuc2VsZWN0YWJsZUNvbHVtbnMuaW5kZXhPZihjZWxsLmNvbHVtbk5hbWUpKSlcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kTGFzdFNlbGVjdGVkQ2VsbChzZWxlY3RlZENlbGxzOiBDW10pOiBDIHtcbiAgICAvLyBGaW5kIHRoZSBjZWxsIHdpdGggdGhlIGxvd2VzdCByb3dJZCBhbmQgY29sdW1uSW5kZXhcbiAgICByZXR1cm4gdGhpcy5maW5kU2VsZWN0ZWRDZWxsKFxuICAgICAgc2VsZWN0ZWRDZWxscyxcbiAgICAgIE1hdGgubWF4KC4uLnNlbGVjdGVkQ2VsbHMubWFwKChjZWxsKSA9PiBjZWxsLnJvd0lkKSksXG4gICAgICBNYXRoLm1heCguLi5zZWxlY3RlZENlbGxzLm1hcCgoY2VsbCkgPT4gdGhpcy5zZWxlY3RhYmxlQ29sdW1ucy5pbmRleE9mKGNlbGwuY29sdW1uTmFtZSkpKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGZpbmRTZWxlY3RlZENlbGwoc2VsZWN0ZWRDZWxsczogQ1tdLCByb3dJZDogbnVtYmVyLCBjb2x1bW5JbmRleDogbnVtYmVyKTogQyB7XG4gICAgLy8gRmluZCB0aGUgY2VsbCB3aXRoIHRoZSBjdXJyZW50IGluZGV4ZXNcbiAgICByZXR1cm4gc2VsZWN0ZWRDZWxscy5maWx0ZXIoKGNlbGwpID0+IGNlbGwucm93SWQgPT09IHJvd0lkICYmIGNlbGwuY29sdW1uTmFtZSA9PT0gdGhpcy5zZWxlY3RhYmxlQ29sdW1uc1tjb2x1bW5JbmRleF0pWzBdO1xuICB9XG59XG4iXX0=