lightning-base-components 1.14.3-alpha → 1.15.1-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 (152) hide show
  1. package/metadata/raptor.json +37 -4
  2. package/package.json +11 -4
  3. package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
  4. package/scopedImports/@salesforce-label-LightningModalBase.cancelandclose.js +1 -0
  5. package/scopedImports/@salesforce-label-LightningProgressBar.progressBar.js +1 -0
  6. package/src/lightning/alert/__docs__/alert.md +101 -0
  7. package/src/lightning/alert/__examples__disabled/basic/basic.css +7 -0
  8. package/src/lightning/alert/__examples__disabled/basic/basic.html +8 -0
  9. package/src/lightning/alert/__examples__disabled/basic/basic.js +14 -0
  10. package/src/lightning/alert/alert.html +3 -0
  11. package/src/lightning/alert/alert.js +78 -0
  12. package/src/lightning/alert/alert.js-meta.xml +6 -0
  13. package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +9 -0
  14. package/src/lightning/ariaObserver/ariaObserver.js +24 -35
  15. package/src/lightning/baseFormattedText/baseFormattedText.html +6 -1
  16. package/src/lightning/baseFormattedText/baseFormattedText.js +5 -0
  17. package/src/lightning/button/__wdio__/utam/utam.html +3 -0
  18. package/src/lightning/button/__wdio__/utam/utam.js +3 -0
  19. package/src/lightning/button/__wdio__/utam/utam.spec.js +20 -0
  20. package/src/lightning/buttonMenu/buttonMenu.js +12 -0
  21. package/src/lightning/confirm/__docs__/confirm.md +100 -0
  22. package/src/lightning/confirm/__examples__disabled/basic/basic.css +7 -0
  23. package/src/lightning/confirm/__examples__disabled/basic/basic.html +8 -0
  24. package/src/lightning/confirm/__examples__disabled/basic/basic.js +14 -0
  25. package/src/lightning/confirm/confirm.html +3 -0
  26. package/src/lightning/confirm/confirm.js +80 -0
  27. package/src/lightning/confirm/confirm.js-meta.xml +6 -0
  28. package/src/lightning/datatable/__examples__/withInfiniteLoading/fetchDataHelper.js +21 -0
  29. package/src/lightning/datatable/__examples__/withInfiniteLoading/withInfiniteLoading.html +13 -0
  30. package/src/lightning/datatable/__examples__/withInfiniteLoading/withInfiniteLoading.js +42 -0
  31. package/src/lightning/datatable/__wdio__/utam/utam.html +17 -0
  32. package/src/lightning/datatable/__wdio__/utam/utam.js +91 -0
  33. package/src/lightning/datatable/__wdio__/utam/utam.spec.js +189 -0
  34. package/src/lightning/datatable/autoWidthStrategy.js +170 -61
  35. package/src/lightning/datatable/{resizer.js → columnResizer.js} +0 -0
  36. package/src/lightning/datatable/columnWidthManager.js +226 -44
  37. package/src/lightning/datatable/columns.js +166 -71
  38. package/src/lightning/datatable/datatable.js +136 -60
  39. package/src/lightning/datatable/fixedWidthStrategy.js +43 -8
  40. package/src/lightning/datatable/headerActions.js +2 -2
  41. package/src/lightning/datatable/infiniteLoading.js +100 -28
  42. package/src/lightning/datatable/inlineEdit.js +21 -30
  43. package/src/lightning/datatable/keyboard.js +166 -131
  44. package/src/lightning/datatable/renderManager.js +117 -122
  45. package/src/lightning/datatable/{datatableResizeObserver.js → resizeObserver.js} +46 -29
  46. package/src/lightning/datatable/resizeSensor.js +19 -3
  47. package/src/lightning/datatable/rowSelection.js +1 -1
  48. package/src/lightning/datatable/rowSelectionShared.js +33 -20
  49. package/src/lightning/datatable/rows.js +9 -8
  50. package/src/lightning/datatable/sort.js +8 -8
  51. package/src/lightning/datatable/state.js +14 -2
  52. package/src/lightning/datatable/templates/div/div.html +133 -119
  53. package/src/lightning/datatable/templates/table/table.html +10 -2
  54. package/src/lightning/datatable/tree.js +25 -0
  55. package/src/lightning/datatable/types.js +77 -9
  56. package/src/lightning/datatable/utils.js +51 -24
  57. package/src/lightning/datatable/virtualization.js +319 -0
  58. package/src/lightning/datatable/widthManagerShared.js +27 -3
  59. package/src/lightning/datatable/wrapText.js +115 -48
  60. package/src/lightning/datepicker/__perf__DISABLED/datepickerWithCalendarOpen.perf.js +55 -0
  61. package/src/lightning/formattedDateTime/__docs__/formattedDateTime.md +36 -3
  62. package/src/lightning/formattedDateTime/__examples__/datetime/datetime.html +2 -2
  63. package/src/lightning/formattedDateTime/__examples__/datetime/datetime.js +3 -1
  64. package/src/lightning/formattedDateTime/__examples__/time/time.html +1 -1
  65. package/src/lightning/formattedDateTime/__examples__/time/time.js +3 -1
  66. package/src/lightning/formattedDateTime/formattedDateTime.js +1 -0
  67. package/src/lightning/iconSvgTemplates/buildTemplates/standard/dashboard_component.html +7 -0
  68. package/src/lightning/iconSvgTemplates/buildTemplates/standard/slack.html +7 -0
  69. package/src/lightning/iconSvgTemplates/buildTemplates/standard/tableau.html +7 -0
  70. package/src/lightning/iconSvgTemplates/buildTemplates/standard/travel_mode.html +2 -2
  71. package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +8 -1
  72. package/src/lightning/iconSvgTemplates/buildTemplates/utility/data_model.html +7 -0
  73. package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product.html +1 -1
  74. package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product_transaction.html +2 -1
  75. package/src/lightning/iconSvgTemplates/buildTemplates/utility/slack.html +7 -0
  76. package/src/lightning/iconSvgTemplates/buildTemplates/utility/tableau.html +7 -0
  77. package/src/lightning/iconSvgTemplates/buildTemplates/utility/video_off.html +7 -0
  78. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/dashboard_component.html +7 -0
  79. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/slack.html +7 -0
  80. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/tableau.html +7 -0
  81. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/travel_mode.html +2 -2
  82. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +8 -1
  83. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/data_model.html +7 -0
  84. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product.html +1 -1
  85. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
  86. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/slack.html +7 -0
  87. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/tableau.html +7 -0
  88. package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/video_off.html +7 -0
  89. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/dashboard_component.html +7 -0
  90. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/slack.html +7 -0
  91. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/tableau.html +7 -0
  92. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/travel_mode.html +2 -2
  93. package/src/lightning/iconSvgTemplatesStandard/buildTemplates/templates.js +4 -1
  94. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/dashboard_component.html +7 -0
  95. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/slack.html +7 -0
  96. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/tableau.html +7 -0
  97. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/travel_mode.html +2 -2
  98. package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/templates.js +4 -1
  99. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +5 -1
  100. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/data_model.html +7 -0
  101. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product.html +1 -1
  102. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product_transaction.html +2 -1
  103. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/slack.html +7 -0
  104. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/tableau.html +7 -0
  105. package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/video_off.html +7 -0
  106. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +5 -1
  107. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/data_model.html +7 -0
  108. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product.html +1 -1
  109. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
  110. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/slack.html +7 -0
  111. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/tableau.html +7 -0
  112. package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/video_off.html +7 -0
  113. package/src/lightning/input/__docs__/input.md +2 -0
  114. package/src/lightning/input/input.html +2 -5
  115. package/src/lightning/interactiveDialogBase/interactiveDialogBase.css +494 -0
  116. package/src/lightning/interactiveDialogBase/interactiveDialogBase.html +63 -0
  117. package/src/lightning/interactiveDialogBase/interactiveDialogBase.js +200 -0
  118. package/src/lightning/menuItem/menuItem.js +4 -1
  119. package/src/lightning/modalBase/modalBase.css +20 -0
  120. package/src/lightning/modalBase/modalBase.html +54 -0
  121. package/src/lightning/modalBase/modalBase.js +1039 -0
  122. package/src/lightning/overlay/__docs__/overlay.md +90 -0
  123. package/src/lightning/overlay/__examples__/alert/alert.html +27 -0
  124. package/src/lightning/overlay/__examples__/alert/alert.js +33 -0
  125. package/src/lightning/overlay/__examples__/basic/basic.css +7 -0
  126. package/src/lightning/overlay/__examples__/basic/basic.html +18 -0
  127. package/src/lightning/overlay/__examples__/basic/basic.js +61 -0
  128. package/src/lightning/overlay/__examples__/demo/demo.html +29 -0
  129. package/src/lightning/overlay/__examples__/demo/demo.js +40 -0
  130. package/src/lightning/overlay/__examples__/panel/panel.html +17 -0
  131. package/src/lightning/overlay/__examples__/panel/panel.js +21 -0
  132. package/src/lightning/overlay/overlay.html +3 -0
  133. package/src/lightning/overlay/overlay.js +45 -0
  134. package/src/lightning/overlayContainer/__docs__/overlayContainer.md +0 -0
  135. package/src/lightning/overlayContainer/overlayContainer.html +3 -0
  136. package/src/lightning/overlayContainer/overlayContainer.js +138 -0
  137. package/src/lightning/overlayManager/overlayManager.js +54 -0
  138. package/src/lightning/overlayUtils/overlayUtils.js +17 -0
  139. package/src/lightning/progressBar/progressBar.html +2 -1
  140. package/src/lightning/progressBar/progressBar.js +18 -1
  141. package/src/lightning/prompt/__docs__/prompt.md +102 -0
  142. package/src/lightning/prompt/__examples__disabled/basic/basic.css +7 -0
  143. package/src/lightning/prompt/__examples__disabled/basic/basic.html +8 -0
  144. package/src/lightning/prompt/__examples__disabled/basic/basic.js +15 -0
  145. package/src/lightning/prompt/prompt.css +81 -0
  146. package/src/lightning/prompt/prompt.html +8 -0
  147. package/src/lightning/prompt/prompt.js +92 -0
  148. package/src/lightning/prompt/prompt.js-meta.xml +6 -0
  149. package/src/lightning/spinner/spinner.html +1 -1
  150. package/src/lightning/spinner/spinner.js +12 -0
  151. package/src/lightning/utilsPrivate/phonify.js +1 -1
  152. package/scopedImports/@salesforce-label-LightningModalBase.close.js +0 -1
