@@ -35,6 +35,7 @@ import {
35
35
import { matchInputValue } from '@/utils/maskUtility/mask.utility' ;
36
36
37
37
import { limitValue } from './helpers/limitValue' ;
38
+ import { modifyInputNumberValue } from './helpers/modifyInputNumberValue' ;
38
39
import { ParamsTypeInputHook , ReturnTypeInputHook } from './types/inputHook' ;
39
40
40
41
export const useInput = ( props : ParamsTypeInputHook ) : ReturnTypeInputHook => {
@@ -128,17 +129,41 @@ export const useInput = (props: ParamsTypeInputHook): ReturnTypeInputHook => {
128
129
}
129
130
} , [ value ] ) ;
130
131
132
+ const truncateFloatValue = value => {
133
+ if ( value === '' ) {
134
+ return ;
135
+ }
136
+ const hasMark = value . match ( / [ ^ a - z A - Z 0 - 9 ] / g) ;
137
+
138
+ const isLastCharAMark =
139
+ hasMark &&
140
+ props . maxLength &&
141
+ value . length >= props . maxLength &&
142
+ value [ props . maxLength - 1 ] === hasMark [ 0 ] ;
143
+
144
+ return isLastCharAMark && props . type === InputTypeType . NUMBER
145
+ ? value . replace ( hasMark [ 0 ] , '' )
146
+ : value ;
147
+ } ;
148
+
131
149
const controlValue = value => {
132
150
// control character limit
133
151
const limitedValue = value && limitValue ( value , props . min , props . max , props . maxLength ) ;
134
152
135
153
// truncate the value with maximun of decimals
136
154
const truncateValue =
137
155
props . truncate && props . maxDecimals !== null && props . maxDecimals !== undefined
138
- ? truncatedValue ( String ( limitedValue ) , props . maxDecimals )
156
+ ? truncatedValue (
157
+ String ( limitedValue ) ,
158
+ props . maxDecimals ,
159
+ props . locale || props . formatNumber ?. locale
160
+ )
139
161
: limitedValue ;
140
- handleSetValue ( truncateValue ) ;
141
- return truncateValue ;
162
+
163
+ const valueTruncated = truncateFloatValue ( truncateValue ) ;
164
+
165
+ handleSetValue ( valueTruncated ) ;
166
+ return valueTruncated ;
142
167
} ;
143
168
144
169
// add thousand separator to the value
@@ -154,36 +179,42 @@ export const useInput = (props: ParamsTypeInputHook): ReturnTypeInputHook => {
154
179
} ;
155
180
156
181
const handleChangeInternal : React . ChangeEventHandler < HTMLInputElement > = event => {
182
+ let eventValue = event . target . value ;
157
183
// format value with the mask
158
184
if ( props . maskType ) {
159
- let newMaskedValue = cleanInputValue ( event . target . value , props . maskType ) ;
185
+ let newMaskedValue = cleanInputValue ( eventValue , props . maskType ) ;
160
186
if ( props . mask ) {
161
187
newMaskedValue = formatMask ( newMaskedValue , props . mask ) ;
162
188
}
163
- event . target . value = newMaskedValue ;
189
+ eventValue = newMaskedValue ;
164
190
} else if ( props . regex ) {
165
- const newMaskedValue = matchInputValue ( String ( value ) , event . target . value , props . regex ) ;
166
- event . target . value = newMaskedValue ;
167
- }
168
- if ( props . truncate && props . maxDecimals !== null && props . maxDecimals !== undefined ) {
169
- event . target . value = truncatedValue (
170
- String ( event . target . value ) ,
171
- props . maxDecimals ,
172
- props . locale || props . formatNumber ?. locale
173
- ) ;
191
+ const newMaskedValue = matchInputValue ( String ( value ) , eventValue , props . regex ) ;
192
+ eventValue = newMaskedValue ;
174
193
}
175
194
176
195
// key validation
177
196
if ( props . errorExecution === ERROR_EXECUTION . ON_CHANGE && props . keyValidation ) {
178
- props . onError ?.( ! validationValue ( props . keyValidation , event . target . value ) ) ;
197
+ props . onError ?.( ! validationValue ( props . keyValidation , eventValue ) ) ;
179
198
}
180
199
181
200
// limit or truncate the value
182
- const valueControlled = controlValue ( event . target . value ) ;
201
+ const valueControlled = controlValue ( eventValue ) ;
183
202
184
203
// check internal validations
185
204
if ( props . type !== InputTypeType . DATE ) {
186
- checkInternalValidations ( event . target . value ) ;
205
+ checkInternalValidations ( eventValue ) ;
206
+ }
207
+
208
+ if (
209
+ modifyInputNumberValue ( {
210
+ value : eventValue ,
211
+ min : props . min ,
212
+ max : props . max ,
213
+ maxLength : props . maxLength ,
214
+ } ) ||
215
+ props . type !== InputTypeType . NUMBER
216
+ ) {
217
+ event . target . value = valueControlled ;
187
218
}
188
219
189
220
// value = previous value
@@ -192,10 +223,6 @@ export const useInput = (props: ParamsTypeInputHook): ReturnTypeInputHook => {
192
223
return ;
193
224
}
194
225
195
- if ( props . type === InputTypeType . NUMBER ) {
196
- event . target . value = valueControlled ;
197
- }
198
-
199
226
props . onChange ?.( event ) ;
200
227
} ;
201
228
@@ -223,10 +250,14 @@ export const useInput = (props: ParamsTypeInputHook): ReturnTypeInputHook => {
223
250
handleSetValue ( event . target . value ) ;
224
251
}
225
252
// transform the string value to a number format with dot as decimal separator to avoid errors
226
- event . target . value = convertDecimalSeparator (
253
+ const decimalNumber = convertDecimalSeparator (
227
254
event . target . value ,
228
255
getDecimalSeparator ( props . locale || props . formatNumber ?. locale )
229
256
) ;
257
+
258
+ if ( ! isNaN ( parseFloat ( decimalNumber ) ) && isFinite ( parseFloat ( decimalNumber ) ) ) {
259
+ event . target . value = decimalNumber ;
260
+ }
230
261
props . onFocus ?.( event ) ;
231
262
setFocus ( true ) ;
232
263
} ;
0 commit comments