import React , { useEffect , useState } from 'react' ; import { IProps , noop } from '@uiw/utils' ; import Input , { InputProps } from '@uiw/react-input' ; import './style/input.less' ; export interface PinCodeProps extends IProps { value ? : string [ ] ; disabled ? : boolean ; onChange ? : ( value : string [ ] ) => void ; onBlur ? : InputProps < { } > [ 'onBlur' ] ; onFocus ? : InputProps < { } > [ 'onFocus' ] ; autoFocus ? : boolean ; size ? : InputProps < { } > [ 'size' ] ; placeholder ? : string ; } function InternalPinCode ( props = { } , ref ) { const { prefixCls = 'w-pin-code' , placeholder = '○' , value = [ ] , autoFocus , className , size = 'default' , style , disabled , onChange = noop , onBlur = noop , onFocus = noop , ... otherProps } = props ; const [ input ] = useState < { [ key ] : HTMLInputElement ; } > ( { } ) ; const [ placehold , setPlacehold ] = useState ( placeholder ) ; const [ values , setValues ] = useState ( value ) ; const cls = [ prefixCls , className , size ? `${ prefixCls }-${ size }` : null , disabled ? 'disabled' : null ] . filter ( Boolean ) . join ( ' ' ) . trim ( ) ; function handleChange ( e , idx ) { let val = e . target . value ; val = val . charAt ( val . length - 1 ) ; const arr = [ ... values ] ; if ( Number ( val ) > - 1 && val ) { e . currentTarget . value = val ; arr [ idx ] = val ; if ( input [ idx + 1 ] ) { input [ idx + 1 ] . focus ( ) ; } setValues ( arr ) ; } else if ( ! val ) { arr [ idx ] = '' ; setValues ( arr ) ; } } function handleKeyDown ( e , idx ) { let val = e . currentTarget . value ; const key = e . key . toLocaleLowerCase ( ) ; if ( ! val && input [ idx - 1 ] && /(backspace|delete)/ . test ( key ) ) { input [ idx - 1 ] . focus ( ) ; } } useEffect ( ( ) => { if ( values !== value ) { onChange ( values ) ; } } , [ values ] ) ; function handleBlur ( event ) { setPlacehold ( placeholder ) ; onBlur ( event ) ; } function handleFocus ( event ) { setPlacehold ( '' ) ; onFocus ( event ) ; } return ( < div className = { cls } style = { style } { ... otherProps } ref = { ref } > { [ ... values ] . map ( ( val , key ) => { const inpProps = { min : 0 , type : 'text' , inputMode : 'numeric' , autoComplete : 'off' , value : val , onChange : ( e ) => handleChange ( e , key ) , onKeyDown : ( e ) => handleKeyDown ( e , key ) , onBlur : ( e ) => handleBlur ( e ) , onFocus : ( e ) => handleFocus ( e ) , className : `${ prefixCls }-inner` , placeholder : placehold , disabled , size , } ; if ( autoFocus && key === 0 ) { inpProps . autoFocus = true ; } const child = ( < Input ref = { ( instance ) => { if ( instance ) { input [ key ] = instance ; } } } { ... inpProps } key = { key } / > ) ; return child ; } ) } < /div>); } export default React . forwardRef < HTMLDivElement , PinCodeProps > ( InternalPinCode ) ;