payloadcms_otp_plugin
Version:
A comprehensive One-Time Password (OTP) authentication plugin for Payload CMS that enables secure passwordless authentication via SMS and email
87 lines (86 loc) • 3.21 kB
JavaScript
'use client';
import { jsx as _jsx } from "react/jsx-runtime";
import React, { useState, useRef } from 'react';
import './otp-view.scss';
const OTPInput = ({ length = 6, disabled = false, onComplete, onChange, className = '', value = '', onReset })=>{
const [otp, setOtp] = useState(()=>{
const initialOtp = value.split('').slice(0, length);
while(initialOtp.length < length){
initialOtp.push('');
}
return initialOtp;
});
const inputRefs = useRef([]);
// Note: We don't update the array when length changes dynamically
// to avoid state management issues. The parent component should
// handle ensuring the correct length is passed from the start.
// Reset OTP when onReset is called
React.useEffect(()=>{
if (onReset) {
const resetOtp = Array(length).fill('');
setOtp(resetOtp);
// Use setTimeout to ensure DOM is updated before focusing
setTimeout(()=>{
inputRefs.current[0]?.focus();
}, 0);
}
}, [
onReset,
length
]);
// Handle input change
const handleInputChange = (index, inputValue)=>{
if (disabled) return;
if (inputValue.length > 1) return;
// Only allow numeric input
if (inputValue && !/^\d$/.test(inputValue)) return;
const newOtp = [
...otp
];
newOtp[index] = inputValue;
setOtp(newOtp);
const otpString = newOtp.join('');
// Call onChange callback
onChange?.(otpString);
// Call onComplete if all digits are filled
if (otpString.length === length && !otpString.includes('')) {
onComplete?.(otpString);
}
// Auto-focus next input
if (inputValue && index < length - 1) {
inputRefs.current[index + 1]?.focus();
}
};
// Handle key down for backspace
const handleKeyDown = (index, e)=>{
if (disabled) return;
if (e.key === 'Backspace' && !otp[index] && index > 0) {
inputRefs.current[index - 1]?.focus();
}
};
return /*#__PURE__*/ _jsx("div", {
className: `otp-input ${className}`,
children: /*#__PURE__*/ _jsx("div", {
className: "otp-input__container",
children: otp.map((digit, index)=>/*#__PURE__*/ _jsx("input", {
ref: (el)=>{
if (el) {
inputRefs.current[index] = el;
}
},
type: "text",
inputMode: "numeric",
pattern: "\\d*",
maxLength: 1,
value: digit,
onChange: (e)=>handleInputChange(index, e.target.value),
onKeyDown: (e)=>handleKeyDown(index, e),
className: `otp-input__field ${disabled ? 'otp-input__field--disabled' : ''}`,
disabled: disabled,
"aria-label": `Digit ${index + 1} of ${length}`
}, index))
})
});
};
export default OTPInput;
//# sourceMappingURL=otp-input.js.map