apex-grid 3.2.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/README.md +229 -52
  3. package/components/cell.d.ts +16 -3
  4. package/components/cell.js +78 -8
  5. package/components/cell.js.map +1 -1
  6. package/components/filter-row.d.ts +3 -6
  7. package/components/filter-row.js +144 -115
  8. package/components/filter-row.js.map +1 -1
  9. package/components/grid.d.ts +421 -77
  10. package/components/grid.js +432 -13
  11. package/components/grid.js.map +1 -1
  12. package/components/group-header-row.d.ts +34 -0
  13. package/components/group-header-row.js +125 -0
  14. package/components/group-header-row.js.map +1 -0
  15. package/components/header-row.d.ts +13 -2
  16. package/components/header-row.js +33 -18
  17. package/components/header-row.js.map +1 -1
  18. package/components/header.d.ts +11 -0
  19. package/components/header.js +209 -8
  20. package/components/header.js.map +1 -1
  21. package/components/paginator.d.ts +6 -1
  22. package/components/paginator.js +17 -11
  23. package/components/paginator.js.map +1 -1
  24. package/components/row.d.ts +28 -0
  25. package/components/row.js +100 -3
  26. package/components/row.js.map +1 -1
  27. package/components/toolbar.d.ts +8 -1
  28. package/components/toolbar.js +25 -7
  29. package/components/toolbar.js.map +1 -1
  30. package/controllers/data-operation.js +1 -0
  31. package/controllers/data-operation.js.map +1 -1
  32. package/controllers/dom.d.ts +24 -6
  33. package/controllers/dom.js +62 -5
  34. package/controllers/dom.js.map +1 -1
  35. package/controllers/editing.d.ts +68 -1
  36. package/controllers/editing.js +129 -44
  37. package/controllers/editing.js.map +1 -1
  38. package/controllers/expansion.js +4 -4
  39. package/controllers/expansion.js.map +1 -1
  40. package/controllers/filter.d.ts +1 -1
  41. package/controllers/filter.js +27 -5
  42. package/controllers/filter.js.map +1 -1
  43. package/controllers/history.d.ts +86 -0
  44. package/controllers/history.js +125 -0
  45. package/controllers/history.js.map +1 -0
  46. package/controllers/navigation.d.ts +49 -2
  47. package/controllers/navigation.js +145 -3
  48. package/controllers/navigation.js.map +1 -1
  49. package/controllers/pagination.js +1 -1
  50. package/controllers/pagination.js.map +1 -1
  51. package/controllers/reorder.js +3 -1
  52. package/controllers/reorder.js.map +1 -1
  53. package/controllers/row-pin.d.ts +59 -0
  54. package/controllers/row-pin.js +75 -0
  55. package/controllers/row-pin.js.map +1 -0
  56. package/controllers/row-reorder.d.ts +161 -0
  57. package/controllers/row-reorder.js +332 -0
  58. package/controllers/row-reorder.js.map +1 -0
  59. package/controllers/selection.js +3 -3
  60. package/controllers/selection.js.map +1 -1
  61. package/controllers/sort.js +13 -3
  62. package/controllers/sort.js.map +1 -1
  63. package/controllers/state.d.ts +33 -0
  64. package/controllers/state.js +37 -2
  65. package/controllers/state.js.map +1 -1
  66. package/controllers/tree.d.ts +8 -0
  67. package/controllers/tree.js +0 -0
  68. package/controllers/tree.js.map +1 -1
  69. package/custom-elements.json +4667 -926
  70. package/docs/assets/hierarchy.js +1 -1
  71. package/docs/assets/highlight.css +28 -0
  72. package/docs/assets/navigation.js +1 -1
  73. package/docs/assets/search.js +1 -1
  74. package/docs/functions/custom.html +3 -0
  75. package/docs/functions/interpolate.html +4 -0
  76. package/docs/functions/localize.html +8 -0
  77. package/docs/functions/max.html +3 -0
  78. package/docs/functions/min.html +3 -0
  79. package/docs/functions/pattern.html +3 -0
  80. package/docs/functions/required.html +3 -0
  81. package/docs/hierarchy.html +1 -1
  82. package/docs/index.html +245 -54
  83. package/docs/interfaces/ApexCellValidationFailedEvent.html +13 -0
  84. package/docs/interfaces/ApexCellValueChangedEvent.html +1 -1
  85. package/docs/interfaces/ApexCellValueChangingEvent.html +2 -2
  86. package/docs/interfaces/ApexColumnGroupContext.html +6 -0
  87. package/docs/interfaces/ApexColumnMovedEvent.html +2 -2
  88. package/docs/interfaces/ApexColumnMovingEvent.html +1 -1
  89. package/docs/interfaces/ApexDetailContext.html +2 -2
  90. package/docs/interfaces/ApexGridEventMap.html +37 -9
  91. package/docs/interfaces/ApexHistoryChangedEvent.html +6 -0
  92. package/docs/interfaces/ApexPageChangedEvent.html +1 -1
  93. package/docs/interfaces/ApexRowMovingEvent.html +9 -0
  94. package/docs/interfaces/ApexRowPinningEvent.html +8 -0
  95. package/docs/interfaces/ApexStateChangedEvent.html +4 -0
  96. package/docs/interfaces/BaseApexCellContext.html +1 -1
  97. package/docs/interfaces/BaseApexEditorContext.html +1 -1
  98. package/docs/interfaces/BaseColumnConfiguration.html +42 -17
  99. package/docs/interfaces/CSVExportOptions.html +2 -2
  100. package/docs/interfaces/ColumnGroupConfiguration.html +12 -0
  101. package/docs/interfaces/ColumnLayoutState.html +2 -0
  102. package/docs/interfaces/ColumnSchema.html +22 -0
  103. package/docs/interfaces/DataPipelineConfiguration.html +2 -2
  104. package/docs/interfaces/EditingHistoryConfiguration.html +10 -0
  105. package/docs/interfaces/ExportFormat.html +2 -2
  106. package/docs/interfaces/ExportOptions.html +1 -1
  107. package/docs/interfaces/FilterStateSnapshot.html +4 -0
  108. package/docs/interfaces/GetStateOptions.html +4 -0
  109. package/docs/interfaces/GridCapabilities.html +8 -0
  110. package/docs/interfaces/GridEditingConfiguration.html +4 -2
  111. package/docs/interfaces/GridRowPinningConfiguration.html +5 -0
  112. package/docs/interfaces/GridRowReorderingConfiguration.html +22 -0
  113. package/docs/interfaces/GridSchema.html +19 -0
  114. package/docs/interfaces/GridState.html +41 -0
  115. package/docs/interfaces/GridTreeConfiguration.html +2 -2
  116. package/docs/interfaces/PaginationConfiguration.html +1 -1
  117. package/docs/interfaces/PaginationState.html +1 -1
  118. package/docs/interfaces/SetStateOptions.html +9 -0
  119. package/docs/interfaces/SetStateResult.html +11 -0
  120. package/docs/interfaces/SortStateSnapshot.html +2 -0
  121. package/docs/interfaces/ValidatorContext.html +8 -0
  122. package/docs/media/_tokens.scss +70 -81
  123. package/docs/media/package.json +2 -2
  124. package/docs/media/state-persistence.html +189 -0
  125. package/docs/modules.html +1 -1
  126. package/docs/types/DataPipelineParams.html +2 -2
  127. package/docs/types/EditMode.html +2 -2
  128. package/docs/types/GridLocaleKey.html +3 -0
  129. package/docs/types/GridLocaleText.html +5 -0
  130. package/docs/types/LocaleParams.html +2 -0
  131. package/docs/types/PaginationMode.html +1 -1
  132. package/docs/types/RowDropPosition.html +2 -0
  133. package/docs/types/RowPinPosition.html +2 -0
  134. package/docs/types/RowRef.html +3 -0
  135. package/docs/types/Validator.html +4 -0
  136. package/docs/variables/EN_LOCALE.html +9 -0
  137. package/docs/variables/esLocale.html +8 -0
  138. package/i18n/en.d.ts +245 -0
  139. package/i18n/en.js +219 -0
  140. package/i18n/en.js.map +1 -0
  141. package/i18n/es.d.ts +18 -0
  142. package/i18n/es.js +219 -0
  143. package/i18n/es.js.map +1 -0
  144. package/i18n/index.d.ts +3 -0
  145. package/i18n/index.js +4 -0
  146. package/i18n/index.js.map +1 -0
  147. package/i18n/localize.d.ts +23 -0
  148. package/i18n/localize.js +15 -0
  149. package/i18n/localize.js.map +1 -0
  150. package/index.d.ts +8 -2
  151. package/index.js +2 -0
  152. package/index.js.map +1 -1
  153. package/internal/column-types.js +1 -1
  154. package/internal/column-types.js.map +1 -1
  155. package/internal/feature-module.d.ts +46 -0
  156. package/internal/feature-module.js +11 -0
  157. package/internal/feature-module.js.map +1 -1
  158. package/internal/flip.js +1 -1
  159. package/internal/flip.js.map +1 -1
  160. package/internal/icons.d.ts +9 -7
  161. package/internal/icons.js +75 -35
  162. package/internal/icons.js.map +1 -1
  163. package/internal/index.d.ts +5 -3
  164. package/internal/index.js +2 -1
  165. package/internal/index.js.map +1 -1
  166. package/internal/state-schema.d.ts +85 -0
  167. package/internal/state-schema.js +27 -0
  168. package/internal/state-schema.js.map +1 -0
  169. package/internal/state-snapshot.d.ts +152 -0
  170. package/internal/state-snapshot.js +115 -0
  171. package/internal/state-snapshot.js.map +1 -0
  172. package/internal/tags.d.ts +1 -0
  173. package/internal/tags.js +1 -0
  174. package/internal/tags.js.map +1 -1
  175. package/internal/types.d.ts +162 -2
  176. package/internal/types.js.map +1 -1
  177. package/internal/utils.d.ts +12 -0
  178. package/internal/utils.js +17 -0
  179. package/internal/utils.js.map +1 -1
  180. package/internal/validators.d.ts +31 -0
  181. package/internal/validators.js +44 -0
  182. package/internal/validators.js.map +1 -0
  183. package/package.json +1 -1
  184. package/styles/_tokens.css.js +1 -1
  185. package/styles/_tokens.css.js.map +1 -1
  186. package/styles/body-cell/body-cell.css.js +1 -1
  187. package/styles/body-cell/body-cell.css.js.map +1 -1
  188. package/styles/body-row/body-row.css.js +1 -1
  189. package/styles/body-row/body-row.css.js.map +1 -1
  190. package/styles/filter-row/filter-row.css.js +1 -1
  191. package/styles/filter-row/filter-row.css.js.map +1 -1
  192. package/styles/grid/_grid.base.css.js +1 -1
  193. package/styles/grid/_grid.base.css.js.map +1 -1
  194. package/styles/grid/grid.css.js +1 -1
  195. package/styles/grid/grid.css.js.map +1 -1
  196. package/styles/group-header-row/group-header-row.css.d.ts +1 -0
  197. package/styles/group-header-row/group-header-row.css.js +3 -0
  198. package/styles/group-header-row/group-header-row.css.js.map +1 -0
  199. package/styles/header-cell/header-cell.css.js +1 -1
  200. package/styles/header-cell/header-cell.css.js.map +1 -1
  201. package/styles/header-row/header-row.base.css.js +1 -1
  202. package/styles/header-row/header-row.base.css.js.map +1 -1
  203. package/styles/toolbar/toolbar.css.js +1 -1
  204. package/styles/toolbar/toolbar.css.js.map +1 -1
  205. package/docs/classes/ApexGrid.html +0 -399
