UNPKG

3.16 kBJavaScriptView Raw
1/**
2 * A [ponyfill](https://github.com/sindresorhus/ponyfill) is an opt-in polyfill,
3 * which replaces missing builtins on older or non-compliant platforms, but
4 * without monkey-patching the native API.
5 *
6 * Many browsers do not yet support Intl.NumberFormat.prototype.formatToParts,
7 * which is tracked here: https://github.com/tc39/proposal-intl-formatToParts
8 *
9 * The polyfill available in that repository covers many edge cases, but it's
10 * more functionality than we need at this stage, it's not distributed over
11 * NPM, and it's 18kb. The below
12 * [ponyfill](https://github.com/sindresorhus/ponyfill) is not fully compliant,
13 * but it'll do for now.
14 *
15 * TODO: Replace with a formally maintained, but small-enough, ponyfill.
16 */
17
18const intlFormats = {
19 USD: {
20 symbol: '$',
21 decimal: '.',
22 groupDelim: ','
23 },
24 GBP: {
25 symbol: '£',
26 decimal: '.',
27 groupDelim: ','
28 },
29 EUR: {
30 symbol: '€',
31 decimal: '.',
32 groupDelim: ','
33 }
34};
35
36const IntlPatches = {
37 formatToPartsPatch({ currency, maximumFractionDigits, useGrouping }, num) {
38 const format = intlFormats[currency] || {
39 ...intlFormats.USD,
40 symbol: currency
41 };
42 const { symbol, decimal, groupDelim } = format;
43 const parts = [{ type: 'currency', value: symbol }];
44
45 const [integer, fraction] = num
46 .toFixed(maximumFractionDigits)
47 .match(/\d+/g);
48
49 if (useGrouping !== false) {
50 const intParts = [];
51 const firstGroupLength = integer.length % 3;
52 let integerSlice = integer;
53 if (firstGroupLength > 0) {
54 intParts.push(
55 JSON.stringify({
56 type: 'integer',
57 value: integer.slice(0, firstGroupLength)
58 })
59 );
60 integerSlice = integer.slice(firstGroupLength);
61 }
62
63 const groups = integerSlice.match(/\d{3}/g);
64
65 if (groups) {
66 intParts.push(
67 ...groups.map(intPart =>
68 JSON.stringify({
69 type: 'integer',
70 value: intPart
71 })
72 )
73 );
74 }
75
76 const groupDelimJSON =
77 ',' +
78 JSON.stringify({
79 type: 'group',
80 value: groupDelim
81 }) +
82 ',';
83
84 const intAndGroupParts = JSON.parse(
85 `[${intParts.join(groupDelimJSON)}]`
86 );
87
88 parts.push(...intAndGroupParts);
89 } else {
90 parts.push({ type: 'integer', value: integer });
91 }
92 return parts.concat([
93 { type: 'decimal', value: decimal },
94 { type: 'fraction', value: fraction }
95 ]);
96 },
97
98 toParts(num) {
99 return this.formatToParts
100 ? this.formatToParts(num)
101 : IntlPatches.formatToPartsPatch(this.resolvedOptions(), num);
102 }
103};
104export default IntlPatches;