mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-15 08:59:15 +08:00
100fa29bef
* chore: basic control * chore: input instad * docs: update demo * chore: adjust operation interactive * chore: lock selection * chore: fix patch logic * chore: merge logic * chore: patch autoFocus * test: update snapshot * test: add test case * test: coverage * chore: update size limit * docs: update docs * test: fix test case * chore: update comment * refactor: change to length * chore: blur all * chore: size limit
70 lines
1.9 KiB
TypeScript
70 lines
1.9 KiB
TypeScript
import * as React from 'react';
|
|
import raf from 'rc-util/lib/raf';
|
|
|
|
import Input, { type InputProps, type 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;
|