lightning-base-components 1.21.5-alpha → 1.21.6-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 (49) hide show
  1. package/metadata/raptor.json +1 -0
  2. package/package.json +1 -1
  3. package/src/lightning/badge/badge.slds.css +1 -1
  4. package/src/lightning/combobox/form-element.slds.css +4 -1
  5. package/src/lightning/datatable/columns.js +17 -18
  6. package/src/lightning/datatable/datatable.js +143 -80
  7. package/src/lightning/datatable/indexes.js +1 -3
  8. package/src/lightning/datatable/infiniteLoading.js +1 -1
  9. package/src/lightning/datatable/inlineEdit.js +9 -7
  10. package/src/lightning/datatable/keyboard.js +21 -44
  11. package/src/lightning/datatable/renderManager.js +9 -18
  12. package/src/lightning/datatable/rows.js +112 -128
  13. package/src/lightning/datatable/sort.js +35 -14
  14. package/src/lightning/datatable/state.js +5 -0
  15. package/src/lightning/datatable/tree.js +0 -33
  16. package/src/lightning/datatable/utils.js +11 -0
  17. package/src/lightning/datepicker/datepicker.js +12 -3
  18. package/src/lightning/datepicker/form-element.slds.css +4 -1
  19. package/src/lightning/datetimepicker/form-element.slds.css +4 -1
  20. package/src/lightning/dualListbox/form-element.slds.css +4 -1
  21. package/src/lightning/groupedCombobox/form-element.slds.css +4 -1
  22. package/src/lightning/helptext/form-element.slds.css +4 -1
  23. package/src/lightning/input/form-element.slds.css +4 -1
  24. package/src/lightning/inputAddress/form-element.slds.css +4 -1
  25. package/src/lightning/inputLocation/form-element.slds.css +4 -1
  26. package/src/lightning/inputName/form-element.slds.css +4 -1
  27. package/src/lightning/lookupAddress/form-element.slds.css +4 -1
  28. package/src/lightning/modalBase/modalBase.js +12 -29
  29. package/src/lightning/primitiveBubble/primitiveBubble.js +26 -11
  30. package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +1 -1
  31. package/src/lightning/primitiveInputCheckbox/form-element.slds.css +4 -1
  32. package/src/lightning/primitiveInputCheckboxButton/form-element.slds.css +4 -1
  33. package/src/lightning/primitiveInputColor/form-element.slds.css +4 -1
  34. package/src/lightning/primitiveInputFile/form-element.slds.css +4 -1
  35. package/src/lightning/primitiveInputSimple/form-element.slds.css +4 -1
  36. package/src/lightning/primitiveInputToggle/form-element.slds.css +4 -1
  37. package/src/lightning/progressBar/progress-bar.slds.css +1 -1
  38. package/src/lightning/radioGroup/form-element.slds.css +4 -1
  39. package/src/lightning/select/form-element.slds.css +4 -1
  40. package/src/lightning/textarea/__examples__/various/various.html +18 -1
  41. package/src/lightning/textarea/form-element.slds.css +4 -1
  42. package/src/lightning/textarea/textarea.js +25 -0
  43. package/src/lightning/timepicker/form-element.slds.css +4 -1
  44. package/src/lightning/verticalNavigationItem/vertical-navigation-item.slds.css +1 -1
  45. package/src/lightning/verticalNavigationItemBadge/badge.slds.css +1 -1
  46. package/src/lightning/verticalNavigationItemBadge/vertical-navigation-item.slds.css +1 -1
  47. package/src/lightning/verticalNavigationItemIcon/vertical-navigation-item.slds.css +1 -1
  48. package/src/lightning/verticalNavigationOverflow/vertical-navigation-item.slds.css +1 -1
  49. package/src/lightning/datatable/columns-shared.js +0 -12
@@ -3083,6 +3083,7 @@
3083
3083
  "minVersion": "45.0"
3084
3084
  },
3085
3085
  "platformScaleCenterApi": {},
