apex-grid 3.5.0 → 4.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/CHANGELOG.md +573 -0
  2. package/LICENSE.md +125 -0
  3. package/README.md +143 -23
  4. package/components/cell.d.ts +43 -5
  5. package/components/cell.js +225 -64
  6. package/components/cell.js.map +1 -1
  7. package/components/filter-row.d.ts +2 -0
  8. package/components/filter-row.js +82 -28
  9. package/components/filter-row.js.map +1 -1
  10. package/components/grid.d.ts +281 -49
  11. package/components/grid.js +600 -159
  12. package/components/grid.js.map +1 -1
  13. package/components/group-header-row.js +28 -25
  14. package/components/group-header-row.js.map +1 -1
  15. package/components/header-row.d.ts +6 -10
  16. package/components/header-row.js +12 -28
  17. package/components/header-row.js.map +1 -1
  18. package/components/header.js +71 -22
  19. package/components/header.js.map +1 -1
  20. package/components/paginator.d.ts +20 -5
  21. package/components/paginator.js +54 -17
  22. package/components/paginator.js.map +1 -1
  23. package/components/row.d.ts +19 -3
  24. package/components/row.js +211 -56
  25. package/components/row.js.map +1 -1
  26. package/components/toolbar.d.ts +5 -1
  27. package/components/toolbar.js +6 -2
  28. package/components/toolbar.js.map +1 -1
  29. package/components/virtualize-rows.d.ts +38 -0
  30. package/components/virtualize-rows.js +286 -0
  31. package/components/virtualize-rows.js.map +1 -0
  32. package/components/virtualizer.d.ts +111 -1
  33. package/components/virtualizer.js +192 -5
  34. package/components/virtualizer.js.map +1 -1
  35. package/controllers/dom.d.ts +14 -7
  36. package/controllers/dom.js +45 -27
  37. package/controllers/dom.js.map +1 -1
  38. package/controllers/editing.d.ts +104 -37
  39. package/controllers/editing.js +230 -78
  40. package/controllers/editing.js.map +1 -1
  41. package/controllers/expansion.d.ts +14 -5
  42. package/controllers/expansion.js +24 -1
  43. package/controllers/expansion.js.map +1 -1
  44. package/controllers/filter.d.ts +10 -2
  45. package/controllers/filter.js +62 -17
  46. package/controllers/filter.js.map +1 -1
  47. package/controllers/history.d.ts +45 -8
  48. package/controllers/history.js +58 -20
  49. package/controllers/history.js.map +1 -1
  50. package/controllers/navigation.d.ts +130 -13
  51. package/controllers/navigation.js +474 -60
  52. package/controllers/navigation.js.map +1 -1
  53. package/controllers/pagination.d.ts +13 -6
  54. package/controllers/pagination.js +29 -22
  55. package/controllers/pagination.js.map +1 -1
  56. package/controllers/reorder.js +38 -22
  57. package/controllers/reorder.js.map +1 -1
  58. package/controllers/resize.d.ts +17 -2
  59. package/controllers/resize.js +16 -6
  60. package/controllers/resize.js.map +1 -1
  61. package/controllers/row-pin.d.ts +26 -2
  62. package/controllers/row-pin.js +24 -11
  63. package/controllers/row-pin.js.map +1 -1
  64. package/controllers/row-reorder.d.ts +40 -12
  65. package/controllers/row-reorder.js +137 -43
  66. package/controllers/row-reorder.js.map +1 -1
  67. package/controllers/selection.d.ts +33 -4
  68. package/controllers/selection.js +49 -11
  69. package/controllers/selection.js.map +1 -1
  70. package/controllers/sort.d.ts +22 -2
  71. package/controllers/sort.js +30 -25
  72. package/controllers/sort.js.map +1 -1
  73. package/controllers/state.d.ts +74 -7
  74. package/controllers/state.js +117 -36
  75. package/controllers/state.js.map +1 -1
  76. package/controllers/tree.d.ts +15 -10
  77. package/controllers/tree.js +0 -0
  78. package/controllers/tree.js.map +1 -1
  79. package/custom-elements.json +5091 -1023
  80. package/docs/assets/hierarchy.js +1 -1
  81. package/docs/assets/highlight.css +15 -8
  82. package/docs/assets/navigation.js +1 -1
  83. package/docs/assets/search.js +1 -1
  84. package/docs/classes/ApexGrid.html +233 -87
  85. package/docs/classes/ApexGridPaginator.html +39 -8
  86. package/docs/classes/ApexGridToolbar.html +11 -7
  87. package/docs/functions/localize.html +2 -2
  88. package/docs/hierarchy.html +1 -1
  89. package/docs/index.html +159 -26
  90. package/docs/interfaces/ApexCellValidationFailedEvent.html +3 -2
  91. package/docs/interfaces/ApexCellValueChangedEvent.html +4 -2
  92. package/docs/interfaces/ApexCellValueChangingEvent.html +3 -2
  93. package/docs/interfaces/ApexGridEventMap.html +5 -2
  94. package/docs/interfaces/ApexPageChangedEvent.html +3 -1
  95. package/docs/interfaces/ApexRowEditEndedEvent.html +2 -1
  96. package/docs/interfaces/ApexRowEditStartedEvent.html +2 -1
  97. package/docs/interfaces/ApexRowMovingEvent.html +9 -3
  98. package/docs/interfaces/ApexRowPinningEvent.html +1 -1
  99. package/docs/interfaces/ApexTreeRowExpandedEvent.html +4 -1
  100. package/docs/interfaces/ApexTreeRowExpandingEvent.html +4 -1
  101. package/docs/interfaces/BaseApexCellContext.html +18 -5
  102. package/docs/interfaces/BaseApexEditorContext.html +20 -5
  103. package/docs/interfaces/BaseFilterExpression.html +3 -3
  104. package/docs/interfaces/CSVExportOptions.html +12 -4
  105. package/docs/interfaces/DataPipelineConfiguration.html +4 -9
  106. package/docs/interfaces/ExportOptions.html +5 -3
  107. package/docs/interfaces/GridExpansionConfiguration.html +6 -2
  108. package/docs/interfaces/GridRowReorderingConfiguration.html +1 -1
  109. package/docs/interfaces/GridSelectionConfiguration.html +19 -4
  110. package/docs/interfaces/PaginationConfiguration.html +11 -4
  111. package/docs/interfaces/PaginationState.html +4 -2
  112. package/docs/interfaces/SetStateResult.html +3 -2
  113. package/docs/interfaces/ValidatorContext.html +7 -2
  114. package/docs/media/_token-values.scss +118 -0
  115. package/docs/media/package.json +9 -5
  116. package/docs/modules.html +1 -1
  117. package/docs/types/DataPipelineParams.html +2 -2
  118. package/docs/types/ExportSource.html +6 -4
  119. package/docs/types/OperandKeys.html +9 -0
  120. package/docs/types/PaginationMode.html +5 -4
  121. package/docs/variables/EN_LOCALE.html +2 -2
  122. package/i18n/en.d.ts +7 -0
  123. package/i18n/en.js +7 -0
  124. package/i18n/en.js.map +1 -1
  125. package/i18n/es.js +7 -0
  126. package/i18n/es.js.map +1 -1
  127. package/internal/column-types.d.ts +38 -2
  128. package/internal/column-types.js +83 -55
  129. package/internal/column-types.js.map +1 -1
  130. package/internal/constants.d.ts +1 -2
  131. package/internal/constants.js +0 -4
  132. package/internal/constants.js.map +1 -1
  133. package/internal/document-styles.d.ts +30 -0
  134. package/internal/document-styles.js +48 -0
  135. package/internal/document-styles.js.map +1 -0
  136. package/internal/export.d.ts +45 -7
  137. package/internal/export.js +39 -34
  138. package/internal/export.js.map +1 -1
  139. package/internal/feature-module.d.ts +67 -3
  140. package/internal/feature-module.js +6 -0
  141. package/internal/feature-module.js.map +1 -1
  142. package/internal/flip.d.ts +28 -16
  143. package/internal/flip.js +42 -10
  144. package/internal/flip.js.map +1 -1
  145. package/internal/index.d.ts +7 -5
  146. package/internal/index.js +6 -4
  147. package/internal/index.js.map +1 -1
  148. package/internal/normalize-case.d.ts +8 -1
  149. package/internal/normalize-case.js +3 -2
  150. package/internal/normalize-case.js.map +1 -1
  151. package/internal/state-snapshot.d.ts +60 -8
  152. package/internal/state-snapshot.js +87 -19
  153. package/internal/state-snapshot.js.map +1 -1
  154. package/internal/types.d.ts +92 -21
  155. package/internal/types.js.map +1 -1
  156. package/internal/utils.d.ts +34 -6
  157. package/internal/utils.js +30 -21
  158. package/internal/utils.js.map +1 -1
  159. package/internal/validators.js +1 -0
  160. package/internal/validators.js.map +1 -1
  161. package/operations/filter/operands/number.js +9 -6
  162. package/operations/filter/operands/number.js.map +1 -1
  163. package/operations/filter/operands/string.js +2 -3
  164. package/operations/filter/operands/string.js.map +1 -1
  165. package/operations/filter/types.d.ts +14 -2
  166. package/operations/filter/types.js.map +1 -1
  167. package/operations/filter.d.ts +6 -0
  168. package/operations/filter.js +23 -7
  169. package/operations/filter.js.map +1 -1
  170. package/operations/quick-filter.js +2 -5
  171. package/operations/quick-filter.js.map +1 -1
  172. package/operations/sort.d.ts +21 -2
  173. package/operations/sort.js +41 -14
  174. package/operations/sort.js.map +1 -1
  175. package/package.json +9 -4
  176. package/setup.d.ts +11 -0
  177. package/setup.js +9 -19
  178. package/setup.js.map +1 -1
  179. package/styles/_token-values.css.d.ts +1 -0
  180. package/styles/_token-values.css.js +3 -0
  181. package/styles/_token-values.css.js.map +1 -0
  182. package/styles/_tokens.css.js +1 -1
  183. package/styles/_tokens.css.js.map +1 -1
  184. package/styles/body-cell/body-cell.css.js +1 -1
  185. package/styles/body-cell/body-cell.css.js.map +1 -1
  186. package/styles/body-cell/cell-renderers.css.js +1 -1
  187. package/styles/body-cell/cell-renderers.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/document-tokens.css.d.ts +1 -0
  191. package/styles/document-tokens.css.js +3 -0
  192. package/styles/document-tokens.css.js.map +1 -0
  193. package/styles/filter-row/filter-row.css.js +1 -1
  194. package/styles/filter-row/filter-row.css.js.map +1 -1
  195. package/styles/grid/_grid.base.css.js +1 -1
  196. package/styles/grid/_grid.base.css.js.map +1 -1
  197. package/styles/grid/grid.css.js +1 -1
  198. package/styles/grid/grid.css.js.map +1 -1
  199. package/styles/group-header-row/group-header-row.css.js +1 -1
  200. package/styles/group-header-row/group-header-row.css.js.map +1 -1
  201. package/styles/header-cell/header-cell.css.js +1 -1
  202. package/styles/header-cell/header-cell.css.js.map +1 -1
  203. package/styles/header-row/header-row.base.css.js +1 -1
  204. package/styles/header-row/header-row.base.css.js.map +1 -1
  205. package/styles/paginator/paginator.css.js +1 -1
  206. package/styles/paginator/paginator.css.js.map +1 -1
  207. package/styles/toolbar/toolbar.css.js +1 -1
  208. package/styles/toolbar/toolbar.css.js.map +1 -1
  209. package/tokens.css +78 -0
  210. package/LICENSE +0 -80
  211. package/docs/media/LICENSE +0 -80
  212. package/docs/media/_tokens.scss +0 -214
  213. package/operations/pagination.d.ts +0 -19
  214. package/operations/pagination.js +0 -12
  215. package/operations/pagination.js.map +0 -1
