@one-grid-core/angular 0.1.0-beta.5 → 0.2.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 (66) hide show
  1. package/README.md +49 -4
  2. package/esm2022/lib/components/one-grid/one-grid.component.mjs +67 -16
  3. package/esm2022/lib/components/one-grid-body/one-grid-body.component.mjs +282 -30
  4. package/esm2022/lib/components/one-grid-cell-group-renderer/one-grid-cell-group-renderer.component.mjs +10 -7
  5. package/esm2022/lib/components/one-grid-cell-option-menu/one-grid-cell-option-menu.component.mjs +60 -4
  6. package/esm2022/lib/components/one-grid-checkbox-header/one-grid-checkbox-header.component.mjs +14 -5
  7. package/esm2022/lib/components/one-grid-header/one-grid-header.component.mjs +50 -13
  8. package/esm2022/lib/components/one-grid-pagination/one-grid-pagination.component.mjs +39 -15
  9. package/esm2022/lib/components/one-grid-row-action/one-grid-row-action.component.mjs +54 -8
  10. package/esm2022/lib/components/one-grid-row-drag-handle/one-grid-row-drag-handle.component.mjs +110 -0
  11. package/esm2022/lib/core/directives/one-cell-renderer-component.directive.mjs +9 -2
  12. package/esm2022/lib/core/directives/one-cell-text-expand.directive.mjs +33 -51
  13. package/esm2022/lib/core/instants/one-grid-api.class.mjs +429 -166
  14. package/esm2022/lib/core/instants/one-row-node.class.mjs +103 -37
  15. package/esm2022/lib/core/models/one-column-def-types.model.mjs +1 -1
  16. package/esm2022/lib/core/models/one-event-types.model.mjs +1 -1
  17. package/esm2022/lib/core/models/one-grid-types.model.mjs +1 -1
  18. package/esm2022/lib/core/models/one-row-drag.model.mjs +2 -0
  19. package/esm2022/lib/core/models/one-row.model.mjs +1 -1
  20. package/esm2022/lib/core/models/one-tree-data.model.mjs +1 -1
  21. package/esm2022/lib/core/models/one-validation.model.mjs +1 -1
  22. package/esm2022/lib/core/pipes/cell-field-value-empty.pipe.mjs +8 -3
  23. package/esm2022/lib/core/pipes/column-sort-state.pipe.mjs +3 -1
  24. package/esm2022/lib/core/services/og-column.service.mjs +120 -13
  25. package/esm2022/lib/core/services/one-grid-cell.service.mjs +123 -20
  26. package/esm2022/lib/core/services/one-grid-row-drag.service.mjs +351 -0
  27. package/esm2022/lib/core/services/one-grid-selection.service.mjs +19 -6
  28. package/esm2022/lib/helpers/one-column-def.helper.mjs +27 -2
  29. package/esm2022/lib/helpers/one-filter.helper.mjs +71 -12
  30. package/esm2022/lib/helpers/one-validation.helper.mjs +7 -2
  31. package/esm2022/lib/index.mjs +8 -1
  32. package/esm2022/lib/one-grid.module.mjs +7 -16
  33. package/fesm2022/one-grid-core-angular.mjs +2046 -503
  34. package/fesm2022/one-grid-core-angular.mjs.map +1 -1
  35. package/lib/components/one-grid/one-grid.component.d.ts +16 -1
  36. package/lib/components/one-grid-body/one-grid-body.component.d.ts +132 -5
  37. package/lib/components/one-grid-cell-group-renderer/one-grid-cell-group-renderer.component.d.ts +6 -1
  38. package/lib/components/one-grid-cell-option-menu/one-grid-cell-option-menu.component.d.ts +19 -2
  39. package/lib/components/one-grid-checkbox-header/one-grid-checkbox-header.component.d.ts +5 -2
  40. package/lib/components/one-grid-header/one-grid-header.component.d.ts +15 -7
  41. package/lib/components/one-grid-pagination/one-grid-pagination.component.d.ts +24 -5
  42. package/lib/components/one-grid-row-action/one-grid-row-action.component.d.ts +44 -0
  43. package/lib/components/one-grid-row-drag-handle/one-grid-row-drag-handle.component.d.ts +39 -0
  44. package/lib/core/directives/one-cell-text-expand.directive.d.ts +21 -9
  45. package/lib/core/instants/one-grid-api.class.d.ts +212 -26
  46. package/lib/core/instants/one-row-node.class.d.ts +67 -14
  47. package/lib/core/models/one-column-def-types.model.d.ts +89 -15
  48. package/lib/core/models/one-event-types.model.d.ts +24 -1
  49. package/lib/core/models/one-grid-types.model.d.ts +36 -1
  50. package/lib/core/models/one-row-drag.model.d.ts +44 -0
  51. package/lib/core/models/one-row.model.d.ts +0 -5
  52. package/lib/core/models/one-tree-data.model.d.ts +13 -0
  53. package/lib/core/models/one-validation.model.d.ts +12 -2
  54. package/lib/core/pipes/column-sort-state.pipe.d.ts +1 -1
  55. package/lib/core/services/og-column.service.d.ts +44 -3
  56. package/lib/core/services/one-grid-cell.service.d.ts +52 -4
  57. package/lib/core/services/one-grid-row-drag.service.d.ts +113 -0
  58. package/lib/core/services/one-grid-selection.service.d.ts +9 -0
  59. package/lib/helpers/one-column-def.helper.d.ts +19 -1
  60. package/lib/helpers/one-filter.helper.d.ts +29 -4
  61. package/lib/index.d.ts +7 -0
  62. package/lib/one-grid.module.d.ts +17 -19
  63. package/package.json +1 -2
  64. package/scss/_one-grid.scss +389 -17
  65. package/esm2022/lib/core/pipes/cell-disable-resolver.pipe.mjs +0 -26
  66. package/lib/core/pipes/cell-disable-resolver.pipe.d.ts +0 -9
