@@ -68,6 +68,14 @@ const makeVNumberInputProps = propsFactory({
68
68
type : String ,
69
69
validator : ( v : any ) => ! v || v . length === 1 ,
70
70
} ,
71
+ grouping : {
72
+ type : [ Boolean , String ] as PropType < 'always' | 'auto' | 'min2' | boolean > ,
73
+ default : false ,
74
+ } ,
75
+ groupSeparator : {
76
+ type : String ,
77
+ validator : ( v : any ) => ! v || v . length === 1 ,
78
+ } ,
71
79
72
80
...omit ( makeVTextFieldProps ( ) , [ 'modelValue' , 'validationValue' ] ) ,
73
81
} , 'VNumberInput' )
@@ -95,32 +103,21 @@ export const VNumberInput = genericComponent<VNumberInputSlots>()({
95
103
96
104
const isFocused = shallowRef ( props . focused )
97
105
98
- const { decimalSeparator : decimalSeparatorFromLocale } = useLocale ( )
106
+ const {
107
+ current : locale ,
108
+ decimalSeparator : decimalSeparatorFromLocale ,
109
+ numericGroupSeparator : numericGroupSeparatorFromLocale ,
110
+ } = useLocale ( )
99
111
const decimalSeparator = computed ( ( ) => props . decimalSeparator ?. [ 0 ] || decimalSeparatorFromLocale . value )
100
-
101
- function correctPrecision ( val : number , precision = props . precision , trim = true ) {
102
- const fixed = precision == null
103
- ? String ( val )
104
- : val . toFixed ( precision )
105
-
106
- if ( isFocused . value && trim ) {
107
- return Number ( fixed ) . toString ( ) // trim zeros
108
- . replace ( '.' , decimalSeparator . value )
109
- }
110
-
111
- if ( props . minFractionDigits === null || ( precision !== null && precision < props . minFractionDigits ) ) {
112
- return fixed . replace ( '.' , decimalSeparator . value )
113
- }
114
-
115
- let [ baseDigits , fractionDigits ] = fixed . split ( '.' )
116
-
117
- fractionDigits = ( fractionDigits ?? '' ) . padEnd ( props . minFractionDigits , '0' )
118
- . replace ( new RegExp ( `(?<=\\d{${ props . minFractionDigits } })0+$` , 'g' ) , '' )
119
-
120
- return [
121
- baseDigits ,
122
- fractionDigits ,
123
- ] . filter ( Boolean ) . join ( decimalSeparator . value )
112
+ const groupSeparator = computed ( ( ) => props . groupSeparator ?. [ 0 ] || numericGroupSeparatorFromLocale . value )
113
+
114
+ function correctPrecision ( val : number , precision ?: number | null , trim = true ) {
115
+ precision ??= isFocused . value && trim ? undefined : props . precision ?? undefined
116
+ return new Intl . NumberFormat ( locale . value , {
117
+ minimumFractionDigits : props . minFractionDigits ?? precision ,
118
+ maximumFractionDigits : precision ,
119
+ useGrouping : props . grouping ,
120
+ } ) . format ( val )
124
121
}
125
122
126
123
const model = useProxiedModel ( props , 'modelValue' , null ,
@@ -154,7 +151,10 @@ export const VNumberInput = genericComponent<VNumberInputSlots>()({
154
151
_inputText . value = null
155
152
return
156
153
}
157
- const parsedValue = Number ( val . replace ( decimalSeparator . value , '.' ) )
154
+ const parsedValue = Number ( val
155
+ . replaceAll ( groupSeparator . value , '' )
156
+ . replace ( decimalSeparator . value , '.' )
157
+ )
158
158
if ( ! isNaN ( parsedValue ) && parsedValue <= props . max && parsedValue >= props . min ) {
159
159
model . value = parsedValue
160
160
_inputText . value = val
@@ -315,7 +315,10 @@ export const VNumberInput = genericComponent<VNumberInputSlots>()({
315
315
if ( controlsDisabled . value ) return
316
316
if ( ! vTextFieldRef . value ) return
317
317
const actualText = vTextFieldRef . value . value
318
- const parsedValue = Number ( actualText . replace ( decimalSeparator . value , '.' ) )
318
+ const parsedValue = Number ( actualText
319
+ . replaceAll ( groupSeparator . value , '' )
320
+ . replace ( decimalSeparator . value , '.' )
321
+ )
319
322
if ( actualText && ! isNaN ( parsedValue ) ) {
320
323
inputText . value = correctPrecision ( clamp ( parsedValue , props . min , props . max ) )
321
324
} else {
0 commit comments