@automattic/number-formatters 1.0.0-alpha.1
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/CHANGELOG.md +23 -0
- package/LICENSE.txt +357 -0
- package/README.md +163 -0
- package/SECURITY.md +47 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/create-number-formatters.d.ts +124 -0
- package/dist/create-number-formatters.js +101 -0
- package/dist/get-cached-formatter.d.ts +17 -0
- package/dist/get-cached-formatter.js +32 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +7 -0
- package/dist/number-format-currency/currencies.d.ts +2 -0
- package/dist/number-format-currency/currencies.js +485 -0
- package/dist/number-format-currency/index.d.ts +89 -0
- package/dist/number-format-currency/index.js +317 -0
- package/dist/number-format.d.ts +22 -0
- package/dist/number-format.js +55 -0
- package/dist/types.d.ts +109 -0
- package/dist/types.js +1 -0
- package/package.json +45 -0
- package/src/constants.ts +2 -0
- package/src/create-number-formatters.ts +260 -0
- package/src/get-cached-formatter.ts +53 -0
- package/src/index.ts +19 -0
- package/src/number-format-currency/currencies.ts +487 -0
- package/src/number-format-currency/index.ts +395 -0
- package/src/number-format.ts +66 -0
- package/src/types.ts +144 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { FormatCurrency, FormatNumber, GetCurrencyObject } from './types.js';
|
|
2
|
+
export interface NumberFormatters {
|
|
3
|
+
/**
|
|
4
|
+
* Sets the locale for number formatting
|
|
5
|
+
* @param locale - The locale to use for formatting
|
|
6
|
+
*/
|
|
7
|
+
setLocale(locale: string): void;
|
|
8
|
+
/**
|
|
9
|
+
* Sets the user's geo location for currency formatting if available
|
|
10
|
+
* @param geoLocation - The geo location to use for formatting
|
|
11
|
+
*/
|
|
12
|
+
setGeoLocation(geoLocation: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Formats numbers using locale settings and/or passed options.
|
|
15
|
+
* @param number - The number to format.
|
|
16
|
+
* @param params - The parameters for the formatter.
|
|
17
|
+
* @param params.decimals - The number of decimal places to display.
|
|
18
|
+
* @param params.forceLatin - Whether to force the Latin script.
|
|
19
|
+
* @param params.numberFormatOptions - Additional options to pass to the formatter.
|
|
20
|
+
* @return {string} Formatted number as string, or original number as string if formatting fails.
|
|
21
|
+
*/
|
|
22
|
+
formatNumber: FormatNumber;
|
|
23
|
+
/**
|
|
24
|
+
* Formats numbers using locale settings and/or passed options, with a compact notation.
|
|
25
|
+
* Convenience method for formatting numbers in a compact notation e.g. 1K, 1M, etc.
|
|
26
|
+
* Basically sets `notation: 'compact'` and `maximumFractionDigits: 1` in the options.
|
|
27
|
+
* Everything is overridable by passing the `numberFormatOptions` option.
|
|
28
|
+
* If you want more digits, pass `maximumFractionDigits: 2`.
|
|
29
|
+
* @param number - The number to format.
|
|
30
|
+
* @param params - The parameters for the formatter.
|
|
31
|
+
* @param params.decimals - The number of decimal places to display.
|
|
32
|
+
* @param params.forceLatin - Whether to force the Latin script.
|
|
33
|
+
* @param params.numberFormatOptions - Additional options to pass to the formatter.
|
|
34
|
+
* @return {string} Formatted number as string, or original number as string if formatting fails.
|
|
35
|
+
*/
|
|
36
|
+
formatNumberCompact: FormatNumber;
|
|
37
|
+
/**
|
|
38
|
+
* Formats money with a given currency code.
|
|
39
|
+
*
|
|
40
|
+
* The currency will define the properties to use for this formatting, but
|
|
41
|
+
* those properties can be overridden using the options. Be careful when doing
|
|
42
|
+
* this.
|
|
43
|
+
*
|
|
44
|
+
* For currencies that include decimals, this will always return the amount
|
|
45
|
+
* with decimals included, even if those decimals are zeros. To exclude the
|
|
46
|
+
* zeros, use the `stripZeros` option. For example, the function will normally
|
|
47
|
+
* format `10.00` in `USD` as `$10.00` but when this option is true, it will
|
|
48
|
+
* return `$10` instead.
|
|
49
|
+
*
|
|
50
|
+
* Since rounding errors are common in floating point math, sometimes a price
|
|
51
|
+
* is provided as an integer in the smallest unit of a currency (eg: cents in
|
|
52
|
+
* USD or yen in JPY). Set the `isSmallestUnit` to change the function to
|
|
53
|
+
* operate on integer numbers instead. If this option is not set or false, the
|
|
54
|
+
* function will format the amount `1025` in `USD` as `$1,025.00`, but when the
|
|
55
|
+
* option is true, it will return `$10.25` instead.
|
|
56
|
+
*
|
|
57
|
+
* If the number is NaN, it will be treated as 0.
|
|
58
|
+
*
|
|
59
|
+
* If the currency code is not known, this will assume a default currency
|
|
60
|
+
* similar to USD.
|
|
61
|
+
*
|
|
62
|
+
* If `isSmallestUnit` is set and the number is not an integer, it will be
|
|
63
|
+
* rounded to an integer.
|
|
64
|
+
* @param number - The number to format.
|
|
65
|
+
* @param currency - The currency to format.
|
|
66
|
+
* @param options - The options for the formatter.
|
|
67
|
+
* @param options.stripZeros - Whether to strip zeros.
|
|
68
|
+
* @param options.isSmallestUnit - Whether the number is the smallest unit of a currency.
|
|
69
|
+
* @param options.signForPositive - Whether to show the sign for positive numbers.
|
|
70
|
+
* @param options.forceLatin - Whether to force the latin locale.
|
|
71
|
+
* @return {string} A formatted string.
|
|
72
|
+
*/
|
|
73
|
+
formatCurrency: FormatCurrency;
|
|
74
|
+
/**
|
|
75
|
+
* Returns a formatted price object which can be used to manually render a
|
|
76
|
+
* formatted currency (eg: if you wanted to render the currency symbol in a
|
|
77
|
+
* different font size).
|
|
78
|
+
*
|
|
79
|
+
* The currency will define the properties to use for this formatting, but
|
|
80
|
+
* those properties can be overridden using the options. Be careful when doing
|
|
81
|
+
* this.
|
|
82
|
+
*
|
|
83
|
+
* For currencies that include decimals, this will always return the amount
|
|
84
|
+
* with decimals included, even if those decimals are zeros. To exclude the
|
|
85
|
+
* zeros, use the `stripZeros` option. For example, the function will normally
|
|
86
|
+
* format `10.00` in `USD` as `$10.00` but when this option is true, it will
|
|
87
|
+
* return `$10` instead.
|
|
88
|
+
*
|
|
89
|
+
* Since rounding errors are common in floating point math, sometimes a price
|
|
90
|
+
* is provided as an integer in the smallest unit of a currency (eg: cents in
|
|
91
|
+
* USD or yen in JPY). Set the `isSmallestUnit` to change the function to
|
|
92
|
+
* operate on integer numbers instead. If this option is not set or false, the
|
|
93
|
+
* function will format the amount `1025` in `USD` as `$1,025.00`, but when the
|
|
94
|
+
* option is true, it will return `$10.25` instead.
|
|
95
|
+
*
|
|
96
|
+
* Note that the `integer` return value of this function is not a number, but a
|
|
97
|
+
* locale-formatted string which may include symbols like spaces, commas, or
|
|
98
|
+
* periods as group separators. Similarly, the `fraction` property is a string
|
|
99
|
+
* that contains the decimal separator.
|
|
100
|
+
*
|
|
101
|
+
* If the number is NaN, it will be treated as 0.
|
|
102
|
+
*
|
|
103
|
+
* If the currency code is not known, this will assume a default currency
|
|
104
|
+
* similar to USD.
|
|
105
|
+
*
|
|
106
|
+
* If `isSmallestUnit` is set and the number is not an integer, it will be
|
|
107
|
+
* rounded to an integer.
|
|
108
|
+
* @param number - The number to format.
|
|
109
|
+
* @param currency - The currency to format.
|
|
110
|
+
* @param options - The options for the formatter.
|
|
111
|
+
* @param options.stripZeros - Whether to strip zeros.
|
|
112
|
+
* @param options.isSmallestUnit - Whether the number is the smallest unit of a currency.
|
|
113
|
+
* @param options.signForPositive - Whether to show the sign for positive numbers.
|
|
114
|
+
* @param options.forceLatin - Whether to force the latin locale.
|
|
115
|
+
* @return {CurrencyObject} A formatted price object.
|
|
116
|
+
*/
|
|
117
|
+
getCurrencyObject: GetCurrencyObject;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Creates a NumberFormatters instance that provides number and currency formatting functionality with locale awareness
|
|
121
|
+
* @return {NumberFormatters} A NumberFormatters instance
|
|
122
|
+
*/
|
|
123
|
+
declare function createNumberFormatters(): NumberFormatters;
|
|
124
|
+
export default createNumberFormatters;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { getSettings } from '@wordpress/date';
|
|
2
|
+
import { FALLBACK_LOCALE } from './constants.js';
|
|
3
|
+
import { numberFormatCurrency, getCurrencyObject as getCurrencyObjectFromCurrencyFormatter, } from './number-format-currency/index.js';
|
|
4
|
+
import { numberFormat, numberFormatCompact } from './number-format.js';
|
|
5
|
+
/**
|
|
6
|
+
* Creates a NumberFormatters instance that provides number and currency formatting functionality with locale awareness
|
|
7
|
+
* @return {NumberFormatters} A NumberFormatters instance
|
|
8
|
+
*/
|
|
9
|
+
function createNumberFormatters() {
|
|
10
|
+
let localeState;
|
|
11
|
+
let geoLocationState;
|
|
12
|
+
const setLocale = (locale) => {
|
|
13
|
+
/**
|
|
14
|
+
* The `Intl.NumberFormat` constructor fails only when there is a variant, divided by `_`.
|
|
15
|
+
* These suffixes should be removed. Values like `de-at` or `es-mx`
|
|
16
|
+
* should all be valid inputs for the constructor.
|
|
17
|
+
*/
|
|
18
|
+
localeState = locale;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Returns the locale defined on the module instance (through `setLocale`)
|
|
22
|
+
* or the "fallback locale" if no locale has been set.
|
|
23
|
+
*
|
|
24
|
+
* The "fallback locale" is defined as:
|
|
25
|
+
* - the current WP user locale, if available through `@wordpress/date` settings (assuming this runs in a WordPress context)
|
|
26
|
+
* - or the browser locale, if available through `window.navigator.language`
|
|
27
|
+
* - or the fallback locale constant (`FALLBACK_LOCALE`)
|
|
28
|
+
*
|
|
29
|
+
* @return {string} The locale to use for formatting.
|
|
30
|
+
*/
|
|
31
|
+
const getBrowserSafeLocale = () => {
|
|
32
|
+
const { l10n: { locale: localeFromUserSettings }, } = getSettings();
|
|
33
|
+
return (localeState ??
|
|
34
|
+
(localeFromUserSettings || global?.window?.navigator?.language) ??
|
|
35
|
+
FALLBACK_LOCALE).split('_')[0];
|
|
36
|
+
};
|
|
37
|
+
const setGeoLocation = (geoLocation) => {
|
|
38
|
+
geoLocationState = geoLocation;
|
|
39
|
+
};
|
|
40
|
+
const formatNumber = (number, { decimals = 0, forceLatin = true, numberFormatOptions = {} } = {}) => {
|
|
41
|
+
try {
|
|
42
|
+
const formatter = numberFormat({
|
|
43
|
+
browserSafeLocale: getBrowserSafeLocale(),
|
|
44
|
+
decimals,
|
|
45
|
+
forceLatin,
|
|
46
|
+
numberFormatOptions,
|
|
47
|
+
});
|
|
48
|
+
return formatter.format(number);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return String(number);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const formatNumberCompact = (number, { decimals = 0, forceLatin = true, numberFormatOptions = {} } = {}) => {
|
|
55
|
+
try {
|
|
56
|
+
const formatter = numberFormatCompact({
|
|
57
|
+
browserSafeLocale: getBrowserSafeLocale(),
|
|
58
|
+
decimals,
|
|
59
|
+
forceLatin,
|
|
60
|
+
numberFormatOptions,
|
|
61
|
+
});
|
|
62
|
+
return formatter.format(number);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return String(number);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const formatCurrency = (number, currency, { stripZeros = false, isSmallestUnit = false, signForPositive = false, forceLatin = true } = {}) => {
|
|
69
|
+
return numberFormatCurrency({
|
|
70
|
+
number,
|
|
71
|
+
currency,
|
|
72
|
+
browserSafeLocale: getBrowserSafeLocale(),
|
|
73
|
+
stripZeros,
|
|
74
|
+
isSmallestUnit,
|
|
75
|
+
signForPositive,
|
|
76
|
+
geoLocation: geoLocationState,
|
|
77
|
+
forceLatin,
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
const getCurrencyObject = (number, currency, { stripZeros = false, isSmallestUnit = false, signForPositive = false, forceLatin = true } = {}) => {
|
|
81
|
+
return getCurrencyObjectFromCurrencyFormatter({
|
|
82
|
+
number,
|
|
83
|
+
currency,
|
|
84
|
+
browserSafeLocale: getBrowserSafeLocale(),
|
|
85
|
+
stripZeros,
|
|
86
|
+
isSmallestUnit,
|
|
87
|
+
signForPositive,
|
|
88
|
+
geoLocation: geoLocationState,
|
|
89
|
+
forceLatin,
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
setLocale,
|
|
94
|
+
setGeoLocation,
|
|
95
|
+
formatNumber,
|
|
96
|
+
formatNumberCompact,
|
|
97
|
+
formatCurrency,
|
|
98
|
+
getCurrencyObject,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export default createNumberFormatters;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface Params {
|
|
2
|
+
locale: string;
|
|
3
|
+
options?: Intl.NumberFormatOptions;
|
|
4
|
+
fallbackLocale?: string;
|
|
5
|
+
retries?: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Get a cached formatter for a given locale and options.
|
|
9
|
+
* @param params - The parameters for the formatter.
|
|
10
|
+
* @param params.locale - The locale to format the number in.
|
|
11
|
+
* @param params.options - Intl.NumberFormatOptions to pass to the formatter.
|
|
12
|
+
* @param params.fallbackLocale - The locale to fallback to if the locale is not supported.
|
|
13
|
+
* @param params.retries - The number of retries to attempt if the formatter is not created.
|
|
14
|
+
* @return {Intl.NumberFormat} A cached formatter for the given locale and options.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getCachedFormatter({ locale, fallbackLocale, options, retries, }: Params): Intl.NumberFormat;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import debugFactory from 'debug';
|
|
2
|
+
import { FALLBACK_LOCALE } from './constants.js';
|
|
3
|
+
const debug = debugFactory('number-formatters:get-cached-formatter');
|
|
4
|
+
const formatterCache = new Map();
|
|
5
|
+
/**
|
|
6
|
+
* Get a cached formatter for a given locale and options.
|
|
7
|
+
* @param params - The parameters for the formatter.
|
|
8
|
+
* @param params.locale - The locale to format the number in.
|
|
9
|
+
* @param params.options - Intl.NumberFormatOptions to pass to the formatter.
|
|
10
|
+
* @param params.fallbackLocale - The locale to fallback to if the locale is not supported.
|
|
11
|
+
* @param params.retries - The number of retries to attempt if the formatter is not created.
|
|
12
|
+
* @return {Intl.NumberFormat} A cached formatter for the given locale and options.
|
|
13
|
+
*/
|
|
14
|
+
export function getCachedFormatter({ locale, fallbackLocale = FALLBACK_LOCALE, options, retries = 1, }) {
|
|
15
|
+
const cacheKey = JSON.stringify([locale, options]);
|
|
16
|
+
try {
|
|
17
|
+
return (formatterCache.get(cacheKey) ??
|
|
18
|
+
formatterCache.set(cacheKey, new Intl.NumberFormat(locale, options)).get(cacheKey));
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
// If the locale is invalid, creating the NumberFormat will throw.
|
|
22
|
+
debug(`Intl.NumberFormat was called with a non-existent locale "${locale}"; falling back to ${fallbackLocale}`);
|
|
23
|
+
if (retries) {
|
|
24
|
+
return getCachedFormatter({
|
|
25
|
+
locale: fallbackLocale,
|
|
26
|
+
options,
|
|
27
|
+
retries: retries - 1,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import createNumberFormatters from './create-number-formatters.js';
|
|
2
|
+
export declare const setLocale: (locale: string) => void, setGeoLocation: (geoLocation: string) => void, formatNumber: import("./types.js").FormatNumber, formatNumberCompact: import("./types.js").FormatNumber, formatCurrency: import("./types.js").FormatCurrency, getCurrencyObject: import("./types.js").GetCurrencyObject;
|
|
3
|
+
export { createNumberFormatters };
|
|
4
|
+
export * from './types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import createNumberFormatters from './create-number-formatters.js';
|
|
2
|
+
const defaultFormatter = createNumberFormatters();
|
|
3
|
+
export const { setLocale, setGeoLocation, formatNumber, formatNumberCompact, formatCurrency, getCurrencyObject, } = defaultFormatter;
|
|
4
|
+
export { createNumberFormatters };
|
|
5
|
+
export * from './types.js';
|
|
6
|
+
// We can optionally export the formatters individually if we want to use them in a more granular way.
|
|
7
|
+
// export { numberFormat, numberFormatCompact, numberFormatCurrency, getCurrencyObject };
|