mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) move home server into core
Summary: This moves enough server material into core to run a home server. The data engine is not yet incorporated (though in manual testing it works when ported). Test Plan: existing tests pass Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2552
This commit is contained in:
76
app/common/NumberFormat.ts
Normal file
76
app/common/NumberFormat.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Here are the most relevant formats we want to support.
|
||||
* -1234.56 Plain
|
||||
* -1,234.56 Number (with separators)
|
||||
* 12.34% Percent
|
||||
* 1.23E3 Scientific
|
||||
* $(1,234.56) Accounting
|
||||
* (1,234.56) Financial
|
||||
* -$1,234.56 Currency
|
||||
*
|
||||
* We implement a button-based UI, using one selector button to choose mode:
|
||||
* none = NumMode undefined (plain number, no thousand separators)
|
||||
* `$` = NumMode 'currency'
|
||||
* `,` = NumMode 'decimal' (plain number, with thousand separators)
|
||||
* `%` = NumMode 'percent'
|
||||
* `Exp` = NumMode 'scientific'
|
||||
* A second toggle button is `(-)` for Sign, to use parentheses rather than "-" for negative
|
||||
* numbers. It is Ignored and disabled when mode is 'scientific'.
|
||||
*/
|
||||
|
||||
import {clamp} from 'app/common/gutil';
|
||||
|
||||
// Options for number formatting.
|
||||
export type NumMode = 'currency' | 'decimal' | 'percent' | 'scientific';
|
||||
export type NumSign = 'parens';
|
||||
|
||||
// TODO: In the future, locale should be a value associated with the document or the user.
|
||||
const defaultLocale = 'en-US';
|
||||
|
||||
// TODO: The currency to use for currency formatting could be made configurable.
|
||||
const defaultCurrency = 'USD';
|
||||
|
||||
export interface NumberFormatOptions {
|
||||
numMode?: NumMode;
|
||||
numSign?: NumSign;
|
||||
decimals?: number; // aka minimum fraction digits
|
||||
maxDecimals?: number;
|
||||
}
|
||||
|
||||
export function buildNumberFormat(options: NumberFormatOptions): Intl.NumberFormat {
|
||||
const nfOptions: Intl.NumberFormatOptions = parseNumMode(options.numMode);
|
||||
|
||||
// numSign is implemented outside of Intl.NumberFormat since the latter's similar 'currencySign'
|
||||
// option is not well-supported, and doesn't apply to non-currency formats.
|
||||
|
||||
if (options.decimals !== undefined) {
|
||||
// Should be at least 0
|
||||
nfOptions.minimumFractionDigits = clamp(Number(options.decimals), 0, 20);
|
||||
}
|
||||
|
||||
// maximumFractionDigits must not be less than the minimum, so we need to know the minimum
|
||||
// implied by numMode.
|
||||
const tmp = new Intl.NumberFormat(defaultLocale, nfOptions).resolvedOptions();
|
||||
|
||||
if (options.maxDecimals !== undefined) {
|
||||
// Should be at least 0 and at least minimumFractionDigits.
|
||||
nfOptions.maximumFractionDigits = clamp(Number(options.maxDecimals), tmp.minimumFractionDigits || 0, 20);
|
||||
} else if (!options.numMode) {
|
||||
// For the default format, keep max digits at 10 as we had before.
|
||||
nfOptions.maximumFractionDigits = clamp(10, tmp.minimumFractionDigits || 0, 20);
|
||||
}
|
||||
|
||||
return new Intl.NumberFormat(defaultLocale, nfOptions);
|
||||
}
|
||||
|
||||
function parseNumMode(numMode?: NumMode): Intl.NumberFormatOptions {
|
||||
switch (numMode) {
|
||||
case 'currency': return {style: 'currency', currency: defaultCurrency};
|
||||
case 'decimal': return {useGrouping: true};
|
||||
case 'percent': return {style: 'percent'};
|
||||
// TODO 'notation' option (and therefore numMode 'scientific') works on recent Firefox and
|
||||
// Chrome, not on Safari or Node 10.
|
||||
case 'scientific': return {notation: 'scientific'} as Intl.NumberFormatOptions;
|
||||
default: return {useGrouping: false};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user