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: PinCodeProps = {}, ref: React.ForwardedRef) { 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: string]: 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: React.ChangeEvent, idx: number) { 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: React.KeyboardEvent, idx: number) { 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: React.FocusEvent) { setPlacehold(placeholder); onBlur(event); } function handleFocus(event: React.FocusEvent) { setPlacehold(''); onFocus(event); } return (
{[...values].map((val, key) => { const inpProps: InputProps = { 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 = ( { if (instance) { input[key] = instance; } }} {...inpProps} key={key} /> ); return child; })}
); } export default React.forwardRef(InternalPinCode);