apex-grid 3.6.0 → 4.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/CHANGELOG.md +301 -0
  2. package/LICENSE.md +2 -1
  3. package/README.md +117 -18
  4. package/components/cell.d.ts +13 -1
  5. package/components/cell.js +28 -13
  6. package/components/cell.js.map +1 -1
  7. package/components/grid.d.ts +175 -28
  8. package/components/grid.js +183 -63
  9. package/components/grid.js.map +1 -1
  10. package/components/header-row.d.ts +0 -6
  11. package/components/header-row.js +1 -19
  12. package/components/header-row.js.map +1 -1
  13. package/components/header.js +39 -2
  14. package/components/header.js.map +1 -1
  15. package/components/paginator.d.ts +20 -5
  16. package/components/paginator.js +54 -17
  17. package/components/paginator.js.map +1 -1
  18. package/components/row.js +149 -40
  19. package/components/row.js.map +1 -1
  20. package/components/toolbar.d.ts +5 -1
  21. package/components/toolbar.js +4 -1
  22. package/components/toolbar.js.map +1 -1
  23. package/components/virtualize-rows.d.ts +38 -0
  24. package/components/virtualize-rows.js +286 -0
  25. package/components/virtualize-rows.js.map +1 -0
  26. package/components/virtualizer.d.ts +71 -1
  27. package/components/virtualizer.js +105 -29
  28. package/components/virtualizer.js.map +1 -1
  29. package/controllers/dom.d.ts +10 -3
  30. package/controllers/dom.js +5 -5
  31. package/controllers/dom.js.map +1 -1
  32. package/controllers/navigation.d.ts +63 -0
  33. package/controllers/navigation.js +295 -21
  34. package/controllers/navigation.js.map +1 -1
  35. package/controllers/pagination.d.ts +7 -6
  36. package/controllers/pagination.js +27 -28
  37. package/controllers/pagination.js.map +1 -1
  38. package/controllers/row-pin.d.ts +6 -0
  39. package/controllers/row-pin.js +8 -2
  40. package/controllers/row-pin.js.map +1 -1
  41. package/controllers/row-reorder.d.ts +12 -4
  42. package/controllers/row-reorder.js +20 -6
  43. package/controllers/row-reorder.js.map +1 -1
  44. package/controllers/selection.d.ts +32 -10
  45. package/controllers/selection.js +33 -10
  46. package/controllers/selection.js.map +1 -1
  47. package/controllers/sort.js +2 -3
  48. package/controllers/sort.js.map +1 -1
  49. package/controllers/state.d.ts +18 -5
  50. package/controllers/state.js +53 -46
  51. package/controllers/state.js.map +1 -1
  52. package/custom-elements.json +1762 -339
  53. package/docs/assets/hierarchy.js +1 -1
  54. package/docs/assets/search.js +1 -1
  55. package/docs/classes/ApexGrid.html +166 -66
  56. package/docs/classes/ApexGridPaginator.html +39 -8
  57. package/docs/classes/ApexGridToolbar.html +9 -5
  58. package/docs/functions/localize.html +2 -2
  59. package/docs/hierarchy.html +1 -1
  60. package/docs/index.html +123 -20
  61. package/docs/interfaces/ApexPageChangedEvent.html +3 -1
  62. package/docs/interfaces/BaseApexCellContext.html +18 -5
  63. package/docs/interfaces/BaseApexEditorContext.html +20 -5
  64. package/docs/interfaces/BaseFilterExpression.html +1 -1
  65. package/docs/interfaces/CSVExportOptions.html +1 -1
  66. package/docs/interfaces/DataPipelineConfiguration.html +4 -9
  67. package/docs/interfaces/ExportOptions.html +1 -1
  68. package/docs/interfaces/GridSelectionConfiguration.html +19 -4
  69. package/docs/interfaces/PaginationConfiguration.html +11 -4
  70. package/docs/interfaces/PaginationState.html +4 -2
  71. package/docs/media/_token-values.scss +42 -16
  72. package/docs/media/package.json +12 -4
  73. package/docs/types/DataPipelineParams.html +2 -2
  74. package/docs/types/PaginationMode.html +5 -4
  75. package/docs/variables/EN_LOCALE.html +2 -2
  76. package/i18n/en.d.ts +2 -0
  77. package/i18n/en.js +2 -0
  78. package/i18n/en.js.map +1 -1
  79. package/i18n/es.js +2 -0
  80. package/i18n/es.js.map +1 -1
  81. package/ignite-ui.d.ts +1 -0
  82. package/ignite-ui.js +4 -0
  83. package/ignite-ui.js.map +1 -0
  84. package/internal/column-types.d.ts +11 -1
  85. package/internal/column-types.js +8 -6
  86. package/internal/column-types.js.map +1 -1
  87. package/internal/design-system.d.ts +32 -0
  88. package/internal/design-system.js +66 -0
  89. package/internal/design-system.js.map +1 -0
  90. package/internal/export.d.ts +6 -0
  91. package/internal/export.js +4 -0
  92. package/internal/export.js.map +1 -1
  93. package/internal/feature-module.d.ts +7 -0
  94. package/internal/feature-module.js.map +1 -1
  95. package/internal/flip.d.ts +28 -16
  96. package/internal/flip.js +42 -10
  97. package/internal/flip.js.map +1 -1
  98. package/internal/icons.d.ts +2 -16
  99. package/internal/icons.js +0 -8
  100. package/internal/icons.js.map +1 -1
  101. package/internal/ignite-ui.d.ts +10 -0
  102. package/internal/ignite-ui.js +118 -0
  103. package/internal/ignite-ui.js.map +1 -0
  104. package/internal/index.d.ts +4 -2
  105. package/internal/index.js +3 -2
  106. package/internal/index.js.map +1 -1
  107. package/internal/types.d.ts +75 -19
  108. package/internal/types.js.map +1 -1
  109. package/operations/filter/types.d.ts +1 -1
  110. package/operations/filter/types.js.map +1 -1
  111. package/package.json +7 -2
  112. package/styles/_token-blocks.css.d.ts +1 -0
  113. package/styles/_token-blocks.css.js +3 -0
  114. package/styles/_token-blocks.css.js.map +1 -0
  115. package/styles/_tokens.css.js +1 -1
  116. package/styles/_tokens.css.js.map +1 -1
  117. package/styles/body-cell/body-cell.css.js +1 -1
  118. package/styles/body-cell/body-cell.css.js.map +1 -1
  119. package/styles/body-cell/cell-renderers.css.js +1 -1
  120. package/styles/body-cell/cell-renderers.css.js.map +1 -1
  121. package/styles/body-row/body-row.css.js +1 -1
  122. package/styles/body-row/body-row.css.js.map +1 -1
  123. package/styles/document-tokens.css.js +1 -1
  124. package/styles/document-tokens.css.js.map +1 -1
  125. package/styles/grid/_grid.base.css.js +1 -1
  126. package/styles/grid/_grid.base.css.js.map +1 -1
  127. package/styles/grid/grid.css.js +1 -1
  128. package/styles/grid/grid.css.js.map +1 -1
  129. package/styles/group-header-row/group-header-row.css.js +1 -1
  130. package/styles/group-header-row/group-header-row.css.js.map +1 -1
  131. package/styles/header-cell/header-cell.css.js +1 -1
  132. package/styles/header-cell/header-cell.css.js.map +1 -1
  133. package/styles/header-row/header-row.base.css.js +1 -1
  134. package/styles/header-row/header-row.base.css.js.map +1 -1
  135. package/styles/ignite-ui/ignite-ui-dark.css.d.ts +1 -0
  136. package/styles/ignite-ui/ignite-ui-dark.css.js +3 -0
  137. package/styles/ignite-ui/ignite-ui-dark.css.js.map +1 -0
  138. package/styles/ignite-ui/ignite-ui-document.css.d.ts +1 -0
  139. package/styles/ignite-ui/ignite-ui-document.css.js +3 -0
  140. package/styles/ignite-ui/ignite-ui-document.css.js.map +1 -0
  141. package/styles/ignite-ui/ignite-ui.css.d.ts +1 -0
  142. package/styles/ignite-ui/ignite-ui.css.js +3 -0
  143. package/styles/ignite-ui/ignite-ui.css.js.map +1 -0
  144. package/styles/paginator/paginator.css.js +1 -1
  145. package/styles/paginator/paginator.css.js.map +1 -1
  146. package/styles/toolbar/toolbar.css.js +1 -1
  147. package/styles/toolbar/toolbar.css.js.map +1 -1
  148. package/tokens.css +14 -15
  149. package/operations/pagination.d.ts +0 -19
  150. package/operations/pagination.js +0 -12
  151. package/operations/pagination.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { revealWithin } from '../components/virtualizer.js';
2
2
  import { SENTINEL_NODE } from '../internal/constants.js';
3
- import { GRID_ROW_TAG } from '../internal/tags.js';
3
+ import { GRID_BODY, GRID_CELL_TAG, GRID_ROW_TAG } from '../internal/tags.js';
4
4
  import { getDisplayColumns, isRTL } from '../internal/utils.js';
