@@ -85,11 +85,10 @@ class SingleOtpInput extends PureComponent<*> {
8585 ...rest
8686 } = this . props ;
8787
88- const numValueLimits = isInputNum ? { min : 0 , max : 9 } : { } ;
89-
9088 return (
9189 < div style = { { display : 'flex' , alignItems : 'center' } } >
9290 < input
91+ autoComplete = "off"
9392 style = { Object . assign (
9493 { width : '1em' , textAlign : 'center' } ,
9594 isStyleObject ( inputStyle ) && inputStyle ,
@@ -103,8 +102,7 @@ class SingleOtpInput extends PureComponent<*> {
103102 isDisabled && disabledStyle ,
104103 hasErrored && errorStyle
105104 ) }
106- type = { isInputNum ? 'number' : 'tel' }
107- { ...numValueLimits }
105+ type = { isInputNum ? 'tel' : 'text' }
108106 maxLength = "1"
109107 ref = { input => {
110108 this . input = input ;
@@ -137,11 +135,20 @@ class OtpInput extends Component<Props, State> {
137135
138136 // Helper to return OTP from input
139137 handleOtpChange = ( otp : string [ ] ) => {
140- const { onChange, isInputNum } = this . props ;
138+ const { onChange } = this . props ;
141139 const otpValue = otp . join ( '' ) ;
140+
142141 onChange ( otpValue ) ;
143142 } ;
144143
144+ isInputValueValid = value => {
145+ const isTypeValid = this . props . isInputNum
146+ ? ! isNaN ( parseInt ( value , 10 ) )
147+ : typeof value === 'string' ;
148+
149+ return isTypeValid && value . trim ( ) . length === 1 ;
150+ } ;
151+
145152 // Focus on input by index
146153 focusInput = ( input : number ) => {
147154 const { numInputs } = this . props ;
@@ -195,7 +202,11 @@ class OtpInput extends Component<Props, State> {
195202 } ;
196203
197204 handleOnChange = ( e : Object ) => {
198- this . changeCodeAtFocus ( e . target . value ) ;
205+ const { value } = e . target ;
206+
207+ if ( this . isInputValueValid ( value ) ) {
208+ this . changeCodeAtFocus ( value ) ;
209+ }
199210 } ;
200211
201212 // Handle cases of backspace, delete, left arrow, right arrow, space
@@ -216,21 +227,32 @@ class OtpInput extends Component<Props, State> {
216227 } else if (
217228 e . keyCode === SPACEBAR ||
218229 e . key === ' ' ||
219- e . key === 'Spacebar'
230+ e . key === 'Spacebar' ||
231+ e . key === 'Space'
220232 ) {
221233 e . preventDefault ( ) ;
222234 }
223235 } ;
224236
225237 // The content may not have changed, but some input took place hence change the focus
226- handleInput = ( e : Object ) => {
227- this . focusNextInput ( ) ;
228- }
229-
230- checkLength = ( e : Object ) => {
231- if ( e . target . value . length > 1 ) {
232- e . preventDefault ( ) ;
238+ handleOnInput = ( e : Object ) => {
239+ if ( this . isInputValueValid ( e . target . value ) ) {
233240 this . focusNextInput ( ) ;
241+ } else {
242+ // This is a workaround for dealing with keyCode "229 Unidentified" on Android.
243+
244+ if ( ! this . props . isInputNum ) {
245+ const { nativeEvent } = e ;
246+
247+ if (
248+ nativeEvent . data === null &&
249+ nativeEvent . inputType === 'deleteContentBackward'
250+ ) {
251+ e . preventDefault ( ) ;
252+ this . changeCodeAtFocus ( '' ) ;
253+ this . focusPrevInput ( ) ;
254+ }
255+ }
234256 }
235257 } ;
236258
@@ -259,7 +281,7 @@ class OtpInput extends Component<Props, State> {
259281 value = { otp && otp [ i ] }
260282 onChange = { this . handleOnChange }
261283 onKeyDown = { this . handleOnKeyDown }
262- onInput = { this . handleInput }
284+ onInput = { this . handleOnInput }
263285 onPaste = { this . handleOnPaste }
264286 onFocus = { e => {
265287 this . setState ( { activeInput : i } ) ;
0 commit comments