apex-grid 3.6.0 → 4.0.0-beta.1

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 (122) hide show
  1. package/CHANGELOG.md +235 -0
  2. package/README.md +79 -13
  3. package/components/cell.d.ts +13 -1
  4. package/components/cell.js +28 -13
  5. package/components/cell.js.map +1 -1
  6. package/components/grid.d.ts +135 -13
  7. package/components/grid.js +165 -63
  8. package/components/grid.js.map +1 -1
  9. package/components/header-row.d.ts +0 -6
  10. package/components/header-row.js +1 -19
  11. package/components/header-row.js.map +1 -1
  12. package/components/header.js +39 -2
  13. package/components/header.js.map +1 -1
  14. package/components/paginator.d.ts +20 -5
  15. package/components/paginator.js +54 -17
  16. package/components/paginator.js.map +1 -1
  17. package/components/row.js +149 -40
  18. package/components/row.js.map +1 -1
  19. package/components/toolbar.d.ts +5 -1
  20. package/components/toolbar.js +4 -1
  21. package/components/toolbar.js.map +1 -1
  22. package/components/virtualize-rows.d.ts +38 -0
  23. package/components/virtualize-rows.js +286 -0
  24. package/components/virtualize-rows.js.map +1 -0
  25. package/components/virtualizer.d.ts +71 -1
  26. package/components/virtualizer.js +105 -29
  27. package/components/virtualizer.js.map +1 -1
  28. package/controllers/dom.d.ts +10 -3
  29. package/controllers/dom.js +5 -5
  30. package/controllers/dom.js.map +1 -1
  31. package/controllers/navigation.d.ts +63 -0
  32. package/controllers/navigation.js +295 -21
  33. package/controllers/navigation.js.map +1 -1
  34. package/controllers/pagination.d.ts +7 -6
  35. package/controllers/pagination.js +27 -28
  36. package/controllers/pagination.js.map +1 -1
  37. package/controllers/row-pin.d.ts +6 -0
  38. package/controllers/row-pin.js +8 -2
  39. package/controllers/row-pin.js.map +1 -1
  40. package/controllers/row-reorder.d.ts +12 -4
  41. package/controllers/row-reorder.js +20 -6
  42. package/controllers/row-reorder.js.map +1 -1
  43. package/controllers/selection.d.ts +32 -10
  44. package/controllers/selection.js +33 -10
  45. package/controllers/selection.js.map +1 -1
  46. package/controllers/sort.js +2 -3
  47. package/controllers/sort.js.map +1 -1
  48. package/controllers/state.d.ts +18 -0
  49. package/controllers/state.js +53 -42
  50. package/controllers/state.js.map +1 -1
  51. package/custom-elements.json +1404 -215
  52. package/docs/assets/hierarchy.js +1 -1
  53. package/docs/assets/search.js +1 -1
  54. package/docs/classes/ApexGrid.html +119 -47
  55. package/docs/classes/ApexGridPaginator.html +39 -8
  56. package/docs/classes/ApexGridToolbar.html +9 -5
  57. package/docs/functions/localize.html +2 -2
  58. package/docs/hierarchy.html +1 -1
  59. package/docs/index.html +85 -15
  60. package/docs/interfaces/ApexPageChangedEvent.html +3 -1
  61. package/docs/interfaces/BaseApexCellContext.html +18 -5
  62. package/docs/interfaces/BaseApexEditorContext.html +20 -5
  63. package/docs/interfaces/BaseFilterExpression.html +1 -1
  64. package/docs/interfaces/CSVExportOptions.html +1 -1
  65. package/docs/interfaces/DataPipelineConfiguration.html +4 -9
  66. package/docs/interfaces/ExportOptions.html +1 -1
  67. package/docs/interfaces/GridSelectionConfiguration.html +19 -4
  68. package/docs/interfaces/PaginationConfiguration.html +11 -4
  69. package/docs/interfaces/PaginationState.html +4 -2
  70. package/docs/media/package.json +7 -4
  71. package/docs/types/DataPipelineParams.html +2 -2
  72. package/docs/types/PaginationMode.html +5 -4
  73. package/docs/variables/EN_LOCALE.html +2 -2
  74. package/i18n/en.d.ts +2 -0
  75. package/i18n/en.js +2 -0
  76. package/i18n/en.js.map +1 -1
  77. package/i18n/es.js +2 -0
  78. package/i18n/es.js.map +1 -1
  79. package/internal/column-types.d.ts +11 -1
  80. package/internal/column-types.js +8 -6
  81. package/internal/column-types.js.map +1 -1
  82. package/internal/export.d.ts +6 -0
  83. package/internal/export.js +4 -0
  84. package/internal/export.js.map +1 -1
  85. package/internal/feature-module.d.ts +7 -0
  86. package/internal/feature-module.js.map +1 -1
  87. package/internal/flip.d.ts +28 -16
  88. package/internal/flip.js +42 -10
  89. package/internal/flip.js.map +1 -1
  90. package/internal/index.d.ts +2 -2
  91. package/internal/index.js +2 -2
  92. package/internal/index.js.map +1 -1
  93. package/internal/types.d.ts +75 -19
  94. package/internal/types.js.map +1 -1
  95. package/operations/filter/types.d.ts +1 -1
  96. package/operations/filter/types.js.map +1 -1
  97. package/package.json +2 -2
  98. package/styles/_tokens.css.js +1 -1
  99. package/styles/_tokens.css.js.map +1 -1
  100. package/styles/body-cell/body-cell.css.js +1 -1
  101. package/styles/body-cell/body-cell.css.js.map +1 -1
  102. package/styles/body-cell/cell-renderers.css.js +1 -1
  103. package/styles/body-cell/cell-renderers.css.js.map +1 -1
  104. package/styles/body-row/body-row.css.js +1 -1
  105. package/styles/body-row/body-row.css.js.map +1 -1
  106. package/styles/grid/_grid.base.css.js +1 -1
  107. package/styles/grid/_grid.base.css.js.map +1 -1
  108. package/styles/grid/grid.css.js +1 -1
  109. package/styles/grid/grid.css.js.map +1 -1
  110. package/styles/group-header-row/group-header-row.css.js +1 -1
  111. package/styles/group-header-row/group-header-row.css.js.map +1 -1
  112. package/styles/header-cell/header-cell.css.js +1 -1
  113. package/styles/header-cell/header-cell.css.js.map +1 -1
  114. package/styles/header-row/header-row.base.css.js +1 -1
  115. package/styles/header-row/header-row.base.css.js.map +1 -1
  116. package/styles/paginator/paginator.css.js +1 -1
  117. package/styles/paginator/paginator.css.js.map +1 -1
  118. package/styles/toolbar/toolbar.css.js +1 -1
  119. package/styles/toolbar/toolbar.css.js.map +1 -1
  120. package/operations/pagination.d.ts +0 -19
  121. package/operations/pagination.js +0 -12
  122. package/operations/pagination.js.map +0 -1