@@ -9,7 +9,7 @@ import {
9
9
  isSafari,
10
10
  synchronizeAttrs,
11
11
  } from 'lightning/utilsPrivate';
12
- import { LightningDatatableResizeObserver } from './datatableResizeObserver';
12
+ import { LightningDatatableResizeObserver } from './resizeObserver';
13
13
  import { ColumnWidthManager } from './columnWidthManager';
14
14
  import { getDefaultState } from './state';
15
15
  import { getColumns, normalizeColumns, generateHeaderIndexes } from './columns';
@@ -38,7 +38,7 @@ import {
38
38
  getCSSWidthStyleOfTable,
39
39
  updateColumnWidthsMetadata,
40
40
  getResizerDefaultState,
41
- } from './resizer';
41
+ } from './columnResizer';
42
42
  import {
43
43
  syncSelectedRowsKeys,
44
44
  handleRowSelectionChange,
@@ -81,6 +81,9 @@ import {
81
81
  addFocusStylesToActiveCell,
82
82
  refocusCellElement,
83
83
  isCellElement,
84
+ getActiveCellElement,
85
+ getDataRow,
86
+ FOCUS_CLASS,
84
87
  } from './keyboard';
85
88
  import {
86
89
  getRowNumberOffset,
@@ -135,14 +138,16 @@ import {
135
138
  import {
136
139
  isViewportRenderingEnabled,
137
140
  setViewportRendering,
138
- getDTRows,
139
- getDTRenderedRowCount,
140
- setDTRenderedRowCount,
141
141
  getDTWrapperHeight,
142
- normalizeVirtualization,
142
+ setVirtualize,
143
143
  RenderManager,
144
- DEFAULT_ROW_HEIGHT,
145
144
  } from './renderManager';
145
+ import {
146
+ handleVariableRowHeights,
147
+ resetRowHeights,
148
+ resetTableHeight,
149
+ findFirstVisibleIndex,
150
+ } from './virtualization';
146
151
 
147
152
  import { hasTreeDataType } from './tree';
148
153
  import { setErrors, getTableError, getErrors } from './errors';
@@ -200,14 +205,14 @@ export default class LightningDatatable extends LightningElement {
200
205
  _customerSelectedRows = null;
201
206
  _datatableId = generateUniqueId('lgt-datatable');
202
207
  _draftValues = [];
203
- _firstVisibleIndex = 0; // first row that should be visible in viewport, used for virtualization
204
208
  _isResizing = false; // Whether resizing is in progress
209
+ _lastRenderedRow = null; // last rendered row, used for UTAM
205
210
  _privateTypes = {};
206
211
  _privateWidthObserver = null; // Instance of LightningDatatableResizeObserver
207
212
  _renderMode = 'table';
208
- _renderedRowCount = 0;
213
+ _shouldResetFocus = false; // used to ensure focus isn't lost from changes in renderedRows
214
+ _shouldResetHeights = false;
209
215
  _suppressBottomBar = false;
210
- _virtualize = '';
211
216
 
212
217
  /************************* PUBLIC PROPERTIES *************************/
213
218
 
@@ -287,6 +292,7 @@ export default class LightningDatatable extends LightningElement {
287
292
  // do necessary updates since rows have changed
288
293
  if (hasValidKeyField(this.state)) {
289
294
  this.updateRowsState();
295
+ resetTableHeight(this.state);
290
296
  }
291
297
  if (this._customerSelectedRows) {
292
298
  this.setSelectedRows(this._customerSelectedRows);
@@ -342,6 +348,7 @@ export default class LightningDatatable extends LightningElement {
342
348
 
343
349
  set enableInfiniteLoading(value) {
344
350
  setInfiniteLoading(this.state, value);
351
+ handlePrefetch.call(this, this.template, this.state);
345
352
  }
346
353
 
347
354
  /**
@@ -519,24 +526,17 @@ export default class LightningDatatable extends LightningElement {
519
526
 
520
527
  set renderConfig(value) {
521
528
  if (typeof value === 'object' && !isIE11) {
522
- const { viewportRendering, virtualize } = value;
523
- setViewportRendering(this.state, viewportRendering);
524
- if (this.state.renderModeRoleBased) {
525
- this._virtualize = normalizeVirtualization(virtualize);
526
- }
529
+ setViewportRendering(this.state, value.viewportRendering);
527
530
 
528
531
  this._renderManager.configure(
529
- this.getRows,
532
+ this.state,
530
533
  this.getWrapperHeight,
531
- this.getRenderedRowCount,
532
- this.setRenderedRowCount,
533
534
  value
534
535
  );
535
536
  // if renderConfig already exists, update rendering
536
537
  if (this._renderConfig) {
537
538
  this._renderManager.updateViewportRendering(
538
- this.state.rows,
539
- this.setRenderedRowCount,
539
+ this.state,
540
540
  this.gridContainer,
541
541
  true
542
542
  );
@@ -565,6 +565,10 @@ export default class LightningDatatable extends LightningElement {
565
565
  validValues: ['default', 'role-based'],
566
566
  });
567
567
  this.state.renderModeRoleBased = this._renderMode === 'role-based';
568
+ this._columnWidthManager.setRenderMode(this.renderMode);
569
+ if (this._renderConfig) {
570
+ setVirtualize(this.state, this._renderConfig.virtualize);
571
+ }
568
572
  updateCellClassForRoleBasedMode(this.state);
569
573
  }
570
574
 
@@ -803,21 +807,23 @@ export default class LightningDatatable extends LightningElement {
803
807
  * virtualization is enabled
804
808
  */
805
809
  get computedTbodyStyle() {
806
- const style = [];
810
+ const style = {};
811
+ const { firstVisibleIndex, bufferSize, virtualize, tableHeight } =
812
+ this.state;
807
813
  if (
808
814
  hasRowNumberColumn(this.state) &&
809
815
  getRowNumberOffset(this.state) >= 0
810
816
  ) {
811
- style.push(
812
- 'counter-reset: row-number ' + getRowNumberOffset(this.state)
817
+ const firstRenderedRow = Math.max(
818
+ firstVisibleIndex - bufferSize,
819
+ 0
813
820
  );
821
+ const rowNumber = firstRenderedRow + getRowNumberOffset(this.state);
822
+ style['counter-reset'] = `row-number ${rowNumber}`;
814
823
  }
815
- if (this._virtualize) {
816
- const length = this.state.rows.length;
817
- style.push(
818
- 'position: relative',
819
- `height:${length * DEFAULT_ROW_HEIGHT}px`
820
- );
824
+ if (virtualize) {
825
+ style.position = 'relative';
826
+ style.height = `${tableHeight}px`;
821
827
  }
822
828
  return styleToString(style);
823
829
  }
@@ -938,18 +944,21 @@ export default class LightningDatatable extends LightningElement {
938
944
  }
939
945
 
940
946
  get renderedRows() {
941
- if (this._virtualize) {
947
+ const { virtualize, rows, renderedRowCount } = this.state;
948
+ if (virtualize) {
942
949
  const { firstIndex, lastIndex } =
943
- this._renderManager.getRenderedRange(
944
- this._firstVisibleIndex,
945
- this._renderedRowCount
946
- );
947
- return this.state.rows.slice(firstIndex, lastIndex);
950
+ this._renderManager.getRenderedRange(this.state);
951
+ this._lastRenderedRow = lastIndex + 1; // UTAM rows are 1-indexed
952
+ // we shouldn't lose focus from re-renders caused by a change in renderedRows
953
+ this._shouldResetFocus = true;
954
+ return rows.slice(firstIndex, lastIndex);
948
955
  }
949
956
  if (this.viewportRendering && !isIE11) {
950
- return this.state.rows.slice(0, this._renderedRowCount);
957
+ this._lastRenderedRow = renderedRowCount;
958
+ return rows.slice(0, renderedRowCount);
951
959
  }
952
- return this.state.rows;
960
+ this._lastRenderedRow = rows.length;
961
+ return rows;
953
962
  }
954
963
 
955
964
  get showSelectAllCheckbox() {
@@ -980,14 +989,10 @@ export default class LightningDatatable extends LightningElement {
980
989
  super();
981
990
 
982
991
  this._privateTypes = new DatatableTypes(this.constructor.customTypes);
983
-
984
992
  this._columnWidthManager = new ColumnWidthManager(this.widthsData);
985
993
  this.updateRowsAndCellIndexes = updateRowsAndCellIndexes.bind(this);
986
994
 
987
995
  this._renderManager = new RenderManager();
988
- this.getRenderedRowCount = getDTRenderedRowCount.bind(this);
989
- this.setRenderedRowCount = setDTRenderedRowCount.bind(this);
990
- this.getRows = getDTRows.bind(this);
991
996
  this.getWrapperHeight = getDTWrapperHeight.bind(this);
992
997
  }
993
998
 
@@ -1134,6 +1139,7 @@ export default class LightningDatatable extends LightningElement {
1134
1139
  if (fireResizeEvent) {
1135
1140
  this.fireOnResize(false);
1136
1141
  }
1142
+ this.updateTableAndScrollerStyleOnRender();
1137
1143
  }
1138
1144
 
1139
1145
  // Managing the cell widths is only required for the role-based table
@@ -1147,8 +1153,25 @@ export default class LightningDatatable extends LightningElement {
1147
1153
  this._customerSelectedRows = null;
1148
1154
  // set the previous focused cell to null after render is done
1149
1155
  resetCellToFocusFromPrev(state);
1156
+ // reset focus styles on re-render
1157
+ if (this._shouldResetFocus) {
1158
+ // since focus is now getting reset, can change this back to false
1159
+ this._shouldResetFocus = false;
1160
+ if (state.activeCell && state.activeCell.focused) {
1161
+ const cellElement = getActiveCellElement(template, state);
1162
+ if (
1163
+ cellElement &&
1164
+ cellElement.parentElement &&
1165
+ !cellElement.parentElement.classList.contains(FOCUS_CLASS)
1166
+ ) {
1167
+ setFocusActiveCell(template, state, null, null, false);
1168
+ }
1169
+ }
1170
+ }
1150
1171
 
1151
- if (this.viewportRendering || this._virtualize) {
1172
+ this.updateVirtualizedRowHeights();
1173
+
1174
+ if (this.viewportRendering || state.virtualize) {
1152
1175
  const resizeTarget = this.template.querySelector(
1153
1176
  'div.dt-outer-container'
1154
1177
  );
@@ -1159,10 +1182,9 @@ export default class LightningDatatable extends LightningElement {
1159
1182
  // Reset the row count if we already had one before updating the wrapper height.
1160
1183
  // This can happen if the number of rows was calculated before the datatable
1161
1184
  // was rendered.
1162
- if (this._renderedRowCount) {
1185
+ if (this.state.renderedRowCount) {
1163
1186
  this._renderManager.updateViewportRendering(
1164
- this.state.rows,
1165
- this.setRenderedRowCount,
1187
+ this.state,
1166
1188
  this.gridContainer,
1167
1189
  true
1168
1190
  );
@@ -1171,6 +1193,18 @@ export default class LightningDatatable extends LightningElement {
1171
1193
  }
1172
1194
  }
1173
1195
 
1196
+ updateTableAndScrollerStyleOnRender() {
1197
+ const role = '[role="' + this.computedTableRole + '"]';
1198
+ const tableElement = this.template.querySelector(role);
1199
+ const scrollYEle = this.template.querySelector('.slds-scrollable_y');
1200
+ if (tableElement) {
1201
+ tableElement.style = this.computedTableStyle;
1202
+ }
1203
+ if (scrollYEle) {
1204
+ scrollYEle.style = this.computedScrollerStyle;
1205
+ }
1206
+ }
1207
+
1174
1208
  disconnectedCallback() {
1175
1209
  if (this._privateWidthObserver) {
1176
1210
  this._privateWidthObserver.disconnect();
@@ -1248,16 +1282,13 @@ export default class LightningDatatable extends LightningElement {
1248
1282
  }
1249
1283
 
1250
1284
  handleInlineEditPanelScroll.call(this, event);
1251
- if (this._virtualize) {
1252
- this._firstVisibleIndex =
1253
- this._renderManager.getFirstVisibleIndex(event);
1254
- } else if (this.viewportRendering) {
1255
- this._renderManager.handleScroll(
1256
- this.state.rows,
1257
- this._renderedRowCount,
1258
- this.setRenderedRowCount,
1259
- event
1285
+ if (this.state.virtualize) {
1286
+ this.state.firstVisibleIndex = findFirstVisibleIndex(
1287
+ this.state,
1288
+ event.target.scrollTop
1260
1289
  );
1290
+ } else if (this.viewportRendering) {
1291
+ this._renderManager.handleScroll(this.state, event);
1261
1292
  }
1262
1293
  }
1263
1294
 
@@ -1349,6 +1380,7 @@ export default class LightningDatatable extends LightningElement {
1349
1380
  handleResizeEnd(event) {
1350
1381
  event.stopPropagation();
1351
1382
  this._isResizing = false;
1383
+ this._shouldResetHeights = true;
1352
1384
  }
1353
1385
 
1354
1386
  /**
@@ -1421,10 +1453,19 @@ export default class LightningDatatable extends LightningElement {
1421
1453
  * Handles the `focusout` event on <table> and the corresponding
1422
1454
  * <div> on the role-based table
1423
1455
  *
1456
+ * This gets called both when we expect the table to lose focus
1457
+ * and when the active cell loses focus after renderedRows changes
1458
+ * on a virtualized table, in which case we don't want to lose focus.
1459
+ *
1460
+ * We account for this by setting activeCell.focused to the value of
1461
+ * _shouldResetFocus, which will be true if and only if focus was
1462
+ * lost due to a renderedRows change for a virtualized table.
1463
+ *
1424
1464
  * @param {FocusEvent} event - `focusout`
1425
1465
  */
1426
1466
  handleTableFocusOut(event) {
1427
1467
  handleDatatableFocusOut.call(this, event);
1468
+ this.state.activeCell.focused = this._shouldResetFocus;
1428
1469
  }
1429
1470
 
1430
1471
  /**
@@ -1533,11 +1574,11 @@ export default class LightningDatatable extends LightningElement {
1533
1574
 
1534
1575
  this.updateRowsAndCellIndexes(state);
1535
1576
 
1536
- if (this.viewportRendering || this._virtualize) {
1577
+ if (this.viewportRendering || state.virtualize) {
1537
1578
  this._renderManager.updateViewportRendering(
1538
- this.state.rows,
1539
- this.setRenderedRowCount,
1540
- this.gridContainer
1579
+ this.state,
1580
+ this.gridContainer,
1581
+ !!state.virtualize
1541
1582
  );
1542
1583
  }
1543
1584
 
@@ -1578,7 +1619,7 @@ export default class LightningDatatable extends LightningElement {
1578
1619
  setDirtyValues(state, this._draftValues);
1579
1620
  updateRowNavigationMode(hadTreeDataTypePreviously, state);
1580
1621
  state.headerIndexes = generateHeaderIndexes(getColumns(state));
1581
- // Updates state.wrapText and when isWrapableType, sets internal header actions
1622
+ // Updates state.wrapText and when isWrappableType, sets internal header actions
1582
1623
  updateHeaderActions(state);
1583
1624
  this.updateRowsAndCellIndexes(state);
1584
1625
  updateBulkSelectionState(state);
@@ -1603,6 +1644,41 @@ export default class LightningDatatable extends LightningElement {
1603
1644
  }
1604
1645
  }
1605
1646
 
1647
+ updateVirtualizedRowHeights() {
1648
+ const state = this.state;
1649
+ const virtualizedRows = state.virtualize && this.renderedRows.length;
1650
+
1651
+ // no need to handle other virtualization/row height logic
1652
+ // if heights need to be reset
1653
+ if (this._shouldResetHeights) {
1654
+ resetRowHeights(state);
1655
+ this._shouldResetHeights = false;
1656
+ } else if (virtualizedRows && !state.fixedHeight) {
1657
+ // if row heights aren't fixed, we need to update items
1658
+ // in state to know where rows should be positioned
1659
+ handleVariableRowHeights(this.template, state, this.renderedRows);
1660
+ } else if (virtualizedRows && state.fixedHeight) {
1661
+ // if heights are fixed, we only need to check height of first row
1662
+ const rowElement = this.template.querySelector(
1663
+ getDataRow(this.renderedRows[0].key)
1664
+ );
1665
+ // increase height by 1 since first rendered row is missing an extra 1px border
1666
+ if (rowElement) {
1667
+ const height = rowElement.getBoundingClientRect().height + 1;
1668
+ if (state.rowHeight !== height) {
1669
+ state.rowHeight = height;
1670
+ resetTableHeight(state);
1671
+ state.rows.forEach((row) => {
1672
+ row.style = styleToString({
1673
+ position: 'absolute',
1674
+ top: `${row.rowIndex * height}px`,
1675
+ });
1676
+ });
1677
+ }
1678
+ }
1679
+ }
1680
+ }
1681
+
1606
1682
  setSelectedRows(value) {
1607
1683
  setSelectedRowsKeys(this.state, value);
1608
1684
  handleRowSelectionChange.call(this);
@@ -1622,7 +1698,7 @@ export default class LightningDatatable extends LightningElement {
1622
1698
  }
1623
1699
 
1624
1700
  /**
1625
- * @return {Object} containing the visible dimensions of the table { left, right, top, bottom, }
1701
+ * @returns {Object} containing the visible dimensions of the table { left, right, top, bottom, }
1626
1702
  */
1627
1703
  getViewableRect() {
1628
1704
  const scrollerX = this.template
@@ -3,13 +3,26 @@ import {
3
3
  getColumnWidthFromDef,
4
4
  } from './widthManagerShared';
5
5
 
6
+ /**
7
+ * Determines the expected table width
8
+ *
9
+ * @param {Number} availableWidth The available width for the entire table
10
+ * @param {Object} widthsMetadata The widths metadata object
11
+ * @returns {Number} The expected width of the table
12
+ */
6
13
  function getExpectedTableWidth(availableWidth, widthsMetadata) {
7
14
  const minExpectedTableWidth = getMinExpectedTableWidth(widthsMetadata);
8
- return hasNoFlexibleColumns(widthsMetadata)
15
+ return widthsMetadata.totalFlexibleColumns === 0
9
16
  ? minExpectedTableWidth
10
17
  : Math.max(minExpectedTableWidth, availableWidth);
11
18
  }
12
19
 
20
+ /**
21
+ * Determines the minimum expected table width
22
+ *
23
+ * @param {Object} widthsMetadata The widths metadata object
24
+ * @returns {Number} The minimum expected table width
25
+ */
13
26
  function getMinExpectedTableWidth(widthsMetadata) {
14
27
  const {
15
28
  totalFixedWidth,
@@ -21,21 +34,35 @@ function getMinExpectedTableWidth(widthsMetadata) {
21
34
  return minTotalFlexibleWidth + totalFixedWidth + totalResizedWidth;
22
35
  }
23
36
 
24
- function hasNoFlexibleColumns(widthsMetadata) {
25
- return widthsMetadata.totalFlexibleColumns === 0;
26
- }
27
-
37
+ /**
38
+ * Strategy for columns with defined fixed widths.
39
+ */
28
40
  export class FixedWidthStrategy {
41
+ // Private variables
29
42
  _columnWidthMetaData = {};
30
43
 
44
+ /************************** LIFECYCLE HOOKS **************************/
45
+
31
46
  constructor(minColumnWidth, maxColumnWidth) {
32
47
  this._columnWidthMetaData = { minColumnWidth, maxColumnWidth };
33
48
  }
34
49
 
50
+ /************************** PRIVATE SETTERS **************************/
51
+
52
+ /**
53
+ * Sets the minimum column width
54
+ *
55
+ * @param {Number} value The minimum width
56
+ */
35
57
  set minColumnWidth(value) {
36
58
  this._columnWidthMetaData.minColumnWidth = value;
37
59
  }
38
60
 
61
+ /**
62
+ * Sets the maximum column width
63
+ *
64
+ * @param {Number} value The maximum width
65
+ */
39
66
  set maxColumnWidth(value) {
40
67
  this._columnWidthMetaData.maxColumnWidth = value;
41
68
  }
@@ -43,9 +70,10 @@ export class FixedWidthStrategy {
43
70
  /**
44
71
  * Get adjusted column widths either from defined widths in columnDefs or by dividing total width
45
72
  * equally amongst the possible columns
46
- * @param datatableInterface - interface to datatable with callbacks giving width information
47
- * @param columnDefs - column definitions array with defined widths and other attributes
48
- * @returns {object} with columnWidths: [], expectedTableWidth: (number)
73
+ *
74
+ * @param {Object} datatableInterface Interface to datatable with callbacks giving width information
75
+ * @param {Array} columnDefs Ccolumn definitions array with defined widths and other attributes
76
+ * @returns {Object} columnWidths: [], expectedTableWidth: (number)
49
77
  */
50
78
  getAdjustedColumnWidths(datatableInterface, columnDefs) {
51
79
  const widthsMetadata = getTotalWidthsMetadata(
@@ -73,6 +101,13 @@ export class FixedWidthStrategy {
73
101
  return { columnWidths, expectedTableWidth };
74
102
  }
75
103
 
104
+ /**
105
+ * Determines the expected flexible column width
106
+ *
107
+ * @param {Object} widthsMetadata The widths metadata object
108
+ * @param {Number} totalTableWidth The total available width for the table
109
+ * @returns {Number} The column width
110
+ */
76
111
  _getFlexibleColumnWidth(widthsMetadata, totalTableWidth) {
77
112
  const {
78
113
  totalFixedWidth,
@@ -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;
@@ -1,34 +1,67 @@
1
1
  import { normalizeBoolean } from 'lightning/utilsPrivate';
2
2
  import { getScrollOffsetFromTableEnd, isNonNegativeInteger } from './utils';
3
3
 
4
- const SCROLLABLE_CONTAINER_SEL = '.slds-scrollable_y';
5
4
  const SCROLL_ALLOWANCE = 2;
5
+ export const DEFAULT_LOAD_MORE_OFFSET = 20;
6
6
 
7
- export function getInfiniteLoadingDefaultState() {
8
- return {
9
- enableInfiniteLoading: false,
10
- loadMoreOffset: 20,
11
- isLoading: false,
12
- };
13
- }
7
+ /*********************** STATE MANAGEMENT ************************/
14
8
 
9
+ /**
10
+ * Returns whether the datatable is in a loading state
11
+ *
12
+ * @param {Object} state The datatable state object
13
+ * @returns {Boolean} The loading state
14
+ */
15
15
  export function isLoading(state) {
16
16
  return state.isLoading;
17
17
  }
18
+
19
+ /**
20
+ * Sets the loading state of the datatable
21
+ *
22
+ * @param {Object} state The datatable state object
23
+ * @param {Boolean} value The loading state to set
24
+ */
18
25
  export function setLoading(state, value) {
19
26
  state.isLoading = normalizeBoolean(value);
20
27
  }
21
28
 
29
+ /**
30
+ * Returns whether infinite loading is enabled on the datatable
31
+ *
32
+ * @param {Object} state The datatable state object
33
+ * @returns {Boolean} The infinite loading state
34
+ */
22
35
  export function isInfiniteLoadingEnabled(state) {
23
36
  return state.enableInfiniteLoading;
24
37
  }
38
+
39
+ /**
40
+ * Sets the infinite loading option on the datatable
41
+ *
42
+ * @param {Object} state The datatable state object
43
+ * @param {Boolean} value The infinite loading state to set
44
+ */
25
45
  export function setInfiniteLoading(state, value) {
26
46
  state.enableInfiniteLoading = normalizeBoolean(value);
27
47
  }
28
48
 
49
+ /**
50
+ * Returns the load more offset
51
+ *
52
+ * @param {Object} state The datatable state object
53
+ * @returns {Number} The currently configured load more offset value
54
+ */
29
55
  export function getLoadMoreOffset(state) {
30
56
  return state.loadMoreOffset;
31
57
  }
58
+
59
+ /**
60
+ * Sets the load more offset value. Must be a number >= 0.
61
+ *
62
+ * @param {Object} state The datatable state object
63
+ * @param {Boolean} value The load more offset value to set
64
+ */
32
65
  export function setLoadMoreOffset(state, value) {
33
66
  if (!isNonNegativeInteger(value)) {
34
67
  // eslint-disable-next-line no-console
@@ -40,9 +73,17 @@ export function setLoadMoreOffset(state, value) {
40
73
 
41
74
  state.loadMoreOffset = isNonNegativeInteger(value)
42
75
  ? parseInt(value, 10)
43
- : getInfiniteLoadingDefaultState().loadMoreOffset;
76
+ : DEFAULT_LOAD_MORE_OFFSET;
44
77
  }
45
78
 
79
+ /************************** PUBLIC METHODS ***************************/
80
+
81
+ /**
82
+ * Checks whether the datatable should begin loading more content
83
+ * and then dispatches the `loadmore` event indicating that directive.
84
+ *
85
+ * @param {Event} event
86
+ */
46
87
  export function handleLoadMoreCheck(event) {
47
88
  if (isLoading(this.state)) {
48
89
  return;
@@ -60,24 +101,13 @@ export function handleLoadMoreCheck(event) {
60
101
  }
61
102
  }
62
103
 
63
- function isScrollable(element) {
64
- // scrollHeight should be greater than clientHeight by some allowance
65
- return (
66
- element &&
67
- element.scrollHeight > element.clientHeight + SCROLL_ALLOWANCE
68
- );
69
- }
70
-
71
- function isScrollerVisible(elem) {
72
- return (
73
- elem && !!(elem.offsetParent || elem.offsetHeight || elem.offsetWidth)
74
- );
75
- }
76
-
77
- function hasData(root) {
78
- return root.querySelectorAll('tbody > tr').length > 0;
79
- }
80
-
104
+ /**
105
+ * Determines whether or not to prefetch data. If so,
106
+ * dispatches the `loadmore` event.
107
+ *
108
+ * @param {Object} root The datatable
109
+ * @param {Object} state The datatable state object
110
+ */
81
111
  export function handlePrefetch(root, state) {
82
112
  if (
83
113
  !isInfiniteLoadingEnabled(state) ||
@@ -91,9 +121,51 @@ export function handlePrefetch(root, state) {
91
121
  return;
92
122
  }
93
123
 
94
- const elem = root.querySelector(SCROLLABLE_CONTAINER_SEL);
124
+ const elem = root.querySelector('.slds-scrollable_y');
95
125
 
96
126
  if (isScrollerVisible(elem) && !isScrollable(elem)) {
97
127
  this.dispatchEvent(new CustomEvent('loadmore'));
98
128
  }
99
129
  }
130
+
131
+ /************************** PRIVATE METHODS ***************************/
132
+
133
+ /**
134
+ * Determines if a DOM element is scrollable
135
+ *
136
+ * @param {Element} element The DOM element to check
137
+ * @returns {Boolean} Whether or not the element is scrollable
138
+ */
139
+ function isScrollable(element) {
140
+ // scrollHeight should be greater than clientHeight by some allowance
141
+ return (
142
+ element &&
143
+ element.scrollHeight > element.clientHeight + SCROLL_ALLOWANCE
144
+ );
145
+ }
146
+
147
+ /**
148
+ * Determines if a DOM element's scroll bars are visible
149
+ *
150
+ * @param {Element} element The DOM element to check
151
+ * @returns {Boolean} Whether or not the element's scroll bars are visible
152
+ */
153
+ function isScrollerVisible(element) {
154
+ return (
155
+ element &&
156
+ !!(element.offsetParent || element.offsetHeight || element.offsetWidth)
157
+ );
158
+ }
159
+
160
+ /**
161
+ * Determines if a root element has data
162
+ *
163
+ * @param {Element} root The parent element to check
164
+ * @returns {Boolean} Whether or not the element contains any data
165
+ */
166
+ function hasData(root) {
167
+ return (
168
+ root.querySelectorAll('tbody > tr, [role="rowgroup"] > [role="row"]')
169
+ .length > 0
170
+ );
171
+ }