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
@@ -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,9 +12,11 @@ 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';
19
+ import { connectDesignSystem, disconnectDesignSystem } from '../internal/design-system.js';
17
20
  import { adoptGridDocumentStyles } from '../internal/document-styles.js';
18
21
  import { buildCSV, downloadBlob, } from '../internal/export.js';
19
22
  import { EventEmitterBase } from '../internal/mixins/event-emitter.js';
@@ -31,7 +34,7 @@ import ApexGridHeaderRow from './header-row.js';
31
34
  import ApexGridPaginator from './paginator.js';
32
35
  import ApexGridRow from './row.js';
33
36
  import ApexGridToolbar from './toolbar.js';
34
- import ApexVirtualizer from './virtualizer.js';
37
+ import ApexVirtualizer, { quietResizeObserverLoopNotice } from './virtualizer.js';
35
38
  const SORT_DIRECTIONS = ['ascending', 'descending', 'none'];
36
39
  const VIEW_SHAPING_SLICES = new Set([
37
40
  'columns',
@@ -45,7 +48,7 @@ const VIEW_SHAPING_PROPERTIES = new Map([
45
48
  ['quickFilter', null],
46
49
  ['pagination', ['enabled', 'mode', 'pageSize', 'totalItems']],
47
50
  ['tree', ['enabled', 'getDataPath', 'defaultExpanded']],
48
- ['dataPipelineConfiguration', ['sort', 'filter', 'pagination', 'quickFilter']],
51
+ ['dataPipelineConfiguration', ['sort', 'filter', 'quickFilter']],
49
52
  ]);
50
53
  function viewShapeChanged(fields, before, after) {
51
54
  if (Object.is(before, after))
@@ -56,6 +59,13 @@ function viewShapeChanged(fields, before, after) {
56
59
  const b = (after ?? {});
57
60
  return fields.some((field) => !Object.is(a[field], b[field]));
58
61
  }
62
+ function keyChanged(key, previous) {
63
+ return key.some((value, i) => value !== previous[i]);
64
+ }
65
+ const OFF_SWITCH = {
66
+ fromAttribute: (value) => value !== 'off',
67
+ toAttribute: (value) => (value ? null : 'off'),
68
+ };
59
69
  function warnDropped(message) {
60
70
  console.warn(`[apex-grid] ${message}`);
61
71
  }
@@ -83,23 +93,33 @@ export class ApexGrid extends EventEmitterBase {
83
93
  this.showExport = false;
84
94
  this.columnReordering = false;
85
95
  this.columnSeparator = true;
96
+ this.#rowRecycling = _a.defaultRowRecycling;
86
97
  this.coordinateHints = false;
87
98
  this.columnMenu = true;
99
+ this.showHeader = true;
100
+ this.designSystem = true;
101
+ this.tokens = true;
102
+ this.#bodyKey = [];
103
+ this.#bodyRows = [];
104
+ this.#pageKey = [];
105
+ this.#pageItems = [];
88
106
  this.#viewChangePending = false;
89
107
  this.#shapingPending = false;
90
108
  this.#pipelineRun = 0;
91
109
  this.#pipelineSettled = Promise.resolve();
92
110
  this.#settlePipeline = null;
93
- this.#autoAriaLabel = null;
111
+ this.#pinKey = [];
94
112
  this.#stateChangedListeners = new Map();
95
113
  this.#lastStateJson = null;
114
+ this.#labelObserver = new MutationObserver(() => this.requestUpdate());
96
115
  }
97
116
  static get tagName() {
98
117
  return GRID_TAG;
99
118
  }
100
119
  static { this.styles = gridStyles; }
120
+ static { this.defaultRowRecycling = globalThis.__apexRowKeying !== 'item'; }
101
121
  static register() {
102
- registerComponent(ApexGrid, ApexVirtualizer, ApexGridRow, ApexGridGroupHeaderRow, ApexGridHeaderRow, ApexFilterRow, ApexGridPaginator, ApexGridToolbar);
122
+ registerComponent(_a, ApexVirtualizer, ApexGridRow, ApexGridGroupHeaderRow, ApexGridHeaderRow, ApexFilterRow, ApexGridPaginator, ApexGridToolbar);
103
123
  }
104
124
  createStateController() {
105
125
  return new StateController(this);
@@ -125,6 +145,13 @@ export class ApexGrid extends EventEmitterBase {
125
145
  localize(key, params, fallback) {
126
146
  return resolveLocaleText(this.localeText, key, params, fallback);
127
147
  }
148
+ get rowRecycling() {
149
+ return this.#rowRecycling;
150
+ }
151
+ set rowRecycling(value) {
152
+ this.#rowRecycling = value ?? _a.defaultRowRecycling;
153
+ }
154
+ #rowRecycling;
128
155
  get selectedRows() {
129
156
  return this.stateController.selection.selectedRows();
130
157
  }
@@ -254,26 +281,44 @@ export class ApexGrid extends EventEmitterBase {
254
281
  return getDisplayColumns(this.columns);
255
282
  }
256
283
  get totalItems() {
257
- if (this.pagination?.mode === 'remote') {
258
- return Math.max(0, this.pagination?.totalItems ?? 0);
284
+ return this.stateController.pagination.totalItems;
285
+ }
286
+ get bodyRows() {
287
+ const { rowPin, dataVersion } = this.stateController;
288
+ const key = [this.dataState, dataVersion, rowPin.version, rowPin.enabled];
289
+ if (keyChanged(key, this.#bodyKey)) {
290
+ this.#bodyKey = key;
291
+ this.#bodyRows = rowPin.hasPinnedRows
292
+ ? this.dataState.filter((row) => !rowPin.isPinned(row))
293
+ : this.dataState;
259
294
  }
260
- return this.dataState.length;
295
+ return this.#bodyRows;
261
296
  }
297
+ #bodyKey;
298
+ #bodyRows;
262
299
  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);
300
+ const { pagination, dataVersion } = this.stateController;
301
+ const key = [
302
+ this.bodyRows,
303
+ dataVersion,
304
+ pagination.enabled,
305
+ this.pagination?.mode,
306
+ pagination.page,
307
+ pagination.pageSize,
308
+ ];
309
+ if (keyChanged(key, this.#pageKey)) {
310
+ this.#pageKey = key;
311
+ const base = this.bodyRows;
312
+ const { page, pageSize } = pagination;
313
+ this.#pageItems =
314
+ !pagination.enabled || this.pagination?.mode === 'remote' || !pageSize
315
+ ? base
316
+ : base.slice(page * pageSize, (page + 1) * pageSize);
317
+ }
318
+ return this.#pageItems;
276
319
  }
320
+ #pageKey;
321
+ #pageItems;
277
322
  get page() {
278
323
  return this.stateController.pagination.page;
279
324
  }
@@ -450,35 +495,23 @@ export class ApexGrid extends EventEmitterBase {
450
495
  if (entries.length)
451
496
  this.filter([...entries]);
452
497
  }
498
+ willUpdate(changed) {
499
+ super.willUpdate(changed);
500
+ const { rowPin, pagination } = this.stateController;
501
+ const key = [rowPin.version, rowPin.enabled];
502
+ if (keyChanged(key, this.#pinKey)) {
503
+ this.#pinKey = key;
504
+ if (!changed.has(PIPELINE) && !this.#viewStale)
505
+ pagination.reclamp();
506
+ }
507
+ }
508
+ #pinKey;
453
509
  updated() {
454
510
  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
511
  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
- }
512
+ this.stateController.navigation.reconcileFocus();
479
513
  this.#emitStateChangedIfNeeded();
480
514
  }
481
- #autoAriaLabel;
482
515
  #stateChangedListeners;
483
516
  #lastStateJson;
484
517
  addEventListener(type, listener, options) {
@@ -545,7 +578,17 @@ export class ApexGrid extends EventEmitterBase {
545
578
  connectedCallback() {
546
579
  super.connectedCallback();
547
580
  adoptGridDocumentStyles(this);
581
+ connectDesignSystem(this);
582
+ quietResizeObserverLoopNotice();
583
+ this.#labelObserver.observe(this, {
584
+ attributeFilter: ['aria-label', 'aria-labelledby', 'aria-describedby'],
585
+ });
548
586
  }
587
+ disconnectedCallback() {
588
+ super.disconnectedCallback();
589
+ disconnectDesignSystem(this);
590
+ }
591
+ #labelObserver;
549
592
  firstUpdated() {
550
593
  if (typeof getComputedStyle === 'function' && getComputedStyle(this).display !== 'grid') {
551
594
  console.warn('[apex-grid] Host `display` has been overridden. The grid requires ' +
@@ -745,7 +788,11 @@ export class ApexGrid extends EventEmitterBase {
745
788
  const selection = asArray(state.selection, 'selection');
746
789
  if (selection) {
747
790
  const ctrl = this.stateController.selection;
748
- const rows = resolveCounted(selection, 'selection');
791
+ const resolved = resolveCounted(selection, 'selection');
792
+ const rows = ctrl.selectable(resolved);
793
+ if (rows.length < resolved.length) {
794
+ warn(`selection: ${resolved.length - rows.length} row(s) are not selectable; skipped`);
795
+ }
749
796
  const expected = ctrl.mode === 'single' ? rows.slice(0, 1) : rows;
750
797
  if (this.#replaceRows('selection', ctrl.enabled, expected, warn, () => {
751
798
  void ctrl.replaceSelection(expected);
@@ -1053,7 +1100,7 @@ export class ApexGrid extends EventEmitterBase {
1053
1100
  for (const node of event.composedPath()) {
1054
1101
  if (node === this || node === this.scrollContainer)
1055
1102
  return true;
1056
- if (node instanceof ApexGrid || node instanceof ApexVirtualizer)
1103
+ if (node instanceof _a || node instanceof ApexVirtualizer)
1057
1104
  return false;
1058
1105
  }
1059
1106
  return false;
@@ -1074,6 +1121,7 @@ export class ApexGrid extends EventEmitterBase {
1074
1121
  (focused.index < first || focused.index > last)) {
1075
1122
  this.scrollContainer.focus({ preventScroll: true });
1076
1123
  }
1124
+ this.stateController.navigation.reconcileFocus();
1077
1125
  }
1078
1126
  #ownCell(event) {
1079
1127
  if (!this.ownsEvent(event))
@@ -1114,10 +1162,16 @@ export class ApexGrid extends EventEmitterBase {
1114
1162
  }
1115
1163
  }
1116
1164
  bodyFocusHandler(event) {
1117
- if (this.scrollContainer.isSameNode(event.target)) {
1118
- this.stateController.navigation.focusActiveCell();
1165
+ const navigation = this.stateController.navigation;
1166
+ navigation.focusEntered(event, this.ownsEvent(event));
1167
+ if (this.scrollContainer.isSameNode(event.target) &&
1168
+ navigation.forwardsBodyFocus) {
1169
+ navigation.focusActiveCell();
1119
1170
  }
1120
1171
  }
1172
+ bodyFocusOutHandler(event) {
1173
+ this.stateController.navigation.focusLeft(event, this.ownsEvent(event));
1174
+ }
1121
1175
  bodyPointerHandler(event) {
1122
1176
  if (this.stateController.modules.size === 0)
1123
1177
  return;
@@ -1143,6 +1197,7 @@ export class ApexGrid extends EventEmitterBase {
1143
1197
  return nothing;
1144
1198
  return html `
1145
1199
  <apex-grid-group-header-row
1200
+ ?data-visually-hidden=${!this.showHeader}
1146
1201
  style=${styleMap(this.DOM.columnSizes)}
1147
1202
  .columns=${this.DOM.displayColumns}
1148
1203
  .pinOffsets=${this.DOM.pinOffsets}
@@ -1153,6 +1208,7 @@ export class ApexGrid extends EventEmitterBase {
1153
1208
  renderHeaderRow() {
1154
1209
  return html `
1155
1210
  <apex-grid-header-row
1211
+ ?data-visually-hidden=${!this.showHeader}
1156
1212
  style=${styleMap(this.DOM.columnSizes)}
1157
1213
  .columns=${this.DOM.displayColumns}
1158
1214
  .pinOffsets=${this.DOM.pinOffsets}
@@ -1163,11 +1219,14 @@ export class ApexGrid extends EventEmitterBase {
1163
1219
  renderBody() {
1164
1220
  return html `
1165
1221
  <apex-virtualizer
1222
+ role="rowgroup"
1166
1223
  .items=${this.pageItems}
1167
1224
  .renderItem=${this.DOM.rowRenderer}
1225
+ .rowMode=${this.rowRecycling ? 'slot' : 'item'}
1168
1226
  @click=${this.bodyClickHandler}
1169
1227
  @keydown=${this.bodyKeydownHandler}
1170
1228
  @focusin=${this.bodyFocusHandler}
1229
+ @focusout=${this.bodyFocusOutHandler}
1171
1230
  @rangeChanged=${this.bodyRangeChanged}
1172
1231
  @pointerdown=${this.bodyPointerHandler}
1173
1232
  @pointermove=${this.bodyPointerHandler}
@@ -1175,16 +1234,13 @@ export class ApexGrid extends EventEmitterBase {
1175
1234
  ></apex-virtualizer>
1176
1235
  `;
1177
1236
  }
1178
- get headerRowCount() {
1179
- return this.columnGroupDepth + 1 + (this.columns.some((column) => column.filter) ? 1 : 0);
1180
- }
1181
1237
  renderPinnedTop() {
1182
1238
  const rowPin = this.stateController.rowPin;
1183
1239
  const rows = rowPin.pinnedRows.top;
1184
1240
  if (rows.length === 0)
1185
1241
  return nothing;
1186
1242
  return html `<div part="pinned-rows pinned-top">
1187
- ${rows.map((data, i) => this.DOM.pinnedRowRenderer(data, i, this.headerRowCount))}
1243
+ ${rows.map((data, i) => this.DOM.pinnedRowRenderer(data, i, this.DOM.headerRowCount))}
1188
1244
  </div>`;
1189
1245
  }
1190
1246
  renderPinnedBottom() {
@@ -1192,13 +1248,13 @@ export class ApexGrid extends EventEmitterBase {
1192
1248
  const rows = rowPin.pinnedRows.bottom;
1193
1249
  if (rows.length === 0)
1194
1250
  return nothing;
1195
- const offset = this.headerRowCount + rowPin.pinnedRows.top.length + this.pageItems.length;
1251
+ const offset = this.DOM.headerRowCount + rowPin.pinnedRows.top.length + this.pageItems.length;
1196
1252
  return html `<div part="pinned-rows pinned-bottom">
1197
1253
  ${rows.map((data, i) => this.DOM.pinnedRowRenderer(data, i, offset))}
1198
1254
  </div>`;
1199
1255
  }
1200
1256
  renderFilterRow() {
1201
- return this.columns.some((column) => column.filter)
1257
+ return this.showHeader && this.columns.some((column) => column.filter)
1202
1258
  ? html `<apex-filter-row></apex-filter-row>`
1203
1259
  : nothing;
1204
1260
  }
@@ -1207,22 +1263,27 @@ export class ApexGrid extends EventEmitterBase {
1207
1263
  return nothing;
1208
1264
  }
1209
1265
  return html `<apex-grid-toolbar
1266
+ part="toolbar-host"
1267
+ 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
1268
  .value=${this.quickFilter}
1211
1269
  .showQuickFilter=${this.showQuickFilter}
1212
1270
  .showExport=${this.showExport}
1213
1271
  @apex-quick-filter=${(event) => {
1214
1272
  event.stopPropagation();
1215
1273
  this.setQuickFilter(event.detail);
1274
+ if (this.quickFilter !== event.detail)
1275
+ event.preventDefault();
1216
1276
  }}
1217
1277
  ></apex-grid-toolbar>`;
1218
1278
  }
1219
1279
  renderPaginator() {
1220
1280
  if (!this.stateController.pagination.enabled)
1221
1281
  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>`;
1282
+ return html `<apex-grid-paginator
1283
+ part="paginator-host"
1284
+ exportparts="paginator,paginator-size,paginator-info,paginator-controls,paginator-page,paginator-button,paginator-first,paginator-prev,paginator-next,paginator-last"
1285
+ .pageSizeOptions=${this.pagination?.pageSizeOptions ?? DEFAULT_PAGINATION.pageSizeOptions}
1286
+ ></apex-grid-paginator>`;
1226
1287
  }
1227
1288
  renderLiveRegion() {
1228
1289
  return html `<div
@@ -1235,6 +1296,22 @@ export class ApexGrid extends EventEmitterBase {
1235
1296
  ${this.stateController.announcement}
1236
1297
  </div>`;
1237
1298
  }
1299
+ renderColumnDragGhost() {
1300
+ const state = this.stateController.reordering.state;
1301
+ if (!state)
1302
+ return nothing;
1303
+ return html `<div
1304
+ part="drag-ghost"
1305
+ style=${styleMap({
1306
+ left: `${state.ghostX}px`,
1307
+ top: `${state.ghostY}px`,
1308
+ width: `${state.ghostWidth}px`,
1309
+ height: `${state.ghostHeight}px`,
1310
+ })}
1311
+ >
1312
+ ${state.label}
1313
+ </div>`;
1314
+ }
1238
1315
  renderRowDragGhost() {
1239
1316
  const ghost = this.stateController.rowReorder.ghost;
1240
1317
  if (!ghost)
@@ -1264,18 +1341,45 @@ export class ApexGrid extends EventEmitterBase {
1264
1341
  >`)}
1265
1342
  </div>`;
1266
1343
  }
1344
+ #refs(attr) {
1345
+ const root = this.getRootNode();
1346
+ const found = (this.getAttribute(attr) ?? '')
1347
+ .split(/\s+/)
1348
+ .flatMap((id) => (id && root.getElementById?.(id)) || []);
1349
+ return found.length ? found : null;
1350
+ }
1351
+ renderTable() {
1352
+ const state = this.stateController;
1353
+ const { top, bottom } = state.rowPin.pinnedRows;
1354
+ const selection = state.selection;
1355
+ const labelledBy = this.#refs('aria-labelledby');
1356
+ const describedBy = this.#refs('aria-describedby');
1357
+ const copy = (refs) => !('ariaLabelledByElements' in Element.prototype) &&
1358
+ refs?.map((el) => el.textContent?.trim()).join(' ');
1359
+ return html `<div
1360
+ part="table"
1361
+ role=${state.hierarchical ? 'treegrid' : 'grid'}
1362
+ aria-rowcount=${this.DOM.headerRowCount + top.length + this.pageItems.length + bottom.length}
1363
+ aria-colcount=${state.colCount}
1364
+ aria-multiselectable=${selection.enabled && selection.mode === 'multiple' ? 'true' : nothing}
1365
+ aria-label=${copy(labelledBy) || this.getAttribute('aria-label') || this.localize('grid.label')}
1366
+ aria-description=${copy(describedBy) || nothing}
1367
+ .ariaLabelledByElements=${labelledBy}
1368
+ .ariaDescribedByElements=${describedBy}
1369
+ >
1370
+ ${this.renderGroupHeaderRow()} ${this.renderHeaderRow()} ${this.renderPinnedTop()}
1371
+ ${this.renderBody()} ${this.renderPinnedBottom()}
1372
+ </div>`;
1373
+ }
1267
1374
  render() {
1268
1375
  return html `
1269
1376
  ${this.stateController.resizing.renderIndicator()}
1270
1377
  ${this.renderToolbar()}
1271
- ${this.renderGroupHeaderRow()}
1272
- ${this.renderHeaderRow()}
1378
+ ${this.renderTable()}
1273
1379
  ${this.renderFilterRow()}
1274
- ${this.renderPinnedTop()}
1275
- ${this.renderBody()}
1276
- ${this.renderPinnedBottom()}
1277
1380
  ${this.renderPaginator()}
1278
1381
  ${this.renderLiveRegion()}
1382
+ ${this.renderColumnDragGhost()}
1279
1383
  ${this.renderRowDragGhost()}
1280
1384
  `;
1281
1385
  }
@@ -1283,6 +1387,7 @@ export class ApexGrid extends EventEmitterBase {
1283
1387
  this.stateController.setAnnouncement(message);
1284
1388
  }
1285
1389
  }
1390
+ _a = ApexGrid;
1286
1391
  __decorate([
1287
1392
  query(ApexVirtualizer.tagName)
1288
1393
  ], ApexGrid.prototype, "scrollContainer", void 0);
@@ -1343,6 +1448,9 @@ __decorate([
1343
1448
  __decorate([
1344
1449
  property({ type: Boolean, attribute: 'column-separator', reflect: true })
1345
1450
  ], ApexGrid.prototype, "columnSeparator", void 0);
1451
+ __decorate([
1452
+ property({ attribute: 'row-recycling', converter: (value) => value !== 'false' })
1453
+ ], ApexGrid.prototype, "rowRecycling", null);
1346
1454
  __decorate([
1347
1455
  property({ attribute: false })
1348
1456
  ], ApexGrid.prototype, "editing", void 0);
@@ -1364,6 +1472,15 @@ __decorate([
1364
1472
  __decorate([
1365
1473
  property({ attribute: false })
1366
1474
  ], ApexGrid.prototype, "columnMenu", void 0);
1475
+ __decorate([
1476
+ property({ attribute: 'show-header', converter: (value) => value !== 'false' })
1477
+ ], ApexGrid.prototype, "showHeader", void 0);
1478
+ __decorate([
1479
+ property({ attribute: 'design-system', reflect: true, converter: OFF_SWITCH })
1480
+ ], ApexGrid.prototype, "designSystem", void 0);
1481
+ __decorate([
1482
+ property({ attribute: 'tokens', reflect: true, converter: OFF_SWITCH })
1483
+ ], ApexGrid.prototype, "tokens", void 0);
1367
1484
  __decorate([
1368
1485
  property({ attribute: false })
1369
1486
  ], ApexGrid.prototype, "columnGroups", void 0);
@@ -1403,4 +1520,7 @@ __decorate([
1403
1520
  __decorate([
1404
1521
  eventOptions({ capture: true })
1405
1522
  ], ApexGrid.prototype, "bodyClickHandler", null);
1523
+ __decorate([
1524
+ eventOptions({ capture: true })
1525
+ ], ApexGrid.prototype, "bodyFocusOutHandler", null);
1406
1526
  //# sourceMappingURL=grid.js.map