lightning-base-components 1.19.2-alpha → 1.19.4-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 +2066 -1632
- package/package.json +5 -1
- package/scopedImports/@salesforce-label-LightningProgressIndicator.stageNotStarted.js +1 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.html +1 -1
- package/src/lightning/ariaObserver/__docs__/ariaObserver.md +12 -4
- package/src/lightning/ariaObserver/__examples__/connectChild/connectChild.js +3 -1
- package/src/lightning/baseCombobox/baseCombobox.html +1 -0
- package/src/lightning/buttonMenu/buttonMenu.js +16 -1
- package/src/lightning/colorPickerPanel/colorPickerPanel.html +1 -1
- package/src/lightning/confirm/__examples__disabled/basic/basic.html +1 -1
- package/src/lightning/datatable/datatable.js +19 -0
- package/src/lightning/datatable/state.js +1 -0
- package/src/lightning/datatable/templates/div/div.html +4 -2
- package/src/lightning/datatable/templates/table/table.html +4 -2
- package/src/lightning/fileDownload/resourceResolver.js +4 -3
- package/src/lightning/input/input.js +43 -29
- package/src/lightning/inputUtils/inputUtils.js +0 -12
- package/src/lightning/modal/__docs__/modal.md +2 -2
- package/src/lightning/modal/__examples__disabled/all/all.html +2 -2
- package/src/lightning/modal/__examples__disabled/allform/allform.html +1 -1
- package/src/lightning/modal/__examples__disabled/allformfull/allformfull.html +1 -1
- package/src/lightning/modal/__examples__disabled/basic/basic.html +2 -2
- package/src/lightning/modal/__examples__disabled/footless/footless.html +2 -2
- package/src/lightning/modal/__examples__disabled/headless/headless.html +2 -2
- package/src/lightning/modal/__modalUtils__/modalContainerTestConstants.js +15 -2
- package/src/lightning/modal/__modalUtils__/modalContainerTestMethods.js +6 -6
- package/src/lightning/modalBase/modalBase.js +3 -3
- package/src/lightning/numberUtils/numberUtils.js +269 -5
- package/src/lightning/primitiveCustomCell/primitiveCustomCell.js +5 -5
- package/src/lightning/primitiveHeaderFactory/nonsortableHeader.html +3 -3
- package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +39 -0
- package/src/lightning/primitiveHeaderFactory/sortableHeader.html +2 -2
- package/src/lightning/primitiveInputFile/primitiveInputFile.html +1 -0
- package/src/lightning/primitiveInputFile/primitiveInputFile.js +4 -0
- package/src/lightning/primitiveInputSimple/primitiveInputSimple.js +33 -12
- package/src/lightning/progressStep/progressStep.js +13 -2
- package/src/lightning/prompt/__examples__disabled/basic/basic.html +1 -1
- package/src/lightning/resizeObserver/resizeObserver.js +10 -15
- package/src/lightning/slider/slider.js +2 -2
- package/src/lightning/tabBar/tabBar.js +3 -1
- package/src/lightning/timepicker/timepicker.html +3 -3
- package/src/lightning/tooltipLibrary/tooltipLibrary.js +3 -1
- package/src/lightning/utils/queryFocusable.js +33 -15
- package/src/lightning/utilsPrivate/videoUtils.js +35 -0
- package/src/lightning/inputUtils/number.js +0 -267
|
@@ -1,29 +1,47 @@
|
|
|
1
|
+
// Matches lower cased tag names of standard inputable elements as well as
|
|
2
|
+
// custom elements whose tag names contain inputable names.
|
|
1
3
|
const inputableNode = /input|select|textarea|button|object/;
|
|
2
4
|
|
|
3
5
|
function visible(element) {
|
|
6
|
+
// Check computed style visibility first because it doesn't cause a layout
|
|
7
|
+
// reflow/recalculation.
|
|
8
|
+
if (window.getComputedStyle(element).visibility === 'hidden') {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
// Perform the performance heavier `getBoundingClientRect()` last because
|
|
12
|
+
// it causes a page layout reflow/recalculation.
|
|
4
13
|
const { width, height } = element.getBoundingClientRect();
|
|
5
|
-
|
|
6
|
-
return (
|
|
7
|
-
noZeroSize && window.getComputedStyle(element).visibility !== 'hidden'
|
|
8
|
-
);
|
|
14
|
+
return width > 0 || height > 0;
|
|
9
15
|
}
|
|
10
16
|
|
|
11
17
|
function focusable(element) {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
(
|
|
15
|
-
(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
const tagName = element.tagName.toLowerCase();
|
|
19
|
+
if (
|
|
20
|
+
(tagName === 'a' && element.href) ||
|
|
21
|
+
(!element.disabled && inputableNode.test(tagName))
|
|
22
|
+
) {
|
|
23
|
+
return visible(element);
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
function tabbable(element) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
// Perform the "isDataActionable" first as `focusable()` is potentially
|
|
30
|
+
// performance heavy.
|
|
31
|
+
return (
|
|
32
|
+
element.dataset.navigation === 'enable' ||
|
|
33
|
+
(element.tabIndex >= 0 && focusable(element))
|
|
34
|
+
);
|
|
25
35
|
}
|
|
26
36
|
|
|
27
37
|
export function queryFocusable(element) {
|
|
28
|
-
|
|
38
|
+
const childElements = element.querySelectorAll('*');
|
|
39
|
+
const focusables = [];
|
|
40
|
+
for (let i = 0, { length } = childElements; i < length; i += 1) {
|
|
41
|
+
const child = childElements[i];
|
|
42
|
+
if (tabbable(child)) {
|
|
43
|
+
focusables.push(child);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return focusables;
|
|
29
47
|
}
|
|
@@ -22,6 +22,11 @@ const ALLOWED_DOMAINS = new Set([
|
|
|
22
22
|
'appiniummastertrial.secure.force.com',
|
|
23
23
|
'embed.app.guidde.com',
|
|
24
24
|
]);
|
|
25
|
+
// In addition to:
|
|
26
|
+
// vimeo.com/showcase/*/embed
|
|
27
|
+
// *.my.site.com
|
|
28
|
+
// *.lightning.force.com
|
|
29
|
+
// *.my.salesforce-sites.com
|
|
25
30
|
|
|
26
31
|
export function hasOnlyAllowedVideoIframes(htmlString) {
|
|
27
32
|
if (htmlString && htmlString.indexOf('<iframe') > -1) {
|
|
@@ -55,5 +60,35 @@ function isUrlAllowed(url) {
|
|
|
55
60
|
return path.match(regex) !== null;
|
|
56
61
|
}
|
|
57
62
|
|
|
63
|
+
if (anchor.hostname === 'www.my.salesforce-sites.com') {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (anchor.hostname.match(/^[\w-]+\.my\.salesforce-sites\.com$/)) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
if (anchor.hostname.match(/^[\w-]+\.sandbox\.my\.salesforce-sites\.com$/)) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (anchor.hostname === 'www.lightning.force.com') {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
if (anchor.hostname.match(/^[\w-]+\.lightning\.force\.com$/)) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
if (anchor.hostname.match(/^[\w-]+\.sandbox\.lightning\.force\.com$/)) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (anchor.hostname === 'www.my.site.com') {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
if (anchor.hostname.match(/^[\w-]+\.my\.site\.com$/)) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
if (anchor.hostname.match(/^[\w-]+\.sandbox\.my\.site\.com$/)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
58
93
|
return ALLOWED_DOMAINS.has(anchor.hostname);
|
|
59
94
|
}
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
import groupingSeparator from '@salesforce/i18n/number.groupingSeparator';
|
|
2
|
-
import decimalSeparator from '@salesforce/i18n/number.decimalSeparator';
|
|
3
|
-
import {
|
|
4
|
-
fromLocalizedDigits,
|
|
5
|
-
toLocalizedDigits,
|
|
6
|
-
numberFormat,
|
|
7
|
-
} from 'lightning/internationalizationLibrary';
|
|
8
|
-
import { isEmptyString } from './utils';
|
|
9
|
-
import { normalizeNumber } from 'lightning/utilsPrivate';
|
|
10
|
-
|
|
11
|
-
const VALID_NUMBER_CHARACTERS_EXPRESSION = new RegExp(
|
|
12
|
-
// eslint-disable-next-line no-useless-escape
|
|
13
|
-
'^[-+0-9kKmMbBtTeE.,\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9' +
|
|
14
|
-
'\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF' +
|
|
15
|
-
'\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF' +
|
|
16
|
-
'\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9' +
|
|
17
|
-
'\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9' +
|
|
18
|
-
'\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89' +
|
|
19
|
-
'\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49' +
|
|
20
|
-
'\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909' +
|
|
21
|
-
'\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9' +
|
|
22
|
-
']$'
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
const SHORTCUT_FACTORS = {
|
|
26
|
-
k: 3,
|
|
27
|
-
m: 6,
|
|
28
|
-
b: 9,
|
|
29
|
-
t: 12,
|
|
30
|
-
};
|
|
31
|
-
const SHORTCUTS = ['k', 'm', 'b', 't'];
|
|
32
|
-
|
|
33
|
-
const NUMBER_SYMBOLS = ['+', '-'];
|
|
34
|
-
|
|
35
|
-
export function toIsoDecimal(numberAsString) {
|
|
36
|
-
const result = transformLocalizedNumberToIsoDecimal(numberAsString);
|
|
37
|
-
if (isNaN(result)) {
|
|
38
|
-
return '';
|
|
39
|
-
}
|
|
40
|
-
return result;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function isValidNumber(numberAsString) {
|
|
44
|
-
return !isNaN(transformLocalizedNumberToIsoDecimal(numberAsString));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function fromIsoDecimal(numberAsString) {
|
|
48
|
-
return toLocalizedDigits(numberAsString.replace('.', decimalSeparator));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// TODO: Too many options, simplify
|
|
52
|
-
export function increaseNumberByStep({
|
|
53
|
-
value,
|
|
54
|
-
increment,
|
|
55
|
-
step,
|
|
56
|
-
fractionDigits,
|
|
57
|
-
}) {
|
|
58
|
-
const startingValue = value === '' || value == null ? '0' : value;
|
|
59
|
-
|
|
60
|
-
const stepAsFloat = parseFloat(step);
|
|
61
|
-
|
|
62
|
-
let result;
|
|
63
|
-
if (isNaN(stepAsFloat)) {
|
|
64
|
-
result = parseFloat(startingValue) + increment;
|
|
65
|
-
} else {
|
|
66
|
-
// ideally we'd round the value to the closest correct step, so that if say the step is '2', and the
|
|
67
|
-
// current value is '1' it would increment to '2' instead of '3', since the former would be the valid
|
|
68
|
-
// number given the step constraint, however this would significantly complicate the code, keeping
|
|
69
|
-
// it simple for now.
|
|
70
|
-
const increaseBy = increment * stepAsFloat;
|
|
71
|
-
result = parseFloat(startingValue) + increaseBy;
|
|
72
|
-
}
|
|
73
|
-
return result.toFixed(fractionDigits);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function calculateFractionDigitsFromStep(step) {
|
|
77
|
-
let calculatedFractionDigits;
|
|
78
|
-
|
|
79
|
-
if (step) {
|
|
80
|
-
const stepAsString = String(step).toLowerCase();
|
|
81
|
-
if (stepAsString !== 'any') {
|
|
82
|
-
// lowering the case because we're checking for exponent format as well
|
|
83
|
-
let fractionDigits = 0;
|
|
84
|
-
if (
|
|
85
|
-
stepAsString.indexOf('.') >= 0 &&
|
|
86
|
-
stepAsString.indexOf('e') < 0
|
|
87
|
-
) {
|
|
88
|
-
const fractionalPart = stepAsString.split('.')[1];
|
|
89
|
-
// we're parsing to account for cases where the step is
|
|
90
|
-
// '1.0', or '1.000', etc.
|
|
91
|
-
if (parseInt(fractionalPart, 10) > 0) {
|
|
92
|
-
fractionDigits = fractionalPart.length;
|
|
93
|
-
}
|
|
94
|
-
} else if (stepAsString.indexOf('e-') > 0) {
|
|
95
|
-
// exponent form eg. 1.5e-5
|
|
96
|
-
const splitOnExponent = stepAsString.split('e-');
|
|
97
|
-
const fractionalPart = splitOnExponent[0].split('.')[1];
|
|
98
|
-
const exponentPart = splitOnExponent[1];
|
|
99
|
-
const fractionalPartLength = fractionalPart
|
|
100
|
-
? fractionalPart.length
|
|
101
|
-
: 0;
|
|
102
|
-
fractionDigits =
|
|
103
|
-
parseInt(exponentPart, 10) + fractionalPartLength;
|
|
104
|
-
}
|
|
105
|
-
calculatedFractionDigits = fractionDigits;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return calculatedFractionDigits;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function formatNumber(numberAsString, options) {
|
|
112
|
-
if (isEmptyString(numberAsString)) {
|
|
113
|
-
return '';
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
let formattedValue = numberAsString;
|
|
117
|
-
let inputValue = numberAsString;
|
|
118
|
-
|
|
119
|
-
// set formatter style & default options
|
|
120
|
-
const formatStyle = options.style;
|
|
121
|
-
const formatOptions = { style: formatStyle };
|
|
122
|
-
|
|
123
|
-
formatOptions.minimumFractionDigits = options.minimumFractionDigits;
|
|
124
|
-
formatOptions.maximumFractionDigits = options.maximumFractionDigits;
|
|
125
|
-
|
|
126
|
-
if (formatStyle === 'percent-fixed') {
|
|
127
|
-
// percent-fixed just uses percent format and divides the value by 100
|
|
128
|
-
// before passing to the library, this is to deal with the
|
|
129
|
-
// fact that percentages in salesforce are 0-100, not 0-1
|
|
130
|
-
formatOptions.style = 'percent';
|
|
131
|
-
const inputValueAsString = inputValue.toString();
|
|
132
|
-
const normalisedNumberInPercent = parseFloat(inputValue) / 100;
|
|
133
|
-
|
|
134
|
-
// If the number contains fraction digits and is not in an exponent format
|
|
135
|
-
if (
|
|
136
|
-
inputValueAsString.indexOf('.') > 0 &&
|
|
137
|
-
inputValueAsString.indexOf('e') < 0
|
|
138
|
-
) {
|
|
139
|
-
// Depending on the input number, division by 100 may lead to rounding errors
|
|
140
|
-
// (e.g 0.785 / 100 is 0.007850000000000001), so we need to round back
|
|
141
|
-
// to the correct precision, that is - existing number of fractional digits
|
|
142
|
-
// plus extra 2 for division by 100.
|
|
143
|
-
inputValue = normalisedNumberInPercent.toFixed(
|
|
144
|
-
inputValueAsString.split('.')[1].length + 2
|
|
145
|
-
);
|
|
146
|
-
} else {
|
|
147
|
-
inputValue = normalisedNumberInPercent;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
formattedValue = numberFormat(formatOptions).format(inputValue) || '';
|
|
153
|
-
} catch (ignore) {
|
|
154
|
-
// ignore any errors
|
|
155
|
-
}
|
|
156
|
-
return formattedValue;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Exporting only to test, separators are only overridden in the tests
|
|
160
|
-
export function transformLocalizedNumberToIsoDecimal(
|
|
161
|
-
numberAsString,
|
|
162
|
-
separators
|
|
163
|
-
) {
|
|
164
|
-
if (numberAsString == null || numberAsString.length === 0) {
|
|
165
|
-
return '';
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const decimalSymbol = separators
|
|
169
|
-
? separators.decimalSeparator
|
|
170
|
-
: decimalSeparator;
|
|
171
|
-
const groupingSymbol = separators
|
|
172
|
-
? separators.groupSeparator
|
|
173
|
-
: groupingSeparator;
|
|
174
|
-
|
|
175
|
-
// remove the grouping separator
|
|
176
|
-
let result = numberAsString.split(groupingSymbol).join('');
|
|
177
|
-
if (decimalSymbol !== '.') {
|
|
178
|
-
// replace the local decimal separator with a
|
|
179
|
-
result = result.replace(decimalSymbol, '.');
|
|
180
|
-
}
|
|
181
|
-
return expandShortcuts(addLeadingZeroIfNeeded(fromLocalizedDigits(result)));
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export function isValidNumberCharacter(character) {
|
|
185
|
-
return VALID_NUMBER_CHARACTERS_EXPRESSION.test(character);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* validate the string-typed number and return the number string
|
|
190
|
-
* @param {String} value, number string to be validated
|
|
191
|
-
* @returns a valid number in string-typed, otherwise, empty string
|
|
192
|
-
*/
|
|
193
|
-
export function stringifyNumber(value) {
|
|
194
|
-
const numericValue = typeof value === 'string' ? Number(value) : value;
|
|
195
|
-
const normalizedNumber = normalizeNumber(numericValue);
|
|
196
|
-
return normalizedNumber === undefined ? '' : String(value);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
export function hasValidNumberSymbol(value) {
|
|
200
|
-
const validSymbols = NUMBER_SYMBOLS.join('');
|
|
201
|
-
const matchSymbols = new RegExp(`[${validSymbols}]`);
|
|
202
|
-
return value.match(matchSymbols) ? true : false;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export function hasValidNumberShortcut(value) {
|
|
206
|
-
const result = value.toLowerCase().trim();
|
|
207
|
-
const kmb = SHORTCUTS.join('');
|
|
208
|
-
// Cannot have two shortcuts /([kmb])/g
|
|
209
|
-
const matchShortcuts = new RegExp(`([${kmb}])`, 'g');
|
|
210
|
-
const shortcutMatch = result.match(matchShortcuts);
|
|
211
|
-
if (shortcutMatch && shortcutMatch.length > 1) {
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
// Must end with 'm', 'k', 'b' and more than just a single letter
|
|
215
|
-
const matchEndsWith = new RegExp(`[${kmb}]$`);
|
|
216
|
-
const endsWithShortcut = result.match(matchEndsWith) !== null;
|
|
217
|
-
// has 'm' / 'k' / 'b' and more than just them (ie. result of 'm' / 'k' / 'b' are not valid.
|
|
218
|
-
return endsWithShortcut && result.length > 1;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Exported for testing only
|
|
222
|
-
export function expandShortcuts(isoValue) {
|
|
223
|
-
if (!hasValidNumberShortcut(isoValue)) {
|
|
224
|
-
return isoValue;
|
|
225
|
-
}
|
|
226
|
-
let result = isoValue.toLowerCase().trim();
|
|
227
|
-
const shortcut = result.charAt(result.length - 1);
|
|
228
|
-
// remove the suffix
|
|
229
|
-
result = result.substring(0, result.length - 1);
|
|
230
|
-
if (isNaN(result)) {
|
|
231
|
-
return isoValue;
|
|
232
|
-
}
|
|
233
|
-
const parts = result.split('.');
|
|
234
|
-
let fractionDigits = 0;
|
|
235
|
-
const hasDecimalPart = parts.length > 1;
|
|
236
|
-
if (hasDecimalPart) {
|
|
237
|
-
fractionDigits = parts[1].length;
|
|
238
|
-
}
|
|
239
|
-
const exponent = SHORTCUT_FACTORS[shortcut];
|
|
240
|
-
// since multiplication may result in loss of precision on javascript's part,
|
|
241
|
-
// we're calculating here the number of fraction digits needed and formatting
|
|
242
|
-
// the number at that
|
|
243
|
-
const newFractionDigits = Math.max(0, fractionDigits - exponent);
|
|
244
|
-
return parseFloat(result * Math.pow(10, exponent)).toFixed(
|
|
245
|
-
newFractionDigits
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function addLeadingZeroIfNeeded(result) {
|
|
250
|
-
// If the number starts with +. OR -. OR . ; insert a 0 before the decimal separator.
|
|
251
|
-
// eg. -.2 -> -0.2
|
|
252
|
-
const decimalSeparatorLocation = result.indexOf('.');
|
|
253
|
-
if (decimalSeparatorLocation === 0 || decimalSeparatorLocation === 1) {
|
|
254
|
-
const firstCharacter = result.charAt(0);
|
|
255
|
-
if (
|
|
256
|
-
firstCharacter === '+' ||
|
|
257
|
-
firstCharacter === '-' ||
|
|
258
|
-
firstCharacter === '.'
|
|
259
|
-
) {
|
|
260
|
-
result =
|
|
261
|
-
result.substring(0, decimalSeparatorLocation) +
|
|
262
|
-
'0' +
|
|
263
|
-
result.substring(decimalSeparatorLocation);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
return result;
|
|
267
|
-
}
|