@@ -4,6 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
+ var _a;
7
8
  import { ContextProvider } from '@lit/context';
8
9
  import { html, nothing } from 'lit';
9
10
  import { eventOptions, property, query, queryAll, state } from 'lit/decorators.js';
@@ -11,6 +12,7 @@ import { styleMap } from 'lit/directives/style-map.js';
11
12
  import { DataOperationsController } from '../controllers/data-operation.js';
12
13
  import { GridDOMController } from '../controllers/dom.js';
13
14
  import { viewIndexer } from '../controllers/history.js';
15
+ import { DEFAULT_PAGINATION } from '../controllers/pagination.js';
14
16
  import { gridStateContext, StateController } from '../controllers/state.js';
15
17
  import { localize as resolveLocaleText, } from '../i18n/index.js';
16
18
  import { DEFAULT_COLUMN_CONFIG, PIPELINE, SENTINEL_NODE } from '../internal/constants.js';
@@ -31,7 +33,7 @@ import ApexGridHeaderRow from './header-row.js';
31
33
  import ApexGridPaginator from './paginator.js';
32
34
  import ApexGridRow from './row.js';
33
35
  import ApexGridToolbar from './toolbar.js';
34
- import ApexVirtualizer from './virtualizer.js';
36
+ import ApexVirtualizer, { quietResizeObserverLoopNotice } from './virtualizer.js';
35
37
  const SORT_DIRECTIONS = ['ascending', 'descending', 'none'];
