fix: show number keyboard in mobile in otp forms
This commit is contained in:
@@ -25,6 +25,10 @@ const DigitInput: React.FC<DigitInputProps> = ({
|
|||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
const inputRefs = useRef<Array<HTMLInputElement | null>>([]);
|
const inputRefs = useRef<Array<HTMLInputElement | null>>([]);
|
||||||
|
|
||||||
|
const isMobile =
|
||||||
|
typeof navigator !== 'undefined' &&
|
||||||
|
/Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
inputRefs.current[0]?.focus();
|
inputRefs.current[0]?.focus();
|
||||||
}, []);
|
}, []);
|
||||||
@@ -44,7 +48,7 @@ const DigitInput: React.FC<DigitInputProps> = ({
|
|||||||
setCode(newCode);
|
setCode(newCode);
|
||||||
handleDigitInputValueChange(newCode);
|
handleDigitInputValueChange(newCode);
|
||||||
|
|
||||||
if (value && index < 4 - 1) {
|
if (value && index < newCode.length - 1) {
|
||||||
inputRefs.current[index + 1]?.focus();
|
inputRefs.current[index + 1]?.focus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -53,37 +57,33 @@ const DigitInput: React.FC<DigitInputProps> = ({
|
|||||||
event: KeyboardEvent<HTMLDivElement>,
|
event: KeyboardEvent<HTMLDivElement>,
|
||||||
index: number,
|
index: number,
|
||||||
) => {
|
) => {
|
||||||
|
if (event.key === 'Backspace' && code[index]) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (index >= 0) {
|
|
||||||
handleChange('', index);
|
handleChange('', index);
|
||||||
inputRefs.current[index - 1]?.focus();
|
if (index > 0) inputRefs.current[index - 1]?.focus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePaste = (event: React.ClipboardEvent) => {
|
const handlePaste = (event: React.ClipboardEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const pastedData = event.clipboardData.getData('text').replace(/\D/g, ''); // Remove non-digit characters
|
const pastedData = event.clipboardData.getData('text').replace(/\D/g, '');
|
||||||
const newCode = [...code];
|
const newCode = [...code];
|
||||||
|
|
||||||
pastedData.split('').forEach((digit, i) => {
|
pastedData.split('').forEach((digit, i) => {
|
||||||
if (i < code.length) {
|
if (i < newCode.length) newCode[i] = digit;
|
||||||
newCode[i] = digit;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setCode(newCode);
|
setCode(newCode);
|
||||||
handleDigitInputValueChange(newCode);
|
handleDigitInputValueChange(newCode);
|
||||||
|
|
||||||
// Focus the next empty input after the last pasted character
|
const nextEmpty = newCode.findIndex((d) => d === '');
|
||||||
const lastIndex = Math.min(pastedData.length, code.length) - 1;
|
const focusIndex = nextEmpty === -1 ? newCode.length - 1 : nextEmpty;
|
||||||
if (lastIndex >= 0 && inputRefs.current[lastIndex]) {
|
inputRefs.current[focusIndex]?.focus();
|
||||||
inputRefs.current[lastIndex]?.focus();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
direction={i18n.dir() == 'ltr' ? 'row' : 'row-reverse'}
|
direction={i18n.dir() === 'ltr' ? 'row' : 'row-reverse'}
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
sx={{ gap: 2, width: '100%', my: 4 }}
|
sx={{ gap: 2, width: '100%', my: 4 }}
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
@@ -97,11 +97,18 @@ const DigitInput: React.FC<DigitInputProps> = ({
|
|||||||
autoFocus={index === 0}
|
autoFocus={index === 0}
|
||||||
value={digit}
|
value={digit}
|
||||||
onChange={(e) => handleChange(e.target.value, index)}
|
onChange={(e) => handleChange(e.target.value, index)}
|
||||||
onKeyDown={(e) => e.key === 'Backspace' && handleBackspace(e, index)}
|
onKeyDown={(e) => handleBackspace(e, index)}
|
||||||
onPaste={(e) => handlePaste(e)}
|
onPaste={handlePaste}
|
||||||
|
type={isMobile ? 'tel' : 'text'}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
htmlInput: {
|
htmlInput: {
|
||||||
maxLength: 1,
|
maxLength: 1,
|
||||||
|
inputMode: isMobile ? 'numeric' : undefined,
|
||||||
|
pattern: isMobile ? '[0-9]*' : undefined,
|
||||||
|
autoComplete: 'one-time-code',
|
||||||
|
name: 'one-time-code',
|
||||||
|
enterKeyHint: 'done',
|
||||||
|
dir: 'ltr',
|
||||||
sx: {
|
sx: {
|
||||||
height: '72px',
|
height: '72px',
|
||||||
color: error
|
color: error
|
||||||
|
|||||||
Reference in New Issue
Block a user