lightning-base-components 1.14.6-alpha → 1.15.2-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 (169) hide show
  1. package/metadata/raptor.json +31 -4
  2. package/package.json +13 -2
  3. package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
  4. package/scopedImports/@salesforce-label-LightningMap.defaultTitle.js +1 -0
  5. package/scopedImports/@salesforce-label-LightningProgressBar.progressBar.js +1 -0
  6. package/src/lightning/alert/__docs__/alert.md +99 -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/baseCombobox/baseCombobox.html +2 -1
  14. package/src/lightning/baseCombobox/baseCombobox.js +41 -6
  15. package/src/lightning/button/__wdio__/utam/utam.html +3 -0
  16. package/src/lightning/button/__wdio__/utam/utam.js +3 -0
  17. package/src/lightning/button/__wdio__/utam/utam.spec.js +20 -0
  18. package/src/lightning/button/button.js +22 -1
  19. package/src/lightning/buttonMenu/buttonMenu.js +12 -0
  20. package/src/lightning/checkboxGroup/checkboxGroup.html +2 -2
  21. package/src/lightning/checkboxGroup/checkboxGroup.js +9 -5
  22. package/src/lightning/combobox/__docs__/combobox.md +3 -1
  23. package/src/lightning/combobox/combobox.js +0 -1
  24. package/src/lightning/confirm/__docs__/confirm.md +98 -0
  25. package/src/lightning/confirm/__examples__disabled/basic/basic.css +7 -0
  26. package/src/lightning/confirm/__examples__disabled/basic/basic.html +8 -0
  27. package/src/lightning/confirm/__examples__disabled/basic/basic.js +14 -0
  28. package/src/lightning/confirm/confirm.html +3 -0
  29. package/src/lightning/confirm/confirm.js +80 -0
  30. package/src/lightning/confirm/confirm.js-meta.xml +6 -0
  31. package/src/lightning/datatable/__docs__/datatable.md +45 -0
  32. package/src/lightning/datatable/__wdio__/utam/utam.html +32 -0
  33. package/src/lightning/datatable/__wdio__/utam/utam.js +91 -0
  34. package/src/lightning/datatable/__wdio__/utam/utam.spec.js +214 -0
  35. package/src/lightning/datatable/columns.js +166 -71
  36. package/src/lightning/datatable/datatable.js +103 -20
  37. package/src/lightning/datatable/headerActions.js +2 -2
  38. package/src/lightning/datatable/inlineEdit.js +0 -5
  39. package/src/lightning/datatable/inlineEditShared.js +4 -2
  40. package/src/lightning/datatable/keyboard.js +17 -13
  41. package/src/lightning/datatable/renderManager.js +45 -13
  42. package/src/lightning/datatable/resizeSensor.js +11 -3
  43. package/src/lightning/datatable/rowSelection.js +9 -3
  44. package/src/lightning/datatable/rowSelectionShared.js +33 -20
  45. package/src/lightning/datatable/rows.js +3 -2
  46. package/src/lightning/datatable/sort.js +8 -8
  47. package/src/lightning/datatable/state.js +9 -1
  48. package/src/lightning/datatable/templates/div/div.html +6 -2
  49. package/src/lightning/datatable/templates/table/table.html +7 -4
  50. package/src/lightning/datatable/tree.js +25 -0
  51. package/src/lightning/datatable/types.js +77 -9
  52. package/src/lightning/datatable/utils.js +51 -24
  53. package/src/lightning/datatable/virtualization.js +319 -0
  54. package/src/lightning/datatable/wrapText.js +54 -16
  55. package/src/lightning/datepicker/__perf__DISABLED/datepickerWithCalendarOpen.perf.js +55 -0
  56. package/src/lightning/datepicker/datepicker.html +1 -0
  57. package/src/lightning/datepicker/datepicker.js +10 -0
  58. package/src/lightning/datetimepicker/datetimepicker.html +2 -0
  59. package/src/lightning/datetimepicker/datetimepicker.js +8 -0
  60. package/src/lightning/dualListbox/dualListbox.js +2 -1
  61. package/src/lightning/formattedAddress/__docs__/formattedAddress.md +3 -0
  62. package/src/lightning/formattedAddress/__examples__/customLocale/customLocale.html +22 -0
  63. package/src/lightning/formattedAddress/__examples__/customLocale/customLocale.js +3 -0
  64. package/src/lightning/formattedAddress/formattedAddress.js +7 -1
  65. package/src/lightning/groupedCombobox/groupedCombobox.html +2 -1
  66. package/src/lightning/groupedCombobox/groupedCombobox.js +16 -2
  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 +6 -0
  115. package/src/lightning/input/input.js +2 -1
  116. package/src/lightning/inputAddress/__docs__/inputAddress.md +5 -0
  117. package/src/lightning/inputAddress/__examples__/customLocale/customLocale.html +12 -0
  118. package/src/lightning/inputAddress/__examples__/customLocale/customLocale.js +3 -0
  119. package/src/lightning/inputAddress/inputAddress.html +2 -0
  120. package/src/lightning/inputAddress/inputAddress.js +26 -3
  121. package/src/lightning/inputName/__docs__/inputName.md +2 -0
  122. package/src/lightning/inputName/inputName.html +4 -1
  123. package/src/lightning/inputUtils/inputUtils.js +11 -0
  124. package/src/lightning/interactiveDialogBase/interactiveDialogBase.css +494 -0
  125. package/src/lightning/interactiveDialogBase/interactiveDialogBase.html +63 -0
  126. package/src/lightning/interactiveDialogBase/interactiveDialogBase.js +200 -0
  127. package/src/lightning/menuItem/menuItem.js +4 -1
  128. package/src/lightning/modalBase/modalBase.css +20 -0
  129. package/src/lightning/modalBase/modalBase.html +54 -0
  130. package/src/lightning/modalBase/modalBase.js +1039 -0
  131. package/src/lightning/overlay/__docs__/overlay.md +90 -0
  132. package/src/lightning/overlay/__examples__/alert/alert.html +27 -0
  133. package/src/lightning/overlay/__examples__/alert/alert.js +33 -0
  134. package/src/lightning/overlay/__examples__/basic/basic.css +7 -0
  135. package/src/lightning/overlay/__examples__/basic/basic.html +18 -0
  136. package/src/lightning/overlay/__examples__/basic/basic.js +61 -0
  137. package/src/lightning/overlay/__examples__/demo/demo.html +29 -0
  138. package/src/lightning/overlay/__examples__/demo/demo.js +40 -0
  139. package/src/lightning/overlay/__examples__/panel/panel.html +17 -0
  140. package/src/lightning/overlay/__examples__/panel/panel.js +21 -0
  141. package/src/lightning/overlay/overlay.html +3 -0
  142. package/src/lightning/overlay/overlay.js +45 -0
  143. package/src/lightning/overlayContainer/__docs__/overlayContainer.md +0 -0
  144. package/src/lightning/overlayContainer/overlayContainer.html +3 -0
  145. package/src/lightning/overlayContainer/overlayContainer.js +138 -0
  146. package/src/lightning/overlayManager/overlayManager.js +54 -0
  147. package/src/lightning/overlayUtils/overlayUtils.js +17 -0
  148. package/src/lightning/picklist/picklist.js +6 -1
  149. package/src/lightning/progressBar/progressBar.html +2 -1
  150. package/src/lightning/progressBar/progressBar.js +18 -1
  151. package/src/lightning/prompt/__docs__/prompt.md +100 -0
  152. package/src/lightning/prompt/__examples__disabled/basic/basic.css +7 -0
  153. package/src/lightning/prompt/__examples__disabled/basic/basic.html +8 -0
  154. package/src/lightning/prompt/__examples__disabled/basic/basic.js +15 -0
  155. package/src/lightning/prompt/prompt.css +81 -0
  156. package/src/lightning/prompt/prompt.html +8 -0
  157. package/src/lightning/prompt/prompt.js +92 -0
  158. package/src/lightning/prompt/prompt.js-meta.xml +6 -0
  159. package/src/lightning/radioGroup/radioGroup.js +9 -0
  160. package/src/lightning/select/select.html +3 -1
  161. package/src/lightning/select/select.js +5 -1
  162. package/src/lightning/textarea/textarea.html +1 -0
  163. package/src/lightning/textarea/textarea.js +5 -0
  164. package/src/lightning/timepicker/timepicker.html +3 -1
  165. package/src/lightning/timepicker/timepicker.js +8 -0
  166. package/src/lightning/utilsPrivate/aria.js +26 -0
  167. package/src/lightning/utilsPrivate/linkify.js +1 -1
  168. package/src/lightning/utilsPrivate/utilsPrivate.js +7 -1
  169. package/src/lightning/icon/__component__/icon-spirite.spec.js +0 -59
