ant-design/components/input/OTP/OTPInput.tsx
叶枫 502dac12aa
docs: format code (#48309)
* docs: fix code

* feat: lint

* feat: prettier

* feat: test

* feat: review

* feat: format html

* feat: format html
2024-04-08 14:04:08 +08:00

71 lines
2.0 KiB
TypeScript

import * as React from 'react';
import raf from 'rc-util/lib/raf';
import Input from '../Input';
import type { InputProps, InputRef } from '../Input';
export interface OTPInputProps extends Omit<InputProps, 'onChange'> {
index: number;
onChange: (index: number, value: string) => void;
/** Tell parent to do active offset */
onActiveChange: (nextIndex: number) => void;
}
const OTPInput = React.forwardRef<InputRef, OTPInputProps>((props, ref) => {
const { value, onChange, onActiveChange, index, ...restProps } = props;
const onInternalChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
onChange(index, e.target.value);
};
// ========================== Ref ===========================
const inputRef = React.useRef<InputRef>(null);
React.useImperativeHandle(ref, () => inputRef.current!);
// ========================= Focus ==========================
const syncSelection = () => {
raf(() => {
const inputEle = inputRef.current?.input;
if (document.activeElement === inputEle && inputEle) {
inputEle.select();
}
});
};
// ======================== Keyboard ========================
const onInternalKeyDown: React.KeyboardEventHandler<HTMLInputElement> = ({ key }) => {
if (key === 'ArrowLeft') {
onActiveChange(index - 1);
} else if (key === 'ArrowRight') {
onActiveChange(index + 1);
}
syncSelection();
};
const onInternalKeyUp: React.KeyboardEventHandler<HTMLInputElement> = (e) => {
if (e.key === 'Backspace' && !value) {
onActiveChange(index - 1);
}
syncSelection();
};
// ========================= Render =========================
return (
<Input
{...restProps}
ref={inputRef}
value={value}
onInput={onInternalChange}
onFocus={syncSelection}
onKeyDown={onInternalKeyDown}
onKeyUp={onInternalKeyUp}
onMouseDown={syncSelection}
onMouseUp={syncSelection}
/>
);
});
export default OTPInput;