3086
+ "platformSharingApi": {},
3086
3087
  "platformShowToastEvent": {
3087
3088
  "minVersion": "45.0"
3088
3089
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lightning-base-components",
3
- "version": "1.21.5-alpha",
3
+ "version": "1.21.6-alpha",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "external",
@@ -12,7 +12,7 @@
12
12
  align-items: center;
13
13
  padding: var(--slds-g-spacing-1) var(--slds-g-spacing-2);
14
14
  color: var(--slds-c-badge-text-color, var(--slds-g-color-on-surface-3));
15
- font-size: var(--slds-c-badge-font-size, var(--slds-g-font-scale-neg-2));
15
+ font-size: var(--slds-c-badge-font-size, var(--slds-g-font-scale-neg-1));
16
16
  font-weight: var(--slds-g-font-weight-7);
17
17
  /* stylelint-disable */
18
18
  line-height: var(--slds-c-badge-font-lineheight, initial);
@@ -187,7 +187,10 @@
187
187
  }
188
188
 
189
189
  :host([data-render-mode="shadow"][variant='label-stacked']) .slds-form-element__label,:host([data-render-mode="shadow"][variant='label-stacked']) .slds-form-element__control {
190
- border-bottom: 0; /* Remove border when using legacy version of slds-form-element */
190
+ /* @W-14518344 The following line still exists in SLDS-internal
191
+ but it was removed here because it was causing the input
192
+ component to not display it's bottom border
193
+ border-bottom: 0; Remove border when using legacy version of slds-form-element */
191
194
  padding-inline-start: 0;
192
195
  }
193
196
 