@@ -0,0 +1,319 @@
1
+ import { styleToString } from './utils';
2
+
3
+ /**
4
+ * sets an initial table height in the datatable state
5
+ *
6
+ * @param {Object} state - datatable state
7
+ */
8
+ export function resetTableHeight(state) {
9
+ state.tableHeight = state.rowHeight * state.rows.length;
10
+ }
11
+
12
+ /**
13
+ * resets state properties relevant to virtualization
14
+ * rowHeights when fixedHeight is false
15
+ *
16
+ * @param {Object} state - datatable state
17
+ */
18
+ export function resetRowHeights(state) {
19
+ state.heightCache = {};
20
+ state.offsets = [0];
21
+ state.offsetRanges = [];
22
+ if (state.virtualize && state.rows.length) {
23
+ resetTableHeight(state);
24
+ }
25
+ }
26
+
27
+ /**
28
+ * updates state properties relevant to virtualization
29
+ * rowHeights when fixedHeight is false
30
+ *
31
+ * @param {Node} template - the custom element root `this.template` from datatable.js
32
+ * @param {Object} state - datatable state
33
+ * @param {Array} renderedRows - array of rows currently being rendered
34
+ */
35
+ export function handleVariableRowHeights(template, state, renderedRows) {
36
+ const currentRange = {
37
+ start: renderedRows[0].rowIndex,
38
+ end: renderedRows[renderedRows.length - 1].rowIndex + 1,
39
+ };
40
+ let adjustFromIndex;
41
+ let adjustmentValue = 0;
42
+ let offsetRangeIndex = findOffsetRangeIndex(
43
+ state.offsetRanges,
44
+ currentRange.start
45
+ );
46
+
47
+ renderedRows.forEach((row) => {
48
+ if (!state.heightCache[row.key]) {
49
+ // need to get row actual element so we can find its height
50
+ const rowElement = template.querySelector(
51
+ `[data-row-key-value="${row.key}"]`
52
+ );
53
+ if (rowElement) {
54
+ // first rendered row needs height increased by 1 to account for missing border
55
+ let height = rowElement.getBoundingClientRect().height;
56
+ if (row.rowIndex === currentRange.start) {
57
+ height++;
58
+ }
59
+ state.heightCache[row.key] = height;
60
+
61
+ // calculate estimate of row offset
62
+ setOffset(state, row, offsetRangeIndex, height);
63
+
64
+ // update variables used to adjust later row offsets
65
+ adjustmentValue += height - state.rowHeight;
66
+ adjustFromIndex = row.rowIndex + 2;
67
+ }
68
+ }
69
+ });
70
+ state.tableHeight += adjustmentValue;
71
+ updateOffsetRanges(
72
+ state,
73
+ offsetRangeIndex,
74
+ currentRange,
75
+ adjustFromIndex,
76
+ adjustmentValue
77
+ );
78
+ updateVirtualizeStyles(template, state, renderedRows);
79
+ }
80
+
81
+ /**
82
+ * uses binary search with offsets and offsetRange
83
+ * to determine what the first visible index should be
84
+ * for a given scrollTop value
85
+ */
86
+ export function findFirstVisibleIndex(state, scrollTop) {
87
+ const { offsetRanges, offsets, rowHeight, fixedHeight, virtualize } = state;
88
+ if (virtualize && fixedHeight) {
89
+ return scrollTop / rowHeight;
90
+ }
91
+ let start = 0;
92
+ let end = offsetRanges.length - 1;
93
+
94
+ while (start <= end) {
95
+ let mid = Math.floor((start + end) / 2);
96
+ const prevRange = offsetRanges[mid];
97
+ const nextRange = offsetRanges[mid + 1];
98
+ const startOffset = offsets[prevRange.start];
99
+ const endOffset = offsets[prevRange.end];
100
+
101
+ const scrollTopAfterPrevStart = startOffset <= scrollTop;
102
+ const scrollTopInPrevRange =
103
+ scrollTopAfterPrevStart && scrollTop <= endOffset;
104
+ const scrollTopBeforeNextRange =
105
+ !nextRange || scrollTop < offsets[nextRange.start];
106
+ const scrollTopBetweenRanges =
107
+ scrollTopAfterPrevStart && scrollTopBeforeNextRange;
108
+
109
+ // check if scrollTop is in prevAdj offset values
110
+ // or between prevAdj and nextAdj offsetValues
111
+ if (scrollTopInPrevRange) {
112
+ // find offset in prevRange to use for firstVisibleIndex
113
+ return searchForOffset(state, prevRange, scrollTop);
114
+ } else if (scrollTopBetweenRanges) {
115
+ // use scrollTop and rowHeight to calculate firstVisibleIndex
116
+ const diff = scrollTop - endOffset;
117
+ const extraRows = Math.floor(diff / rowHeight);
118
+ state._firstRowOffset = diff % rowHeight;
119
+ return prevRange.end + extraRows;
120
+ }
121
+ // update start or end for next round of binary search
122
+ if (scrollTop < startOffset) {
123
+ end = mid - 1;
124
+ } else {
125
+ start = mid + 1;
126
+ }
127
+ }
128
+ return -1;
129
+ }
130
+
131
+ /**
132
+ * determines the rowIndex for given scrollTop
133
+ * within a provided offset range using binary search
134
+ * also sets firstRowOffset to correct value
135
+ *
136
+ * @param {object} range - object with start and end index for binary search
137
+ * @param {number} scrollTop - value to find offset rowIndex for
138
+ * @returns {number} representing firstVisibleIndex for given scrollTop
139
+ */
140
+ function searchForOffset(state, range, scrollTop) {
141
+ let { start, end } = range;
142
+ const offsets = state.offsets;
143
+
144
+ while (start <= end) {
145
+ const mid = Math.floor((start + end) / 2);
146
+ const currentOffsetUnderScrollTop = offsets[mid] <= scrollTop;
147
+ const nextOffsetUnderScrollTop =
148
+ offsets[mid + 1] && offsets[mid + 1] <= scrollTop;
149
+
150
+ if (currentOffsetUnderScrollTop && !nextOffsetUnderScrollTop) {
151
+ // store how many pixels scrollTop is from top of row
152
+ state.firstRowOffset = scrollTop - offsets[mid];
153
+ return mid;
154
+ } else if (currentOffsetUnderScrollTop) {
155
+ start = mid + 1;
156
+ } else {
157
+ end = mid - 1;
158
+ }
159
+ }
160
+ return -1;
161
+ }
162
+
163
+ /**
164
+ * uses a binary search to find the offsetRange index that
165
+ * encompasses the provided row index, or the one immediately
166
+ * before if no offsetRange encompasses the provided rowIndex
167
+ */
168
+ function findOffsetRangeIndex(offsetRanges, rowIndex) {
169
+ let start = 0;
170
+ let end = offsetRanges.length - 1;
171
+ while (start <= end) {
172
+ let mid = Math.floor((start + end) / 2);
173
+ const currentRangeStartsBeforeRowIndex =
174
+ offsetRanges[mid].start <= rowIndex;
175
+ const nextRangeStartsBeforeRowIndex =
176
+ offsetRanges[mid + 1] && offsetRanges[mid + 1].start <= rowIndex;
177
+
178
+ // check if rowIndex is between start of range at "mid"
179
+ // and start of range at "mid + 1" (or if there is no "mid + 1")
180
+ if (
181
+ currentRangeStartsBeforeRowIndex &&
182
+ !nextRangeStartsBeforeRowIndex
183
+ ) {
184
+ return mid;
185
+ } else if (currentRangeStartsBeforeRowIndex) {
186
+ // look for earlier offsetRanges
187
+ start = mid + 1;
188
+ } else {
189
+ // look for later offsetRanges
190
+ end = mid - 1;
191
+ }
192
+ }
193
+ return -1;
194
+ }
195
+
196
+ /**
197
+ * sets the offset value for a given row and the next
198
+ * based on the closest set offset value, the default
199
+ * row height and the height of the current row
200
+ *
201
+ * @param {object} state - datatable state
202
+ * @param {object} row - specific row object from state
203
+ * @param {number} offsetRangeIndex - index of offset range to use for row
204
+ * @param {number} height - height of row's node
205
+ */
206
+ function setOffset(state, row, offsetRangeIndex, height) {
207
+ let currentRange = state.offsetRanges[offsetRangeIndex];
208
+ let currentOffset = state.offsets[row.rowIndex];
209
+ // if no offset is set for current row, estimate it
210
+ // based on most recent offset and default rowHeight
211
+ if (!currentOffset) {
212
+ currentOffset = 0;
213
+ if (currentRange) {
214
+ const baseOffset = state.offsets[currentRange.end];
215
+ const estimatedRowOffsets =
216
+ (row.rowIndex - currentRange.end) * state.rowHeight;
217
+ currentOffset = baseOffset + estimatedRowOffsets;
218
+ state.offsets[row.rowIndex] = currentOffset;
219
+ }
220
+ }
221
+ // set next offset based on current offset and height
222
+ state.offsets[row.rowIndex + 1] = currentOffset + height;
223
+ }
224
+
225
+ /**
226
+ * merges or adds new offset range and
227
+ * updates offsets and range values as needed
228
+ *
229
+ * @param {number} offsetRangeIndex
230
+ * @param {*} state - datatable state
231
+ * @param {object} currentRange - range for current rendered rows
232
+ * @param {number} adjustFromIndex - first index to increase by rangeValue
233
+ * @param {number} rangeValue - amount to increase offsets after adjustFromIndex
234
+ */
235
+ function updateOffsetRanges(
236
+ state,
237
+ offsetRangeIndex,
238
+ currentRange,
239
+ adjustFromIndex,
240
+ adjustmentValue
241
+ ) {
242
+ const { offsets, offsetRanges } = state;
243
+ let prevRange = offsetRanges[offsetRangeIndex];
244
+ let nextRange = offsetRanges[offsetRangeIndex + 1];
245
+ const overlapsWithPrevRange =
246
+ prevRange && checkOverlap(prevRange, currentRange);
247
+ const overlapsWithNextRange =
248
+ nextRange && checkOverlap(currentRange, nextRange);
249
+
250
+ // update remaining values in next range by
251
+ // adjustment value if we're overlapping it
252
+ if (overlapsWithNextRange && adjustmentValue) {
253
+ for (let i = adjustFromIndex; i <= nextRange.end; i++) {
254
+ offsets[i] = offsets[i] + adjustmentValue;
255
+ }
256
+ }
257
+
258
+ // update state.offsetRanges
259
+ if (overlapsWithPrevRange && overlapsWithNextRange) {
260
+ nextRange.start = prevRange.start;
261
+ nextRange.end = Math.max(currentRange.end, nextRange.end);
262
+ state.offsetRanges.splice(offsetRangeIndex, 1); // removes prevRange
263
+ } else if (overlapsWithPrevRange) {
264
+ prevRange.end = Math.max(prevRange.end, currentRange.end);
265
+ } else if (overlapsWithNextRange) {
266
+ nextRange.start = currentRange.start;
267
+ nextRange.end = Math.max(currentRange.end, nextRange.end);
268
+ // increase offsetRangeIndex; since it's values have already been updated
269
+ // we want to skip it when adjusting offsets in later ranges
270
+ offsetRangeIndex = offsetRangeIndex + 1;
271
+ } else {
272
+ state.offsetRanges.splice(offsetRangeIndex + 1, 0, currentRange);
273
+ // need to increase offsetRangeIndex so we don't
274
+ // unnecessarily add adjustmentValue to currentRange
275
+ offsetRangeIndex = offsetRangeIndex + 1;
276
+ }
277
+
278
+ // loop through every offset range after the current one
279
+ // and increase the offset for each index by adjustmentValue
280
+ if (offsetRangeIndex >= 0) {
281
+ for (let i = offsetRangeIndex + 1; i < offsetRanges.length; i++) {
282
+ const { start: rangeStart, end: rangeEnd } = offsetRanges[i];
283
+ for (let j = rangeStart; j <= rangeEnd; j++) {
284
+ offsets[j] = offsets[j] + adjustmentValue;
285
+ }
286
+ }
287
+ }
288
+ }
289
+
290
+ /**
291
+ * compares start/end of two ranges to see if the values overlap
292
+ * used to determine if renderedRows are part of an existent offsetRange
293
+ * or if a new offsetRange will need to be added
294
+ */
295
+ function checkOverlap(range1, range2) {
296
+ return (
297
+ (range1.start <= range2.start && range2.start <= range1.end) ||
298
+ (range1.start <= range2.end && range2.end <= range1.end)
299
+ );
300
+ }
301
+
302
+ /**
303
+ * updates scrollTop and top values for rows when
304
+ * using virtualization with fixedHeight of false
305
+ */
306
+ function updateVirtualizeStyles(template, state, renderedRows) {
307
+ // update scrollTop so firstVisibleIndex is correctly placed in viewport
308
+ const scrollerY = template.querySelector('.slds-scrollable_y');
309
+ scrollerY.scrollTop =
310
+ state.offsets[state.firstVisibleIndex] + state.firstRowOffset;
311
+
312
+ // update top of rendered rows based on offsets
313
+ renderedRows.forEach((row) => {
314
+ row.style = styleToString({
315
+ position: 'absolute',
316
+ top: `${state.offsets[row.rowIndex]}px`,
317
+ });
318
+ });
319
+ }
@@ -1,7 +1,7 @@
1
1
  import labelClipText from '@salesforce/label/LightningDatatable.clipText';