@@ -6,10 +6,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { consume } from '@lit/context';
8
8
  import { html, LitElement, nothing } from 'lit';
9
- import { property } from 'lit/decorators.js';
9
+ import { property, state } from 'lit/decorators.js';
10
10
  import { gridStateContext } from '../controllers/state.js';
11
11
  import { MIN_COL_RESIZE_WIDTH } from '../internal/constants.js';
12
- import { renderSortArrows } from '../internal/icons.js';
12
+ import { renderIcon, renderSortArrows } from '../internal/icons.js';
13
13
  import { partNameMap } from '../internal/part-map.js';
14
14
  import { registerComponent } from '../internal/register.js';
15
15
  import { GRID_HEADER_TAG } from '../internal/tags.js';
@@ -19,6 +19,8 @@ export default class ApexGridHeader extends LitElement {
19
19
  constructor() {
20
20
  super(...arguments);
21
21
  this.colindex = 0;
22
+ this.coordinateLetter = '';
23
+ this.menuOpen = false;
22
24
  this.#handleResize = ({ clientX }) => {
23
25
  const { left } = this.getBoundingClientRect();
24
26
  const width = Math.max(clientX - left, MIN_COL_RESIZE_WIDTH);
@@ -42,7 +44,8 @@ export default class ApexGridHeader extends LitElement {
42
44
  return;
43
45
  const path = event.composedPath();
44
46
  const target = path[0];
45
- if (target instanceof Element && target.closest?.('[part~="resizable"], [part~="action"]')) {
47
+ if (target instanceof Element &&
48
+ target.closest?.('[part~="resizable"], [part~="action"], [part~="col-menu"]')) {
46
49
  return;
47
50
  }
48
51
  this.#dragStartX = event.clientX;
@@ -89,6 +92,79 @@ export default class ApexGridHeader extends LitElement {
89
92
  }
90
93
  this.#dragPointerId = -1;
91
94
  };
95
+ this.#handleFilterClick = (e) => {
96
+ e.stopPropagation();
97
+ const rect = e.currentTarget.getBoundingClientRect();
98
+ this.state.filtering.setActiveColumn(this.column, rect);
99
+ };
100
+ this.#handleMenuClick = (e) => {
101
+ e.stopPropagation();
102
+ const request = new CustomEvent('apex-grid-column-menu', {
103
+ detail: { column: this.column, anchor: e.currentTarget },
104
+ bubbles: true,
105
+ composed: true,
106
+ cancelable: true,
107
+ });
108
+ this.dispatchEvent(request);
109
+ if (request.defaultPrevented)
110
+ return;
111
+ this.menuOpen = !this.menuOpen;
112
+ };
113
+ this.#handleMenuOutside = (e) => {
114
+ if (!this.menuOpen)
115
+ return;
116
+ if (e.composedPath().includes(this))
117
+ return;
118
+ this.menuOpen = false;
119
+ };
120
+ this.#handleMenuTriggerKeydown = (e) => {
121
+ if (e.key !== 'ArrowDown' && e.key !== 'Down')
122
+ return;
123
+ e.preventDefault();
124
+ e.stopPropagation();
125
+ if (!this.menuOpen) {
126
+ this.#handleMenuClick(e);
127
+ }
128
+ this.#focusMenuItem(0);
129
+ };
130
+ this.#handleColMenuKeydown = (e) => {
131
+ const items = this.#menuItems();
132
+ const current = items.findIndex((item) => item.matches(':focus'));
133
+ switch (e.key) {
134
+ case 'ArrowDown':
135
+ case 'Down':
136
+ e.preventDefault();
137
+ e.stopPropagation();
138
+ items[(current + 1) % items.length]?.focus();
139
+ return;
140
+ case 'ArrowUp':
141
+ case 'Up':
142
+ e.preventDefault();
143
+ e.stopPropagation();
144
+ items[(current - 1 + items.length) % items.length]?.focus();
145
+ return;
146
+ case 'Home':
147
+ e.preventDefault();
148
+ e.stopPropagation();
149
+ items[0]?.focus();
150
+ return;
151
+ case 'End':
152
+ e.preventDefault();
153
+ e.stopPropagation();
154
+ items[items.length - 1]?.focus();
155
+ return;
156
+ case 'Escape':
157
+ e.preventDefault();
158
+ e.stopPropagation();
159
+ this.#closeMenu(true);
160
+ return;
161
+ case 'Tab':
162
+ this.#closeMenu();
163
+ return;
164
+ default:
165
+ return;
166
+ }
167
+ };
92
168
  }
93
169
  static get tagName() {
94
170
  return GRID_HEADER_TAG;
@@ -104,7 +180,13 @@ export default class ApexGridHeader extends LitElement {
104
180
  };
105
181
  }
106
182
  get isSortable() {
107
- return Boolean(this.column.sort);
183
+ return Boolean(this.column.sort) && !this.state?.rowReorder?.hasManualOrder;
184
+ }
185
+ get isFilterable() {
186
+ return Boolean(this.column.filter);
187
+ }
188
+ get hasActiveFilter() {
189
+ return Boolean(this.state?.filtering?.state.has(this.column.key));
108
190
  }
