mui-one-time-password-input
Version:
A One-Time Password input designed for the React library MUI
213 lines (212 loc) • 5.79 kB
JavaScript
import { jsx as R } from "react/jsx-runtime";
import g from "react";
import { styled as W } from "@mui/material/styles";
import q from "@mui/material/TextField";
import z from "@mui/material/Box";
const G = W(q)`
input {
text-align: center;
}
`, J = {
TextFieldStyled: G
}, Q = (n) => /* @__PURE__ */ R(J.TextFieldStyled, { ...n }), D = {
left: "ArrowLeft",
right: "ArrowRight",
backspace: "Backspace",
home: "Home",
end: "End"
};
function U(n, s) {
return n <= 0 ? [] : Array.from({ length: n }, s);
}
function X(n, s, l) {
return n.map((i, F) => s === F ? l : i);
}
function P(n) {
return n.join("");
}
function M(n, s) {
return [...n, s];
}
function Z(n, s, l) {
return n.reduce(
(i, F, C) => {
const { characters: y, restArrayMerged: d } = i;
if (C < l)
return {
restArrayMerged: d,
characters: M(y, F)
};
const [V, ...E] = d;
return {
restArrayMerged: E,
characters: M(y, V || "")
};
},
{
restArrayMerged: s,
characters: []
}
).characters;
}
function v(n) {
return (s) => {
n.forEach((l) => {
typeof l == "function" ? l(s) : l != null && (l.current = s);
});
};
}
function ee(n) {
return n.split("");
}
function N(n) {
const s = g.useRef(() => {
throw new Error("Cannot call an event handler while rendering.");
});
return g.useInsertionEffect(() => {
s.current = n;
}), g.useCallback((...l) => s.current?.(...l), []);
}
const te = () => !0, le = g.forwardRef(
(n, s) => {
const {
value: l = "",
length: i = 4,
autoFocus: F = !1,
onChange: C,
TextFieldsProps: y,
onComplete: d,
validateChar: V = te,
className: E,
onBlur: b,
...K
} = n, j = g.useRef(l), w = N(d), I = N((e) => {
const t = e.slice(0, i);
return {
isCompleted: t.length === i,
finalValue: t
};
});
g.useEffect(() => {
const { isCompleted: e, finalValue: t } = I(
j.current
);
e && w(t);
}, [i, w, I]);
const p = U(
i,
(e, t) => ({
character: l[t] || "",
inputRef: g.createRef()
})
), T = (e) => p.findIndex(({ inputRef: t }) => t.current === e), k = () => p.map(({ character: e }) => e), A = (e, t) => {
const r = X(
k(),
e,
t
);
return P(r);
}, $ = (e) => {
p[e]?.inputRef.current?.focus();
}, c = (e) => {
p[e]?.inputRef.current?.select();
}, O = (e) => {
e + 1 !== i && (p[e + 1].character ? c(e + 1) : $(e + 1));
}, S = (e, t) => typeof V != "function" ? !0 : V(e, t), Y = (e) => {
const t = T(e.target);
if (t === 0 && e.target.value.length > 1) {
const { finalValue: m, isCompleted: B } = I(
e.target.value
);
C?.(m), B && d?.(m), c(m.length - 1);
return;
}
const r = e.target.value[0] || "";
let u = r;
u && !S(u, t) && (u = "");
const a = A(t, u);
C?.(a);
const { isCompleted: h, finalValue: f } = I(a);
h && d?.(f), u !== "" ? a.length - 1 < t ? c(a.length) : O(t) : r === "" && a.length <= t && c(t - 1);
}, _ = (e) => {
const t = e.target, r = t.selectionStart, u = t.selectionEnd, a = T(t), h = r === 0 && u === 0;
if (t.value === e.key)
e.preventDefault(), O(a);
else if (D.backspace === e.key) {
if (!t.value)
e.preventDefault(), c(a - 1);
else if (h) {
e.preventDefault();
const f = A(a, "");
C?.(f), f.length <= a && c(a - 1);
}
} else D.left === e.key ? (e.preventDefault(), c(a - 1)) : D.right === e.key ? (e.preventDefault(), c(a + 1)) : D.home === e.key ? (e.preventDefault(), c(0)) : D.end === e.key && (e.preventDefault(), c(p.length - 1));
}, H = (e) => {
const t = e.clipboardData.getData("text/plain"), r = e.target, u = p.findIndex(
({ character: x, inputRef: o }) => x === "" || o.current === r
), a = k(), h = Z(
a,
ee(t),
u
).map((x, o) => S(x, o) ? x : ""), f = P(h);
C?.(f);
const { isCompleted: m, finalValue: B } = I(f);
m ? (d?.(B), c(i - 1)) : c(f.length);
}, L = (e) => {
if (!p.some(({ inputRef: r }) => r.current === e.relatedTarget)) {
const { isCompleted: r, finalValue: u } = I(l);
b?.(u, r);
}
};
return /* @__PURE__ */ R(
z,
{
display: "flex",
gap: "20px",
alignItems: "center",
ref: s,
className: `MuiOtpInput-Box ${E || ""}`,
...K,
children: p.map(({ character: e, inputRef: t }, r) => {
const {
onPaste: u,
onFocus: a,
onKeyDown: h,
className: f,
onBlur: m,
inputRef: B,
...x
} = typeof y == "function" ? y(r) || {} : y || {};
return /* @__PURE__ */ R(
Q,
{
autoFocus: F ? r === 0 : !1,
autoComplete: "one-time-code",
value: e,
inputRef: v([t, B]),
className: `MuiOtpInput-TextField MuiOtpInput-TextField-${r + 1} ${f || ""}`,
onPaste: (o) => {
o.preventDefault(), H(o), u?.(o);
},
onFocus: (o) => {
o.preventDefault(), o.target.select(), a?.(o);
},
onChange: Y,
onKeyDown: (o) => {
_(o), h?.(o);
},
onBlur: (o) => {
m?.(o), L(o);
},
...x
},
r
);
})
}
);
}
);
export {
le as MuiOtpInput
};