lightning-base-components 1.21.4-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 (104) hide show
  1. package/metadata/raptor.json +2 -1
  2. package/package.json +9 -1
  3. package/scopedImports/@salesforce-label-LightningLookup.messageWhenSearchTermTooShort.js +1 -0
  4. package/src/lightning/accordion/__docs__/accordion.md +0 -4
  5. package/src/lightning/accordionSection/__docs__/accordionSection.md +0 -4
  6. package/src/lightning/avatar/__docs__/avatar.md +0 -4
  7. package/src/lightning/badge/__docs__/badge.md +0 -4
  8. package/src/lightning/badge/badge.slds.css +1 -1
  9. package/src/lightning/barcodeScanner/__docs__/barcodeScanner.md +0 -4
  10. package/src/lightning/baseCombobox/baseCombobox.js +2 -2
  11. package/src/lightning/baseComboboxItem/baseComboboxItem.js +6 -10
  12. package/src/lightning/button/__docs__/button.md +3 -7
  13. package/src/lightning/buttonGroup/__docs__/buttonGroup.md +0 -4
  14. package/src/lightning/buttonIcon/__docs__/buttonIcon.md +0 -4
  15. package/src/lightning/buttonIconStateful/__docs__/buttonIconStateful.md +0 -4
  16. package/src/lightning/buttonMenu/__docs__/buttonMenu.md +0 -4
  17. package/src/lightning/buttonStateful/__docs__/buttonStateful.md +0 -4
  18. package/src/lightning/buttonStateful/buttonStateful.html +5 -3
  19. package/src/lightning/buttonStateful/buttonStateful.js +4 -0
  20. package/src/lightning/card/__docs__/card.md +0 -4
  21. package/src/lightning/card/card.js-meta.xml +3 -0
  22. package/src/lightning/carousel/__docs__/carousel.md +0 -4
  23. package/src/lightning/checkboxGroup/__docs__/checkboxGroup.md +0 -4
  24. package/src/lightning/combobox/__docs__/combobox.md +0 -4
  25. package/src/lightning/combobox/form-element.slds.css +4 -1
  26. package/src/lightning/datatable/columnWidthManager.js +3 -3
  27. package/src/lightning/datatable/columns.js +17 -18
  28. package/src/lightning/datatable/datatable.js +146 -84
  29. package/src/lightning/datatable/indexes.js +1 -3
  30. package/src/lightning/datatable/infiniteLoading.js +1 -1
  31. package/src/lightning/datatable/inlineEdit.js +10 -7
  32. package/src/lightning/datatable/keyboard.js +21 -44
  33. package/src/lightning/datatable/renderManager.js +9 -18
  34. package/src/lightning/datatable/rows.js +112 -128
  35. package/src/lightning/datatable/sort.js +35 -14
  36. package/src/lightning/datatable/state.js +5 -0
  37. package/src/lightning/datatable/tree.js +0 -33
  38. package/src/lightning/datatable/utils.js +15 -5
  39. package/src/lightning/datepicker/datepicker.js +12 -3
  40. package/src/lightning/datepicker/form-element.slds.css +4 -1
  41. package/src/lightning/datetimepicker/form-element.slds.css +4 -1
  42. package/src/lightning/dualListbox/__docs__/dualListbox.md +0 -4
  43. package/src/lightning/dualListbox/form-element.slds.css +4 -1
  44. package/src/lightning/dynamicIcon/__docs__/dynamicIcon.md +0 -4
  45. package/src/lightning/formattedDateTime/__docs__/formattedDateTime.md +0 -4
  46. package/src/lightning/formattedLocation/__docs__/formattedLocation.md +0 -4
  47. package/src/lightning/formattedName/__docs__/formattedName.md +0 -4
  48. package/src/lightning/formattedNumber/__docs__/formattedNumber.md +0 -4
  49. package/src/lightning/formattedPhone/__docs__/formattedPhone.md +0 -4
  50. package/src/lightning/formattedText/__docs__/formattedText.md +0 -4
  51. package/src/lightning/formattedTime/__docs__/formattedTime.md +0 -4
  52. package/src/lightning/formattedUrl/__docs__/formattedUrl.md +0 -4
  53. package/src/lightning/groupedCombobox/form-element.slds.css +4 -1
  54. package/src/lightning/helptext/form-element.slds.css +4 -1
  55. package/src/lightning/icon/__docs__/icon.md +0 -4
  56. package/src/lightning/input/form-element.slds.css +4 -1
  57. package/src/lightning/inputAddress/form-element.slds.css +4 -1
  58. package/src/lightning/inputAddress/inputAddress.js +13 -7
  59. package/src/lightning/inputLocation/__docs__/inputLocation.md +0 -4
  60. package/src/lightning/inputLocation/form-element.slds.css +4 -1
  61. package/src/lightning/inputName/form-element.slds.css +4 -1
  62. package/src/lightning/layout/__docs__/layout.md +0 -4
  63. package/src/lightning/layoutItem/__docs__/layoutItem.md +0 -4
  64. package/src/lightning/lookupAddress/form-element.slds.css +4 -1
  65. package/src/lightning/menuItem/__docs__/menuItem.md +0 -4
  66. package/src/lightning/menuSubheader/menu-subheader.slds.css +1 -1
  67. package/src/lightning/modalBase/modalBase.js +14 -31
  68. package/src/lightning/pill/__docs__/pill.md +0 -4
  69. package/src/lightning/pillContainer/__docs__/pillContainer.md +0 -4
  70. package/src/lightning/primitiveBubble/primitiveBubble.js +26 -11
  71. package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +1 -1
  72. package/src/lightning/primitiveInputCheckbox/form-element.slds.css +4 -1
  73. package/src/lightning/primitiveInputCheckboxButton/form-element.slds.css +4 -1
  74. package/src/lightning/primitiveInputColor/form-element.slds.css +4 -1
  75. package/src/lightning/primitiveInputFile/form-element.slds.css +4 -1
  76. package/src/lightning/primitiveInputSimple/form-element.slds.css +4 -1
  77. package/src/lightning/primitiveInputToggle/form-element.slds.css +4 -1
  78. package/src/lightning/progressBar/progress-bar.slds.css +1 -1
  79. package/src/lightning/radioGroup/__docs__/radioGroup.md +0 -4
  80. package/src/lightning/radioGroup/form-element.slds.css +4 -1
  81. package/src/lightning/relativeDateTime/__docs__/relativeDateTime.md +0 -4
  82. package/src/lightning/select/form-element.slds.css +4 -1
  83. package/src/lightning/slider/__docs__/slider.md +0 -4
  84. package/src/lightning/spinner/__docs__/spinner.md +0 -4
  85. package/src/lightning/tab/__docs__/tab.md +0 -4
  86. package/src/lightning/tabset/__docs__/tabset.md +0 -4
  87. package/src/lightning/textarea/__docs__/textarea.md +0 -4
  88. package/src/lightning/textarea/__examples__/various/various.html +18 -1
  89. package/src/lightning/textarea/form-element.slds.css +4 -1
  90. package/src/lightning/textarea/textarea.js +25 -0
  91. package/src/lightning/tile/__docs__/tile.md +0 -4
  92. package/src/lightning/timepicker/form-element.slds.css +4 -1
  93. package/src/lightning/tree/__docs__/tree.md +0 -4
  94. package/src/lightning/tree/tree.js +5 -1
  95. package/src/lightning/verticalNavigation/__docs__/verticalNavigation.md +0 -4
  96. package/src/lightning/verticalNavigationItem/__docs__/verticalNavigationItem.md +0 -4
  97. package/src/lightning/verticalNavigationItem/vertical-navigation-item.slds.css +1 -1
  98. package/src/lightning/verticalNavigationItemBadge/__docs__/verticalNavigationItemBadge.md +0 -4
  99. package/src/lightning/verticalNavigationItemBadge/badge.slds.css +1 -1
  100. package/src/lightning/verticalNavigationItemBadge/vertical-navigation-item.slds.css +1 -1
  101. package/src/lightning/verticalNavigationItemIcon/__docs__/verticalNavigationItemIcon.md +0 -4
  102. package/src/lightning/verticalNavigationItemIcon/vertical-navigation-item.slds.css +1 -1
  103. package/src/lightning/verticalNavigationOverflow/vertical-navigation-item.slds.css +1 -1
  104. package/src/lightning/datatable/columns-shared.js +0 -12