109
191
  get resizeController() {
110
192
  return this.state.resizing;
@@ -146,7 +228,30 @@ export default class ApexGridHeader extends LitElement {
146
228
  #handleReorderPointerDown;
147
229
  #handleReorderPointerMove;
148
230
  #handleReorderPointerUp;
231
+ #handleFilterClick;
232
+ #handleMenuClick;
233
+ #handleMenuOutside;
234
+ #handleMenuTriggerKeydown;
235
+ #menuItems() {
236
+ return Array.from(this.renderRoot.querySelectorAll('[role="menuitem"]'));
237
+ }
238
+ #focusMenuItem(index) {
239
+ requestAnimationFrame(() => {
240
+ const items = this.#menuItems();
241
+ if (!items.length)
242
+ return;
243
+ items[(index + items.length) % items.length]?.focus();
244
+ });
245
+ }
246
+ #closeMenu(returnFocus = false) {
247
+ this.menuOpen = false;
248
+ if (returnFocus) {
249
+ requestAnimationFrame(() => this.renderRoot.querySelector('[part~="menu-btn"]')?.focus());
250
+ }
251
+ }
252
+ #handleColMenuKeydown;
149
253
  updated() {
254
+ this.setAttribute('data-cell-type', this.column.type ?? 'string');
150
255
  if (this.isDraggable) {
151
256
  this.setAttribute('data-reorderable', '');
152
257
  }
@@ -169,9 +274,11 @@ export default class ApexGridHeader extends LitElement {
169
274
  super.connectedCallback();
170
275
  this.setAttribute('role', 'columnheader');
171
276
  this.addEventListener('pointerdown', this.#handleReorderPointerDown);
277
+ document.addEventListener('pointerdown', this.#handleMenuOutside, true);
172
278
  }
173
279
  disconnectedCallback() {
174
280
  this.removeEventListener('pointerdown', this.#handleReorderPointerDown);
281
+ document.removeEventListener('pointerdown', this.#handleMenuOutside, true);
175
282
  super.disconnectedCallback();
176
283
  }
177
284
  renderSortPart() {
@@ -184,10 +291,10 @@ export default class ApexGridHeader extends LitElement {
184
291
  : nothing;
185
292
  const direction = state?.direction ?? 'none';
186
293
  const label = state?.direction === 'ascending'
187
- ? 'Sorted ascending. Activate to sort descending.'
294
+ ? this.state.localize('header.sortedAscending')
188
295
  : state?.direction === 'descending'
189
- ? 'Sorted descending. Activate to clear sort.'
190
- : 'Not sorted. Activate to sort ascending.';
296
+ ? this.state.localize('header.sortedDescending')
297
+ : this.state.localize('header.notSorted');
191
298
  return state || this.isSortable
192
299
  ? this.isSortable
193
300
  ? html `<button
@@ -210,11 +317,94 @@ export default class ApexGridHeader extends LitElement {
210
317
  </span>`
211
318
  : nothing;
212
319
  }
320
+ renderFilterButton() {
321
+ if (!this.isFilterable)
322
+ return nothing;
323
+ const count = this.state?.filtering?.state.get(this.column.key)?.length ?? 0;
324
+ return html `<button
325
+ type="button"
326
+ part=${partNameMap({ action: true, 'filter-btn': true, 'filter-active': this.hasActiveFilter })}
327
+ aria-label=${this.state.localize('header.filterColumn')}
328
+ @click=${this.#handleFilterClick}
329
+ >
330
+ ${renderIcon('filter')}
331
+ ${count > 1 ? html `<span part="filter-count">${count}</span>` : nothing}
332
+ </button>`;
333
+ }
334
+ renderMenuButton() {
335
+ if (this.state?.host?.columnMenu === false)
336
+ return nothing;
337
+ const hasMenuItems = this.isSortable || this.column.resizable || Boolean(this.state?.hasColumnMenu);
338
+ if (!hasMenuItems)
339
+ return nothing;
340
+ return html `<button
341
+ type="button"
342
+ part=${partNameMap({ action: true, 'menu-btn': true })}
343
+ aria-label=${this.state.localize('header.columnMenu')}
344
+ aria-expanded=${this.menuOpen ? 'true' : 'false'}
345
+ aria-haspopup="menu"
346
+ @click=${this.#handleMenuClick}
347
+ @keydown=${this.#handleMenuTriggerKeydown}
348
+ >
349
+ ${renderIcon('more-vert')}
350
+ </button>`;
351
+ }
352
+ renderColumnMenu() {
353
+ if (!this.menuOpen)
354
+ return nothing;
355
+ return html `<div part="col-menu" role="menu" @keydown=${this.#handleColMenuKeydown}>
356
+ ${this.isSortable
357
+ ? html `
358
+ <button
359
+ type="button"
360
+ part="col-menu-item"
361
+ role="menuitem"
362
+ tabindex="-1"
363
+ @click=${() => {
364
+ this.state.sorting.sort({ key: this.column.key, direction: 'ascending' });
365
+ this.menuOpen = false;
366
+ }}
367
+ >
368
+ ${renderIcon('sort-asc')} ${this.state.localize('contextMenu.sortAsc')}
369
+ </button>
370
+ <button
371
+ type="button"
372
+ part="col-menu-item"
373
+ role="menuitem"
374
+ tabindex="-1"
375
+ @click=${() => {
376
+ this.state.sorting.sort({ key: this.column.key, direction: 'descending' });
377
+ this.menuOpen = false;
378
+ }}
379
+ >
380
+ ${renderIcon('sort-desc')} ${this.state.localize('contextMenu.sortDesc')}
381
+ </button>
382
+ `
383
+ : nothing}
384
+ ${this.column.resizable
385
+ ? html `<button
386
+ type="button"
387
+ part="col-menu-item"
388
+ role="menuitem"
389
+ tabindex="-1"
390
+ @click=${() => {
391
+ this.state.resizing.autosize(this.column, this);
392
+ this.menuOpen = false;
393
+ }}
394
+ >
395
+ ${renderIcon('arrow-upward')} ${this.state.localize('header.autosizeColumn')}
396
+ </button>`
397
+ : nothing}
398
+ </div>`;
399
+ }
213
400
  renderContentPart() {
214
401
  const defaultContent = this.column.headerText ?? this.column.key;
215
402
  const template = this.column.headerTemplate;
216
403
  return html `
217
404
  <span part="title">
405
+ ${this.coordinateLetter
406
+ ? html `<span part="coord-letter" aria-hidden="true">${this.coordinateLetter}</span>`
407
+ : nothing}
218
408
  <span>${template ? template(this.context) : html `${defaultContent}`}</span>
219
409
  </span>
220
410
  `;
@@ -238,9 +428,14 @@ export default class ApexGridHeader extends LitElement {
238
428
  })}
239
429
  >
240
430
  ${this.renderContentPart()}
241
- <div part="actions">${this.renderSortPart()}</div>
431
+ <div part="actions">
432
+ ${this.renderSortPart()}
433
+ ${this.renderFilterButton()}
434
+ ${this.renderMenuButton()}
435
+ </div>
242
436
  </div>
243
437
  ${this.renderResizePart()}
438
+ ${this.renderColumnMenu()}
244
439
  `;
245
440
  }
246
441
  }
@@ -254,4 +449,10 @@ __decorate([
254
449
  __decorate([
255
450
  property({ attribute: false, type: Number })
256
451
  ], ApexGridHeader.prototype, "colindex", void 0);
452
+ __decorate([
453
+ property({ attribute: false })
454
+ ], ApexGridHeader.prototype, "coordinateLetter", void 0);
455
+ __decorate([
456
+ state()
457
+ ], ApexGridHeader.prototype, "menuOpen", void 0);
257
458
  //# sourceMappingURL=header.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/components/header.ts"],"names":[],"mappings":"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","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { gridStateContext, type StateController } from '../controllers/state.js';\nimport { MIN_COL_RESIZE_WIDTH } from '../internal/constants.js';\nimport { renderSortArrows } from '../internal/icons.js';\nimport { partNameMap } from '../internal/part-map.js';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_HEADER_TAG } from '../internal/tags.js';\nimport type { ApexHeaderContext, ColumnConfiguration } from '../internal/types.js';\nimport { styles } from '../styles/header-cell/header-cell.css.js';\n\n/** Pixels of pointer travel before a hold turns into a drag — avoids\n * accidental drags on click. */\nconst DRAG_THRESHOLD_PX = 4;\n\nexport default class ApexGridHeader<T extends object> extends LitElement {\n public static get tagName() {\n return GRID_HEADER_TAG;\n }\n\n public static override styles = styles;\n\n public static register(): void {\n registerComponent(ApexGridHeader);\n }\n\n protected get context(): ApexHeaderContext<T> {\n return {\n parent: this,\n column: this.column,\n };\n }\n\n protected get isSortable() {\n return Boolean(this.column.sort);\n }\n\n protected get resizeController() {\n return this.state.resizing;\n }\n\n protected get reorderController() {\n return this.state.reordering;\n }\n\n protected get isDraggable() {\n return Boolean(this.state?.reordering?.isDraggable(this.column));\n }\n\n @consume({ context: gridStateContext, subscribe: true })\n @property({ attribute: false })\n public state!: StateController<T>;\n\n @property({ attribute: false })\n public column!: ColumnConfiguration<T>;\n\n /** 1-based column index passed in by the parent header row for `aria-colindex`. */\n @property({ attribute: false, type: Number })\n public colindex = 0;\n\n #addResizeEventHandlers() {\n const config: AddEventListenerOptions = { once: true };\n\n this.addEventListener(\n 'gotpointercapture',\n () => {\n this.resizeController.indicatorActive = true;\n },\n config\n );\n this.addEventListener('lostpointercapture', this.#handlePointerLost, config);\n this.addEventListener('pointerup', (e) => this.releasePointerCapture(e.pointerId), config);\n this.addEventListener('pointermove', this.#handleResize);\n }\n\n #handleClick(e: MouseEvent) {\n e.stopPropagation();\n // Ctrl/Cmd+click appends to a multi-column sort; a plain click sorts by\n // this column alone. Keyboard activation (Enter/Space) fires a click whose\n // modifier flags mirror the keys held, so Ctrl/Cmd+Enter is additive too.\n this.state.sorting.sortFromHeaderClick(this.column, e.ctrlKey || e.metaKey);\n }\n\n #handleResize = ({ clientX }: PointerEvent) => {\n const { left } = this.getBoundingClientRect();\n const width = Math.max(clientX - left, MIN_COL_RESIZE_WIDTH);\n const x = this.offsetLeft + width;\n\n this.resizeController.resize(this.column, width, x);\n };\n\n #handleResizeStart(ev: PointerEvent) {\n const { target, pointerId } = ev;\n\n ev.preventDefault();\n // Resize takes priority over reorder — stop the event so the header's\n // pointerdown listener doesn't also start arming a drag.\n ev.stopPropagation();\n\n this.#addResizeEventHandlers();\n this.resizeController.start(this);\n\n (target as HTMLElement).setPointerCapture(pointerId);\n }\n\n #handlePointerLost = () => {\n this.resizeController.indicatorActive = false;\n this.removeEventListener('pointermove', this.#handleResize);\n this.resizeController.stop();\n };\n\n #handleAutosize = () => this.resizeController.autosize(this.column, this);\n\n // --- Reorder (pointer-driven) ------------------------------------------\n\n #dragStartX = 0;\n #dragStartY = 0;\n #dragPointerId = -1;\n #isDragging = false;\n\n #handleReorderPointerDown = (event: PointerEvent) => {\n if (!this.isDraggable) return;\n if (event.button !== 0) return;\n // Skip if the user grabbed an interactive sub-part of the header — the\n // resize handle or the sort/action icons. Those have their own handlers\n // and should not arm a drag.\n const path = event.composedPath();\n const target = path[0];\n if (target instanceof Element && target.closest?.('[part~=\"resizable\"], [part~=\"action\"]')) {\n return;\n }\n this.#dragStartX = event.clientX;\n this.#dragStartY = event.clientY;\n this.#dragPointerId = event.pointerId;\n this.addEventListener('pointermove', this.#handleReorderPointerMove);\n this.addEventListener('pointerup', this.#handleReorderPointerUp);\n this.addEventListener('pointercancel', this.#handleReorderPointerUp);\n };\n\n #handleReorderPointerMove = (event: PointerEvent) => {\n if (event.pointerId !== this.#dragPointerId) return;\n if (!this.#isDragging) {\n const dx = event.clientX - this.#dragStartX;\n const dy = event.clientY - this.#dragStartY;\n if (Math.hypot(dx, dy) < DRAG_THRESHOLD_PX) return;\n // Threshold crossed — start the drag in earnest.\n this.#isDragging = true;\n this.setPointerCapture(event.pointerId);\n this.setAttribute('data-dragging', '');\n const rect = this.getBoundingClientRect();\n const label = this.column.headerText ?? String(this.column.key);\n this.reorderController.start(\n this.column.key,\n rect,\n this.#dragStartX,\n this.#dragStartY,\n label\n );\n }\n this.reorderController.move(event.clientX, event.clientY);\n };\n\n #handleReorderPointerUp = (event: PointerEvent) => {\n if (event.pointerId !== this.#dragPointerId) return;\n this.removeEventListener('pointermove', this.#handleReorderPointerMove);\n this.removeEventListener('pointerup', this.#handleReorderPointerUp);\n this.removeEventListener('pointercancel', this.#handleReorderPointerUp);\n try {\n if (this.hasPointerCapture(event.pointerId)) {\n this.releasePointerCapture(event.pointerId);\n }\n } catch {\n /* capture was already released */\n }\n if (this.#isDragging) {\n this.#isDragging = false;\n this.removeAttribute('data-dragging');\n this.reorderController.end();\n }\n this.#dragPointerId = -1;\n };\n\n protected override updated() {\n // Reflect reorderability as an attribute so SCSS can show the grab\n // cursor only on columns that can actually be dragged. Tracks both the\n // grid-level `columnReordering` flag (arriving via context) and the\n // per-column `reorderable: false` opt-out at runtime.\n if (this.isDraggable) {\n this.setAttribute('data-reorderable', '');\n } else {\n this.removeAttribute('data-reorderable');\n }\n // aria-colindex stays in sync with the parent header row's numbering.\n if (this.colindex > 0) {\n this.setAttribute('aria-colindex', String(this.colindex));\n }\n // aria-sort communicates current sort direction for this column to AT.\n if (this.isSortable) {\n const sort = this.state?.sorting.state.get(this.column.key);\n const dir = sort?.direction;\n this.setAttribute(\n 'aria-sort',\n dir === 'ascending' ? 'ascending' : dir === 'descending' ? 'descending' : 'none'\n );\n } else {\n this.removeAttribute('aria-sort');\n }\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n this.setAttribute('role', 'columnheader');\n this.addEventListener('pointerdown', this.#handleReorderPointerDown);\n }\n\n public override disconnectedCallback(): void {\n this.removeEventListener('pointerdown', this.#handleReorderPointerDown);\n super.disconnectedCallback();\n }\n\n protected renderSortPart() {\n const state = this.state.sorting.state.get(this.column.key);\n const idx = Array.from(this.state.sorting.state.values()).indexOf(state!);\n const attr = this.state.host.sortConfiguration.multiple\n ? idx > -1\n ? idx + 1\n : nothing\n : nothing;\n const direction = state?.direction ?? 'none';\n\n const label =\n state?.direction === 'ascending'\n ? 'Sorted ascending. Activate to sort descending.'\n : state?.direction === 'descending'\n ? 'Sorted descending. Activate to clear sort.'\n : 'Not sorted. Activate to sort ascending.';\n\n return state || this.isSortable\n ? this.isSortable\n ? html`<button\n type=\"button\"\n part=${partNameMap({ action: true, sorted: !!state?.direction })}\n data-sort-active=${direction}\n data-sort-index=${attr === nothing ? '' : (attr as number)}\n aria-label=${label}\n @click=${this.#handleClick}\n >\n ${renderSortArrows()}\n </button>`\n : html`<span\n part=${partNameMap({ action: true, sorted: !!state?.direction })}\n data-sort-active=${direction}\n data-sort-index=${attr === nothing ? '' : (attr as number)}\n aria-hidden=\"true\"\n >\n ${renderSortArrows()}\n </span>`\n : nothing;\n }\n\n protected renderContentPart() {\n const defaultContent = this.column.headerText ?? this.column.key;\n const template = this.column.headerTemplate;\n\n return html`\n <span part=\"title\">\n <span>${template ? template(this.context) : html`${defaultContent}`}</span>\n </span>\n `;\n }\n\n protected renderResizePart() {\n return this.column.resizable\n ? html`<span\n part=\"resizable\"\n @dblclick=${this.#handleAutosize}\n @pointerdown=${this.#handleResizeStart}\n ></span>`\n : nothing;\n }\n\n protected override render() {\n return html`\n <div\n part=${partNameMap({\n content: true,\n sortable: this.isSortable,\n resizing: this.resizeController.indicatorActive,\n })}\n >\n ${this.renderContentPart()}\n <div part=\"actions\">${this.renderSortPart()}</div>\n </div>\n ${this.renderResizePart()}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexGridHeader.tagName]: ApexGridHeader<object>;\n }\n}\n"]}
1
+ {"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/components/header.ts"],"names":[],"mappings":"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","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { gridStateContext, type StateController } from '../controllers/state.js';\nimport { MIN_COL_RESIZE_WIDTH } from '../internal/constants.js';\nimport { renderIcon, renderSortArrows } from '../internal/icons.js';\nimport { partNameMap } from '../internal/part-map.js';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_HEADER_TAG } from '../internal/tags.js';\nimport type { ApexHeaderContext, ColumnConfiguration } from '../internal/types.js';\nimport { styles } from '../styles/header-cell/header-cell.css.js';\n\n/** Pixels of pointer travel before a hold turns into a drag — avoids\n * accidental drags on click. */\nconst DRAG_THRESHOLD_PX = 4;\n\nexport default class ApexGridHeader<T extends object> extends LitElement {\n public static get tagName() {\n return GRID_HEADER_TAG;\n }\n\n public static override styles = styles;\n\n public static register(): void {\n registerComponent(ApexGridHeader);\n }\n\n protected get context(): ApexHeaderContext<T> {\n return {\n parent: this,\n column: this.column,\n };\n }\n\n protected get isSortable() {\n // Sort affordances are hidden while a manual row order is active (F5):\n // sorting and manual order are mutually exclusive.\n return Boolean(this.column.sort) && !this.state?.rowReorder?.hasManualOrder;\n }\n\n protected get isFilterable() {\n return Boolean(this.column.filter);\n }\n\n protected get hasActiveFilter() {\n return Boolean(this.state?.filtering?.state.has(this.column.key));\n }\n\n protected get resizeController() {\n return this.state.resizing;\n }\n\n protected get reorderController() {\n return this.state.reordering;\n }\n\n protected get isDraggable() {\n return Boolean(this.state?.reordering?.isDraggable(this.column));\n }\n\n @consume({ context: gridStateContext, subscribe: true })\n @property({ attribute: false })\n public state!: StateController<T>;\n\n @property({ attribute: false })\n public column!: ColumnConfiguration<T>;\n\n /** 1-based column index passed in by the parent header row for `aria-colindex`. */\n @property({ attribute: false, type: Number })\n public colindex = 0;\n\n /**\n * Spreadsheet column letter (A, B, C, ...) shown as a prefix while formula\n * coordinate hints are active. Empty string hides it.\n */\n @property({ attribute: false })\n public coordinateLetter = '';\n\n @state()\n protected menuOpen = false;\n\n #addResizeEventHandlers() {\n const config: AddEventListenerOptions = { once: true };\n\n this.addEventListener(\n 'gotpointercapture',\n () => {\n this.resizeController.indicatorActive = true;\n },\n config\n );\n this.addEventListener('lostpointercapture', this.#handlePointerLost, config);\n this.addEventListener('pointerup', (e) => this.releasePointerCapture(e.pointerId), config);\n this.addEventListener('pointermove', this.#handleResize);\n }\n\n #handleClick(e: MouseEvent) {\n e.stopPropagation();\n // Ctrl/Cmd+click appends to a multi-column sort; a plain click sorts by\n // this column alone. Keyboard activation (Enter/Space) fires a click whose\n // modifier flags mirror the keys held, so Ctrl/Cmd+Enter is additive too.\n this.state.sorting.sortFromHeaderClick(this.column, e.ctrlKey || e.metaKey);\n }\n\n #handleResize = ({ clientX }: PointerEvent) => {\n const { left } = this.getBoundingClientRect();\n const width = Math.max(clientX - left, MIN_COL_RESIZE_WIDTH);\n const x = this.offsetLeft + width;\n\n this.resizeController.resize(this.column, width, x);\n };\n\n #handleResizeStart(ev: PointerEvent) {\n const { target, pointerId } = ev;\n\n ev.preventDefault();\n // Resize takes priority over reorder — stop the event so the header's\n // pointerdown listener doesn't also start arming a drag.\n ev.stopPropagation();\n\n this.#addResizeEventHandlers();\n this.resizeController.start(this);\n\n (target as HTMLElement).setPointerCapture(pointerId);\n }\n\n #handlePointerLost = () => {\n this.resizeController.indicatorActive = false;\n this.removeEventListener('pointermove', this.#handleResize);\n this.resizeController.stop();\n };\n\n #handleAutosize = () => this.resizeController.autosize(this.column, this);\n\n // --- Reorder (pointer-driven) ------------------------------------------\n\n #dragStartX = 0;\n #dragStartY = 0;\n #dragPointerId = -1;\n #isDragging = false;\n\n #handleReorderPointerDown = (event: PointerEvent) => {\n if (!this.isDraggable) return;\n if (event.button !== 0) return;\n // Skip if the user grabbed an interactive sub-part of the header — the\n // resize handle, sort/action icons, filter button, menu button, or the\n // column menu dropdown. Those have their own handlers and should not arm\n // a drag.\n const path = event.composedPath();\n const target = path[0];\n if (\n target instanceof Element &&\n target.closest?.('[part~=\"resizable\"], [part~=\"action\"], [part~=\"col-menu\"]')\n ) {\n return;\n }\n this.#dragStartX = event.clientX;\n this.#dragStartY = event.clientY;\n this.#dragPointerId = event.pointerId;\n this.addEventListener('pointermove', this.#handleReorderPointerMove);\n this.addEventListener('pointerup', this.#handleReorderPointerUp);\n this.addEventListener('pointercancel', this.#handleReorderPointerUp);\n };\n\n #handleReorderPointerMove = (event: PointerEvent) => {\n if (event.pointerId !== this.#dragPointerId) return;\n if (!this.#isDragging) {\n const dx = event.clientX - this.#dragStartX;\n const dy = event.clientY - this.#dragStartY;\n if (Math.hypot(dx, dy) < DRAG_THRESHOLD_PX) return;\n // Threshold crossed — start the drag in earnest.\n this.#isDragging = true;\n this.setPointerCapture(event.pointerId);\n this.setAttribute('data-dragging', '');\n const rect = this.getBoundingClientRect();\n const label = this.column.headerText ?? String(this.column.key);\n this.reorderController.start(\n this.column.key,\n rect,\n this.#dragStartX,\n this.#dragStartY,\n label\n );\n }\n this.reorderController.move(event.clientX, event.clientY);\n };\n\n #handleReorderPointerUp = (event: PointerEvent) => {\n if (event.pointerId !== this.#dragPointerId) return;\n this.removeEventListener('pointermove', this.#handleReorderPointerMove);\n this.removeEventListener('pointerup', this.#handleReorderPointerUp);\n this.removeEventListener('pointercancel', this.#handleReorderPointerUp);\n try {\n if (this.hasPointerCapture(event.pointerId)) {\n this.releasePointerCapture(event.pointerId);\n }\n } catch {\n /* capture was already released */\n }\n if (this.#isDragging) {\n this.#isDragging = false;\n this.removeAttribute('data-dragging');\n this.reorderController.end();\n }\n this.#dragPointerId = -1;\n };\n\n // --- Filter button --------------------------------------------------\n\n #handleFilterClick = (e: MouseEvent) => {\n e.stopPropagation();\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n this.state.filtering.setActiveColumn(this.column, rect);\n };\n\n // --- Column menu button ---------------------------------------------\n\n #handleMenuClick = (e: MouseEvent) => {\n e.stopPropagation();\n // Offer the column menu to a feature module first: the enterprise context\n // menu opens its richer, shared menu (sort / pin / hide / group / chart)\n // anchored at this button and calls preventDefault(). When nothing handles\n // it (the community grid), fall back to the built-in inline menu below.\n // Event name is a stable string contract (mirrored in the enterprise\n // context-menu controller), like the native 'contextmenu'.\n const request = new CustomEvent('apex-grid-column-menu', {\n detail: { column: this.column, anchor: e.currentTarget as HTMLElement },\n bubbles: true,\n composed: true,\n cancelable: true,\n });\n this.dispatchEvent(request);\n if (request.defaultPrevented) return;\n this.menuOpen = !this.menuOpen;\n };\n\n #handleMenuOutside = (e: PointerEvent) => {\n if (!this.menuOpen) return;\n if (e.composedPath().includes(this)) return;\n this.menuOpen = false;\n };\n\n /** ArrowDown on the kebab opens the menu and moves focus to its first item. */\n #handleMenuTriggerKeydown = (e: KeyboardEvent) => {\n if (e.key !== 'ArrowDown' && e.key !== 'Down') return;\n e.preventDefault();\n e.stopPropagation();\n if (!this.menuOpen) {\n // Route through the same module-first contract as a click.\n this.#handleMenuClick(e as unknown as MouseEvent);\n }\n this.#focusMenuItem(0);\n };\n\n #menuItems(): HTMLElement[] {\n return Array.from(this.renderRoot.querySelectorAll<HTMLElement>('[role=\"menuitem\"]'));\n }\n\n #focusMenuItem(index: number) {\n requestAnimationFrame(() => {\n const items = this.#menuItems();\n if (!items.length) return;\n items[(index + items.length) % items.length]?.focus();\n });\n }\n\n #closeMenu(returnFocus = false) {\n this.menuOpen = false;\n if (returnFocus) {\n requestAnimationFrame(() =>\n this.renderRoot.querySelector<HTMLElement>('[part~=\"menu-btn\"]')?.focus()\n );\n }\n }\n\n /** Menu keyboard pattern: arrows/Home/End rove, Escape closes and restores focus. */\n #handleColMenuKeydown = (e: KeyboardEvent) => {\n const items = this.#menuItems();\n const current = items.findIndex((item) => item.matches(':focus'));\n switch (e.key) {\n case 'ArrowDown':\n case 'Down':\n e.preventDefault();\n e.stopPropagation();\n items[(current + 1) % items.length]?.focus();\n return;\n case 'ArrowUp':\n case 'Up':\n e.preventDefault();\n e.stopPropagation();\n items[(current - 1 + items.length) % items.length]?.focus();\n return;\n case 'Home':\n e.preventDefault();\n e.stopPropagation();\n items[0]?.focus();\n return;\n case 'End':\n e.preventDefault();\n e.stopPropagation();\n items[items.length - 1]?.focus();\n return;\n case 'Escape':\n e.preventDefault();\n e.stopPropagation();\n this.#closeMenu(true);\n return;\n case 'Tab':\n this.#closeMenu();\n return;\n default:\n return;\n }\n };\n\n protected override updated() {\n // Mirror the column's data type onto the host so the header label can match\n // the body cell alignment by default (numeric/currency cells right-align,\n // so their headers should too). Kept in sync on every update because the\n // column config can change at runtime (reorder, reconfigure).\n this.setAttribute('data-cell-type', this.column.type ?? 'string');\n // Reflect reorderability as an attribute so SCSS can show the grab\n // cursor only on columns that can actually be dragged. Tracks both the\n // grid-level `columnReordering` flag (arriving via context) and the\n // per-column `reorderable: false` opt-out at runtime.\n if (this.isDraggable) {\n this.setAttribute('data-reorderable', '');\n } else {\n this.removeAttribute('data-reorderable');\n }\n // aria-colindex stays in sync with the parent header row's numbering.\n if (this.colindex > 0) {\n this.setAttribute('aria-colindex', String(this.colindex));\n }\n // aria-sort communicates current sort direction for this column to AT.\n if (this.isSortable) {\n const sort = this.state?.sorting.state.get(this.column.key);\n const dir = sort?.direction;\n this.setAttribute(\n 'aria-sort',\n dir === 'ascending' ? 'ascending' : dir === 'descending' ? 'descending' : 'none'\n );\n } else {\n this.removeAttribute('aria-sort');\n }\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n this.setAttribute('role', 'columnheader');\n this.addEventListener('pointerdown', this.#handleReorderPointerDown);\n document.addEventListener('pointerdown', this.#handleMenuOutside, true);\n }\n\n public override disconnectedCallback(): void {\n this.removeEventListener('pointerdown', this.#handleReorderPointerDown);\n document.removeEventListener('pointerdown', this.#handleMenuOutside, true);\n super.disconnectedCallback();\n }\n\n protected renderSortPart() {\n const state = this.state.sorting.state.get(this.column.key);\n const idx = Array.from(this.state.sorting.state.values()).indexOf(state!);\n const attr = this.state.host.sortConfiguration.multiple\n ? idx > -1\n ? idx + 1\n : nothing\n : nothing;\n const direction = state?.direction ?? 'none';\n\n const label =\n state?.direction === 'ascending'\n ? this.state.localize('header.sortedAscending')\n : state?.direction === 'descending'\n ? this.state.localize('header.sortedDescending')\n : this.state.localize('header.notSorted');\n\n return state || this.isSortable\n ? this.isSortable\n ? html`<button\n type=\"button\"\n part=${partNameMap({ action: true, sorted: !!state?.direction })}\n data-sort-active=${direction}\n data-sort-index=${attr === nothing ? '' : (attr as number)}\n aria-label=${label}\n @click=${this.#handleClick}\n >\n ${renderSortArrows()}\n </button>`\n : html`<span\n part=${partNameMap({ action: true, sorted: !!state?.direction })}\n data-sort-active=${direction}\n data-sort-index=${attr === nothing ? '' : (attr as number)}\n aria-hidden=\"true\"\n >\n ${renderSortArrows()}\n </span>`\n : nothing;\n }\n\n protected renderFilterButton() {\n if (!this.isFilterable) return nothing;\n const count = this.state?.filtering?.state.get(this.column.key)?.length ?? 0;\n return html`<button\n type=\"button\"\n part=${partNameMap({ action: true, 'filter-btn': true, 'filter-active': this.hasActiveFilter })}\n aria-label=${this.state.localize('header.filterColumn')}\n @click=${this.#handleFilterClick}\n >\n ${renderIcon('filter')}\n ${count > 1 ? html`<span part=\"filter-count\">${count}</span>` : nothing}\n </button>`;\n }\n\n protected renderMenuButton() {\n // Suppress the kebab entirely when the grid opts out.\n if (this.state?.host?.columnMenu === false) return nothing;\n // Show the kebab when this column has built-in menu items (sort / autosize)\n // or when a feature module provides a richer column menu (the enterprise\n // context menu: pin / hide / group / chart), so the affordance appears even\n // on columns that are neither sortable nor resizable.\n const hasMenuItems =\n this.isSortable || this.column.resizable || Boolean(this.state?.hasColumnMenu);\n if (!hasMenuItems) return nothing;\n return html`<button\n type=\"button\"\n part=${partNameMap({ action: true, 'menu-btn': true })}\n aria-label=${this.state.localize('header.columnMenu')}\n aria-expanded=${this.menuOpen ? 'true' : 'false'}\n aria-haspopup=\"menu\"\n @click=${this.#handleMenuClick}\n @keydown=${this.#handleMenuTriggerKeydown}\n >\n ${renderIcon('more-vert')}\n </button>`;\n }\n\n protected renderColumnMenu() {\n if (!this.menuOpen) return nothing;\n return html`<div part=\"col-menu\" role=\"menu\" @keydown=${this.#handleColMenuKeydown}>\n ${\n this.isSortable\n ? html`\n <button\n type=\"button\"\n part=\"col-menu-item\"\n role=\"menuitem\"\n tabindex=\"-1\"\n @click=${() => {\n this.state.sorting.sort({ key: this.column.key, direction: 'ascending' } as any);\n this.menuOpen = false;\n }}\n >\n ${renderIcon('sort-asc')} ${this.state.localize('contextMenu.sortAsc')}\n </button>\n <button\n type=\"button\"\n part=\"col-menu-item\"\n role=\"menuitem\"\n tabindex=\"-1\"\n @click=${() => {\n this.state.sorting.sort({ key: this.column.key, direction: 'descending' } as any);\n this.menuOpen = false;\n }}\n >\n ${renderIcon('sort-desc')} ${this.state.localize('contextMenu.sortDesc')}\n </button>\n `\n : nothing\n }\n ${\n this.column.resizable\n ? html`<button\n type=\"button\"\n part=\"col-menu-item\"\n role=\"menuitem\"\n tabindex=\"-1\"\n @click=${() => {\n this.state.resizing.autosize(this.column, this);\n this.menuOpen = false;\n }}\n >\n ${renderIcon('arrow-upward')} ${this.state.localize('header.autosizeColumn')}\n </button>`\n : nothing\n }\n </div>`;\n }\n\n protected renderContentPart() {\n const defaultContent = this.column.headerText ?? this.column.key;\n const template = this.column.headerTemplate;\n\n return html`\n <span part=\"title\">\n ${\n this.coordinateLetter\n ? html`<span part=\"coord-letter\" aria-hidden=\"true\">${this.coordinateLetter}</span>`\n : nothing\n }\n <span>${template ? template(this.context) : html`${defaultContent}`}</span>\n </span>\n `;\n }\n\n protected renderResizePart() {\n return this.column.resizable\n ? html`<span\n part=\"resizable\"\n @dblclick=${this.#handleAutosize}\n @pointerdown=${this.#handleResizeStart}\n ></span>`\n : nothing;\n }\n\n protected override render() {\n return html`\n <div\n part=${partNameMap({\n content: true,\n sortable: this.isSortable,\n resizing: this.resizeController.indicatorActive,\n })}\n >\n ${this.renderContentPart()}\n <div part=\"actions\">\n ${this.renderSortPart()}\n ${this.renderFilterButton()}\n ${this.renderMenuButton()}\n </div>\n </div>\n ${this.renderResizePart()}\n ${this.renderColumnMenu()}\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexGridHeader.tagName]: ApexGridHeader<object>;\n }\n}\n"]}
@@ -34,9 +34,14 @@ export default class ApexGridPaginator<T extends object> extends LitElement {
34
34
  pageSizeOptions: number[];
35
35
  /**
36
36
  * Accessible label for the rows-per-page selector.
37
+ *
38
+ * @remarks
39
+ * When unset, falls back to the grid's localized `pagination.rowsPerPage`
40
+ * text (see {@link ApexGrid.localeText}).
37
41
  */
38
- pageSizeLabel: string;
42
+ pageSizeLabel?: string;
39
43
  protected get controller(): import("../controllers/pagination.js").PaginationController<T>;
44
+ protected get sizeLabel(): string;
40
45
  protected renderSizeSelect(): import("lit-html").TemplateResult<1>;
41
46
  protected renderInfo(): import("lit-html").TemplateResult<1>;
42
47
  protected renderButton(opts: {
@@ -16,7 +16,6 @@ export default class ApexGridPaginator extends LitElement {
16
16
  constructor() {
17
17
  super(...arguments);
18
18
  this.pageSizeOptions = [10, 25, 50, 100];
19
- this.pageSizeLabel = 'Rows per page';
20
19
  this.#handleSizeChange = (event) => {
21
20
  event.stopPropagation();
22
21
  const next = Number(event.target.value);
@@ -43,14 +42,17 @@ export default class ApexGridPaginator extends LitElement {
43
42
  get controller() {
44
43
  return this.state.pagination;
45
44
  }
45
+ get sizeLabel() {
46
+ return this.pageSizeLabel ?? this.state.localize('pagination.rowsPerPage');
47
+ }
46
48
  #handleSizeChange;
47
49
  renderSizeSelect() {
48
50
  const current = this.controller.pageSize;
49
51
  return html `
50
52
  <label part="paginator-size">
51
- <span class="visually-hidden">${this.pageSizeLabel}</span>
53
+ <span class="visually-hidden">${this.sizeLabel}</span>
52
54
  <select
53
- aria-label=${this.pageSizeLabel}
55
+ aria-label=${this.sizeLabel}
54
56
  .value=${String(current)}
55
57
  @change=${this.#handleSizeChange}
56
58
  >
@@ -62,11 +64,15 @@ export default class ApexGridPaginator extends LitElement {
62
64
  renderInfo() {
63
65
  const { page, pageSize, totalItems } = this.controller.state;
64
66
  if (totalItems === 0) {
65
- return html `<span part="paginator-info" aria-live="polite">0 of 0</span>`;
67
+ return html `<span part="paginator-info" aria-live="polite"
68
+ >${this.state.localize('pagination.summaryEmpty')}</span
69
+ >`;
66
70
  }
67
71
  const start = page * pageSize + 1;
68
72
  const end = Math.min(totalItems, (page + 1) * pageSize);
69
- return html `<span part="paginator-info" aria-live="polite">${start}–${end} of ${totalItems}</span>`;
73
+ return html `<span part="paginator-info" aria-live="polite"
74
+ >${this.state.localize('pagination.summary', { start, end, total: totalItems })}</span
75
+ >`;
70
76
  }
71
77
  renderButton(opts) {
72
78
  return html `<button
@@ -90,20 +96,20 @@ export default class ApexGridPaginator extends LitElement {
90
96
  <div
91
97
  part="paginator-controls"
92
98
  role="group"
93
- aria-label="Pagination controls"
99
+ aria-label=${this.state.localize('pagination.controls')}
94
100
  @keydown=${this.#handleControlsKeydown}
95
101
  >
96
102
  ${this.renderButton({
97
103
  id: 'first',
98
104
  icon: 'page-first',
99
- label: 'Go to first page',
105
+ label: this.state.localize('pagination.firstPage'),
100
106
  disabled: onFirst,
101
107
  onClick: () => this.controller.firstPage(),
102
108
  })}
103
109
  ${this.renderButton({
104
110
  id: 'previous',
105
111
  icon: 'page-previous',
106
- label: 'Go to previous page',
112
+ label: this.state.localize('pagination.previousPage'),
107
113
  disabled: onFirst,
108
114
  onClick: () => this.controller.previousPage(),
109
115
  })}
@@ -111,14 +117,14 @@ export default class ApexGridPaginator extends LitElement {
111
117
  ${this.renderButton({
112
118
  id: 'next',
113
119
  icon: 'page-next',
114
- label: 'Go to next page',
120
+ label: this.state.localize('pagination.nextPage'),
115
121
  disabled: onLast,
116
122
  onClick: () => this.controller.nextPage(),
117
123
  })}
118
124
  ${this.renderButton({
119
125
  id: 'last',
120
126
  icon: 'page-last',
121
- label: 'Go to last page',
127
+ label: this.state.localize('pagination.lastPage'),
122
128
  disabled: onLast,
123
129
  onClick: () => this.controller.lastPage(),
124
130
  })}
@@ -129,7 +135,7 @@ export default class ApexGridPaginator extends LitElement {
129
135
  if (!this.state)
130
136
  return nothing;
131
137
  return html `
132
- <div part="paginator" role="navigation" aria-label="Grid pagination">
138
+ <div part="paginator" role="navigation" aria-label=${this.state.localize('pagination.label')}>
133
139
  ${this.renderSizeSelect()} ${this.renderInfo()} ${this.renderControls()}
134
140
  </div>
135
141
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"paginator.js","sourceRoot":"","sources":["../../src/components/paginator.ts"],"names":[],"mappings":"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","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { gridStateContext, type StateController } from '../controllers/state.js';\nimport { renderIcon } from '../internal/icons.js';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_PAGINATOR_TAG } from '../internal/tags.js';\nimport { styles } from '../styles/paginator/paginator.css.js';\n\n/**\n * Pagination toolbar rendered beneath the grid body.\n *\n * @remarks\n * Drives {@link PaginationController} on the host grid. The component is purely\n * presentational — page transitions go through the controller so they emit the\n * cancellable `pageChanging` event and the post-update `pageChanged` event.\n *\n * @element apex-grid-paginator\n *\n * @csspart paginator - The root container.\n * @csspart paginator-size - The page-size selector wrapper.\n * @csspart paginator-info - The \"1–25 of 100\" status label.\n * @csspart paginator-controls - The first/prev/next/last button cluster.\n * @csspart paginator-page - The \"Page X of N\" status label.\n */\nexport default class ApexGridPaginator<T extends object> extends LitElement {\n public static get tagName() {\n return GRID_PAGINATOR_TAG;\n }\n\n public static override styles = styles;\n\n /**\n * Registers the `<apex-grid-paginator>` element and its dependencies. Idempotent.\n */\n public static register() {\n registerComponent(ApexGridPaginator);\n }\n\n @consume({ context: gridStateContext, subscribe: true })\n @property({ attribute: false })\n public state!: StateController<T>;\n\n /**\n * The page-size choices rendered in the rows-per-page selector.\n *\n * @remarks\n * Defaults to `[10, 25, 50, 100]`.\n */\n @property({ attribute: false })\n public pageSizeOptions: number[] = [10, 25, 50, 100];\n\n /**\n * Accessible label for the rows-per-page selector.\n */\n @property({ type: String, attribute: 'page-size-label' })\n public pageSizeLabel = 'Rows per page';\n\n protected get controller() {\n return this.state.pagination;\n }\n\n #handleSizeChange = (event: Event) => {\n event.stopPropagation();\n const next = Number((event.target as HTMLSelectElement).value);\n if (Number.isFinite(next)) {\n this.controller.setPageSize(next);\n }\n };\n\n protected renderSizeSelect() {\n const current = this.controller.pageSize;\n return html`\n <label part=\"paginator-size\">\n <span class=\"visually-hidden\">${this.pageSizeLabel}</span>\n <select\n aria-label=${this.pageSizeLabel}\n .value=${String(current)}\n @change=${this.#handleSizeChange}\n >\n ${this.pageSizeOptions.map(\n (size) =>\n html`<option .value=${String(size)} ?selected=${size === current}>${size}</option>`\n )}\n </select>\n </label>\n `;\n }\n\n protected renderInfo() {\n const { page, pageSize, totalItems } = this.controller.state;\n if (totalItems === 0) {\n return html`<span part=\"paginator-info\" aria-live=\"polite\">0 of 0</span>`;\n }\n const start = page * pageSize + 1;\n const end = Math.min(totalItems, (page + 1) * pageSize);\n return html`<span part=\"paginator-info\" aria-live=\"polite\">${start}–${end} of ${totalItems}</span>`;\n }\n\n protected renderButton(opts: {\n id: string;\n icon: string;\n label: string;\n disabled: boolean;\n onClick: () => void;\n }) {\n return html`<button\n part=\"paginator-button\"\n id=${opts.id}\n type=\"button\"\n aria-label=${opts.label}\n title=${opts.label}\n ?disabled=${opts.disabled}\n @click=${opts.onClick}\n >\n ${renderIcon(opts.icon)}\n </button>`;\n }\n\n #handleControlsKeydown = (event: KeyboardEvent) => {\n // Keep arrow-key navigation inside the paginator instead of bubbling into the grid.\n if (\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowRight' ||\n event.key === 'ArrowUp' ||\n event.key === 'ArrowDown'\n ) {\n event.stopPropagation();\n }\n };\n\n protected renderControls() {\n const { page, pageCount, totalItems } = this.controller.state;\n const onFirst = page <= 0 || totalItems === 0;\n const onLast = page >= pageCount - 1 || totalItems === 0;\n\n return html`\n <div\n part=\"paginator-controls\"\n role=\"group\"\n aria-label=\"Pagination controls\"\n @keydown=${this.#handleControlsKeydown}\n >\n ${this.renderButton({\n id: 'first',\n icon: 'page-first',\n label: 'Go to first page',\n disabled: onFirst,\n onClick: () => this.controller.firstPage(),\n })}\n ${this.renderButton({\n id: 'previous',\n icon: 'page-previous',\n label: 'Go to previous page',\n disabled: onFirst,\n onClick: () => this.controller.previousPage(),\n })}\n <span part=\"paginator-page\" aria-live=\"polite\">${page + 1} / ${pageCount}</span>\n ${this.renderButton({\n id: 'next',\n icon: 'page-next',\n label: 'Go to next page',\n disabled: onLast,\n onClick: () => this.controller.nextPage(),\n })}\n ${this.renderButton({\n id: 'last',\n icon: 'page-last',\n label: 'Go to last page',\n disabled: onLast,\n onClick: () => this.controller.lastPage(),\n })}\n </div>\n `;\n }\n\n protected override render() {\n if (!this.state) return nothing;\n return html`\n <div part=\"paginator\" role=\"navigation\" aria-label=\"Grid pagination\">\n ${this.renderSizeSelect()} ${this.renderInfo()} ${this.renderControls()}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexGridPaginator.tagName]: ApexGridPaginator<object>;\n }\n}\n"]}
1
+ {"version":3,"file":"paginator.js","sourceRoot":"","sources":["../../src/components/paginator.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAwB,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAC;AAkB9D,MAAM,CAAC,OAAO,OAAO,iBAAoC,SAAQ,UAAU;IAA3E;;QAyBS,oBAAe,GAAa,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QAoBrD,sBAAiB,GAAG,CAAC,KAAY,EAAE,EAAE;YACnC,KAAK,CAAC,eAAe,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,MAAM,CAAE,KAAK,CAAC,MAA4B,CAAC,KAAK,CAAC,CAAC;YAC/D,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC;QACH,CAAC,CAAC;QAuDF,2BAAsB,GAAG,CAAC,KAAoB,EAAE,EAAE;YAEhD,IACE,KAAK,CAAC,GAAG,KAAK,WAAW;gBACzB,KAAK,CAAC,GAAG,KAAK,YAAY;gBAC1B,KAAK,CAAC,GAAG,KAAK,SAAS;gBACvB,KAAK,CAAC,GAAG,KAAK,WAAW,EACzB,CAAC;gBACD,KAAK,CAAC,eAAe,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC;IAuDJ,CAAC;IA1KQ,MAAM,KAAK,OAAO;QACvB,OAAO,kBAAkB,CAAC;IAC5B,CAAC;aAEsB,WAAM,GAAG,MAAM,AAAT,CAAU;IAKhC,MAAM,CAAC,QAAQ;QACpB,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IACvC,CAAC;IAyBD,IAAc,UAAU;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;IAC/B,CAAC;IAED,IAAc,SAAS;QACrB,OAAO,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC;IAC7E,CAAC;IAED,iBAAiB,CAMf;IAEQ,gBAAgB;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QACzC,OAAO,IAAI,CAAA;;wCAEyB,IAAI,CAAC,SAAS;;uBAE/B,IAAI,CAAC,SAAS;mBAClB,MAAM,CAAC,OAAO,CAAC;oBACd,IAAI,CAAC,iBAAiB;;YAE9B,IAAI,CAAC,eAAe,CAAC,GAAG,CACxB,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,CAAA,kBAAkB,MAAM,CAAC,IAAI,CAAC,cAAc,IAAI,KAAK,OAAO,IAAI,IAAI,WAAW,CACtF;;;KAGN,CAAC;IACJ,CAAC;IAES,UAAU;QAClB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAC7D,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,IAAI,CAAA;WACN,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QACjD,CAAC;QACL,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,GAAG,QAAQ,GAAG,CAAC,CAAC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;QACxD,OAAO,IAAI,CAAA;SACN,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;MAC/E,CAAC;IACL,CAAC;IAES,YAAY,CAAC,IAMtB;QACC,OAAO,IAAI,CAAA;;WAEJ,IAAI,CAAC,EAAE;;mBAEC,IAAI,CAAC,KAAK;cACf,IAAI,CAAC,KAAK;kBACN,IAAI,CAAC,QAAQ;eAChB,IAAI,CAAC,OAAO;;QAEnB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;cACf,CAAC;IACb,CAAC;IAED,sBAAsB,CAUpB;IAEQ,cAAc;QACtB,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAC9D,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,UAAU,KAAK,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,IAAI,SAAS,GAAG,CAAC,IAAI,UAAU,KAAK,CAAC,CAAC;QAEzD,OAAO,IAAI,CAAA;;;;qBAIM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,qBAAqB,CAAC;mBAC5C,IAAI,CAAC,sBAAsB;;UAEpC,IAAI,CAAC,YAAY,CAAC;YAClB,EAAE,EAAE,OAAO;YACX,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YAClD,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE;SAC3C,CAAC;UACA,IAAI,CAAC,YAAY,CAAC;YAClB,EAAE,EAAE,UAAU;YACd,IAAI,EAAE,eAAe;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,yBAAyB,CAAC;YACrD,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE;SAC9C,CAAC;yDAC+C,IAAI,GAAG,CAAC,MAAM,SAAS;UACtE,IAAI,CAAC,YAAY,CAAC;YAClB,EAAE,EAAE,MAAM;YACV,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,qBAAqB,CAAC;YACjD,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE;SAC1C,CAAC;UACA,IAAI,CAAC,YAAY,CAAC;YAClB,EAAE,EAAE,MAAM;YACV,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,qBAAqB,CAAC;YACjD,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE;SAC1C,CAAC;;KAEL,CAAC;IACJ,CAAC;IAEkB,MAAM;QACvB,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,OAAO,CAAC;QAChC,OAAO,IAAI,CAAA;2DAC4C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC;UACxF,IAAI,CAAC,gBAAgB,EAAE,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,IAAI,CAAC,cAAc,EAAE;;KAE1E,CAAC;IACJ,CAAC;;AA1JM;IAFN,OAAO,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACvD,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;gDACG;AAS3B;IADN,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;0DACsB;AAU9C;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;wDAC3B","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { gridStateContext, type StateController } from '../controllers/state.js';\nimport { renderIcon } from '../internal/icons.js';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_PAGINATOR_TAG } from '../internal/tags.js';\nimport { styles } from '../styles/paginator/paginator.css.js';\n\n/**\n * Pagination toolbar rendered beneath the grid body.\n *\n * @remarks\n * Drives {@link PaginationController} on the host grid. The component is purely\n * presentational — page transitions go through the controller so they emit the\n * cancellable `pageChanging` event and the post-update `pageChanged` event.\n *\n * @element apex-grid-paginator\n *\n * @csspart paginator - The root container.\n * @csspart paginator-size - The page-size selector wrapper.\n * @csspart paginator-info - The \"1–25 of 100\" status label.\n * @csspart paginator-controls - The first/prev/next/last button cluster.\n * @csspart paginator-page - The \"Page X of N\" status label.\n */\nexport default class ApexGridPaginator<T extends object> extends LitElement {\n public static get tagName() {\n return GRID_PAGINATOR_TAG;\n }\n\n public static override styles = styles;\n\n /**\n * Registers the `<apex-grid-paginator>` element and its dependencies. Idempotent.\n */\n public static register() {\n registerComponent(ApexGridPaginator);\n }\n\n @consume({ context: gridStateContext, subscribe: true })\n @property({ attribute: false })\n public state!: StateController<T>;\n\n /**\n * The page-size choices rendered in the rows-per-page selector.\n *\n * @remarks\n * Defaults to `[10, 25, 50, 100]`.\n */\n @property({ attribute: false })\n public pageSizeOptions: number[] = [10, 25, 50, 100];\n\n /**\n * Accessible label for the rows-per-page selector.\n *\n * @remarks\n * When unset, falls back to the grid's localized `pagination.rowsPerPage`\n * text (see {@link ApexGrid.localeText}).\n */\n @property({ type: String, attribute: 'page-size-label' })\n public pageSizeLabel?: string;\n\n protected get controller() {\n return this.state.pagination;\n }\n\n protected get sizeLabel() {\n return this.pageSizeLabel ?? this.state.localize('pagination.rowsPerPage');\n }\n\n #handleSizeChange = (event: Event) => {\n event.stopPropagation();\n const next = Number((event.target as HTMLSelectElement).value);\n if (Number.isFinite(next)) {\n this.controller.setPageSize(next);\n }\n };\n\n protected renderSizeSelect() {\n const current = this.controller.pageSize;\n return html`\n <label part=\"paginator-size\">\n <span class=\"visually-hidden\">${this.sizeLabel}</span>\n <select\n aria-label=${this.sizeLabel}\n .value=${String(current)}\n @change=${this.#handleSizeChange}\n >\n ${this.pageSizeOptions.map(\n (size) =>\n html`<option .value=${String(size)} ?selected=${size === current}>${size}</option>`\n )}\n </select>\n </label>\n `;\n }\n\n protected renderInfo() {\n const { page, pageSize, totalItems } = this.controller.state;\n if (totalItems === 0) {\n return html`<span part=\"paginator-info\" aria-live=\"polite\"\n >${this.state.localize('pagination.summaryEmpty')}</span\n >`;\n }\n const start = page * pageSize + 1;\n const end = Math.min(totalItems, (page + 1) * pageSize);\n return html`<span part=\"paginator-info\" aria-live=\"polite\"\n >${this.state.localize('pagination.summary', { start, end, total: totalItems })}</span\n >`;\n }\n\n protected renderButton(opts: {\n id: string;\n icon: string;\n label: string;\n disabled: boolean;\n onClick: () => void;\n }) {\n return html`<button\n part=\"paginator-button\"\n id=${opts.id}\n type=\"button\"\n aria-label=${opts.label}\n title=${opts.label}\n ?disabled=${opts.disabled}\n @click=${opts.onClick}\n >\n ${renderIcon(opts.icon)}\n </button>`;\n }\n\n #handleControlsKeydown = (event: KeyboardEvent) => {\n // Keep arrow-key navigation inside the paginator instead of bubbling into the grid.\n if (\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowRight' ||\n event.key === 'ArrowUp' ||\n event.key === 'ArrowDown'\n ) {\n event.stopPropagation();\n }\n };\n\n protected renderControls() {\n const { page, pageCount, totalItems } = this.controller.state;\n const onFirst = page <= 0 || totalItems === 0;\n const onLast = page >= pageCount - 1 || totalItems === 0;\n\n return html`\n <div\n part=\"paginator-controls\"\n role=\"group\"\n aria-label=${this.state.localize('pagination.controls')}\n @keydown=${this.#handleControlsKeydown}\n >\n ${this.renderButton({\n id: 'first',\n icon: 'page-first',\n label: this.state.localize('pagination.firstPage'),\n disabled: onFirst,\n onClick: () => this.controller.firstPage(),\n })}\n ${this.renderButton({\n id: 'previous',\n icon: 'page-previous',\n label: this.state.localize('pagination.previousPage'),\n disabled: onFirst,\n onClick: () => this.controller.previousPage(),\n })}\n <span part=\"paginator-page\" aria-live=\"polite\">${page + 1} / ${pageCount}</span>\n ${this.renderButton({\n id: 'next',\n icon: 'page-next',\n label: this.state.localize('pagination.nextPage'),\n disabled: onLast,\n onClick: () => this.controller.nextPage(),\n })}\n ${this.renderButton({\n id: 'last',\n icon: 'page-last',\n label: this.state.localize('pagination.lastPage'),\n disabled: onLast,\n onClick: () => this.controller.lastPage(),\n })}\n </div>\n `;\n }\n\n protected override render() {\n if (!this.state) return nothing;\n return html`\n <div part=\"paginator\" role=\"navigation\" aria-label=${this.state.localize('pagination.label')}>\n ${this.renderSizeSelect()} ${this.renderInfo()} ${this.renderControls()}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexGridPaginator.tagName]: ApexGridPaginator<object>;\n }\n}\n"]}
@@ -23,6 +23,12 @@ export default class ApexGridRow<T extends object> extends LitElement {
23
23
  selected: boolean;
24
24
  /** Reflects current expansion state so SCSS can rotate the chevron. */
25
25
  expanded: boolean;
26
+ /** Reflects pointer-drag state (row reorder) so SCSS can dim the source. */
27
+ dragging: boolean;
28
+ /** Reflects keyboard-grab state (row reorder) so SCSS can outline the row. */
29
+ grabbed: boolean;
30
+ /** Reveal the spreadsheet row-number gutter cell (transient formula coordinate hint). */
31
+ coordinateHints: boolean;
26
32
  /** The column key currently being edited in this row, or `null`. */
27
33
  editingKey: Keys<T> | null;
28
34
  /**
@@ -31,13 +37,35 @@ export default class ApexGridRow<T extends object> extends LitElement {
31
37
  * for the community grid.
32
38
  */
33
39
  decorationVersion: number;
40
+ /**
41
+ * Reactive token from {@link EditingController.validationVersion}, forwarded to
42
+ * each cell so a validation-only change re-renders the row's cells (toggling
43
+ * `aria-invalid` and the inline error node). Stays `0` until the first
44
+ * validation failure.
45
+ */
46
+ validationVersion: number;
34
47
  connectedCallback(): void;
48
+ disconnectedCallback(): void;
35
49
  /**
36
50
  * The number of "chrome" rows (header + filter) above the body. Used to
37
51
  * derive `aria-rowindex` from {@link index}. Set by the parent grid.
38
52
  */
39
53
  ariaRowOffset: number;
40
54
  protected willUpdate(): void;
55
+ /**
56
+ * Leading row-number gutter cell (transient spreadsheet coordinate hint). Shown
57
+ * only while `coordinateHints` is on; pinned rows render an empty spacer (their
58
+ * band-local index is not a meaningful A1 row number) so the track stays
59
+ * aligned. Presentational: the accessible row index is `aria-rowindex`.
60
+ */
61
+ protected renderRowNumber(): import("lit-html").TemplateResult<1> | typeof nothing;
62
+ /**
63
+ * Leading drag-handle (grip) cell. Rendered only in handle mode; pinned rows
64
+ * get an empty spacer so the grid track stays aligned. The cell is
65
+ * presentational (`aria-hidden`) — the accessible reorder path is the keyboard
66
+ * grab flow, not this pointer affordance.
67
+ */
68
+ protected renderReorderHandle(): import("lit-html").TemplateResult<1> | typeof nothing;
41
69
  protected renderExpansionToggle(colindex: number): import("lit-html").TemplateResult<1> | typeof nothing;
42
70
  protected renderDetailPanel(): import("lit-html").TemplateResult<1> | typeof nothing;
43
71
  protected renderSelectionCell(colindex: number): import("lit-html").TemplateResult<1> | typeof nothing;