5
5
  const RELATIVE_KEYS = new Set([
6
6
  'ArrowDown',
@@ -12,6 +12,12 @@ const RELATIVE_KEYS = new Set([
12
12
  'PageUp',
13
13
  'PageDown',
14
14
  ]);
15
+ function deepActiveElement() {
16
+ let el = document.activeElement;
17
+ while (el?.shadowRoot?.activeElement)
18
+ el = el.shadowRoot.activeElement;
19
+ return el;
20
+ }
15
21
  export class NavigationController {
16
22
  get virtualizer() {
17
23
  return this.host.scrollContainer;
@@ -127,26 +133,31 @@ export class NavigationController {
127
133
  };
128
134
  }
129
135
  focusActiveCell(reveal = false) {
136
+ void this.#focusActive(reveal);
137
+ }
138
+ async #focusActive(reveal = false) {
130
139
  const node = this._active;
131
140
  if (node === SENTINEL_NODE)
132
141
  return;
133
- void (async () => {
134
- await this.host.updateComplete;
135
- let cell = this.findCell(node);
136
- if (!cell) {
137
- await this.virtualizer.settled();
138
- cell = this.findCell(node);
139
- }
140
- if (!cell) {
141
- await new Promise(requestAnimationFrame);
142
- cell = this.findCell(node);
143
- }
144
- if (!cell || this._active !== node)
145
- return;
146
- if (reveal)
147
- this.scrollToCell(node);
148
- cell.focus({ preventScroll: true });
149
- })();
142
+ await this.host.updateComplete;
143
+ let cell = this.findCell(node);
144
+ if (!cell) {
145
+ await this.virtualizer.settled();
146
+ cell = this.findCell(node);
147
+ }
148
+ if (!cell) {
149
+ await new Promise(requestAnimationFrame);
150
+ cell = this.findCell(node);
151
+ }
152
+ if (!cell && this._active === node) {
153
+ await this.virtualizer.revealed();
154
+ cell = this.findCell(node);
155
+ }
156
+ if (!cell || this._active !== node)
157
+ return;
158
+ if (reveal)
159
+ this.scrollToCell(node);
160
+ cell.focus({ preventScroll: true });
150
161
  }
151
162
  get active() {
152
163
  return this._active;
@@ -170,8 +181,212 @@ export class NavigationController {
170
181
  }));
171
182
  this._active = SENTINEL_NODE;
172
183
  this.#revealing = null;
184
+ this.#ownsFocus = false;
185
+ this.#focusedRecord = null;
186
+ this.#focusTarget = null;
187
+ this.#blurred = null;
188
+ this.#moved = null;
189
+ this.#reconcile = 0;
190
+ this.#reconciling = 0;
191
+ this.#parked = null;
192
+ this.#focusingBody = false;
193
+ this.#detached = null;
173
194
  this.host.addController(this);
174
195
  }
