1
- import { useState } from "react" ;
1
+ import { useEffect , useState } from "react" ;
2
2
import {
3
3
OutlinedInput ,
4
4
OutlinedInputProps ,
@@ -8,12 +8,14 @@ import {
8
8
} from "@mui/material" ;
9
9
10
10
import "./NumberInput.scss" ;
11
- import { applyWhenNotNullable , getDefaultRequiredVal } from "../../../helpers/util" ;
11
+ import {
12
+ applyWhenNotNullable ,
13
+ getDefaultRequiredVal ,
14
+ } from "../../../helpers/util" ;
12
15
import { convertToNumberIfValid } from "../../../helpers/numeric/convertToNumberIfValid" ;
13
16
import { isNull , RequiredOrNull } from "../../../types/common" ;
14
17
15
- type NumberInputClassKey =
16
- "root" | "label" ;
18
+ type NumberInputClassKey = "root" | "label" ;
17
19
18
20
export interface NumberInputProps {
19
21
classes ?: Partial < Record < NumberInputClassKey , string > > ;
@@ -35,34 +37,56 @@ export const NumberInput = (props: NumberInputProps) => {
35
37
const helperMessages = getDefaultRequiredVal ( [ ] , props . helperText ?. messages ) ;
36
38
const errorMessages = getDefaultRequiredVal ( [ ] , props . helperText ?. errors ) ;
37
39
const helperTexts = [
38
- ...helperMessages . map ( message => ( {
40
+ ...helperMessages . map ( ( message ) => ( {
39
41
type : "message" ,
40
42
message,
41
43
} ) ) ,
42
- ...errorMessages . map ( message => ( {
44
+ ...errorMessages . map ( ( message ) => ( {
43
45
type : "error" ,
44
46
message,
45
47
} ) ) ,
46
48
] ;
47
49
48
- const { maskFn, onChange, onBlur, ...inputProps } = props . inputProps ;
50
+ const { maskFn, onChange, onBlur, ...inputProps } = props . inputProps ;
49
51
const inputSlotProps = inputProps . slotProps ?. input ;
52
+ const inputValue = inputProps . value ;
50
53
const initialValueDisplay = applyWhenNotNullable (
51
- ( num ) => maskFn ? maskFn ( num ) : `${ num } ` ,
52
- inputProps . value ,
54
+ ( num ) => ( maskFn ? maskFn ( num ) : `${ num } ` ) ,
55
+ inputValue ,
53
56
"" ,
54
57
) ;
55
58
56
59
const [ valueDisplay , setValueDisplay ] = useState < string > ( initialValueDisplay ) ;
57
60
61
+ useEffect ( ( ) => {
62
+ setValueDisplay (
63
+ applyWhenNotNullable (
64
+ ( num ) => ( maskFn ? maskFn ( num ) : `${ num } ` ) ,
65
+ inputValue ,
66
+ "" ,
67
+ ) ,
68
+ ) ;
69
+ } , [ inputValue ] ) ;
70
+
58
71
const handleChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
59
72
const updatedVal = e . target . value ;
73
+
74
+ // Allow clearing the input
75
+ if ( updatedVal === "" ) {
76
+ setValueDisplay ( updatedVal ) ;
77
+ onChange ?.( e ) ;
78
+ return ;
79
+ }
80
+
60
81
const numericVal = convertToNumberIfValid ( updatedVal , null ) ;
61
82
62
83
// If an invalid numeric string was inputted, do nothing
63
- if ( isNull ( numericVal ) ) return ;
84
+ if ( isNull ( numericVal ) ) {
85
+ return ;
86
+ }
64
87
65
88
// Otherwise display it without formatting it immediately (as that affects user's ability to input)
89
+
66
90
setValueDisplay ( updatedVal ) ;
67
91
onChange ?.( e ) ;
68
92
} ;
@@ -81,9 +105,7 @@ export const NumberInput = (props: NumberInputProps) => {
81
105
< FormControl
82
106
margin = "normal"
83
107
className = { `
84
- number-input ${
85
- props . classes ?. root ? props . classes . root : ""
86
- } ${
108
+ number-input ${ props . classes ?. root ? props . classes . root : "" } ${
87
109
errorMessages . length > 0 ? "number-input--error" : ""
88
110
}
89
111
` }
@@ -102,20 +124,18 @@ export const NumberInput = (props: NumberInputProps) => {
102
124
103
125
< OutlinedInput
104
126
{ ...inputProps }
105
- className = {
106
- `number-input__input ${
107
- inputProps . className ? inputProps . className : ""
108
- } `
109
- }
110
- type = "number"
127
+ className = { `number-input__input ${
128
+ inputProps . className ? inputProps . className : ""
129
+ } `}
130
+ type = "text"
111
131
value = { valueDisplay }
112
132
onChange = { handleChange }
113
133
onBlur = { handleBlur }
114
134
slotProps = { {
115
135
...inputProps . slotProps ,
116
136
input : {
117
137
...inputSlotProps ,
118
- type : "number " ,
138
+ type : "text " ,
119
139
} ,
120
140
} }
121
141
/>
0 commit comments