@@ -0,0 +1,351 @@
1
+ import { Injectable, NgZone, inject } from '@angular/core';
2
+ import { BehaviorSubject } from 'rxjs';
3
+ import * as i0 from "@angular/core";
4
+ /** Pointer distance before a press becomes a drag. */
5
+ const DRAG_THRESHOLD_PX = 4;
6
+ /** How close to an edge auto-scroll kicks in, and how fast it goes. */
7
+ const EDGE_ZONE_PX = 36;
8
+ const EDGE_SPEED_PX = 12;
9
+ /**
10
+ * Owns one row-drag gesture at a time.
11
+ *
12
+ * Built on pointer events rather than HTML5 drag-and-drop or the CDK's
13
+ * drag-drop:
14
+ *
15
+ * - HTML5 DnD does not fire for touch at all, and its drag image cannot be
16
+ * styled to match the grid.
17
+ * - `cdkDropList` assumes every item it manages is in the DOM. Inside a virtual
18
+ * scroll viewport rows unmount as they leave the buffer, so the list it
19
+ * thinks it is sorting is only ever the visible window.
20
+ * - Pointer events cover mouse, touch and pen in one path, and pointer capture
21
+ * keeps the gesture alive when the finger leaves the row it started on.
22
+ *
23
+ * Because rows are a fixed `itemSize`, the drop target is arithmetic on the
24
+ * pointer's Y rather than a hit test against row elements — which is also why
25
+ * it stays correct for rows that are scrolled out and not rendered.
26
+ */
27
+ export class OneGridRowDragService {
28
+ constructor() {
29
+ this.zone = inject(NgZone);
30
+ /** Live drag, for the body to render the handle state and the indicator. */
31
+ this.state$ = new BehaviorSubject(null);
32
+ /** Screen-reader narration for the keyboard path. */
33
+ this.announcement$ = new BehaviorSubject('');
34
+ this.context = null;
35
+ this.pointerId = null;
36
+ this.handle = null;
37
+ this.startY = 0;
38
+ this.armed = false;
39
+ this.lastClientY = 0;
40
+ this.scrollFrame = null;
41
+ /** A move already applied during this drag, so a cancel can undo it. */
42
+ this.appliedFrom = null;
43
+ this.handlePointerMove = (event) => {
44
+ if (this.pointerId === null || event.pointerId !== this.pointerId)
45
+ return;
46
+ if (!this.armed) {
47
+ if (Math.abs(event.clientY - this.startY) < DRAG_THRESHOLD_PX)
48
+ return;
49
+ this.armed = true;
50
+ this.publish({ rowId: this.nodeAt(this.appliedFrom)?.rowId ?? '', fromIndex: this.appliedFrom, insertAt: this.appliedFrom, source: 'pointer' });
51
+ }
52
+ // Held so the auto-scroll loop can recompute the target as the viewport
53
+ // moves under a stationary finger.
54
+ this.lastClientY = event.clientY;
55
+ // Touch scrolling would otherwise pan the viewport out from under us.
56
+ event.preventDefault();
57
+ this.updateFromPointer();
58
+ this.updateAutoScroll();
59
+ };
60
+ this.handlePointerUp = (event) => {
61
+ if (this.pointerId === null || event.pointerId !== this.pointerId)
62
+ return;
63
+ const dragged = this.armed;
64
+ this.teardownPointer();
65
+ if (!dragged) {
66
+ this.reset();
67
+ return;
68
+ }
69
+ this.commit('pointer');
70
+ };
71
+ this.handlePointerCancel = () => {
72
+ this.teardownPointer();
73
+ this.cancel();
74
+ };
75
+ /** Escape aborts a pointer drag, the same as it does a keyboard one. */
76
+ this.handlePointerKeydown = (event) => {
77
+ if (event.key !== 'Escape')
78
+ return;
79
+ event.preventDefault();
80
+ this.teardownPointer();
81
+ this.cancel();
82
+ };
83
+ }
84
+ attach(context) {
85
+ this.context = context;
86
+ }
87
+ get state() {
88
+ return this.state$.value;
89
+ }
90
+ get dragging() {
91
+ return this.state$.value !== null;
92
+ }
93
+ // -------------------------------------------------------------------------
94
+ // Pointer
95
+ // -------------------------------------------------------------------------
96
+ /**
97
+ * Begin a pointer drag. Nothing visible happens until the pointer has moved
98
+ * {@link DRAG_THRESHOLD_PX}, so a click on the handle — which is also the
99
+ * keyboard affordance — is not swallowed by a zero-distance drag.
100
+ */
101
+ startPointerDrag(event, node, handlers = {}) {
102
+ if (!this.context || this.dragging || this.pointerId !== null)
103
+ return;
104
+ // Secondary buttons open context menus; they are not a drag.
105
+ if (event.button !== 0)
106
+ return;
107
+ const index = this.indexOf(node);
108
+ if (index === -1)
109
+ return;
110
+ this.pointerId = event.pointerId;
111
+ this.handle = event.target;
112
+ this.startY = event.clientY;
113
+ this.lastClientY = event.clientY;
114
+ this.armed = false;
115
+ this.appliedFrom = index;
116
+ this.onEnd = handlers.onEnd;
117
+ this.handle.setPointerCapture?.(event.pointerId);
118
+ // Outside Angular: pointermove fires at the display's refresh rate and
119
+ // every one of them would otherwise run change detection over the grid.
120
+ // The few that change the drop target re-enter through `publish`.
121
+ this.zone.runOutsideAngular(() => {
122
+ document.addEventListener('pointermove', this.handlePointerMove, { passive: false });
123
+ document.addEventListener('pointerup', this.handlePointerUp);
124
+ document.addEventListener('pointercancel', this.handlePointerCancel);
125
+ document.addEventListener('keydown', this.handlePointerKeydown);
126
+ });
127
+ }
128
+ /**
129
+ * Turn the pointer's Y into an insertion boundary.
130
+ *
131
+ * Boundaries, not rows: the value is where the row would be *inserted*, so
132
+ * 0 is above the first row and `length` is below the last. Rounding rather
133
+ * than flooring puts the split at the middle of each row, which is what
134
+ * makes the indicator flip when you cross the halfway point.
135
+ */
136
+ updateFromPointer() {
137
+ const current = this.state$.value;
138
+ if (!this.context || !current)
139
+ return;
140
+ const rect = this.context.viewport.getBoundingClientRect();
141
+ const offset = this.lastClientY - rect.top + this.context.viewport.scrollTop;
142
+ const insertAt = this.clamp(Math.round(offset / this.context.itemSize), 0, this.context.nodes().length);
143
+ if (insertAt === current.insertAt)
144
+ return;
145
+ this.publish({ ...current, insertAt });
146
+ }
147
+ /**
148
+ * Scroll when the pointer sits near an edge, so rows outside the viewport
149
+ * are reachable without letting go. Runs on rAF while the pointer is parked
150
+ * in the zone, and re-derives the target each frame because the content
151
+ * moves while the pointer does not.
152
+ */
153
+ updateAutoScroll() {
154
+ if (!this.context)
155
+ return;
156
+ const rect = this.context.viewport.getBoundingClientRect();
157
+ const distanceToTop = this.lastClientY - rect.top;
158
+ const distanceToBottom = rect.bottom - this.lastClientY;
159
+ let delta = 0;
160
+ if (distanceToTop < EDGE_ZONE_PX)
161
+ delta = -EDGE_SPEED_PX;
162
+ else if (distanceToBottom < EDGE_ZONE_PX)
163
+ delta = EDGE_SPEED_PX;
164
+ if (delta === 0) {
165
+ this.stopAutoScroll();
166
+ return;
167
+ }
168
+ if (this.scrollFrame !== null)
169
+ return;
170
+ const step = () => {
171
+ if (!this.context || !this.dragging) {
172
+ this.stopAutoScroll();
173
+ return;
174
+ }
175
+ const viewport = this.context.viewport;
176
+ const before = viewport.scrollTop;
177
+ viewport.scrollTop = before + delta;
178
+ // Hit the end — nothing more to reveal, so stop burning frames.
179
+ if (viewport.scrollTop === before) {
180
+ this.stopAutoScroll();
181
+ return;
182
+ }
183
+ this.updateFromPointer();
184
+ this.scrollFrame = requestAnimationFrame(step);
185
+ };
186
+ this.scrollFrame = requestAnimationFrame(step);
187
+ }
188
+ stopAutoScroll() {
189
+ if (this.scrollFrame === null)
190
+ return;
191
+ cancelAnimationFrame(this.scrollFrame);
192
+ this.scrollFrame = null;
193
+ }
194
+ teardownPointer() {
195
+ this.stopAutoScroll();
196
+ if (this.handle && this.pointerId !== null) {
197
+ this.handle.releasePointerCapture?.(this.pointerId);
198
+ }
199
+ document.removeEventListener('pointermove', this.handlePointerMove);
200
+ document.removeEventListener('pointerup', this.handlePointerUp);
201
+ document.removeEventListener('pointercancel', this.handlePointerCancel);
202
+ document.removeEventListener('keydown', this.handlePointerKeydown);
203
+ this.pointerId = null;
204
+ this.handle = null;
205
+ this.armed = false;
206
+ }
207
+ // -------------------------------------------------------------------------
208
+ // Keyboard
209
+ //
210
+ // WCAG 2.5.7 Dragging Movements: anything achievable by dragging needs a
211
+ // single-pointer, non-dragging alternative. Arrow-key moves are that, and
212
+ // they are also simply how a keyboard user reorders a list.
213
+ // -------------------------------------------------------------------------
214
+ /** Space/Enter on the handle: pick the row up, or put it down. */
215
+ toggleKeyboardDrag(node, handlers = {}) {
216
+ if (!this.context)
217
+ return;
218
+ if (this.state$.value?.source === 'keyboard') {
219
+ this.commit('keyboard');
220
+ return;
221
+ }
222
+ if (this.dragging)
223
+ return;
224
+ const index = this.indexOf(node);
225
+ if (index === -1)
226
+ return;
227
+ this.appliedFrom = index;
228
+ this.onEnd = handlers.onEnd;
229
+ this.publish({ rowId: node.rowId, fromIndex: index, insertAt: index, source: 'keyboard' });
230
+ this.announce(`${this.describe(node, index)} grabbed. Use the arrow keys to move it, space to drop, escape to cancel.`);
231
+ }
232
+ /**
233
+ * Arrow keys move the row a position at a time, applying as they go.
234
+ *
235
+ * Applied rather than previewed because the row has to be seen to move: a
236
+ * keyboard user gets no drag image, and a preview line alone tells someone
237
+ * relying on a screen reader nothing about where the row now sits. Escape
238
+ * still restores the original position.
239
+ */
240
+ moveKeyboard(delta) {
241
+ const current = this.state$.value;
242
+ if (!this.context || current?.source !== 'keyboard')
243
+ return false;
244
+ const nodes = this.context.nodes();
245
+ const from = current.insertAt;
246
+ const to = this.clamp(from + delta, 0, nodes.length - 1);
247
+ if (to === from) {
248
+ this.announce(to === 0 ? 'Already at the top.' : 'Already at the bottom.');
249
+ return true;
250
+ }
251
+ if (!this.context.move(from, to))
252
+ return true;
253
+ this.publish({ ...current, insertAt: to });
254
+ const node = this.nodeAt(to);
255
+ this.announce(node ? `Moved to position ${to + 1} of ${nodes.length}.` : '');
256
+ return true;
257
+ }
258
+ // -------------------------------------------------------------------------
259
+ // Commit / cancel
260
+ // -------------------------------------------------------------------------
261
+ commit(source) {
262
+ const current = this.state$.value;
263
+ if (!this.context || !current) {
264
+ this.reset();
265
+ return;
266
+ }
267
+ const nodes = this.context.nodes();
268
+ // Pointer drags apply once, at the end. A boundary index becomes a row
269
+ // index by dropping one when the row travelled downwards, since lifting
270
+ // it out first shifts everything below it up.
271
+ if (source === 'pointer') {
272
+ const from = current.fromIndex;
273
+ const to = this.clamp(current.insertAt > from ? current.insertAt - 1 : current.insertAt, 0, nodes.length - 1);
274
+ const node = this.nodeAt(from);
275
+ if (node && to !== from && this.context.move(from, to)) {
276
+ this.finish({ node, fromIndex: from, toIndex: to, source });
277
+ return;
278
+ }
279
+ this.reset();
280
+ return;
281
+ }
282
+ // Keyboard moves were applied as they happened; this only confirms.
283
+ const node = this.nodeAt(current.insertAt);
284
+ const moved = node && current.insertAt !== current.fromIndex;
285
+ this.announce(moved ? `Dropped at position ${current.insertAt + 1} of ${nodes.length}.` : 'Cancelled. Row returned to its original position.');
286
+ if (moved) {
287
+ this.finish({ node: node, fromIndex: current.fromIndex, toIndex: current.insertAt, source });
288
+ return;
289
+ }
290
+ this.reset();
291
+ }
292
+ /** Abort, restoring anything a keyboard drag already applied. */
293
+ cancel() {
294
+ const current = this.state$.value;
295
+ if (current?.source === 'keyboard' && this.context && current.insertAt !== current.fromIndex) {
296
+ this.context.move(current.insertAt, current.fromIndex);
297
+ this.announce('Cancelled. Row returned to its original position.');
298
+ }
299
+ else if (current) {
300
+ this.announce('Cancelled.');
301
+ }
302
+ this.reset();
303
+ }
304
+ finish(event) {
305
+ const done = this.onEnd;
306
+ this.reset();
307
+ this.zone.run(() => done?.(event));
308
+ }
309
+ reset() {
310
+ this.stopAutoScroll();
311
+ this.appliedFrom = null;
312
+ this.onEnd = undefined;
313
+ if (this.state$.value !== null) {
314
+ this.zone.run(() => this.state$.next(null));
315
+ }
316
+ }
317
+ // -------------------------------------------------------------------------
318
+ // Helpers
319
+ // -------------------------------------------------------------------------
320
+ publish(state) {
321
+ this.zone.run(() => this.state$.next(state));
322
+ }
323
+ announce(message) {
324
+ this.zone.run(() => this.announcement$.next(message));
325
+ }
326
+ describe(node, index) {
327
+ return `Row ${index + 1} of ${this.context?.nodes().length ?? 0},`;
328
+ }
329
+ indexOf(node) {
330
+ return this.context?.nodes().findIndex(candidate => candidate.rowId === node.rowId) ?? -1;
331
+ }
332
+ nodeAt(index) {
333
+ return this.context?.nodes()[index] ?? null;
334
+ }
335
+ clamp(value, min, max) {
336
+ return Math.min(Math.max(value, min), max);
337
+ }
338
+ ngOnDestroy() {
339
+ this.teardownPointer();
340
+ this.state$.next(null);
341
+ this.state$.complete();
342
+ this.announcement$.complete();
343
+ this.context = null;
344
+ }
345
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OneGridRowDragService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
346
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OneGridRowDragService }); }
347
+ }
348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OneGridRowDragService, decorators: [{
349
+ type: Injectable
350
+ }] });
351
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25lLWdyaWQtcm93LWRyYWcuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29uZS1ncmlkL3NyYy9saWIvY29yZS9zZXJ2aWNlcy9vbmUtZ3JpZC1yb3ctZHJhZy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFhLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDOztBQW9CdkMsc0RBQXNEO0FBQ3RELE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0FBRTVCLHVFQUF1RTtBQUN2RSxNQUFNLFlBQVksR0FBRyxFQUFFLENBQUM7QUFDeEIsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO0FBRXpCOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUVILE1BQU0sT0FBTyxxQkFBcUI7SUFEbEM7UUFHcUIsU0FBSSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV2Qyw0RUFBNEU7UUFDbkUsV0FBTSxHQUFHLElBQUksZUFBZSxDQUF5QixJQUFJLENBQUMsQ0FBQztRQUVwRSxxREFBcUQ7UUFDNUMsa0JBQWEsR0FBRyxJQUFJLGVBQWUsQ0FBUyxFQUFFLENBQUMsQ0FBQztRQUVqRCxZQUFPLEdBQWdDLElBQUksQ0FBQztRQUU1QyxjQUFTLEdBQWtCLElBQUksQ0FBQztRQUNoQyxXQUFNLEdBQXVCLElBQUksQ0FBQztRQUNsQyxXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsVUFBSyxHQUFHLEtBQUssQ0FBQztRQUNkLGdCQUFXLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLGdCQUFXLEdBQWtCLElBQUksQ0FBQztRQUUxQyx3RUFBd0U7UUFDaEUsZ0JBQVcsR0FBa0IsSUFBSSxDQUFDO1FBaUVsQyxzQkFBaUIsR0FBRyxDQUFDLEtBQW1CLEVBQVEsRUFBRTtZ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QUFlLEVBQUUsQ0FBQztRQUV2QixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFOUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7SUFDeEIsQ0FBQzsrR0FuZFEscUJBQXFCO21IQUFyQixxQkFBcUI7OzRGQUFyQixxQkFBcUI7a0JBRGpDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBOZ1pvbmUsIE9uRGVzdHJveSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE9uZVJvd0RyYWdFdmVudCwgT25lUm93RHJhZ1N0YXRlIH0gZnJvbSAnLi4vbW9kZWxzL29uZS1yb3ctZHJhZy5tb2RlbCc7XG5pbXBvcnQgeyBPbmVSb3dOb2RlIH0gZnJvbSAnLi4vaW5zdGFudHMvb25lLXJvdy1ub2RlLmNsYXNzJztcblxuLyoqIFdoYXQgdGhlIGJvZHkgaGFzIHRvIGxlbmQgdGhlIHNlcnZpY2UgdG8gcnVuIGEgZHJhZy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT25lUm93RHJhZ0NvbnRleHQ8VCA9IGFueT4ge1xuXG4gICAgLyoqIFRoZSBzY3JvbGxpbmcgZWxlbWVudCB0aGUgcm93cyBsaXZlIGluLiAqL1xuICAgIHZpZXdwb3J0OiBIVE1MRWxlbWVudDtcblxuICAgIC8qKiBGaXhlZCByb3cgaGVpZ2h0LiBUaGUgd2hvbGUgaW5kZXggY2FsY3VsYXRpb24gcmVzdHMgb24gcm93cyBiZWluZyB1bmlmb3JtLiAqL1xuICAgIGl0ZW1TaXplOiBudW1iZXI7XG5cbiAgICAvKiogQ3VycmVudCBkaXNwbGF5IG9yZGVyLiBSZWFkIGZyZXNoIG9uIGV2ZXJ5IG1vdmUg4oCUIGEgZHJhZyBtdXRhdGVzIGl0LiAqL1xuICAgIG5vZGVzOiAoKSA9PiBPbmVSb3dOb2RlPFQ+W107XG5cbiAgICAvKiogQXBwbHkgdGhlIG1vdmUuIFJldHVybnMgZmFsc2UgaWYgdGhlIGdyaWQgcmVmdXNlZCBpdC4gKi9cbiAgICBtb3ZlOiAoZnJvbUluZGV4OiBudW1iZXIsIHRvSW5kZXg6IG51bWJlcikgPT4gYm9vbGVhbjtcbn1cblxuLyoqIFBvaW50ZXIgZGlzdGFuY2UgYmVmb3JlIGEgcHJlc3MgYmVjb21lcyBhIGRyYWcuICovXG5jb25zdCBEUkFHX1RIUkVTSE9MRF9QWCA9IDQ7XG5cbi8qKiBIb3cgY2xvc2UgdG8gYW4gZWRnZSBhdXRvLXNjcm9sbCBraWNrcyBpbiwgYW5kIGhvdyBmYXN0IGl0IGdvZXMuICovXG5jb25zdCBFREdFX1pPTkVfUFggPSAzNjtcbmNvbnN0IEVER0VfU1BFRURfUFggPSAxMjtcblxuLyoqXG4gKiBPd25zIG9uZSByb3ctZHJhZyBnZXN0dXJlIGF0IGEgdGltZS5cbiAqXG4gKiBCdWlsdCBvbiBwb2ludGVyIGV2ZW50cyByYXRoZXIgdGhhbiBIVE1MNSBkcmFnLWFuZC1kcm9wIG9yIHRoZSBDREsnc1xuICogZHJhZy1kcm9wOlxuICpcbiAqIC0gSFRNTDUgRG5EIGRvZXMgbm90IGZpcmUgZm9yIHRvdWNoIGF0IGFsbCwgYW5kIGl0cyBkcmFnIGltYWdlIGNhbm5vdCBiZVxuICogICBzdHlsZWQgdG8gbWF0Y2ggdGhlIGdyaWQuXG4gKiAtIGBjZGtEcm9wTGlzdGAgYXNzdW1lcyBldmVyeSBpdGVtIGl0IG1hbmFnZXMgaXMgaW4gdGhlIERPTS4gSW5zaWRlIGEgdmlydHVhbFxuICogICBzY3JvbGwgdmlld3BvcnQgcm93cyB1bm1vdW50IGFzIHRoZXkgbGVhdmUgdGhlIGJ1ZmZlciwgc28gdGhlIGxpc3QgaXRcbiAqICAgdGhpbmtzIGl0IGlzIHNvcnRpbmcgaXMgb25seSBldmVyIHRoZSB2aXNpYmxlIHdpbmRvdy5cbiAqIC0gUG9pbnRlciBldmVudHMgY292ZXIgbW91c2UsIHRvdWNoIGFuZCBwZW4gaW4gb25lIHBhdGgsIGFuZCBwb2ludGVyIGNhcHR1cmVcbiAqICAga2VlcHMgdGhlIGdlc3R1cmUgYWxpdmUgd2hlbiB0aGUgZmluZ2VyIGxlYXZlcyB0aGUgcm93IGl0IHN0YXJ0ZWQgb24uXG4gKlxuICogQmVjYXVzZSByb3dzIGFyZSBhIGZpeGVkIGBpdGVtU2l6ZWAsIHRoZSBkcm9wIHRhcmdldCBpcyBhcml0aG1ldGljIG9uIHRoZVxuICogcG9pbnRlcidzIFkgcmF0aGVyIHRoYW4gYSBoaXQgdGVzdCBhZ2FpbnN0IHJvdyBlbGVtZW50cyDigJQgd2hpY2ggaXMgYWxzbyB3aHlcbiAqIGl0IHN0YXlzIGNvcnJlY3QgZm9yIHJvd3MgdGhhdCBhcmUgc2Nyb2xsZWQgb3V0IGFuZCBub3QgcmVuZGVyZWQuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBPbmVHcmlkUm93RHJhZ1NlcnZpY2U8VCA9IGFueT4gaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSB6b25lID0gaW5qZWN0KE5nWm9uZSk7XG5cbiAgICAvKiogTGl2ZSBkcmFnLCBmb3IgdGhlIGJvZHkgdG8gcmVuZGVyIHRoZSBoYW5kbGUgc3RhdGUgYW5kIHRoZSBpbmRpY2F0b3IuICovXG4gICAgcmVhZG9ubHkgc3RhdGUkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxPbmVSb3dEcmFnU3RhdGUgfCBudWxsPihudWxsKTtcblxuICAgIC8qKiBTY3JlZW4tcmVhZGVyIG5hcnJhdGlvbiBmb3IgdGhlIGtleWJvYXJkIHBhdGguICovXG4gICAgcmVhZG9ubHkgYW5ub3VuY2VtZW50JCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nPignJyk7XG5cbiAgICBwcml2YXRlIGNvbnRleHQ6IE9uZVJvd0RyYWdDb250ZXh0PFQ+IHwgbnVsbCA9IG51bGw7XG5cbiAgICBwcml2YXRlIHBvaW50ZXJJZDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBoYW5kbGU6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBzdGFydFkgPSAwO1xuICAgIHByaXZhdGUgYXJtZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIGxhc3RDbGllbnRZID0gMDtcbiAgICBwcml2YXRlIHNjcm9sbEZyYW1lOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICAgIC8qKiBBIG1vdmUgYWxyZWFkeSBhcHBsaWVkIGR1cmluZyB0aGlzIGRyYWcsIHNvIGEgY2FuY2VsIGNhbiB1bmRvIGl0LiAqL1xuICAgIHByaXZhdGUgYXBwbGllZEZyb206IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gICAgcHJpdmF0ZSBvbk1vdmU/OiAoZXZlbnQ6IE9uZVJvd0RyYWdFdmVudDxUPikgPT4gdm9pZDtcbiAgICBwcml2YXRlIG9uRW5kPzogKGV2ZW50OiBPbmVSb3dEcmFnRXZlbnQ8VD4gfCBudWxsKSA9PiB2b2lkO1xuXG4gICAgYXR0YWNoKGNvbnRleHQ6IE9uZVJvd0RyYWdDb250ZXh0PFQ+KTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICB9XG5cbiAgICBnZXQgc3RhdGUoKTogT25lUm93RHJhZ1N0YXRlIHwgbnVsbCB7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGUkLnZhbHVlO1xuICAgIH1cblxuICAgIGdldCBkcmFnZ2luZygpOiBib29sZWFuIHtcblxuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZSQudmFsdWUgIT09IG51bGw7XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFBvaW50ZXJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgICAvKipcbiAgICAgKiBCZWdpbiBhIHBvaW50ZXIgZHJhZy4gTm90aGluZyB2aXNpYmxlIGhhcHBlbnMgdW50aWwgdGhlIHBvaW50ZXIgaGFzIG1vdmVkXG4gICAgICoge0BsaW5rIERSQUdfVEhSRVNIT0xEX1BYfSwgc28gYSBjbGljayBvbiB0aGUgaGFuZGxlIOKAlCB3aGljaCBpcyBhbHNvIHRoZVxuICAgICAqIGtleWJvYXJkIGFmZm9yZGFuY2Ug4oCUIGlzIG5vdCBzd2FsbG93ZWQgYnkgYSB6ZXJvLWRpc3RhbmNlIGRyYWcuXG4gICAgICovXG4gICAgc3RhcnRQb2ludGVyRHJhZyhcbiAgICAgICAgZXZlbnQ6IFBvaW50ZXJFdmVudCxcbiAgICAgICAgbm9kZTogT25lUm93Tm9kZTxUPixcbiAgICAgICAgaGFuZGxlcnM6IHsgb25FbmQ/OiAoZXZlbnQ6IE9uZVJvd0RyYWdFdmVudDxUPiB8IG51bGwpID0+IHZvaWQgfSA9IHt9LFxuICAgICk6IHZvaWQge1xuXG4gICAgICAgIGlmICghdGhpcy5jb250ZXh0IHx8IHRoaXMuZHJhZ2dpbmcgfHwgdGhpcy5wb2ludGVySWQgIT09IG51bGwpIHJldHVybjtcblxuICAgICAgICAvLyBTZWNvbmRhcnkgYnV0dG9ucyBvcGVuIGNvbnRleHQgbWVudXM7IHRoZXkgYXJlIG5vdCBhIGRyYWcuXG4gICAgICAgIGlmIChldmVudC5idXR0b24gIT09IDApIHJldHVybjtcblxuICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuaW5kZXhPZihub2RlKTtcblxuICAgICAgICBpZiAoaW5kZXggPT09IC0xKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy5wb2ludGVySWQgPSBldmVudC5wb2ludGVySWQ7XG4gICAgICAgIHRoaXMuaGFuZGxlID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgICAgICB0aGlzLnN0YXJ0WSA9IGV2ZW50LmNsaWVudFk7XG4gICAgICAgIHRoaXMubGFzdENsaWVudFkgPSBldmVudC5jbGllbnRZO1xuICAgICAgICB0aGlzLmFybWVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYXBwbGllZEZyb20gPSBpbmRleDtcbiAgICAgICAgdGhpcy5vbkVuZCA9IGhhbmRsZXJzLm9uRW5kO1xuXG4gICAgICAgIHRoaXMuaGFuZGxlLnNldFBvaW50ZXJDYXB0dXJlPy4oZXZlbnQucG9pbnRlcklkKTtcblxuICAgICAgICAvLyBPdXRzaWRlIEFuZ3VsYXI6IHBvaW50ZXJtb3ZlIGZpcmVzIGF0IHRoZSBkaXNwbGF5J3MgcmVmcmVzaCByYXRlIGFuZFxuICAgICAgICAvLyBldmVyeSBvbmUgb2YgdGhlbSB3b3VsZCBvdGhlcndpc2UgcnVuIGNoYW5nZSBkZXRlY3Rpb24gb3ZlciB0aGUgZ3JpZC5cbiAgICAgICAgLy8gVGhlIGZldyB0aGF0IGNoYW5nZSB0aGUgZHJvcCB0YXJnZXQgcmUtZW50ZXIgdGhyb3VnaCBgcHVibGlzaGAuXG4gICAgICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVybW92ZScsIHRoaXMuaGFuZGxlUG9pbnRlck1vdmUsIHsgcGFzc2l2ZTogZmFsc2UgfSk7XG4gICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVydXAnLCB0aGlzLmhhbmRsZVBvaW50ZXJVcCk7XG4gICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVyY2FuY2VsJywgdGhpcy5oYW5kbGVQb2ludGVyQ2FuY2VsKTtcbiAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLmhhbmRsZVBvaW50ZXJLZXlkb3duKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVQb2ludGVyTW92ZSA9IChldmVudDogUG9pbnRlckV2ZW50KTogdm9pZCA9PiB7XG5cbiAgICAgICAgaWYgKHRoaXMucG9pbnRlcklkID09PSBudWxsIHx8IGV2ZW50LnBvaW50ZXJJZCAhPT0gdGhpcy5wb2ludGVySWQpIHJldHVybjtcblxuICAgICAgICBpZiAoIXRoaXMuYXJtZWQpIHtcblxuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGV2ZW50LmNsaWVudFkgLSB0aGlzLnN0YXJ0WSkgPCBEUkFHX1RIUkVTSE9MRF9QWCkgcmV0dXJuO1xuXG4gICAgICAgICAgICB0aGlzLmFybWVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgdGhpcy5wdWJsaXNoKHsgcm93SWQ6IHRoaXMubm9kZUF0KHRoaXMuYXBwbGllZEZyb20hKT8ucm93SWQgPz8gJycsIGZyb21JbmRleDogdGhpcy5hcHBsaWVkRnJvbSEsIGluc2VydEF0OiB0aGlzLmFwcGxpZWRGcm9tISwgc291cmNlOiAncG9pbnRlcicgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBIZWxkIHNvIHRoZSBhdXRvLXNjcm9sbCBsb29wIGNhbiByZWNvbXB1dGUgdGhlIHRhcmdldCBhcyB0aGUgdmlld3BvcnRcbiAgICAgICAgLy8gbW92ZXMgdW5kZXIgYSBzdGF0aW9uYXJ5IGZpbmdlci5cbiAgICAgICAgdGhpcy5sYXN0Q2xpZW50WSA9IGV2ZW50LmNsaWVudFk7XG5cbiAgICAgICAgLy8gVG91Y2ggc2Nyb2xsaW5nIHdvdWxkIG90aGVyd2lzZSBwYW4gdGhlIHZpZXdwb3J0IG91dCBmcm9tIHVuZGVyIHVzLlxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHRoaXMudXBkYXRlRnJvbVBvaW50ZXIoKTtcbiAgICAgICAgdGhpcy51cGRhdGVBdXRvU2Nyb2xsKCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgaGFuZGxlUG9pbnRlclVwID0gKGV2ZW50OiBQb2ludGVyRXZlbnQpOiB2b2lkID0+IHtcblxuICAgICAgICBpZiAodGhpcy5wb2ludGVySWQgPT09IG51bGwgfHwgZXZlbnQucG9pbnRlcklkICE9PSB0aGlzLnBvaW50ZXJJZCkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IGRyYWdnZWQgPSB0aGlzLmFybWVkO1xuXG4gICAgICAgIHRoaXMudGVhcmRvd25Qb2ludGVyKCk7XG5cbiAgICAgICAgaWYgKCFkcmFnZ2VkKSB7XG5cbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb21taXQoJ3BvaW50ZXInKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBoYW5kbGVQb2ludGVyQ2FuY2VsID0gKCk6IHZvaWQgPT4ge1xuXG4gICAgICAgIHRoaXMudGVhcmRvd25Qb2ludGVyKCk7XG5cbiAgICAgICAgdGhpcy5jYW5jZWwoKTtcbiAgICB9O1xuXG4gICAgLyoqIEVzY2FwZSBhYm9ydHMgYSBwb2ludGVyIGRyYWcsIHRoZSBzYW1lIGFzIGl0IGRvZXMgYSBrZXlib2FyZCBvbmUuICovXG4gICAgcHJpdmF0ZSBoYW5kbGVQb2ludGVyS2V5ZG93biA9IChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQgPT4ge1xuXG4gICAgICAgIGlmIChldmVudC5rZXkgIT09ICdFc2NhcGUnKSByZXR1cm47XG5cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICB0aGlzLnRlYXJkb3duUG9pbnRlcigpO1xuXG4gICAgICAgIHRoaXMuY2FuY2VsKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFR1cm4gdGhlIHBvaW50ZXIncyBZIGludG8gYW4gaW5zZXJ0aW9uIGJvdW5kYXJ5LlxuICAgICAqXG4gICAgICogQm91bmRhcmllcywgbm90IHJvd3M6IHRoZSB2YWx1ZSBpcyB3aGVyZSB0aGUgcm93IHdvdWxkIGJlICppbnNlcnRlZCosIHNvXG4gICAgICogMCBpcyBhYm92ZSB0aGUgZmlyc3Qgcm93IGFuZCBgbGVuZ3RoYCBpcyBiZWxvdyB0aGUgbGFzdC4gUm91bmRpbmcgcmF0aGVyXG4gICAgICogdGhhbiBmbG9vcmluZyBwdXRzIHRoZSBzcGxpdCBhdCB0aGUgbWlkZGxlIG9mIGVhY2ggcm93LCB3aGljaCBpcyB3aGF0XG4gICAgICogbWFrZXMgdGhlIGluZGljYXRvciBmbGlwIHdoZW4geW91IGNyb3NzIHRoZSBoYWxmd2F5IHBvaW50LlxuICAgICAqL1xuICAgIHByaXZhdGUgdXBkYXRlRnJvbVBvaW50ZXIoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuc3RhdGUkLnZhbHVlO1xuXG4gICAgICAgIGlmICghdGhpcy5jb250ZXh0IHx8ICFjdXJyZW50KSByZXR1cm47XG5cbiAgICAgICAgY29uc3QgcmVjdCA9IHRoaXMuY29udGV4dC52aWV3cG9ydC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gdGhpcy5sYXN0Q2xpZW50WSAtIHJlY3QudG9wICsgdGhpcy5jb250ZXh0LnZpZXdwb3J0LnNjcm9sbFRvcDtcblxuICAgICAgICBjb25zdCBpbnNlcnRBdCA9IHRoaXMuY2xhbXAoTWF0aC5yb3VuZChvZmZzZXQgLyB0aGlzLmNvbnRleHQuaXRlbVNpemUpLCAwLCB0aGlzLmNvbnRleHQubm9kZXMoKS5sZW5ndGgpO1xuXG4gICAgICAgIGlmIChpbnNlcnRBdCA9PT0gY3VycmVudC5pbnNlcnRBdCkgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMucHVibGlzaCh7IC4uLmN1cnJlbnQsIGluc2VydEF0IH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNjcm9sbCB3aGVuIHRoZSBwb2ludGVyIHNpdHMgbmVhciBhbiBlZGdlLCBzbyByb3dzIG91dHNpZGUgdGhlIHZpZXdwb3J0XG4gICAgICogYXJlIHJlYWNoYWJsZSB3aXRob3V0IGxldHRpbmcgZ28uIFJ1bnMgb24gckFGIHdoaWxlIHRoZSBwb2ludGVyIGlzIHBhcmtlZFxuICAgICAqIGluIHRoZSB6b25lLCBhbmQgcmUtZGVyaXZlcyB0aGUgdGFyZ2V0IGVhY2ggZnJhbWUgYmVjYXVzZSB0aGUgY29udGVudFxuICAgICAqIG1vdmVzIHdoaWxlIHRoZSBwb2ludGVyIGRvZXMgbm90LlxuICAgICAqL1xuICAgIHByaXZhdGUgdXBkYXRlQXV0b1Njcm9sbCgpOiB2b2lkIHtcblxuICAgICAgICBpZiAoIXRoaXMuY29udGV4dCkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHJlY3QgPSB0aGlzLmNvbnRleHQudmlld3BvcnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgY29uc3QgZGlzdGFuY2VUb1RvcCA9IHRoaXMubGFzdENsaWVudFkgLSByZWN0LnRvcDtcbiAgICAgICAgY29uc3QgZGlzdGFuY2VUb0JvdHRvbSA9IHJlY3QuYm90dG9tIC0gdGhpcy5sYXN0Q2xpZW50WTtcblxuICAgICAgICBsZXQgZGVsdGEgPSAwO1xuXG4gICAgICAgIGlmIChkaXN0YW5jZVRvVG9wIDwgRURHRV9aT05FX1BYKSBkZWx0YSA9IC1FREdFX1NQRUVEX1BYO1xuICAgICAgICBlbHNlIGlmIChkaXN0YW5jZVRvQm90dG9tIDwgRURHRV9aT05FX1BYKSBkZWx0YSA9IEVER0VfU1BFRURfUFg7XG5cbiAgICAgICAgaWYgKGRlbHRhID09PSAwKSB7XG5cbiAgICAgICAgICAgIHRoaXMuc3RvcEF1dG9TY3JvbGwoKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2Nyb2xsRnJhbWUgIT09IG51bGwpIHJldHVybjtcblxuICAgICAgICBjb25zdCBzdGVwID0gKCk6IHZvaWQgPT4ge1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuY29udGV4dCB8fCAhdGhpcy5kcmFnZ2luZykge1xuXG4gICAgICAgICAgICAgICAgdGhpcy5zdG9wQXV0b1Njcm9sbCgpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCB2aWV3cG9ydCA9IHRoaXMuY29udGV4dC52aWV3cG9ydDtcbiAgICAgICAgICAgIGNvbnN0IGJlZm9yZSA9IHZpZXdwb3J0LnNjcm9sbFRvcDtcblxuICAgICAgICAgICAgdmlld3BvcnQuc2Nyb2xsVG9wID0gYmVmb3JlICsgZGVsdGE7XG5cbiAgICAgICAgICAgIC8vIEhpdCB0aGUgZW5kIOKAlCBub3RoaW5nIG1vcmUgdG8gcmV2ZWFsLCBzbyBzdG9wIGJ1cm5pbmcgZnJhbWVzLlxuICAgICAgICAgICAgaWYgKHZpZXdwb3J0LnNjcm9sbFRvcCA9PT0gYmVmb3JlKSB7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnN0b3BBdXRvU2Nyb2xsKCk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudXBkYXRlRnJvbVBvaW50ZXIoKTtcblxuICAgICAgICAgICAgdGhpcy5zY3JvbGxGcmFtZSA9IHJlcXVlc3RBbmltYXRpb25GcmFtZShzdGVwKTtcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnNjcm9sbEZyYW1lID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHN0ZXApO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RvcEF1dG9TY3JvbGwoKTogdm9pZCB7XG5cbiAgICAgICAgaWYgKHRoaXMuc2Nyb2xsRnJhbWUgPT09IG51bGwpIHJldHVybjtcblxuICAgICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnNjcm9sbEZyYW1lKTtcblxuICAgICAgICB0aGlzLnNjcm9sbEZyYW1lID0gbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHRlYXJkb3duUG9pbnRlcigpOiB2b2lkIHtcblxuICAgICAgICB0aGlzLnN0b3BBdXRvU2Nyb2xsKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuaGFuZGxlICYmIHRoaXMucG9pbnRlcklkICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIHRoaXMuaGFuZGxlLnJlbGVhc2VQb2ludGVyQ2FwdHVyZT8uKHRoaXMucG9pbnRlcklkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJtb3ZlJywgdGhpcy5oYW5kbGVQb2ludGVyTW92ZSk7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJ1cCcsIHRoaXMuaGFuZGxlUG9pbnRlclVwKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncG9pbnRlcmNhbmNlbCcsIHRoaXMuaGFuZGxlUG9pbnRlckNhbmNlbCk7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLmhhbmRsZVBvaW50ZXJLZXlkb3duKTtcblxuICAgICAgICB0aGlzLnBvaW50ZXJJZCA9IG51bGw7XG4gICAgICAgIHRoaXMuaGFuZGxlID0gbnVsbDtcbiAgICAgICAgdGhpcy5hcm1lZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBLZXlib2FyZFxuICAgIC8vXG4gICAgLy8gV0NBRyAyLjUuNyBEcmFnZ2luZyBNb3ZlbWVudHM6IGFueXRoaW5nIGFjaGlldmFibGUgYnkgZHJhZ2dpbmcgbmVlZHMgYVxuICAgIC8vIHNpbmdsZS1wb2ludGVyLCBub24tZHJhZ2dpbmcgYWx0ZXJuYXRpdmUuIEFycm93LWtleSBtb3ZlcyBhcmUgdGhhdCwgYW5kXG4gICAgLy8gdGhleSBhcmUgYWxzbyBzaW1wbHkgaG93IGEga2V5Ym9hcmQgdXNlciByZW9yZGVycyBhIGxpc3QuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gICAgLyoqIFNwYWNlL0VudGVyIG9uIHRoZSBoYW5kbGU6IHBpY2sgdGhlIHJvdyB1cCwgb3IgcHV0IGl0IGRvd24uICovXG4gICAgdG9nZ2xlS2V5Ym9hcmREcmFnKG5vZGU6IE9uZVJvd05vZGU8VD4sIGhhbmRsZXJzOiB7IG9uRW5kPzogKGV2ZW50OiBPbmVSb3dEcmFnRXZlbnQ8VD4gfCBudWxsKSA9PiB2b2lkIH0gPSB7fSk6IHZvaWQge1xuXG4gICAgICAgIGlmICghdGhpcy5jb250ZXh0KSByZXR1cm47XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUkLnZhbHVlPy5zb3VyY2UgPT09ICdrZXlib2FyZCcpIHtcblxuICAgICAgICAgICAgdGhpcy5jb21taXQoJ2tleWJvYXJkJyk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmRyYWdnaW5nKSByZXR1cm47XG5cbiAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmluZGV4T2Yobm9kZSk7XG5cbiAgICAgICAgaWYgKGluZGV4ID09PSAtMSkgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMuYXBwbGllZEZyb20gPSBpbmRleDtcbiAgICAgICAgdGhpcy5vbkVuZCA9IGhhbmRsZXJzLm9uRW5kO1xuXG4gICAgICAgIHRoaXMucHVibGlzaCh7IHJvd0lkOiBub2RlLnJvd0lkLCBmcm9tSW5kZXg6IGluZGV4LCBpbnNlcnRBdDogaW5kZXgsIHNvdXJjZTogJ2tleWJvYXJkJyB9KTtcblxuICAgICAgICB0aGlzLmFubm91bmNlKGAke3RoaXMuZGVzY3JpYmUobm9kZSwgaW5kZXgpfSBncmFiYmVkLiBVc2UgdGhlIGFycm93IGtleXMgdG8gbW92ZSBpdCwgc3BhY2UgdG8gZHJvcCwgZXNjYXBlIHRvIGNhbmNlbC5gKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBcnJvdyBrZXlzIG1vdmUgdGhlIHJvdyBhIHBvc2l0aW9uIGF0IGEgdGltZSwgYXBwbHlpbmcgYXMgdGhleSBnby5cbiAgICAgKlxuICAgICAqIEFwcGxpZWQgcmF0aGVyIHRoYW4gcHJldmlld2VkIGJlY2F1c2UgdGhlIHJvdyBoYXMgdG8gYmUgc2VlbiB0byBtb3ZlOiBhXG4gICAgICoga2V5Ym9hcmQgdXNlciBnZXRzIG5vIGRyYWcgaW1hZ2UsIGFuZCBhIHByZXZpZXcgbGluZSBhbG9uZSB0ZWxscyBzb21lb25lXG4gICAgICogcmVseWluZyBvbiBhIHNjcmVlbiByZWFkZXIgbm90aGluZyBhYm91dCB3aGVyZSB0aGUgcm93IG5vdyBzaXRzLiBFc2NhcGVcbiAgICAgKiBzdGlsbCByZXN0b3JlcyB0aGUgb3JpZ2luYWwgcG9zaXRpb24uXG4gICAgICovXG4gICAgbW92ZUtleWJvYXJkKGRlbHRhOiBudW1iZXIpOiBib29sZWFuIHtcblxuICAgICAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5zdGF0ZSQudmFsdWU7XG5cbiAgICAgICAgaWYgKCF0aGlzLmNvbnRleHQgfHwgY3VycmVudD8uc291cmNlICE9PSAna2V5Ym9hcmQnKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgY29uc3Qgbm9kZXMgPSB0aGlzLmNvbnRleHQubm9kZXMoKTtcbiAgICAgICAgY29uc3QgZnJvbSA9IGN1cnJlbnQuaW5zZXJ0QXQ7XG4gICAgICAgIGNvbnN0IHRvID0gdGhpcy5jbGFtcChmcm9tICsgZGVsdGEsIDAsIG5vZGVzLmxlbmd0aCAtIDEpO1xuXG4gICAgICAgIGlmICh0byA9PT0gZnJvbSkge1xuXG4gICAgICAgICAgICB0aGlzLmFubm91bmNlKHRvID09PSAwID8gJ0FscmVhZHkgYXQgdGhlIHRvcC4nIDogJ0FscmVhZHkgYXQgdGhlIGJvdHRvbS4nKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuY29udGV4dC5tb3ZlKGZyb20sIHRvKSkgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgdGhpcy5wdWJsaXNoKHsgLi4uY3VycmVudCwgaW5zZXJ0QXQ6IHRvIH0pO1xuXG4gICAgICAgIGNvbnN0IG5vZGUgPSB0aGlzLm5vZGVBdCh0byk7XG5cbiAgICAgICAgdGhpcy5hbm5vdW5jZShub2RlID8gYE1vdmVkIHRvIHBvc2l0aW9uICR7dG8gKyAxfSBvZiAke25vZGVzLmxlbmd0aH0uYCA6ICcnKTtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gQ29tbWl0IC8gY2FuY2VsXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gICAgcHJpdmF0ZSBjb21taXQoc291cmNlOiAncG9pbnRlcicgfCAna2V5Ym9hcmQnKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuc3RhdGUkLnZhbHVlO1xuXG4gICAgICAgIGlmICghdGhpcy5jb250ZXh0IHx8ICFjdXJyZW50KSB7XG5cbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgbm9kZXMgPSB0aGlzLmNvbnRleHQubm9kZXMoKTtcblxuICAgICAgICAvLyBQb2ludGVyIGRyYWdzIGFwcGx5IG9uY2UsIGF0IHRoZSBlbmQuIEEgYm91bmRhcnkgaW5kZXggYmVjb21lcyBhIHJvd1xuICAgICAgICAvLyBpbmRleCBieSBkcm9wcGluZyBvbmUgd2hlbiB0aGUgcm93IHRyYXZlbGxlZCBkb3dud2FyZHMsIHNpbmNlIGxpZnRpbmdcbiAgICAgICAgLy8gaXQgb3V0IGZpcnN0IHNoaWZ0cyBldmVyeXRoaW5nIGJlbG93IGl0IHVwLlxuICAgICAgICBpZiAoc291cmNlID09PSAncG9pbnRlcicpIHtcblxuICAgICAgICAgICAgY29uc3QgZnJvbSA9IGN1cnJlbnQuZnJvbUluZGV4O1xuICAgICAgICAgICAgY29uc3QgdG8gPSB0aGlzLmNsYW1wKGN1cnJlbnQuaW5zZXJ0QXQgPiBmcm9tID8gY3VycmVudC5pbnNlcnRBdCAtIDEgOiBjdXJyZW50Lmluc2VydEF0LCAwLCBub2Rlcy5sZW5ndGggLSAxKTtcblxuICAgICAgICAgICAgY29uc3Qgbm9kZSA9IHRoaXMubm9kZUF0KGZyb20pO1xuXG4gICAgICAgICAgICBpZiAobm9kZSAmJiB0byAhPT0gZnJvbSAmJiB0aGlzLmNvbnRleHQubW92ZShmcm9tLCB0bykpIHtcblxuICAgICAgICAgICAgICAgIHRoaXMuZmluaXNoKHsgbm9kZSwgZnJvbUluZGV4OiBmcm9tLCB0b0luZGV4OiB0bywgc291cmNlIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEtleWJvYXJkIG1vdmVzIHdlcmUgYXBwbGllZCBhcyB0aGV5IGhhcHBlbmVkOyB0aGlzIG9ubHkgY29uZmlybXMuXG4gICAgICAgIGNvbnN0IG5vZGUgPSB0aGlzLm5vZGVBdChjdXJyZW50Lmluc2VydEF0KTtcblxuICAgICAgICBjb25zdCBtb3ZlZCA9IG5vZGUgJiYgY3VycmVudC5pbnNlcnRBdCAhPT0gY3VycmVudC5mcm9tSW5kZXg7XG5cbiAgICAgICAgdGhpcy5hbm5vdW5jZShtb3ZlZCA/IGBEcm9wcGVkIGF0IHBvc2l0aW9uICR7Y3VycmVudC5pbnNlcnRBdCArIDF9IG9mICR7bm9kZXMubGVuZ3RofS5gIDogJ0NhbmNlbGxlZC4gUm93IHJldHVybmVkIHRvIGl0cyBvcmlnaW5hbCBwb3NpdGlvbi4nKTtcblxuICAgICAgICBpZiAobW92ZWQpIHtcblxuICAgICAgICAgICAgdGhpcy5maW5pc2goeyBub2RlOiBub2RlISwgZnJvbUluZGV4OiBjdXJyZW50LmZyb21JbmRleCwgdG9JbmRleDogY3VycmVudC5pbnNlcnRBdCwgc291cmNlIH0pO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfVxuXG4gICAgLyoqIEFib3J0LCByZXN0b3JpbmcgYW55dGhpbmcgYSBrZXlib2FyZCBkcmFnIGFscmVhZHkgYXBwbGllZC4gKi9cbiAgICBjYW5jZWwoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuc3RhdGUkLnZhbHVlO1xuXG4gICAgICAgIGlmIChjdXJyZW50Py5zb3VyY2UgPT09ICdrZXlib2FyZCcgJiYgdGhpcy5jb250ZXh0ICYmIGN1cnJlbnQuaW5zZXJ0QXQgIT09IGN1cnJlbnQuZnJvbUluZGV4KSB7XG5cbiAgICAgICAgICAgIHRoaXMuY29udGV4dC5tb3ZlKGN1cnJlbnQuaW5zZXJ0QXQsIGN1cnJlbnQuZnJvbUluZGV4KTtcblxuICAgICAgICAgICAgdGhpcy5hbm5vdW5jZSgnQ2FuY2VsbGVkLiBSb3cgcmV0dXJuZWQgdG8gaXRzIG9yaWdpbmFsIHBvc2l0aW9uLicpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudCkge1xuXG4gICAgICAgICAgICB0aGlzLmFubm91bmNlKCdDYW5jZWxsZWQuJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaW5pc2goZXZlbnQ6IE9uZVJvd0RyYWdFdmVudDxUPik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGRvbmUgPSB0aGlzLm9uRW5kO1xuXG4gICAgICAgIHRoaXMucmVzZXQoKTtcblxuICAgICAgICB0aGlzLnpvbmUucnVuKCgpID0+IGRvbmU/LihldmVudCkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVzZXQoKTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5zdG9wQXV0b1Njcm9sbCgpO1xuXG4gICAgICAgIHRoaXMuYXBwbGllZEZyb20gPSBudWxsO1xuICAgICAgICB0aGlzLm9uRW5kID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlJC52YWx1ZSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICB0aGlzLnpvbmUucnVuKCgpID0+IHRoaXMuc3RhdGUkLm5leHQobnVsbCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEhlbHBlcnNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgICBwcml2YXRlIHB1Ymxpc2goc3RhdGU6IE9uZVJvd0RyYWdTdGF0ZSk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4gdGhpcy5zdGF0ZSQubmV4dChzdGF0ZSkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYW5ub3VuY2UobWVzc2FnZTogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy56b25lLnJ1bigoKSA9PiB0aGlzLmFubm91bmNlbWVudCQubmV4dChtZXNzYWdlKSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBkZXNjcmliZShub2RlOiBPbmVSb3dOb2RlPFQ+LCBpbmRleDogbnVtYmVyKTogc3RyaW5nIHtcblxuICAgICAgICByZXR1cm4gYFJvdyAke2luZGV4ICsgMX0gb2YgJHt0aGlzLmNvbnRleHQ/Lm5vZGVzKCkubGVuZ3RoID8/IDB9LGA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbmRleE9mKG5vZGU6IE9uZVJvd05vZGU8VD4pOiBudW1iZXIge1xuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbnRleHQ/Lm5vZGVzKCkuZmluZEluZGV4KGNhbmRpZGF0ZSA9PiBjYW5kaWRhdGUucm93SWQgPT09IG5vZGUucm93SWQpID8/IC0xO1xuICAgIH1cblxuICAgIHByaXZhdGUgbm9kZUF0KGluZGV4OiBudW1iZXIpOiBPbmVSb3dOb2RlPFQ+IHwgbnVsbCB7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGV4dD8ubm9kZXMoKVtpbmRleF0gPz8gbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNsYW1wKHZhbHVlOiBudW1iZXIsIG1pbjogbnVtYmVyLCBtYXg6IG51bWJlcik6IG51bWJlciB7XG5cbiAgICAgICAgcmV0dXJuIE1hdGgubWluKE1hdGgubWF4KHZhbHVlLCBtaW4pLCBtYXgpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMudGVhcmRvd25Qb2ludGVyKCk7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSQubmV4dChudWxsKTtcbiAgICAgICAgdGhpcy5zdGF0ZSQuY29tcGxldGUoKTtcbiAgICAgICAgdGhpcy5hbm5vdW5jZW1lbnQkLmNvbXBsZXRlKCk7XG5cbiAgICAgICAgdGhpcy5jb250ZXh0ID0gbnVsbDtcbiAgICB9XG59XG4iXX0=
@@ -31,13 +31,26 @@ export class OneGridSelectionService {
31
31
  toggleAllSelection(allIds, selected) {
32
32
  selected ? this._selectedIds = new Set(allIds) : this._selectedIds.clear();
33
33
  }
34
- // Header Checkbox State
34
+ /**
35
+ * Tri-state for the header checkbox, over the rows currently present.
36
+ *
37
+ * This compared `_selectedIds.size` with `allIds.length` and never checked
38
+ * that the selected ids were among the present ones. Selecting two rows and
39
+ * then swapping in two different rows reported `checked` with nothing
40
+ * actually selected, because the two counts happened to match. Counting the
41
+ * intersection is the only thing that answers the question being asked.
42
+ */
35
43
  getSelectAllState(allIds) {
36
- if (this._selectedIds.size === 0)
44
+ if (!allIds?.length)
37
45
  return 'unchecked';
38
- if (this._selectedIds.size === allIds.length)
39
- return 'checked';
40
- return 'indeterminate';
46
+ let selected = 0;
47
+ for (const rowId of allIds) {
48
+ if (this._selectedIds.has(rowId))
49
+ selected++;
50
+ }
51
+ if (selected === 0)
52
+ return 'unchecked';
53
+ return selected === allIds.length ? 'checked' : 'indeterminate';
41
54
  }
42
55
  selectAll(rowIds) {
43
56
  this._selectedIds = new Set(rowIds);
@@ -51,4 +64,4 @@ export class OneGridSelectionService {
51
64
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OneGridSelectionService, decorators: [{
52
65
  type: Injectable
53
66
  }] });
54
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25lLWdyaWQtc2VsZWN0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9vbmUtZ3JpZC9zcmMvbGliL2NvcmUvc2VydmljZXMvb25lLWdyaWQtc2VsZWN0aW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFJM0MsTUFBTSxPQUFPLHVCQUF1QjtJQURwQztRQUdVLGlCQUFZLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUNqQyxtQkFBYyxHQUFxQixJQUFJLENBQUM7S0FnRWpEO0lBOURRLGNBQWM7UUFFbkIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7SUFFTSxjQUFjLENBQUMsTUFBZ0I7UUFFcEMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRU0sZ0JBQWdCO1FBRXJCLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUM3QixDQUFDO0lBRU0sZ0JBQWdCLENBQUMsSUFBc0I7UUFFNUMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7UUFFM0IsSUFBSSxJQUFJLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBRXBELGtDQUFrQztZQUNsQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQztZQUV0RCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUN2QyxDQUFDO0lBQ0gsQ0FBQztJQUVNLGVBQWUsQ0FBQyxLQUFhLEVBQUUsUUFBaUI7UUFFckQsSUFBSSxJQUFJLENBQUMsY0FBYyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBRXJDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDNUIsQ0FBQztRQUVELFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFTSxrQkFBa0IsQ0FBQyxNQUFnQixFQUFFLFFBQWlCO1FBRTNELFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM3RSxDQUFDO0lBRUQsd0JBQXdCO0lBQ2pCLGlCQUFpQixDQUFDLE1BQWtCO1FBRXpDLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEtBQUssQ0FBQztZQUFFLE9BQU8sV0FBVyxDQUFDO1FBRXJELElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLE1BQU07WUFBRSxPQUFPLFNBQVMsQ0FBQztRQUUvRCxPQUFPLGVBQWUsQ0FBQztJQUN6QixDQUFDO0lBRU0sU0FBUyxDQUFDLE1BQWdCO1FBRS9CLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVNLFdBQVc7UUFFaEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM1QixDQUFDOytHQWxFVSx1QkFBdUI7bUhBQXZCLHVCQUF1Qjs7NEZBQXZCLHVCQUF1QjtrQkFEbkMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9uZUNoZWNrYm94U3RhdGUsIFJvd1NlbGVjdGlvbk1vZGUgfSBmcm9tICcuLi9tb2RlbHMvb25lLWV2ZW50LXR5cGVzLm1vZGVsJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE9uZUdyaWRTZWxlY3Rpb25TZXJ2aWNlIHtcblxuICBwcml2YXRlIF9zZWxlY3RlZElkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBwcml2YXRlIF9zZWxlY3Rpb25Nb2RlOiBSb3dTZWxlY3Rpb25Nb2RlID0gbnVsbDtcblxuICBwdWJsaWMgZ2V0U2VsZWN0ZWRJZHMoKTogU2V0PHN0cmluZz4ge1xuXG4gICAgcmV0dXJuIHRoaXMuX3NlbGVjdGVkSWRzO1xuICB9XG5cbiAgcHVibGljIHNldFNlbGVjdGVkSWRzKHJvd0lkczogc3RyaW5nW10pIHtcblxuICAgIHRoaXMuX3NlbGVjdGVkSWRzID0gbmV3IFNldChyb3dJZHMpO1xuICB9XG5cbiAgcHVibGljIGdldFNlbGVjdGlvbk1vZGUoKTogUm93U2VsZWN0aW9uTW9kZSB7XG5cbiAgICByZXR1cm4gdGhpcy5fc2VsZWN0aW9uTW9kZTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRTZWxlY3Rpb25Nb2RlKG1vZGU6IFJvd1NlbGVjdGlvbk1vZGUpIHtcblxuICAgIHRoaXMuX3NlbGVjdGlvbk1vZGUgPSBtb2RlO1xuXG4gICAgaWYgKG1vZGUgPT09ICdzaW5nbGUnICYmIHRoaXMuX3NlbGVjdGVkSWRzLnNpemUgPiAxKSB7XG5cbiAgICAgIC8vIGtlZXAgb25seSBvbmUgaWYgbW9kZSBpcyBzaW5nbGVcbiAgICAgIGNvbnN0IGZpcnN0ID0gdGhpcy5fc2VsZWN0ZWRJZHMudmFsdWVzKCkubmV4dCgpLnZhbHVlO1xuXG4gICAgICB0aGlzLl9zZWxlY3RlZElkcyA9IG5ldyBTZXQoW2ZpcnN0XSk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHRvZ2dsZVNlbGVjdGlvbihyb3dJZDogc3RyaW5nLCBzZWxlY3RlZDogYm9vbGVhbikge1xuXG4gICAgaWYgKHRoaXMuX3NlbGVjdGlvbk1vZGUgPT09ICdzaW5nbGUnKSB7XG5cbiAgICAgIHRoaXMuX3NlbGVjdGVkSWRzLmNsZWFyKCk7XG4gICAgfVxuXG4gICAgc2VsZWN0ZWQgPyB0aGlzLl9zZWxlY3RlZElkcy5hZGQocm93SWQpIDogdGhpcy5fc2VsZWN0ZWRJZHMuZGVsZXRlKHJvd0lkKTtcbiAgfVxuXG4gIHB1YmxpYyB0b2dnbGVBbGxTZWxlY3Rpb24oYWxsSWRzOiBzdHJpbmdbXSwgc2VsZWN0ZWQ6IGJvb2xlYW4pIHtcblxuICAgIHNlbGVjdGVkID8gdGhpcy5fc2VsZWN0ZWRJZHMgPSBuZXcgU2V0KGFsbElkcykgOiB0aGlzLl9zZWxlY3RlZElkcy5jbGVhcigpO1xuICB9XG5cbiAgLy8gSGVhZGVyIENoZWNrYm94IFN0YXRlXG4gIHB1YmxpYyBnZXRTZWxlY3RBbGxTdGF0ZShhbGxJZHM6IChzdHJpbmcpW10pOiBPbmVDaGVja2JveFN0YXRlIHtcblxuICAgIGlmICh0aGlzLl9zZWxlY3RlZElkcy5zaXplID09PSAwKSByZXR1cm4gJ3VuY2hlY2tlZCc7XG5cbiAgICBpZiAodGhpcy5fc2VsZWN0ZWRJZHMuc2l6ZSA9PT0gYWxsSWRzLmxlbmd0aCkgcmV0dXJuICdjaGVja2VkJztcblxuICAgIHJldHVybiAnaW5kZXRlcm1pbmF0ZSc7XG4gIH1cblxuICBwdWJsaWMgc2VsZWN0QWxsKHJvd0lkczogc3RyaW5nW10pOiB2b2lkIHtcblxuICAgIHRoaXMuX3NlbGVjdGVkSWRzID0gbmV3IFNldChyb3dJZHMpO1xuICB9XG5cbiAgcHVibGljIGRlc2VsZWN0QWxsKCk6IHZvaWQge1xuXG4gICAgdGhpcy5fc2VsZWN0ZWRJZHMuY2xlYXIoKTtcbiAgfVxufVxuIl19
67
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25lLWdyaWQtc2VsZWN0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9vbmUtZ3JpZC9zcmMvbGliL2NvcmUvc2VydmljZXMvb25lLWdyaWQtc2VsZWN0aW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFJM0MsTUFBTSxPQUFPLHVCQUF1QjtJQURwQztRQUdVLGlCQUFZLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUNqQyxtQkFBYyxHQUFxQixJQUFJLENBQUM7S0ErRWpEO0lBN0VRLGNBQWM7UUFFbkIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7SUFFTSxjQUFjLENBQUMsTUFBZ0I7UUFFcEMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRU0sZ0JBQWdCO1FBRXJCLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUM3QixDQUFDO0lBRU0sZ0JBQWdCLENBQUMsSUFBc0I7UUFFNUMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7UUFFM0IsSUFBSSxJQUFJLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBRXBELGtDQUFrQztZQUNsQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQztZQUV0RCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUN2QyxDQUFDO0lBQ0gsQ0FBQztJQUVNLGVBQWUsQ0FBQyxLQUFhLEVBQUUsUUFBaUI7UUFFckQsSUFBSSxJQUFJLENBQUMsY0FBYyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBRXJDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDNUIsQ0FBQztRQUVELFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFTSxrQkFBa0IsQ0FBQyxNQUFnQixFQUFFLFFBQWlCO1FBRTNELFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM3RSxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSSxpQkFBaUIsQ0FBQyxNQUFrQjtRQUV6QyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU07WUFBRSxPQUFPLFdBQVcsQ0FBQztRQUV4QyxJQUFJLFFBQVEsR0FBRyxDQUFDLENBQUM7UUFFakIsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUUzQixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQztnQkFBRSxRQUFRLEVBQUUsQ0FBQztRQUMvQyxDQUFDO1FBRUQsSUFBSSxRQUFRLEtBQUssQ0FBQztZQUFFLE9BQU8sV0FBVyxDQUFDO1FBRXZDLE9BQU8sUUFBUSxLQUFLLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDO0lBQ2xFLENBQUM7SUFFTSxTQUFTLENBQUMsTUFBZ0I7UUFFL0IsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRU0sV0FBVztRQUVoQixJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzVCLENBQUM7K0dBakZVLHVCQUF1QjttSEFBdkIsdUJBQXVCOzs0RkFBdkIsdUJBQXVCO2tCQURuQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgT25lQ2hlY2tib3hTdGF0ZSwgUm93U2VsZWN0aW9uTW9kZSB9IGZyb20gJy4uL21vZGVscy9vbmUtZXZlbnQtdHlwZXMubW9kZWwnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgT25lR3JpZFNlbGVjdGlvblNlcnZpY2Uge1xuXG4gIHByaXZhdGUgX3NlbGVjdGVkSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIHByaXZhdGUgX3NlbGVjdGlvbk1vZGU6IFJvd1NlbGVjdGlvbk1vZGUgPSBudWxsO1xuXG4gIHB1YmxpYyBnZXRTZWxlY3RlZElkcygpOiBTZXQ8c3RyaW5nPiB7XG5cbiAgICByZXR1cm4gdGhpcy5fc2VsZWN0ZWRJZHM7XG4gIH1cblxuICBwdWJsaWMgc2V0U2VsZWN0ZWRJZHMocm93SWRzOiBzdHJpbmdbXSkge1xuXG4gICAgdGhpcy5fc2VsZWN0ZWRJZHMgPSBuZXcgU2V0KHJvd0lkcyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0U2VsZWN0aW9uTW9kZSgpOiBSb3dTZWxlY3Rpb25Nb2RlIHtcblxuICAgIHJldHVybiB0aGlzLl9zZWxlY3Rpb25Nb2RlO1xuICB9XG5cbiAgcHVibGljIHNldFNlbGVjdGlvbk1vZGUobW9kZTogUm93U2VsZWN0aW9uTW9kZSkge1xuXG4gICAgdGhpcy5fc2VsZWN0aW9uTW9kZSA9IG1vZGU7XG5cbiAgICBpZiAobW9kZSA9PT0gJ3NpbmdsZScgJiYgdGhpcy5fc2VsZWN0ZWRJZHMuc2l6ZSA+IDEpIHtcblxuICAgICAgLy8ga2VlcCBvbmx5IG9uZSBpZiBtb2RlIGlzIHNpbmdsZVxuICAgICAgY29uc3QgZmlyc3QgPSB0aGlzLl9zZWxlY3RlZElkcy52YWx1ZXMoKS5uZXh0KCkudmFsdWU7XG5cbiAgICAgIHRoaXMuX3NlbGVjdGVkSWRzID0gbmV3IFNldChbZmlyc3RdKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgdG9nZ2xlU2VsZWN0aW9uKHJvd0lkOiBzdHJpbmcsIHNlbGVjdGVkOiBib29sZWFuKSB7XG5cbiAgICBpZiAodGhpcy5fc2VsZWN0aW9uTW9kZSA9PT0gJ3NpbmdsZScpIHtcblxuICAgICAgdGhpcy5fc2VsZWN0ZWRJZHMuY2xlYXIoKTtcbiAgICB9XG5cbiAgICBzZWxlY3RlZCA/IHRoaXMuX3NlbGVjdGVkSWRzLmFkZChyb3dJZCkgOiB0aGlzLl9zZWxlY3RlZElkcy5kZWxldGUocm93SWQpO1xuICB9XG5cbiAgcHVibGljIHRvZ2dsZUFsbFNlbGVjdGlvbihhbGxJZHM6IHN0cmluZ1tdLCBzZWxlY3RlZDogYm9vbGVhbikge1xuXG4gICAgc2VsZWN0ZWQgPyB0aGlzLl9zZWxlY3RlZElkcyA9IG5ldyBTZXQoYWxsSWRzKSA6IHRoaXMuX3NlbGVjdGVkSWRzLmNsZWFyKCk7XG4gIH1cblxuICAvKipcbiAgICogVHJpLXN0YXRlIGZvciB0aGUgaGVhZGVyIGNoZWNrYm94LCBvdmVyIHRoZSByb3dzIGN1cnJlbnRseSBwcmVzZW50LlxuICAgKlxuICAgKiBUaGlzIGNvbXBhcmVkIGBfc2VsZWN0ZWRJZHMuc2l6ZWAgd2l0aCBgYWxsSWRzLmxlbmd0aGAgYW5kIG5ldmVyIGNoZWNrZWRcbiAgICogdGhhdCB0aGUgc2VsZWN0ZWQgaWRzIHdlcmUgYW1vbmcgdGhlIHByZXNlbnQgb25lcy4gU2VsZWN0aW5nIHR3byByb3dzIGFuZFxuICAgKiB0aGVuIHN3YXBwaW5nIGluIHR3byBkaWZmZXJlbnQgcm93cyByZXBvcnRlZCBgY2hlY2tlZGAgd2l0aCBub3RoaW5nXG4gICAqIGFjdHVhbGx5IHNlbGVjdGVkLCBiZWNhdXNlIHRoZSB0d28gY291bnRzIGhhcHBlbmVkIHRvIG1hdGNoLiBDb3VudGluZyB0aGVcbiAgICogaW50ZXJzZWN0aW9uIGlzIHRoZSBvbmx5IHRoaW5nIHRoYXQgYW5zd2VycyB0aGUgcXVlc3Rpb24gYmVpbmcgYXNrZWQuXG4gICAqL1xuICBwdWJsaWMgZ2V0U2VsZWN0QWxsU3RhdGUoYWxsSWRzOiAoc3RyaW5nKVtdKTogT25lQ2hlY2tib3hTdGF0ZSB7XG5cbiAgICBpZiAoIWFsbElkcz8ubGVuZ3RoKSByZXR1cm4gJ3VuY2hlY2tlZCc7XG5cbiAgICBsZXQgc2VsZWN0ZWQgPSAwO1xuXG4gICAgZm9yIChjb25zdCByb3dJZCBvZiBhbGxJZHMpIHtcblxuICAgICAgaWYgKHRoaXMuX3NlbGVjdGVkSWRzLmhhcyhyb3dJZCkpIHNlbGVjdGVkKys7XG4gICAgfVxuXG4gICAgaWYgKHNlbGVjdGVkID09PSAwKSByZXR1cm4gJ3VuY2hlY2tlZCc7XG5cbiAgICByZXR1cm4gc2VsZWN0ZWQgPT09IGFsbElkcy5sZW5ndGggPyAnY2hlY2tlZCcgOiAnaW5kZXRlcm1pbmF0ZSc7XG4gIH1cblxuICBwdWJsaWMgc2VsZWN0QWxsKHJvd0lkczogc3RyaW5nW10pOiB2b2lkIHtcblxuICAgIHRoaXMuX3NlbGVjdGVkSWRzID0gbmV3IFNldChyb3dJZHMpO1xuICB9XG5cbiAgcHVibGljIGRlc2VsZWN0QWxsKCk6IHZvaWQge1xuXG4gICAgdGhpcy5fc2VsZWN0ZWRJZHMuY2xlYXIoKTtcbiAgfVxufVxuIl19
@@ -1,3 +1,20 @@
1
+ /** Width used when a column defines neither `width` nor `minWidth`. */
2
+ export const ONE_DEFAULT_COLUMN_WIDTH = 150;
3
+ /**
4
+ * The rendered width of a column, clamped to its bounds.
5
+ *
6
+ * `width`, `minWidth` and `maxWidth` are all optional, and the previous inline
7
+ * expression — repeated in two places — fell back to `minWidth` when `width`
8
+ * was absent. With neither set that produced `undefined`, and summing it gave
9
+ * a `NaN` row width, so the row collapsed. This is total: every combination of
10
+ * present and absent bounds resolves to a usable number.
11
+ */
12
+ export function resolveColumnWidth(column) {
13
+ const min = column?.minWidth ?? 0;
14
+ const max = column?.maxWidth ?? Number.POSITIVE_INFINITY;
15
+ const width = column?.width ?? column?.minWidth ?? ONE_DEFAULT_COLUMN_WIDTH;
16
+ return Math.min(Math.max(width, min), max);
17
+ }
1
18
  /**
2
19
  * Apply Default Column Definitions
3
20
  */
@@ -10,7 +27,15 @@ export function applyDefaultColumnDef(columnDefs, defaultColumnDef) {
10
27
  /**
11
28
  * One Column Params Resolver (Cell Renderer)
12
29
  */
13
- export function resolveOneCellRendererParams(prop, params) {
30
+ export function resolveOneCellRendererParams(prop, params,
31
+ /**
32
+ * What an unset property means: `false` for a capability you opt into,
33
+ * `true` for a restriction you opt out of. `!!prop` could not tell the two
34
+ * apart, which left `updatable` — a restriction — defaulting to "deny".
35
+ */
36
+ whenUnset = false) {
37
+ if (prop === undefined || prop === null)
38
+ return whenUnset;
14
39
  return typeof prop === 'function' ? prop(params) : !!prop;
15
40
  }
16
41
  /**
@@ -25,4 +50,4 @@ export function resolveOneColumDefParams(prop, params) {
25
50
  export function resolveOneValueGetterParams(prop, params) {
26
51
  return typeof prop === 'function' ? prop(params) : prop;
27
52
  }
28
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25lLWNvbHVtbi1kZWYuaGVscGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvb25lLWdyaWQvc3JjL2xpYi9oZWxwZXJzL29uZS1jb2x1bW4tZGVmLmhlbHBlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7R0FFRztBQUNILE1BQU0sVUFBVSxxQkFBcUIsQ0FBSSxVQUE2QixFQUFFLGdCQUFpQztJQUV2RyxPQUFPLFVBQVUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9CLEdBQUcsZ0JBQWdCO1FBQ25CLEdBQUcsTUFBTTtLQUNWLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLDRCQUE0QixDQUFJLElBQTBDLEVBQUUsTUFBZ0M7SUFFMUgsT0FBTyxPQUFPLElBQUksS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUM1RCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsd0JBQXdCLENBQUksSUFBOEIsRUFBRSxNQUFXO0lBRXJGLE9BQU8sT0FBTyxJQUFJLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBRSxJQUFzQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDN0UsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLDJCQUEyQixDQUFPLElBQWtELEVBQUUsTUFBK0I7SUFFbkksT0FBTyxPQUFPLElBQUksS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFFLElBQTBDLENBQUUsTUFBTSxDQUFDLENBQUEsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUNqRyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT25lQ2VsbFJlbmRlcmVyUGFyYW1zLCBPbmVDb2x1bW5EZWYsIE9uZVZhbHVlR2V0dGVyUGFyYW1zIH0gZnJvbSBcIi4uL2NvcmUvbW9kZWxzL29uZS1jb2x1bW4tZGVmLXR5cGVzLm1vZGVsXCI7XG5cbi8qKlxuICogQXBwbHkgRGVmYXVsdCBDb2x1bW4gRGVmaW5pdGlvbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5RGVmYXVsdENvbHVtbkRlZjxUPihjb2x1bW5EZWZzOiBPbmVDb2x1bW5EZWY8VD5bXSwgZGVmYXVsdENvbHVtbkRlZjogT25lQ29sdW1uRGVmPFQ+KTogT25lQ29sdW1uRGVmPFQ+W10ge1xuXG4gIHJldHVybiBjb2x1bW5EZWZzLm1hcChjb2xEZWYgPT4gKHtcbiAgICAuLi5kZWZhdWx0Q29sdW1uRGVmLFxuICAgIC4uLmNvbERlZlxuICB9KSk7XG59XG5cbi8qKlxuICogT25lIENvbHVtbiBQYXJhbXMgUmVzb2x2ZXIgKENlbGwgUmVuZGVyZXIpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlT25lQ2VsbFJlbmRlcmVyUGFyYW1zPFQ+KHByb3A6IGJvb2xlYW4gfCAoKHBhcmFtczogYW55KSA9PiBib29sZWFuKSwgcGFyYW1zOiBPbmVDZWxsUmVuZGVyZXJQYXJhbXM8VD4pOiBib29sZWFuIHtcblxuICByZXR1cm4gdHlwZW9mIHByb3AgPT09ICdmdW5jdGlvbicgPyBwcm9wKHBhcmFtcykgOiAhIXByb3A7XG59XG5cbi8qKlxuICogT25lIENvbHVtbiBQYXJhbXMgUmVzb2x2ZXIgKEdlbmVyaWNzKVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU9uZUNvbHVtRGVmUGFyYW1zPFI+KHByb3A6IFIgfCAoKHBhcmFtczogYW55KSA9PiBSKSwgcGFyYW1zOiBhbnkpOiBSIHtcblxuICByZXR1cm4gdHlwZW9mIHByb3AgPT09ICdmdW5jdGlvbicgPyAocHJvcCBhcyAocDogYW55KSA9PiBSKShwYXJhbXMpIDogcHJvcDtcbn1cblxuLyoqXG4gKiBPbmUgQ29sdW1uIFBhcmFtcyBSZXNvbHZlciAoVmFsdWUgR2V0dGVyKVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU9uZVZhbHVlR2V0dGVyUGFyYW1zPFQsIFI+KHByb3A6IFIgfCAoKHBhcmFtczogT25lVmFsdWVHZXR0ZXJQYXJhbXM8VD4pID0+IFIpLCBwYXJhbXM6IE9uZVZhbHVlR2V0dGVyUGFyYW1zPFQ+KTogUiB7XG5cbiAgcmV0dXJuIHR5cGVvZiBwcm9wID09PSAnZnVuY3Rpb24nID8gKHByb3AgYXMgKHA6IE9uZVZhbHVlR2V0dGVyUGFyYW1zPFQ+KSA9PiBSKSAocGFyYW1zKTogcHJvcDtcbn0iXX0=
53
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25lLWNvbHVtbi1kZWYuaGVscGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvb25lLWdyaWQvc3JjL2xpYi9oZWxwZXJzL29uZS1jb2x1bW4tZGVmLmhlbHBlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSx1RUFBdUU7QUFDdkUsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxDQUFDO0FBRTVDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUFJLE1BQXVCO0lBRXpELE1BQU0sR0FBRyxHQUFHLE1BQU0sRUFBRSxRQUFRLElBQUksQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sR0FBRyxHQUFHLE1BQU0sRUFBRSxRQUFRLElBQUksTUFBTSxDQUFDLGlCQUFpQixDQUFDO0lBQ3pELE1BQU0sS0FBSyxHQUFHLE1BQU0sRUFBRSxLQUFLLElBQUksTUFBTSxFQUFFLFFBQVEsSUFBSSx3QkFBd0IsQ0FBQztJQUU1RSxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDL0MsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQixDQUFJLFVBQTZCLEVBQUUsZ0JBQWlDO0lBRXZHLE9BQU8sVUFBVSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDL0IsR0FBRyxnQkFBZ0I7UUFDbkIsR0FBRyxNQUFNO0tBQ1YsQ0FBQyxDQUFDLENBQUM7QUFDTixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsNEJBQTRCLENBQzFDLElBQTBDLEVBQzFDLE1BQWdDO0FBQ2hDOzs7O0dBSUc7QUFDSCxZQUFxQixLQUFLO0lBRzFCLElBQUksSUFBSSxLQUFLLFNBQVMsSUFBSSxJQUFJLEtBQUssSUFBSTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBRTFELE9BQU8sT0FBTyxJQUFJLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDNUQsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLHdCQUF3QixDQUFJLElBQThCLEVBQUUsTUFBVztJQUVyRixPQUFPLE9BQU8sSUFBSSxLQUFLLFVBQVUsQ0FBQyxDQUFDLENBQUUsSUFBc0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQzdFLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFBVSwyQkFBMkIsQ0FBTyxJQUFrRCxFQUFFLE1BQStCO0lBRW5JLE9BQU8sT0FBTyxJQUFJLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBRSxJQUEwQyxDQUFFLE1BQU0sQ0FBQyxDQUFBLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDakcsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9uZUNlbGxSZW5kZXJlclBhcmFtcywgT25lQ29sdW1uRGVmLCBPbmVWYWx1ZUdldHRlclBhcmFtcyB9IGZyb20gXCIuLi9jb3JlL21vZGVscy9vbmUtY29sdW1uLWRlZi10eXBlcy5tb2RlbFwiO1xuXG4vKiogV2lkdGggdXNlZCB3aGVuIGEgY29sdW1uIGRlZmluZXMgbmVpdGhlciBgd2lkdGhgIG5vciBgbWluV2lkdGhgLiAqL1xuZXhwb3J0IGNvbnN0IE9ORV9ERUZBVUxUX0NPTFVNTl9XSURUSCA9IDE1MDtcblxuLyoqXG4gKiBUaGUgcmVuZGVyZWQgd2lkdGggb2YgYSBjb2x1bW4sIGNsYW1wZWQgdG8gaXRzIGJvdW5kcy5cbiAqXG4gKiBgd2lkdGhgLCBgbWluV2lkdGhgIGFuZCBgbWF4V2lkdGhgIGFyZSBhbGwgb3B0aW9uYWwsIGFuZCB0aGUgcHJldmlvdXMgaW5saW5lXG4gKiBleHByZXNzaW9uIOKAlCByZXBlYXRlZCBpbiB0d28gcGxhY2VzIOKAlCBmZWxsIGJhY2sgdG8gYG1pbldpZHRoYCB3aGVuIGB3aWR0aGBcbiAqIHdhcyBhYnNlbnQuIFdpdGggbmVpdGhlciBzZXQgdGhhdCBwcm9kdWNlZCBgdW5kZWZpbmVkYCwgYW5kIHN1bW1pbmcgaXQgZ2F2ZVxuICogYSBgTmFOYCByb3cgd2lkdGgsIHNvIHRoZSByb3cgY29sbGFwc2VkLiBUaGlzIGlzIHRvdGFsOiBldmVyeSBjb21iaW5hdGlvbiBvZlxuICogcHJlc2VudCBhbmQgYWJzZW50IGJvdW5kcyByZXNvbHZlcyB0byBhIHVzYWJsZSBudW1iZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQ29sdW1uV2lkdGg8VD4oY29sdW1uOiBPbmVDb2x1bW5EZWY8VD4pOiBudW1iZXIge1xuXG4gICAgY29uc3QgbWluID0gY29sdW1uPy5taW5XaWR0aCA/PyAwO1xuICAgIGNvbnN0IG1heCA9IGNvbHVtbj8ubWF4V2lkdGggPz8gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuICAgIGNvbnN0IHdpZHRoID0gY29sdW1uPy53aWR0aCA/PyBjb2x1bW4/Lm1pbldpZHRoID8/IE9ORV9ERUZBVUxUX0NPTFVNTl9XSURUSDtcblxuICAgIHJldHVybiBNYXRoLm1pbihNYXRoLm1heCh3aWR0aCwgbWluKSwgbWF4KTtcbn1cblxuLyoqXG4gKiBBcHBseSBEZWZhdWx0IENvbHVtbiBEZWZpbml0aW9uc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlEZWZhdWx0Q29sdW1uRGVmPFQ+KGNvbHVtbkRlZnM6IE9uZUNvbHVtbkRlZjxUPltdLCBkZWZhdWx0Q29sdW1uRGVmOiBPbmVDb2x1bW5EZWY8VD4pOiBPbmVDb2x1bW5EZWY8VD5bXSB7XG5cbiAgcmV0dXJuIGNvbHVtbkRlZnMubWFwKGNvbERlZiA9PiAoe1xuICAgIC4uLmRlZmF1bHRDb2x1bW5EZWYsXG4gICAgLi4uY29sRGVmXG4gIH0pKTtcbn1cblxuLyoqXG4gKiBPbmUgQ29sdW1uIFBhcmFtcyBSZXNvbHZlciAoQ2VsbCBSZW5kZXJlcilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVPbmVDZWxsUmVuZGVyZXJQYXJhbXM8VD4oXG4gIHByb3A6IGJvb2xlYW4gfCAoKHBhcmFtczogYW55KSA9PiBib29sZWFuKSxcbiAgcGFyYW1zOiBPbmVDZWxsUmVuZGVyZXJQYXJhbXM8VD4sXG4gIC8qKlxuICAgKiBXaGF0IGFuIHVuc2V0IHByb3BlcnR5IG1lYW5zOiBgZmFsc2VgIGZvciBhIGNhcGFiaWxpdHkgeW91IG9wdCBpbnRvLFxuICAgKiBgdHJ1ZWAgZm9yIGEgcmVzdHJpY3Rpb24geW91IG9wdCBvdXQgb2YuIGAhIXByb3BgIGNvdWxkIG5vdCB0ZWxsIHRoZSB0d29cbiAgICogYXBhcnQsIHdoaWNoIGxlZnQgYHVwZGF0YWJsZWAg4oCUIGEgcmVzdHJpY3Rpb24g4oCUIGRlZmF1bHRpbmcgdG8gXCJkZW55XCIuXG4gICAqL1xuICB3aGVuVW5zZXQ6IGJvb2xlYW4gPSBmYWxzZSxcbik6IGJvb2xlYW4ge1xuXG4gIGlmIChwcm9wID09PSB1bmRlZmluZWQgfHwgcHJvcCA9PT0gbnVsbCkgcmV0dXJuIHdoZW5VbnNldDtcblxuICByZXR1cm4gdHlwZW9mIHByb3AgPT09ICdmdW5jdGlvbicgPyBwcm9wKHBhcmFtcykgOiAhIXByb3A7XG59XG5cbi8qKlxuICogT25lIENvbHVtbiBQYXJhbXMgUmVzb2x2ZXIgKEdlbmVyaWNzKVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU9uZUNvbHVtRGVmUGFyYW1zPFI+KHByb3A6IFIgfCAoKHBhcmFtczogYW55KSA9PiBSKSwgcGFyYW1zOiBhbnkpOiBSIHtcblxuICByZXR1cm4gdHlwZW9mIHByb3AgPT09ICdmdW5jdGlvbicgPyAocHJvcCBhcyAocDogYW55KSA9PiBSKShwYXJhbXMpIDogcHJvcDtcbn1cblxuLyoqXG4gKiBPbmUgQ29sdW1uIFBhcmFtcyBSZXNvbHZlciAoVmFsdWUgR2V0dGVyKVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU9uZVZhbHVlR2V0dGVyUGFyYW1zPFQsIFI+KHByb3A6IFIgfCAoKHBhcmFtczogT25lVmFsdWVHZXR0ZXJQYXJhbXM8VD4pID0+IFIpLCBwYXJhbXM6IE9uZVZhbHVlR2V0dGVyUGFyYW1zPFQ+KTogUiB7XG5cbiAgcmV0dXJuIHR5cGVvZiBwcm9wID09PSAnZnVuY3Rpb24nID8gKHByb3AgYXMgKHA6IE9uZVZhbHVlR2V0dGVyUGFyYW1zPFQ+KSA9PiBSKSAocGFyYW1zKTogcHJvcDtcbn0iXX0=