lightning-base-components 1.14.6-alpha → 1.14.7-alpha

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 (115) hide show
  1. package/metadata/raptor.json +5 -3
  2. package/package.json +8 -1
  3. package/scopedImports/@salesforce-label-LightningProgressBar.progressBar.js +1 -0
  4. package/src/lightning/alert/__docs__/alert.md +101 -0
  5. package/src/lightning/alert/__examples__disabled/basic/basic.css +7 -0
  6. package/src/lightning/alert/__examples__disabled/basic/basic.html +8 -0
  7. package/src/lightning/alert/__examples__disabled/basic/basic.js +14 -0
  8. package/src/lightning/alert/alert.html +3 -0
  9. package/src/lightning/alert/alert.js +78 -0
  10. package/src/lightning/alert/alert.js-meta.xml +6 -0
  11. package/src/lightning/buttonMenu/buttonMenu.js +12 -0
  12. package/src/lightning/confirm/__docs__/confirm.md +100 -0
  13. package/src/lightning/confirm/__examples__disabled/basic/basic.css +7 -0
  14. package/src/lightning/confirm/__examples__disabled/basic/basic.html +8 -0
  15. package/src/lightning/confirm/__examples__disabled/basic/basic.js +14 -0
  16. package/src/lightning/confirm/confirm.html +3 -0
  17. package/src/lightning/confirm/confirm.js +80 -0
  18. package/src/lightning/confirm/confirm.js-meta.xml +6 -0
  19. package/src/lightning/datatable/columns.js +166 -71
  20. package/src/lightning/datatable/datatable.js +94 -20
  21. package/src/lightning/datatable/headerActions.js +2 -2
  22. package/src/lightning/datatable/keyboard.js +10 -10
  23. package/src/lightning/datatable/renderManager.js +45 -13
  24. package/src/lightning/datatable/resizeSensor.js +11 -3
  25. package/src/lightning/datatable/rowSelection.js +1 -1
  26. package/src/lightning/datatable/rowSelectionShared.js +33 -20
  27. package/src/lightning/datatable/rows.js +1 -2
  28. package/src/lightning/datatable/sort.js +8 -8
  29. package/src/lightning/datatable/state.js +8 -1
  30. package/src/lightning/datatable/tree.js +25 -0
  31. package/src/lightning/datatable/types.js +77 -9
  32. package/src/lightning/datatable/utils.js +51 -24
  33. package/src/lightning/datatable/virtualization.js +319 -0
  34. package/src/lightning/datatable/wrapText.js +53 -16
  35. package/src/lightning/iconSvgTemplates/buildTemplates/standard/dashboard_component.html +7 -0
  36. package/src/lightning/iconSvgTemplates/buildTemplates/standard/slack.html +7 -0
  37. package/src/lightning/iconSvgTemplates/buildTemplates/standard/tableau.html +7 -0
  38. package/src/lightning/iconSvgTemplates/buildTemplates/standard/travel_mode.html +2 -2
  39. package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +8 -1
  40. package/src/lightning/iconSvgTemplates/buildTemplates/utility/data_model.html +7 -0
  41. package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product.html +1 -1
  42. package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product_transaction.html +2 -1
  43. package/src/lightning/iconSvgTemplates/buildTemplates/utility/slack.html +7 -0
  44. package/src/lightning/iconSvgTemplates/buildTemplates/utility/tableau.html +7 -0
  45. package/src/lightning/iconSvgTemplates/buildTemplates/utility/video_off.html +7 -0
  46. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/dashboard_component.html +7 -0
  47. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/slack.html +7 -0
  48. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/tableau.html +7 -0
  49. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/travel_mode.html +2 -2
  50. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +8 -1
  51. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/data_model.html +7 -0
  52. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product.html +1 -1
  53. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
  54. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/slack.html +7 -0
  55. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/tableau.html +7 -0
  56. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/video_off.html +7 -0
  57. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/dashboard_component.html +7 -0
  58. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/slack.html +7 -0
  59. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/tableau.html +7 -0
  60. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/travel_mode.html +2 -2
  61. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/templates.js +4 -1
  62. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/dashboard_component.html +7 -0
  63. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/slack.html +7 -0
  64. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/tableau.html +7 -0
  65. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/travel_mode.html +2 -2
  66. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/templates.js +4 -1
  67. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +5 -1
  68. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/data_model.html +7 -0
  69. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product.html +1 -1
  70. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product_transaction.html +2 -1
  71. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/slack.html +7 -0
  72. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/tableau.html +7 -0
  73. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/video_off.html +7 -0
  74. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +5 -1
  75. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/data_model.html +7 -0
  76. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product.html +1 -1
  77. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
  78. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/slack.html +7 -0
  79. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/tableau.html +7 -0
  80. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/video_off.html +7 -0
  81. package/src/lightning/input/__docs__/input.md +2 -0
  82. package/src/lightning/interactiveDialogBase/interactiveDialogBase.css +494 -0
  83. package/src/lightning/interactiveDialogBase/interactiveDialogBase.html +63 -0
  84. package/src/lightning/interactiveDialogBase/interactiveDialogBase.js +200 -0
  85. package/src/lightning/menuItem/menuItem.js +4 -1
  86. package/src/lightning/modalBase/modalBase.css +20 -0
  87. package/src/lightning/modalBase/modalBase.html +54 -0
  88. package/src/lightning/modalBase/modalBase.js +1039 -0
  89. package/src/lightning/overlay/__docs__/overlay.md +90 -0
  90. package/src/lightning/overlay/__examples__/alert/alert.html +27 -0
  91. package/src/lightning/overlay/__examples__/alert/alert.js +33 -0
  92. package/src/lightning/overlay/__examples__/basic/basic.css +7 -0
  93. package/src/lightning/overlay/__examples__/basic/basic.html +18 -0
  94. package/src/lightning/overlay/__examples__/basic/basic.js +61 -0
  95. package/src/lightning/overlay/__examples__/demo/demo.html +29 -0
  96. package/src/lightning/overlay/__examples__/demo/demo.js +40 -0
  97. package/src/lightning/overlay/__examples__/panel/panel.html +17 -0
  98. package/src/lightning/overlay/__examples__/panel/panel.js +21 -0
  99. package/src/lightning/overlay/overlay.html +3 -0
  100. package/src/lightning/overlay/overlay.js +45 -0
  101. package/src/lightning/overlayContainer/__docs__/overlayContainer.md +0 -0
  102. package/src/lightning/overlayContainer/overlayContainer.html +3 -0
  103. package/src/lightning/overlayContainer/overlayContainer.js +138 -0
  104. package/src/lightning/overlayManager/overlayManager.js +54 -0
  105. package/src/lightning/overlayUtils/overlayUtils.js +17 -0
  106. package/src/lightning/progressBar/progressBar.html +2 -1
  107. package/src/lightning/progressBar/progressBar.js +18 -1
  108. package/src/lightning/prompt/__docs__/prompt.md +102 -0
  109. package/src/lightning/prompt/__examples__disabled/basic/basic.css +7 -0
  110. package/src/lightning/prompt/__examples__disabled/basic/basic.html +8 -0
  111. package/src/lightning/prompt/__examples__disabled/basic/basic.js +15 -0
  112. package/src/lightning/prompt/prompt.css +81 -0
  113. package/src/lightning/prompt/prompt.html +8 -0
  114. package/src/lightning/prompt/prompt.js +92 -0
  115. package/src/lightning/prompt/prompt.js-meta.xml +6 -0
