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.
- package/metadata/raptor.json +31 -4
- package/package.json +13 -2
- package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
- package/scopedImports/@salesforce-label-LightningMap.defaultTitle.js +1 -0
- package/scopedImports/@salesforce-label-LightningProgressBar.progressBar.js +1 -0
- package/src/lightning/alert/__docs__/alert.md +99 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.html +8 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.js +14 -0
- package/src/lightning/alert/alert.html +3 -0
- package/src/lightning/alert/alert.js +78 -0
- package/src/lightning/alert/alert.js-meta.xml +6 -0
- package/src/lightning/baseCombobox/baseCombobox.html +2 -1
- package/src/lightning/baseCombobox/baseCombobox.js +41 -6
- package/src/lightning/button/__wdio__/utam/utam.html +3 -0
- package/src/lightning/button/__wdio__/utam/utam.js +3 -0
- package/src/lightning/button/__wdio__/utam/utam.spec.js +20 -0
- package/src/lightning/button/button.js +22 -1
- package/src/lightning/buttonMenu/buttonMenu.js +12 -0
- package/src/lightning/checkboxGroup/checkboxGroup.html +2 -2
- package/src/lightning/checkboxGroup/checkboxGroup.js +9 -5
- package/src/lightning/combobox/__docs__/combobox.md +3 -1
- package/src/lightning/combobox/combobox.js +0 -1
- package/src/lightning/confirm/__docs__/confirm.md +98 -0
- package/src/lightning/confirm/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/confirm/__examples__disabled/basic/basic.html +8 -0
- package/src/lightning/confirm/__examples__disabled/basic/basic.js +14 -0
- package/src/lightning/confirm/confirm.html +3 -0
- package/src/lightning/confirm/confirm.js +80 -0
- package/src/lightning/confirm/confirm.js-meta.xml +6 -0
- package/src/lightning/datatable/__docs__/datatable.md +45 -0
- package/src/lightning/datatable/__wdio__/utam/utam.html +32 -0
- package/src/lightning/datatable/__wdio__/utam/utam.js +91 -0
- package/src/lightning/datatable/__wdio__/utam/utam.spec.js +214 -0
- package/src/lightning/datatable/columns.js +166 -71
- package/src/lightning/datatable/datatable.js +103 -20
- package/src/lightning/datatable/headerActions.js +2 -2
- package/src/lightning/datatable/inlineEdit.js +0 -5
- package/src/lightning/datatable/inlineEditShared.js +4 -2
- package/src/lightning/datatable/keyboard.js +17 -13
- package/src/lightning/datatable/renderManager.js +45 -13
- package/src/lightning/datatable/resizeSensor.js +11 -3
- package/src/lightning/datatable/rowSelection.js +9 -3
- package/src/lightning/datatable/rowSelectionShared.js +33 -20
- package/src/lightning/datatable/rows.js +3 -2
- package/src/lightning/datatable/sort.js +8 -8
- package/src/lightning/datatable/state.js +9 -1
- package/src/lightning/datatable/templates/div/div.html +6 -2
- package/src/lightning/datatable/templates/table/table.html +7 -4
- package/src/lightning/datatable/tree.js +25 -0
- package/src/lightning/datatable/types.js +77 -9
- package/src/lightning/datatable/utils.js +51 -24
- package/src/lightning/datatable/virtualization.js +319 -0
- package/src/lightning/datatable/wrapText.js +54 -16
- package/src/lightning/datepicker/__perf__DISABLED/datepickerWithCalendarOpen.perf.js +55 -0
- package/src/lightning/datepicker/datepicker.html +1 -0
- package/src/lightning/datepicker/datepicker.js +10 -0
- package/src/lightning/datetimepicker/datetimepicker.html +2 -0
- package/src/lightning/datetimepicker/datetimepicker.js +8 -0
- package/src/lightning/dualListbox/dualListbox.js +2 -1
- package/src/lightning/formattedAddress/__docs__/formattedAddress.md +3 -0
- package/src/lightning/formattedAddress/__examples__/customLocale/customLocale.html +22 -0
- package/src/lightning/formattedAddress/__examples__/customLocale/customLocale.js +3 -0
- package/src/lightning/formattedAddress/formattedAddress.js +7 -1
- package/src/lightning/groupedCombobox/groupedCombobox.html +2 -1
- package/src/lightning/groupedCombobox/groupedCombobox.js +16 -2
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +8 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +8 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/templates.js +4 -1
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/templates.js +4 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +5 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +5 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/input/__docs__/input.md +2 -0
- package/src/lightning/input/input.html +6 -0
- package/src/lightning/input/input.js +2 -1
- package/src/lightning/inputAddress/__docs__/inputAddress.md +5 -0
- package/src/lightning/inputAddress/__examples__/customLocale/customLocale.html +12 -0
- package/src/lightning/inputAddress/__examples__/customLocale/customLocale.js +3 -0
- package/src/lightning/inputAddress/inputAddress.html +2 -0
- package/src/lightning/inputAddress/inputAddress.js +26 -3
- package/src/lightning/inputName/__docs__/inputName.md +2 -0
- package/src/lightning/inputName/inputName.html +4 -1
- package/src/lightning/inputUtils/inputUtils.js +11 -0
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.css +494 -0
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.html +63 -0
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.js +200 -0
- package/src/lightning/menuItem/menuItem.js +4 -1
- package/src/lightning/modalBase/modalBase.css +20 -0
- package/src/lightning/modalBase/modalBase.html +54 -0
- package/src/lightning/modalBase/modalBase.js +1039 -0
- package/src/lightning/overlay/__docs__/overlay.md +90 -0
- package/src/lightning/overlay/__examples__/alert/alert.html +27 -0
- package/src/lightning/overlay/__examples__/alert/alert.js +33 -0
- package/src/lightning/overlay/__examples__/basic/basic.css +7 -0
- package/src/lightning/overlay/__examples__/basic/basic.html +18 -0
- package/src/lightning/overlay/__examples__/basic/basic.js +61 -0
- package/src/lightning/overlay/__examples__/demo/demo.html +29 -0
- package/src/lightning/overlay/__examples__/demo/demo.js +40 -0
- package/src/lightning/overlay/__examples__/panel/panel.html +17 -0
- package/src/lightning/overlay/__examples__/panel/panel.js +21 -0
- package/src/lightning/overlay/overlay.html +3 -0
- package/src/lightning/overlay/overlay.js +45 -0
- package/src/lightning/overlayContainer/__docs__/overlayContainer.md +0 -0
- package/src/lightning/overlayContainer/overlayContainer.html +3 -0
- package/src/lightning/overlayContainer/overlayContainer.js +138 -0
- package/src/lightning/overlayManager/overlayManager.js +54 -0
- package/src/lightning/overlayUtils/overlayUtils.js +17 -0
- package/src/lightning/picklist/picklist.js +6 -1
- package/src/lightning/progressBar/progressBar.html +2 -1
- package/src/lightning/progressBar/progressBar.js +18 -1
- package/src/lightning/prompt/__docs__/prompt.md +100 -0
- package/src/lightning/prompt/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/prompt/__examples__disabled/basic/basic.html +8 -0
- package/src/lightning/prompt/__examples__disabled/basic/basic.js +15 -0
- package/src/lightning/prompt/prompt.css +81 -0
- package/src/lightning/prompt/prompt.html +8 -0
- package/src/lightning/prompt/prompt.js +92 -0
- package/src/lightning/prompt/prompt.js-meta.xml +6 -0
- package/src/lightning/radioGroup/radioGroup.js +9 -0
- package/src/lightning/select/select.html +3 -1
- package/src/lightning/select/select.js +5 -1
- package/src/lightning/textarea/textarea.html +1 -0
- package/src/lightning/textarea/textarea.js +5 -0
- package/src/lightning/timepicker/timepicker.html +3 -1
- package/src/lightning/timepicker/timepicker.js +8 -0
- package/src/lightning/utilsPrivate/aria.js +26 -0
- package/src/lightning/utilsPrivate/linkify.js +1 -1
- package/src/lightning/utilsPrivate/utilsPrivate.js +7 -1
- 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
|
-
|
|
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
|
-
|
|
31
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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
|
-
|
|
55
|
-
|
|
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
|
|
74
|
-
* @param {Object} columnDefinition
|
|
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
|
|
112
|
-
* @param {String} action
|
|
113
|
-
* @param {String} colKeyValue
|
|
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
|
-
|
|
128
|
-
|
|
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
|
+
});
|
|
@@ -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:
|
|
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>
|
|
@@ -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}>
|