@@ -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,
@@ -126,8 +121,10 @@ import {
126
121
  import {
127
122
  getGridContainerFromScrollerY,
128
123
  getRowDataSelector,
129
- getScrollerXFromScrollerY,
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
  }
@@ -1011,8 +1005,7 @@ export default class LightningDatatable extends LightningElement {
1011
1005
  this._privateTypes = new DatatableTypes(this.constructor.customTypes);
1012
1006
 
1013
1007
  this._renderManager = new RenderManager();
1014
- this.getWrapperHeight = () =>
1015
- getScrollerXFromScrollerY(getScrollerY(this.template)).offsetHeight;
1008
+ this.getWrapperHeight = () => getScrollerX(this.template).offsetHeight;
1016
1009
  }
1017
1010
 
1018
1011
  /**
@@ -1101,11 +1094,17 @@ export default class LightningDatatable extends LightningElement {
1101
1094
  }
1102
1095
 
1103
1096
  renderedCallback() {
1104
- const { _columnWidthManager, state, template, widthsData } = this;
1097
+ const {
1098
+ _columnWidthManager,
1099
+ gridContainer,
1100
+ state,
1101
+ template,
1102
+ widthsData,
1103
+ } = this;
1105
1104
 
1106
1105
  // This keeps underlying table element up to date if the aria-* properties on this element is dynamically changed.
1107
1106
  // It does the work of removing and adding the attribute if the value is empty(ish) or a normal string.
1108
- synchronizeAttrs(this.gridContainer, {
1107
+ synchronizeAttrs(gridContainer, {
1109
1108
  'aria-label': this.ariaLabel,
1110
1109
  'aria-labelledby': this.ariaLabelledBy,
1111
1110
  'aria-describedby': this.ariaDescribedBy,
@@ -1123,6 +1122,10 @@ export default class LightningDatatable extends LightningElement {
1123
1122
  columns,
1124
1123
  widthsData
1125
1124
  );
1125
+ // Managing cell widths is required for role-based render mode.
1126
+ if (state.renderModeRoleBased) {
1127
+ recomputeCellStyles(state);
1128
+ }
1126
1129
  if (fireResizeEvent) {
1127
1130
  this.fireOnResize(false);
1128
1131
  }
@@ -1141,6 +1144,10 @@ export default class LightningDatatable extends LightningElement {
1141
1144
  state.columns,
1142
1145
  widthsData
1143
1146
  );
1147
+ // Managing cell widths is required for role-based render mode.
1148
+ if (state.renderModeRoleBased) {
1149
+ recomputeCellStyles(state);
1150
+ }
1144
1151
  }
1145
1152
  );
1146
1153
  this._widthObserver = _widthObserver;
@@ -1148,12 +1155,6 @@ export default class LightningDatatable extends LightningElement {
1148
1155
  _widthObserver.observe(template);
1149
1156
  }
1150
1157
 
1151
- // Managing the cell widths is only required for the role-based table
1152
- if (state.renderModeRoleBased) {
1153
- // TODO: Look to further optimize - Do this only when required
1154
- recomputeCellStyles(this.privateTypes, state);
1155
- }
1156
-
1157
1158
  handlePrefetch.call(this);
1158
1159
 
1159
1160
  // customerSelectedRows is only valid till render, after it, the one
@@ -1170,7 +1171,7 @@ export default class LightningDatatable extends LightningElement {
1170
1171
  const { activeCell } = state;
1171
1172
  if (
1172
1173
  activeCell &&
1173
- activeCell.focused &&
1174
+ activeCell.hasFocus &&
1174
1175
  !state.inlineEdit.isPanelVisible
1175
1176
  ) {
1176
1177
  const cellElement = getActiveCellElement(template, state);
@@ -1185,23 +1186,36 @@ export default class LightningDatatable extends LightningElement {
1185
1186
  }
1186
1187
  }
1187
1188
 
1188
- this.updateVirtualizedRowHeights();
1189
+ const { hasRenderedFirstTime } = state;
1190
+ const virtualize = !!state.virtualize;
1191
+ const { length: rowCount } = state.rows;
1189
1192
 
1190
- if (this.viewportRendering || state.virtualize) {
1191
- const resizeTarget = this.template.querySelector(
1192
- 'div.dt-outer-container'
1193
- );
1194
- this._renderManager.connectResizeObserver(resizeTarget);
1195
- if (!this._renderManager.hasWrapperHeight()) {
1196
- 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);
1197
1211
 
1198
1212
  // Reset the row count if we already had one before updating the wrapper height.
1199
1213
  // This can happen if the number of rows was calculated before the datatable
1200
1214
  // was rendered.
1201
- if (this.state.renderedRowCount) {
1202
- this._renderManager.updateViewportRendering(
1203
- this.state,
1204
- this.gridContainer,
1215
+ if (state.renderedRowCount) {
1216
+ _renderManager.updateViewportRendering(
1217
+ state,
1218
+ gridContainer,
1205
1219
  true
1206
1220
  );
1207
1221
  }
@@ -1325,16 +1339,16 @@ export default class LightningDatatable extends LightningElement {
1325
1339
  this.state,
1326
1340
  event.target.scrollTop
1327
1341
  );
1328
- } else if (this.viewportRendering) {
1342
+ } else if (state.enableViewportRendering) {
1329
1343
  this._renderManager.handleScroll(state, event);
1330
1344
  }
1331
1345
  }
1332
1346
 
1333
1347
  /**
1334
- * Handles the `click` event on the <table> element and
1348
+ * Handles the 'click' event on the <table> element and
1335
1349
  * the corresponding <div> in the role-based table
1336
1350
  *
1337
- * @param {MouseEvent} event - `click`
1351
+ * @param {MouseEvent} event - 'click'
1338
1352
  */
1339
1353
  handleTableCellClick(event) {
1340
1354
  // handles the case when clicking on the margin/pading of the td/th
@@ -1344,20 +1358,22 @@ export default class LightningDatatable extends LightningElement {
1344
1358
  const { rowKeyValue, colKeyValue } =
1345
1359
  target.querySelector(':first-child');
1346
1360
 
1347
- const { state, template } = this;
1361
+ const { state } = this;
1348
1362
  if (
1349
1363
  state.rowMode ||
1350
1364
  !isActiveCell(state, rowKeyValue, colKeyValue)
1351
1365
  ) {
1352
- if (state.rowMode && state.activeCell) {
1366
+ if (state.activeCell && state.rowMode) {
1367
+ // Untracked state change.
1353
1368
  unsetRowNavigationMode(state);
1354
1369
  const { rowIndex } = getIndexesActiveCell(state);
1370
+ // Tracked state change.
1355
1371
  updateRowTabIndex(state, rowIndex, -1);
1356
1372
  }
1357
1373
  this.setActiveCell(rowKeyValue, colKeyValue);
1358
1374
  }
1359
1375
 
1360
- if (!datatableHasFocus(state, template)) {
1376
+ if (!datatableHasFocus(state, this.template)) {
1361
1377
  setCellClickedForFocus(state);
1362
1378
  }
1363
1379
  }
@@ -1370,8 +1386,36 @@ export default class LightningDatatable extends LightningElement {
1370
1386
  */
1371
1387
  handleUpdateColumnSort(event) {
1372
1388
  event.stopPropagation();
1373
- const { fieldName, columnKey, sortDirection } = event.detail;
1374
- 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
+ }
1375
1419
  }
1376
1420
 
1377
1421
  handleCheckboxHeaderId(event) {
@@ -1394,6 +1438,10 @@ export default class LightningDatatable extends LightningElement {
1394
1438
  colIndex,
1395
1439
  delta
1396
1440
  );
1441
+ // Managing cell widths is required for role-based render mode.
1442
+ if (state.renderModeRoleBased) {
1443
+ recomputeCellStyles(state);
1444
+ }
1397
1445
  this.fireOnResize(true);
1398
1446
  this.fixHeaderForSafari();
1399
1447
  }
@@ -1453,7 +1501,7 @@ export default class LightningDatatable extends LightningElement {
1453
1501
  const { rowKeyValue, colKeyValue, needsRefocusOnCellElement } =
1454
1502
  event.detail;
1455
1503
  if (!isActiveCell(state, rowKeyValue, colKeyValue)) {
1456
- if (state.rowMode && state.activeCell) {
1504
+ if (state.activeCell && state.rowMode) {
1457
1505
  unsetRowNavigationMode(state);
1458
1506
  const { rowIndex } = getIndexesActiveCell(state);
1459
1507
  updateRowTabIndex(state, rowIndex, -1);
@@ -1495,7 +1543,7 @@ export default class LightningDatatable extends LightningElement {
1495
1543
  * and when the active cell loses focus after renderedRows changes
1496
1544
  * on a virtualized table, in which case we don't want to lose focus.
1497
1545
  *
1498
- * 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
1499
1547
  * _shouldResetFocus, which will be true if and only if focus was
1500
1548
  * lost due to a renderedRows change for a virtualized table.
1501
1549
  *
@@ -1505,7 +1553,7 @@ export default class LightningDatatable extends LightningElement {
1505
1553
  handleDatatableFocusOut.call(this, event);
1506
1554
  const { activeCell } = this.state;
1507
1555
  if (activeCell) {
1508
- activeCell.focused = this._shouldResetFocus;
1556
+ activeCell.hasFocus = this._shouldResetFocus;
1509
1557
  }
1510
1558
  }
1511
1559
 
@@ -1622,10 +1670,24 @@ export default class LightningDatatable extends LightningElement {
1622
1670
  );
1623
1671
  }
1624
1672
 
1625
- fireSortedColumnChange(fieldName, columnKey, sortDirection) {
1673
+ fireSortedColumnChange(
1674
+ fieldNames,
1675
+ sortDirections,
1676
+ isMultiColumnSort,
1677
+ fieldName,
1678
+ columnKey,
1679
+ sortDirection
1680
+ ) {
1626
1681
  this.dispatchEvent(
1627
1682
  new CustomEvent('sort', {
1628
- detail: { fieldName, columnKey, sortDirection },
1683
+ detail: {
1684
+ fieldNames,
1685
+ sortDirections,
1686
+ isMultiColumnSort,
1687
+ fieldName,
1688
+ columnKey,
1689
+ sortDirection,
1690
+ },
1629
1691
  })
1630
1692
  );
1631
1693
  }
@@ -1646,7 +1708,7 @@ export default class LightningDatatable extends LightningElement {
1646
1708
 
1647
1709
  /************************* HELPER FUNCTIONS **************************/
1648
1710
 
1649
- updateRowsState() {
1711
+ updateRows() {
1650
1712
  this.updateRowsBeforeIndexes();
1651
1713
  this.updateRowsAndCells();
1652
1714
  this.updateRowsAfterIndexes();
@@ -1659,7 +1721,7 @@ export default class LightningDatatable extends LightningElement {
1659
1721
 
1660
1722
  updateRowsAfterIndexes() {
1661
1723
  const { state, widthsData } = this;
1662
- if (this.viewportRendering || state.virtualize) {
1724
+ if (state.enableViewportRendering || state.virtualize) {
1663
1725
  this._renderManager.updateViewportRendering(
1664
1726
  state,
1665
1727
  this.gridContainer,
@@ -1711,15 +1773,15 @@ export default class LightningDatatable extends LightningElement {
1711
1773
 
1712
1774
  updateColumnsBeforeIndexes(columns) {
1713
1775
  const { state } = this;
1714
- const hadTreeDataTypePreviously = hasTreeDataType(state);
1715
1776
  // Untracked state changes.
1716
1777
  // Calculate cell to focus next before indexes are updated.
1717
1778
  setCellToFocusFromPrev(state, this.template);
1718
- normalizeColumns(state, columns, this.privateTypes);
1719
- updateRowNavigationMode(hadTreeDataTypePreviously, state);
1779
+ setColumns(state, columns, this.privateTypes);
1780
+ updateRowNavigationMode(state);
1720
1781
  // Tracked state changes.
1721
1782
  setDirtyValues(state, this._draftValues);
1722
- // 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.
1723
1785
  updateHeaderInternalActions(state);
1724
1786
  }
1725
1787
 
@@ -1754,7 +1816,7 @@ export default class LightningDatatable extends LightningElement {
1754
1816
  }
1755
1817
 
1756
1818
  updateRowsAndCells() {
1757
- updateRowsAndCellIndexes(this.state, this._privateTypes);
1819
+ updateRowsAndCells(this.state, this._privateTypes);
1758
1820
  }
1759
1821
 
1760
1822
  updateVirtualizedRowHeights() {
@@ -1819,7 +1881,7 @@ export default class LightningDatatable extends LightningElement {
1819
1881
  const { template } = this;
1820
1882
  const scrollerY = getScrollerY(template);
1821
1883
  const scrollerYRect = scrollerY.getBoundingClientRect();
1822
- const scrollerX = getScrollerXFromScrollerY(scrollerY);
1884
+ const scrollerX = getScrollerX(template);
1823
1885
  const scrollerXRect = scrollerX.getBoundingClientRect();
1824
1886
 
1825
1887
  return {
@@ -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)
@@ -12,7 +12,7 @@ import {
12
12
  NAVIGATION_DIR,
13
13
  isValidCell,
14
14
  } from './keyboard';
15
- import { updateRowsAndCellIndexes, isCellEditable } from './rows';
15
+ import { updateRowsAndCells } from './rows';
16
16
  import { getStateColumnIndex } from './columns';
17
17
  import { resetErrors } from './errors';
18
18
  import { setAriaSelectedOnCell, unsetAriaSelectedOnCell } from './rowSelection';
@@ -160,7 +160,8 @@ export function cancelInlineEdit(dt) {
160
160
  const { state, _privateTypes } = dt;
161
161
  resetErrors(state);
162
162
  state.inlineEdit.dirtyValues = {};
163
- updateRowsAndCellIndexes(state, _privateTypes);
163
+ dt._draftValues = [];
164
+ updateRowsAndCells(state, _privateTypes);
164
165
  }
165
166
 
166
167
  export function closeInlineEdit(dt) {
@@ -246,7 +247,7 @@ function processInlineEditFinish(dt, reason, rowKeyValue, colKeyValue) {
246
247
  dispatchCellChangeEvent(dt, changes);
247
248
 
248
249
  // TODO: do we need to update all rows in the dt or just the one that was modified?
249
- updateRowsAndCellIndexes(state, dt._privateTypes);
250
+ updateRowsAndCells(state, dt._privateTypes);
250
251
  }
251
252
  }
252
253
 
@@ -571,8 +572,7 @@ function getResolvedCellChanges(state, rowChanges) {
571
572
  const colIndex = getStateColumnIndex(state, colKeyValue);
572
573
  if (colIndex !== -1) {
573
574
  const col = columns[colIndex];
574
- cellChanges[col.columnKey || col.fieldName] =
575
- colChanges[colKeyValue];
575
+ cellChanges[col.name] = colChanges[colKeyValue];
576
576
  }
577
577
  }
578
578
  result.push(cellChanges);
@@ -709,13 +709,16 @@ function getFirstEditableCell(dt) {
709
709
  if (editableColumnsLength > 0) {
710
710
  const { rows } = state;
711
711
  for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) {
712
- const { key: rowKeyValue } = rows[rowIndex];
712
+ const row = rows[rowIndex];
713
+ const { key: rowKeyValue } = row;
713
714
  for (let i = 0; i < editableColumnsLength; i += 1) {
714
715
  // Loop through the editable columns in order and examine the
715
716
  // corresponding cells in the current row for editability,
716
717
  // returning the first such cell that is editable.
717
718
  const editableColumn = editableColumns[i];
718
- if (isCellEditable(rows[rowIndex], editableColumn)) {
719
+ const { colKeyValue } = editableColumns[i];
720
+ const cell = row.cells[getStateColumnIndex(state, colKeyValue)];
721
+ if (cell && cell.editable) {
719
722
  return {
720
723
  rowKeyValue,
721
724
  colKeyValue: editableColumn.colKeyValue,