@@ -13,33 +13,62 @@ const i18n = {
13
13
  rowActionsDefaultAriaLabel,
14
14
  };
15
15
 
16
+ export const SELECTABLE_ROW_CHECKBOX = 'SELECTABLE_CHECKBOX';
17
+
18
+ const SELECTABLE_COLUMN = {
19
+ type: SELECTABLE_ROW_CHECKBOX,
20
+ fixedWidth: 32,
21
+ tabIndex: -1,
22
+ internal: true,
23
+ };
24
+
25
+ /**
26
+ * Returns the columns default state.
27
+ *
28
+ * @returns {Object} The default column state.
29
+ */
16
30
  export function getColumnsDefaultState() {
17
31
  return {
18
32
  columns: [],
19
33
  };
20
34
  }
21
35
 
36
+ /**
37
+ * Returns whether or not the datatable has columns.
38
+ *
39
+ * @param {Object} state The datatable's state.
40
+ * @returns {Boolean} Whether the datatable has columns.
41
+ */
22
42
  export function hasColumns(state) {
23
43
  return getColumns(state).length > 0;
24
44
  }
25
45
 
46
+ /**
47
+ * Returns whether or not the column has been specified by the customer.
48
+ *
49
+ * @param {Object} column The column definition object.
50
+ * @returns {Boolean} Whether the column is customer defined or not.
51
+ */
26
52
  export function isCustomerColumn(column) {
27
53
  return column.internal !== true;
28
54
  }
29
55
 
56
+ /**
57
+ * Returns the datatable's columns from state.
58
+ *
59
+ * @param {Object} state The datatable's state.
60
+ * @returns {Array} The datatable's columns definition.
61
+ */
30
62
  export function getColumns(state) {
31
63
  return state.columns;
32
64
  }
33
65
 