196
+ get ownsFocus() {
197
+ this.#settleLoss();
198
+ return this.#ownsFocus;
199
+ }
200
+ #ownsFocus;
201
+ #settleLoss() {
202
+ if (!this.#ownsFocus || this.#reconciling || this.#parked || this.#detached)
203
+ return;
204
+ if (this.#lost())
205
+ this.#ownsFocus = false;
206
+ }
207
+ #focusedRecord;
208
+ #focusTarget;
209
+ #blurred;
210
+ #moved;
211
+ #reconcile;
212
+ #reconciling;
213
+ #parked;
214
+ #focusingBody;
215
+ #detached;
216
+ get forwardsBodyFocus() {
217
+ return !this.#parked && !this.#focusingBody;
218
+ }
219
+ focusEntered(event, owned) {
220
+ this.#blurred = null;
221
+ this.#moved = null;
222
+ this.#ownsFocus = owned;
223
+ const el = event.composedPath()[0];
224
+ const row = owned ? this.#locate(el)?.row : undefined;
225
+ this.#focusedRecord = row?.data ?? null;
226
+ this.#focusTarget = owned ? { el, row } : null;
227
+ }
228
+ focusLeft(event, owned) {
229
+ if (!owned)
230
+ return;
231
+ if (event.relatedTarget) {
232
+ this.#ownsFocus = false;
233
+ return;
234
+ }
235
+ const target = event.composedPath()[0];
236
+ const from = this.#locate(target)?.row;
237
+ this.#blurred = target;
238
+ queueMicrotask(() => {
239
+ if (this.#blurred !== target)
240
+ return;
241
+ this.#blurred = null;
242
+ if (!this.#reconciling) {
243
+ this.#ownsFocus = false;
244
+ return;
245
+ }
246
+ if (!target.isConnected)
247
+ return;
248
+ const to = this.#locate(target)?.row;
249
+ if (to && to !== from)
250
+ this.#moved = target;
251
+ else
252
+ this.#ownsFocus = false;
253
+ });
254
+ }
255
+ reconcileFocus() {
256
+ this.#settleLoss();
257
+ if (!this.#ownsFocus || !this.host.rowRecycling)
258
+ return;
259
+ const token = ++this.#reconcile;
260
+ this.#reconciling = token;
261
+ void (async () => {
262
+ try {
263
+ await Promise.resolve();
264
+ await this.virtualizer.rendered();
265
+ if (token !== this.#reconcile || this.#parked)
266
+ return;
267
+ if (!this.#ownsFocus || !this.host.isConnected)
268
+ return;
269
+ const focused = deepActiveElement();
270
+ if (focused && focused !== document.body) {
271
+ const at = this.#locate(focused);
272
+ if (!at?.row)
273
+ return;
274
+ const active = this._active;
275
+ const onActive = at.row.index === active.row && (!at.cell || at.cell.column.key === active.column);
276
+ if (onActive || at.row.data === this.#focusedRecord)
277
+ return;
278
+ }
279
+ await this.#restoreFocus();
280
+ }
281
+ finally {
282
+ if (token === this.#reconcile) {
283
+ this.#reconciling = 0;
284
+ this.#moved = null;
285
+ if (!this.#parked && this.#lost())
286
+ this.#ownsFocus = false;
287
+ }
288
+ }
289
+ })();
290
+ }
291
+ async #restoreFocus() {
292
+ const moved = this.#moved ?? this.#silentlyMoved();
293
+ this.#moved = null;
294
+ if (moved?.isConnected && moved instanceof HTMLElement) {
295
+ const at = this.#locate(moved);
296
+ if (at?.row && at.row.data === this.#focusedRecord) {
297
+ moved.focus({ preventScroll: true });
298
+ return;
299
+ }
300
+ }
301
+ const edit = this.editing?.activeCell;
302
+ const row = edit && this.#renderedRows().find((each) => each.data === edit.data);
303
+ const cell = row?.cells.find((each) => each.column.key === edit?.columnKey);
304
+ if (cell) {
305
+ await cell.updateComplete;
306
+ const editor = cell.shadowRoot?.querySelector('input, [data-apex-editor]');
307
+ if (this.#lost())
308
+ (editor ?? cell).focus({ preventScroll: true });
309
+ return;
310
+ }
311
+ if (this._active !== SENTINEL_NODE && this.virtualizer.isRendered(this._active.row)) {
312
+ await this.#focusActive();
313
+ return;
314
+ }
315
+ this.#focusBody();
316
+ }
317
+ #silentlyMoved() {
318
+ const target = this.#focusTarget;
319
+ if (!target?.el.isConnected || !this.#lost())
320
+ return null;
321
+ const to = this.#locate(target.el)?.row;
322
+ return to && to !== target.row ? target.el : null;
323
+ }
324
+ parkFocus() {
325
+ this.#settleLoss();
326
+ if (!this.host.rowRecycling || !this.#ownsFocus)
327
+ return null;
328
+ const at = this.#locate(deepActiveElement());
329
+ const park = { record: at?.row?.data ?? null };
330
+ this.#parked = park;
331
+ return async () => {
332
+ await this.virtualizer.rendered();
333
+ if (this.#parked !== park)
334
+ return;
335
+ this.#parked = null;
336
+ if (!this.#ownsFocus || !this.host.isConnected)
337
+ return;
338
+ const focused = deepActiveElement();
339
+ if (focused && focused !== document.body) {
340
+ const now = this.#locate(focused);
341
+ if (!now?.row)
342
+ return;
343
+ if (now.cell && now.cell.editing)
344
+ return;
345
+ if (now.row.data === park.record)
346
+ return;
347
+ }
348
+ this.#focusBody();
349
+ };
350
+ }
351
+ #focusBody() {
352
+ this.#focusingBody = true;
353
+ try {
354
+ this.virtualizer.focus({ preventScroll: true });
355
+ }
356
+ finally {
357
+ this.#focusingBody = false;
358
+ }
359
+ }
360
+ #lost() {
361
+ const focused = deepActiveElement();
362
+ return !focused || focused === document.body;
363
+ }
364
+ #renderedRows() {
365
+ return Array.from(this.virtualizer.querySelectorAll(GRID_ROW_TAG));
366
+ }
367
+ #locate(el) {
368
+ const body = this.virtualizer;
369
+ if (!body)
370
+ return null;
371
+ let row;
372
+ let cell;
373
+ let node = el instanceof Node ? el : null;
374
+ while (node) {
375
+ if (node === body)
376
+ return { row, cell };
377
+ if (node instanceof Element) {
378
+ const name = node.localName;
379
+ if (name === GRID_BODY)
380
+ return null;
381
+ if (!cell && name === GRID_CELL_TAG)
382
+ cell = node;
383
+ if (!row && name === GRID_ROW_TAG)
384
+ row = node;
385
+ }
386
+ node = node instanceof ShadowRoot ? node.host : node.parentNode;
387
+ }
388
+ return null;
389
+ }
175
390
  hostUpdate() {
176
391
  const node = this._active;
177
392
  if (node === SENTINEL_NODE)
@@ -181,6 +396,14 @@ export class NavigationController {
181
396
  this._active = SENTINEL_NODE;
182
397
  return;
183
398
  }
399
+ const edit = this.editing?.activeCell;
400
+ if (edit && node.row === edit.rowIndex && node.column === edit.columnKey) {
401
+ const index = this.host.pageItems.indexOf(edit.data);
402
+ if (index >= 0 && index !== edit.rowIndex && this.virtualizer.isRendered(index)) {
403
+ this._active = { column: node.column, row: index };
404
+ return;
405
+ }
406
+ }
184
407
  const row = Math.min(node.row, count - 1);
185
408
  const column = this.#nearestVisibleColumn(node.column);
186
409
  if (row !== node.row || column !== node.column) {
@@ -285,9 +508,39 @@ export class NavigationController {
285
508
  return;
286
509
  void this.host.toggleRowSelection(data);
287
510
  }
288
- hostConnected() { }
511
+ hostConnected() {
512
+ const detached = this.#detached;
513
+ this.#detached = null;
514
+ if (detached)
515
+ this.#refocusAfterMove(detached.node);
516
+ }
289
517
  hostDisconnected() {
518
+ const dropped = this.#blurred !== null || (this.#ownsFocus && this.#lost());
519
+ const moved = dropped && this.host.rowRecycling;
520
+ const detached = moved ? { node: this._active } : null;
290
521
  this.active = SENTINEL_NODE;
522
+ this.#detached = detached;
523
+ if (!detached)
524
+ this.#ownsFocus = false;
525
+ if (detached) {
526
+ setTimeout(() => {
527
+ if (this.#detached !== detached)
528
+ return;
529
+ this.#detached = null;
530
+ this.#ownsFocus = false;
531
+ });
532
+ }
533
+ }
534
+ #refocusAfterMove(node) {
535
+ if (node !== SENTINEL_NODE)
536
+ this.active = node;
537
+ void (async () => {
538
+ await this.host.updateComplete;
539
+ if (!this.#lost() || this._active !== node || !this.host.isConnected)
540
+ return;
541
+ const cell = node === SENTINEL_NODE ? undefined : this.findCell(node);
542
+ (cell ?? this.virtualizer).focus({ preventScroll: true });
543
+ })();
291
544
  }
292
545
  get editing() {
293
546
  return this.host.stateController.editing;
@@ -321,10 +574,12 @@ export class NavigationController {
321
574
  case 'ArrowUp':
322
575
  case 'ArrowDown': {
323
576
  event.preventDefault();
577
+ const row = reorder.grabbed;
324
578
  const next = reorder.moveGrabbed(event.key === 'ArrowDown' ? 1 : -1);
325
- if (next >= 0) {
579
+ if (next >= 0 && row) {
326
580
  this.active = Object.assign(this.nextNode, { row: next });
327
581
  this.scrollToRow(next);
582
+ this.#followRecord(row);
328
583
  }
329
584
  return true;
330
585
  }
@@ -333,10 +588,14 @@ export class NavigationController {
333
588
  event.preventDefault();
334
589
  reorder.drop();
335
590
  return true;
336
- case 'Escape':
591
+ case 'Escape': {
337
592
  event.preventDefault();
593
+ const row = reorder.grabbed;
338
594
  reorder.cancelGrab();
595
+ if (row)
596
+ this.#followRecord(row);
339
597
  return true;
598
+ }
340
599
  default:
341
600
  return false;
342
601
  }
@@ -347,6 +606,21 @@ export class NavigationController {
347
606
  }
348
607
  return false;
349
608
  }
609
+ #followRecord(record) {
610
+ const node = this._active;
611
+ void this.host.pipelineSettled().then(() => {
612
+ if (this._active !== node || node === SENTINEL_NODE)
613
+ return;
614
+ const row = this.host.pageItems.indexOf(record);
615
+ if (row < 0)
616
+ return;
617
+ if (row !== node.row) {
618
+ this.active = { ...node, row };
619
+ this.scrollToRow(row);
620
+ }
621
+ this.focusActiveCell();
622
+ });
623
+ }
350
624
  navigate(event) {
351
625
  if (this.handleReorderKey(event))
352
626
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/controllers/navigation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type ApexGridRow from '../components/row.js';\nimport { revealWithin, type ScrollInsets } from '../components/virtualizer.js';\nimport { SENTINEL_NODE } from '../internal/constants.js';\nimport { GRID_ROW_TAG } from '../internal/tags.js';\nimport type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport { getDisplayColumns, isRTL } from '../internal/utils.js';\n\n/** Keys that move the active cell relative to where it is. */\nconst RELATIVE_KEYS = new Set([\n 'ArrowDown',\n 'ArrowUp',\n 'ArrowLeft',\n 'ArrowRight',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown',\n]);\n\nexport class NavigationController<T extends object> implements ReactiveController {\n protected handlers = new Map(\n Object.entries({\n ArrowDown: this.arrowDown,\n ArrowUp: this.arrowUp,\n ArrowLeft: this.arrowLeft,\n ArrowRight: this.arrowRight,\n Home: this.home,\n End: this.end,\n PageUp: this.pageUp,\n PageDown: this.pageDown,\n ' ': this.toggleSelection,\n })\n );\n\n protected get virtualizer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n /**\n * The active cell of this grid. Instance state on purpose: every grid on a\n * page, including one nested in another grid's detail panel, keeps its own.\n */\n protected _active = SENTINEL_NODE as ActiveNode<T>;\n\n protected get nextNode() {\n return this._active === SENTINEL_NODE\n ? ({ column: this.firstColumn, row: 0 } as ActiveNode<T>)\n : ({ ...this._active } as ActiveNode<T>);\n }\n\n protected get columns(): Array<{ key: Keys<T>; hidden?: boolean }> {\n return getDisplayColumns(this.host.columns) as unknown as Array<{\n key: Keys<T>;\n hidden?: boolean;\n }>;\n }\n\n protected get visibleColumns() {\n return this.columns.filter((column) => !column.hidden);\n }\n\n protected get firstColumn(): Keys<T> {\n const first = this.visibleColumns.at(0);\n return (first?.key ?? (this.host.columns[0]?.key as Keys<T>)) as Keys<T>;\n }\n\n /** Whether there is any cell to move to: a body row and a visible column. */\n protected get navigable(): boolean {\n return this.host.pageItems.length > 0 && this.visibleColumns.length > 0;\n }\n\n protected getPreviousColumn(key: Keys<T>): Keys<T> {\n const columns = this.visibleColumns;\n const idx = columns.findIndex((column) => column.key === key);\n return columns[Math.max(idx - 1, 0)]?.key ?? key;\n }\n\n protected getNextColumn(key: Keys<T>): Keys<T> {\n const columns = this.visibleColumns;\n const idx = columns.findIndex((column) => column.key === key);\n return columns[Math.min(idx + 1, columns.length - 1)]?.key ?? key;\n }\n\n /** The rendered body row at `index`, when the virtualizer has it in the DOM. */\n protected findRow(index: number) {\n return Array.from(this.virtualizer.querySelectorAll(GRID_ROW_TAG)).find(\n (row) => (row as unknown as ApexGridRow<T>).index === index\n ) as unknown as ApexGridRow<T> | undefined;\n }\n\n /**\n * The element that stands for `node` in the DOM: the cell, or for a row a\n * feature module renders full width (a group header, a total row) the\n * row's single focus target, whatever the column.\n */\n protected findCell(node: ActiveNode<T>): HTMLElement | undefined {\n const row = this.findRow(node.row);\n if (!row) return undefined;\n return (\n row.presentedCell ??\n (row.cells.find((cell) => cell.column.key === node.column) as HTMLElement | undefined)\n );\n }\n\n protected scrollToCell(node: ActiveNode<T>) {\n const cell = this.findCell(node);\n if (cell) {\n revealWithin(this.host as unknown as HTMLElement, cell, {\n block: 'nearest',\n inline: 'nearest',\n insets: this.scrollInsets(),\n });\n }\n }\n\n /** Scrolls body row `index` into view, rendered or not. */\n protected scrollToRow(index: number) {\n this.virtualizer\n .element(index)\n ?.scrollIntoView({ block: 'nearest', insets: this.scrollInsets() });\n }\n\n /** The cell {@link revealCell} last asked for, so a late reveal yields to a newer one. */\n #revealing: ActiveNode<T> | null = null;\n\n /**\n * Scrolls the cell at `node` into view clear of the sticky chrome without\n * moving the active cell: the cell itself when it is rendered, else its row\n * first and the cell once the virtualizer has rendered it. For a feature\n * that moves something other than the active cell with the keyboard (range\n * extension), so it scrolls the way arrow navigation does.\n */\n public revealCell(node: ActiveNode<T>): void {\n this.#revealing = node;\n if (this.findCell(node)) {\n this.scrollToCell(node);\n return;\n }\n this.scrollToRow(node.row);\n void this.virtualizer.settled().then(() => {\n if (this.#revealing === node) this.scrollToCell(node);\n });\n }\n\n /**\n * Whether ArrowLeft or ArrowRight steps towards the end of the column\n * order: ArrowRight in a left-to-right grid, ArrowLeft in a right-to-left\n * one. The rule every inline arrow key on this grid follows.\n */\n public towardsInlineEnd(key: string): boolean {\n return isRTL(this.host as unknown as Element) === (key === 'ArrowLeft');\n }\n\n /**\n * How much of the scroll container's scrollport the sticky chrome covers\n * (toolbar, headers and the pinned-top band above, the pinned-bottom band\n * and the paginator below, pinned columns on either side). Keyboard scrolls\n * use it as scroll-padding, so a row or cell the keyboard moves to is never\n * parked underneath that chrome. Measured right before each keyboard scroll\n * because any of those bands can change size between key presses. Public\n * so a feature scrolling the body itself (drag auto-scroll) measures the\n * same chrome.\n */\n public scrollInsets(): ScrollInsets {\n const host = this.host as unknown as HTMLElement;\n const root = host.shadowRoot;\n if (!root) return { top: 0, right: 0, bottom: 0, left: 0 };\n const box = host.getBoundingClientRect();\n const top = box.top + host.clientTop;\n const left = box.left + host.clientLeft;\n const bottom = top + host.clientHeight;\n const right = left + host.clientWidth;\n\n let insetTop = 0;\n for (const el of root.querySelectorAll('apex-grid-header-row, [part~=\"pinned-top\"]')) {\n insetTop = Math.max(insetTop, el.getBoundingClientRect().bottom - top);\n }\n let insetBottom = 0;\n for (const el of root.querySelectorAll('apex-grid-paginator, [part~=\"pinned-bottom\"]')) {\n insetBottom = Math.max(insetBottom, bottom - el.getBoundingClientRect().top);\n }\n\n let insetLeft = 0;\n let insetRight = 0;\n const headerRow = root.querySelector('apex-grid-header-row');\n const pinned = headerRow?.shadowRoot?.querySelectorAll(\n '[data-pinned=\"start\"], [data-pinned=\"end\"]'\n );\n if (pinned?.length) {\n const rtl = isRTL(host);\n for (const el of pinned) {\n const rect = el.getBoundingClientRect();\n const atLeft = (el.getAttribute('data-pinned') === 'start') !== rtl;\n if (atLeft) insetLeft = Math.max(insetLeft, rect.right - left);\n else insetRight = Math.max(insetRight, right - rect.left);\n }\n }\n\n const clamp = (inset: number) => Math.max(0, Math.round(inset));\n return {\n top: clamp(insetTop),\n right: clamp(insetRight),\n bottom: clamp(insetBottom),\n left: clamp(insetLeft),\n };\n }\n\n /**\n * Moves real DOM focus to the active cell (the grid body's roving tab stop),\n * so screen readers track keyboard navigation. Waits for the host render to\n * commit the cell's `active` state and, when the cell is not in the DOM yet\n * (a long jump), for the virtualizer to finish laying out the new range.\n * No-op while no cell is active (the scroll container keeps focus as the\n * entry point).\n *\n * @param reveal - also scroll the cell into view once it exists, for jumps\n * whose target row was not rendered when the scroll started.\n */\n public focusActiveCell(reveal = false): void {\n const node = this._active;\n if (node === SENTINEL_NODE) return;\n void (async () => {\n await this.host.updateComplete;\n let cell = this.findCell(node);\n if (!cell) {\n await this.virtualizer.settled();\n cell = this.findCell(node);\n }\n if (!cell) {\n await new Promise(requestAnimationFrame);\n cell = this.findCell(node);\n }\n // The user moved on while this was waiting: leave focus to the newer move.\n if (!cell || this._active !== node) return;\n if (reveal) this.scrollToCell(node);\n cell.focus({ preventScroll: true });\n })();\n }\n\n public get active() {\n return this._active;\n }\n\n public set active(node: ActiveNode<T>) {\n this._active = node;\n this.host.requestUpdate();\n }\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n /**\n * Keeps the active cell pointing at something that exists. Runs before\n * every grid render, so after a data swap, sort, filter, page change or a\n * column hide or reorder the active node is clamped to the last row and the\n * nearest visible column, or cleared when there is nothing left to point\n * at (no rows, no visible columns). Without it a stale node names a cell\n * that is never rendered, which leaves the body with no tab stop.\n */\n public hostUpdate() {\n const node = this._active;\n if (node === SENTINEL_NODE) return;\n const count = this.host.pageItems.length;\n if (!count || !this.visibleColumns.length) {\n this._active = SENTINEL_NODE as ActiveNode<T>;\n return;\n }\n const row = Math.min(node.row, count - 1);\n const column = this.#nearestVisibleColumn(node.column);\n if (row !== node.row || column !== node.column) {\n this._active = { column, row } as ActiveNode<T>;\n }\n }\n\n /** `key` when it is visible, else the closest visible column in display order. */\n #nearestVisibleColumn(key: Keys<T>): Keys<T> {\n const columns = this.columns;\n const index = columns.findIndex((column) => column.key === key);\n if (index < 0) return this.firstColumn;\n for (let distance = 0; distance < columns.length; distance++) {\n for (const at of [index + distance, index - distance]) {\n const column = columns[at];\n if (column && !column.hidden) return column.key;\n }\n }\n return this.firstColumn;\n }\n\n /** The active row is one a feature module renders full width (no cells). */\n protected isPresentedRow(index: number): boolean {\n const data = this.host.pageItems[index];\n if (!data) return false;\n // @ts-expect-error - protected member access\n const state = this.host.stateController as {\n presentRow(row: T, ctx: { columns: ColumnConfiguration<T>[]; rowIndex: number }): unknown;\n };\n return state.presentRow(data, { columns: this.host.columns, rowIndex: index }) !== null;\n }\n\n /** Home moves to the first cell in the row (ARIA grid pattern). */\n protected home() {\n this.active = Object.assign(this.nextNode, { column: this.firstColumn });\n this.scrollToCell(this.active);\n }\n\n /** End moves to the last cell in the row (ARIA grid pattern). */\n protected end() {\n const last = this.visibleColumns.at(-1)?.key ?? this.firstColumn;\n this.active = Object.assign(this.nextNode, { column: last });\n this.scrollToCell(this.active);\n }\n\n /** Ctrl/Cmd+Home moves to the first cell of the grid. */\n protected ctrlHome() {\n this.active = { column: this.firstColumn, row: 0 } as ActiveNode<T>;\n this.scrollToRow(0);\n }\n\n /** Ctrl/Cmd+End moves to the last cell of the grid. */\n protected ctrlEnd() {\n const row = this.host.pageItems.length - 1;\n const last = this.visibleColumns.at(-1)?.key ?? this.firstColumn;\n this.active = { column: last, row } as ActiveNode<T>;\n this.scrollToRow(row);\n }\n\n /**\n * Rows per Page Up/Down step: the rows that fit in the part of the\n * scrollport the sticky chrome leaves visible, minus one so the row the\n * user was on stays in view. Falls back to 10 when nothing is measurable.\n */\n protected pageStep(): number {\n const host = this.host as unknown as HTMLElement;\n let rowHeight = 0;\n for (const row of this.virtualizer.querySelectorAll(GRID_ROW_TAG)) {\n const height = (row as HTMLElement).offsetHeight;\n // The shortest rendered row: an expanded detail panel is not a row height.\n if (height > 0 && (!rowHeight || height < rowHeight)) rowHeight = height;\n }\n const { top, bottom } = this.scrollInsets();\n const viewport = host.clientHeight - top - bottom;\n if (!rowHeight || viewport <= 0) return 10;\n return Math.max(1, Math.floor(viewport / rowHeight) - 1);\n }\n\n protected pageUp() {\n const next = this.nextNode;\n this.active = Object.assign(next, { row: Math.max(0, next.row - this.pageStep()) });\n this.scrollToRow(this.active.row);\n }\n\n protected pageDown() {\n const next = this.nextNode;\n this.active = Object.assign(next, {\n row: Math.min(this.host.pageItems.length - 1, next.row + this.pageStep()),\n });\n this.scrollToRow(this.active.row);\n }\n\n protected arrowDown() {\n const next = this.nextNode;\n this.active = Object.assign(next, {\n row: Math.min(next.row + 1, this.host.pageItems.length - 1),\n });\n this.scrollToRow(next.row);\n }\n\n protected arrowUp() {\n const next = this.nextNode;\n this.active = Object.assign(next, { row: Math.max(0, next.row - 1) });\n this.scrollToRow(next.row);\n }\n\n protected arrowLeft() {\n this.#moveInline('ArrowLeft');\n }\n\n protected arrowRight() {\n this.#moveInline('ArrowRight');\n }\n\n /**\n * Moves the active cell one column in a *physical* direction.\n *\n * ArrowLeft and ArrowRight name screen directions, not column order, so under\n * `dir=\"rtl\"` the column to the left is the *next* one and the mapping onto\n * previous/next inverts ({@link towardsInlineEnd}). Everything else about\n * navigation is order-based and needs no direction awareness.\n */\n #moveInline(key: 'ArrowLeft' | 'ArrowRight') {\n const next = this.nextNode;\n const column = this.towardsInlineEnd(key)\n ? this.getNextColumn(next.column)\n : this.getPreviousColumn(next.column);\n this.active = Object.assign(next, { column });\n this.scrollToCell(this.active);\n }\n\n protected toggleSelection() {\n // Space on the focused grid toggles selection of the active row.\n // No-op when selection is disabled, there's no active row, or the row is\n // module-rendered (a group header or total row is not a data row).\n const data = this.host.pageItems[this._active.row] as T | undefined;\n if (!data || this.isPresentedRow(this._active.row)) return;\n void this.host.toggleRowSelection(data);\n }\n\n public hostConnected() {}\n\n public hostDisconnected() {\n this.active = SENTINEL_NODE as ActiveNode<T>;\n }\n\n protected get editing() {\n // @ts-expect-error - protected member access\n return this.host.stateController.editing as\n | {\n enabled: boolean;\n isEditable(column: ColumnConfiguration<T>): boolean;\n editCell(rowIndex: number, columnKey: Keys<T>): Promise<boolean>;\n }\n | undefined;\n }\n\n /**\n * Enter / F2 on the active cell opens its editor (the keyboard path into\n * edit mode). Returns `true` when the event was consumed.\n */\n protected handleEditKey(event: KeyboardEvent): boolean {\n if (event.key !== 'Enter' && event.key !== 'F2') return false;\n if (event.ctrlKey || event.metaKey || event.altKey) return false;\n if (this._active === SENTINEL_NODE || this.isPresentedRow(this._active.row)) return false;\n const editing = this.editing;\n if (!editing?.enabled) return false;\n const column = this.host.getColumn(this.active.column);\n if (!column || !editing.isEditable(column)) return false;\n event.preventDefault();\n void editing.editCell(this.active.row, this.active.column);\n return true;\n }\n\n protected get rowReorder() {\n // @ts-expect-error - protected member access\n return this.host.stateController.rowReorder as\n | {\n enabled: boolean;\n isGrabbing: boolean;\n grab(rowIndex: number): boolean;\n moveGrabbed(direction: -1 | 1): number;\n drop(): void;\n cancelGrab(): void;\n }\n | undefined;\n }\n\n /**\n * Keyboard row reorder: Space grabs the active row, arrows move it, Space /\n * Enter drops, Escape cancels. Returns `true` when the event was consumed.\n * Only active when `rowReordering.enabled` (so it never shadows Space-to-select\n * on grids without reordering).\n */\n protected handleReorderKey(event: KeyboardEvent): boolean {\n const reorder = this.rowReorder;\n if (!reorder?.enabled) return false;\n\n if (reorder.isGrabbing) {\n switch (event.key) {\n case 'ArrowUp':\n case 'ArrowDown': {\n event.preventDefault();\n const next = reorder.moveGrabbed(event.key === 'ArrowDown' ? 1 : -1);\n if (next >= 0) {\n this.active = Object.assign(this.nextNode, { row: next });\n this.scrollToRow(next);\n }\n return true;\n }\n case ' ':\n case 'Enter':\n event.preventDefault();\n reorder.drop();\n return true;\n case 'Escape':\n event.preventDefault();\n reorder.cancelGrab();\n return true;\n default:\n return false;\n }\n }\n\n if (event.key === ' ' && this.active.row >= 0 && !this.isPresentedRow(this.active.row)) {\n event.preventDefault();\n return reorder.grab(this.active.row);\n }\n return false;\n }\n\n public navigate(event: KeyboardEvent) {\n if (this.handleReorderKey(event)) return;\n // Undo / redo: Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, Ctrl/Cmd+Y. Only fires when the\n // grid body (not an open editor) has focus, so a text editor's native undo\n // is never hijacked.\n if ((event.ctrlKey || event.metaKey) && !event.altKey) {\n const key = event.key.toLowerCase();\n if (key === 'z' && !event.shiftKey) {\n event.preventDefault();\n this.host.undo();\n return;\n }\n if ((key === 'z' && event.shiftKey) || key === 'y') {\n event.preventDefault();\n this.host.redo();\n return;\n }\n // Ctrl/Cmd+Home / Ctrl/Cmd+End jump to the grid corners (ARIA grid pattern).\n if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n if (!this.navigable) return;\n if (event.key === 'Home') {\n this.ctrlHome();\n } else {\n this.ctrlEnd();\n }\n // The target row is often outside the rendered window, so the cell is\n // revealed (horizontally too) once the virtualizer has rendered it.\n this.focusActiveCell(true);\n return;\n }\n }\n if (this.handleEditKey(event)) return;\n if (RELATIVE_KEYS.has(event.key)) {\n event.preventDefault();\n if (!this.navigable) return;\n // Entering the body with the keyboard (Tab lands on the scroll\n // container, no cell active yet): an arrow, Home or Page Up activates\n // the first cell instead of moving past it. End and Page Down still\n // move, starting from that first cell.\n if (this._active === SENTINEL_NODE) {\n // Through the setter: the render it requests moves the tab stop\n // from the body to the cell.\n this.active = { column: this.firstColumn, row: 0 } as ActiveNode<T>;\n if (event.key !== 'End' && event.key !== 'PageDown') {\n this.scrollToRow(0);\n this.focusActiveCell(true);\n return;\n }\n }\n }\n if (this.handlers.has(event.key)) {\n event.preventDefault();\n this.handlers.get(event.key)!.call(this);\n // Real focus follows the active cell so AT tracks the movement.\n this.focusActiveCell();\n }\n }\n}\n"]}
1
+ {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/controllers/navigation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type ApexGridRow from '../components/row.js';\nimport { revealWithin, type ScrollInsets } from '../components/virtualizer.js';\nimport { SENTINEL_NODE } from '../internal/constants.js';\nimport { GRID_BODY, GRID_CELL_TAG, GRID_ROW_TAG } from '../internal/tags.js';\nimport type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport { getDisplayColumns, isRTL } from '../internal/utils.js';\n\n/** Keys that move the active cell relative to where it is. */\nconst RELATIVE_KEYS = new Set([\n 'ArrowDown',\n 'ArrowUp',\n 'ArrowLeft',\n 'ArrowRight',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown',\n]);\n\n/** The focused element, through every open shadow root on the way down. */\nfunction deepActiveElement(): Element | null {\n let el = document.activeElement;\n while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement;\n return el;\n}\n\nexport class NavigationController<T extends object> implements ReactiveController {\n protected handlers = new Map(\n Object.entries({\n ArrowDown: this.arrowDown,\n ArrowUp: this.arrowUp,\n ArrowLeft: this.arrowLeft,\n ArrowRight: this.arrowRight,\n Home: this.home,\n End: this.end,\n PageUp: this.pageUp,\n PageDown: this.pageDown,\n ' ': this.toggleSelection,\n })\n );\n\n protected get virtualizer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n /**\n * The active cell of this grid. Instance state on purpose: every grid on a\n * page, including one nested in another grid's detail panel, keeps its own.\n */\n protected _active = SENTINEL_NODE as ActiveNode<T>;\n\n protected get nextNode() {\n return this._active === SENTINEL_NODE\n ? ({ column: this.firstColumn, row: 0 } as ActiveNode<T>)\n : ({ ...this._active } as ActiveNode<T>);\n }\n\n protected get columns(): Array<{ key: Keys<T>; hidden?: boolean }> {\n return getDisplayColumns(this.host.columns) as unknown as Array<{\n key: Keys<T>;\n hidden?: boolean;\n }>;\n }\n\n protected get visibleColumns() {\n return this.columns.filter((column) => !column.hidden);\n }\n\n protected get firstColumn(): Keys<T> {\n const first = this.visibleColumns.at(0);\n return (first?.key ?? (this.host.columns[0]?.key as Keys<T>)) as Keys<T>;\n }\n\n /** Whether there is any cell to move to: a body row and a visible column. */\n protected get navigable(): boolean {\n return this.host.pageItems.length > 0 && this.visibleColumns.length > 0;\n }\n\n protected getPreviousColumn(key: Keys<T>): Keys<T> {\n const columns = this.visibleColumns;\n const idx = columns.findIndex((column) => column.key === key);\n return columns[Math.max(idx - 1, 0)]?.key ?? key;\n }\n\n protected getNextColumn(key: Keys<T>): Keys<T> {\n const columns = this.visibleColumns;\n const idx = columns.findIndex((column) => column.key === key);\n return columns[Math.min(idx + 1, columns.length - 1)]?.key ?? key;\n }\n\n /** The rendered body row at `index`, when the virtualizer has it in the DOM. */\n protected findRow(index: number) {\n return Array.from(this.virtualizer.querySelectorAll(GRID_ROW_TAG)).find(\n (row) => (row as unknown as ApexGridRow<T>).index === index\n ) as unknown as ApexGridRow<T> | undefined;\n }\n\n /**\n * The element that stands for `node` in the DOM: the cell, or for a row a\n * feature module renders full width (a group header, a total row) the\n * row's single focus target, whatever the column.\n */\n protected findCell(node: ActiveNode<T>): HTMLElement | undefined {\n const row = this.findRow(node.row);\n if (!row) return undefined;\n return (\n row.presentedCell ??\n (row.cells.find((cell) => cell.column.key === node.column) as HTMLElement | undefined)\n );\n }\n\n protected scrollToCell(node: ActiveNode<T>) {\n const cell = this.findCell(node);\n if (cell) {\n revealWithin(this.host as unknown as HTMLElement, cell, {\n block: 'nearest',\n inline: 'nearest',\n insets: this.scrollInsets(),\n });\n }\n }\n\n /** Scrolls body row `index` into view, rendered or not. */\n protected scrollToRow(index: number) {\n this.virtualizer\n .element(index)\n ?.scrollIntoView({ block: 'nearest', insets: this.scrollInsets() });\n }\n\n /** The cell {@link revealCell} last asked for, so a late reveal yields to a newer one. */\n #revealing: ActiveNode<T> | null = null;\n\n /**\n * Scrolls the cell at `node` into view clear of the sticky chrome without\n * moving the active cell: the cell itself when it is rendered, else its row\n * first and the cell once the virtualizer has rendered it. For a feature\n * that moves something other than the active cell with the keyboard (range\n * extension), so it scrolls the way arrow navigation does.\n */\n public revealCell(node: ActiveNode<T>): void {\n this.#revealing = node;\n if (this.findCell(node)) {\n this.scrollToCell(node);\n return;\n }\n this.scrollToRow(node.row);\n void this.virtualizer.settled().then(() => {\n if (this.#revealing === node) this.scrollToCell(node);\n });\n }\n\n /**\n * Whether ArrowLeft or ArrowRight steps towards the end of the column\n * order: ArrowRight in a left-to-right grid, ArrowLeft in a right-to-left\n * one. The rule every inline arrow key on this grid follows.\n */\n public towardsInlineEnd(key: string): boolean {\n return isRTL(this.host as unknown as Element) === (key === 'ArrowLeft');\n }\n\n /**\n * How much of the scroll container's scrollport the sticky chrome covers\n * (toolbar, headers and the pinned-top band above, the pinned-bottom band\n * and the paginator below, pinned columns on either side). Keyboard scrolls\n * use it as scroll-padding, so a row or cell the keyboard moves to is never\n * parked underneath that chrome. Measured right before each keyboard scroll\n * because any of those bands can change size between key presses. Public\n * so a feature scrolling the body itself (drag auto-scroll) measures the\n * same chrome.\n */\n public scrollInsets(): ScrollInsets {\n const host = this.host as unknown as HTMLElement;\n const root = host.shadowRoot;\n if (!root) return { top: 0, right: 0, bottom: 0, left: 0 };\n const box = host.getBoundingClientRect();\n const top = box.top + host.clientTop;\n const left = box.left + host.clientLeft;\n const bottom = top + host.clientHeight;\n const right = left + host.clientWidth;\n\n let insetTop = 0;\n for (const el of root.querySelectorAll('apex-grid-header-row, [part~=\"pinned-top\"]')) {\n insetTop = Math.max(insetTop, el.getBoundingClientRect().bottom - top);\n }\n let insetBottom = 0;\n for (const el of root.querySelectorAll('apex-grid-paginator, [part~=\"pinned-bottom\"]')) {\n insetBottom = Math.max(insetBottom, bottom - el.getBoundingClientRect().top);\n }\n\n let insetLeft = 0;\n let insetRight = 0;\n const headerRow = root.querySelector('apex-grid-header-row');\n const pinned = headerRow?.shadowRoot?.querySelectorAll(\n '[data-pinned=\"start\"], [data-pinned=\"end\"]'\n );\n if (pinned?.length) {\n const rtl = isRTL(host);\n for (const el of pinned) {\n const rect = el.getBoundingClientRect();\n const atLeft = (el.getAttribute('data-pinned') === 'start') !== rtl;\n if (atLeft) insetLeft = Math.max(insetLeft, rect.right - left);\n else insetRight = Math.max(insetRight, right - rect.left);\n }\n }\n\n const clamp = (inset: number) => Math.max(0, Math.round(inset));\n return {\n top: clamp(insetTop),\n right: clamp(insetRight),\n bottom: clamp(insetBottom),\n left: clamp(insetLeft),\n };\n }\n\n /**\n * Moves real DOM focus to the active cell (the grid body's roving tab stop),\n * so screen readers track keyboard navigation. Waits for the host render to\n * commit the cell's `active` state and, when the cell is not in the DOM yet\n * (a long jump), for the virtualizer to finish laying out the new range.\n * No-op while no cell is active (the scroll container keeps focus as the\n * entry point).\n *\n * @param reveal - also scroll the cell into view once it exists, for jumps\n * whose target row was not rendered when the scroll started.\n */\n public focusActiveCell(reveal = false): void {\n void this.#focusActive(reveal);\n }\n\n /** {@link focusActiveCell}, settling once the focus moved or was given up. */\n async #focusActive(reveal = false): Promise<void> {\n const node = this._active;\n if (node === SENTINEL_NODE) return;\n await this.host.updateComplete;\n let cell = this.findCell(node);\n if (!cell) {\n await this.virtualizer.settled();\n cell = this.findCell(node);\n }\n if (!cell) {\n await new Promise(requestAnimationFrame);\n cell = this.findCell(node);\n }\n // An estimated scroll missed the row (stale size estimates): wait for the\n // virtualizer's corrected scrolls to render it.\n if (!cell && this._active === node) {\n await this.virtualizer.revealed();\n cell = this.findCell(node);\n }\n // The user moved on while this was waiting: leave focus to the newer move.\n if (!cell || this._active !== node) return;\n if (reveal) this.scrollToCell(node);\n cell.focus({ preventScroll: true });\n }\n\n public get active() {\n return this._active;\n }\n\n public set active(node: ActiveNode<T>) {\n this._active = node;\n this.host.requestUpdate();\n }\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n /**\n * Whether this grid's body holds focus: the body itself, one of its cells\n * or an editor in one, not a grid nested in a detail panel. Tracked from\n * the body's focus events ({@link focusEntered}, {@link focusLeft}). A\n * focus loss a re-bind caused (it removed the focused editor while a\n * reconcile is running) keeps it until that reconcile has run, so it can\n * put focus back under row recycling. Any other loss clears it: a click\n * elsewhere, the window losing focus, a template removing its own focused\n * element, the grid leaving the document. Focus is never taken back once\n * it left the grid.\n */\n public get ownsFocus(): boolean {\n this.#settleLoss();\n return this.#ownsFocus;\n }\n\n #ownsFocus = false;\n\n /**\n * Clears {@link ownsFocus} when focus went nowhere with nothing pending to\n * repair it. Chromium reports a focused element removed or moved in the\n * DOM with a `focusout` ({@link focusLeft} decides then); Firefox and\n * WebKit drop focus silently, so the loss is noticed here, the next time\n * anything asks.\n */\n #settleLoss(): void {\n if (!this.#ownsFocus || this.#reconciling || this.#parked || this.#detached) return;\n if (this.#lost()) this.#ownsFocus = false;\n }\n\n /** The record the focused row showed when focus arrived, for the reconcile. */\n #focusedRecord: T | null = null;\n\n /** The element focus arrived on and the row it stood in, for the reconcile. */\n #focusTarget: { el: Element; row: ApexGridRow<T> | undefined } | null = null;\n\n /**\n * The element that lost focus to nowhere in this task, until a microtask\n * tells a removal (no longer in the document) from a blur (still there).\n */\n #blurred: Element | null = null;\n\n /**\n * An element that lost focus by moving into another row with its record\n * while a reconcile was running, for the reconcile to focus again.\n */\n #moved: Element | null = null;\n\n /** Bumped by every {@link reconcileFocus}, so only the latest one acts. */\n #reconcile = 0;\n\n /** The token of the reconcile still to run, or 0 when none is. */\n #reconciling = 0;\n\n /** Set while a page change holds focus in the body (see {@link parkFocus}). */\n #parked: { record: T | null } | null = null;\n\n /** Set while this controller focuses the body itself, which must not forward. */\n #focusingBody = false;\n\n /** A focused grid's active cell when it was detached, until it is re-attached. */\n #detached: { node: ActiveNode<T> } | null = null;\n\n /**\n * Whether focus arriving on the body itself should move on to the active\n * cell (the roving tab stop). Not while a page change holds focus in the\n * body, or while this controller puts it there.\n */\n public get forwardsBodyFocus(): boolean {\n return !this.#parked && !this.#focusingBody;\n }\n\n /**\n * Focus arrived in the body. `owned` is whether the event is this grid's\n * rather than a nested grid's (the grid's `ownsEvent`).\n */\n public focusEntered(event: FocusEvent, owned: boolean): void {\n this.#blurred = null;\n this.#moved = null;\n this.#ownsFocus = owned;\n const el = event.composedPath()[0] as Element;\n const row = owned ? this.#locate(el)?.row : undefined;\n this.#focusedRecord = row?.data ?? null;\n this.#focusTarget = owned ? { el, row } : null;\n }\n\n /**\n * Focus left something in the body. Focus moving to another element is\n * followed by its `focusin`, which sets {@link ownsFocus} again when that\n * element is this body's. Focus going nowhere is a blur when the element\n * is still in the document a microtask later, and a removal otherwise. A\n * removal keeps {@link ownsFocus} only while a reconcile is running, which\n * then decides; with none, nothing would repair it, so a later reconcile\n * must not either.\n */\n public focusLeft(event: FocusEvent, owned: boolean): void {\n if (!owned) return;\n if (event.relatedTarget) {\n this.#ownsFocus = false;\n return;\n }\n const target = event.composedPath()[0] as Element;\n const from = this.#locate(target)?.row;\n this.#blurred = target;\n queueMicrotask(() => {\n if (this.#blurred !== target) return;\n this.#blurred = null;\n if (!this.#reconciling) {\n this.#ownsFocus = false;\n return;\n }\n if (!target.isConnected) return;\n // Still in the document but in another row: a detail panel's content\n // followed its record there (see DetailRoots in row.ts), which the\n // browser treats as a blur. The reconcile puts focus back on it.\n const to = this.#locate(target)?.row;\n if (to && to !== from) this.#moved = target;\n else this.#ownsFocus = false;\n });\n }\n\n /**\n * Row recycling: after the rows re-render, puts focus back in the body when\n * the render took it away. A re-bind keeps every row element in place, so\n * focus usually stays where it was, on the cell at the active position; it\n * is lost only when the focused element left the document (an editor whose\n * slot now shows another record) or stands on a row that now shows another\n * record without being active. Then focus goes to the edited record's\n * editor when it is rendered, else the active cell when its row is, else\n * the body. Acts only while the body owns focus, so it never takes focus\n * back from outside the grid or off a nested grid. A loss it leaves\n * unrepaired clears {@link ownsFocus}.\n */\n public reconcileFocus(): void {\n this.#settleLoss();\n if (!this.#ownsFocus || !this.host.rowRecycling) return;\n const token = ++this.#reconcile;\n this.#reconciling = token;\n void (async () => {\n try {\n // A range change commits its rows right after its listeners return.\n await Promise.resolve();\n await this.virtualizer.rendered();\n if (token !== this.#reconcile || this.#parked) return;\n if (!this.#ownsFocus || !this.host.isConnected) return;\n const focused = deepActiveElement();\n if (focused && focused !== document.body) {\n const at = this.#locate(focused);\n if (!at?.row) return;\n const active = this._active;\n const onActive =\n at.row.index === active.row && (!at.cell || at.cell.column.key === active.column);\n if (onActive || at.row.data === this.#focusedRecord) return;\n }\n await this.#restoreFocus();\n } finally {\n if (token === this.#reconcile) {\n this.#reconciling = 0;\n this.#moved = null;\n // A page change decides once its pipeline has run (parkFocus).\n if (!this.#parked && this.#lost()) this.#ownsFocus = false;\n }\n }\n })();\n }\n\n /**\n * Focus on what moved with the focused record (a detail panel's input),\n * else the edited record's editor, else the active cell, else the body.\n */\n async #restoreFocus(): Promise<void> {\n const moved = this.#moved ?? this.#silentlyMoved();\n this.#moved = null;\n if (moved?.isConnected && moved instanceof HTMLElement) {\n const at = this.#locate(moved);\n if (at?.row && at.row.data === this.#focusedRecord) {\n moved.focus({ preventScroll: true });\n return;\n }\n }\n const edit = this.editing?.activeCell;\n const row = edit && this.#renderedRows().find((each) => each.data === edit.data);\n const cell = row?.cells.find((each) => each.column.key === edit?.columnKey);\n if (cell) {\n await cell.updateComplete;\n const editor = cell.shadowRoot?.querySelector<HTMLElement>('input, [data-apex-editor]');\n if (this.#lost()) (editor ?? cell).focus({ preventScroll: true });\n return;\n }\n if (this._active !== SENTINEL_NODE && this.virtualizer.isRendered(this._active.row)) {\n await this.#focusActive();\n return;\n }\n this.#focusBody();\n }\n\n /**\n * The focused element when it moved into another row without a `focusout`\n * (Firefox, WebKit), which {@link focusLeft} records as {@link #moved} in\n * Chromium: focus went nowhere and the element is back in the document in\n * another row.\n */\n #silentlyMoved(): Element | null {\n const target = this.#focusTarget;\n if (!target?.el.isConnected || !this.#lost()) return null;\n const to = this.#locate(target.el)?.row;\n return to && to !== target.row ? target.el : null;\n }\n\n /**\n * Row recycling: a page change re-binds every row to the new page's\n * records, so a focused cell would stay focused on another record. Holds\n * focus in the body across the change: the body does not forward focus to\n * the active cell, and the post-render reconcile waits. Returns what to\n * call once the change has run its pipeline: focus then moves to the body\n * unless it rests on an editor or on a cell still showing the record it\n * showed before. Returns `null`, holding nothing, without row recycling or\n * while the body does not own focus.\n */\n public parkFocus(): (() => Promise<void>) | null {\n this.#settleLoss();\n if (!this.host.rowRecycling || !this.#ownsFocus) return null;\n const at = this.#locate(deepActiveElement());\n const park = { record: at?.row?.data ?? null };\n this.#parked = park;\n return async () => {\n await this.virtualizer.rendered();\n if (this.#parked !== park) return;\n this.#parked = null;\n if (!this.#ownsFocus || !this.host.isConnected) return;\n const focused = deepActiveElement();\n if (focused && focused !== document.body) {\n const now = this.#locate(focused);\n if (!now?.row) return;\n if (now.cell && (now.cell as HTMLElement & { editing?: boolean }).editing) return;\n if (now.row.data === park.record) return;\n }\n this.#focusBody();\n };\n }\n\n /** Focuses the body itself, without its forward to the active cell. */\n #focusBody(): void {\n this.#focusingBody = true;\n try {\n (this.virtualizer as HTMLElement).focus({ preventScroll: true });\n } finally {\n this.#focusingBody = false;\n }\n }\n\n /** Whether focus has gone nowhere. */\n #lost(): boolean {\n const focused = deepActiveElement();\n return !focused || focused === document.body;\n }\n\n #renderedRows(): ApexGridRow<T>[] {\n return Array.from(\n this.virtualizer.querySelectorAll(GRID_ROW_TAG)\n ) as unknown as ApexGridRow<T>[];\n }\n\n /**\n * Where `el` stands in this grid's body: the row and cell holding it, or\n * neither for the body itself. `null` when it is not in this body, which\n * includes a grid nested in one of its rows (its own body comes first on\n * the way up).\n */\n #locate(\n el: EventTarget | null\n ): { row?: ApexGridRow<T>; cell?: ApexGridRow<T>['cells'][number] } | null {\n const body = this.virtualizer as Element | null;\n if (!body) return null;\n let row: ApexGridRow<T> | undefined;\n let cell: ApexGridRow<T>['cells'][number] | undefined;\n let node = el instanceof Node ? el : null;\n while (node) {\n if (node === body) return { row, cell };\n if (node instanceof Element) {\n const name = node.localName;\n if (name === GRID_BODY) return null;\n if (!cell && name === GRID_CELL_TAG) cell = node as unknown as typeof cell;\n if (!row && name === GRID_ROW_TAG) row = node as unknown as ApexGridRow<T>;\n }\n node = node instanceof ShadowRoot ? node.host : node.parentNode;\n }\n return null;\n }\n\n /**\n * Keeps the active cell pointing at something that exists. Runs before\n * every grid render, so after a data swap, sort, filter, page change or a\n * column hide or reorder the active node is clamped to the last row and the\n * nearest visible column, or cleared when there is nothing left to point\n * at (no rows, no visible columns). Without it a stale node names a cell\n * that is never rendered, which leaves the body with no tab stop.\n */\n public hostUpdate() {\n const node = this._active;\n if (node === SENTINEL_NODE) return;\n const count = this.host.pageItems.length;\n if (!count || !this.visibleColumns.length) {\n this._active = SENTINEL_NODE as ActiveNode<T>;\n return;\n }\n // An open edit follows its record when a sort, filter or data change\n // moves it (the editing controller updates its index after this render).\n // The active cell on it goes along when the record stays in the rendered\n // rows, so the keyboard carries on from the edited cell once the edit\n // closes. A record moved out of view leaves the active cell in place,\n // where the user is looking.\n const edit = this.editing?.activeCell;\n if (edit && node.row === edit.rowIndex && node.column === edit.columnKey) {\n const index = this.host.pageItems.indexOf(edit.data);\n if (index >= 0 && index !== edit.rowIndex && this.virtualizer.isRendered(index)) {\n this._active = { column: node.column, row: index } as ActiveNode<T>;\n return;\n }\n }\n const row = Math.min(node.row, count - 1);\n const column = this.#nearestVisibleColumn(node.column);\n if (row !== node.row || column !== node.column) {\n this._active = { column, row } as ActiveNode<T>;\n }\n }\n\n /** `key` when it is visible, else the closest visible column in display order. */\n #nearestVisibleColumn(key: Keys<T>): Keys<T> {\n const columns = this.columns;\n const index = columns.findIndex((column) => column.key === key);\n if (index < 0) return this.firstColumn;\n for (let distance = 0; distance < columns.length; distance++) {\n for (const at of [index + distance, index - distance]) {\n const column = columns[at];\n if (column && !column.hidden) return column.key;\n }\n }\n return this.firstColumn;\n }\n\n /** The active row is one a feature module renders full width (no cells). */\n protected isPresentedRow(index: number): boolean {\n const data = this.host.pageItems[index];\n if (!data) return false;\n // @ts-expect-error - protected member access\n const state = this.host.stateController as {\n presentRow(row: T, ctx: { columns: ColumnConfiguration<T>[]; rowIndex: number }): unknown;\n };\n return state.presentRow(data, { columns: this.host.columns, rowIndex: index }) !== null;\n }\n\n /** Home moves to the first cell in the row (ARIA grid pattern). */\n protected home() {\n this.active = Object.assign(this.nextNode, { column: this.firstColumn });\n this.scrollToCell(this.active);\n }\n\n /** End moves to the last cell in the row (ARIA grid pattern). */\n protected end() {\n const last = this.visibleColumns.at(-1)?.key ?? this.firstColumn;\n this.active = Object.assign(this.nextNode, { column: last });\n this.scrollToCell(this.active);\n }\n\n /** Ctrl/Cmd+Home moves to the first cell of the grid. */\n protected ctrlHome() {\n this.active = { column: this.firstColumn, row: 0 } as ActiveNode<T>;\n this.scrollToRow(0);\n }\n\n /** Ctrl/Cmd+End moves to the last cell of the grid. */\n protected ctrlEnd() {\n const row = this.host.pageItems.length - 1;\n const last = this.visibleColumns.at(-1)?.key ?? this.firstColumn;\n this.active = { column: last, row } as ActiveNode<T>;\n this.scrollToRow(row);\n }\n\n /**\n * Rows per Page Up/Down step: the rows that fit in the part of the\n * scrollport the sticky chrome leaves visible, minus one so the row the\n * user was on stays in view. Falls back to 10 when nothing is measurable.\n */\n protected pageStep(): number {\n const host = this.host as unknown as HTMLElement;\n let rowHeight = 0;\n for (const row of this.virtualizer.querySelectorAll(GRID_ROW_TAG)) {\n const height = (row as HTMLElement).offsetHeight;\n // The shortest rendered row: an expanded detail panel is not a row height.\n if (height > 0 && (!rowHeight || height < rowHeight)) rowHeight = height;\n }\n const { top, bottom } = this.scrollInsets();\n const viewport = host.clientHeight - top - bottom;\n if (!rowHeight || viewport <= 0) return 10;\n return Math.max(1, Math.floor(viewport / rowHeight) - 1);\n }\n\n protected pageUp() {\n const next = this.nextNode;\n this.active = Object.assign(next, { row: Math.max(0, next.row - this.pageStep()) });\n this.scrollToRow(this.active.row);\n }\n\n protected pageDown() {\n const next = this.nextNode;\n this.active = Object.assign(next, {\n row: Math.min(this.host.pageItems.length - 1, next.row + this.pageStep()),\n });\n this.scrollToRow(this.active.row);\n }\n\n protected arrowDown() {\n const next = this.nextNode;\n this.active = Object.assign(next, {\n row: Math.min(next.row + 1, this.host.pageItems.length - 1),\n });\n this.scrollToRow(next.row);\n }\n\n protected arrowUp() {\n const next = this.nextNode;\n this.active = Object.assign(next, { row: Math.max(0, next.row - 1) });\n this.scrollToRow(next.row);\n }\n\n protected arrowLeft() {\n this.#moveInline('ArrowLeft');\n }\n\n protected arrowRight() {\n this.#moveInline('ArrowRight');\n }\n\n /**\n * Moves the active cell one column in a *physical* direction.\n *\n * ArrowLeft and ArrowRight name screen directions, not column order, so under\n * `dir=\"rtl\"` the column to the left is the *next* one and the mapping onto\n * previous/next inverts ({@link towardsInlineEnd}). Everything else about\n * navigation is order-based and needs no direction awareness.\n */\n #moveInline(key: 'ArrowLeft' | 'ArrowRight') {\n const next = this.nextNode;\n const column = this.towardsInlineEnd(key)\n ? this.getNextColumn(next.column)\n : this.getPreviousColumn(next.column);\n this.active = Object.assign(next, { column });\n this.scrollToCell(this.active);\n }\n\n protected toggleSelection() {\n // Space on the focused grid toggles selection of the active row.\n // No-op when selection is disabled, there's no active row, or the row is\n // module-rendered (a group header or total row is not a data row).\n const data = this.host.pageItems[this._active.row] as T | undefined;\n if (!data || this.isPresentedRow(this._active.row)) return;\n void this.host.toggleRowSelection(data);\n }\n\n public hostConnected() {\n const detached = this.#detached;\n this.#detached = null;\n if (detached) this.#refocusAfterMove(detached.node);\n }\n\n public hostDisconnected() {\n // A grid moved while its body held focus: under row recycling the master\n // row showing this grid's record changes on a master sort, and the\n // detail node follows its record into another row. The browser dropped\n // focus just before (`#blurred`, or silently in Firefox and WebKit, which\n // fire no `focusout` for it); a re-attach within this task restores the\n // active cell and focus. Anything later is a removal, as before.\n const dropped = this.#blurred !== null || (this.#ownsFocus && this.#lost());\n const moved = dropped && this.host.rowRecycling;\n const detached = moved ? { node: this._active } : null;\n this.active = SENTINEL_NODE as ActiveNode<T>;\n this.#detached = detached;\n // A grid out of the document holds no focus: a re-attach later (a kept\n // alive tab or route) must not take focus on its next sort or scroll.\n if (!detached) this.#ownsFocus = false;\n if (detached) {\n setTimeout(() => {\n if (this.#detached !== detached) return;\n this.#detached = null;\n this.#ownsFocus = false;\n });\n }\n }\n\n /**\n * Restores the active cell a moved grid had and focuses it (the body when\n * no cell was active, or its row is not rendered), unless something else\n * took focus in the meantime.\n */\n #refocusAfterMove(node: ActiveNode<T>): void {\n if (node !== SENTINEL_NODE) this.active = node;\n void (async () => {\n await this.host.updateComplete;\n if (!this.#lost() || this._active !== node || !this.host.isConnected) return;\n const cell = node === SENTINEL_NODE ? undefined : this.findCell(node);\n // The body forwards to the active cell once the rows have rendered.\n (cell ?? (this.virtualizer as HTMLElement)).focus({ preventScroll: true });\n })();\n }\n\n protected get editing() {\n // @ts-expect-error - protected member access\n return this.host.stateController.editing as\n | {\n activeCell: { data: T; columnKey: Keys<T>; rowIndex: number } | null;\n enabled: boolean;\n isEditable(column: ColumnConfiguration<T>): boolean;\n editCell(rowIndex: number, columnKey: Keys<T>): Promise<boolean>;\n }\n | undefined;\n }\n\n /**\n * Enter / F2 on the active cell opens its editor (the keyboard path into\n * edit mode). Returns `true` when the event was consumed.\n */\n protected handleEditKey(event: KeyboardEvent): boolean {\n if (event.key !== 'Enter' && event.key !== 'F2') return false;\n if (event.ctrlKey || event.metaKey || event.altKey) return false;\n if (this._active === SENTINEL_NODE || this.isPresentedRow(this._active.row)) return false;\n const editing = this.editing;\n if (!editing?.enabled) return false;\n const column = this.host.getColumn(this.active.column);\n if (!column || !editing.isEditable(column)) return false;\n event.preventDefault();\n void editing.editCell(this.active.row, this.active.column);\n return true;\n }\n\n protected get rowReorder() {\n // @ts-expect-error - protected member access\n return this.host.stateController.rowReorder as\n | {\n enabled: boolean;\n isGrabbing: boolean;\n grabbed: T | null;\n grab(rowIndex: number): boolean;\n moveGrabbed(direction: -1 | 1): number;\n drop(): void;\n cancelGrab(): void;\n }\n | undefined;\n }\n\n /**\n * Keyboard row reorder: Space grabs the active row, arrows move it, Space /\n * Enter drops, Escape cancels. Returns `true` when the event was consumed.\n * Only active when `rowReordering.enabled` (so it never shadows Space-to-select\n * on grids without reordering).\n */\n protected handleReorderKey(event: KeyboardEvent): boolean {\n const reorder = this.rowReorder;\n if (!reorder?.enabled) return false;\n\n if (reorder.isGrabbing) {\n switch (event.key) {\n case 'ArrowUp':\n case 'ArrowDown': {\n event.preventDefault();\n const row = reorder.grabbed;\n const next = reorder.moveGrabbed(event.key === 'ArrowDown' ? 1 : -1);\n if (next >= 0 && row) {\n this.active = Object.assign(this.nextNode, { row: next });\n this.scrollToRow(next);\n this.#followRecord(row);\n }\n return true;\n }\n case ' ':\n case 'Enter':\n event.preventDefault();\n reorder.drop();\n return true;\n case 'Escape': {\n event.preventDefault();\n const row = reorder.grabbed;\n reorder.cancelGrab();\n if (row) this.#followRecord(row);\n return true;\n }\n default:\n return false;\n }\n }\n\n if (event.key === ' ' && this.active.row >= 0 && !this.isPresentedRow(this.active.row)) {\n event.preventDefault();\n return reorder.grab(this.active.row);\n }\n return false;\n }\n\n /**\n * After a keyboard grab moves `record` (or Escape puts it back), puts the\n * active row on the record's view index and real focus on its cell, once\n * the re-run pipeline has rendered. The move re-renders the rows, which\n * can drop focus or leave it on an element now showing another record.\n * Yields when the active cell changed in the meantime (a newer key).\n */\n #followRecord(record: T): void {\n const node = this._active;\n // @ts-expect-error - protected member access\n void (this.host.pipelineSettled() as Promise<void>).then(() => {\n if (this._active !== node || node === SENTINEL_NODE) return;\n const row = this.host.pageItems.indexOf(record);\n if (row < 0) return;\n if (row !== node.row) {\n this.active = { ...node, row };\n this.scrollToRow(row);\n }\n this.focusActiveCell();\n });\n }\n\n public navigate(event: KeyboardEvent) {\n if (this.handleReorderKey(event)) return;\n // Undo / redo: Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, Ctrl/Cmd+Y. Only fires when the\n // grid body (not an open editor) has focus, so a text editor's native undo\n // is never hijacked.\n if ((event.ctrlKey || event.metaKey) && !event.altKey) {\n const key = event.key.toLowerCase();\n if (key === 'z' && !event.shiftKey) {\n event.preventDefault();\n this.host.undo();\n return;\n }\n if ((key === 'z' && event.shiftKey) || key === 'y') {\n event.preventDefault();\n this.host.redo();\n return;\n }\n // Ctrl/Cmd+Home / Ctrl/Cmd+End jump to the grid corners (ARIA grid pattern).\n if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n if (!this.navigable) return;\n if (event.key === 'Home') {\n this.ctrlHome();\n } else {\n this.ctrlEnd();\n }\n // The target row is often outside the rendered window, so the cell is\n // revealed (horizontally too) once the virtualizer has rendered it.\n this.focusActiveCell(true);\n return;\n }\n }\n if (this.handleEditKey(event)) return;\n if (RELATIVE_KEYS.has(event.key)) {\n event.preventDefault();\n if (!this.navigable) return;\n // Entering the body with the keyboard (Tab lands on the scroll\n // container, no cell active yet): an arrow, Home or Page Up activates\n // the first cell instead of moving past it. End and Page Down still\n // move, starting from that first cell.\n if (this._active === SENTINEL_NODE) {\n // Through the setter: the render it requests moves the tab stop\n // from the body to the cell.\n this.active = { column: this.firstColumn, row: 0 } as ActiveNode<T>;\n if (event.key !== 'End' && event.key !== 'PageDown') {\n this.scrollToRow(0);\n this.focusActiveCell(true);\n return;\n }\n }\n }\n if (this.handlers.has(event.key)) {\n event.preventDefault();\n this.handlers.get(event.key)!.call(this);\n // Real focus follows the active cell so AT tracks the movement.\n this.focusActiveCell();\n }\n }\n}\n"]}