@@ -43,7 +43,11 @@ const SELECTABLE_COLUMN = {
43
43
  * @param {Array} rawColumns - The user provided column definitions to normalize
44
44
  * @param {Object} types - The type handling factory
45
45
  */
46
- export function normalizeColumns(state, rawColumns, types) {
46
+ export function setColumns(state, rawColumns, types) {
47
+ // Untracked state changes.
48
+ state.hadTreeDataTypePreviously = state.treeColumn !== undefined;
49
+ state.treeColumn = undefined;
50
+
47
51
  const { length: colCount } = rawColumns;
48
52
  if (colCount === 0) {
49
53
  // Tracked state change.
@@ -176,13 +180,22 @@ export function normalizeColumns(state, rawColumns, types) {
176
180
  }
177
181
 
178
182
  // Generate colKeyValue after normalizing customer column.
179
- normCol.colKeyValue = generateColKeyValue(normCol, colIndex);
183
+ const colKeyValue =
184
+ normCol.colKeyValue ||
185
+ `${colName || colIndex}-${columnType}-${colIndex}`;
186
+
187
+ normCol.colKeyValue = colKeyValue;
180
188
  normCol.isScopeCol = colIndex === firstColumnForReaders;
181
189
  normCol.isLastCol = colIndex === normColCount - 1;
190
+ normCol.name = colName;
182
191
  normCol.tabIndex = -1;
183
192
 
184
193
  // normalize tree column
185
194
  if (normCol.type === 'tree') {
195
+ if (state.treeColumn === undefined) {
196
+ // Untracked state changes
197
+ state.treeColumn = normCol;
198
+ }
186
199
  // normalized subType attributes
187
200
  const { typeAttributes } = normCol;
188
201
  const typeAttributesOverrides = {};
@@ -201,10 +214,9 @@ export function normalizeColumns(state, rawColumns, types) {
201
214
 
202
215
  // partially inline updateHeaderInternalActions from datatable/headerActions
203
216
  const { actions } = normCol;
204
- const isLastColumn = colIndex === normColCount - 1;
205
217
  normCol.actions = {
206
218
  menuAlignment:
207
- isLastColumn ||
219
+ normCol.isLastCol ||
208
220
  normalizedColumns[colIndex + 1].type === 'action'
209
221
  ? 'auto-right'
210
222
  : 'auto-left',
@@ -247,19 +259,6 @@ export function getCellAttributesValues(column) {
247
259
  return isObjectLike(cellAttributes) ? cellAttributes : {};
248
260
  }
249
261
 
250
- /**
251
- * Generates a unique column key value.
252
- *
253
- * @param {Object} columnMetadata The object for an specific column metadata
254
- * @param {Integer} index Optionally, the index of the column.
255
- * @returns {String} It generates the column key value based on the column field name and type.
256
- */
257
- export function generateColKeyValue(columnMetadata, index) {
258
- const { columnKey, fieldName, type } = columnMetadata;
259
- const prefix = columnKey || fieldName || index;
260
- return `${prefix}-${type}-${index}`;
261
- }
262
-
263
262
  /**
264
263
  * Return the index in dt.columns (user definition) related to colKeyValue.
265
264
  * -1 if no column with that key exist or if its internal.
@@ -296,7 +295,7 @@ export function getUserColumnIndex(state, colKeyValue) {
296
295
  */
297
296
  export const generateHeaderIndexes = function (columns) {
298
297
  return columns.reduce((prev, col, index) => {
299
- prev[generateColKeyValue(col, index)] = index;
298
+ prev[col.colKeyValue] = index;
300
299
  return prev;
301
300
  }, {});
302
301
  };
@@ -15,7 +15,7 @@ import {
15
15
  import { LightningDatatableResizeObserver } from './resizeObserver';
16
16
  import { ColumnWidthManager } from './columnWidthManager';
17
17
  import { getDefaultState } from './state';
18
- import { normalizeColumns, generateHeaderIndexes } from './columns';
18
+ import { setColumns, generateHeaderIndexes } from './columns';
19
19
  import {
20
20
  getCustomerColumnWidths,
21
21
  getResizerDefaultState,
@@ -29,7 +29,7 @@ import {
29
29
  import { setErrors } from './errors';
30
30
  import {
31
31
  setKeyField,
32
- updateRowsAndCellIndexes,
32
+ updateRowsAndCells,
33
33
  updateCellClassForRoleBasedMode,
34
34
  recomputeCellStyles,
35
35
  } from './rows';
@@ -111,12 +111,7 @@ import {
111
111
  updateRowNavigationMode,
112
112
  updateRowTabIndex,
113
113
  } from './keyboard';
114
- import {
115
- isViewportRenderingEnabled,
116
- setViewportRendering,
117
- setVirtualize,
118
- RenderManager,
119
- } from './renderManager';
114
+ import { setVirtualize, RenderManager } from './renderManager';
120
115
  import {
121
116
  setDefaultSortDirection,
122
117
  setSortedBy,
@@ -128,6 +123,8 @@ import {
128
123
  getRowDataSelector,
129
124
  getScrollerX,
130
125
  getScrollerY,
126
+ isObjectLike,
127
+ isRenderModeRoleBased,
131
128
  } from './utils';
132
129
  import { setWrapTextMaxLines } from './wrapText';
133
130
  import {
@@ -136,7 +133,6 @@ import {
136
133
  resetTableHeight,
137
134
  findFirstVisibleIndex,
138
135
  } from './virtualization';
139
- import { hasTreeDataType } from './tree';
140
136
  import DatatableTypes from './types';
141
137
 
142
138
  const i18n = {
@@ -188,6 +184,7 @@ export default class LightningDatatable extends LightningElement {
188
184
  _draftValues = [];
189
185
  _isResizing = false; // Whether resizing is in progress
190
186
  _lastRenderedRow = null; // last rendered row, used for UTAM
187
+ _positionRelationship;
191
188
  _privateTypes = {};
192
189
  _rawColumns = [];
193
190
  _renderConfig;
@@ -195,7 +192,7 @@ export default class LightningDatatable extends LightningElement {
195
192
  _renderMode = 'default';
196
193
  _shouldResetFocus = false; // used to ensure focus isn't lost from changes in renderedRows
197
194
  _suppressBottomBar = false;
198
- _widthObserver = null; // Instance of LightningDatatableResizeObserver
195
+ _widthObserver; // Instance of LightningDatatableResizeObserver
199
196
 
200
197
  /************************* PUBLIC PROPERTIES *************************/
201
198
 
@@ -284,7 +281,7 @@ export default class LightningDatatable extends LightningElement {
284
281
 
285
282
  // do necessary updates since rows have changed
286
283
  if (this.hasValidKeyField) {
287
- this.updateRowsState();
284
+ this.updateRows();
288
285
  resetTableHeight(state);
289
286
  }
290
287
  if (this._customerSelectedRows) {
@@ -362,7 +359,7 @@ export default class LightningDatatable extends LightningElement {
362
359
 
363
360
  set errors(value) {
364
361
  setErrors(this.state, value);
365
- this.updateRowsState();
362
+ this.updateRows();
366
363
  }
367
364
 
368
365
  /**
@@ -452,7 +449,7 @@ export default class LightningDatatable extends LightningElement {
452
449
  setKeyField(state, value);
453
450
  // Tracked state change.
454
451
  setDirtyValues(state, this._draftValues);
455
- this.updateRowsState();
452
+ this.updateRows();
456
453
  }
457
454
 
458
455
  /**
@@ -550,9 +547,7 @@ export default class LightningDatatable extends LightningElement {
550
547
  }
551
548
 
552
549
  set renderConfig(value) {
553
- if (typeof value === 'object') {
554
- setViewportRendering(this.state, value.viewportRendering);
555
-
550
+ if (isObjectLike(value)) {
556
551
  this._renderManager.configure(
557
552
  this.state,
558
553
  this.getWrapperHeight,
@@ -586,11 +581,23 @@ export default class LightningDatatable extends LightningElement {
586
581
 
587
582
  set renderMode(value) {
588
583
  const { _renderConfig, state } = this;
589
- this._renderMode = normalizeString(value, {
584
+ const renderMode = normalizeString(value, {
590
585
  fallbackValue: 'default',
591
586
  validValues: ['default', 'role-based'],
592
587
  });
593
- state.renderModeRoleBased = this._renderMode === 'role-based';
588
+ const renderModeRoleBased = isRenderModeRoleBased(renderMode);
589
+
590
+ this._renderMode = renderMode;
591
+ // Untracked state changes.
592
+ state.hasRenderedFirstTime = false;
593
+ state.renderModeRoleBased = renderModeRoleBased;
594
+ if (this.isConnected) {
595
+ const { _widthObserver } = this;
596
+ if (_widthObserver) {
597
+ _widthObserver.disconnect();
598
+ }
599
+ this._renderManager.disconnectResizeObserver();
600
+ }
594
601
  if (_renderConfig) {
595
602
  setVirtualize(state, _renderConfig.virtualize);
596
603
  }
@@ -688,9 +695,9 @@ export default class LightningDatatable extends LightningElement {
688
695
  }
689
696
 
690
697
  /**
691
- * The column key or fieldName that controls the sorting order.
698
+ * The column key or fieldName(s) that controls the sorting order.
692
699
  * Sort the data using the onsort event handler.
693
- * @type {String}
700
+ * @type {String|String[]}
694
701
  */
695
702
  @api
696
703
  get sortedBy() {
@@ -706,8 +713,8 @@ export default class LightningDatatable extends LightningElement {
706
713
  /**
707
714
  * Specifies the sorting direction.
708
715
  * Sort the data using the onsort event handler.
709
- * Valid options include 'asc' and 'desc'.
710
- * @type {String}
716
+ * Valid options include a single value of 'asc' or 'desc' or an array of such values.
717
+ * @type {String|String[]}
711
718
  */
712
719
  @api
713
720
  get sortedDirection() {
@@ -793,17 +800,8 @@ export default class LightningDatatable extends LightningElement {
793
800
 
794
801
  /************************** PRIVATE GETTERS **************************/
795
802
 
796
- /**
797
- * Retrieves the grid container:
798
- * 1. For a table-based table, it will retrieve the <table role="grid"> element
799
- * 2. For a role-based table, it will retrieve the <div role="grid"> element
800
- * 3. If it is a tree grid, it will retrieve the <table role="treegrid"> element
801
- */
802
803
  get gridContainer() {
803
- return (
804
- this.template.querySelector('[role="grid"]') ||
805
- this.template.querySelector('[role="treegrid"]')
806
- );
804
+ return getGridContainerFromScrollerY(getScrollerY(this.template));
807
805
  }
808
806
 
809
807
  get computedTableContainerClass() {
@@ -822,12 +820,12 @@ export default class LightningDatatable extends LightningElement {
822
820
  'slds-table_bordered': true,
823
821
  'slds-table_edit': true,
824
822
  'slds-table_resizable-cols': !this.widthsData.resizeColumnDisabled,
825
- 'slds-tree slds-table_tree': hasTreeDataType(state),
823
+ 'slds-tree slds-table_tree': !!state.treeColumn,
826
824
  });
827
825
  }
828
826
 
829
827
  get computedTableRole() {
830
- return hasTreeDataType(this.state) ? 'treegrid' : 'grid';
828
+ return this.state.treeColumn ? 'treegrid' : 'grid';
831
829
  }
832
830
 
833
831
  get computedTableStyle() {
@@ -957,10 +955,6 @@ export default class LightningDatatable extends LightningElement {
957
955
  return this._privateTypes;
958
956
  }
959
957
 
960
- get viewportRendering() {
961
- return isViewportRenderingEnabled(this.state);
962
- }
963
-
964
958
  get renderedRows() {
965
959
  const { state } = this;
966
960
  const { virtualize, rows, renderedRowCount } = state;
@@ -972,7 +966,7 @@ export default class LightningDatatable extends LightningElement {
972
966
  this._shouldResetFocus = true;
973
967
  return rows.slice(firstIndex, lastIndex);
974
968
  }
975
- if (this.viewportRendering) {
969
+ if (state.enableViewportRendering) {
976
970
  this._lastRenderedRow = renderedRowCount;
977
971
  return rows.slice(0, renderedRowCount);
978
972
  }
@@ -1100,11 +1094,17 @@ export default class LightningDatatable extends LightningElement {
1100
1094
  }
1101
1095
 
1102
1096
  renderedCallback() {
1103
- const { _columnWidthManager, state, template, widthsData } = this;
1097
+ const {
1098
+ _columnWidthManager,
1099
+ gridContainer,
1100
+ state,
1101
+ template,
1102
+ widthsData,
1103
+ } = this;
1104
1104
 
1105
1105
  // This keeps underlying table element up to date if the aria-* properties on this element is dynamically changed.
1106
1106
  // It does the work of removing and adding the attribute if the value is empty(ish) or a normal string.
1107
- synchronizeAttrs(this.gridContainer, {
1107
+ synchronizeAttrs(gridContainer, {
1108
1108
  'aria-label': this.ariaLabel,
1109
1109
  'aria-labelledby': this.ariaLabelledBy,
1110
1110
  'aria-describedby': this.ariaDescribedBy,
@@ -1122,6 +1122,10 @@ export default class LightningDatatable extends LightningElement {
1122
1122
  columns,
1123
1123
  widthsData
1124
1124
  );
1125
+ // Managing cell widths is required for role-based render mode.
1126
+ if (state.renderModeRoleBased) {
1127
+ recomputeCellStyles(state);
1128
+ }
1125
1129
  if (fireResizeEvent) {
1126
1130
  this.fireOnResize(false);
1127
1131
  }
@@ -1140,6 +1144,10 @@ export default class LightningDatatable extends LightningElement {
1140
1144
  state.columns,
1141
1145
  widthsData
1142
1146
  );
1147
+ // Managing cell widths is required for role-based render mode.
1148
+ if (state.renderModeRoleBased) {
1149
+ recomputeCellStyles(state);
1150
+ }
1143
1151
  }
1144
1152
  );
1145
1153
  this._widthObserver = _widthObserver;
@@ -1147,12 +1155,6 @@ export default class LightningDatatable extends LightningElement {
1147
1155
  _widthObserver.observe(template);
1148
1156
  }
1149
1157
 
1150
- // Managing the cell widths is only required for the role-based table
1151
- if (state.renderModeRoleBased) {
1152
- // TODO: Look to further optimize - Do this only when required
1153
- recomputeCellStyles(this.privateTypes, state);
1154
- }
1155
-
1156
1158
  handlePrefetch.call(this);
1157
1159
 
1158
1160
  // customerSelectedRows is only valid till render, after it, the one
@@ -1169,7 +1171,7 @@ export default class LightningDatatable extends LightningElement {
1169
1171
  const { activeCell } = state;
1170
1172
  if (
1171
1173
  activeCell &&
1172
- activeCell.focused &&
1174
+ activeCell.hasFocus &&
1173
1175
  !state.inlineEdit.isPanelVisible
1174
1176
  ) {
1175
1177
  const cellElement = getActiveCellElement(template, state);
@@ -1184,23 +1186,36 @@ export default class LightningDatatable extends LightningElement {
1184
1186
  }
1185
1187
  }
1186
1188
 
1187
- this.updateVirtualizedRowHeights();
1189
+ const { hasRenderedFirstTime } = state;
1190
+ const virtualize = !!state.virtualize;
1191
+ const { length: rowCount } = state.rows;
1188
1192
 
1189
- if (this.viewportRendering || state.virtualize) {
1190
- const resizeTarget = this.template.querySelector(
1191
- 'div.dt-outer-container'
1192
- );
1193
- this._renderManager.connectResizeObserver(resizeTarget);
1194
- if (!this._renderManager.hasWrapperHeight()) {
1195
- this._renderManager.updateWrapperHeight(this.getWrapperHeight);
1193
+ // Untracked state changes.
1194
+ // Set rendered flags BEFORE handlePrefetch() is called.
1195
+ state.hasRenderedFirstTime = true;
1196
+
1197
+ if (virtualize || state.enableViewportRendering) {
1198
+ const { _renderManager } = this;
1199
+ if (rowCount) {
1200
+ if (virtualize) {
1201
+ this.updateVirtualizedRowHeights();
1202
+ }
1203
+ }
1204
+ if (!hasRenderedFirstTime) {
1205
+ this._renderManager.connectResizeObserver(
1206
+ template.querySelector('div.dt-outer-container')
1207
+ );
1208
+ }
1209
+ if (!_renderManager.hasWrapperHeight()) {
1210
+ _renderManager.updateWrapperHeight(this.getWrapperHeight);
1196
1211
 
1197
1212
  // Reset the row count if we already had one before updating the wrapper height.
1198
1213
  // This can happen if the number of rows was calculated before the datatable
1199
1214
  // was rendered.
1200
- if (this.state.renderedRowCount) {
1201
- this._renderManager.updateViewportRendering(
1202
- this.state,
1203
- this.gridContainer,
1215
+ if (state.renderedRowCount) {
1216
+ _renderManager.updateViewportRendering(
1217
+ state,
1218
+ gridContainer,
1204
1219
  true
1205
1220
  );
1206
1221
  }
@@ -1324,16 +1339,16 @@ export default class LightningDatatable extends LightningElement {
1324
1339
  this.state,
1325
1340
  event.target.scrollTop
1326
1341
  );
1327
- } else if (this.viewportRendering) {
1342
+ } else if (state.enableViewportRendering) {
1328
1343
  this._renderManager.handleScroll(state, event);
1329
1344
  }
1330
1345
  }
1331
1346
 
1332
1347
  /**
1333
- * Handles the `click` event on the <table> element and
1348
+ * Handles the 'click' event on the <table> element and
1334
1349
  * the corresponding <div> in the role-based table
1335
1350
  *
1336
- * @param {MouseEvent} event - `click`
1351
+ * @param {MouseEvent} event - 'click'
1337
1352
  */
1338
1353
  handleTableCellClick(event) {
1339
1354
  // handles the case when clicking on the margin/pading of the td/th
@@ -1343,20 +1358,22 @@ export default class LightningDatatable extends LightningElement {
1343
1358
  const { rowKeyValue, colKeyValue } =
1344
1359
  target.querySelector(':first-child');
1345
1360
 
1346
- const { state, template } = this;
1361
+ const { state } = this;
1347
1362
  if (
1348
1363
  state.rowMode ||
1349
1364
  !isActiveCell(state, rowKeyValue, colKeyValue)
1350
1365
  ) {
1351
- if (state.rowMode && state.activeCell) {
1366
+ if (state.activeCell && state.rowMode) {
1367
+ // Untracked state change.
1352
1368
  unsetRowNavigationMode(state);
1353
1369
  const { rowIndex } = getIndexesActiveCell(state);
1370
+ // Tracked state change.
1354
1371
  updateRowTabIndex(state, rowIndex, -1);
1355
1372
  }
1356
1373
  this.setActiveCell(rowKeyValue, colKeyValue);
1357
1374
  }
1358
1375
 
1359
- if (!datatableHasFocus(state, template)) {
1376
+ if (!datatableHasFocus(state, this.template)) {
1360
1377
  setCellClickedForFocus(state);
1361
1378
  }
1362
1379
  }
@@ -1369,8 +1386,36 @@ export default class LightningDatatable extends LightningElement {
1369
1386
  */
1370
1387
  handleUpdateColumnSort(event) {
1371
1388
  event.stopPropagation();
1372
- const { fieldName, columnKey, sortDirection } = event.detail;
1373
- this.fireSortedColumnChange(fieldName, columnKey, sortDirection);
1389
+ const {
1390
+ fieldNames,
1391
+ sortDirections,
1392
+ isMultiColumnSort,
1393
+ fieldName,
1394
+ columnKey,
1395
+ sortDirection,
1396
+ } = event.detail;
1397
+
1398
+ if (isMultiColumnSort) {
1399
+ // multi-column sort
1400
+ this.fireSortedColumnChange(
1401
+ fieldNames,
1402
+ sortDirections,
1403
+ isMultiColumnSort,
1404
+ fieldName,
1405
+ columnKey,
1406
+ sortDirection
1407
+ );
1408
+ } else {
1409
+ // single-column sort
1410
+ this.fireSortedColumnChange(
1411
+ [fieldName],
1412
+ [sortDirection],
1413
+ false,
1414
+ fieldName,
1415
+ columnKey,
1416
+ sortDirection
1417
+ );
1418
+ }
1374
1419
  }
1375
1420
 
1376
1421
  handleCheckboxHeaderId(event) {
@@ -1393,6 +1438,10 @@ export default class LightningDatatable extends LightningElement {
1393
1438
  colIndex,
1394
1439
  delta
1395
1440
  );
1441
+ // Managing cell widths is required for role-based render mode.
1442
+ if (state.renderModeRoleBased) {
1443
+ recomputeCellStyles(state);
1444
+ }
1396
1445
  this.fireOnResize(true);
1397
1446
  this.fixHeaderForSafari();
1398
1447
  }
@@ -1452,7 +1501,7 @@ export default class LightningDatatable extends LightningElement {
1452
1501
  const { rowKeyValue, colKeyValue, needsRefocusOnCellElement } =
1453
1502
  event.detail;
1454
1503
  if (!isActiveCell(state, rowKeyValue, colKeyValue)) {
1455
- if (state.rowMode && state.activeCell) {
1504
+ if (state.activeCell && state.rowMode) {
1456
1505
  unsetRowNavigationMode(state);
1457
1506
  const { rowIndex } = getIndexesActiveCell(state);
1458
1507
  updateRowTabIndex(state, rowIndex, -1);
@@ -1494,7 +1543,7 @@ export default class LightningDatatable extends LightningElement {
1494
1543
  * and when the active cell loses focus after renderedRows changes
1495
1544
  * on a virtualized table, in which case we don't want to lose focus.
1496
1545
  *
1497
- * We account for this by setting activeCell.focused to the value of
1546
+ * We account for this by setting activeCell.hasFocus to the value of
1498
1547
  * _shouldResetFocus, which will be true if and only if focus was
1499
1548
  * lost due to a renderedRows change for a virtualized table.
1500
1549
  *
@@ -1504,7 +1553,7 @@ export default class LightningDatatable extends LightningElement {
1504
1553
  handleDatatableFocusOut.call(this, event);
1505
1554
  const { activeCell } = this.state;
1506
1555
  if (activeCell) {
1507
- activeCell.focused = this._shouldResetFocus;
1556
+ activeCell.hasFocus = this._shouldResetFocus;
1508
1557
  }
1509
1558
  }
1510
1559
 
@@ -1621,10 +1670,24 @@ export default class LightningDatatable extends LightningElement {
1621
1670
  );
1622
1671
  }
1623
1672
 
1624
- fireSortedColumnChange(fieldName, columnKey, sortDirection) {
1673
+ fireSortedColumnChange(
1674
+ fieldNames,
1675
+ sortDirections,
1676
+ isMultiColumnSort,
1677
+ fieldName,
1678
+ columnKey,
1679
+ sortDirection
1680
+ ) {
1625
1681
  this.dispatchEvent(
1626
1682
  new CustomEvent('sort', {
1627
- detail: { fieldName, columnKey, sortDirection },
1683
+ detail: {
1684
+ fieldNames,
1685
+ sortDirections,
1686
+ isMultiColumnSort,
1687
+ fieldName,
1688
+ columnKey,
1689
+ sortDirection,
1690
+ },
1628
1691
  })
1629
1692
  );
1630
1693
  }
@@ -1645,7 +1708,7 @@ export default class LightningDatatable extends LightningElement {
1645
1708
 
1646
1709
  /************************* HELPER FUNCTIONS **************************/
1647
1710
 
1648
- updateRowsState() {
1711
+ updateRows() {
1649
1712
  this.updateRowsBeforeIndexes();
1650
1713
  this.updateRowsAndCells();
1651
1714
  this.updateRowsAfterIndexes();
@@ -1658,7 +1721,7 @@ export default class LightningDatatable extends LightningElement {
1658
1721
 
1659
1722
  updateRowsAfterIndexes() {
1660
1723
  const { state, widthsData } = this;
1661
- if (this.viewportRendering || state.virtualize) {
1724
+ if (state.enableViewportRendering || state.virtualize) {
1662
1725
  this._renderManager.updateViewportRendering(
1663
1726
  state,
1664
1727
  this.gridContainer,
@@ -1710,15 +1773,15 @@ export default class LightningDatatable extends LightningElement {
1710
1773
 
1711
1774
  updateColumnsBeforeIndexes(columns) {
1712
1775
  const { state } = this;
1713
- const hadTreeDataTypePreviously = hasTreeDataType(state);
1714
1776
  // Untracked state changes.
1715
1777
  // Calculate cell to focus next before indexes are updated.
1716
1778
  setCellToFocusFromPrev(state, this.template);
1717
- normalizeColumns(state, columns, this.privateTypes);
1718
- updateRowNavigationMode(hadTreeDataTypePreviously, state);
1779
+ setColumns(state, columns, this.privateTypes);
1780
+ updateRowNavigationMode(state);
1719
1781
  // Tracked state changes.
1720
1782
  setDirtyValues(state, this._draftValues);
1721
- // Updates state.wrapText and when isWrappableType, sets internal header actions
1783
+ // Update state.wrapText and when type is not in NON_WRAPPABLE_TYPES
1784
+ // and sets internal header actions.
1722
1785
  updateHeaderInternalActions(state);
1723
1786
  }
1724
1787
 
@@ -1753,7 +1816,7 @@ export default class LightningDatatable extends LightningElement {
1753
1816
  }
1754
1817
 
1755
1818
  updateRowsAndCells() {
1756
- updateRowsAndCellIndexes(this.state, this._privateTypes);
1819
+ updateRowsAndCells(this.state, this._privateTypes);
1757
1820
  }
1758
1821
 
1759
1822
  updateVirtualizedRowHeights() {
@@ -1,5 +1,3 @@
1
- import { generateColKeyValue } from './columns';
2
-
3
1
  export const HEADER_ROW_INDEX = -1;
4
2
  export const HEADER_ROW_KEY = 'HEADER';
5
3
 
@@ -11,7 +9,7 @@ export function getCellFromIndexes(state, rowIndex, colIndex) {
11
9
  rowIndex === HEADER_ROW_INDEX
12
10
  ? HEADER_ROW_KEY
13
11
  : rows[rowIndex].key,
14
- colKeyValue: generateColKeyValue(columns[colIndex], colIndex),
12
+ colKeyValue: columns[colIndex].colKeyValue,
15
13
  };
16
14
  }
17
15
  return undefined;
@@ -94,7 +94,7 @@ export function handlePrefetch() {
94
94
  if (
95
95
  state.isLoading ||
96
96
  !state.enableInfiniteLoading ||
97
- (this.viewportRendering &&
97
+ (state.enableViewportRendering &&
98
98
  this._renderManager &&
99
99
  !this._renderManager.hasWrapperHeight()) ||
100
100
  !hasData(template)