UNPKG

react-pin-field

Version:

React component for entering PIN codes

195 lines (194 loc) 6.18 kB
import { useRef as _, useReducer as R, useMemo as C, useCallback as B, forwardRef as I, useImperativeHandle as O, useEffect as m, createElement as q } from "react"; const k = 8, b = 46; function E() { } function H(s, e) { return Array.from({ length: e }, (t, u) => u + s); } function N(s) { try { return (s.webkitMatchesSelector || s.matches).call(s, ":focus"); } catch { return !1; } } const h = { length: 5, format: (s) => s, formatAriaLabel: (s, e) => `PIN field ${s} of ${e}`, onChange: E, onComplete: E }, V = { type: "text", inputMode: "text", autoCapitalize: "off", autoCorrect: "off", autoComplete: "off" }, Y = { length: h.length, format: h.format, dir: "ltr", cursor: 0, values: Array(h.length), backspace: !1, composition: !1, ready: !1, dirty: !1 }; function $(s, e) { switch (e.type) { case "update-props": { const t = { ...s, ...e.props }; return t.cursor = Math.min(t.cursor, t.length - 1), t.values = t.values.slice(0, t.cursor + 1), t.ready = !0, t; } case "start-composition": return { ...s, dirty: !0, composition: !0 }; case "end-composition": { const t = { ...s }; e.value ? t.values[e.index] = e.value : delete t.values[e.index]; const u = t.values[e.index] ? 1 : 0; return t.cursor = Math.min(e.index + u, t.length - 1), t.composition = !1, t.dirty = !0, t; } case "handle-change": { if (s.composition) break; const t = { ...s }; if (e.reset && t.values.splice(e.index, t.length), e.value) { const u = e.value.split("").map(t.format), i = Math.min(t.length - e.index, u.length); t.values.splice(e.index, i, ...u.slice(0, i)), t.cursor = Math.min(e.index + i, t.length - 1); } else { delete t.values[e.index]; const u = t.backspace ? 0 : 1; t.cursor = Math.max(0, e.index - u); } return t.backspace = !1, t.dirty = !0, t; } case "handle-key-down": { const t = e.key === "Backspace" || e.key === "Delete", u = e.code === "Backspace" || e.code === "Delete", i = e.keyCode === k || e.keyCode === b, p = e.which === k || e.which === b; if (!(t || u || i || p) || s.values[e.index]) break; { const c = { ...s }; return c.cursor = Math.max(0, e.index - 1), c.backspace = !0, c.dirty = !0, c; } } } return s; } function z() { const s = _([]), [e, t] = R($, Y), u = C(() => { let p = ""; for (let y = 0; y < e.length; y++) p += y in e.values ? e.values[y] : ""; return p; }, [e]), i = B( (p) => { t({ type: "handle-change", index: 0, value: p, reset: !0 }); }, [t, e.cursor] ); return C( () => ({ refs: s, state: e, dispatch: t, value: u, setValue: i }), [s, e, t, u, i] ); } const W = I( ({ length: s = h.length, format: e = h.format, formatAriaLabel: t = h.formatAriaLabel, onChange: u = h.onChange, onComplete: i = h.onComplete, handler: p, autoFocus: y, ...c }, w) => { const A = z(), { refs: f, state: r, dispatch: l } = p || A; O(w, () => f.current, [f]); function x(n) { return (o) => { o && (f.current[n] = o); }; } function M(n) { return (o) => { const { key: a, code: d, keyCode: g, which: F } = o; l({ type: "handle-key-down", index: n, key: a, code: d, keyCode: g, which: F }); }; } function D(n) { return (o) => { if (o.nativeEvent instanceof InputEvent) { const a = o.nativeEvent.data; l({ type: "handle-change", index: n, value: a }); } else { const { value: a } = o.target; l({ type: "handle-change", index: n, value: a, reset: !0 }); } }; } function K(n) { return () => { l({ type: "start-composition", index: n }); }; } function L(n) { return (o) => { l({ type: "end-composition", index: n, value: o.data }); }; } if (m(() => { var o, a; if (r.ready) return; const n = ((o = c.dir) == null ? void 0 : o.toLowerCase()) || ((a = document.documentElement.getAttribute("dir")) == null ? void 0 : a.toLowerCase()); l({ type: "update-props", props: { length: s, format: e, dir: n } }); }, [r.ready, l, s, e]), m(() => { r.ready && s !== r.length && l({ type: "update-props", props: { length: s } }); }, [r.ready, s, r.length, l]), m(() => { r.ready && e !== r.format && l({ type: "update-props", props: { format: e } }); }, [r.ready, e, r.format, l]), m(() => { var o, a; if (!r.ready) return; const n = ((o = c.dir) == null ? void 0 : o.toLowerCase()) || ((a = document.documentElement.getAttribute("dir")) == null ? void 0 : a.toLowerCase()); n !== r.dir && l({ type: "update-props", props: { dir: n } }); }, [r.ready, c.dir, r.dir, l]), m(() => { if (!f.current || !r.ready || !r.dirty) return; let n = !1, o = r.values.length == r.length, a = ""; for (let d = 0; d < r.length; d++) { const g = d in r.values ? r.values[d] : ""; f.current[d].value = g, n = n || N(f.current[d]), o = o && d in r.values && f.current[d].checkValidity(), a += g; } n && f.current[r.cursor].focus(), u && u(a), i && o && i(a); }, [f, r, u, i]), !r.ready) return null; const v = H(0, r.length).map((n) => /* @__PURE__ */ q( "input", { ...V, ...c, key: n, ref: x(n), value: n in r.values ? r.values[n] : "", autoFocus: n === 0 && y, onKeyDown: M(n), onChange: D(n), onCompositionStart: K(n), onCompositionEnd: L(n), "aria-label": t(n + 1, r.length), "aria-required": c.required ? "true" : void 0, "aria-disabled": c.disabled ? "true" : void 0, "aria-readonly": c.readOnly ? "true" : void 0 } )); return r.dir === "rtl" && v.reverse(), v; } ); export { W as default, V as defaultNativeProps, h as defaultProps, Y as defaultState, $ as reducer, z as usePinField }; //# sourceMappingURL=react-pin-field.js.map