react-native-otp-fields
Version:
A customizable React Native OTP input component with smooth focus handling, digit-only validation, and easy integration for verification codes, PINs, or passcodes.
73 lines (72 loc) • 2.81 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = OtpInput;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const react_native_1 = require("react-native");
;
function OtpInput({ length = 6, onOtpComplete, inputStyle, containerStyle, }) {
const [otp, setOtp] = (0, react_1.useState)(Array(length).fill(''));
const inputsRef = (0, react_1.useRef)([]);
const handleChangeText = (text, index) => {
var _a;
const newOtp = [...otp];
const char = text.slice(-1);
const digitRegex = /^\d$/;
if (digitRegex.test(char)) {
newOtp[index] = char;
setOtp(newOtp);
if (index < length - 1) {
(_a = inputsRef.current[index + 1]) === null || _a === void 0 ? void 0 : _a.focus();
}
if (newOtp.every(d => d !== '')) {
onOtpComplete === null || onOtpComplete === void 0 ? void 0 : onOtpComplete(newOtp.join(''));
}
}
else if (text === '') {
newOtp[index] = '';
setOtp(newOtp);
}
};
const handleKeyPress = ({ nativeEvent }, index) => {
if (nativeEvent.key === 'Backspace') {
setOtp((prevOtp) => {
var _a, _b;
const newOtp = [...prevOtp];
if (newOtp[index] === '') {
if (index > 0) {
newOtp[index - 1] = '';
(_a = inputsRef.current[index - 1]) === null || _a === void 0 ? void 0 : _a.focus();
}
}
else {
newOtp[index] = '';
(_b = inputsRef.current[index]) === null || _b === void 0 ? void 0 : _b.focus();
}
return newOtp;
});
}
};
return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.container, containerStyle], children: Array.from({ length }).map((_, i) => ((0, jsx_runtime_1.jsx)(react_native_1.TextInput, {
// @ts-ignore
ref: ref => (inputsRef.current[i] = ref), value: otp[i], onChangeText: text => handleChangeText(text, i), onKeyPress: e => handleKeyPress(e, i), keyboardType: "number-pad", maxLength: 1, style: [styles.input, inputStyle], returnKeyType: "done", autoFocus: i === 0 }, i))) }));
}
;
const styles = react_native_1.StyleSheet.create({
container: {
flexDirection: 'row',
gap: 12,
justifyContent: 'center',
padding: 20,
},
input: {
width: 48,
height: 58,
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 8,
textAlign: 'center',
fontSize: 20,
backgroundColor: '#fff',
},
});