@internationalized/number 3.3.1-nightly.4202 → 3.3.1-nightly.4206

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 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
- */ const $6c7bd7858deea686$var$CURRENCY_SIGN_REGEX = new RegExp("^.*\\(.*\\).*$");
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
- newValue /= 100;
243
- var _this_options_maximumFractionDigits;
244
- // after dividing to get the percent value, javascript may get .0210999999 instead of .0211, so fix the number of fraction digits
245
- newValue = +newValue.toFixed(((_this_options_maximumFractionDigits = this.options.maximumFractionDigits) !== null && _this_options_maximumFractionDigits !== void 0 ? _this_options_maximumFractionDigits : 0) + 2);
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, _allParts_find1, _allParts_find2;
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 = formatter.formatToParts(-10000.111);
314
- let posAllParts = formatter.formatToParts(10000.111);
315
- let pluralParts = $6c7bd7858deea686$var$pluralNumbers.map((n)=>formatter.formatToParts(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
- let decimal = (_allParts_find1 = allParts.find((p)=>p.type === "decimal")) === null || _allParts_find1 === void 0 ? void 0 : _allParts_find1.value;
324
- let group = (_allParts_find2 = allParts.find((p)=>p.type === "group")) === null || _allParts_find2 === void 0 ? void 0 : _allParts_find2.value;
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(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
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
- */ const $d68f3f4c684426c6$var$CURRENCY_SIGN_REGEX = new RegExp("^.*\\(.*\\).*$");
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
- newValue /= 100;
249
- var _this_options_maximumFractionDigits;
250
- // after dividing to get the percent value, javascript may get .0210999999 instead of .0211, so fix the number of fraction digits
251
- newValue = +newValue.toFixed(((_this_options_maximumFractionDigits = this.options.maximumFractionDigits) !== null && _this_options_maximumFractionDigits !== void 0 ? _this_options_maximumFractionDigits : 0) + 2);
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, _allParts_find1, _allParts_find2;
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 = formatter.formatToParts(-10000.111);
320
- let posAllParts = formatter.formatToParts(10000.111);
321
- let pluralParts = $d68f3f4c684426c6$var$pluralNumbers.map((n)=>formatter.formatToParts(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
- let decimal = (_allParts_find1 = allParts.find((p)=>p.type === "decimal")) === null || _allParts_find1 === void 0 ? void 0 : _allParts_find1.value;
330
- let group = (_allParts_find2 = allParts.find((p)=>p.type === "group")) === null || _allParts_find2 === void 0 ? void 0 : _allParts_find2.value;
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(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
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":"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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":"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
- */ const $6c7bd7858deea686$var$CURRENCY_SIGN_REGEX = new RegExp("^.*\\(.*\\).*$");
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
- newValue /= 100;
243
- var _this_options_maximumFractionDigits;
244
- // after dividing to get the percent value, javascript may get .0210999999 instead of .0211, so fix the number of fraction digits
245
- newValue = +newValue.toFixed(((_this_options_maximumFractionDigits = this.options.maximumFractionDigits) !== null && _this_options_maximumFractionDigits !== void 0 ? _this_options_maximumFractionDigits : 0) + 2);
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, _allParts_find1, _allParts_find2;
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 = formatter.formatToParts(-10000.111);
314
- let posAllParts = formatter.formatToParts(10000.111);
315
- let pluralParts = $6c7bd7858deea686$var$pluralNumbers.map((n)=>formatter.formatToParts(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
- let decimal = (_allParts_find1 = allParts.find((p)=>p.type === "decimal")) === null || _allParts_find1 === void 0 ? void 0 : _allParts_find1.value;
324
- let group = (_allParts_find2 = allParts.find((p)=>p.type === "group")) === null || _allParts_find2 === void 0 ? void 0 : _allParts_find2.value;
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(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
400
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
366
401
  }
367
402
 
368
403
 
@@ -1 +1 @@
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,GAYD,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;IAWJ,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,WAAW,sBAAsB,CAAC,sBAAsB;QAC5D,IAAI,MAAM,WACR,OAAO;QAGT,wJAAwJ;QACxJ,IAAI,IAAI,CAAC,QAAQ,iBAAiB,gBAAgB,0CAAoB,KAAK,QACzE,WAAW,KAAK;QAGlB,oGAAoG;QACpG,IAAI,IAAI,CAAC,QAAQ,UAAU,WAAW;YACpC,YAAY;gBAEkB;YAD9B,iIAAiI;YACjI,WAAW,CAAC,SAAS,QAAQ,AAAC,CAAA,CAAA,sCAAA,IAAI,CAAC,QAAQ,mCAAb,iDAAA,sCAAsC,CAAA,IAAK;QAC3E;QAEA,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,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;IAnFA,YAAY,MAAc,EAAE,UAAoC,CAAC,CAAC,CAAE;QAClE,IAAI,CAAC,YAAY,IAAI,KAAK,aAAa,QAAQ;QAC/C,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU;QAC9B,IAAI,CAAC,UAAU,iCAAW,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS;IAC1D;AAgFF;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,SAA4B,EAAE,WAA6C,EAAE,eAAyC;QAMxH,gBACD,mBASD,iBACF;IAhBZ,oFAAoF;IACpF,IAAI,WAAW,UAAU,cAAc;IACvC,IAAI,cAAc,UAAU,cAAc;IAC1C,IAAI,cAAc,oCAAc,IAAI,CAAA,IAAK,UAAU,cAAc;QAEjD;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,IAAI,UAAU,CAAA,kBAAA,SAAS,KAAK,CAAA,IAAK,EAAE,SAAS,wBAA9B,6BAAA,KAAA,IAAA,gBAA0C;IACxD,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,yBAAyB;AACjD;","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"}
@@ -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;ACnHD;;;;;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"}
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.4202+21501b784",
3
+ "version": "3.3.1-nightly.4206+88550234c",
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": "21501b7843fd9d255fd18d33f25740923a32f083"
30
+ "gitHead": "88550234c383f2a07a27aa2ca9a0a47a9f49e9aa"
31
31
  }
@@ -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 = formatter.formatToParts(-10000.111);
204
- let posAllParts = formatter.formatToParts(10000.111);
205
- let pluralParts = pluralNumbers.map(n => formatter.formatToParts(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
- let decimal = allParts.find(p => p.type === 'decimal')?.value;
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(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
295
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
251
296
  }