@internationalized/number 3.3.1-nightly.4202 → 3.3.1-nightly.4205
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/dist/import.mjs +52 -17
- package/dist/main.js +52 -17
- package/dist/main.js.map +1 -1
- package/dist/module.js +52 -17
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/NumberParser.ts +60 -15
package/dist/import.mjs
CHANGED
|
@@ -171,7 +171,8 @@ function $488c6ddbf4ef74c2$export$711b50b3c525e0f2(numberFormat, signDisplay, nu
|
|
|
171
171
|
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
172
172
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
173
173
|
* governing permissions and limitations under the License.
|
|
174
|
-
*/
|
|
174
|
+
*/
|
|
175
|
+
const $6c7bd7858deea686$var$CURRENCY_SIGN_REGEX = new RegExp("^.*\\(.*\\).*$");
|
|
175
176
|
const $6c7bd7858deea686$var$NUMBERING_SYSTEMS = [
|
|
176
177
|
"latn",
|
|
177
178
|
"arab",
|
|
@@ -233,17 +234,33 @@ class $6c7bd7858deea686$var$NumberParserImpl {
|
|
|
233
234
|
let fullySanitizedValue = this.sanitize(value);
|
|
234
235
|
// Remove group characters, and replace decimal points and numerals with ASCII values.
|
|
235
236
|
fullySanitizedValue = $6c7bd7858deea686$var$replaceAll(fullySanitizedValue, this.symbols.group, "").replace(this.symbols.decimal, ".").replace(this.symbols.minusSign, "-").replace(this.symbols.numeral, this.symbols.index);
|
|
237
|
+
if (this.options.style === "percent") {
|
|
238
|
+
// javascript is bad at dividing by 100 and maintaining the same significant figures, so perform it on the string before parsing
|
|
239
|
+
let isNegative = fullySanitizedValue.indexOf("-");
|
|
240
|
+
fullySanitizedValue = fullySanitizedValue.replace("-", "");
|
|
241
|
+
let index = fullySanitizedValue.indexOf(".");
|
|
242
|
+
if (index === -1) index = fullySanitizedValue.length;
|
|
243
|
+
fullySanitizedValue = fullySanitizedValue.replace(".", "");
|
|
244
|
+
if (index - 2 === 0) fullySanitizedValue = `0.${fullySanitizedValue}`;
|
|
245
|
+
else if (index - 2 === -1) fullySanitizedValue = `0.0${fullySanitizedValue}`;
|
|
246
|
+
else if (index - 2 === -2) fullySanitizedValue = "0.00";
|
|
247
|
+
else fullySanitizedValue = `${fullySanitizedValue.slice(0, index - 2)}.${fullySanitizedValue.slice(index - 2)}`;
|
|
248
|
+
if (isNegative > -1) fullySanitizedValue = `-${fullySanitizedValue}`;
|
|
249
|
+
}
|
|
236
250
|
let newValue = fullySanitizedValue ? +fullySanitizedValue : NaN;
|
|
237
251
|
if (isNaN(newValue)) return NaN;
|
|
238
|
-
// accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again
|
|
239
|
-
if (this.options.currencySign === "accounting" && $6c7bd7858deea686$var$CURRENCY_SIGN_REGEX.test(value)) newValue = -1 * newValue;
|
|
240
|
-
// when reading the number, if it's a percent, then it should be interpreted as being divided by 100
|
|
241
252
|
if (this.options.style === "percent") {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
253
|
+
// extra step for rounding percents to what our formatter would output
|
|
254
|
+
let options = {
|
|
255
|
+
...this.options,
|
|
256
|
+
style: "decimal",
|
|
257
|
+
minimumFractionDigits: Math.min(this.options.minimumFractionDigits + 2, 20),
|
|
258
|
+
maximumFractionDigits: Math.min(this.options.maximumFractionDigits + 2, 20)
|
|
259
|
+
};
|
|
260
|
+
return new $6c7bd7858deea686$export$cd11ab140839f11d(this.locale, options).parse(new (0, $488c6ddbf4ef74c2$export$cc77c4ff7e8673c5)(this.locale, options).format(newValue));
|
|
246
261
|
}
|
|
262
|
+
// accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again
|
|
263
|
+
if (this.options.currencySign === "accounting" && $6c7bd7858deea686$var$CURRENCY_SIGN_REGEX.test(value)) newValue = -1 * newValue;
|
|
247
264
|
return newValue;
|
|
248
265
|
}
|
|
249
266
|
sanitize(value) {
|
|
@@ -271,15 +288,20 @@ class $6c7bd7858deea686$var$NumberParserImpl {
|
|
|
271
288
|
else if (this.symbols.plusSign && value.startsWith(this.symbols.plusSign) && maxValue > 0) value = value.slice(this.symbols.plusSign.length);
|
|
272
289
|
// Numbers cannot start with a group separator
|
|
273
290
|
if (value.startsWith(this.symbols.group)) return false;
|
|
291
|
+
// Numbers that can't have any decimal values fail if a decimal character is typed
|
|
292
|
+
if (value.indexOf(this.symbols.decimal) > -1 && this.options.maximumFractionDigits === 0) return false;
|
|
274
293
|
// Remove numerals, groups, and decimals
|
|
275
294
|
value = $6c7bd7858deea686$var$replaceAll(value, this.symbols.group, "").replace(this.symbols.numeral, "").replace(this.symbols.decimal, "");
|
|
276
295
|
// The number is valid if there are no remaining characters
|
|
277
296
|
return value.length === 0;
|
|
278
297
|
}
|
|
279
298
|
constructor(locale, options = {}){
|
|
299
|
+
this.locale = locale;
|
|
280
300
|
this.formatter = new Intl.NumberFormat(locale, options);
|
|
281
301
|
this.options = this.formatter.resolvedOptions();
|
|
282
|
-
this.symbols = $6c7bd7858deea686$var$getSymbols(this.formatter, this.options, options);
|
|
302
|
+
this.symbols = $6c7bd7858deea686$var$getSymbols(locale, this.formatter, this.options, options);
|
|
303
|
+
var _this_options_minimumFractionDigits, _this_options_maximumFractionDigits;
|
|
304
|
+
if (this.options.style === "percent" && (((_this_options_minimumFractionDigits = this.options.minimumFractionDigits) !== null && _this_options_minimumFractionDigits !== void 0 ? _this_options_minimumFractionDigits : 0) > 18 || ((_this_options_maximumFractionDigits = this.options.maximumFractionDigits) !== null && _this_options_maximumFractionDigits !== void 0 ? _this_options_maximumFractionDigits : 0) > 18)) console.warn("NumberParser cannot handle percentages with greater than 18 decimal places, please reduce the number in your options.");
|
|
283
305
|
}
|
|
284
306
|
}
|
|
285
307
|
const $6c7bd7858deea686$var$nonLiteralParts = new Set([
|
|
@@ -307,12 +329,18 @@ const $6c7bd7858deea686$var$pluralNumbers = [
|
|
|
307
329
|
0.1,
|
|
308
330
|
1.1
|
|
309
331
|
];
|
|
310
|
-
function $6c7bd7858deea686$var$getSymbols(formatter, intlOptions, originalOptions) {
|
|
311
|
-
var _allParts_find, _posAllParts_find,
|
|
332
|
+
function $6c7bd7858deea686$var$getSymbols(locale, formatter, intlOptions, originalOptions) {
|
|
333
|
+
var _allParts_find, _posAllParts_find, _decimalParts_find, _allParts_find1;
|
|
334
|
+
// formatter needs access to all decimal places in order to generate the correct literal strings for the plural set
|
|
335
|
+
let symbolFormatter = new Intl.NumberFormat(locale, {
|
|
336
|
+
...intlOptions,
|
|
337
|
+
minimumSignificantDigits: 1,
|
|
338
|
+
maximumSignificantDigits: 21
|
|
339
|
+
});
|
|
312
340
|
// Note: some locale's don't add a group symbol until there is a ten thousands place
|
|
313
|
-
let allParts =
|
|
314
|
-
let posAllParts =
|
|
315
|
-
let pluralParts = $6c7bd7858deea686$var$pluralNumbers.map((n)=>
|
|
341
|
+
let allParts = symbolFormatter.formatToParts(-10000.111);
|
|
342
|
+
let posAllParts = symbolFormatter.formatToParts(10000.111);
|
|
343
|
+
let pluralParts = $6c7bd7858deea686$var$pluralNumbers.map((n)=>symbolFormatter.formatToParts(n));
|
|
316
344
|
var _allParts_find_value;
|
|
317
345
|
let minusSign = (_allParts_find_value = (_allParts_find = allParts.find((p)=>p.type === "minusSign")) === null || _allParts_find === void 0 ? void 0 : _allParts_find.value) !== null && _allParts_find_value !== void 0 ? _allParts_find_value : "-";
|
|
318
346
|
let plusSign = (_posAllParts_find = posAllParts.find((p)=>p.type === "plusSign")) === null || _posAllParts_find === void 0 ? void 0 : _posAllParts_find.value;
|
|
@@ -320,8 +348,15 @@ function $6c7bd7858deea686$var$getSymbols(formatter, intlOptions, originalOption
|
|
|
320
348
|
// If no plus sign was returned, but the original options contained signDisplay, default to the '+' character.
|
|
321
349
|
// @ts-ignore
|
|
322
350
|
if (!plusSign && ((originalOptions === null || originalOptions === void 0 ? void 0 : originalOptions.signDisplay) === "exceptZero" || (originalOptions === null || originalOptions === void 0 ? void 0 : originalOptions.signDisplay) === "always")) plusSign = "+";
|
|
323
|
-
|
|
324
|
-
|
|
351
|
+
// If maximumSignificantDigits is 1 (the minimum) then we won't get decimal characters out of the above formatters
|
|
352
|
+
// Percent also defaults to 0 fractionDigits, so we need to make a new one that isn't percent to get an accurate decimal
|
|
353
|
+
let decimalParts = new Intl.NumberFormat(locale, {
|
|
354
|
+
...intlOptions,
|
|
355
|
+
minimumFractionDigits: 2,
|
|
356
|
+
maximumFractionDigits: 2
|
|
357
|
+
}).formatToParts(0.001);
|
|
358
|
+
let decimal = (_decimalParts_find = decimalParts.find((p)=>p.type === "decimal")) === null || _decimalParts_find === void 0 ? void 0 : _decimalParts_find.value;
|
|
359
|
+
let group = (_allParts_find1 = allParts.find((p)=>p.type === "group")) === null || _allParts_find1 === void 0 ? void 0 : _allParts_find1.value;
|
|
325
360
|
// this set is also for a regex, it's all literals that might be in the string we want to eventually parse that
|
|
326
361
|
// don't contribute to the numerical value
|
|
327
362
|
let allPartsLiterals = allParts.filter((p)=>!$6c7bd7858deea686$var$nonLiteralParts.has(p.type)).map((p)=>$6c7bd7858deea686$var$escapeRegex(p.value));
|
|
@@ -362,7 +397,7 @@ function $6c7bd7858deea686$var$replaceAll(str, find, replace) {
|
|
|
362
397
|
return str.split(find).join(replace);
|
|
363
398
|
}
|
|
364
399
|
function $6c7bd7858deea686$var$escapeRegex(string) {
|
|
365
|
-
return string.replace(/[
|
|
400
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
366
401
|
}
|
|
367
402
|
|
|
368
403
|
|
package/dist/main.js
CHANGED
|
@@ -177,7 +177,8 @@ function $0c1d5654b62fc485$export$711b50b3c525e0f2(numberFormat, signDisplay, nu
|
|
|
177
177
|
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
178
178
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
179
179
|
* governing permissions and limitations under the License.
|
|
180
|
-
*/
|
|
180
|
+
*/
|
|
181
|
+
const $d68f3f4c684426c6$var$CURRENCY_SIGN_REGEX = new RegExp("^.*\\(.*\\).*$");
|
|
181
182
|
const $d68f3f4c684426c6$var$NUMBERING_SYSTEMS = [
|
|
182
183
|
"latn",
|
|
183
184
|
"arab",
|
|
@@ -239,17 +240,33 @@ class $d68f3f4c684426c6$var$NumberParserImpl {
|
|
|
239
240
|
let fullySanitizedValue = this.sanitize(value);
|
|
240
241
|
// Remove group characters, and replace decimal points and numerals with ASCII values.
|
|
241
242
|
fullySanitizedValue = $d68f3f4c684426c6$var$replaceAll(fullySanitizedValue, this.symbols.group, "").replace(this.symbols.decimal, ".").replace(this.symbols.minusSign, "-").replace(this.symbols.numeral, this.symbols.index);
|
|
243
|
+
if (this.options.style === "percent") {
|
|
244
|
+
// javascript is bad at dividing by 100 and maintaining the same significant figures, so perform it on the string before parsing
|
|
245
|
+
let isNegative = fullySanitizedValue.indexOf("-");
|
|
246
|
+
fullySanitizedValue = fullySanitizedValue.replace("-", "");
|
|
247
|
+
let index = fullySanitizedValue.indexOf(".");
|
|
248
|
+
if (index === -1) index = fullySanitizedValue.length;
|
|
249
|
+
fullySanitizedValue = fullySanitizedValue.replace(".", "");
|
|
250
|
+
if (index - 2 === 0) fullySanitizedValue = `0.${fullySanitizedValue}`;
|
|
251
|
+
else if (index - 2 === -1) fullySanitizedValue = `0.0${fullySanitizedValue}`;
|
|
252
|
+
else if (index - 2 === -2) fullySanitizedValue = "0.00";
|
|
253
|
+
else fullySanitizedValue = `${fullySanitizedValue.slice(0, index - 2)}.${fullySanitizedValue.slice(index - 2)}`;
|
|
254
|
+
if (isNegative > -1) fullySanitizedValue = `-${fullySanitizedValue}`;
|
|
255
|
+
}
|
|
242
256
|
let newValue = fullySanitizedValue ? +fullySanitizedValue : NaN;
|
|
243
257
|
if (isNaN(newValue)) return NaN;
|
|
244
|
-
// accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again
|
|
245
|
-
if (this.options.currencySign === "accounting" && $d68f3f4c684426c6$var$CURRENCY_SIGN_REGEX.test(value)) newValue = -1 * newValue;
|
|
246
|
-
// when reading the number, if it's a percent, then it should be interpreted as being divided by 100
|
|
247
258
|
if (this.options.style === "percent") {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
259
|
+
// extra step for rounding percents to what our formatter would output
|
|
260
|
+
let options = {
|
|
261
|
+
...this.options,
|
|
262
|
+
style: "decimal",
|
|
263
|
+
minimumFractionDigits: Math.min(this.options.minimumFractionDigits + 2, 20),
|
|
264
|
+
maximumFractionDigits: Math.min(this.options.maximumFractionDigits + 2, 20)
|
|
265
|
+
};
|
|
266
|
+
return new $d68f3f4c684426c6$export$cd11ab140839f11d(this.locale, options).parse(new (0, $0c1d5654b62fc485$export$cc77c4ff7e8673c5)(this.locale, options).format(newValue));
|
|
252
267
|
}
|
|
268
|
+
// accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again
|
|
269
|
+
if (this.options.currencySign === "accounting" && $d68f3f4c684426c6$var$CURRENCY_SIGN_REGEX.test(value)) newValue = -1 * newValue;
|
|
253
270
|
return newValue;
|
|
254
271
|
}
|
|
255
272
|
sanitize(value) {
|
|
@@ -277,15 +294,20 @@ class $d68f3f4c684426c6$var$NumberParserImpl {
|
|
|
277
294
|
else if (this.symbols.plusSign && value.startsWith(this.symbols.plusSign) && maxValue > 0) value = value.slice(this.symbols.plusSign.length);
|
|
278
295
|
// Numbers cannot start with a group separator
|
|
279
296
|
if (value.startsWith(this.symbols.group)) return false;
|
|
297
|
+
// Numbers that can't have any decimal values fail if a decimal character is typed
|
|
298
|
+
if (value.indexOf(this.symbols.decimal) > -1 && this.options.maximumFractionDigits === 0) return false;
|
|
280
299
|
// Remove numerals, groups, and decimals
|
|
281
300
|
value = $d68f3f4c684426c6$var$replaceAll(value, this.symbols.group, "").replace(this.symbols.numeral, "").replace(this.symbols.decimal, "");
|
|
282
301
|
// The number is valid if there are no remaining characters
|
|
283
302
|
return value.length === 0;
|
|
284
303
|
}
|
|
285
304
|
constructor(locale, options = {}){
|
|
305
|
+
this.locale = locale;
|
|
286
306
|
this.formatter = new Intl.NumberFormat(locale, options);
|
|
287
307
|
this.options = this.formatter.resolvedOptions();
|
|
288
|
-
this.symbols = $d68f3f4c684426c6$var$getSymbols(this.formatter, this.options, options);
|
|
308
|
+
this.symbols = $d68f3f4c684426c6$var$getSymbols(locale, this.formatter, this.options, options);
|
|
309
|
+
var _this_options_minimumFractionDigits, _this_options_maximumFractionDigits;
|
|
310
|
+
if (this.options.style === "percent" && (((_this_options_minimumFractionDigits = this.options.minimumFractionDigits) !== null && _this_options_minimumFractionDigits !== void 0 ? _this_options_minimumFractionDigits : 0) > 18 || ((_this_options_maximumFractionDigits = this.options.maximumFractionDigits) !== null && _this_options_maximumFractionDigits !== void 0 ? _this_options_maximumFractionDigits : 0) > 18)) console.warn("NumberParser cannot handle percentages with greater than 18 decimal places, please reduce the number in your options.");
|
|
289
311
|
}
|
|
290
312
|
}
|
|
291
313
|
const $d68f3f4c684426c6$var$nonLiteralParts = new Set([
|
|
@@ -313,12 +335,18 @@ const $d68f3f4c684426c6$var$pluralNumbers = [
|
|
|
313
335
|
0.1,
|
|
314
336
|
1.1
|
|
315
337
|
];
|
|
316
|
-
function $d68f3f4c684426c6$var$getSymbols(formatter, intlOptions, originalOptions) {
|
|
317
|
-
var _allParts_find, _posAllParts_find,
|
|
338
|
+
function $d68f3f4c684426c6$var$getSymbols(locale, formatter, intlOptions, originalOptions) {
|
|
339
|
+
var _allParts_find, _posAllParts_find, _decimalParts_find, _allParts_find1;
|
|
340
|
+
// formatter needs access to all decimal places in order to generate the correct literal strings for the plural set
|
|
341
|
+
let symbolFormatter = new Intl.NumberFormat(locale, {
|
|
342
|
+
...intlOptions,
|
|
343
|
+
minimumSignificantDigits: 1,
|
|
344
|
+
maximumSignificantDigits: 21
|
|
345
|
+
});
|
|
318
346
|
// Note: some locale's don't add a group symbol until there is a ten thousands place
|
|
319
|
-
let allParts =
|
|
320
|
-
let posAllParts =
|
|
321
|
-
let pluralParts = $d68f3f4c684426c6$var$pluralNumbers.map((n)=>
|
|
347
|
+
let allParts = symbolFormatter.formatToParts(-10000.111);
|
|
348
|
+
let posAllParts = symbolFormatter.formatToParts(10000.111);
|
|
349
|
+
let pluralParts = $d68f3f4c684426c6$var$pluralNumbers.map((n)=>symbolFormatter.formatToParts(n));
|
|
322
350
|
var _allParts_find_value;
|
|
323
351
|
let minusSign = (_allParts_find_value = (_allParts_find = allParts.find((p)=>p.type === "minusSign")) === null || _allParts_find === void 0 ? void 0 : _allParts_find.value) !== null && _allParts_find_value !== void 0 ? _allParts_find_value : "-";
|
|
324
352
|
let plusSign = (_posAllParts_find = posAllParts.find((p)=>p.type === "plusSign")) === null || _posAllParts_find === void 0 ? void 0 : _posAllParts_find.value;
|
|
@@ -326,8 +354,15 @@ function $d68f3f4c684426c6$var$getSymbols(formatter, intlOptions, originalOption
|
|
|
326
354
|
// If no plus sign was returned, but the original options contained signDisplay, default to the '+' character.
|
|
327
355
|
// @ts-ignore
|
|
328
356
|
if (!plusSign && ((originalOptions === null || originalOptions === void 0 ? void 0 : originalOptions.signDisplay) === "exceptZero" || (originalOptions === null || originalOptions === void 0 ? void 0 : originalOptions.signDisplay) === "always")) plusSign = "+";
|
|
329
|
-
|
|
330
|
-
|
|
357
|
+
// If maximumSignificantDigits is 1 (the minimum) then we won't get decimal characters out of the above formatters
|
|
358
|
+
// Percent also defaults to 0 fractionDigits, so we need to make a new one that isn't percent to get an accurate decimal
|
|
359
|
+
let decimalParts = new Intl.NumberFormat(locale, {
|
|
360
|
+
...intlOptions,
|
|
361
|
+
minimumFractionDigits: 2,
|
|
362
|
+
maximumFractionDigits: 2
|
|
363
|
+
}).formatToParts(0.001);
|
|
364
|
+
let decimal = (_decimalParts_find = decimalParts.find((p)=>p.type === "decimal")) === null || _decimalParts_find === void 0 ? void 0 : _decimalParts_find.value;
|
|
365
|
+
let group = (_allParts_find1 = allParts.find((p)=>p.type === "group")) === null || _allParts_find1 === void 0 ? void 0 : _allParts_find1.value;
|
|
331
366
|
// this set is also for a regex, it's all literals that might be in the string we want to eventually parse that
|
|
332
367
|
// don't contribute to the numerical value
|
|
333
368
|
let allPartsLiterals = allParts.filter((p)=>!$d68f3f4c684426c6$var$nonLiteralParts.has(p.type)).map((p)=>$d68f3f4c684426c6$var$escapeRegex(p.value));
|
|
@@ -368,7 +403,7 @@ function $d68f3f4c684426c6$var$replaceAll(str, find, replace) {
|
|
|
368
403
|
return str.split(find).join(replace);
|
|
369
404
|
}
|
|
370
405
|
function $d68f3f4c684426c6$var$escapeRegex(string) {
|
|
371
|
-
return string.replace(/[
|
|
406
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
372
407
|
}
|
|
373
408
|
|
|
374
409
|
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/@internationalized/number/src/index.ts","packages/@internationalized/number/src/NumberFormatter.ts","packages/@internationalized/number/src/NumberParser.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type {NumberFormatOptions} from './NumberFormatter';\n\nexport {NumberFormatter} from './NumberFormatter';\nexport {NumberParser} from './NumberParser';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nlet formatterCache = new Map<string, Intl.NumberFormat>();\n\nlet supportsSignDisplay = false;\ntry {\n // @ts-ignore\n supportsSignDisplay = (new Intl.NumberFormat('de-DE', {signDisplay: 'exceptZero'})).resolvedOptions().signDisplay === 'exceptZero';\n // eslint-disable-next-line no-empty\n} catch (e) {}\n\nlet supportsUnit = false;\ntry {\n // @ts-ignore\n supportsUnit = (new Intl.NumberFormat('de-DE', {style: 'unit', unit: 'degree'})).resolvedOptions().style === 'unit';\n // eslint-disable-next-line no-empty\n} catch (e) {}\n\n// Polyfill for units since Safari doesn't support them yet. See https://bugs.webkit.org/show_bug.cgi?id=215438.\n// Currently only polyfilling the unit degree in narrow format for ColorSlider in our supported locales.\n// Values were determined by switching to each locale manually in Chrome.\nconst UNITS = {\n degree: {\n narrow: {\n default: '°',\n 'ja-JP': ' 度',\n 'zh-TW': '度',\n 'sl-SI': ' °'\n // Arabic?? But Safari already doesn't use Arabic digits so might be ok...\n // https://bugs.webkit.org/show_bug.cgi?id=218139\n }\n }\n};\n\nexport interface NumberFormatOptions extends Intl.NumberFormatOptions {\n /** Overrides default numbering system for the current locale. */\n numberingSystem?: string\n}\n\ninterface NumberRangeFormatPart extends Intl.NumberFormatPart {\n source: 'startRange' | 'endRange' | 'shared'\n}\n\n/**\n * A wrapper around Intl.NumberFormat providing additional options, polyfills, and caching for performance.\n */\nexport class NumberFormatter implements Intl.NumberFormat {\n private numberFormatter: Intl.NumberFormat;\n private options: NumberFormatOptions;\n\n constructor(locale: string, options: NumberFormatOptions = {}) {\n this.numberFormatter = getCachedNumberFormatter(locale, options);\n this.options = options;\n }\n\n /** Formats a number value as a string, according to the locale and options provided to the constructor. */\n format(value: number): string {\n let res = '';\n if (!supportsSignDisplay && this.options.signDisplay != null) {\n res = numberFormatSignDisplayPolyfill(this.numberFormatter, this.options.signDisplay, value);\n } else {\n res = this.numberFormatter.format(value);\n }\n\n if (this.options.style === 'unit' && !supportsUnit) {\n let {unit, unitDisplay = 'short', locale} = this.resolvedOptions();\n let values = UNITS[unit]?.[unitDisplay];\n res += values[locale] || values.default;\n }\n\n return res;\n }\n\n /** Formats a number to an array of parts such as separators, digits, punctuation, and more. */\n formatToParts(value: number): Intl.NumberFormatPart[] {\n // TODO: implement signDisplay for formatToParts\n // @ts-ignore\n return this.numberFormatter.formatToParts(value);\n }\n\n /** Formats a number range as a string. */\n formatRange(start: number, end: number): string {\n // @ts-ignore\n if (typeof this.numberFormatter.formatRange === 'function') {\n // @ts-ignore\n return this.numberFormatter.formatRange(start, end);\n }\n\n if (end < start) {\n throw new RangeError('End date must be >= start date');\n }\n\n // Very basic fallback for old browsers.\n return `${this.format(start)} – ${this.format(end)}`;\n }\n\n /** Formats a number range as an array of parts. */\n formatRangeToParts(start: number, end: number): NumberRangeFormatPart[] {\n // @ts-ignore\n if (typeof this.numberFormatter.formatRangeToParts === 'function') {\n // @ts-ignore\n return this.numberFormatter.formatRangeToParts(start, end);\n }\n\n if (end < start) {\n throw new RangeError('End date must be >= start date');\n }\n\n let startParts = this.numberFormatter.formatToParts(start);\n let endParts = this.numberFormatter.formatToParts(end);\n return [\n ...startParts.map(p => ({...p, source: 'startRange'} as NumberRangeFormatPart)),\n {type: 'literal', value: ' – ', source: 'shared'},\n ...endParts.map(p => ({...p, source: 'endRange'} as NumberRangeFormatPart))\n ];\n }\n\n /** Returns the resolved formatting options based on the values passed to the constructor. */\n resolvedOptions(): Intl.ResolvedNumberFormatOptions {\n let options = this.numberFormatter.resolvedOptions();\n if (!supportsSignDisplay && this.options.signDisplay != null) {\n options = {...options, signDisplay: this.options.signDisplay};\n }\n\n if (!supportsUnit && this.options.style === 'unit') {\n options = {...options, style: 'unit', unit: this.options.unit, unitDisplay: this.options.unitDisplay};\n }\n\n return options;\n }\n}\n\nfunction getCachedNumberFormatter(locale: string, options: NumberFormatOptions = {}): Intl.NumberFormat {\n let {numberingSystem} = options;\n if (numberingSystem && locale.indexOf('-u-nu-') === -1) {\n locale = `${locale}-u-nu-${numberingSystem}`;\n }\n\n if (options.style === 'unit' && !supportsUnit) {\n let {unit, unitDisplay = 'short'} = options;\n if (!unit) {\n throw new Error('unit option must be provided with style: \"unit\"');\n }\n if (!UNITS[unit]?.[unitDisplay]) {\n throw new Error(`Unsupported unit ${unit} with unitDisplay = ${unitDisplay}`);\n }\n options = {...options, style: 'decimal'};\n }\n\n let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : '');\n if (formatterCache.has(cacheKey)) {\n return formatterCache.get(cacheKey);\n }\n\n let numberFormatter = new Intl.NumberFormat(locale, options);\n formatterCache.set(cacheKey, numberFormatter);\n return numberFormatter;\n}\n\n/** @private - exported for tests */\nexport function numberFormatSignDisplayPolyfill(numberFormat: Intl.NumberFormat, signDisplay: string, num: number) {\n if (signDisplay === 'auto') {\n return numberFormat.format(num);\n } else if (signDisplay === 'never') {\n return numberFormat.format(Math.abs(num));\n } else {\n let needsPositiveSign = false;\n if (signDisplay === 'always') {\n needsPositiveSign = num > 0 || Object.is(num, 0);\n } else if (signDisplay === 'exceptZero') {\n if (Object.is(num, -0) || Object.is(num, 0)) {\n num = Math.abs(num);\n } else {\n needsPositiveSign = num > 0;\n }\n }\n\n if (needsPositiveSign) {\n let negative = numberFormat.format(-num);\n let noSign = numberFormat.format(num);\n // ignore RTL/LTR marker character\n let minus = negative.replace(noSign, '').replace(/\\u200e|\\u061C/, '');\n if ([...minus].length !== 1) {\n console.warn('@react-aria/i18n polyfill for NumberFormat signDisplay: Unsupported case');\n }\n let positive = negative.replace(noSign, '!!!').replace(minus, '+').replace('!!!', noSign);\n return positive;\n } else {\n return numberFormat.format(num);\n }\n }\n}\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\ninterface Symbols {\n minusSign: string,\n plusSign: string,\n decimal: string,\n group: string,\n literals: RegExp,\n numeral: RegExp,\n index: (v: string) => string\n}\n\nconst CURRENCY_SIGN_REGEX = new RegExp('^.*\\\\(.*\\\\).*$');\nconst NUMBERING_SYSTEMS = ['latn', 'arab', 'hanidec'];\n\n/**\n * A NumberParser can be used to perform locale-aware parsing of numbers from Unicode strings,\n * as well as validation of partial user input. It automatically detects the numbering system\n * used in the input, and supports parsing decimals, percentages, currency values, and units\n * according to the locale.\n */\nexport class NumberParser {\n private locale: string;\n private options: Intl.NumberFormatOptions;\n\n constructor(locale: string, options: Intl.NumberFormatOptions = {}) {\n this.locale = locale;\n this.options = options;\n }\n\n /**\n * Parses the given string to a number. Returns NaN if a valid number could not be parsed.\n */\n parse(value: string): number {\n return getNumberParserImpl(this.locale, this.options, value).parse(value);\n }\n\n /**\n * Returns whether the given string could potentially be a valid number. This should be used to\n * validate user input as the user types. If a `minValue` or `maxValue` is provided, the validity\n * of the minus/plus sign characters can be checked.\n */\n isValidPartialNumber(value: string, minValue?: number, maxValue?: number): boolean {\n return getNumberParserImpl(this.locale, this.options, value).isValidPartialNumber(value, minValue, maxValue);\n }\n\n /**\n * Returns a numbering system for which the given string is valid in the current locale.\n * If no numbering system could be detected, the default numbering system for the current\n * locale is returned.\n */\n getNumberingSystem(value: string): string {\n return getNumberParserImpl(this.locale, this.options, value).options.numberingSystem;\n }\n}\n\nconst numberParserCache = new Map<string, NumberParserImpl>();\nfunction getNumberParserImpl(locale: string, options: Intl.NumberFormatOptions, value: string) {\n // First try the default numbering system for the provided locale\n let defaultParser = getCachedNumberParser(locale, options);\n\n // If that doesn't match, and the locale doesn't include a hard coded numbering system,\n // try each of the other supported numbering systems until we find one that matches.\n if (!locale.includes('-nu-') && !defaultParser.isValidPartialNumber(value)) {\n for (let numberingSystem of NUMBERING_SYSTEMS) {\n if (numberingSystem !== defaultParser.options.numberingSystem) {\n let parser = getCachedNumberParser(locale + (locale.includes('-u-') ? '-nu-' : '-u-nu-') + numberingSystem, options);\n if (parser.isValidPartialNumber(value)) {\n return parser;\n }\n }\n }\n }\n\n return defaultParser;\n}\n\nfunction getCachedNumberParser(locale: string, options: Intl.NumberFormatOptions) {\n let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : '');\n let parser = numberParserCache.get(cacheKey);\n if (!parser) {\n parser = new NumberParserImpl(locale, options);\n numberParserCache.set(cacheKey, parser);\n }\n\n return parser;\n}\n\n// The actual number parser implementation. Instances of this class are cached\n// based on the locale, options, and detected numbering system.\nclass NumberParserImpl {\n formatter: Intl.NumberFormat;\n options: Intl.ResolvedNumberFormatOptions;\n symbols: Symbols;\n\n constructor(locale: string, options: Intl.NumberFormatOptions = {}) {\n this.formatter = new Intl.NumberFormat(locale, options);\n this.options = this.formatter.resolvedOptions();\n this.symbols = getSymbols(this.formatter, this.options, options);\n }\n\n parse(value: string) {\n // to parse the number, we need to remove anything that isn't actually part of the number, for example we want '-10.40' not '-10.40 USD'\n let fullySanitizedValue = this.sanitize(value);\n\n // Remove group characters, and replace decimal points and numerals with ASCII values.\n fullySanitizedValue = replaceAll(fullySanitizedValue, this.symbols.group, '')\n .replace(this.symbols.decimal, '.')\n .replace(this.symbols.minusSign, '-')\n .replace(this.symbols.numeral, this.symbols.index);\n\n let newValue = fullySanitizedValue ? +fullySanitizedValue : NaN;\n if (isNaN(newValue)) {\n return NaN;\n }\n\n // accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again\n if (this.options.currencySign === 'accounting' && CURRENCY_SIGN_REGEX.test(value)) {\n newValue = -1 * newValue;\n }\n\n // when reading the number, if it's a percent, then it should be interpreted as being divided by 100\n if (this.options.style === 'percent') {\n newValue /= 100;\n // after dividing to get the percent value, javascript may get .0210999999 instead of .0211, so fix the number of fraction digits\n newValue = +newValue.toFixed((this.options.maximumFractionDigits ?? 0) + 2);\n }\n\n return newValue;\n }\n\n sanitize(value: string) {\n // Remove literals and whitespace, which are allowed anywhere in the string\n value = value.replace(this.symbols.literals, '');\n\n // Replace the ASCII minus sign with the minus sign used in the current locale\n // so that both are allowed in case the user's keyboard doesn't have the locale's minus sign.\n value = value.replace('-', this.symbols.minusSign);\n\n // In arab numeral system, their decimal character is 1643, but most keyboards don't type that\n // instead they use the , (44) character or apparently the (1548) character.\n if (this.options.numberingSystem === 'arab') {\n value = value.replace(',', this.symbols.decimal);\n value = value.replace(String.fromCharCode(1548), this.symbols.decimal);\n value = replaceAll(value, '.', this.symbols.group);\n }\n\n // fr-FR group character is char code 8239, but that's not a key on the french keyboard,\n // so allow 'period' as a group char and replace it with a space\n if (this.options.locale === 'fr-FR') {\n value = replaceAll(value, '.', String.fromCharCode(8239));\n }\n\n return value;\n }\n\n isValidPartialNumber(value: string, minValue: number = -Infinity, maxValue: number = Infinity): boolean {\n value = this.sanitize(value);\n\n // Remove minus or plus sign, which must be at the start of the string.\n if (value.startsWith(this.symbols.minusSign) && minValue < 0) {\n value = value.slice(this.symbols.minusSign.length);\n } else if (this.symbols.plusSign && value.startsWith(this.symbols.plusSign) && maxValue > 0) {\n value = value.slice(this.symbols.plusSign.length);\n }\n\n // Numbers cannot start with a group separator\n if (value.startsWith(this.symbols.group)) {\n return false;\n }\n\n // Remove numerals, groups, and decimals\n value = replaceAll(value, this.symbols.group, '')\n .replace(this.symbols.numeral, '')\n .replace(this.symbols.decimal, '');\n\n // The number is valid if there are no remaining characters\n return value.length === 0;\n }\n}\n\nconst nonLiteralParts = new Set(['decimal', 'fraction', 'integer', 'minusSign', 'plusSign', 'group']);\n\n// This list is derived from https://www.unicode.org/cldr/charts/43/supplemental/language_plural_rules.html#comparison and includes\n// all unique numbers which we need to check in order to determine all the plural forms for a given locale.\n// See: https://github.com/adobe/react-spectrum/pull/5134/files#r1337037855 for used script\nconst pluralNumbers = [\n 0, 4, 2, 1, 11, 20, 3, 7, 100, 21, 0.1, 1.1\n];\n\nfunction getSymbols(formatter: Intl.NumberFormat, intlOptions: Intl.ResolvedNumberFormatOptions, originalOptions: Intl.NumberFormatOptions): Symbols {\n // Note: some locale's don't add a group symbol until there is a ten thousands place\n let allParts = formatter.formatToParts(-10000.111);\n let posAllParts = formatter.formatToParts(10000.111);\n let pluralParts = pluralNumbers.map(n => formatter.formatToParts(n));\n\n let minusSign = allParts.find(p => p.type === 'minusSign')?.value ?? '-';\n let plusSign = posAllParts.find(p => p.type === 'plusSign')?.value;\n\n // Safari does not support the signDisplay option, but our number parser polyfills it.\n // If no plus sign was returned, but the original options contained signDisplay, default to the '+' character.\n // @ts-ignore\n if (!plusSign && (originalOptions?.signDisplay === 'exceptZero' || originalOptions?.signDisplay === 'always')) {\n plusSign = '+';\n }\n\n let decimal = allParts.find(p => p.type === 'decimal')?.value;\n let group = allParts.find(p => p.type === 'group')?.value;\n\n // this set is also for a regex, it's all literals that might be in the string we want to eventually parse that\n // don't contribute to the numerical value\n let allPartsLiterals = allParts.filter(p => !nonLiteralParts.has(p.type)).map(p => escapeRegex(p.value));\n let pluralPartsLiterals = pluralParts.flatMap(p => p.filter(p => !nonLiteralParts.has(p.type)).map(p => escapeRegex(p.value)));\n let sortedLiterals = [...new Set([...allPartsLiterals, ...pluralPartsLiterals])].sort((a, b) => b.length - a.length);\n\n let literals = sortedLiterals.length === 0 ? \n new RegExp('[\\\\p{White_Space}]', 'gu') :\n new RegExp(`${sortedLiterals.join('|')}|[\\\\p{White_Space}]`, 'gu');\n\n // These are for replacing non-latn characters with the latn equivalent\n let numerals = [...new Intl.NumberFormat(intlOptions.locale, {useGrouping: false}).format(9876543210)].reverse();\n let indexes = new Map(numerals.map((d, i) => [d, i]));\n let numeral = new RegExp(`[${numerals.join('')}]`, 'g');\n let index = d => String(indexes.get(d));\n\n return {minusSign, plusSign, decimal, group, literals, numeral, index};\n}\n\nfunction replaceAll(str: string, find: string, replace: string) {\n // @ts-ignore\n if (str.replaceAll) {\n // @ts-ignore\n return str.replaceAll(find, replace);\n }\n\n return str.split(find).join(replace);\n}\n\nfunction escapeRegex(string: string) {\n return string.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n}\n"],"names":[],"version":3,"file":"main.js.map"}
|
|
1
|
+
{"mappings":";;;;;;AAAA;;;;;;;;;;ACAA;;;;;;;;;;CAUC,GAED,IAAI,uCAAiB,IAAI;AAEzB,IAAI,4CAAsB;AAC1B,IAAI;IACF,aAAa;IACb,4CAAsB,AAAC,IAAI,KAAK,aAAa,SAAS;QAAC,aAAa;IAAY,GAAI,kBAAkB,gBAAgB;AACtH,oCAAoC;AACtC,EAAE,OAAO,GAAG,CAAC;AAEb,IAAI,qCAAe;AACnB,IAAI;IACF,aAAa;IACb,qCAAe,AAAC,IAAI,KAAK,aAAa,SAAS;QAAC,OAAO;QAAQ,MAAM;IAAQ,GAAI,kBAAkB,UAAU;AAC7G,oCAAoC;AACtC,EAAE,OAAO,GAAG,CAAC;AAEb,gHAAgH;AAChH,wGAAwG;AACxG,yEAAyE;AACzE,MAAM,8BAAQ;IACZ,QAAQ;QACN,QAAQ;YACN,SAAS;YACT,SAAS;YACT,SAAS;YACT,SAAS;QAGX;IACF;AACF;AAcO,MAAM;IASX,yGAAyG,GACzG,OAAO,KAAa,EAAU;QAC5B,IAAI,MAAM;QACV,IAAI,CAAC,6CAAuB,IAAI,CAAC,QAAQ,eAAe,MACtD,MAAM,0CAAgC,IAAI,CAAC,iBAAiB,IAAI,CAAC,QAAQ,aAAa;aAEtF,MAAM,IAAI,CAAC,gBAAgB,OAAO;QAGpC,IAAI,IAAI,CAAC,QAAQ,UAAU,UAAU,CAAC,oCAAc;gBAErC;YADb,IAAI,QAAC,IAAI,eAAE,cAAc,iBAAS,MAAM,EAAC,GAAG,IAAI,CAAC;YACjD,IAAI,SAAS,CAAA,cAAA,2BAAK,CAAC,KAAK,cAAX,yBAAA,KAAA,IAAA,WAAa,CAAC,YAAY;YACvC,OAAO,MAAM,CAAC,OAAO,IAAI,OAAO;QAClC;QAEA,OAAO;IACT;IAEA,6FAA6F,GAC7F,cAAc,KAAa,EAA2B;QACpD,gDAAgD;QAChD,aAAa;QACb,OAAO,IAAI,CAAC,gBAAgB,cAAc;IAC5C;IAEA,wCAAwC,GACxC,YAAY,KAAa,EAAE,GAAW,EAAU;QAC9C,aAAa;QACb,IAAI,OAAO,IAAI,CAAC,gBAAgB,gBAAgB,YAC9C,aAAa;QACb,OAAO,IAAI,CAAC,gBAAgB,YAAY,OAAO;QAGjD,IAAI,MAAM,OACR,MAAM,IAAI,WAAW;QAGvB,wCAAwC;QACxC,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,OAAO,GAAG,EAAE,IAAI,CAAC,OAAO,KAAK,CAAC;IACtD;IAEA,iDAAiD,GACjD,mBAAmB,KAAa,EAAE,GAAW,EAA2B;QACtE,aAAa;QACb,IAAI,OAAO,IAAI,CAAC,gBAAgB,uBAAuB,YACrD,aAAa;QACb,OAAO,IAAI,CAAC,gBAAgB,mBAAmB,OAAO;QAGxD,IAAI,MAAM,OACR,MAAM,IAAI,WAAW;QAGvB,IAAI,aAAa,IAAI,CAAC,gBAAgB,cAAc;QACpD,IAAI,WAAW,IAAI,CAAC,gBAAgB,cAAc;QAClD,OAAO;eACF,WAAW,IAAI,CAAA,IAAM,CAAA;oBAAC,GAAG,CAAC;oBAAE,QAAQ;gBAAY,CAAA;YACnD;gBAAC,MAAM;gBAAW,OAAO;gBAAO,QAAQ;YAAQ;eAC7C,SAAS,IAAI,CAAA,IAAM,CAAA;oBAAC,GAAG,CAAC;oBAAE,QAAQ;gBAAU,CAAA;SAChD;IACH;IAEA,2FAA2F,GAC3F,kBAAoD;QAClD,IAAI,UAAU,IAAI,CAAC,gBAAgB;QACnC,IAAI,CAAC,6CAAuB,IAAI,CAAC,QAAQ,eAAe,MACtD,UAAU;YAAC,GAAG,OAAO;YAAE,aAAa,IAAI,CAAC,QAAQ;QAAW;QAG9D,IAAI,CAAC,sCAAgB,IAAI,CAAC,QAAQ,UAAU,QAC1C,UAAU;YAAC,GAAG,OAAO;YAAE,OAAO;YAAQ,MAAM,IAAI,CAAC,QAAQ;YAAM,aAAa,IAAI,CAAC,QAAQ;QAAW;QAGtG,OAAO;IACT;IA/EA,YAAY,MAAc,EAAE,UAA+B,CAAC,CAAC,CAAE;QAC7D,IAAI,CAAC,kBAAkB,+CAAyB,QAAQ;QACxD,IAAI,CAAC,UAAU;IACjB;AA6EF;AAEA,SAAS,+CAAyB,MAAc,EAAE,UAA+B,CAAC,CAAC;IACjF,IAAI,mBAAC,eAAe,EAAC,GAAG;IACxB,IAAI,mBAAmB,OAAO,QAAQ,cAAc,IAClD,SAAS,CAAC,EAAE,OAAO,MAAM,EAAE,gBAAgB,CAAC;IAG9C,IAAI,QAAQ,UAAU,UAAU,CAAC,oCAAc;YAKxC;QAJL,IAAI,QAAC,IAAI,eAAE,cAAc,SAAQ,GAAG;QACpC,IAAI,CAAC,MACH,MAAM,IAAI,MAAM;QAElB,IAAI,CAAC,CAAA,CAAA,cAAA,2BAAK,CAAC,KAAK,cAAX,yBAAA,KAAA,IAAA,WAAa,CAAC,YAAY,AAAD,GAC5B,MAAM,IAAI,MAAM,CAAC,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,YAAY,CAAC;QAE9E,UAAU;YAAC,GAAG,OAAO;YAAE,OAAO;QAAS;IACzC;IAEA,IAAI,WAAW,SAAU,CAAA,UAAU,OAAO,QAAQ,SAAS,KAAK,CAAC,GAAG,IAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG,SAAS,EAAC;IAC1G,IAAI,qCAAe,IAAI,WACrB,OAAO,qCAAe,IAAI;IAG5B,IAAI,kBAAkB,IAAI,KAAK,aAAa,QAAQ;IACpD,qCAAe,IAAI,UAAU;IAC7B,OAAO;AACT;AAGO,SAAS,0CAAgC,YAA+B,EAAE,WAAmB,EAAE,GAAW;IAC/G,IAAI,gBAAgB,QAClB,OAAO,aAAa,OAAO;SACtB,IAAI,gBAAgB,SACzB,OAAO,aAAa,OAAO,KAAK,IAAI;SAC/B;QACL,IAAI,oBAAoB;QACxB,IAAI,gBAAgB,UAClB,oBAAoB,MAAM,KAAK,OAAO,GAAG,KAAK;aACzC,IAAI,gBAAgB;YACzB,IAAI,OAAO,GAAG,KAAK,OAAO,OAAO,GAAG,KAAK,IACvC,MAAM,KAAK,IAAI;iBAEf,oBAAoB,MAAM;;QAI9B,IAAI,mBAAmB;YACrB,IAAI,WAAW,aAAa,OAAO,CAAC;YACpC,IAAI,SAAS,aAAa,OAAO;YACjC,kCAAkC;YAClC,IAAI,QAAQ,SAAS,QAAQ,QAAQ,IAAI,QAAQ,iBAAiB;YAClE,IAAI;mBAAI;aAAM,CAAC,WAAW,GACxB,QAAQ,KAAK;YAEf,IAAI,WAAW,SAAS,QAAQ,QAAQ,OAAO,QAAQ,OAAO,KAAK,QAAQ,OAAO;YAClF,OAAO;QACT,OACE,OAAO,aAAa,OAAO;IAE/B;AACF;;CD/LC;AEVD;;;;;;;;;;CAUC;AAcD,MAAM,4CAAsB,IAAI,OAAO;AACvC,MAAM,0CAAoB;IAAC;IAAQ;IAAQ;CAAU;AAQ9C,MAAM;IASX;;GAEC,GACD,MAAM,KAAa,EAAU;QAC3B,OAAO,0CAAoB,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,OAAO,MAAM;IACrE;IAEA;;;;GAIC,GACD,qBAAqB,KAAa,EAAE,QAAiB,EAAE,QAAiB,EAAW;QACjF,OAAO,0CAAoB,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,OAAO,qBAAqB,OAAO,UAAU;IACrG;IAEA;;;;GAIC,GACD,mBAAmB,KAAa,EAAU;QACxC,OAAO,0CAAoB,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,OAAO,QAAQ;IACvE;IA5BA,YAAY,MAAc,EAAE,UAAoC,CAAC,CAAC,CAAE;QAClE,IAAI,CAAC,SAAS;QACd,IAAI,CAAC,UAAU;IACjB;AA0BF;AAEA,MAAM,0CAAoB,IAAI;AAC9B,SAAS,0CAAoB,MAAc,EAAE,OAAiC,EAAE,KAAa;IAC3F,iEAAiE;IACjE,IAAI,gBAAgB,4CAAsB,QAAQ;IAElD,uFAAuF;IACvF,oFAAoF;IACpF,IAAI,CAAC,OAAO,SAAS,WAAW,CAAC,cAAc,qBAAqB,QAAQ;QAC1E,KAAK,IAAI,mBAAmB,wCAC1B,IAAI,oBAAoB,cAAc,QAAQ,iBAAiB;YAC7D,IAAI,SAAS,4CAAsB,SAAU,CAAA,OAAO,SAAS,SAAS,SAAS,QAAO,IAAK,iBAAiB;YAC5G,IAAI,OAAO,qBAAqB,QAC9B,OAAO;QAEX;IAEJ;IAEA,OAAO;AACT;AAEA,SAAS,4CAAsB,MAAc,EAAE,OAAiC;IAC9E,IAAI,WAAW,SAAU,CAAA,UAAU,OAAO,QAAQ,SAAS,KAAK,CAAC,GAAG,IAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG,SAAS,EAAC;IAC1G,IAAI,SAAS,wCAAkB,IAAI;IACnC,IAAI,CAAC,QAAQ;QACX,SAAS,IAAI,uCAAiB,QAAQ;QACtC,wCAAkB,IAAI,UAAU;IAClC;IAEA,OAAO;AACT;AAEA,8EAA8E;AAC9E,+DAA+D;AAC/D,MAAM;IAgBJ,MAAM,KAAa,EAAE;QACnB,wIAAwI;QACxI,IAAI,sBAAsB,IAAI,CAAC,SAAS;QAExC,sFAAsF;QACtF,sBAAsB,iCAAW,qBAAqB,IAAI,CAAC,QAAQ,OAAO,IACvE,QAAQ,IAAI,CAAC,QAAQ,SAAS,KAC9B,QAAQ,IAAI,CAAC,QAAQ,WAAW,KAChC,QAAQ,IAAI,CAAC,QAAQ,SAAS,IAAI,CAAC,QAAQ;QAE9C,IAAI,IAAI,CAAC,QAAQ,UAAU,WAAW;YACpC,gIAAgI;YAChI,IAAI,aAAa,oBAAoB,QAAQ;YAC7C,sBAAsB,oBAAoB,QAAQ,KAAK;YACvD,IAAI,QAAQ,oBAAoB,QAAQ;YACxC,IAAI,UAAU,IACZ,QAAQ,oBAAoB;YAE9B,sBAAsB,oBAAoB,QAAQ,KAAK;YACvD,IAAI,QAAQ,MAAM,GAChB,sBAAsB,CAAC,EAAE,EAAE,oBAAoB,CAAC;iBAC3C,IAAI,QAAQ,MAAM,IACvB,sBAAsB,CAAC,GAAG,EAAE,oBAAoB,CAAC;iBAC5C,IAAI,QAAQ,MAAM,IACvB,sBAAsB;iBAEtB,sBAAsB,CAAC,EAAE,oBAAoB,MAAM,GAAG,QAAQ,GAAG,CAAC,EAAE,oBAAoB,MAAM,QAAQ,GAAG,CAAC;YAE5G,IAAI,aAAa,IACf,sBAAsB,CAAC,CAAC,EAAE,oBAAoB,CAAC;QAEnD;QAEA,IAAI,WAAW,sBAAsB,CAAC,sBAAsB;QAC5D,IAAI,MAAM,WACR,OAAO;QAGT,IAAI,IAAI,CAAC,QAAQ,UAAU,WAAW;YACpC,sEAAsE;YACtE,IAAI,UAAU;gBACZ,GAAG,IAAI,CAAC,OAAO;gBACf,OAAO;gBACP,uBAAuB,KAAK,IAAI,IAAI,CAAC,QAAQ,wBAAwB,GAAG;gBACxE,uBAAuB,KAAK,IAAI,IAAI,CAAC,QAAQ,wBAAwB,GAAG;YAC1E;YACA,OAAO,AAAC,IAAI,0CAAa,IAAI,CAAC,QAAQ,SAAU,MAAM,IAAI,CAAA,GAAA,yCAAc,EAAE,IAAI,CAAC,QAAQ,SAAS,OAAO;QACzG;QAEA,wJAAwJ;QACxJ,IAAI,IAAI,CAAC,QAAQ,iBAAiB,gBAAgB,0CAAoB,KAAK,QACzE,WAAW,KAAK;QAGlB,OAAO;IACT;IAEA,SAAS,KAAa,EAAE;QACtB,2EAA2E;QAC3E,QAAQ,MAAM,QAAQ,IAAI,CAAC,QAAQ,UAAU;QAE7C,8EAA8E;QAC9E,6FAA6F;QAC7F,QAAQ,MAAM,QAAQ,KAAK,IAAI,CAAC,QAAQ;QAExC,8FAA8F;QAC9F,4EAA4E;QAC5E,IAAI,IAAI,CAAC,QAAQ,oBAAoB,QAAQ;YAC3C,QAAQ,MAAM,QAAQ,KAAK,IAAI,CAAC,QAAQ;YACxC,QAAQ,MAAM,QAAQ,OAAO,aAAa,OAAO,IAAI,CAAC,QAAQ;YAC9D,QAAQ,iCAAW,OAAO,KAAK,IAAI,CAAC,QAAQ;QAC9C;QAEA,wFAAwF;QACxF,gEAAgE;QAChE,IAAI,IAAI,CAAC,QAAQ,WAAW,SAC1B,QAAQ,iCAAW,OAAO,KAAK,OAAO,aAAa;QAGrD,OAAO;IACT;IAEA,qBAAqB,KAAa,EAAE,WAAmB,CAAC,QAAQ,EAAE,WAAmB,QAAQ,EAAW;QACtG,QAAQ,IAAI,CAAC,SAAS;QAEtB,uEAAuE;QACvE,IAAI,MAAM,WAAW,IAAI,CAAC,QAAQ,cAAc,WAAW,GACzD,QAAQ,MAAM,MAAM,IAAI,CAAC,QAAQ,UAAU;aACtC,IAAI,IAAI,CAAC,QAAQ,YAAY,MAAM,WAAW,IAAI,CAAC,QAAQ,aAAa,WAAW,GACxF,QAAQ,MAAM,MAAM,IAAI,CAAC,QAAQ,SAAS;QAG5C,8CAA8C;QAC9C,IAAI,MAAM,WAAW,IAAI,CAAC,QAAQ,QAChC,OAAO;QAGT,kFAAkF;QAClF,IAAI,MAAM,QAAQ,IAAI,CAAC,QAAQ,WAAW,MAAM,IAAI,CAAC,QAAQ,0BAA0B,GACrF,OAAO;QAGT,wCAAwC;QACxC,QAAQ,iCAAW,OAAO,IAAI,CAAC,QAAQ,OAAO,IAC3C,QAAQ,IAAI,CAAC,QAAQ,SAAS,IAC9B,QAAQ,IAAI,CAAC,QAAQ,SAAS;QAEjC,2DAA2D;QAC3D,OAAO,MAAM,WAAW;IAC1B;IAvHA,YAAY,MAAc,EAAE,UAAoC,CAAC,CAAC,CAAE;QAClE,IAAI,CAAC,SAAS;QACd,IAAI,CAAC,YAAY,IAAI,KAAK,aAAa,QAAQ;QAC/C,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU;QAC9B,IAAI,CAAC,UAAU,iCAAW,QAAQ,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS;YACtB,qCAAkD;QAA5F,IAAI,IAAI,CAAC,QAAQ,UAAU,aAAc,CAAA,AAAC,CAAA,CAAA,sCAAA,IAAI,CAAC,QAAQ,mCAAb,iDAAA,sCAAsC,CAAA,IAAK,MAAM,AAAC,CAAA,CAAA,sCAAA,IAAI,CAAC,QAAQ,mCAAb,iDAAA,sCAAsC,CAAA,IAAK,EAAC,GACtI,QAAQ,KAAK;IAEjB;AAgHF;AAEA,MAAM,wCAAkB,IAAI,IAAI;IAAC;IAAW;IAAY;IAAW;IAAa;IAAY;CAAQ;AAEpG,mIAAmI;AACnI,2GAA2G;AAC3G,2FAA2F;AAC3F,MAAM,sCAAgB;IACpB;IAAG;IAAG;IAAG;IAAG;IAAI;IAAI;IAAG;IAAG;IAAK;IAAI;IAAK;CACzC;AAED,SAAS,iCAAW,MAAc,EAAE,SAA4B,EAAE,WAA6C,EAAE,eAAyC;QAQxI,gBACD,mBAaD,oBACF;IAtBZ,mHAAmH;IACnH,IAAI,kBAAkB,IAAI,KAAK,aAAa,QAAQ;QAAC,GAAG,WAAW;QAAE,0BAA0B;QAAG,0BAA0B;IAAE;IAC9H,oFAAoF;IACpF,IAAI,WAAW,gBAAgB,cAAc;IAC7C,IAAI,cAAc,gBAAgB,cAAc;IAChD,IAAI,cAAc,oCAAc,IAAI,CAAA,IAAK,gBAAgB,cAAc;QAEvD;IAAhB,IAAI,YAAY,CAAA,uBAAA,CAAA,iBAAA,SAAS,KAAK,CAAA,IAAK,EAAE,SAAS,0BAA9B,4BAAA,KAAA,IAAA,eAA4C,mBAA5C,kCAAA,uBAAqD;IACrE,IAAI,WAAW,CAAA,oBAAA,YAAY,KAAK,CAAA,IAAK,EAAE,SAAS,yBAAjC,+BAAA,KAAA,IAAA,kBAA8C;IAE7D,sFAAsF;IACtF,8GAA8G;IAC9G,aAAa;IACb,IAAI,CAAC,YAAa,CAAA,CAAA,4BAAA,6BAAA,KAAA,IAAA,gBAAiB,WAAU,MAAM,gBAAgB,CAAA,4BAAA,6BAAA,KAAA,IAAA,gBAAiB,WAAU,MAAM,QAAO,GACzG,WAAW;IAGb,kHAAkH;IAClH,wHAAwH;IACxH,IAAI,eAAe,IAAI,KAAK,aAAa,QAAQ;QAAC,GAAG,WAAW;QAAE,uBAAuB;QAAG,uBAAuB;IAAC,GAAG,cAAc;IAErI,IAAI,UAAU,CAAA,qBAAA,aAAa,KAAK,CAAA,IAAK,EAAE,SAAS,wBAAlC,gCAAA,KAAA,IAAA,mBAA8C;IAC5D,IAAI,QAAQ,CAAA,kBAAA,SAAS,KAAK,CAAA,IAAK,EAAE,SAAS,sBAA9B,6BAAA,KAAA,IAAA,gBAAwC;IAEpD,+GAA+G;IAC/G,0CAA0C;IAC1C,IAAI,mBAAmB,SAAS,OAAO,CAAA,IAAK,CAAC,sCAAgB,IAAI,EAAE,OAAO,IAAI,CAAA,IAAK,kCAAY,EAAE;IACjG,IAAI,sBAAsB,YAAY,QAAQ,CAAA,IAAK,EAAE,OAAO,CAAA,IAAK,CAAC,sCAAgB,IAAI,EAAE,OAAO,IAAI,CAAA,IAAK,kCAAY,EAAE;IACtH,IAAI,iBAAiB;WAAI,IAAI,IAAI;eAAI;eAAqB;SAAoB;KAAE,CAAC,KAAK,CAAC,GAAG,IAAM,EAAE,SAAS,EAAE;IAE7G,IAAI,WAAW,eAAe,WAAW,IACrC,IAAI,OAAO,sBAAsB,QACjC,IAAI,OAAO,CAAC,EAAE,eAAe,KAAK,KAAK,mBAAmB,CAAC,EAAE;IAEjE,uEAAuE;IACvE,IAAI,WAAW;WAAI,IAAI,KAAK,aAAa,YAAY,QAAQ;YAAC,aAAa;QAAK,GAAG,OAAO;KAAY,CAAC;IACvG,IAAI,UAAU,IAAI,IAAI,SAAS,IAAI,CAAC,GAAG,IAAM;YAAC;YAAG;SAAE;IACnD,IAAI,UAAU,IAAI,OAAO,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC,CAAC,EAAE;IACnD,IAAI,QAAQ,CAAA,IAAK,OAAO,QAAQ,IAAI;IAEpC,OAAO;mBAAC;kBAAW;iBAAU;eAAS;kBAAO;iBAAU;eAAS;IAAK;AACvE;AAEA,SAAS,iCAAW,GAAW,EAAE,IAAY,EAAE,OAAe;IAC5D,aAAa;IACb,IAAI,IAAI,YACN,aAAa;IACb,OAAO,IAAI,WAAW,MAAM;IAG9B,OAAO,IAAI,MAAM,MAAM,KAAK;AAC9B;AAEA,SAAS,kCAAY,MAAc;IACjC,OAAO,OAAO,QAAQ,uBAAuB;AAC/C;","sources":["packages/@internationalized/number/src/index.ts","packages/@internationalized/number/src/NumberFormatter.ts","packages/@internationalized/number/src/NumberParser.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type {NumberFormatOptions} from './NumberFormatter';\n\nexport {NumberFormatter} from './NumberFormatter';\nexport {NumberParser} from './NumberParser';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nlet formatterCache = new Map<string, Intl.NumberFormat>();\n\nlet supportsSignDisplay = false;\ntry {\n // @ts-ignore\n supportsSignDisplay = (new Intl.NumberFormat('de-DE', {signDisplay: 'exceptZero'})).resolvedOptions().signDisplay === 'exceptZero';\n // eslint-disable-next-line no-empty\n} catch (e) {}\n\nlet supportsUnit = false;\ntry {\n // @ts-ignore\n supportsUnit = (new Intl.NumberFormat('de-DE', {style: 'unit', unit: 'degree'})).resolvedOptions().style === 'unit';\n // eslint-disable-next-line no-empty\n} catch (e) {}\n\n// Polyfill for units since Safari doesn't support them yet. See https://bugs.webkit.org/show_bug.cgi?id=215438.\n// Currently only polyfilling the unit degree in narrow format for ColorSlider in our supported locales.\n// Values were determined by switching to each locale manually in Chrome.\nconst UNITS = {\n degree: {\n narrow: {\n default: '°',\n 'ja-JP': ' 度',\n 'zh-TW': '度',\n 'sl-SI': ' °'\n // Arabic?? But Safari already doesn't use Arabic digits so might be ok...\n // https://bugs.webkit.org/show_bug.cgi?id=218139\n }\n }\n};\n\nexport interface NumberFormatOptions extends Intl.NumberFormatOptions {\n /** Overrides default numbering system for the current locale. */\n numberingSystem?: string\n}\n\ninterface NumberRangeFormatPart extends Intl.NumberFormatPart {\n source: 'startRange' | 'endRange' | 'shared'\n}\n\n/**\n * A wrapper around Intl.NumberFormat providing additional options, polyfills, and caching for performance.\n */\nexport class NumberFormatter implements Intl.NumberFormat {\n private numberFormatter: Intl.NumberFormat;\n private options: NumberFormatOptions;\n\n constructor(locale: string, options: NumberFormatOptions = {}) {\n this.numberFormatter = getCachedNumberFormatter(locale, options);\n this.options = options;\n }\n\n /** Formats a number value as a string, according to the locale and options provided to the constructor. */\n format(value: number): string {\n let res = '';\n if (!supportsSignDisplay && this.options.signDisplay != null) {\n res = numberFormatSignDisplayPolyfill(this.numberFormatter, this.options.signDisplay, value);\n } else {\n res = this.numberFormatter.format(value);\n }\n\n if (this.options.style === 'unit' && !supportsUnit) {\n let {unit, unitDisplay = 'short', locale} = this.resolvedOptions();\n let values = UNITS[unit]?.[unitDisplay];\n res += values[locale] || values.default;\n }\n\n return res;\n }\n\n /** Formats a number to an array of parts such as separators, digits, punctuation, and more. */\n formatToParts(value: number): Intl.NumberFormatPart[] {\n // TODO: implement signDisplay for formatToParts\n // @ts-ignore\n return this.numberFormatter.formatToParts(value);\n }\n\n /** Formats a number range as a string. */\n formatRange(start: number, end: number): string {\n // @ts-ignore\n if (typeof this.numberFormatter.formatRange === 'function') {\n // @ts-ignore\n return this.numberFormatter.formatRange(start, end);\n }\n\n if (end < start) {\n throw new RangeError('End date must be >= start date');\n }\n\n // Very basic fallback for old browsers.\n return `${this.format(start)} – ${this.format(end)}`;\n }\n\n /** Formats a number range as an array of parts. */\n formatRangeToParts(start: number, end: number): NumberRangeFormatPart[] {\n // @ts-ignore\n if (typeof this.numberFormatter.formatRangeToParts === 'function') {\n // @ts-ignore\n return this.numberFormatter.formatRangeToParts(start, end);\n }\n\n if (end < start) {\n throw new RangeError('End date must be >= start date');\n }\n\n let startParts = this.numberFormatter.formatToParts(start);\n let endParts = this.numberFormatter.formatToParts(end);\n return [\n ...startParts.map(p => ({...p, source: 'startRange'} as NumberRangeFormatPart)),\n {type: 'literal', value: ' – ', source: 'shared'},\n ...endParts.map(p => ({...p, source: 'endRange'} as NumberRangeFormatPart))\n ];\n }\n\n /** Returns the resolved formatting options based on the values passed to the constructor. */\n resolvedOptions(): Intl.ResolvedNumberFormatOptions {\n let options = this.numberFormatter.resolvedOptions();\n if (!supportsSignDisplay && this.options.signDisplay != null) {\n options = {...options, signDisplay: this.options.signDisplay};\n }\n\n if (!supportsUnit && this.options.style === 'unit') {\n options = {...options, style: 'unit', unit: this.options.unit, unitDisplay: this.options.unitDisplay};\n }\n\n return options;\n }\n}\n\nfunction getCachedNumberFormatter(locale: string, options: NumberFormatOptions = {}): Intl.NumberFormat {\n let {numberingSystem} = options;\n if (numberingSystem && locale.indexOf('-u-nu-') === -1) {\n locale = `${locale}-u-nu-${numberingSystem}`;\n }\n\n if (options.style === 'unit' && !supportsUnit) {\n let {unit, unitDisplay = 'short'} = options;\n if (!unit) {\n throw new Error('unit option must be provided with style: \"unit\"');\n }\n if (!UNITS[unit]?.[unitDisplay]) {\n throw new Error(`Unsupported unit ${unit} with unitDisplay = ${unitDisplay}`);\n }\n options = {...options, style: 'decimal'};\n }\n\n let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : '');\n if (formatterCache.has(cacheKey)) {\n return formatterCache.get(cacheKey);\n }\n\n let numberFormatter = new Intl.NumberFormat(locale, options);\n formatterCache.set(cacheKey, numberFormatter);\n return numberFormatter;\n}\n\n/** @private - exported for tests */\nexport function numberFormatSignDisplayPolyfill(numberFormat: Intl.NumberFormat, signDisplay: string, num: number) {\n if (signDisplay === 'auto') {\n return numberFormat.format(num);\n } else if (signDisplay === 'never') {\n return numberFormat.format(Math.abs(num));\n } else {\n let needsPositiveSign = false;\n if (signDisplay === 'always') {\n needsPositiveSign = num > 0 || Object.is(num, 0);\n } else if (signDisplay === 'exceptZero') {\n if (Object.is(num, -0) || Object.is(num, 0)) {\n num = Math.abs(num);\n } else {\n needsPositiveSign = num > 0;\n }\n }\n\n if (needsPositiveSign) {\n let negative = numberFormat.format(-num);\n let noSign = numberFormat.format(num);\n // ignore RTL/LTR marker character\n let minus = negative.replace(noSign, '').replace(/\\u200e|\\u061C/, '');\n if ([...minus].length !== 1) {\n console.warn('@react-aria/i18n polyfill for NumberFormat signDisplay: Unsupported case');\n }\n let positive = negative.replace(noSign, '!!!').replace(minus, '+').replace('!!!', noSign);\n return positive;\n } else {\n return numberFormat.format(num);\n }\n }\n}\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {NumberFormatter} from './NumberFormatter';\n\ninterface Symbols {\n minusSign: string,\n plusSign: string,\n decimal: string,\n group: string,\n literals: RegExp,\n numeral: RegExp,\n index: (v: string) => string\n}\n\nconst CURRENCY_SIGN_REGEX = new RegExp('^.*\\\\(.*\\\\).*$');\nconst NUMBERING_SYSTEMS = ['latn', 'arab', 'hanidec'];\n\n/**\n * A NumberParser can be used to perform locale-aware parsing of numbers from Unicode strings,\n * as well as validation of partial user input. It automatically detects the numbering system\n * used in the input, and supports parsing decimals, percentages, currency values, and units\n * according to the locale.\n */\nexport class NumberParser {\n private locale: string;\n private options: Intl.NumberFormatOptions;\n\n constructor(locale: string, options: Intl.NumberFormatOptions = {}) {\n this.locale = locale;\n this.options = options;\n }\n\n /**\n * Parses the given string to a number. Returns NaN if a valid number could not be parsed.\n */\n parse(value: string): number {\n return getNumberParserImpl(this.locale, this.options, value).parse(value);\n }\n\n /**\n * Returns whether the given string could potentially be a valid number. This should be used to\n * validate user input as the user types. If a `minValue` or `maxValue` is provided, the validity\n * of the minus/plus sign characters can be checked.\n */\n isValidPartialNumber(value: string, minValue?: number, maxValue?: number): boolean {\n return getNumberParserImpl(this.locale, this.options, value).isValidPartialNumber(value, minValue, maxValue);\n }\n\n /**\n * Returns a numbering system for which the given string is valid in the current locale.\n * If no numbering system could be detected, the default numbering system for the current\n * locale is returned.\n */\n getNumberingSystem(value: string): string {\n return getNumberParserImpl(this.locale, this.options, value).options.numberingSystem;\n }\n}\n\nconst numberParserCache = new Map<string, NumberParserImpl>();\nfunction getNumberParserImpl(locale: string, options: Intl.NumberFormatOptions, value: string) {\n // First try the default numbering system for the provided locale\n let defaultParser = getCachedNumberParser(locale, options);\n\n // If that doesn't match, and the locale doesn't include a hard coded numbering system,\n // try each of the other supported numbering systems until we find one that matches.\n if (!locale.includes('-nu-') && !defaultParser.isValidPartialNumber(value)) {\n for (let numberingSystem of NUMBERING_SYSTEMS) {\n if (numberingSystem !== defaultParser.options.numberingSystem) {\n let parser = getCachedNumberParser(locale + (locale.includes('-u-') ? '-nu-' : '-u-nu-') + numberingSystem, options);\n if (parser.isValidPartialNumber(value)) {\n return parser;\n }\n }\n }\n }\n\n return defaultParser;\n}\n\nfunction getCachedNumberParser(locale: string, options: Intl.NumberFormatOptions) {\n let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : '');\n let parser = numberParserCache.get(cacheKey);\n if (!parser) {\n parser = new NumberParserImpl(locale, options);\n numberParserCache.set(cacheKey, parser);\n }\n\n return parser;\n}\n\n// The actual number parser implementation. Instances of this class are cached\n// based on the locale, options, and detected numbering system.\nclass NumberParserImpl {\n formatter: Intl.NumberFormat;\n options: Intl.ResolvedNumberFormatOptions;\n symbols: Symbols;\n locale: string;\n\n constructor(locale: string, options: Intl.NumberFormatOptions = {}) {\n this.locale = locale;\n this.formatter = new Intl.NumberFormat(locale, options);\n this.options = this.formatter.resolvedOptions();\n this.symbols = getSymbols(locale, this.formatter, this.options, options);\n if (this.options.style === 'percent' && ((this.options.minimumFractionDigits ?? 0) > 18 || (this.options.maximumFractionDigits ?? 0) > 18)) {\n console.warn('NumberParser cannot handle percentages with greater than 18 decimal places, please reduce the number in your options.');\n }\n }\n\n parse(value: string) {\n // to parse the number, we need to remove anything that isn't actually part of the number, for example we want '-10.40' not '-10.40 USD'\n let fullySanitizedValue = this.sanitize(value);\n\n // Remove group characters, and replace decimal points and numerals with ASCII values.\n fullySanitizedValue = replaceAll(fullySanitizedValue, this.symbols.group, '')\n .replace(this.symbols.decimal, '.')\n .replace(this.symbols.minusSign, '-')\n .replace(this.symbols.numeral, this.symbols.index);\n\n if (this.options.style === 'percent') {\n // javascript is bad at dividing by 100 and maintaining the same significant figures, so perform it on the string before parsing\n let isNegative = fullySanitizedValue.indexOf('-');\n fullySanitizedValue = fullySanitizedValue.replace('-', '');\n let index = fullySanitizedValue.indexOf('.');\n if (index === -1) {\n index = fullySanitizedValue.length;\n }\n fullySanitizedValue = fullySanitizedValue.replace('.', '');\n if (index - 2 === 0) {\n fullySanitizedValue = `0.${fullySanitizedValue}`;\n } else if (index - 2 === -1) {\n fullySanitizedValue = `0.0${fullySanitizedValue}`;\n } else if (index - 2 === -2) {\n fullySanitizedValue = '0.00';\n } else {\n fullySanitizedValue = `${fullySanitizedValue.slice(0, index - 2)}.${fullySanitizedValue.slice(index - 2)}`;\n }\n if (isNegative > -1) {\n fullySanitizedValue = `-${fullySanitizedValue}`;\n }\n }\n\n let newValue = fullySanitizedValue ? +fullySanitizedValue : NaN;\n if (isNaN(newValue)) {\n return NaN;\n }\n\n if (this.options.style === 'percent') {\n // extra step for rounding percents to what our formatter would output\n let options = {\n ...this.options,\n style: 'decimal',\n minimumFractionDigits: Math.min(this.options.minimumFractionDigits + 2, 20),\n maximumFractionDigits: Math.min(this.options.maximumFractionDigits + 2, 20)\n };\n return (new NumberParser(this.locale, options)).parse(new NumberFormatter(this.locale, options).format(newValue));\n }\n\n // accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again\n if (this.options.currencySign === 'accounting' && CURRENCY_SIGN_REGEX.test(value)) {\n newValue = -1 * newValue;\n }\n\n return newValue;\n }\n\n sanitize(value: string) {\n // Remove literals and whitespace, which are allowed anywhere in the string\n value = value.replace(this.symbols.literals, '');\n\n // Replace the ASCII minus sign with the minus sign used in the current locale\n // so that both are allowed in case the user's keyboard doesn't have the locale's minus sign.\n value = value.replace('-', this.symbols.minusSign);\n\n // In arab numeral system, their decimal character is 1643, but most keyboards don't type that\n // instead they use the , (44) character or apparently the (1548) character.\n if (this.options.numberingSystem === 'arab') {\n value = value.replace(',', this.symbols.decimal);\n value = value.replace(String.fromCharCode(1548), this.symbols.decimal);\n value = replaceAll(value, '.', this.symbols.group);\n }\n\n // fr-FR group character is char code 8239, but that's not a key on the french keyboard,\n // so allow 'period' as a group char and replace it with a space\n if (this.options.locale === 'fr-FR') {\n value = replaceAll(value, '.', String.fromCharCode(8239));\n }\n\n return value;\n }\n\n isValidPartialNumber(value: string, minValue: number = -Infinity, maxValue: number = Infinity): boolean {\n value = this.sanitize(value);\n\n // Remove minus or plus sign, which must be at the start of the string.\n if (value.startsWith(this.symbols.minusSign) && minValue < 0) {\n value = value.slice(this.symbols.minusSign.length);\n } else if (this.symbols.plusSign && value.startsWith(this.symbols.plusSign) && maxValue > 0) {\n value = value.slice(this.symbols.plusSign.length);\n }\n\n // Numbers cannot start with a group separator\n if (value.startsWith(this.symbols.group)) {\n return false;\n }\n\n // Numbers that can't have any decimal values fail if a decimal character is typed\n if (value.indexOf(this.symbols.decimal) > -1 && this.options.maximumFractionDigits === 0) {\n return false;\n }\n\n // Remove numerals, groups, and decimals\n value = replaceAll(value, this.symbols.group, '')\n .replace(this.symbols.numeral, '')\n .replace(this.symbols.decimal, '');\n\n // The number is valid if there are no remaining characters\n return value.length === 0;\n }\n}\n\nconst nonLiteralParts = new Set(['decimal', 'fraction', 'integer', 'minusSign', 'plusSign', 'group']);\n\n// This list is derived from https://www.unicode.org/cldr/charts/43/supplemental/language_plural_rules.html#comparison and includes\n// all unique numbers which we need to check in order to determine all the plural forms for a given locale.\n// See: https://github.com/adobe/react-spectrum/pull/5134/files#r1337037855 for used script\nconst pluralNumbers = [\n 0, 4, 2, 1, 11, 20, 3, 7, 100, 21, 0.1, 1.1\n];\n\nfunction getSymbols(locale: string, formatter: Intl.NumberFormat, intlOptions: Intl.ResolvedNumberFormatOptions, originalOptions: Intl.NumberFormatOptions): Symbols {\n // formatter needs access to all decimal places in order to generate the correct literal strings for the plural set\n let symbolFormatter = new Intl.NumberFormat(locale, {...intlOptions, minimumSignificantDigits: 1, maximumSignificantDigits: 21});\n // Note: some locale's don't add a group symbol until there is a ten thousands place\n let allParts = symbolFormatter.formatToParts(-10000.111);\n let posAllParts = symbolFormatter.formatToParts(10000.111);\n let pluralParts = pluralNumbers.map(n => symbolFormatter.formatToParts(n));\n\n let minusSign = allParts.find(p => p.type === 'minusSign')?.value ?? '-';\n let plusSign = posAllParts.find(p => p.type === 'plusSign')?.value;\n\n // Safari does not support the signDisplay option, but our number parser polyfills it.\n // If no plus sign was returned, but the original options contained signDisplay, default to the '+' character.\n // @ts-ignore\n if (!plusSign && (originalOptions?.signDisplay === 'exceptZero' || originalOptions?.signDisplay === 'always')) {\n plusSign = '+';\n }\n\n // If maximumSignificantDigits is 1 (the minimum) then we won't get decimal characters out of the above formatters\n // Percent also defaults to 0 fractionDigits, so we need to make a new one that isn't percent to get an accurate decimal\n let decimalParts = new Intl.NumberFormat(locale, {...intlOptions, minimumFractionDigits: 2, maximumFractionDigits: 2}).formatToParts(0.001);\n\n let decimal = decimalParts.find(p => p.type === 'decimal')?.value;\n let group = allParts.find(p => p.type === 'group')?.value;\n\n // this set is also for a regex, it's all literals that might be in the string we want to eventually parse that\n // don't contribute to the numerical value\n let allPartsLiterals = allParts.filter(p => !nonLiteralParts.has(p.type)).map(p => escapeRegex(p.value));\n let pluralPartsLiterals = pluralParts.flatMap(p => p.filter(p => !nonLiteralParts.has(p.type)).map(p => escapeRegex(p.value)));\n let sortedLiterals = [...new Set([...allPartsLiterals, ...pluralPartsLiterals])].sort((a, b) => b.length - a.length);\n\n let literals = sortedLiterals.length === 0 ?\n new RegExp('[\\\\p{White_Space}]', 'gu') :\n new RegExp(`${sortedLiterals.join('|')}|[\\\\p{White_Space}]`, 'gu');\n\n // These are for replacing non-latn characters with the latn equivalent\n let numerals = [...new Intl.NumberFormat(intlOptions.locale, {useGrouping: false}).format(9876543210)].reverse();\n let indexes = new Map(numerals.map((d, i) => [d, i]));\n let numeral = new RegExp(`[${numerals.join('')}]`, 'g');\n let index = d => String(indexes.get(d));\n\n return {minusSign, plusSign, decimal, group, literals, numeral, index};\n}\n\nfunction replaceAll(str: string, find: string, replace: string) {\n // @ts-ignore\n if (str.replaceAll) {\n // @ts-ignore\n return str.replaceAll(find, replace);\n }\n\n return str.split(find).join(replace);\n}\n\nfunction escapeRegex(string: string) {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n"],"names":[],"version":3,"file":"main.js.map"}
|
package/dist/module.js
CHANGED
|
@@ -171,7 +171,8 @@ function $488c6ddbf4ef74c2$export$711b50b3c525e0f2(numberFormat, signDisplay, nu
|
|
|
171
171
|
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
172
172
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
173
173
|
* governing permissions and limitations under the License.
|
|
174
|
-
*/
|
|
174
|
+
*/
|
|
175
|
+
const $6c7bd7858deea686$var$CURRENCY_SIGN_REGEX = new RegExp("^.*\\(.*\\).*$");
|
|
175
176
|
const $6c7bd7858deea686$var$NUMBERING_SYSTEMS = [
|
|
176
177
|
"latn",
|
|
177
178
|
"arab",
|
|
@@ -233,17 +234,33 @@ class $6c7bd7858deea686$var$NumberParserImpl {
|
|
|
233
234
|
let fullySanitizedValue = this.sanitize(value);
|
|
234
235
|
// Remove group characters, and replace decimal points and numerals with ASCII values.
|
|
235
236
|
fullySanitizedValue = $6c7bd7858deea686$var$replaceAll(fullySanitizedValue, this.symbols.group, "").replace(this.symbols.decimal, ".").replace(this.symbols.minusSign, "-").replace(this.symbols.numeral, this.symbols.index);
|
|
237
|
+
if (this.options.style === "percent") {
|
|
238
|
+
// javascript is bad at dividing by 100 and maintaining the same significant figures, so perform it on the string before parsing
|
|
239
|
+
let isNegative = fullySanitizedValue.indexOf("-");
|
|
240
|
+
fullySanitizedValue = fullySanitizedValue.replace("-", "");
|
|
241
|
+
let index = fullySanitizedValue.indexOf(".");
|
|
242
|
+
if (index === -1) index = fullySanitizedValue.length;
|
|
243
|
+
fullySanitizedValue = fullySanitizedValue.replace(".", "");
|
|
244
|
+
if (index - 2 === 0) fullySanitizedValue = `0.${fullySanitizedValue}`;
|
|
245
|
+
else if (index - 2 === -1) fullySanitizedValue = `0.0${fullySanitizedValue}`;
|
|
246
|
+
else if (index - 2 === -2) fullySanitizedValue = "0.00";
|
|
247
|
+
else fullySanitizedValue = `${fullySanitizedValue.slice(0, index - 2)}.${fullySanitizedValue.slice(index - 2)}`;
|
|
248
|
+
if (isNegative > -1) fullySanitizedValue = `-${fullySanitizedValue}`;
|
|
249
|
+
}
|
|
236
250
|
let newValue = fullySanitizedValue ? +fullySanitizedValue : NaN;
|
|
237
251
|
if (isNaN(newValue)) return NaN;
|
|
238
|
-
// accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again
|
|
239
|
-
if (this.options.currencySign === "accounting" && $6c7bd7858deea686$var$CURRENCY_SIGN_REGEX.test(value)) newValue = -1 * newValue;
|
|
240
|
-
// when reading the number, if it's a percent, then it should be interpreted as being divided by 100
|
|
241
252
|
if (this.options.style === "percent") {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
253
|
+
// extra step for rounding percents to what our formatter would output
|
|
254
|
+
let options = {
|
|
255
|
+
...this.options,
|
|
256
|
+
style: "decimal",
|
|
257
|
+
minimumFractionDigits: Math.min(this.options.minimumFractionDigits + 2, 20),
|
|
258
|
+
maximumFractionDigits: Math.min(this.options.maximumFractionDigits + 2, 20)
|
|
259
|
+
};
|
|
260
|
+
return new $6c7bd7858deea686$export$cd11ab140839f11d(this.locale, options).parse(new (0, $488c6ddbf4ef74c2$export$cc77c4ff7e8673c5)(this.locale, options).format(newValue));
|
|
246
261
|
}
|
|
262
|
+
// accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again
|
|
263
|
+
if (this.options.currencySign === "accounting" && $6c7bd7858deea686$var$CURRENCY_SIGN_REGEX.test(value)) newValue = -1 * newValue;
|
|
247
264
|
return newValue;
|
|
248
265
|
}
|
|
249
266
|
sanitize(value) {
|
|
@@ -271,15 +288,20 @@ class $6c7bd7858deea686$var$NumberParserImpl {
|
|
|
271
288
|
else if (this.symbols.plusSign && value.startsWith(this.symbols.plusSign) && maxValue > 0) value = value.slice(this.symbols.plusSign.length);
|
|
272
289
|
// Numbers cannot start with a group separator
|
|
273
290
|
if (value.startsWith(this.symbols.group)) return false;
|
|
291
|
+
// Numbers that can't have any decimal values fail if a decimal character is typed
|
|
292
|
+
if (value.indexOf(this.symbols.decimal) > -1 && this.options.maximumFractionDigits === 0) return false;
|
|
274
293
|
// Remove numerals, groups, and decimals
|
|
275
294
|
value = $6c7bd7858deea686$var$replaceAll(value, this.symbols.group, "").replace(this.symbols.numeral, "").replace(this.symbols.decimal, "");
|
|
276
295
|
// The number is valid if there are no remaining characters
|
|
277
296
|
return value.length === 0;
|
|
278
297
|
}
|
|
279
298
|
constructor(locale, options = {}){
|
|
299
|
+
this.locale = locale;
|
|
280
300
|
this.formatter = new Intl.NumberFormat(locale, options);
|
|
281
301
|
this.options = this.formatter.resolvedOptions();
|
|
282
|
-
this.symbols = $6c7bd7858deea686$var$getSymbols(this.formatter, this.options, options);
|
|
302
|
+
this.symbols = $6c7bd7858deea686$var$getSymbols(locale, this.formatter, this.options, options);
|
|
303
|
+
var _this_options_minimumFractionDigits, _this_options_maximumFractionDigits;
|
|
304
|
+
if (this.options.style === "percent" && (((_this_options_minimumFractionDigits = this.options.minimumFractionDigits) !== null && _this_options_minimumFractionDigits !== void 0 ? _this_options_minimumFractionDigits : 0) > 18 || ((_this_options_maximumFractionDigits = this.options.maximumFractionDigits) !== null && _this_options_maximumFractionDigits !== void 0 ? _this_options_maximumFractionDigits : 0) > 18)) console.warn("NumberParser cannot handle percentages with greater than 18 decimal places, please reduce the number in your options.");
|
|
283
305
|
}
|
|
284
306
|
}
|
|
285
307
|
const $6c7bd7858deea686$var$nonLiteralParts = new Set([
|
|
@@ -307,12 +329,18 @@ const $6c7bd7858deea686$var$pluralNumbers = [
|
|
|
307
329
|
0.1,
|
|
308
330
|
1.1
|
|
309
331
|
];
|
|
310
|
-
function $6c7bd7858deea686$var$getSymbols(formatter, intlOptions, originalOptions) {
|
|
311
|
-
var _allParts_find, _posAllParts_find,
|
|
332
|
+
function $6c7bd7858deea686$var$getSymbols(locale, formatter, intlOptions, originalOptions) {
|
|
333
|
+
var _allParts_find, _posAllParts_find, _decimalParts_find, _allParts_find1;
|
|
334
|
+
// formatter needs access to all decimal places in order to generate the correct literal strings for the plural set
|
|
335
|
+
let symbolFormatter = new Intl.NumberFormat(locale, {
|
|
336
|
+
...intlOptions,
|
|
337
|
+
minimumSignificantDigits: 1,
|
|
338
|
+
maximumSignificantDigits: 21
|
|
339
|
+
});
|
|
312
340
|
// Note: some locale's don't add a group symbol until there is a ten thousands place
|
|
313
|
-
let allParts =
|
|
314
|
-
let posAllParts =
|
|
315
|
-
let pluralParts = $6c7bd7858deea686$var$pluralNumbers.map((n)=>
|
|
341
|
+
let allParts = symbolFormatter.formatToParts(-10000.111);
|
|
342
|
+
let posAllParts = symbolFormatter.formatToParts(10000.111);
|
|
343
|
+
let pluralParts = $6c7bd7858deea686$var$pluralNumbers.map((n)=>symbolFormatter.formatToParts(n));
|
|
316
344
|
var _allParts_find_value;
|
|
317
345
|
let minusSign = (_allParts_find_value = (_allParts_find = allParts.find((p)=>p.type === "minusSign")) === null || _allParts_find === void 0 ? void 0 : _allParts_find.value) !== null && _allParts_find_value !== void 0 ? _allParts_find_value : "-";
|
|
318
346
|
let plusSign = (_posAllParts_find = posAllParts.find((p)=>p.type === "plusSign")) === null || _posAllParts_find === void 0 ? void 0 : _posAllParts_find.value;
|
|
@@ -320,8 +348,15 @@ function $6c7bd7858deea686$var$getSymbols(formatter, intlOptions, originalOption
|
|
|
320
348
|
// If no plus sign was returned, but the original options contained signDisplay, default to the '+' character.
|
|
321
349
|
// @ts-ignore
|
|
322
350
|
if (!plusSign && ((originalOptions === null || originalOptions === void 0 ? void 0 : originalOptions.signDisplay) === "exceptZero" || (originalOptions === null || originalOptions === void 0 ? void 0 : originalOptions.signDisplay) === "always")) plusSign = "+";
|
|
323
|
-
|
|
324
|
-
|
|
351
|
+
// If maximumSignificantDigits is 1 (the minimum) then we won't get decimal characters out of the above formatters
|
|
352
|
+
// Percent also defaults to 0 fractionDigits, so we need to make a new one that isn't percent to get an accurate decimal
|
|
353
|
+
let decimalParts = new Intl.NumberFormat(locale, {
|
|
354
|
+
...intlOptions,
|
|
355
|
+
minimumFractionDigits: 2,
|
|
356
|
+
maximumFractionDigits: 2
|
|
357
|
+
}).formatToParts(0.001);
|
|
358
|
+
let decimal = (_decimalParts_find = decimalParts.find((p)=>p.type === "decimal")) === null || _decimalParts_find === void 0 ? void 0 : _decimalParts_find.value;
|
|
359
|
+
let group = (_allParts_find1 = allParts.find((p)=>p.type === "group")) === null || _allParts_find1 === void 0 ? void 0 : _allParts_find1.value;
|
|
325
360
|
// this set is also for a regex, it's all literals that might be in the string we want to eventually parse that
|
|
326
361
|
// don't contribute to the numerical value
|
|
327
362
|
let allPartsLiterals = allParts.filter((p)=>!$6c7bd7858deea686$var$nonLiteralParts.has(p.type)).map((p)=>$6c7bd7858deea686$var$escapeRegex(p.value));
|
|
@@ -362,7 +397,7 @@ function $6c7bd7858deea686$var$replaceAll(str, find, replace) {
|
|
|
362
397
|
return str.split(find).join(replace);
|
|
363
398
|
}
|
|
364
399
|
function $6c7bd7858deea686$var$escapeRegex(string) {
|
|
365
|
-
return string.replace(/[
|
|
400
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
366
401
|
}
|
|
367
402
|
|
|
368
403
|
|
package/dist/module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/@internationalized/number/src/index.ts","packages/@internationalized/number/src/NumberFormatter.ts","packages/@internationalized/number/src/NumberParser.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type {NumberFormatOptions} from './NumberFormatter';\n\nexport {NumberFormatter} from './NumberFormatter';\nexport {NumberParser} from './NumberParser';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nlet formatterCache = new Map<string, Intl.NumberFormat>();\n\nlet supportsSignDisplay = false;\ntry {\n // @ts-ignore\n supportsSignDisplay = (new Intl.NumberFormat('de-DE', {signDisplay: 'exceptZero'})).resolvedOptions().signDisplay === 'exceptZero';\n // eslint-disable-next-line no-empty\n} catch (e) {}\n\nlet supportsUnit = false;\ntry {\n // @ts-ignore\n supportsUnit = (new Intl.NumberFormat('de-DE', {style: 'unit', unit: 'degree'})).resolvedOptions().style === 'unit';\n // eslint-disable-next-line no-empty\n} catch (e) {}\n\n// Polyfill for units since Safari doesn't support them yet. See https://bugs.webkit.org/show_bug.cgi?id=215438.\n// Currently only polyfilling the unit degree in narrow format for ColorSlider in our supported locales.\n// Values were determined by switching to each locale manually in Chrome.\nconst UNITS = {\n degree: {\n narrow: {\n default: '°',\n 'ja-JP': ' 度',\n 'zh-TW': '度',\n 'sl-SI': ' °'\n // Arabic?? But Safari already doesn't use Arabic digits so might be ok...\n // https://bugs.webkit.org/show_bug.cgi?id=218139\n }\n }\n};\n\nexport interface NumberFormatOptions extends Intl.NumberFormatOptions {\n /** Overrides default numbering system for the current locale. */\n numberingSystem?: string\n}\n\ninterface NumberRangeFormatPart extends Intl.NumberFormatPart {\n source: 'startRange' | 'endRange' | 'shared'\n}\n\n/**\n * A wrapper around Intl.NumberFormat providing additional options, polyfills, and caching for performance.\n */\nexport class NumberFormatter implements Intl.NumberFormat {\n private numberFormatter: Intl.NumberFormat;\n private options: NumberFormatOptions;\n\n constructor(locale: string, options: NumberFormatOptions = {}) {\n this.numberFormatter = getCachedNumberFormatter(locale, options);\n this.options = options;\n }\n\n /** Formats a number value as a string, according to the locale and options provided to the constructor. */\n format(value: number): string {\n let res = '';\n if (!supportsSignDisplay && this.options.signDisplay != null) {\n res = numberFormatSignDisplayPolyfill(this.numberFormatter, this.options.signDisplay, value);\n } else {\n res = this.numberFormatter.format(value);\n }\n\n if (this.options.style === 'unit' && !supportsUnit) {\n let {unit, unitDisplay = 'short', locale} = this.resolvedOptions();\n let values = UNITS[unit]?.[unitDisplay];\n res += values[locale] || values.default;\n }\n\n return res;\n }\n\n /** Formats a number to an array of parts such as separators, digits, punctuation, and more. */\n formatToParts(value: number): Intl.NumberFormatPart[] {\n // TODO: implement signDisplay for formatToParts\n // @ts-ignore\n return this.numberFormatter.formatToParts(value);\n }\n\n /** Formats a number range as a string. */\n formatRange(start: number, end: number): string {\n // @ts-ignore\n if (typeof this.numberFormatter.formatRange === 'function') {\n // @ts-ignore\n return this.numberFormatter.formatRange(start, end);\n }\n\n if (end < start) {\n throw new RangeError('End date must be >= start date');\n }\n\n // Very basic fallback for old browsers.\n return `${this.format(start)} – ${this.format(end)}`;\n }\n\n /** Formats a number range as an array of parts. */\n formatRangeToParts(start: number, end: number): NumberRangeFormatPart[] {\n // @ts-ignore\n if (typeof this.numberFormatter.formatRangeToParts === 'function') {\n // @ts-ignore\n return this.numberFormatter.formatRangeToParts(start, end);\n }\n\n if (end < start) {\n throw new RangeError('End date must be >= start date');\n }\n\n let startParts = this.numberFormatter.formatToParts(start);\n let endParts = this.numberFormatter.formatToParts(end);\n return [\n ...startParts.map(p => ({...p, source: 'startRange'} as NumberRangeFormatPart)),\n {type: 'literal', value: ' – ', source: 'shared'},\n ...endParts.map(p => ({...p, source: 'endRange'} as NumberRangeFormatPart))\n ];\n }\n\n /** Returns the resolved formatting options based on the values passed to the constructor. */\n resolvedOptions(): Intl.ResolvedNumberFormatOptions {\n let options = this.numberFormatter.resolvedOptions();\n if (!supportsSignDisplay && this.options.signDisplay != null) {\n options = {...options, signDisplay: this.options.signDisplay};\n }\n\n if (!supportsUnit && this.options.style === 'unit') {\n options = {...options, style: 'unit', unit: this.options.unit, unitDisplay: this.options.unitDisplay};\n }\n\n return options;\n }\n}\n\nfunction getCachedNumberFormatter(locale: string, options: NumberFormatOptions = {}): Intl.NumberFormat {\n let {numberingSystem} = options;\n if (numberingSystem && locale.indexOf('-u-nu-') === -1) {\n locale = `${locale}-u-nu-${numberingSystem}`;\n }\n\n if (options.style === 'unit' && !supportsUnit) {\n let {unit, unitDisplay = 'short'} = options;\n if (!unit) {\n throw new Error('unit option must be provided with style: \"unit\"');\n }\n if (!UNITS[unit]?.[unitDisplay]) {\n throw new Error(`Unsupported unit ${unit} with unitDisplay = ${unitDisplay}`);\n }\n options = {...options, style: 'decimal'};\n }\n\n let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : '');\n if (formatterCache.has(cacheKey)) {\n return formatterCache.get(cacheKey);\n }\n\n let numberFormatter = new Intl.NumberFormat(locale, options);\n formatterCache.set(cacheKey, numberFormatter);\n return numberFormatter;\n}\n\n/** @private - exported for tests */\nexport function numberFormatSignDisplayPolyfill(numberFormat: Intl.NumberFormat, signDisplay: string, num: number) {\n if (signDisplay === 'auto') {\n return numberFormat.format(num);\n } else if (signDisplay === 'never') {\n return numberFormat.format(Math.abs(num));\n } else {\n let needsPositiveSign = false;\n if (signDisplay === 'always') {\n needsPositiveSign = num > 0 || Object.is(num, 0);\n } else if (signDisplay === 'exceptZero') {\n if (Object.is(num, -0) || Object.is(num, 0)) {\n num = Math.abs(num);\n } else {\n needsPositiveSign = num > 0;\n }\n }\n\n if (needsPositiveSign) {\n let negative = numberFormat.format(-num);\n let noSign = numberFormat.format(num);\n // ignore RTL/LTR marker character\n let minus = negative.replace(noSign, '').replace(/\\u200e|\\u061C/, '');\n if ([...minus].length !== 1) {\n console.warn('@react-aria/i18n polyfill for NumberFormat signDisplay: Unsupported case');\n }\n let positive = negative.replace(noSign, '!!!').replace(minus, '+').replace('!!!', noSign);\n return positive;\n } else {\n return numberFormat.format(num);\n }\n }\n}\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\ninterface Symbols {\n minusSign: string,\n plusSign: string,\n decimal: string,\n group: string,\n literals: RegExp,\n numeral: RegExp,\n index: (v: string) => string\n}\n\nconst CURRENCY_SIGN_REGEX = new RegExp('^.*\\\\(.*\\\\).*$');\nconst NUMBERING_SYSTEMS = ['latn', 'arab', 'hanidec'];\n\n/**\n * A NumberParser can be used to perform locale-aware parsing of numbers from Unicode strings,\n * as well as validation of partial user input. It automatically detects the numbering system\n * used in the input, and supports parsing decimals, percentages, currency values, and units\n * according to the locale.\n */\nexport class NumberParser {\n private locale: string;\n private options: Intl.NumberFormatOptions;\n\n constructor(locale: string, options: Intl.NumberFormatOptions = {}) {\n this.locale = locale;\n this.options = options;\n }\n\n /**\n * Parses the given string to a number. Returns NaN if a valid number could not be parsed.\n */\n parse(value: string): number {\n return getNumberParserImpl(this.locale, this.options, value).parse(value);\n }\n\n /**\n * Returns whether the given string could potentially be a valid number. This should be used to\n * validate user input as the user types. If a `minValue` or `maxValue` is provided, the validity\n * of the minus/plus sign characters can be checked.\n */\n isValidPartialNumber(value: string, minValue?: number, maxValue?: number): boolean {\n return getNumberParserImpl(this.locale, this.options, value).isValidPartialNumber(value, minValue, maxValue);\n }\n\n /**\n * Returns a numbering system for which the given string is valid in the current locale.\n * If no numbering system could be detected, the default numbering system for the current\n * locale is returned.\n */\n getNumberingSystem(value: string): string {\n return getNumberParserImpl(this.locale, this.options, value).options.numberingSystem;\n }\n}\n\nconst numberParserCache = new Map<string, NumberParserImpl>();\nfunction getNumberParserImpl(locale: string, options: Intl.NumberFormatOptions, value: string) {\n // First try the default numbering system for the provided locale\n let defaultParser = getCachedNumberParser(locale, options);\n\n // If that doesn't match, and the locale doesn't include a hard coded numbering system,\n // try each of the other supported numbering systems until we find one that matches.\n if (!locale.includes('-nu-') && !defaultParser.isValidPartialNumber(value)) {\n for (let numberingSystem of NUMBERING_SYSTEMS) {\n if (numberingSystem !== defaultParser.options.numberingSystem) {\n let parser = getCachedNumberParser(locale + (locale.includes('-u-') ? '-nu-' : '-u-nu-') + numberingSystem, options);\n if (parser.isValidPartialNumber(value)) {\n return parser;\n }\n }\n }\n }\n\n return defaultParser;\n}\n\nfunction getCachedNumberParser(locale: string, options: Intl.NumberFormatOptions) {\n let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : '');\n let parser = numberParserCache.get(cacheKey);\n if (!parser) {\n parser = new NumberParserImpl(locale, options);\n numberParserCache.set(cacheKey, parser);\n }\n\n return parser;\n}\n\n// The actual number parser implementation. Instances of this class are cached\n// based on the locale, options, and detected numbering system.\nclass NumberParserImpl {\n formatter: Intl.NumberFormat;\n options: Intl.ResolvedNumberFormatOptions;\n symbols: Symbols;\n\n constructor(locale: string, options: Intl.NumberFormatOptions = {}) {\n this.formatter = new Intl.NumberFormat(locale, options);\n this.options = this.formatter.resolvedOptions();\n this.symbols = getSymbols(this.formatter, this.options, options);\n }\n\n parse(value: string) {\n // to parse the number, we need to remove anything that isn't actually part of the number, for example we want '-10.40' not '-10.40 USD'\n let fullySanitizedValue = this.sanitize(value);\n\n // Remove group characters, and replace decimal points and numerals with ASCII values.\n fullySanitizedValue = replaceAll(fullySanitizedValue, this.symbols.group, '')\n .replace(this.symbols.decimal, '.')\n .replace(this.symbols.minusSign, '-')\n .replace(this.symbols.numeral, this.symbols.index);\n\n let newValue = fullySanitizedValue ? +fullySanitizedValue : NaN;\n if (isNaN(newValue)) {\n return NaN;\n }\n\n // accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again\n if (this.options.currencySign === 'accounting' && CURRENCY_SIGN_REGEX.test(value)) {\n newValue = -1 * newValue;\n }\n\n // when reading the number, if it's a percent, then it should be interpreted as being divided by 100\n if (this.options.style === 'percent') {\n newValue /= 100;\n // after dividing to get the percent value, javascript may get .0210999999 instead of .0211, so fix the number of fraction digits\n newValue = +newValue.toFixed((this.options.maximumFractionDigits ?? 0) + 2);\n }\n\n return newValue;\n }\n\n sanitize(value: string) {\n // Remove literals and whitespace, which are allowed anywhere in the string\n value = value.replace(this.symbols.literals, '');\n\n // Replace the ASCII minus sign with the minus sign used in the current locale\n // so that both are allowed in case the user's keyboard doesn't have the locale's minus sign.\n value = value.replace('-', this.symbols.minusSign);\n\n // In arab numeral system, their decimal character is 1643, but most keyboards don't type that\n // instead they use the , (44) character or apparently the (1548) character.\n if (this.options.numberingSystem === 'arab') {\n value = value.replace(',', this.symbols.decimal);\n value = value.replace(String.fromCharCode(1548), this.symbols.decimal);\n value = replaceAll(value, '.', this.symbols.group);\n }\n\n // fr-FR group character is char code 8239, but that's not a key on the french keyboard,\n // so allow 'period' as a group char and replace it with a space\n if (this.options.locale === 'fr-FR') {\n value = replaceAll(value, '.', String.fromCharCode(8239));\n }\n\n return value;\n }\n\n isValidPartialNumber(value: string, minValue: number = -Infinity, maxValue: number = Infinity): boolean {\n value = this.sanitize(value);\n\n // Remove minus or plus sign, which must be at the start of the string.\n if (value.startsWith(this.symbols.minusSign) && minValue < 0) {\n value = value.slice(this.symbols.minusSign.length);\n } else if (this.symbols.plusSign && value.startsWith(this.symbols.plusSign) && maxValue > 0) {\n value = value.slice(this.symbols.plusSign.length);\n }\n\n // Numbers cannot start with a group separator\n if (value.startsWith(this.symbols.group)) {\n return false;\n }\n\n // Remove numerals, groups, and decimals\n value = replaceAll(value, this.symbols.group, '')\n .replace(this.symbols.numeral, '')\n .replace(this.symbols.decimal, '');\n\n // The number is valid if there are no remaining characters\n return value.length === 0;\n }\n}\n\nconst nonLiteralParts = new Set(['decimal', 'fraction', 'integer', 'minusSign', 'plusSign', 'group']);\n\n// This list is derived from https://www.unicode.org/cldr/charts/43/supplemental/language_plural_rules.html#comparison and includes\n// all unique numbers which we need to check in order to determine all the plural forms for a given locale.\n// See: https://github.com/adobe/react-spectrum/pull/5134/files#r1337037855 for used script\nconst pluralNumbers = [\n 0, 4, 2, 1, 11, 20, 3, 7, 100, 21, 0.1, 1.1\n];\n\nfunction getSymbols(formatter: Intl.NumberFormat, intlOptions: Intl.ResolvedNumberFormatOptions, originalOptions: Intl.NumberFormatOptions): Symbols {\n // Note: some locale's don't add a group symbol until there is a ten thousands place\n let allParts = formatter.formatToParts(-10000.111);\n let posAllParts = formatter.formatToParts(10000.111);\n let pluralParts = pluralNumbers.map(n => formatter.formatToParts(n));\n\n let minusSign = allParts.find(p => p.type === 'minusSign')?.value ?? '-';\n let plusSign = posAllParts.find(p => p.type === 'plusSign')?.value;\n\n // Safari does not support the signDisplay option, but our number parser polyfills it.\n // If no plus sign was returned, but the original options contained signDisplay, default to the '+' character.\n // @ts-ignore\n if (!plusSign && (originalOptions?.signDisplay === 'exceptZero' || originalOptions?.signDisplay === 'always')) {\n plusSign = '+';\n }\n\n let decimal = allParts.find(p => p.type === 'decimal')?.value;\n let group = allParts.find(p => p.type === 'group')?.value;\n\n // this set is also for a regex, it's all literals that might be in the string we want to eventually parse that\n // don't contribute to the numerical value\n let allPartsLiterals = allParts.filter(p => !nonLiteralParts.has(p.type)).map(p => escapeRegex(p.value));\n let pluralPartsLiterals = pluralParts.flatMap(p => p.filter(p => !nonLiteralParts.has(p.type)).map(p => escapeRegex(p.value)));\n let sortedLiterals = [...new Set([...allPartsLiterals, ...pluralPartsLiterals])].sort((a, b) => b.length - a.length);\n\n let literals = sortedLiterals.length === 0 ? \n new RegExp('[\\\\p{White_Space}]', 'gu') :\n new RegExp(`${sortedLiterals.join('|')}|[\\\\p{White_Space}]`, 'gu');\n\n // These are for replacing non-latn characters with the latn equivalent\n let numerals = [...new Intl.NumberFormat(intlOptions.locale, {useGrouping: false}).format(9876543210)].reverse();\n let indexes = new Map(numerals.map((d, i) => [d, i]));\n let numeral = new RegExp(`[${numerals.join('')}]`, 'g');\n let index = d => String(indexes.get(d));\n\n return {minusSign, plusSign, decimal, group, literals, numeral, index};\n}\n\nfunction replaceAll(str: string, find: string, replace: string) {\n // @ts-ignore\n if (str.replaceAll) {\n // @ts-ignore\n return str.replaceAll(find, replace);\n }\n\n return str.split(find).join(replace);\n}\n\nfunction escapeRegex(string: string) {\n return string.replace(/[-/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n}\n"],"names":[],"version":3,"file":"module.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/@internationalized/number/src/index.ts","packages/@internationalized/number/src/NumberFormatter.ts","packages/@internationalized/number/src/NumberParser.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type {NumberFormatOptions} from './NumberFormatter';\n\nexport {NumberFormatter} from './NumberFormatter';\nexport {NumberParser} from './NumberParser';\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nlet formatterCache = new Map<string, Intl.NumberFormat>();\n\nlet supportsSignDisplay = false;\ntry {\n // @ts-ignore\n supportsSignDisplay = (new Intl.NumberFormat('de-DE', {signDisplay: 'exceptZero'})).resolvedOptions().signDisplay === 'exceptZero';\n // eslint-disable-next-line no-empty\n} catch (e) {}\n\nlet supportsUnit = false;\ntry {\n // @ts-ignore\n supportsUnit = (new Intl.NumberFormat('de-DE', {style: 'unit', unit: 'degree'})).resolvedOptions().style === 'unit';\n // eslint-disable-next-line no-empty\n} catch (e) {}\n\n// Polyfill for units since Safari doesn't support them yet. See https://bugs.webkit.org/show_bug.cgi?id=215438.\n// Currently only polyfilling the unit degree in narrow format for ColorSlider in our supported locales.\n// Values were determined by switching to each locale manually in Chrome.\nconst UNITS = {\n degree: {\n narrow: {\n default: '°',\n 'ja-JP': ' 度',\n 'zh-TW': '度',\n 'sl-SI': ' °'\n // Arabic?? But Safari already doesn't use Arabic digits so might be ok...\n // https://bugs.webkit.org/show_bug.cgi?id=218139\n }\n }\n};\n\nexport interface NumberFormatOptions extends Intl.NumberFormatOptions {\n /** Overrides default numbering system for the current locale. */\n numberingSystem?: string\n}\n\ninterface NumberRangeFormatPart extends Intl.NumberFormatPart {\n source: 'startRange' | 'endRange' | 'shared'\n}\n\n/**\n * A wrapper around Intl.NumberFormat providing additional options, polyfills, and caching for performance.\n */\nexport class NumberFormatter implements Intl.NumberFormat {\n private numberFormatter: Intl.NumberFormat;\n private options: NumberFormatOptions;\n\n constructor(locale: string, options: NumberFormatOptions = {}) {\n this.numberFormatter = getCachedNumberFormatter(locale, options);\n this.options = options;\n }\n\n /** Formats a number value as a string, according to the locale and options provided to the constructor. */\n format(value: number): string {\n let res = '';\n if (!supportsSignDisplay && this.options.signDisplay != null) {\n res = numberFormatSignDisplayPolyfill(this.numberFormatter, this.options.signDisplay, value);\n } else {\n res = this.numberFormatter.format(value);\n }\n\n if (this.options.style === 'unit' && !supportsUnit) {\n let {unit, unitDisplay = 'short', locale} = this.resolvedOptions();\n let values = UNITS[unit]?.[unitDisplay];\n res += values[locale] || values.default;\n }\n\n return res;\n }\n\n /** Formats a number to an array of parts such as separators, digits, punctuation, and more. */\n formatToParts(value: number): Intl.NumberFormatPart[] {\n // TODO: implement signDisplay for formatToParts\n // @ts-ignore\n return this.numberFormatter.formatToParts(value);\n }\n\n /** Formats a number range as a string. */\n formatRange(start: number, end: number): string {\n // @ts-ignore\n if (typeof this.numberFormatter.formatRange === 'function') {\n // @ts-ignore\n return this.numberFormatter.formatRange(start, end);\n }\n\n if (end < start) {\n throw new RangeError('End date must be >= start date');\n }\n\n // Very basic fallback for old browsers.\n return `${this.format(start)} – ${this.format(end)}`;\n }\n\n /** Formats a number range as an array of parts. */\n formatRangeToParts(start: number, end: number): NumberRangeFormatPart[] {\n // @ts-ignore\n if (typeof this.numberFormatter.formatRangeToParts === 'function') {\n // @ts-ignore\n return this.numberFormatter.formatRangeToParts(start, end);\n }\n\n if (end < start) {\n throw new RangeError('End date must be >= start date');\n }\n\n let startParts = this.numberFormatter.formatToParts(start);\n let endParts = this.numberFormatter.formatToParts(end);\n return [\n ...startParts.map(p => ({...p, source: 'startRange'} as NumberRangeFormatPart)),\n {type: 'literal', value: ' – ', source: 'shared'},\n ...endParts.map(p => ({...p, source: 'endRange'} as NumberRangeFormatPart))\n ];\n }\n\n /** Returns the resolved formatting options based on the values passed to the constructor. */\n resolvedOptions(): Intl.ResolvedNumberFormatOptions {\n let options = this.numberFormatter.resolvedOptions();\n if (!supportsSignDisplay && this.options.signDisplay != null) {\n options = {...options, signDisplay: this.options.signDisplay};\n }\n\n if (!supportsUnit && this.options.style === 'unit') {\n options = {...options, style: 'unit', unit: this.options.unit, unitDisplay: this.options.unitDisplay};\n }\n\n return options;\n }\n}\n\nfunction getCachedNumberFormatter(locale: string, options: NumberFormatOptions = {}): Intl.NumberFormat {\n let {numberingSystem} = options;\n if (numberingSystem && locale.indexOf('-u-nu-') === -1) {\n locale = `${locale}-u-nu-${numberingSystem}`;\n }\n\n if (options.style === 'unit' && !supportsUnit) {\n let {unit, unitDisplay = 'short'} = options;\n if (!unit) {\n throw new Error('unit option must be provided with style: \"unit\"');\n }\n if (!UNITS[unit]?.[unitDisplay]) {\n throw new Error(`Unsupported unit ${unit} with unitDisplay = ${unitDisplay}`);\n }\n options = {...options, style: 'decimal'};\n }\n\n let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : '');\n if (formatterCache.has(cacheKey)) {\n return formatterCache.get(cacheKey);\n }\n\n let numberFormatter = new Intl.NumberFormat(locale, options);\n formatterCache.set(cacheKey, numberFormatter);\n return numberFormatter;\n}\n\n/** @private - exported for tests */\nexport function numberFormatSignDisplayPolyfill(numberFormat: Intl.NumberFormat, signDisplay: string, num: number) {\n if (signDisplay === 'auto') {\n return numberFormat.format(num);\n } else if (signDisplay === 'never') {\n return numberFormat.format(Math.abs(num));\n } else {\n let needsPositiveSign = false;\n if (signDisplay === 'always') {\n needsPositiveSign = num > 0 || Object.is(num, 0);\n } else if (signDisplay === 'exceptZero') {\n if (Object.is(num, -0) || Object.is(num, 0)) {\n num = Math.abs(num);\n } else {\n needsPositiveSign = num > 0;\n }\n }\n\n if (needsPositiveSign) {\n let negative = numberFormat.format(-num);\n let noSign = numberFormat.format(num);\n // ignore RTL/LTR marker character\n let minus = negative.replace(noSign, '').replace(/\\u200e|\\u061C/, '');\n if ([...minus].length !== 1) {\n console.warn('@react-aria/i18n polyfill for NumberFormat signDisplay: Unsupported case');\n }\n let positive = negative.replace(noSign, '!!!').replace(minus, '+').replace('!!!', noSign);\n return positive;\n } else {\n return numberFormat.format(num);\n }\n }\n}\n","/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {NumberFormatter} from './NumberFormatter';\n\ninterface Symbols {\n minusSign: string,\n plusSign: string,\n decimal: string,\n group: string,\n literals: RegExp,\n numeral: RegExp,\n index: (v: string) => string\n}\n\nconst CURRENCY_SIGN_REGEX = new RegExp('^.*\\\\(.*\\\\).*$');\nconst NUMBERING_SYSTEMS = ['latn', 'arab', 'hanidec'];\n\n/**\n * A NumberParser can be used to perform locale-aware parsing of numbers from Unicode strings,\n * as well as validation of partial user input. It automatically detects the numbering system\n * used in the input, and supports parsing decimals, percentages, currency values, and units\n * according to the locale.\n */\nexport class NumberParser {\n private locale: string;\n private options: Intl.NumberFormatOptions;\n\n constructor(locale: string, options: Intl.NumberFormatOptions = {}) {\n this.locale = locale;\n this.options = options;\n }\n\n /**\n * Parses the given string to a number. Returns NaN if a valid number could not be parsed.\n */\n parse(value: string): number {\n return getNumberParserImpl(this.locale, this.options, value).parse(value);\n }\n\n /**\n * Returns whether the given string could potentially be a valid number. This should be used to\n * validate user input as the user types. If a `minValue` or `maxValue` is provided, the validity\n * of the minus/plus sign characters can be checked.\n */\n isValidPartialNumber(value: string, minValue?: number, maxValue?: number): boolean {\n return getNumberParserImpl(this.locale, this.options, value).isValidPartialNumber(value, minValue, maxValue);\n }\n\n /**\n * Returns a numbering system for which the given string is valid in the current locale.\n * If no numbering system could be detected, the default numbering system for the current\n * locale is returned.\n */\n getNumberingSystem(value: string): string {\n return getNumberParserImpl(this.locale, this.options, value).options.numberingSystem;\n }\n}\n\nconst numberParserCache = new Map<string, NumberParserImpl>();\nfunction getNumberParserImpl(locale: string, options: Intl.NumberFormatOptions, value: string) {\n // First try the default numbering system for the provided locale\n let defaultParser = getCachedNumberParser(locale, options);\n\n // If that doesn't match, and the locale doesn't include a hard coded numbering system,\n // try each of the other supported numbering systems until we find one that matches.\n if (!locale.includes('-nu-') && !defaultParser.isValidPartialNumber(value)) {\n for (let numberingSystem of NUMBERING_SYSTEMS) {\n if (numberingSystem !== defaultParser.options.numberingSystem) {\n let parser = getCachedNumberParser(locale + (locale.includes('-u-') ? '-nu-' : '-u-nu-') + numberingSystem, options);\n if (parser.isValidPartialNumber(value)) {\n return parser;\n }\n }\n }\n }\n\n return defaultParser;\n}\n\nfunction getCachedNumberParser(locale: string, options: Intl.NumberFormatOptions) {\n let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : '');\n let parser = numberParserCache.get(cacheKey);\n if (!parser) {\n parser = new NumberParserImpl(locale, options);\n numberParserCache.set(cacheKey, parser);\n }\n\n return parser;\n}\n\n// The actual number parser implementation. Instances of this class are cached\n// based on the locale, options, and detected numbering system.\nclass NumberParserImpl {\n formatter: Intl.NumberFormat;\n options: Intl.ResolvedNumberFormatOptions;\n symbols: Symbols;\n locale: string;\n\n constructor(locale: string, options: Intl.NumberFormatOptions = {}) {\n this.locale = locale;\n this.formatter = new Intl.NumberFormat(locale, options);\n this.options = this.formatter.resolvedOptions();\n this.symbols = getSymbols(locale, this.formatter, this.options, options);\n if (this.options.style === 'percent' && ((this.options.minimumFractionDigits ?? 0) > 18 || (this.options.maximumFractionDigits ?? 0) > 18)) {\n console.warn('NumberParser cannot handle percentages with greater than 18 decimal places, please reduce the number in your options.');\n }\n }\n\n parse(value: string) {\n // to parse the number, we need to remove anything that isn't actually part of the number, for example we want '-10.40' not '-10.40 USD'\n let fullySanitizedValue = this.sanitize(value);\n\n // Remove group characters, and replace decimal points and numerals with ASCII values.\n fullySanitizedValue = replaceAll(fullySanitizedValue, this.symbols.group, '')\n .replace(this.symbols.decimal, '.')\n .replace(this.symbols.minusSign, '-')\n .replace(this.symbols.numeral, this.symbols.index);\n\n if (this.options.style === 'percent') {\n // javascript is bad at dividing by 100 and maintaining the same significant figures, so perform it on the string before parsing\n let isNegative = fullySanitizedValue.indexOf('-');\n fullySanitizedValue = fullySanitizedValue.replace('-', '');\n let index = fullySanitizedValue.indexOf('.');\n if (index === -1) {\n index = fullySanitizedValue.length;\n }\n fullySanitizedValue = fullySanitizedValue.replace('.', '');\n if (index - 2 === 0) {\n fullySanitizedValue = `0.${fullySanitizedValue}`;\n } else if (index - 2 === -1) {\n fullySanitizedValue = `0.0${fullySanitizedValue}`;\n } else if (index - 2 === -2) {\n fullySanitizedValue = '0.00';\n } else {\n fullySanitizedValue = `${fullySanitizedValue.slice(0, index - 2)}.${fullySanitizedValue.slice(index - 2)}`;\n }\n if (isNegative > -1) {\n fullySanitizedValue = `-${fullySanitizedValue}`;\n }\n }\n\n let newValue = fullySanitizedValue ? +fullySanitizedValue : NaN;\n if (isNaN(newValue)) {\n return NaN;\n }\n\n if (this.options.style === 'percent') {\n // extra step for rounding percents to what our formatter would output\n let options = {\n ...this.options,\n style: 'decimal',\n minimumFractionDigits: Math.min(this.options.minimumFractionDigits + 2, 20),\n maximumFractionDigits: Math.min(this.options.maximumFractionDigits + 2, 20)\n };\n return (new NumberParser(this.locale, options)).parse(new NumberFormatter(this.locale, options).format(newValue));\n }\n\n // accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again\n if (this.options.currencySign === 'accounting' && CURRENCY_SIGN_REGEX.test(value)) {\n newValue = -1 * newValue;\n }\n\n return newValue;\n }\n\n sanitize(value: string) {\n // Remove literals and whitespace, which are allowed anywhere in the string\n value = value.replace(this.symbols.literals, '');\n\n // Replace the ASCII minus sign with the minus sign used in the current locale\n // so that both are allowed in case the user's keyboard doesn't have the locale's minus sign.\n value = value.replace('-', this.symbols.minusSign);\n\n // In arab numeral system, their decimal character is 1643, but most keyboards don't type that\n // instead they use the , (44) character or apparently the (1548) character.\n if (this.options.numberingSystem === 'arab') {\n value = value.replace(',', this.symbols.decimal);\n value = value.replace(String.fromCharCode(1548), this.symbols.decimal);\n value = replaceAll(value, '.', this.symbols.group);\n }\n\n // fr-FR group character is char code 8239, but that's not a key on the french keyboard,\n // so allow 'period' as a group char and replace it with a space\n if (this.options.locale === 'fr-FR') {\n value = replaceAll(value, '.', String.fromCharCode(8239));\n }\n\n return value;\n }\n\n isValidPartialNumber(value: string, minValue: number = -Infinity, maxValue: number = Infinity): boolean {\n value = this.sanitize(value);\n\n // Remove minus or plus sign, which must be at the start of the string.\n if (value.startsWith(this.symbols.minusSign) && minValue < 0) {\n value = value.slice(this.symbols.minusSign.length);\n } else if (this.symbols.plusSign && value.startsWith(this.symbols.plusSign) && maxValue > 0) {\n value = value.slice(this.symbols.plusSign.length);\n }\n\n // Numbers cannot start with a group separator\n if (value.startsWith(this.symbols.group)) {\n return false;\n }\n\n // Numbers that can't have any decimal values fail if a decimal character is typed\n if (value.indexOf(this.symbols.decimal) > -1 && this.options.maximumFractionDigits === 0) {\n return false;\n }\n\n // Remove numerals, groups, and decimals\n value = replaceAll(value, this.symbols.group, '')\n .replace(this.symbols.numeral, '')\n .replace(this.symbols.decimal, '');\n\n // The number is valid if there are no remaining characters\n return value.length === 0;\n }\n}\n\nconst nonLiteralParts = new Set(['decimal', 'fraction', 'integer', 'minusSign', 'plusSign', 'group']);\n\n// This list is derived from https://www.unicode.org/cldr/charts/43/supplemental/language_plural_rules.html#comparison and includes\n// all unique numbers which we need to check in order to determine all the plural forms for a given locale.\n// See: https://github.com/adobe/react-spectrum/pull/5134/files#r1337037855 for used script\nconst pluralNumbers = [\n 0, 4, 2, 1, 11, 20, 3, 7, 100, 21, 0.1, 1.1\n];\n\nfunction getSymbols(locale: string, formatter: Intl.NumberFormat, intlOptions: Intl.ResolvedNumberFormatOptions, originalOptions: Intl.NumberFormatOptions): Symbols {\n // formatter needs access to all decimal places in order to generate the correct literal strings for the plural set\n let symbolFormatter = new Intl.NumberFormat(locale, {...intlOptions, minimumSignificantDigits: 1, maximumSignificantDigits: 21});\n // Note: some locale's don't add a group symbol until there is a ten thousands place\n let allParts = symbolFormatter.formatToParts(-10000.111);\n let posAllParts = symbolFormatter.formatToParts(10000.111);\n let pluralParts = pluralNumbers.map(n => symbolFormatter.formatToParts(n));\n\n let minusSign = allParts.find(p => p.type === 'minusSign')?.value ?? '-';\n let plusSign = posAllParts.find(p => p.type === 'plusSign')?.value;\n\n // Safari does not support the signDisplay option, but our number parser polyfills it.\n // If no plus sign was returned, but the original options contained signDisplay, default to the '+' character.\n // @ts-ignore\n if (!plusSign && (originalOptions?.signDisplay === 'exceptZero' || originalOptions?.signDisplay === 'always')) {\n plusSign = '+';\n }\n\n // If maximumSignificantDigits is 1 (the minimum) then we won't get decimal characters out of the above formatters\n // Percent also defaults to 0 fractionDigits, so we need to make a new one that isn't percent to get an accurate decimal\n let decimalParts = new Intl.NumberFormat(locale, {...intlOptions, minimumFractionDigits: 2, maximumFractionDigits: 2}).formatToParts(0.001);\n\n let decimal = decimalParts.find(p => p.type === 'decimal')?.value;\n let group = allParts.find(p => p.type === 'group')?.value;\n\n // this set is also for a regex, it's all literals that might be in the string we want to eventually parse that\n // don't contribute to the numerical value\n let allPartsLiterals = allParts.filter(p => !nonLiteralParts.has(p.type)).map(p => escapeRegex(p.value));\n let pluralPartsLiterals = pluralParts.flatMap(p => p.filter(p => !nonLiteralParts.has(p.type)).map(p => escapeRegex(p.value)));\n let sortedLiterals = [...new Set([...allPartsLiterals, ...pluralPartsLiterals])].sort((a, b) => b.length - a.length);\n\n let literals = sortedLiterals.length === 0 ?\n new RegExp('[\\\\p{White_Space}]', 'gu') :\n new RegExp(`${sortedLiterals.join('|')}|[\\\\p{White_Space}]`, 'gu');\n\n // These are for replacing non-latn characters with the latn equivalent\n let numerals = [...new Intl.NumberFormat(intlOptions.locale, {useGrouping: false}).format(9876543210)].reverse();\n let indexes = new Map(numerals.map((d, i) => [d, i]));\n let numeral = new RegExp(`[${numerals.join('')}]`, 'g');\n let index = d => String(indexes.get(d));\n\n return {minusSign, plusSign, decimal, group, literals, numeral, index};\n}\n\nfunction replaceAll(str: string, find: string, replace: string) {\n // @ts-ignore\n if (str.replaceAll) {\n // @ts-ignore\n return str.replaceAll(find, replace);\n }\n\n return str.split(find).join(replace);\n}\n\nfunction escapeRegex(string: string) {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n"],"names":[],"version":3,"file":"module.js.map"}
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AA4CA,oCAAqC,SAAQ,IAAI,oBAAoB;IACnE,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,+BAAgC,SAAQ,IAAI,CAAC,gBAAgB;IAC3D,MAAM,EAAE,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAA;CAC7C;AAED;;GAEG;AACH,4BAA6B,YAAW,IAAI,CAAC,YAAY;gBAI3C,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB;IAK7D,2GAA2G;IAC3G,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAiB7B,+FAA+F;IAC/F,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,gBAAgB,EAAE;IAMrD,0CAA0C;IAC1C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAe/C,mDAAmD;IACnD,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,qBAAqB,EAAE;IAoBvE,6FAA6F;IAC7F,eAAe,IAAI,KAAK,2BAA2B;CAYpD;
|
|
1
|
+
{"mappings":"AA4CA,oCAAqC,SAAQ,IAAI,oBAAoB;IACnE,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,+BAAgC,SAAQ,IAAI,CAAC,gBAAgB;IAC3D,MAAM,EAAE,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAA;CAC7C;AAED;;GAEG;AACH,4BAA6B,YAAW,IAAI,CAAC,YAAY;gBAI3C,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB;IAK7D,2GAA2G;IAC3G,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAiB7B,+FAA+F;IAC/F,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,gBAAgB,EAAE;IAMrD,0CAA0C;IAC1C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAe/C,mDAAmD;IACnD,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,qBAAqB,EAAE;IAoBvE,6FAA6F;IAC7F,eAAe,IAAI,KAAK,2BAA2B;CAYpD;ACjHD;;;;;GAKG;AACH;gBAIc,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,KAAK,mBAAwB;IAKlE;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI5B;;;;OAIG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAIlF;;;;OAIG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAG1C","sources":["packages/@internationalized/number/src/packages/@internationalized/number/src/NumberFormatter.ts","packages/@internationalized/number/src/packages/@internationalized/number/src/NumberParser.ts","packages/@internationalized/number/src/packages/@internationalized/number/src/index.ts","packages/@internationalized/number/src/index.ts"],"sourcesContent":[null,null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type {NumberFormatOptions} from './NumberFormatter';\n\nexport {NumberFormatter} from './NumberFormatter';\nexport {NumberParser} from './NumberParser';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internationalized/number",
|
|
3
|
-
"version": "3.3.1-nightly.
|
|
3
|
+
"version": "3.3.1-nightly.4205+778eaa49d",
|
|
4
4
|
"description": "Internationalized number formatting and parsing utilities",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -27,5 +27,5 @@
|
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|
|
29
29
|
},
|
|
30
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "778eaa49d3041287eb52cc3d51e4c45e7515f64f"
|
|
31
31
|
}
|
package/src/NumberParser.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import {NumberFormatter} from './NumberFormatter';
|
|
14
|
+
|
|
13
15
|
interface Symbols {
|
|
14
16
|
minusSign: string,
|
|
15
17
|
plusSign: string,
|
|
@@ -102,11 +104,16 @@ class NumberParserImpl {
|
|
|
102
104
|
formatter: Intl.NumberFormat;
|
|
103
105
|
options: Intl.ResolvedNumberFormatOptions;
|
|
104
106
|
symbols: Symbols;
|
|
107
|
+
locale: string;
|
|
105
108
|
|
|
106
109
|
constructor(locale: string, options: Intl.NumberFormatOptions = {}) {
|
|
110
|
+
this.locale = locale;
|
|
107
111
|
this.formatter = new Intl.NumberFormat(locale, options);
|
|
108
112
|
this.options = this.formatter.resolvedOptions();
|
|
109
|
-
this.symbols = getSymbols(this.formatter, this.options, options);
|
|
113
|
+
this.symbols = getSymbols(locale, this.formatter, this.options, options);
|
|
114
|
+
if (this.options.style === 'percent' && ((this.options.minimumFractionDigits ?? 0) > 18 || (this.options.maximumFractionDigits ?? 0) > 18)) {
|
|
115
|
+
console.warn('NumberParser cannot handle percentages with greater than 18 decimal places, please reduce the number in your options.');
|
|
116
|
+
}
|
|
110
117
|
}
|
|
111
118
|
|
|
112
119
|
parse(value: string) {
|
|
@@ -119,23 +126,50 @@ class NumberParserImpl {
|
|
|
119
126
|
.replace(this.symbols.minusSign, '-')
|
|
120
127
|
.replace(this.symbols.numeral, this.symbols.index);
|
|
121
128
|
|
|
129
|
+
if (this.options.style === 'percent') {
|
|
130
|
+
// javascript is bad at dividing by 100 and maintaining the same significant figures, so perform it on the string before parsing
|
|
131
|
+
let isNegative = fullySanitizedValue.indexOf('-');
|
|
132
|
+
fullySanitizedValue = fullySanitizedValue.replace('-', '');
|
|
133
|
+
let index = fullySanitizedValue.indexOf('.');
|
|
134
|
+
if (index === -1) {
|
|
135
|
+
index = fullySanitizedValue.length;
|
|
136
|
+
}
|
|
137
|
+
fullySanitizedValue = fullySanitizedValue.replace('.', '');
|
|
138
|
+
if (index - 2 === 0) {
|
|
139
|
+
fullySanitizedValue = `0.${fullySanitizedValue}`;
|
|
140
|
+
} else if (index - 2 === -1) {
|
|
141
|
+
fullySanitizedValue = `0.0${fullySanitizedValue}`;
|
|
142
|
+
} else if (index - 2 === -2) {
|
|
143
|
+
fullySanitizedValue = '0.00';
|
|
144
|
+
} else {
|
|
145
|
+
fullySanitizedValue = `${fullySanitizedValue.slice(0, index - 2)}.${fullySanitizedValue.slice(index - 2)}`;
|
|
146
|
+
}
|
|
147
|
+
if (isNegative > -1) {
|
|
148
|
+
fullySanitizedValue = `-${fullySanitizedValue}`;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
122
152
|
let newValue = fullySanitizedValue ? +fullySanitizedValue : NaN;
|
|
123
153
|
if (isNaN(newValue)) {
|
|
124
154
|
return NaN;
|
|
125
155
|
}
|
|
126
156
|
|
|
157
|
+
if (this.options.style === 'percent') {
|
|
158
|
+
// extra step for rounding percents to what our formatter would output
|
|
159
|
+
let options = {
|
|
160
|
+
...this.options,
|
|
161
|
+
style: 'decimal',
|
|
162
|
+
minimumFractionDigits: Math.min(this.options.minimumFractionDigits + 2, 20),
|
|
163
|
+
maximumFractionDigits: Math.min(this.options.maximumFractionDigits + 2, 20)
|
|
164
|
+
};
|
|
165
|
+
return (new NumberParser(this.locale, options)).parse(new NumberFormatter(this.locale, options).format(newValue));
|
|
166
|
+
}
|
|
167
|
+
|
|
127
168
|
// accounting will always be stripped to a positive number, so if it's accounting and has a () around everything, then we need to make it negative again
|
|
128
169
|
if (this.options.currencySign === 'accounting' && CURRENCY_SIGN_REGEX.test(value)) {
|
|
129
170
|
newValue = -1 * newValue;
|
|
130
171
|
}
|
|
131
172
|
|
|
132
|
-
// when reading the number, if it's a percent, then it should be interpreted as being divided by 100
|
|
133
|
-
if (this.options.style === 'percent') {
|
|
134
|
-
newValue /= 100;
|
|
135
|
-
// after dividing to get the percent value, javascript may get .0210999999 instead of .0211, so fix the number of fraction digits
|
|
136
|
-
newValue = +newValue.toFixed((this.options.maximumFractionDigits ?? 0) + 2);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
173
|
return newValue;
|
|
140
174
|
}
|
|
141
175
|
|
|
@@ -179,6 +213,11 @@ class NumberParserImpl {
|
|
|
179
213
|
return false;
|
|
180
214
|
}
|
|
181
215
|
|
|
216
|
+
// Numbers that can't have any decimal values fail if a decimal character is typed
|
|
217
|
+
if (value.indexOf(this.symbols.decimal) > -1 && this.options.maximumFractionDigits === 0) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
|
|
182
221
|
// Remove numerals, groups, and decimals
|
|
183
222
|
value = replaceAll(value, this.symbols.group, '')
|
|
184
223
|
.replace(this.symbols.numeral, '')
|
|
@@ -198,11 +237,13 @@ const pluralNumbers = [
|
|
|
198
237
|
0, 4, 2, 1, 11, 20, 3, 7, 100, 21, 0.1, 1.1
|
|
199
238
|
];
|
|
200
239
|
|
|
201
|
-
function getSymbols(formatter: Intl.NumberFormat, intlOptions: Intl.ResolvedNumberFormatOptions, originalOptions: Intl.NumberFormatOptions): Symbols {
|
|
240
|
+
function getSymbols(locale: string, formatter: Intl.NumberFormat, intlOptions: Intl.ResolvedNumberFormatOptions, originalOptions: Intl.NumberFormatOptions): Symbols {
|
|
241
|
+
// formatter needs access to all decimal places in order to generate the correct literal strings for the plural set
|
|
242
|
+
let symbolFormatter = new Intl.NumberFormat(locale, {...intlOptions, minimumSignificantDigits: 1, maximumSignificantDigits: 21});
|
|
202
243
|
// Note: some locale's don't add a group symbol until there is a ten thousands place
|
|
203
|
-
let allParts =
|
|
204
|
-
let posAllParts =
|
|
205
|
-
let pluralParts = pluralNumbers.map(n =>
|
|
244
|
+
let allParts = symbolFormatter.formatToParts(-10000.111);
|
|
245
|
+
let posAllParts = symbolFormatter.formatToParts(10000.111);
|
|
246
|
+
let pluralParts = pluralNumbers.map(n => symbolFormatter.formatToParts(n));
|
|
206
247
|
|
|
207
248
|
let minusSign = allParts.find(p => p.type === 'minusSign')?.value ?? '-';
|
|
208
249
|
let plusSign = posAllParts.find(p => p.type === 'plusSign')?.value;
|
|
@@ -214,7 +255,11 @@ function getSymbols(formatter: Intl.NumberFormat, intlOptions: Intl.ResolvedNumb
|
|
|
214
255
|
plusSign = '+';
|
|
215
256
|
}
|
|
216
257
|
|
|
217
|
-
|
|
258
|
+
// If maximumSignificantDigits is 1 (the minimum) then we won't get decimal characters out of the above formatters
|
|
259
|
+
// Percent also defaults to 0 fractionDigits, so we need to make a new one that isn't percent to get an accurate decimal
|
|
260
|
+
let decimalParts = new Intl.NumberFormat(locale, {...intlOptions, minimumFractionDigits: 2, maximumFractionDigits: 2}).formatToParts(0.001);
|
|
261
|
+
|
|
262
|
+
let decimal = decimalParts.find(p => p.type === 'decimal')?.value;
|
|
218
263
|
let group = allParts.find(p => p.type === 'group')?.value;
|
|
219
264
|
|
|
220
265
|
// this set is also for a regex, it's all literals that might be in the string we want to eventually parse that
|
|
@@ -223,7 +268,7 @@ function getSymbols(formatter: Intl.NumberFormat, intlOptions: Intl.ResolvedNumb
|
|
|
223
268
|
let pluralPartsLiterals = pluralParts.flatMap(p => p.filter(p => !nonLiteralParts.has(p.type)).map(p => escapeRegex(p.value)));
|
|
224
269
|
let sortedLiterals = [...new Set([...allPartsLiterals, ...pluralPartsLiterals])].sort((a, b) => b.length - a.length);
|
|
225
270
|
|
|
226
|
-
let literals = sortedLiterals.length === 0 ?
|
|
271
|
+
let literals = sortedLiterals.length === 0 ?
|
|
227
272
|
new RegExp('[\\p{White_Space}]', 'gu') :
|
|
228
273
|
new RegExp(`${sortedLiterals.join('|')}|[\\p{White_Space}]`, 'gu');
|
|
229
274
|
|
|
@@ -247,5 +292,5 @@ function replaceAll(str: string, find: string, replace: string) {
|
|
|
247
292
|
}
|
|
248
293
|
|
|
249
294
|
function escapeRegex(string: string) {
|
|
250
|
-
return string.replace(/[
|
|
295
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
251
296
|
}
|