@@ -3,7 +3,13 @@ import { getFormatter } from '../../utils/formatNumber';
33
44const STEP_EPSILON_FACTOR = 1e-10 ;
55
6- function getFractionDigits ( format ?: Intl . NumberFormatOptions ) {
6+ // The repo's configured Intl types do not include the newer NumberFormat v3 rounding options yet.
7+ type NumberFormatOptionsWithRounding = Intl . NumberFormatOptions & {
8+ roundingIncrement ?: number | undefined ;
9+ roundingMode ?: string | undefined ;
10+ } ;
11+
12+ function getFractionDigits ( format ?: NumberFormatOptionsWithRounding ) {
713 const defaultOptions = getFormatter ( 'en-US' ) . resolvedOptions ( ) ;
814 const minimumFractionDigits =
915 format ?. minimumFractionDigits ?? defaultOptions . minimumFractionDigits ?? 0 ;
@@ -14,17 +20,40 @@ function getFractionDigits(format?: Intl.NumberFormatOptions) {
1420 return { maximumFractionDigits, minimumFractionDigits } ;
1521}
1622
17- function roundToFractionDigits ( value : number , maximumFractionDigits : number ) {
23+ export function roundToFractionDigits (
24+ value : number ,
25+ maximumFractionDigits : number ,
26+ format ?: NumberFormatOptionsWithRounding ,
27+ ) {
1828 if ( ! Number . isFinite ( value ) ) {
1929 return value ;
2030 }
2131 const digits = Math . min ( Math . max ( maximumFractionDigits , 0 ) , 20 ) ;
22- return Number ( value . toFixed ( digits ) ) ;
32+ const scale =
33+ format ?. style === 'percent' &&
34+ ( format . maximumFractionDigits != null || format . minimumFractionDigits != null )
35+ ? 100
36+ : 1 ;
37+ const valueToRound = value * scale ;
38+
39+ if ( format ?. roundingIncrement == null && format ?. roundingMode == null ) {
40+ return Number ( valueToRound . toFixed ( digits ) ) / scale ;
41+ }
42+
43+ const roundingFormatOptions : NumberFormatOptionsWithRounding = {
44+ useGrouping : false ,
45+ minimumFractionDigits : digits ,
46+ maximumFractionDigits : digits ,
47+ roundingIncrement : format ?. roundingIncrement ,
48+ roundingMode : format ?. roundingMode ,
49+ } ;
50+
51+ return Number ( getFormatter ( 'en-US' , roundingFormatOptions ) . format ( valueToRound ) ) / scale ;
2352}
2453
25- export function removeFloatingPointErrors ( value : number , format ?: Intl . NumberFormatOptions ) {
54+ export function removeFloatingPointErrors ( value : number , format ?: NumberFormatOptionsWithRounding ) {
2655 const { maximumFractionDigits } = getFractionDigits ( format ) ;
27- return roundToFractionDigits ( value , maximumFractionDigits ) ;
56+ return roundToFractionDigits ( value , maximumFractionDigits , format ) ;
2857}
2958
3059function snapToStep (
@@ -73,7 +102,7 @@ export function toValidatedNumber(
73102 minWithDefault : number ;
74103 maxWithDefault : number ;
75104 minWithZeroDefault : number ;
76- format : Intl . NumberFormatOptions | undefined ;
105+ format : NumberFormatOptionsWithRounding | undefined ;
77106 snapOnStep : boolean ;
78107 small : boolean ;
79108 clamp : boolean ;
0 commit comments