@@ -4,14 +4,13 @@ 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;
8
7
  import { consume } from '@lit/context';
9
8
  import { html, LitElement } from 'lit';
10
9
  import { property, query } from 'lit/decorators.js';
11
10
  import { gridStateContext } from '../controllers/state.js';
12
11
  import { getColumnTypeRenderer } from '../internal/column-types.js';
13
12
  import { registerComponent } from '../internal/register.js';
14
- import { GRID_CELL_TAG } from '../internal/tags.js';
13
+ import { GRID_CELL_TAG, GRID_ROW_TAG } from '../internal/tags.js';
15
14
  import { styles } from '../styles/body-cell/body-cell.css.js';
16
15
  function isErrorLike(value) {
17
16
  return (typeof value === 'object' &&
@@ -19,16 +18,65 @@ function isErrorLike(value) {
19
18
  typeof value.code === 'string' &&
20
19
  value.code.startsWith('#'));
21
20
  }
22
- class ApexGridCell extends LitElement {
21
+ function renderedRows(body) {
22
+ if (!body)
23
+ return [];
24
+ return Array.from(body.children).filter((element) => element.localName === GRID_ROW_TAG);
25
+ }
26
+ function tabTarget(count, from, keys, key, step, isFullWidth) {
27
+ const column = keys[keys.indexOf(key) + step];
28
+ if (column !== undefined)
29
+ return { row: from, column };
30
+ const wrapColumn = keys[step > 0 ? 0 : keys.length - 1];
31
+ for (let index = from + step; index >= 0 && index < count; index += step) {
32
+ if (!isFullWidth(index))
33
+ return { row: index, column: wrapColumn };
34
+ }
35
+ return null;
36
+ }
37
+ function nearestCellRow(count, start, step, isFullWidth) {
38
+ const origin = Math.min(Math.max(start, 0), count - 1);
39
+ for (let distance = 0; distance < count; distance++) {
40
+ for (const index of [origin + distance * step, origin - distance * step]) {
41
+ if (index >= 0 && index < count && !isFullWidth(index))
42
+ return index;
43
+ }
44
+ }
45
+ return -1;
46
+ }
47
+ function findRenderedCell(body, node) {
48
+ return renderedRows(body)
49
+ .find((row) => row.index === node.row)
50
+ ?.cells.find((cell) => cell.column.key === node.column);
51
+ }
52
+ function scrollRowIntoRange(scroller, body, index) {
53
+ const rows = renderedRows(body).sort((a, b) => a.index - b.index);
54
+ const first = rows.at(0);
55
+ const last = rows.at(-1);
56
+ if (!first || !last)
57
+ return;
58
+ const top = first.getBoundingClientRect().top;
59
+ const height = (last.getBoundingClientRect().bottom - top) / (last.index - first.index + 1);
60
+ const view = scroller.getBoundingClientRect();
61
+ const rowCentre = top + (index - first.index + 0.5) * height;
62
+ scroller.scrollTop += rowCentre - (view.top + scroller.clientHeight / 2);
63
+ }
64
+ export default class ApexGridCell extends LitElement {
23
65
  constructor() {
24
66
  super(...arguments);
25
67
  this.active = false;
26
68
  this.editing = false;
27
69
  this.colindex = 0;
70
+ this.rowIndex = -1;
28
71
  this.decorationVersion = 0;
72
+ this.dataVersion = 0;
29
73
  this.validationVersion = 0;
30
74
  this.#decoratedKeys = [];
31
75
  this.#errors = null;
76
+ this.#staged = false;
77
+ this.#resumed = null;
78
+ this.#reconnected = false;
79
+ this.#rebound = false;
32
80
  this.#handleClick = (event) => {
33
81
  if (this.isEditing) {
34
82
  event.stopPropagation();
@@ -56,9 +104,7 @@ class ApexGridCell extends LitElement {
56
104
  this.#startEdit();
57
105
  };
58
106
  this.#refocusAfterEdit = false;
59
- this.#commitWith = async (value) => {
60
- return this.editingController.commitCell(value ?? this.#pendingValue);
61
- };
107
+ this.#commit = () => this.editingController.commitCell();
62
108
  this.#cancel = () => {
63
109
  this.editingController.cancelCell();
64
110
  };
@@ -68,7 +114,7 @@ class ApexGridCell extends LitElement {
68
114
  case 'Enter':
69
115
  event.preventDefault();
70
116
  this.#refocusAfterEdit = true;
71
- this.#commitWith();
117
+ this.#commit();
72
118
  return;
73
119
  case 'Escape':
74
120
  event.preventDefault();
@@ -76,24 +122,12 @@ class ApexGridCell extends LitElement {
76
122
  this.#cancel();
77
123
  return;
78
124
  case 'Tab':
79
- event.preventDefault();
80
- this.#refocusAfterEdit = true;
81
- this.#commitWith();
125
+ this.#commitAndTab(event);
82
126
  return;
83
127
  default:
84
128
  return;
85
129
  }
86
130
  };
87
- this.#handleBlur = () => {
88
- if (!this.isEditing)
89
- return;
90
- if (this.editingController.mode === 'cell') {
91
- this.#commitWith();
92
- }
93
- else {
94
- this.editingController.commitCell(this.#pendingValue);
95
- }
96
- };
97
131
  this.#handleCellKeydown = (event) => {
98
132
  if (!this.isEditing)
99
133
  return;
@@ -103,11 +137,8 @@ class ApexGridCell extends LitElement {
103
137
  this.#cancel();
104
138
  return;
105
139
  }
106
- if (event.key === 'Tab') {
107
- event.preventDefault();
108
- this.#refocusAfterEdit = true;
109
- this.#commitWith();
110
- }
140
+ if (event.key === 'Tab')
141
+ this.#commitAndTab(event);
111
142
  };
112
143
  this.#handleCellFocusOut = (event) => {
113
144
  if (!this.isEditing)
@@ -115,26 +146,23 @@ class ApexGridCell extends LitElement {
115
146
  const next = event.relatedTarget;
116
147
  if (next && (this.contains(next) || this.shadowRoot?.contains(next)))
117
148
  return;
118
- if (this.editingController.mode === 'cell') {
119
- this.#commitWith();
120
- }
121
- else {
122
- this.editingController.commitCell(this.#pendingValue);
123
- }
149
+ this.#refocusAfterEdit = false;
150
+ this.#commit();
124
151
  };
125
152
  this.#handleTextInput = (event) => {
126
153
  const target = event.target;
127
- if (this.column.type === 'number') {
154
+ if (this.#isNumeric) {
128
155
  const numeric = target.valueAsNumber;
129
- this.#pendingValue = target.value === '' || Number.isNaN(numeric) ? null : numeric;
156
+ this.editingController.setDraft(target.value === '' || Number.isNaN(numeric) ? null : numeric);
130
157
  return;
131
158
  }
132
- this.#pendingValue = target.value;
159
+ this.editingController.setDraft(target.value);
133
160
  };
134
- this.#handleCheckboxChange = (event) => {
161
+ this.#handleCheckboxChange = async (event) => {
135
162
  const target = event.target;
136
- this.#pendingValue = target.checked;
137
- this.#commitWith(target.checked);
163
+ if (!(await this.editingController.commitCell(target.checked))) {
164
+ target.checked = !target.checked;
165
+ }
138
166
  };
139
167
  }
140
168
  static get tagName() {
@@ -142,17 +170,20 @@ class ApexGridCell extends LitElement {
142
170
  }
143
171
  static { this.styles = styles; }
144
172
  static register() {
145
- registerComponent(_a);
173
+ registerComponent(ApexGridCell);
146
174
  }
147
175
  get context() {
176
+ const data = this.row.data;
177
+ const key = this.column.key;
148
178
  const ctx = {
149
179
  parent: this,
150
180
  row: this.row,
151
181
  column: this.column,
152
182
  value: this.value,
183
+ data,
153
184
  };
154
185
  if (this.isEditable) {
155
- ctx.commit = (next) => this.editingController.commitImmediate(this.row.index, this.column.key, next);
186
+ ctx.commit = (next) => this.editingController.commitImmediate(data, key, next);
156
187
  }
157
188
  return ctx;
158
189
  }
@@ -167,10 +198,21 @@ class ApexGridCell extends LitElement {
167
198
  return false;
168
199
  return this.editingController.isEditable(this.column);
169
200
  }
201
+ get #inPinnedBand() {
202
+ const pin = this.state.rowPin;
203
+ return pin.hasPinnedRows && pin.enabled && pin.isPinned(this.row.data);
204
+ }
205
+ get #recycledBody() {
206
+ return Boolean(this.state.host.rowRecycling) && !this.#inPinnedBand;
207
+ }
170
208
  #decoratedKeys;
171
- static #ERROR_ID = 'apex-cell-error';
172
209
  #errors;
210
+ #staged;
211
+ #resumed;
212
+ #reconnected;
213
+ #rebound;
173
214
  connectedCallback() {
215
+ this.#reconnected = this.hasUpdated && !this.isUpdatePending;
174
216
  super.connectedCallback();
175
217
  this.setAttribute('role', 'gridcell');
176
218
  this.addEventListener('click', this.#handleClick);
@@ -185,7 +227,30 @@ class ApexGridCell extends LitElement {
185
227
  this.removeEventListener('focusout', this.#handleCellFocusOut);
186
228
  super.disconnectedCallback();
187
229
  }
188
- willUpdate() {
230
+ shouldUpdate(changed) {
231
+ const reconnected = this.#reconnected;
232
+ this.#reconnected = false;
233
+ if (!this.hasUpdated || (!changed.size && !reconnected))
234
+ return true;
235
+ const tree = this.state?.tree;
236
+ const readsRow = this.column.cellTemplate || (tree?.enabled && tree.isGroupColumn(this.column.key));
237
+ for (const key of changed.keys()) {
238
+ const token = key === 'rowIndex' || key === 'dataVersion';
239
+ if (key !== 'decorationVersion' && (readsRow || !token))
240
+ return true;
241
+ }
242
+ if (changed.has('decorationVersion') || changed.has('rowIndex'))
243
+ this.#applyDecoration();
244
+ return false;
245
+ }
246
+ willUpdate(changed) {
247
+ this.#rebound = this.hasUpdated && changed.has('record');
248
+ this.#applyStaged();
249
+ if (changed.has('editing') || this.#rebound) {
250
+ this.#resumed = this.editing
251
+ ? this.editingController.heldDraft(this.row.data, this.column.key)
252
+ : null;
253
+ }
189
254
  if (this.colindex > 0) {
190
255
  this.setAttribute('aria-colindex', String(this.colindex));
191
256
  }
@@ -210,6 +275,20 @@ class ApexGridCell extends LitElement {
210
275
  this.#applyValidation();
211
276
  this.#applyDecoration();
212
277
  }
278
+ #applyStaged() {
279
+ const staged = this.state?.editing?.activeRow
280
+ ? this.editingController.stagedValues(this.row.data)
281
+ : null;
282
+ const key = this.column.key;
283
+ if (staged?.has(key)) {
284
+ this.value = staged.get(key);
285
+ this.#staged = true;
286
+ }
287
+ else if (this.#staged) {
288
+ this.#staged = false;
289
+ this.value = this.row.data[key];
290
+ }
291
+ }
213
292
  #applyValidation() {
214
293
  const errors = this.state && this.row?.data
215
294
  ? (this.editingController?.getCellErrors(this.row.data, this.column.key) ?? null)
@@ -217,13 +296,11 @@ class ApexGridCell extends LitElement {
217
296
  this.#errors = errors && errors.length > 0 ? errors : null;
218
297
  if (this.#errors) {
219
298
  this.setAttribute('aria-invalid', 'true');
220
- this.setAttribute('aria-errormessage', _a.#ERROR_ID);
221
299
  this.setAttribute('data-invalid', '');
222
300
  this.setAttribute('title', this.#errors.join('; '));
223
301
  }
224
302
  else {
225
303
  this.removeAttribute('aria-invalid');
226
- this.removeAttribute('aria-errormessage');
227
304
  this.removeAttribute('data-invalid');
228
305
  this.removeAttribute('title');
229
306
  }
@@ -233,16 +310,17 @@ class ApexGridCell extends LitElement {
233
310
  return null;
234
311
  return html `<span
235
312
  part="cell-error"
236
- id=${_a.#ERROR_ID}
237
313
  role="alert"
238
314
  >${this.#errors.join('; ')}</span
239
315
  >`;
240
316
  }
241
317
  #applyDecoration() {
318
+ if (!this.state?.hasCellDecorators && !this.#decoratedKeys.length)
319
+ return;
242
320
  const decoration = this.state && this.row
243
321
  ? this.state.decorateCell({
244
322
  row: this.row.data,
245
- rowIndex: this.row.index,
323
+ rowIndex: this.#inPinnedBand ? -1 : this.rowIndex,
246
324
  column: this.column,
247
325
  value: this.value,
248
326
  })
@@ -266,9 +344,16 @@ class ApexGridCell extends LitElement {
266
344
  }
267
345
  updated(changed) {
268
346
  if (this.isEditing) {
347
+ if (!changed.has('editing'))
348
+ return;
269
349
  const editor = this.editorElement;
270
- editor?.focus();
271
- if (editor instanceof HTMLInputElement) {
350
+ const resumed = this.#resumed !== null || this.#rebound;
351
+ if (resumed && this.#recycledBody && !this.state.navigation.ownsFocus)
352
+ return;
353
+ if (resumed)
354
+ editor?.getBoundingClientRect();
355
+ editor?.focus(resumed ? { preventScroll: true } : undefined);
356
+ if (!resumed && editor instanceof HTMLInputElement) {
272
357
  if (editor.type === 'text' || editor.type === 'number') {
273
358
  editor.select();
274
359
  }
@@ -277,6 +362,8 @@ class ApexGridCell extends LitElement {
277
362
  }
278
363
  if (changed.get('editing') === true && this.#refocusAfterEdit) {
279
364
  this.#refocusAfterEdit = false;
365
+ if (this.#rebound && this.editingController.activeCell)
366
+ return;
280
367
  this.focus();
281
368
  }
282
369
  }
@@ -285,22 +372,94 @@ class ApexGridCell extends LitElement {
285
372
  #startEdit() {
286
373
  if (!this.row)
287
374
  return;
288
- this.editingController.editCell(this.row.index, this.column.key);
375
+ this.editingController.editRecord(this.row.data, this.column.key);
289
376
  }
290
- #pendingValue;
291
377
  #refocusAfterEdit;
292
- #commitWith;
378
+ #commit;
293
379
  #cancel;
380
+ #commitAndTab(event) {
381
+ event.preventDefault();
382
+ if (this.#inPinnedBand) {
383
+ this.#refocusAfterEdit = true;
384
+ void this.#commit();
385
+ return;
386
+ }
387
+ const step = event.shiftKey ? -1 : 1;
388
+ const host = this.state.host;
389
+ const body = this.row.parentElement;
390
+ const record = this.row.data;
391
+ const origin = this.row.index;
392
+ const key = this.column.key;
393
+ const columns = this.row.columns;
394
+ const keys = this.row.cells.map((cell) => cell.column.key);
395
+ const settle = async () => {
396
+ await host.updateComplete;
397
+ await body?.updateComplete;
398
+ await Promise.all(renderedRows(body).map((row) => row.updateComplete));
399
+ };
400
+ void this.#commit().then(async (committed) => {
401
+ if (!committed)
402
+ return;
403
+ await settle();
404
+ const items = host.pageItems;
405
+ const isFullWidth = (index) => items[index] == null ||
406
+ this.state.presentRow(items[index], { columns, rowIndex: index }) !== null;
407
+ const from = items.indexOf(record);
408
+ let target;
409
+ if (from >= 0) {
410
+ target = tabTarget(items.length, from, keys, key, step, isFullWidth) ?? {
411
+ row: from,
412
+ column: key,
413
+ };
414
+ }
415
+ else {
416
+ const row = nearestCellRow(items.length, origin, step, isFullWidth);
417
+ target = row < 0 ? null : { row, column: key };
418
+ }
419
+ if (!target) {
420
+ body?.focus({ preventScroll: true });
421
+ return;
422
+ }
423
+ this.state.active = target;
424
+ await settle();
425
+ let cell = findRenderedCell(body, target);
426
+ for (let attempt = 0; !cell && attempt < 3; attempt++) {
427
+ scrollRowIntoRange(host, body, target.row);
428
+ await new Promise(requestAnimationFrame);
429
+ await new Promise(requestAnimationFrame);
430
+ await settle();
431
+ cell = findRenderedCell(body, target);
432
+ }
433
+ if (!cell) {
434
+ body?.focus({ preventScroll: true });
435
+ return;
436
+ }
437
+ cell.focus({ preventScroll: true });
438
+ cell.scrollIntoView({ block: 'nearest', inline: 'nearest' });
439
+ await new Promise(requestAnimationFrame);
440
+ await new Promise(requestAnimationFrame);
441
+ const active = this.state.active;
442
+ const dropped = !document.activeElement || document.activeElement === document.body;
443
+ if (dropped && active.row === target.row && active.column === target.column) {
444
+ findRenderedCell(body, target)?.focus({ preventScroll: true });
445
+ }
446
+ });
447
+ }
294
448
  #handleKeydown;
295
- #handleBlur;
296
449
  #handleCellKeydown;
297
450
  #handleCellFocusOut;
451
+ get #isNumeric() {
452
+ const type = this.column.type;
453
+ return type === 'number' || type === 'currency';
454
+ }
298
455
  #handleTextInput;
299
456
  #handleCheckboxChange;
457
+ get #editorValue() {
458
+ return this.#resumed ? this.#resumed.value : this.value;
459
+ }
300
460
  renderDefaultEditor() {
301
- const value = this.value;
461
+ const value = this.#editorValue;
302
462
  if (this.column.type === 'boolean') {
303
- this.#pendingValue = Boolean(value);
304
463
  return html `<input
305
464
  type="checkbox"
306
465
  part="editor"
@@ -308,11 +467,9 @@ class ApexGridCell extends LitElement {
308
467
  ?checked=${Boolean(value)}
309
468
  @change=${this.#handleCheckboxChange}
310
469
  @keydown=${this.#handleKeydown}
311
- @blur=${this.#handleBlur}
312
470
  />`;
313
471
  }
314
- if (this.column.type === 'number') {
315
- this.#pendingValue = value;
472
+ if (this.#isNumeric) {
316
473
  return html `<input
317
474
  type="number"
318
475
  part="editor"
@@ -320,10 +477,8 @@ class ApexGridCell extends LitElement {
320
477
  .value=${value == null ? '' : String(value)}
321
478
  @input=${this.#handleTextInput}
322
479
  @keydown=${this.#handleKeydown}
323
- @blur=${this.#handleBlur}
324
480
  />`;
325
481
  }
326
- this.#pendingValue = value;
327
482
  return html `<input
328
483
  type="text"
329
484
  part="editor"
@@ -331,7 +486,6 @@ class ApexGridCell extends LitElement {
331
486
  .value=${value == null ? '' : String(value)}
332
487
  @input=${this.#handleTextInput}
333
488
  @keydown=${this.#handleKeydown}
334
- @blur=${this.#handleBlur}
335
489
  />`;
336
490
  }
337
491
  renderEditor() {
@@ -340,17 +494,17 @@ class ApexGridCell extends LitElement {
340
494
  parent: this,
341
495
  row: this.row,
342
496
  column: this.column,
343
- value: this.value,
497
+ value: this.#editorValue,
498
+ data: this.row.data,
344
499
  commit: (next) => this.editingController.commitCell(next),
345
500
  cancel: () => this.editingController.cancelCell(),
501
+ setDraft: (next) => this.editingController.setDraft(next),
346
502
  };
347
503
  if (template) {
348
- this.#pendingValue = this.value;
349
504
  return template(ctx);
350
505
  }
351
506
  const typeRenderer = getColumnTypeRenderer(this.column.type);
352
507
  if (typeRenderer?.editor) {
353
- this.#pendingValue = this.value;
354
508
  return typeRenderer.editor(ctx);
355
509
  }
356
510
  return this.renderDefaultEditor();
@@ -446,11 +600,12 @@ class ApexGridCell extends LitElement {
446
600
  return html `${this.renderCellBody()}${error}`;
447
601
  }
448
602
  }
449
- _a = ApexGridCell;
450
- export default ApexGridCell;
451
603
  __decorate([
452
604
  property({ attribute: false })
453
605
  ], ApexGridCell.prototype, "value", void 0);
606
+ __decorate([
607
+ property({ attribute: false })
608
+ ], ApexGridCell.prototype, "record", void 0);
454
609
  __decorate([
455
610
  property({ attribute: false })
456
611
  ], ApexGridCell.prototype, "column", void 0);
@@ -470,9 +625,15 @@ __decorate([
470
625
  __decorate([
471
626
  property({ attribute: false, type: Number })
472
627
  ], ApexGridCell.prototype, "colindex", void 0);
628
+ __decorate([
629
+ property({ attribute: false })
630
+ ], ApexGridCell.prototype, "rowIndex", void 0);
473
631
  __decorate([
474
632
  property({ attribute: false, type: Number })
475
633
  ], ApexGridCell.prototype, "decorationVersion", void 0);
634
+ __decorate([
635
+ property({ attribute: false })
636
+ ], ApexGridCell.prototype, "dataVersion", void 0);
476
637
  __decorate([
477
638
  property({ attribute: false, type: Number })
478
639
  ], ApexGridCell.prototype, "validationVersion", void 0);