34
- export const SELECTABLE_ROW_CHECKBOX = 'SELECTABLE_CHECKBOX';
35
-
36
- const SELECTABLE_COLUMN = {
37
- type: SELECTABLE_ROW_CHECKBOX,
38
- fixedWidth: 32,
39
- tabIndex: -1,
40
- internal: true,
41
- };
42
-
66
+ /**
67
+ * Returns whether any of the datatable's columns are editable.
68
+ *
69
+ * @param {Array} columns The datatable's column definition.
70
+ * @returns {Boolean} Whether any of the columns are editable.
71
+ */
43
72
  export function hasEditableColumn(columns) {
44
73
  return columns.some((column) => column.editable);
45
74
  }
@@ -50,8 +79,8 @@ export function hasEditableColumn(columns) {
50
79
  * that are present in both the input and output array, the relative ordering between
51
80
  * them that existed in the input array is maintained in the output array.
52
81
  *
53
- * @param {Array} columns - the datatable's column definitions. Must be truthy and must be
54
- * filled with truthy column definition objects.
82
+ * @param {Array} columns The datatable's column definition. Must be truthy and must be
83
+ * filled with truthy column definition objects.
55
84
  */
56
85
  export function getEditableColumns(columns) {
57
86
  return columns.filter((column) => column.editable);
@@ -64,8 +93,8 @@ export function getEditableColumns(columns) {
64
93
  * the invocation of this function results in a no-op because we instead rely on later
65
94
  * row level checks to determine cell editability.
66
95
  *
67
- * @param {Object} column column metadata
68
- * @param {Object} types the DatatableTypes object
96
+ * @param {Object} column The column definition object.
97
+ * @param {Object} types The DatatableTypes object.
69
98
  */
70
99
  export function normalizeEditable(column, types) {
71
100
  if (types.isEditableType(column.type)) {
@@ -81,10 +110,24 @@ export function normalizeEditable(column, types) {
81
110
  }
82
111
  }
83
112
 
113
+ /**
114
+ * Steps through and corrects column definitions inconsistencies.
115
+ *
116
+ * For customer-specified columns, we verify all parameters are valid and set
117
+ * how we would expect them to prevent errors from bubbling up.
118
+ * See `normalizeColumnDataType`, `normalizeEditable`.
119
+ *
120
+ * For tree-types, we verify all sub-type attributes are within our allowed
121
+ * parameters. See `getNormalizedSubTypeAttribute`.
122
+ *
123
+ * @param {Object} state The datatable state.
124
+ * @param {Array} columns The datatable's column definitions.
125
+ * @param {Object} types The type handling factory.
126
+ */
84
127
  export function normalizeColumns(state, columns, types) {
85
128
  if (columns.length !== 0) {
86
129
  let firstColumnForReaders = 0;
87
- // workaround https://git.soma.salesforce.com/raptor/raptor/issues/763
130
+ // Workaround: https://git.soma.salesforce.com/raptor/raptor/issues/763
88
131
  const normalizedColumns = Object.assign([], columns);
89
132
 
90
133
  if (!state.hideCheckboxColumn) {
@@ -100,7 +143,7 @@ export function normalizeColumns(state, columns, types) {
100
143
 
101
144
  const columnKeyMap = {};
102
145
  state.columns = normalizedColumns.map((column, index) => {
103
- // Verify columnKey is unique
146
+ // Verify `columnKey` is unique
104
147
  const columnKey = column.columnKey;
105
148
  if (columnKey && columnKeyMap[columnKey]) {
106
149
  console.error(
@@ -115,7 +158,8 @@ export function normalizeColumns(state, columns, types) {
115
158
  );
116
159
  normalizedColumn.ariaLabel =
117
160
  normalizedColumn.label || normalizedColumn.ariaLabel || null;
118
- // customType attribute is needed to render default iedit component
161
+
162
+ // `customType` attribute is needed to render default iedit component
119
163
  normalizedColumn.editableCustomType =
120
164
  types.isStandardCellLayoutForCustomType(normalizedColumn.type);
121
165
 
@@ -131,6 +175,7 @@ export function normalizeColumns(state, columns, types) {
131
175
  normalizedColumn.typeAttributes
132
176
  );
133
177
  }
178
+
134
179
  return Object.assign(normalizedColumn, {
135
180
  tabIndex: -1,
136
181
  colKeyValue: generateColKeyValue(normalizedColumn, index),
@@ -142,17 +187,12 @@ export function normalizeColumns(state, columns, types) {
142
187
  }
143
188
  }
144
189
 
145
- function normalizeColumnDataType(column, types) {
146
- if (!types.isValidType(column.type)) {
147
- column.type = getRegularColumnDefaults().type;
148
- }
149
- }
150
-
151
190
  /**
152
191
  * Normalizes the subType and subTypeAttributes in the typeAttributes.
153
- * @param {String} type the type of this column
154
- * @param {Object} typeAttributes the type attributes of the column
155
- * @returns {Object} a new typeAttributes object with the sybtype and subTypeAttributes normalized.
192
+ *
193
+ * @param {String} type The type of this column
194
+ * @param {Object} typeAttributes The type attributes of the column
195
+ * @returns {Object} A new typeAttributes object with the sybtype and subTypeAttributes normalized.
156
196
  */
157
197
  export function getNormalizedSubTypeAttribute(type, typeAttributes) {
158
198
  const typeAttributesOverrides = {};
@@ -166,42 +206,12 @@ export function getNormalizedSubTypeAttribute(type, typeAttributes) {
166
206
  return Object.assign({}, typeAttributes, typeAttributesOverrides);
167
207
  }
168
208
 
169
- function getRegularColumnDefaults() {
170
- return {
171
- type: 'text',
172
- typeAttributes: {},
173
- cellAttributes: {},
174
- };
175
- }
176
-
177
- function getActionColumnDefaults() {
178
- return {
179
- fixedWidth: 50,
180
- resizable: false,
181
- ariaLabel: i18n.rowActionsDefaultAriaLabel,
182
- };
183
- }
184
-
185
- function getTreeColumnDefaults() {
186
- return {
187
- type: 'tree',
188
- subType: 'text',
189
- typeAttributes: {},
190
- cellAttributes: {},
191
- };
192
- }
193
-
194
- function getColumnDefaults(column) {
195
- switch (column.type) {
196
- case 'action':
197
- return getActionColumnDefaults();
198
- case 'tree':
199
- return getTreeColumnDefaults();
200
- default:
201
- return getRegularColumnDefaults();
202
- }
203
- }
204
-
209
+ /**
210
+ * Retrieves the type attributes for a given column.
211
+ *
212
+ * @param {Object} column The column definition object.
213
+ * @returns Type attributes for the given column, if they exist.
214
+ */
205
215
  export function getTypeAttributesValues(column) {
206
216
  if (isObjectLike(column.typeAttributes)) {
207
217
  return column.typeAttributes;
@@ -209,6 +219,12 @@ export function getTypeAttributesValues(column) {
209
219
  return {};
210
220
  }
211
221
 
222
+ /**
223
+ * Retrieves the sub-type attributes for a given column.
224
+ *
225
+ * @param {Object} column The column definition object.
226
+ * @returns {Object} Sub-type attributes for the given column, if they exist.
227
+ */
212
228
  export function getSubTypeAttributesValues(column) {
213
229
  if (isObjectLike(column.typeAttributes.subTypeAttributes)) {
214
230
  return column.typeAttributes.subTypeAttributes;
@@ -216,6 +232,12 @@ export function getSubTypeAttributesValues(column) {
216
232
  return {};
217
233
  }
218
234
 
235
+ /**
236
+ * Retrieves the cell attributes for a given column.
237
+ *
238
+ * @param {Object} column The column definition object.
239
+ * @returns {Object} Cell attributes for the given column, if they exist.
240
+ */
219
241
  export function getCellAttributesValues(column) {
220
242
  if (isObjectLike(column.cellAttributes)) {
221
243
  return column.cellAttributes;
@@ -226,9 +248,9 @@ export function getCellAttributesValues(column) {
226
248
  /**
227
249
  * Generates a unique column key value.
228
250
  *
229
- * @param {object} columnMetadata - the object for an specific column metadata
230
- * @param {int} index - optionally, the index of the column.
231
- * @returns {string} It generate the column key value based on the column field name and type.
251
+ * @param {Object} columnMetadata The object for an specific column metadata
252
+ * @param {Integer} index Optionally, the index of the column.
253
+ * @returns {String} It generates the column key value based on the column field name and type.
232
254
  */
233
255
  export function generateColKeyValue(columnMetadata, index) {
234
256
  const { columnKey, fieldName, type } = columnMetadata;
@@ -239,9 +261,10 @@ export function generateColKeyValue(columnMetadata, index) {
239
261
  /**
240
262
  * Return the index in dt.columns (user definition) related to colKeyValue.
241
263
  * -1 if no column with that key exist or if its internal.
264
+ *
242
265
  * @param {Object} state The datatable state
243
266
  * @param {String} colKeyValue The generated key for the column
244
- * @return {Number} The index in dt.columns. -1 if not found or if its internal.
267
+ * @returns {Number} The index in `dt.columns`. -1 if not found or if its internal.
245
268
  */
246
269
  export function getUserColumnIndex(state, colKeyValue) {
247
270
  const stateColumnIndex = getStateColumnIndex(state, colKeyValue);
@@ -267,8 +290,8 @@ export function getUserColumnIndex(state, colKeyValue) {
267
290
  *
268
291
  * These indexes are set in the state object - `state.headerIndexes`
269
292
  *
270
- * @param {object} columns - the current normalized column metadata
271
- * @returns {object} headerIndexes e.g. { 'name-text': 0, 'amount-number': 1 }
293
+ * @param {Object} columns The current normalized column metadata
294
+ * @returns {Object} headerIndexes e.g. { 'name-text': 0, 'amount-number': 1 }
272
295
  */
273
296
  export const generateHeaderIndexes = function (columns) {
274
297
  return columns.reduce((prev, col, index) => {
@@ -282,17 +305,18 @@ export const generateHeaderIndexes = function (columns) {
282
305
  *
283
306
  * @param {Object} state The datatable state
284
307
  * @param {String} colKeyValue The generated key for the column
285
- * @return {number} The index in state.columns.
308
+ * @returns {Number} The index in state.columns
286
309
  */
287
310
  export function getStateColumnIndex(state, colKeyValue) {
288
311
  return state.headerIndexes[colKeyValue];
289
312
  }
290
313
 
291
314
  /**
315
+ * Retrieves a column index number by its key.
292
316
  *
293
- * @param {Object} state - The datatable state
294
- * @param {String} key - the key of the column. Defaults to field name if 'columnKey' is not provided.
295
- * @returns {number} The index in state.columns, -1 if it does not exist
317
+ * @param {Object} state The datatable state
318
+ * @param {String} key The key of the column. Defaults to field name if 'columnKey' is not provided.
319
+ * @returns {Number} The index in state.columns, -1 if it does not exist
296
320
  */
297
321
  export function getColumnIndexByColumnKey(state, key) {
298
322
  let i = 0;
@@ -307,3 +331,74 @@ export function getColumnIndexByColumnKey(state, key) {
307
331
 
308
332
  return existFieldName ? i : -1;
309
333
  }
334
+
335
+ /************************** PRIVATE METHODS ***************************/
336
+
337
+ /**
338
+ * If the specified column type is not supported, resets it to default.
339
+ *
340
+ * @param {Object} column The column definition object.
341
+ * @param {Object} types The type handling factory.
342
+ */
343
+ function normalizeColumnDataType(column, types) {
344
+ if (!types.isValidType(column.type)) {
345
+ column.type = getRegularColumnDefaults().type;
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Returns the column defaults based on its type.
351
+ *
352
+ * @param {Object} column The column definition object.
353
+ * @returns {Object} The column defaults.
354
+ */
355
+ function getColumnDefaults(column) {
356
+ switch (column.type) {
357
+ case 'action':
358
+ return getActionColumnDefaults();
359
+ case 'tree':
360
+ return getTreeColumnDefaults();
361
+ default:
362
+ return getRegularColumnDefaults();
363
+ }
364
+ }
365
+
366
+ /**
367
+ * Retrieves the defaults for regular columns.
368
+ *
369
+ * @returns {Object} Regular column defaults
370
+ */
371
+ function getRegularColumnDefaults() {
372
+ return {
373
+ type: 'text',
374
+ typeAttributes: {},
375
+ cellAttributes: {},
376
+ };
377
+ }
378
+
379
+ /**
380
+ * Retrieves the defaults for action columns.
381
+ *
382
+ * @returns {Object} Action column defaults
383
+ */
384
+ function getActionColumnDefaults() {
385
+ return {
386
+ fixedWidth: 50,
387
+ resizable: false,
388
+ ariaLabel: i18n.rowActionsDefaultAriaLabel,
389
+ };
390
+ }
391
+
392
+ /**
393
+ * Retrieves the defaults for tree columns.
394
+ *
395
+ * @returns {Object} Tree column defaults
396
+ */
397
+ function getTreeColumnDefaults() {
398
+ return {
399
+ type: 'tree',
400
+ subType: 'text',
401
+ typeAttributes: {},
402
+ cellAttributes: {},
403
+ };
404
+ }
@@ -82,6 +82,7 @@ import {
82
82
  refocusCellElement,
83
83
  isCellElement,
84
84
  getActiveCellElement,
85
+ getDataRow,
85
86
  FOCUS_CLASS,
86
87
  } from './keyboard';
87
88
  import {
@@ -138,10 +139,15 @@ import {
138
139
  isViewportRenderingEnabled,
139
140
  setViewportRendering,
140
141
  getDTWrapperHeight,
141
- setFirstVisibleIndex,
142
142
  setVirtualize,
143
143
  RenderManager,
144
144
  } from './renderManager';
145
+ import {
146
+ handleVariableRowHeights,
147
+ resetRowHeights,
148
+ resetTableHeight,
149
+ findFirstVisibleIndex,
150
+ } from './virtualization';
145
151
 
146
152
  import { hasTreeDataType } from './tree';
147
153
  import { setErrors, getTableError, getErrors } from './errors';
@@ -203,7 +209,9 @@ export default class LightningDatatable extends LightningElement {
203
209
  _privateTypes = {};
204
210
  _privateWidthObserver = null; // Instance of LightningDatatableResizeObserver
205
211
  _renderMode = 'table';
212
+ _shouldResetHeights = false;
206
213
  _suppressBottomBar = false;
214
+ _shouldResetFocus = false; // used to ensure focus isn't lost from changes in renderedRows
207
215
 
208
216
  /************************* PUBLIC PROPERTIES *************************/
209
217
 
@@ -283,6 +291,7 @@ export default class LightningDatatable extends LightningElement {
283
291
  // do necessary updates since rows have changed
284
292
  if (hasValidKeyField(this.state)) {
285
293
  this.updateRowsState();
294
+ resetTableHeight(this.state);
286
295
  }
287
296
  if (this._customerSelectedRows) {
288
297
  this.setSelectedRows(this._customerSelectedRows);
@@ -797,8 +806,8 @@ export default class LightningDatatable extends LightningElement {
797
806
  * virtualization is enabled
798
807
  */
799
808
  get computedTbodyStyle() {
800
- const style = [];
801
- const { firstVisibleIndex, bufferSize, virtualize, rows, rowHeight } =
809
+ const style = {};
810
+ const { firstVisibleIndex, bufferSize, virtualize, tableHeight } =
802
811
  this.state;
803
812
  if (
804
813
  hasRowNumberColumn(this.state) &&
@@ -809,11 +818,11 @@ export default class LightningDatatable extends LightningElement {
809
818
  0
810
819
  );
811
820
  const rowNumber = firstRenderedRow + getRowNumberOffset(this.state);
812
- style.push(`counter-reset: row-number ${rowNumber}`);
821
+ style['counter-reset'] = `row-number ${rowNumber}`;
813
822
  }
814
823
  if (virtualize) {
815
- const length = rows.length;
816
- style.push('position: relative', `height:${length * rowHeight}px`);
824
+ style.position = 'relative';
825
+ style.height = `${tableHeight}px`;
817
826
  }
818
827
  return styleToString(style);
819
828
  }
@@ -938,6 +947,8 @@ export default class LightningDatatable extends LightningElement {
938
947
  if (virtualize) {
939
948
  const { firstIndex, lastIndex } =
940
949
  this._renderManager.getRenderedRange(this.state);
950
+ // we shouldn't lose focus from re-renders caused by a change in renderedRows
951
+ this._shouldResetFocus = true;
941
952
  return rows.slice(firstIndex, lastIndex);
942
953
  }
943
954
  if (this.viewportRendering && !isIE11) {
@@ -1124,10 +1135,7 @@ export default class LightningDatatable extends LightningElement {
1124
1135
  if (fireResizeEvent) {
1125
1136
  this.fireOnResize(false);
1126
1137
  }
1127
-
1128
- const role = '[role="' + this.computedTableRole + '"]';
1129
-
1130
- this.template.querySelector(role).style = this.computedTableStyle;
1138
+ this.updateTableAndScrollerStyleOnRender();
1131
1139
  }
1132
1140
 
1133
1141
  // Managing the cell widths is only required for the role-based table
@@ -1142,17 +1150,23 @@ export default class LightningDatatable extends LightningElement {
1142
1150
  // set the previous focused cell to null after render is done
1143
1151
  resetCellToFocusFromPrev(state);
1144
1152
  // reset focus styles on re-render
1145
- if (state.activeCell && state.activeCell.focused) {
1146
- const cellElement = getActiveCellElement(template, state);
1147
- if (
1148
- cellElement &&
1149
- cellElement.parentElement &&
1150
- !cellElement.parentElement.classList.contains(FOCUS_CLASS)
1151
- ) {
1152
- setFocusActiveCell(template, state, null, null, false);
1153
+ if (this._shouldResetFocus) {
1154
+ // since focus is now getting reset, can change this back to false
1155
+ this._shouldResetFocus = false;
1156
+ if (state.activeCell && state.activeCell.focused) {
1157
+ const cellElement = getActiveCellElement(template, state);
1158
+ if (
1159
+ cellElement &&
1160
+ cellElement.parentElement &&
1161
+ !cellElement.parentElement.classList.contains(FOCUS_CLASS)
1162
+ ) {
1163
+ setFocusActiveCell(template, state, null, null, false);
1164
+ }
1153
1165
  }
1154
1166
  }
1155
1167
 
1168
+ this.updateVirtualizedRowHeights();
1169
+
1156
1170
  if (this.viewportRendering || state.virtualize) {
1157
1171
  const resizeTarget = this.template.querySelector(
1158
1172
  'div.dt-outer-container'
@@ -1175,6 +1189,18 @@ export default class LightningDatatable extends LightningElement {
1175
1189
  }
1176
1190
  }
1177
1191
 
1192
+ updateTableAndScrollerStyleOnRender() {
1193
+ const role = '[role="' + this.computedTableRole + '"]';
1194
+ const tableElement = this.template.querySelector(role);
1195
+ const scrollYEle = this.template.querySelector('.slds-scrollable_y');
1196
+ if (tableElement) {
1197
+ tableElement.style = this.computedTableStyle;
1198
+ }
1199
+ if (scrollYEle) {
1200
+ scrollYEle.style = this.computedScrollerStyle;
1201
+ }
1202
+ }
1203
+
1178
1204
  disconnectedCallback() {
1179
1205
  if (this._privateWidthObserver) {
1180
1206
  this._privateWidthObserver.disconnect();
@@ -1253,7 +1279,10 @@ export default class LightningDatatable extends LightningElement {
1253
1279
 
1254
1280
  handleInlineEditPanelScroll.call(this, event);
1255
1281
  if (this.state.virtualize) {
1256
- setFirstVisibleIndex(this.state, event.target.scrollTop);
1282
+ this.state.firstVisibleIndex = findFirstVisibleIndex(
1283
+ this.state,
1284
+ event.target.scrollTop
1285
+ );
1257
1286
  } else if (this.viewportRendering) {
1258
1287
  this._renderManager.handleScroll(this.state, event);
1259
1288
  }
@@ -1347,6 +1376,7 @@ export default class LightningDatatable extends LightningElement {
1347
1376
  handleResizeEnd(event) {
1348
1377
  event.stopPropagation();
1349
1378
  this._isResizing = false;
1379
+ this._shouldResetHeights = true;
1350
1380
  }
1351
1381
 
1352
1382
  /**
@@ -1419,10 +1449,19 @@ export default class LightningDatatable extends LightningElement {
1419
1449
  * Handles the `focusout` event on <table> and the corresponding
1420
1450
  * <div> on the role-based table
1421
1451
  *
1452
+ * This gets called both when we expect the table to lose focus
1453
+ * and when the active cell loses focus after renderedRows changes
1454
+ * on a virtualized table, in which case we don't want to lose focus.
1455
+ *
1456
+ * We account for this by setting activeCell.focused to the value of
1457
+ * _shouldResetFocus, which will be true if and only if focus was
1458
+ * lost due to a renderedRows change for a virtualized table.
1459
+ *
1422
1460
  * @param {FocusEvent} event - `focusout`
1423
1461
  */
1424
1462
  handleTableFocusOut(event) {
1425
1463
  handleDatatableFocusOut.call(this, event);
1464
+ this.state.activeCell.focused = this._shouldResetFocus;
1426
1465
  }
1427
1466
 
1428
1467
  /**
@@ -1601,6 +1640,41 @@ export default class LightningDatatable extends LightningElement {
1601
1640
  }
1602
1641
  }
1603
1642
 
1643
+ updateVirtualizedRowHeights() {
1644
+ const state = this.state;
1645
+ const virtualizedRows = state.virtualize && this.renderedRows.length;
1646
+
1647
+ // no need to handle other virtualization/row height logic
1648
+ // if heights need to be reset
1649
+ if (this._shouldResetHeights) {
1650
+ resetRowHeights(state);
1651
+ this._shouldResetHeights = false;
1652
+ } else if (virtualizedRows && !state.fixedHeight) {
1653
+ // if row heights aren't fixed, we need to update items
1654
+ // in state to know where rows should be positioned
1655
+ handleVariableRowHeights(this.template, state, this.renderedRows);
1656
+ } else if (virtualizedRows && state.fixedHeight) {
1657
+ // if heights are fixed, we only need to check height of first row
1658
+ const rowElement = this.template.querySelector(
1659
+ getDataRow(this.renderedRows[0].key)
1660
+ );
1661
+ // increase height by 1 since first rendered row is missing an extra 1px border
1662
+ if (rowElement) {
1663
+ const height = rowElement.getBoundingClientRect().height + 1;
1664
+ if (state.rowHeight !== height) {
1665
+ state.rowHeight = height;
1666
+ resetTableHeight(state);
1667
+ state.rows.forEach((row) => {
1668
+ row.style = styleToString({
1669
+ position: 'absolute',
1670
+ top: `${row.rowIndex * height}px`,
1671
+ });
1672
+ });
1673
+ }
1674
+ }
1675
+ }
1676
+ }
1677
+
1604
1678
  setSelectedRows(value) {
1605
1679
  setSelectedRowsKeys(this.state, value);
1606
1680
  handleRowSelectionChange.call(this);
@@ -1620,7 +1694,7 @@ export default class LightningDatatable extends LightningElement {
1620
1694
  }
1621
1695
 
1622
1696
  /**
1623
- * @return {Object} containing the visible dimensions of the table { left, right, top, bottom, }
1697
+ * @returns {Object} containing the visible dimensions of the table { left, right, top, bottom, }
1624
1698
  */
1625
1699
  getViewableRect() {
1626
1700
  const scrollerX = this.template
@@ -16,7 +16,7 @@ const DIVIDER_REM_HEIGHT = 1.0625;
16
16
  *
17
17
  * @param {Object} state The state of the datatable
18
18
  * @param {Object} columnDefinition The column definition to extract internal actions from
19
- * @return {Array} All wrapText internal actions
19
+ * @returns {Array} All wrapText internal actions
20
20
  */
21
21
  export function getInternalActions(state, columnDefinition) {
22
22
  return [...getActions(state, columnDefinition)];
@@ -113,7 +113,7 @@ function dispatchHeaderActionEvent(dt, action, colKeyValue) {
113
113
  *
114
114
  * @param {Array} columns Array of all the columns
115
115
  * @param {Integer} index The current column index to check
116
- * @return {String} The computed alignment
116
+ * @returns {String} The computed alignment
117
117
  */
118
118
  function getMenuAlignment(columns, index) {
119
119
  const isLastColumn = index === columns.length - 1;
@@ -10,7 +10,7 @@ import {
10
10
  } from './tree';
11
11
  import { isCellEditable, getRowByKey } from './rows';
12
12
  import { isRTL, getShadowActiveElements } from 'lightning/utilsPrivate';
13
- import { setFirstVisibleIndex } from './renderManager';
13
+ import { findFirstVisibleIndex } from './virtualization';
14
14
 
15
15
  // Indicator/flag for a header row
16
16
  const HEADER_ROW = 'HEADER';
@@ -88,7 +88,7 @@ const SELECTORS = {
88
88
  * user keys down on a cell that contains actionable items (ex. edit button, links,
89
89
  * email, buttons).
90
90
  *
91
- * @param {Event} event - Custom DOM event (privatecellkeydown) sent by the cell
91
+ * @param {Event} event Custom DOM event (privatecellkeydown) sent by the cell
92
92
  */
93
93
  export function handleKeydownOnCell(event) {
94
94
  event.stopPropagation();
@@ -110,7 +110,7 @@ export function handleKeydownOnCell(event) {
110
110
  * Those events are handled by `handleKeydownOnCell()` and the remaining are
111
111
  * handled by this function.
112
112
  *
113
- * @param {*} event
113
+ * @param {Event} event
114
114
  */
115
115
  export function handleKeydownOnTable(event) {
116
116
  const targetTagName = event.target.tagName.toLowerCase();
@@ -127,10 +127,10 @@ export function handleKeydownOnTable(event) {
127
127
  * Changes the datatable state based on the keyboard event sent from the cell component.
128
128
  * The result of those changes may trigger a re-render on the table
129
129
  *
130
- * @param {node} template - the custom element root `this.template`
131
- * @param {object} state - datatable state
132
- * @param {event} event - custom DOM event sent by the cell
133
- * @returns {object} - mutated state
130
+ * @param {Node} template The custom element root `this.template`
131
+ * @param {Object} state Datatable state
132
+ * @param {Event} event Custom DOM event sent by the cell
133
+ * @returns {Object} Mutated state
134
134
  */
135
135
  function reactToKeyboardInActionMode(template, state, event) {
136
136
  switch (event.detail.keyCode) {
@@ -1313,7 +1313,7 @@ function isHeaderRow(rowIndex) {
1313
1313
  return rowIndex === -1;
1314
1314
  }
1315
1315
 
1316
- function getDataRow(rowKeyValue) {
1316
+ export function getDataRow(rowKeyValue) {
1317
1317
  return `[data-row-key-value="${rowKeyValue}"]`;
1318
1318
  }
1319
1319
 
@@ -1365,7 +1365,7 @@ function updateScrollTop(state, template, element) {
1365
1365
  } else if (findMeRect.bottom > parentRect.bottom - BOTTOM_MARGIN) {
1366
1366
  scrollableY.scrollTop += SCROLL_OFFSET;
1367
1367
  }
1368
- setFirstVisibleIndex(state, scrollableY.scrollTop);
1368
+ findFirstVisibleIndex(state, scrollableY.scrollTop);
1369
1369
  }
1370
1370
 
1371
1371
  function scrollToCell(state, template, rowIndex) {
@@ -1380,7 +1380,7 @@ function scrollToCell(state, template, rowIndex) {
1380
1380
 
1381
1381
  const scrollableY = template.querySelector('.slds-scrollable_y');
1382
1382
  scrollableY.scrollTop = scrollTop;
1383
- setFirstVisibleIndex(state, scrollTop);
1383
+ findFirstVisibleIndex(state, scrollTop);
1384
1384
  }
1385
1385
 
1386
1386
  export function isActiveCellEditable(state) {