Skip to content

Commit

Permalink
Always precisely format small numbers in getPreciseNumberFormat
Browse files Browse the repository at this point in the history
In browsers with imprecise Intl.NumberFormat: display formatted number after
allowing implicit conversion to rounded float.
  • Loading branch information
lukaw3d committed Aug 3, 2023
1 parent 7fd5740 commit 43229e1
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 1 deletion.
6 changes: 6 additions & 0 deletions playwright/tests/getPreciseNumberFormat.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ async function setup(page: Page, balance: string, decimals: number) {
}

test.describe('getPreciseNumberFormat', () => {
test('small number should be precise and formatted', async ({ page }) => {
await setup(page, '111222333444555', 9)
// Expect precisely formatted small number even when browser doesn't support precise formatting for large numbers
await expect(page.getByText('111,222.333444555', { exact: true })).toBeVisible()
})

test('large number should be precise and formatted or fallback to precise unformatted number in browsers without support', async ({
page,
}) => {
Expand Down
4 changes: 3 additions & 1 deletion src/locales/getPreciseNumberFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const isPreciseIntlSupported =

export function getPreciseNumberFormat(value: string) {
const decimalPlaces = new BigNumber(value).decimalPlaces()
const isFloatPrecise = new BigNumber(value).isEqualTo(parseFloat(value))
// Fallback if types are not strict enough to prevent value=undefined and ''
if (value == null || value === '' || decimalPlaces == null) {
if (process.env.NODE_ENV !== 'production') {
Expand All @@ -26,7 +27,8 @@ export function getPreciseNumberFormat(value: string) {
// TODO: Intl internals only work up to maximumFractionDigits: 20.
// `new Intl.NumberFormat(undefined, { maximumFractionDigits: 21 }).format('1')`
// throws an error, i18n silences it, and displays unformatted original string
maximumFractionDigits: isPreciseIntlSupported && decimalPlaces <= 20 ? 20 : Infinity,
maximumFractionDigits:
(isPreciseIntlSupported || isFloatPrecise) && decimalPlaces <= 20 ? 20 : Infinity,
} satisfies Intl.NumberFormatOptions,
},
}
Expand Down

0 comments on commit 43229e1

Please sign in to comment.