36
38
  const VIEW_SHAPING_SLICES = new Set([
37
39
  'columns',
@@ -45,7 +47,7 @@ const VIEW_SHAPING_PROPERTIES = new Map([
45
47
  ['quickFilter', null],
46
48
  ['pagination', ['enabled', 'mode', 'pageSize', 'totalItems']],
47
49
  ['tree', ['enabled', 'getDataPath', 'defaultExpanded']],
48
- ['dataPipelineConfiguration', ['sort', 'filter', 'pagination', 'quickFilter']],
50
+ ['dataPipelineConfiguration', ['sort', 'filter', 'quickFilter']],
49
51
  ]);
50
52
  function viewShapeChanged(fields, before, after) {
51
53
  if (Object.is(before, after))
@@ -56,6 +58,9 @@ function viewShapeChanged(fields, before, after) {
56
58
  const b = (after ?? {});
57
59
  return fields.some((field) => !Object.is(a[field], b[field]));
58
60
  }
61
+ function keyChanged(key, previous) {
62
+ return key.some((value, i) => value !== previous[i]);
63
+ }
59
64
  function warnDropped(message) {
60
65
  console.warn(`[apex-grid] ${message}`);
61
66
  }
@@ -83,23 +88,31 @@ export class ApexGrid extends EventEmitterBase {
83
88
  this.showExport = false;
84
89
  this.columnReordering = false;
85
90
  this.columnSeparator = true;
91
+ this.#rowRecycling = _a.defaultRowRecycling;
86
92
  this.coordinateHints = false;
87
93
  this.columnMenu = true;
94
+ this.showHeader = true;
95
+ this.#bodyKey = [];
96
+ this.#bodyRows = [];
97
+ this.#pageKey = [];
98
+ this.#pageItems = [];
88
99
  this.#viewChangePending = false;
89
100
  this.#shapingPending = false;
90
101
  this.#pipelineRun = 0;
91
102
  this.#pipelineSettled = Promise.resolve();
92
103
  this.#settlePipeline = null;
93
- this.#autoAriaLabel = null;
104
+ this.#pinKey = [];
94
105
  this.#stateChangedListeners = new Map();
95
106
  this.#lastStateJson = null;
107
+ this.#labelObserver = new MutationObserver(() => this.requestUpdate());
96
108
  }
97
109
  static get tagName() {
98
110
  return GRID_TAG;
99
111
  }
100
112
  static { this.styles = gridStyles; }
113
+ static { this.defaultRowRecycling = globalThis.__apexRowKeying !== 'item'; }
101
114
  static register() {
102
- registerComponent(ApexGrid, ApexVirtualizer, ApexGridRow, ApexGridGroupHeaderRow, ApexGridHeaderRow, ApexFilterRow, ApexGridPaginator, ApexGridToolbar);
115
+ registerComponent(_a, ApexVirtualizer, ApexGridRow, ApexGridGroupHeaderRow, ApexGridHeaderRow, ApexFilterRow, ApexGridPaginator, ApexGridToolbar);
103
116
  }
104
117
  createStateController() {
105
118
  return new StateController(this);
@@ -125,6 +138,13 @@ export class ApexGrid extends EventEmitterBase {
125
138
  localize(key, params, fallback) {
126
139
  return resolveLocaleText(this.localeText, key, params, fallback);
127
140
  }
141
+ get rowRecycling() {
142
+ return this.#rowRecycling;
143
+ }
144
+ set rowRecycling(value) {
145
+ this.#rowRecycling = value ?? _a.defaultRowRecycling;
146
+ }
147
+ #rowRecycling;
128
148
  get selectedRows() {
129
149
  return this.stateController.selection.selectedRows();
130
150
  }
@@ -254,26 +274,44 @@ export class ApexGrid extends EventEmitterBase {
254
274
  return getDisplayColumns(this.columns);
255
275
  }
256
276
  get totalItems() {
257
- if (this.pagination?.mode === 'remote') {
258
- return Math.max(0, this.pagination?.totalItems ?? 0);
277
+ return this.stateController.pagination.totalItems;
278
+ }
279
+ get bodyRows() {
280
+ const { rowPin, dataVersion } = this.stateController;
281
+ const key = [this.dataState, dataVersion, rowPin.version, rowPin.enabled];
282
+ if (keyChanged(key, this.#bodyKey)) {
283
+ this.#bodyKey = key;
284
+ this.#bodyRows = rowPin.hasPinnedRows
285
+ ? this.dataState.filter((row) => !rowPin.isPinned(row))
286
+ : this.dataState;
259
287
  }
260
- return this.dataState.length;
288
+ return this.#bodyRows;
261
289
  }
290
+ #bodyKey;
291
+ #bodyRows;
262
292
  get pageItems() {
263
- const rowPin = this.stateController.rowPin;
264
- const base = rowPin?.hasPinnedRows
265
- ? this.dataState.filter((row) => !rowPin.isPinned(row))
266
- : this.dataState;
267
- if (!this.stateController.pagination.enabled)
268
- return base;
269
- if (this.pagination?.mode === 'remote')
270
- return base;
271
- const { page, pageSize } = this.stateController.pagination;
272
- if (!pageSize)
273
- return base;
274
- const start = page * pageSize;
275
- return base.slice(start, start + pageSize);
293
+ const { pagination, dataVersion } = this.stateController;
294
+ const key = [
295
+ this.bodyRows,
296
+ dataVersion,
297
+ pagination.enabled,
298
+ this.pagination?.mode,
299
+ pagination.page,
300
+ pagination.pageSize,
301
+ ];
302
+ if (keyChanged(key, this.#pageKey)) {
303
+ this.#pageKey = key;
304
+ const base = this.bodyRows;
305
+ const { page, pageSize } = pagination;
306
+ this.#pageItems =
307
+ !pagination.enabled || this.pagination?.mode === 'remote' || !pageSize
308
+ ? base
309
+ : base.slice(page * pageSize, (page + 1) * pageSize);
310
+ }
311
+ return this.#pageItems;
276
312
  }
313
+ #pageKey;
314
+ #pageItems;
277
315
  get page() {
278
316
  return this.stateController.pagination.page;
279
317
  }
@@ -450,35 +488,23 @@ export class ApexGrid extends EventEmitterBase {
450
488
  if (entries.length)
451
489
  this.filter([...entries]);
452
490
  }
491
+ willUpdate(changed) {
492
+ super.willUpdate(changed);
493
+ const { rowPin, pagination } = this.stateController;
494
+ const key = [rowPin.version, rowPin.enabled];
495
+ if (keyChanged(key, this.#pinKey)) {
496
+ this.#pinKey = key;
497
+ if (!changed.has(PIPELINE) && !this.#viewStale)
498
+ pagination.reclamp();
499
+ }
500
+ }
501
+ #pinKey;
453
502
  updated() {
454
503
  this.#viewChangePending = false;
455
- this.setAttribute('role', this.stateController.tree.enabled ? 'treegrid' : 'grid');
456
- const pinned = this.stateController.rowPin.pinnedRows;
457
- this.setAttribute('aria-rowcount', String(this.headerRowCount + pinned.top.length + this.pageItems.length + pinned.bottom.length));
458
- const visibleColumns = this.columns.filter((column) => !column.hidden).length;
459
- const extras = (this.stateController.selection.showCheckboxColumn ? 1 : 0) +
460
- (this.stateController.expansion.showToggleColumn ? 1 : 0);
461
- this.setAttribute('aria-colcount', String(visibleColumns + extras));
462
- const selection = this.stateController.selection;
463
- if (selection.enabled && selection.mode === 'multiple') {
464
- this.setAttribute('aria-multiselectable', 'true');
465
- }
466
- else {
467
- this.removeAttribute('aria-multiselectable');
468
- }
469
504
  this.#syncBodyTabStop();
470
- const currentLabel = this.getAttribute('aria-label');
471
- const authorLabeled = this.hasAttribute('aria-labelledby') ||
472
- (currentLabel !== null && currentLabel !== this.#autoAriaLabel);
473
- if (!authorLabeled) {
474
- const label = this.localize('grid.label');
475
- if (currentLabel !== label)
476
- this.setAttribute('aria-label', label);
477
- this.#autoAriaLabel = label;
478
- }
505
+ this.stateController.navigation.reconcileFocus();
479
506
  this.#emitStateChangedIfNeeded();
480
507
  }
481
- #autoAriaLabel;
482
508
  #stateChangedListeners;
483
509
  #lastStateJson;
484
510
  addEventListener(type, listener, options) {
@@ -545,7 +571,12 @@ export class ApexGrid extends EventEmitterBase {
545
571
  connectedCallback() {
546
572
  super.connectedCallback();
547
573
  adoptGridDocumentStyles(this);
574
+ quietResizeObserverLoopNotice();
575
+ this.#labelObserver.observe(this, {
576
+ attributeFilter: ['aria-label', 'aria-labelledby', 'aria-describedby'],
577
+ });
548
578
  }
579
+ #labelObserver;
549
580
  firstUpdated() {
550
581
  if (typeof getComputedStyle === 'function' && getComputedStyle(this).display !== 'grid') {
551
582
  console.warn('[apex-grid] Host `display` has been overridden. The grid requires ' +
@@ -745,7 +776,11 @@ export class ApexGrid extends EventEmitterBase {
745
776
  const selection = asArray(state.selection, 'selection');
746
777
  if (selection) {
747
778
  const ctrl = this.stateController.selection;
748
- const rows = resolveCounted(selection, 'selection');
779
+ const resolved = resolveCounted(selection, 'selection');
780
+ const rows = ctrl.selectable(resolved);
781
+ if (rows.length < resolved.length) {
782
+ warn(`selection: ${resolved.length - rows.length} row(s) are not selectable; skipped`);
783
+ }
749
784
  const expected = ctrl.mode === 'single' ? rows.slice(0, 1) : rows;
750
785
  if (this.#replaceRows('selection', ctrl.enabled, expected, warn, () => {
751
786
  void ctrl.replaceSelection(expected);
@@ -1053,7 +1088,7 @@ export class ApexGrid extends EventEmitterBase {
1053
1088
  for (const node of event.composedPath()) {
1054
1089
  if (node === this || node === this.scrollContainer)
1055
1090
  return true;
1056
- if (node instanceof ApexGrid || node instanceof ApexVirtualizer)
1091
+ if (node instanceof _a || node instanceof ApexVirtualizer)
1057
1092
  return false;
1058
1093
  }
1059
1094
  return false;
@@ -1074,6 +1109,7 @@ export class ApexGrid extends EventEmitterBase {
1074
1109
  (focused.index < first || focused.index > last)) {
1075
1110
  this.scrollContainer.focus({ preventScroll: true });
1076
1111
  }
1112
+ this.stateController.navigation.reconcileFocus();
1077
1113
  }
1078
1114
  #ownCell(event) {
1079
1115
  if (!this.ownsEvent(event))
@@ -1114,10 +1150,16 @@ export class ApexGrid extends EventEmitterBase {
1114
1150
  }
1115
1151
  }
1116
1152
  bodyFocusHandler(event) {
1117
- if (this.scrollContainer.isSameNode(event.target)) {
1118
- this.stateController.navigation.focusActiveCell();
1153
+ const navigation = this.stateController.navigation;
1154
+ navigation.focusEntered(event, this.ownsEvent(event));
1155
+ if (this.scrollContainer.isSameNode(event.target) &&
1156
+ navigation.forwardsBodyFocus) {
1157
+ navigation.focusActiveCell();
1119
1158
  }
1120
1159
  }
1160
+ bodyFocusOutHandler(event) {
1161
+ this.stateController.navigation.focusLeft(event, this.ownsEvent(event));
1162
+ }
1121
1163
  bodyPointerHandler(event) {
1122
1164
  if (this.stateController.modules.size === 0)
1123
1165
  return;
@@ -1143,6 +1185,7 @@ export class ApexGrid extends EventEmitterBase {
1143
1185
  return nothing;
1144
1186
  return html `
1145
1187
  <apex-grid-group-header-row
1188
+ ?data-visually-hidden=${!this.showHeader}
1146
1189
  style=${styleMap(this.DOM.columnSizes)}
1147
1190
  .columns=${this.DOM.displayColumns}
1148
1191
  .pinOffsets=${this.DOM.pinOffsets}
@@ -1153,6 +1196,7 @@ export class ApexGrid extends EventEmitterBase {
1153
1196
  renderHeaderRow() {
1154
1197
  return html `
1155
1198
  <apex-grid-header-row
1199
+ ?data-visually-hidden=${!this.showHeader}
1156
1200
  style=${styleMap(this.DOM.columnSizes)}
1157
1201
  .columns=${this.DOM.displayColumns}
1158
1202
  .pinOffsets=${this.DOM.pinOffsets}
@@ -1163,11 +1207,14 @@ export class ApexGrid extends EventEmitterBase {
1163
1207
  renderBody() {
1164
1208
  return html `
1165
1209
  <apex-virtualizer
1210
+ role="rowgroup"
1166
1211
  .items=${this.pageItems}
1167
1212
  .renderItem=${this.DOM.rowRenderer}
1213
+ .rowMode=${this.rowRecycling ? 'slot' : 'item'}
1168
1214
  @click=${this.bodyClickHandler}
1169
1215
  @keydown=${this.bodyKeydownHandler}
1170
1216
  @focusin=${this.bodyFocusHandler}
1217
+ @focusout=${this.bodyFocusOutHandler}
1171
1218
  @rangeChanged=${this.bodyRangeChanged}
1172
1219
  @pointerdown=${this.bodyPointerHandler}
1173
1220
  @pointermove=${this.bodyPointerHandler}
@@ -1175,16 +1222,13 @@ export class ApexGrid extends EventEmitterBase {
1175
1222
  ></apex-virtualizer>
1176
1223
  `;
1177
1224
  }
1178
- get headerRowCount() {
1179
- return this.columnGroupDepth + 1 + (this.columns.some((column) => column.filter) ? 1 : 0);
1180
- }
1181
1225
  renderPinnedTop() {
1182
1226
  const rowPin = this.stateController.rowPin;
1183
1227
  const rows = rowPin.pinnedRows.top;
1184
1228
  if (rows.length === 0)
1185
1229
  return nothing;
1186
1230
  return html `<div part="pinned-rows pinned-top">
1187
- ${rows.map((data, i) => this.DOM.pinnedRowRenderer(data, i, this.headerRowCount))}
1231
+ ${rows.map((data, i) => this.DOM.pinnedRowRenderer(data, i, this.DOM.headerRowCount))}
1188
1232
  </div>`;
1189
1233
  }
1190
1234
  renderPinnedBottom() {
@@ -1192,13 +1236,13 @@ export class ApexGrid extends EventEmitterBase {
1192
1236
  const rows = rowPin.pinnedRows.bottom;
1193
1237
  if (rows.length === 0)
1194
1238
  return nothing;
1195
- const offset = this.headerRowCount + rowPin.pinnedRows.top.length + this.pageItems.length;
1239
+ const offset = this.DOM.headerRowCount + rowPin.pinnedRows.top.length + this.pageItems.length;
1196
1240
  return html `<div part="pinned-rows pinned-bottom">
1197
1241
  ${rows.map((data, i) => this.DOM.pinnedRowRenderer(data, i, offset))}
1198
1242
  </div>`;
1199
1243
  }
1200
1244
  renderFilterRow() {
1201
- return this.columns.some((column) => column.filter)
1245
+ return this.showHeader && this.columns.some((column) => column.filter)
1202
1246
  ? html `<apex-filter-row></apex-filter-row>`
1203
1247
  : nothing;
1204
1248
  }
@@ -1207,22 +1251,27 @@ export class ApexGrid extends EventEmitterBase {
1207
1251
  return nothing;
1208
1252
  }
1209
1253
  return html `<apex-grid-toolbar
1254
+ part="toolbar-host"
1255
+ exportparts="toolbar,toolbar-search,search-field,search-icon,search-input,toolbar-actions,toolbar-action,export,export-trigger,export-icon,export-caret,export-menu,export-menu-item"
1210
1256
  .value=${this.quickFilter}
1211
1257
  .showQuickFilter=${this.showQuickFilter}
1212
1258
  .showExport=${this.showExport}
1213
1259
  @apex-quick-filter=${(event) => {
1214
1260
  event.stopPropagation();
1215
1261
  this.setQuickFilter(event.detail);
1262
+ if (this.quickFilter !== event.detail)
1263
+ event.preventDefault();
1216
1264
  }}
1217
1265
  ></apex-grid-toolbar>`;
1218
1266
  }
1219
1267
  renderPaginator() {
1220
1268
  if (!this.stateController.pagination.enabled)
1221
1269
  return nothing;
1222
- const options = this.pagination?.pageSizeOptions && this.pagination.pageSizeOptions.length > 0
1223
- ? this.pagination.pageSizeOptions
1224
- : [10, 25, 50, 100];
1225
- return html `<apex-grid-paginator .pageSizeOptions=${options}></apex-grid-paginator>`;
1270
+ return html `<apex-grid-paginator
1271
+ part="paginator-host"
1272
+ exportparts="paginator,paginator-size,paginator-info,paginator-controls,paginator-page,paginator-button,paginator-first,paginator-prev,paginator-next,paginator-last"
1273
+ .pageSizeOptions=${this.pagination?.pageSizeOptions ?? DEFAULT_PAGINATION.pageSizeOptions}
1274
+ ></apex-grid-paginator>`;
1226
1275
  }
1227
1276
  renderLiveRegion() {
1228
1277
  return html `<div
@@ -1235,6 +1284,22 @@ export class ApexGrid extends EventEmitterBase {
1235
1284
  ${this.stateController.announcement}
1236
1285
  </div>`;
1237
1286
  }
1287
+ renderColumnDragGhost() {
1288
+ const state = this.stateController.reordering.state;
1289
+ if (!state)
1290
+ return nothing;
1291
+ return html `<div
1292
+ part="drag-ghost"
1293
+ style=${styleMap({
1294
+ left: `${state.ghostX}px`,
1295
+ top: `${state.ghostY}px`,
1296
+ width: `${state.ghostWidth}px`,
1297
+ height: `${state.ghostHeight}px`,
1298
+ })}
1299
+ >
1300
+ ${state.label}
1301
+ </div>`;
1302
+ }
1238
1303
  renderRowDragGhost() {
1239
1304
  const ghost = this.stateController.rowReorder.ghost;
1240
1305
  if (!ghost)
@@ -1264,18 +1329,45 @@ export class ApexGrid extends EventEmitterBase {
1264
1329
  >`)}
1265
1330
  </div>`;
1266
1331
  }
1332
+ #refs(attr) {
1333
+ const root = this.getRootNode();
1334
+ const found = (this.getAttribute(attr) ?? '')
1335
+ .split(/\s+/)
1336
+ .flatMap((id) => (id && root.getElementById?.(id)) || []);
1337
+ return found.length ? found : null;
1338
+ }
1339
+ renderTable() {
1340
+ const state = this.stateController;
1341
+ const { top, bottom } = state.rowPin.pinnedRows;
1342
+ const selection = state.selection;
1343
+ const labelledBy = this.#refs('aria-labelledby');
1344
+ const describedBy = this.#refs('aria-describedby');
1345
+ const copy = (refs) => !('ariaLabelledByElements' in Element.prototype) &&
1346
+ refs?.map((el) => el.textContent?.trim()).join(' ');
1347
+ return html `<div
1348
+ part="table"
1349
+ role=${state.hierarchical ? 'treegrid' : 'grid'}
1350
+ aria-rowcount=${this.DOM.headerRowCount + top.length + this.pageItems.length + bottom.length}
1351
+ aria-colcount=${state.colCount}
1352
+ aria-multiselectable=${selection.enabled && selection.mode === 'multiple' ? 'true' : nothing}
1353
+ aria-label=${copy(labelledBy) || this.getAttribute('aria-label') || this.localize('grid.label')}
1354
+ aria-description=${copy(describedBy) || nothing}
1355
+ .ariaLabelledByElements=${labelledBy}
1356
+ .ariaDescribedByElements=${describedBy}
1357
+ >
1358
+ ${this.renderGroupHeaderRow()} ${this.renderHeaderRow()} ${this.renderPinnedTop()}
1359
+ ${this.renderBody()} ${this.renderPinnedBottom()}
1360
+ </div>`;
1361
+ }
1267
1362
  render() {
1268
1363
  return html `
1269
1364
  ${this.stateController.resizing.renderIndicator()}
1270
1365
  ${this.renderToolbar()}
1271
- ${this.renderGroupHeaderRow()}
1272
- ${this.renderHeaderRow()}
1366
+ ${this.renderTable()}
1273
1367
  ${this.renderFilterRow()}
1274
- ${this.renderPinnedTop()}
1275
- ${this.renderBody()}
1276
- ${this.renderPinnedBottom()}
1277
1368
  ${this.renderPaginator()}
1278
1369
  ${this.renderLiveRegion()}
1370
+ ${this.renderColumnDragGhost()}
1279
1371
  ${this.renderRowDragGhost()}
1280
1372
  `;
1281
1373
  }
@@ -1283,6 +1375,7 @@ export class ApexGrid extends EventEmitterBase {
1283
1375
  this.stateController.setAnnouncement(message);
1284
1376
  }
1285
1377
  }
1378
+ _a = ApexGrid;
1286
1379
  __decorate([
1287
1380
  query(ApexVirtualizer.tagName)
1288
1381
  ], ApexGrid.prototype, "scrollContainer", void 0);
@@ -1343,6 +1436,9 @@ __decorate([
1343
1436
  __decorate([
1344
1437
  property({ type: Boolean, attribute: 'column-separator', reflect: true })
1345
1438
  ], ApexGrid.prototype, "columnSeparator", void 0);
1439
+ __decorate([
1440
+ property({ attribute: 'row-recycling', converter: (value) => value !== 'false' })
1441
+ ], ApexGrid.prototype, "rowRecycling", null);
1346
1442
  __decorate([
1347
1443
  property({ attribute: false })
1348
1444
  ], ApexGrid.prototype, "editing", void 0);
@@ -1364,6 +1460,9 @@ __decorate([
1364
1460
  __decorate([
1365
1461
  property({ attribute: false })
1366
1462
  ], ApexGrid.prototype, "columnMenu", void 0);
1463
+ __decorate([
1464
+ property({ attribute: 'show-header', converter: (value) => value !== 'false' })
1465
+ ], ApexGrid.prototype, "showHeader", void 0);
1367
1466
  __decorate([
1368
1467
  property({ attribute: false })
1369
1468
  ], ApexGrid.prototype, "columnGroups", void 0);
@@ -1403,4 +1502,7 @@ __decorate([
1403
1502
  __decorate([
1404
1503
  eventOptions({ capture: true })
1405
1504
  ], ApexGrid.prototype, "bodyClickHandler", null);
1505
+ __decorate([
1506
+ eventOptions({ capture: true })
1507
+ ], ApexGrid.prototype, "bodyFocusOutHandler", null);
1406
1508
  //# sourceMappingURL=grid.js.map