2
2
  import labelWrapText from '@salesforce/label/LightningDatatable.wrapText';
3
- import { getStateColumnIndex, getColumns } from './columns';
4
3
  import { normalizeBoolean } from 'lightning/utilsPrivate';
4
+ import { getStateColumnIndex, getColumns } from './columns';
5
5
  import { normalizeNumberAttribute } from './utils';
6
6
  import { getDefaultState } from './state';
7
7
 
@@ -22,13 +22,28 @@ const i18n = {
22
22
 
23
23
  /************************** WRAP TEXT STATE **************************/
24
24
 
25
- // Returns a boolean representing whether or not the column should be text wrapped
25
+ /**
26
+ * Returns a boolean representing whether or not the column should be text wrapped
27
+ *
28
+ * NOTE: Wrap text is not supported in IE, so default parameters are fine here.
29
+ *
30
+ * @param {Object} state Datatable's state object
31
+ * @param {String} colKeyValue The column key value to look up wrap text configuration
32
+ * @returns {Boolean} Whether the text is currently wrapped
33
+ */
26
34
  export function getWrapTextState(state = getDefaultState(), colKeyValue) {
27
35
  return state.wrapText[colKeyValue] || WRAP_TEXT_DEFAULT;
28
36
  }
29
37
 
30
- // Sets a boolean value in state's wrapText object against the column key value
31
- // representing whether or not the column is text wrapped
38
+ /**
39
+ * Sets a boolean value in state's wrapText object against the column key value
40
+ * representing whether or not the column is text wrapped.
41
+ *
42
+ * NOTE: Wrap text is not supported in IE, so default parameters are fine here.
43
+ *
44
+ * @param {Object} state Datatable's state object
45
+ * @param {Object} columnDefinition Datatable's column definitions
46
+ */
32
47
  export function setWrapTextState(state = getDefaultState(), columnDefinition) {
33
48
  const { colKeyValue, type, wrapText } = columnDefinition;
34
49
 
@@ -40,8 +55,13 @@ export function setWrapTextState(state = getDefaultState(), columnDefinition) {
40
55
 
41
56
  /************************** WRAP TEXT MAX LINES **************************/
42
57
 
43
- // Normalizes and sets wrapTextMaxLines in datatable's state object
44
- // The normalized value should be a positive integer or it'll fall back to undefined
58
+ /**
59
+ * Normalizes and sets wrapTextMaxLines in datatable's state object.
60
+ * The normalized value should be a positive integer or it'll fall back to undefined.
61
+ *
62
+ * @param {Object} state Datatable's state object
63
+ * @param {Integer} value The maximum lines allowed
64
+ */
45
65
  export function setWrapTextMaxLines(state, value) {
46
66
  state.wrapTextMaxLines = normalizeNumberAttribute(
47
67
  'wrapTextMaxLines',
@@ -51,8 +71,14 @@ export function setWrapTextMaxLines(state, value) {
51
71
  );
52
72
  }
53
73
 
54
- // Sets the `wrapText` and `wrapTextMaxLines` values in the cell object for all cells in a column
55
- // These values are used by primitiveCellFactory to set the required classes on the cell for wrapping
74
+ /**
75
+ * Sets the `wrapText` and `wrapTextMaxLines` values in the cell object for all cells in a column.
76
+ * These values are used by primitiveCellFactory to set the required classes on the cell for wrapping
77
+ *
78
+ * @param {Object} state Datatable's state object
79
+ * @param {Number} colIndex The column index to update
80
+ * @param {String} colKeyValue The column key value to look up wrap text configuration
81
+ */
56
82
  function updateWrapTextAndMaxLinesValuesInCells(state, colIndex, colKeyValue) {
57
83
  state.rows.forEach((row) => {
58
84
  const cell = row.cells[colIndex];
@@ -70,9 +96,9 @@ function updateWrapTextAndMaxLinesValuesInCells(state, colIndex, colKeyValue) {
70
96
  * provides - Wrap Text and Clip Text.
71
97
  * Each header action contains a label, title, action name and its selected value (checked)
72
98
  *
73
- * @param {Object} state - datatable's state object
74
- * @param {Object} columnDefinition - datatable's column definitions
75
- * @returns
99
+ * @param {Object} state Datatable's state object
100
+ * @param {Object} columnDefinition Datatable's column definitions
101
+ * @returns {Array} An array of wrap text actions
76
102
  */
77
103
  export function getActions(state, columnDefinition) {
78
104
  const wrapTextActions = [];
@@ -108,15 +134,16 @@ export function getActions(state, columnDefinition) {
108
134
  * needs to be changed in the state, change it to the new value and update
109
135
  * the check mark to represent the currently selected action
110
136
  *
111
- * @param {Object} state - datatable's state object
112
- * @param {String} action - action that was selected/triggered
113
- * @param {String} colKeyValue - column key value
137
+ * @param {Object} state Datatable's state object
138
+ * @param {String} action Action that was selected/triggered
139
+ * @param {String} colKeyValue Column key value
114
140
  */
115
141
  export function handleTriggeredAction(state, action, colKeyValue) {
116
142
  const actionName = action.name;
117
143
  if (actionName === 'wrapText' || actionName === 'clipText') {
118
144
  // If state should be changed
119
145
  if (state.wrapText[colKeyValue] !== (actionName === 'wrapText')) {
146
+ state.shouldResetHeights = true;
120
147
  state.wrapText[colKeyValue] = actionName === 'wrapText';
121
148
 
122
149
  updateSelectedOptionInHeaderActions(state, colKeyValue);
@@ -124,8 +151,13 @@ export function handleTriggeredAction(state, action, colKeyValue) {
124
151
  }
125
152
  }
126
153
 
127
- // Update the 'checked' value of the each action to show which action is selected
128
- // and which action is not selected
154
+ /**
155
+ * Update the 'checked' value of the each action to show which action is selected
156
+ * and which action is not selected.
157
+ *
158
+ * @param {Object} state The datatable state.
159
+ * @param {String} colKeyValue The column key.
160
+ */
129
161
  function updateSelectedOptionInHeaderActions(state, colKeyValue) {
130
162
  const columns = getColumns(state);
131
163
  const colIndex = getStateColumnIndex(state, colKeyValue);
@@ -148,6 +180,12 @@ function updateSelectedOptionInHeaderActions(state, colKeyValue) {
148
180
 
149
181
  /************************** HELPER FUNCTIONS **************************/
150
182
 
183
+ /**
184
+ * Determines if a given column type is wrappable.
185
+ *
186
+ * @param {String} type The type to check.
187
+ * @returns {Boolean} Whether the given type is wrappable.
188
+ */
151
189
  function isWrappableType(type) {
152
190
  return NON_WRAPPABLE_TYPES.indexOf(type) < 0;
153
191
  }
@@ -0,0 +1,55 @@
1
+ import { createElement } from 'lwc';
2
+ import Element from 'lightning/datepicker';
3
+
4
+ describe('datepicker-with-calendar-open', () => {
5
+ let element;
6
+ const createDatepicker = () => {
7
+ const datePicker = createElement(
8
+ 'lightning-datepicker-with-calendar-open',
9
+ { is: Element }
10
+ );
11
+ element.label = 'Datepicker';
12
+ element.min = '2019-01-10';
13
+ element.max = '2022-02-10';
14
+ element.value = '2019-01-20';
15
+ return datePicker;
16
+ };
17
+
18
+ benchmark('create and append', () => {
19
+ run(() => {
20
+ element = createDatepicker();
21
+ document.body.appendChild(element);
22
+ });
23
+ });
24
+
25
+ // disabled due to shadowRoot
26
+ // benchmark('open calendar', () => {
27
+ // run(() => {
28
+ // element.shadowRoot.querySelector('input').click();
29
+ // });
30
+ // });
31
+
32
+ // benchmark('go to previous month', () => {
33
+ // run(() => {
34
+ // element.shadowRoot
35
+ // .querySelector('lightning-calendar')
36
+ // .shadowRoot.querySelector('lightning-button-icon')
37
+ // .click();
38
+ // });
39
+ // });
40
+
41
+ // benchmark('select today', () => {
42
+ // run(() => {
43
+ // element.shadowRoot
44
+ // .querySelector('lightning-calendar')
45
+ // .shadowRoot.querySelector('button[name=today]')
46
+ // .click();
47
+ // });
48
+ // });
49
+
50
+ benchmark('remove', () => {
51
+ run(() => {
52
+ document.body.removeChild(element);
53
+ });
54
+ });
55
+ });
@@ -17,6 +17,7 @@
17
17
  name={name}
18
18
  value={displayValue}
19
19
  placeholder={placeholder}
20
+ aria-invalid={computedAriaInvalid}
20
21
  aria-label={ariaLabel}
21
22
  required={required}
22
23
  readonly={readOnly}
@@ -29,6 +29,7 @@ import {
29
29
  synchronizeAttrs,
30
30
  getRealDOMId,
31
31
  isIE11,
32
+ computeAriaInvalid,
32
33
  } from 'lightning/utilsPrivate';
33
34
  import {
34
35
  generateUniqueId,
@@ -55,6 +56,7 @@ const ARIA_CONTROLS = 'aria-controls';
55
56
  const ARIA_LABEL = 'aria-label';
56
57
  const ARIA_LABELLEDBY = 'aria-labelledby';
57
58
  const ARIA_DESCRIBEDBY = 'aria-describedby';
59
+ const ARIA_INVALID = 'aria-invalid';
58
60
  const DATE_STYLE = {
59
61
  SHORT: 'short',
60
62
  MEDIUM: 'medium',
@@ -228,6 +230,7 @@ export default class LightningDatePicker extends LightningElement {
228
230
  [ARIA_DESCRIBEDBY]: this.computedAriaDescribedby,
229
231
  [ARIA_CONTROLS]: this.ariaControlsId,
230
232
  [ARIA_LABEL]: this._ariaLabel,
233
+ [ARIA_INVALID]: this.computedAriaInvalid,
231
234
  });
232
235
 
233
236
  // Set aria-describedby on the calendar button that opens the calendar dialog
@@ -744,4 +747,11 @@ export default class LightningDatePicker extends LightningElement {
744
747
  this.ariaLabelledByElement.length
745
748
  );
746
749
  }
750
+
751
+ get computedAriaInvalid() {
752
+ const isAriaInvalid =
753
+ this.template.host.getAttribute('data-aria-invalid') ||
754
+ this._errorMessage;
755
+ return computeAriaInvalid(isAriaInvalid, this.value);
756
+ }
747
757
  }
@@ -11,6 +11,7 @@
11
11
  <div class="slds-form-element__group">
12
12
  <div class="slds-form-element__row">
13
13
  <lightning-datepicker
14
+ data-aria-invalid={computedDateAriaInvalid}
14
15
  class="slds-form-element"
15
16
  autocomplete={autocomplete}
16
17
  min={dateMin}
@@ -29,6 +30,7 @@
29
30
  </lightning-datepicker>
30
31
 
31
32
  <lightning-timepicker
33
+ data-aria-invalid={computedTimeAriaInvalid}
32
34
  class="slds-form-element"
33
35
  autocomplete={autocomplete}
34
36
  label={i18n.time}
@@ -9,6 +9,7 @@ import {
9
9
  normalizeAriaAttribute,
10
10
  synchronizeAttrs,
11
11
  getRealDOMId,
12
+ computeAriaInvalid,
12
13
  } from 'lightning/utilsPrivate';
13
14
  import {
14
15
  getCurrentTime,
@@ -579,4 +580,11 @@ export default class LightningDateTimePicker extends LightningElement {
579
580
  ? isoString.split(TIME_SEPARATOR)
580
581
  : null;
581
582
  }
583
+
584
+ get computedDateAriaInvalid() {
585
+ return computeAriaInvalid(this._customErrorMessage, this._dateValue);
586
+ }
587
+ get computedTimeAriaInvalid() {
588
+ return computeAriaInvalid(this._customErrorMessage, this._timeValue);
589
+ }
582
590
  }
@@ -498,7 +498,8 @@ export default class LightningDualListbox extends LightningElement {
498
498
 
499
499
  return {
500
500
  ...option,
501
- tabIndex: option.value === focusableValue ? '0' : '-1',
501
+ tabIndex:
502
+ !this.disabled && option.value === focusableValue ? '0' : '-1',
502
503
  selected: isSelected ? 'true' : 'false',
503
504
  classList,
504
505
  };
@@ -6,6 +6,9 @@ examples:
6
6
  - name: latitude
7
7
  label: Formatted Address with Latitude/Longitude
8
8
  description: Displays an address that includes latitude and longitude.
9
+ - name: customLocale
10
+ label: Formatted Address with Custom Locale
11
+ description: Displays an address in the format of a specific locale.
9
12
  ---
10
13
 
11
14
  A `lightning-formatted-address` component displays addresses in a format and field order
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <h1 class="slds-text-heading_small">Address in Spanish format</h1>
3
+
4
+ <lightning-formatted-address
5
+ street="Avenida Concha Espina, Nº 1"
6
+ city="Madrid"
7
+ postal-code="28036"
8
+ country="España"
9
+ locale="es-ES"
10
+ ></lightning-formatted-address>
11
+
12
+ <h1 class="slds-text-heading_small">Address in Japanese format</h1>
13
+
14
+ <lightning-formatted-address
15
+ street="下連雀1丁目1−83"
16
+ city="三鷹市"
17
+ country="日本"
18
+ province="東京都"
19
+ postal-code="181–0013"
20
+ locale="ja-JP"
21
+ ></lightning-formatted-address>
22
+ </template>
@@ -0,0 +1,3 @@
1
+ import { LightningElement } from 'lwc';
2
+
3
+ export default class LightningExampleFormattedAddressCustomLocale extends LightningElement {}
@@ -25,6 +25,12 @@ export default class LightningFormattedAddress extends LightningElement {
25
25
 
26
26
  @track href;
27
27
 
28
+ /**
29
+ * The locale of the address. The default value is 'en-US'.
30
+ * @type {string}
31
+ */
32
+ @api locale = locale;
33
+
28
34
  /**
29
35
  * The street detail for the address.
30
36
  * @type {string}
@@ -188,7 +194,7 @@ export default class LightningFormattedAddress extends LightningElement {
188
194
  }
189
195
 
190
196
  get address() {
191
- const [langCode, countryCode] = locale.split('-');
197
+ const [langCode, countryCode] = this.locale.split('-');
192
198
  return (
193
199
  addressFormat.formatAddressAllFields(langCode, countryCode, {
194
200
  address: this.street,
@@ -57,7 +57,8 @@
57
57
  onendreached={handleEndReached}
58
58
  ondropdownopen={handleDropdownOpen}
59
59
  ondropdownopenrequest={handleDropdownOpenRequest}
60
- onselect={handleSelect}>
60
+ onselect={handleSelect}
61
+ disable-default-highlight={disableDefaultHighlight}>
61
62
  </lightning-base-combobox>
62
63
  </div>
63
64
  <template if:true={_hasPills}>