@turnkey/react-wallet-kit
Version:
The easiest and most powerful way to integrate Turnkey's Embedded Wallets into your React applications.
289 lines (286 loc) • 11.6 kB
JavaScript
import { slicedToArray as _slicedToArray, asyncToGenerator as _asyncToGenerator, toConsumableArray as _toConsumableArray, regeneratorRuntime as _regeneratorRuntime } from '../../_virtual/_rollupPluginBabelHelpers.mjs';
import { jsxs, jsx } from 'react/jsx-runtime';
import { useState, useRef } from 'react';
import { useModal } from '../../providers/modal/Hook.mjs';
import { useTurnkey } from '../../providers/client/Hook.mjs';
import { Spinner } from '../design/Spinners.mjs';
import { Input } from '@headlessui/react';
import { BaseButton } from '../design/Buttons.mjs';
import { OtpType } from '@turnkey/core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faEnvelope, faPhone } from '@fortawesome/free-solid-svg-icons';
import clsx from 'clsx';
function OtpVerification(props) {
var contact = props.contact,
otpType = props.otpType,
_props$otpLength = props.otpLength,
otpLength = _props$otpLength === void 0 ? 6 : _props$otpLength,
_props$alphanumeric = props.alphanumeric,
alphanumeric = _props$alphanumeric === void 0 ? true : _props$alphanumeric,
formattedContact = props.formattedContact,
_props$onContinue = props.onContinue,
onContinue = _props$onContinue === void 0 ? null : _props$onContinue;
var _useTurnkey = useTurnkey(),
initOtp = _useTurnkey.initOtp,
completeOtp = _useTurnkey.completeOtp;
var _useModal = useModal(),
closeModal = _useModal.closeModal,
isMobile = _useModal.isMobile;
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
submitting = _useState2[0],
setSubmitting = _useState2[1];
var _useState3 = useState(false),
_useState4 = _slicedToArray(_useState3, 2),
resending = _useState4[0],
setResending = _useState4[1];
var _useState5 = useState(false),
_useState6 = _slicedToArray(_useState5, 2),
resent = _useState6[0],
setResent = _useState6[1];
var _useState7 = useState(props.otpId),
_useState8 = _slicedToArray(_useState7, 2),
otpId = _useState8[0],
setOtpId = _useState8[1];
var _useState9 = useState(null),
_useState0 = _slicedToArray(_useState9, 2),
error = _useState0[0],
setError = _useState0[1];
var _useState1 = useState(false),
_useState10 = _slicedToArray(_useState1, 2),
shaking = _useState10[0],
setShaking = _useState10[1];
var shakeInput = function shakeInput() {
setShaking(true);
setTimeout(function () {
return setShaking(false);
}, 250);
};
var handleContinue = /*#__PURE__*/function () {
var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(otpCode) {
var niceError;
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
setSubmitting(true);
if (!onContinue) {
_context.next = 7;
break;
}
_context.next = 5;
return onContinue(otpCode);
case 5:
_context.next = 10;
break;
case 7:
_context.next = 9;
return completeOtp({
otpId: otpId,
otpCode: otpCode,
contact: contact,
otpType: otpType
});
case 9:
closeModal();
case 10:
_context.next = 18;
break;
case 12:
_context.prev = 12;
_context.t0 = _context["catch"](0);
niceError = _context.t0.message.includes("Invalid OTP") ? "Invalid OTP code" : "An error has occurred"; // eek! maybe this is bad!
setError(niceError);
shakeInput();
throw new Error("Error completing OTP: ".concat(_context.t0));
case 18:
_context.prev = 18;
setSubmitting(false);
return _context.finish(18);
case 21:
case "end":
return _context.stop();
}
}, _callee, null, [[0, 12, 18, 21]]);
}));
return function handleContinue(_x) {
return _ref.apply(this, arguments);
};
}();
var handleResend = /*#__PURE__*/function () {
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
var id;
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
setResending(true);
_context2.prev = 1;
_context2.next = 4;
return initOtp({
otpType: otpType,
contact: contact
});
case 4:
id = _context2.sent;
setOtpId(id);
setResent(true);
_context2.next = 12;
break;
case 9:
_context2.prev = 9;
_context2.t0 = _context2["catch"](1);
throw new Error("Error resending OTP: ".concat(_context2.t0));
case 12:
_context2.prev = 12;
setResending(false);
return _context2.finish(12);
case 15:
case "end":
return _context2.stop();
}
}, _callee2, null, [[1, 9, 12, 15]]);
}));
return function handleResend() {
return _ref2.apply(this, arguments);
};
}();
return jsxs("div", {
className: clsx("flex items-center justify-center py-3", isMobile ? "w-full" : "min-w-96"),
children: [jsxs("div", {
className: "flex flex-col items-center justify-center gap-6 transition-all duration-300 ".concat(submitting && "opacity-30 blur"),
children: [jsx(FontAwesomeIcon, {
size: "3x",
icon: otpType === OtpType.Email ? faEnvelope : otpType === OtpType.Sms ? faPhone : faEnvelope
}), jsxs("div", {
className: "flex flex-col text-center",
children: [jsx("span", {
className: "text-lg font-medium",
children: "Enter the ".concat(otpLength, "-digit code we sent to")
}), jsx("span", {
className: "text-base font-semibold",
children: formattedContact !== null && formattedContact !== void 0 ? formattedContact : contact
})]
}), jsx("div", {
className: "transition-all flex justify-center ".concat(shaking ? "animate-shake" : ""),
children: jsx(OtpInput, {
otpLength: otpLength,
onContinue: handleContinue,
alphanumeric: alphanumeric
})
}), error && jsx("div", {
className: "text-red-400 text-center text-sm",
children: error
}), jsx(BaseButton, {
onClick: handleResend,
disabled: resending || resent,
className: "text-xs text-inherit font-semibold bg-transparent border-none ".concat(resent && "opacity-30"),
children: resending ? jsxs("span", {
className: "flex items-center gap-2.5",
children: [jsx(Spinner, {
className: "size-3"
}), "Resending..."]
}) : resent ? "Code sent!" : "Resend Code"
})]
}), submitting && jsx("div", {
className: "absolute flex w-full h-full justify-center items-center",
children: jsx(Spinner, {
strokeWidth: 1,
className: "size-1/2"
})
})]
});
}
function OtpInput(props) {
var otpLength = props.otpLength,
onContinue = props.onContinue,
_props$alphanumeric2 = props.alphanumeric,
alphanumeric = _props$alphanumeric2 === void 0 ? false : _props$alphanumeric2;
var _useModal2 = useModal(),
isMobile = _useModal2.isMobile;
var _useState11 = useState(Array(otpLength).fill("")),
_useState12 = _slicedToArray(_useState11, 2),
values = _useState12[0],
setValues = _useState12[1];
var inputsRef = useRef([]);
var handleChange = function handleChange(index, value) {
if (!alphanumeric) value = value.replace(/[^0-9]/g, "");else value = value.replace(/[^a-zA-Z0-9]/g, "");
var newValues = _toConsumableArray(values);
newValues[index] = value.slice(-1); // only last char
setValues(newValues);
if (value && index < otpLength - 1) {
var _inputsRef$current;
(_inputsRef$current = inputsRef.current[index + 1]) === null || _inputsRef$current === void 0 ? void 0 : _inputsRef$current.focus();
}
if (value && newValues.every(function (v) {
return v;
})) {
onContinue(newValues.join(""));
}
};
var handleKeyDown = function handleKeyDown(e, index) {
if (e.key === "Backspace" && !values[index] && index > 0) {
var _inputsRef$current2;
(_inputsRef$current2 = inputsRef.current[index - 1]) === null || _inputsRef$current2 === void 0 ? void 0 : _inputsRef$current2.focus();
}
if (e.key === "ArrowLeft" && index > 0) {
var _inputsRef$current3;
(_inputsRef$current3 = inputsRef.current[index - 1]) === null || _inputsRef$current3 === void 0 ? void 0 : _inputsRef$current3.focus();
}
if (e.key === "ArrowRight" && index < otpLength - 1) {
var _inputsRef$current4;
(_inputsRef$current4 = inputsRef.current[index + 1]) === null || _inputsRef$current4 === void 0 ? void 0 : _inputsRef$current4.focus();
}
if (e.key === "Enter") {
onContinue(values.join(""));
}
};
var handlePaste = function handlePaste(e) {
var _inputsRef$current$la;
e.preventDefault();
var paste = e.clipboardData.getData("text").trim();
var cleaned = alphanumeric ? paste.replace(/[^a-zA-Z0-9]/g, "") : paste.replace(/[^0-9]/g, "");
var sliced = cleaned.slice(0, otpLength).split("");
var newValues = _toConsumableArray(values);
for (var i = 0; i < sliced.length; i++) {
var _sliced$i;
newValues[i] = (_sliced$i = sliced[i]) !== null && _sliced$i !== void 0 ? _sliced$i : "";
if (inputsRef.current[i]) {
var _sliced$i2;
inputsRef.current[i].value = (_sliced$i2 = sliced[i]) !== null && _sliced$i2 !== void 0 ? _sliced$i2 : "";
}
}
setValues(newValues);
// Focus the last filled box
var lastIndex = Math.min(sliced.length, otpLength - 1);
(_inputsRef$current$la = inputsRef.current[lastIndex]) === null || _inputsRef$current$la === void 0 ? void 0 : _inputsRef$current$la.focus();
onContinue(newValues.join(""));
};
return jsx("div", {
className: clsx("flex items-center justify-center space-x-2", isMobile ? "w-[95%]" : "w-full"),
children: Array.from({
length: otpLength
}).map(function (_, i) {
var _values$i;
return jsx(Input, {
type: alphanumeric ? "text" : "text",
inputMode: alphanumeric ? "text" : "numeric",
maxLength: 1,
value: (_values$i = values[i]) === null || _values$i === void 0 ? void 0 : _values$i.toUpperCase(),
autoComplete: "off",
onChange: function onChange(e) {
return handleChange(i, e.target.value.toUpperCase());
},
onKeyDown: function onKeyDown(e) {
return handleKeyDown(e, i);
},
onPaste: handlePaste,
ref: function ref(el) {
return inputsRef.current[i] = el;
},
className: clsx("text-center text-lg rounded-md border border-modal-background-dark/20 dark:border-modal-background-light/20 bg-button-light dark:bg-button-dark text-inherit focus:outline-primary-light focus:dark:outline-primary-dark focus:outline-[1px] focus:outline-offset-0 transition-all", isMobile ? "w-full h-10" : "h-12 w-12")
}, i);
})
});
}
export { OtpInput, OtpVerification };
//# sourceMappingURL=OTP.mjs.map