@retinalabsllc/zairusjs 11.0.1 → 11.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +61 -94
- package/dist/index.mjs +59 -92
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -71,10 +71,15 @@ interface PipleAuthProps {
|
|
|
71
71
|
}) => Promise<{
|
|
72
72
|
success: boolean;
|
|
73
73
|
error?: string;
|
|
74
|
+
has2FA?: boolean;
|
|
75
|
+
hasPasskey?: boolean;
|
|
76
|
+
passkeyOptions?: any;
|
|
74
77
|
}>;
|
|
75
78
|
onVerifyOtp: (payload: {
|
|
76
79
|
email: string;
|
|
77
|
-
code
|
|
80
|
+
code?: string;
|
|
81
|
+
isPasskey?: boolean;
|
|
82
|
+
passkeyCredential?: any;
|
|
78
83
|
}) => Promise<{
|
|
79
84
|
success: boolean;
|
|
80
85
|
error?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -71,10 +71,15 @@ interface PipleAuthProps {
|
|
|
71
71
|
}) => Promise<{
|
|
72
72
|
success: boolean;
|
|
73
73
|
error?: string;
|
|
74
|
+
has2FA?: boolean;
|
|
75
|
+
hasPasskey?: boolean;
|
|
76
|
+
passkeyOptions?: any;
|
|
74
77
|
}>;
|
|
75
78
|
onVerifyOtp: (payload: {
|
|
76
79
|
email: string;
|
|
77
|
-
code
|
|
80
|
+
code?: string;
|
|
81
|
+
isPasskey?: boolean;
|
|
82
|
+
passkeyCredential?: any;
|
|
78
83
|
}) => Promise<{
|
|
79
84
|
success: boolean;
|
|
80
85
|
error?: string;
|
package/dist/index.js
CHANGED
|
@@ -369,6 +369,7 @@ var import_react6 = __toESM(require("react"));
|
|
|
369
369
|
var import_navigation2 = require("next/navigation");
|
|
370
370
|
var import_react_hot_toast = __toESM(require("react-hot-toast"));
|
|
371
371
|
var import_react_google_recaptcha_v3 = require("react-google-recaptcha-v3");
|
|
372
|
+
var import_browser = require("@simplewebauthn/browser");
|
|
372
373
|
var InputSpinner = () => /* @__PURE__ */ import_react6.default.createElement("svg", { className: "animate-spin h-4 w-4 text-neutral-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ import_react6.default.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ import_react6.default.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
373
374
|
function AuthFormInner({
|
|
374
375
|
companyName,
|
|
@@ -400,6 +401,9 @@ function AuthFormInner({
|
|
|
400
401
|
const [lastName, setLastName] = (0, import_react6.useState)("");
|
|
401
402
|
const [orgName, setOrgName] = (0, import_react6.useState)("");
|
|
402
403
|
const [agreedToTerms, setAgreedToTerms] = (0, import_react6.useState)(false);
|
|
404
|
+
const [userHas2FA, setUserHas2FA] = (0, import_react6.useState)(false);
|
|
405
|
+
const [userHasPasskey, setUserHasPasskey] = (0, import_react6.useState)(false);
|
|
406
|
+
const [authOptions, setAuthOptions] = (0, import_react6.useState)(null);
|
|
403
407
|
const [otp, setOtp] = (0, import_react6.useState)(["", "", "", "", "", ""]);
|
|
404
408
|
const inputRefs = (0, import_react6.useRef)([]);
|
|
405
409
|
const cleanAlpha = (val) => val.replace(/[^a-zA-Z\s-]/g, "");
|
|
@@ -417,9 +421,7 @@ function AuthFormInner({
|
|
|
417
421
|
const newOtp = [...otp];
|
|
418
422
|
newOtp[index] = cleanValue.slice(-1);
|
|
419
423
|
setOtp(newOtp);
|
|
420
|
-
if (cleanValue && index < 5)
|
|
421
|
-
inputRefs.current[index + 1]?.focus();
|
|
422
|
-
}
|
|
424
|
+
if (cleanValue && index < 5) inputRefs.current[index + 1]?.focus();
|
|
423
425
|
};
|
|
424
426
|
const handlePaste = (e) => {
|
|
425
427
|
e.preventDefault();
|
|
@@ -428,13 +430,10 @@ function AuthFormInner({
|
|
|
428
430
|
if (!numbersOnly) return;
|
|
429
431
|
const newOtp = [...otp];
|
|
430
432
|
const length = Math.min(numbersOnly.length, 6);
|
|
431
|
-
for (let i = 0; i < length; i++)
|
|
432
|
-
newOtp[i] = numbersOnly[i];
|
|
433
|
-
}
|
|
433
|
+
for (let i = 0; i < length; i++) newOtp[i] = numbersOnly[i];
|
|
434
434
|
setOtp(newOtp);
|
|
435
|
-
if (length < 6)
|
|
436
|
-
|
|
437
|
-
} else {
|
|
435
|
+
if (length < 6) inputRefs.current[length]?.focus();
|
|
436
|
+
else {
|
|
438
437
|
inputRefs.current[5]?.focus();
|
|
439
438
|
verifyOtpCode(newOtp.join(""));
|
|
440
439
|
}
|
|
@@ -461,7 +460,10 @@ function AuthFormInner({
|
|
|
461
460
|
recaptchaToken
|
|
462
461
|
});
|
|
463
462
|
if (res.success) {
|
|
464
|
-
|
|
463
|
+
setUserHas2FA(!!res.has2FA);
|
|
464
|
+
setUserHasPasskey(!!res.hasPasskey);
|
|
465
|
+
if (res.passkeyOptions) setAuthOptions(res.passkeyOptions);
|
|
466
|
+
import_react_hot_toast.default.success(res.has2FA ? "Security check required" : "Verification code sent");
|
|
465
467
|
setStep("OTP");
|
|
466
468
|
setCountdown(60);
|
|
467
469
|
} else {
|
|
@@ -491,6 +493,23 @@ function AuthFormInner({
|
|
|
491
493
|
setIsSubmitting(false);
|
|
492
494
|
}
|
|
493
495
|
};
|
|
496
|
+
const triggerPasskeyLogin = async () => {
|
|
497
|
+
if (!authOptions || isSubmitting) return;
|
|
498
|
+
setIsSubmitting(true);
|
|
499
|
+
try {
|
|
500
|
+
const credentialResponse = await (0, import_browser.startAuthentication)({ optionsJSON: authOptions });
|
|
501
|
+
const res = await onVerifyOtp({ email: emailId, isPasskey: true, passkeyCredential: credentialResponse });
|
|
502
|
+
if (res.success) {
|
|
503
|
+
window.location.href = res.redirect || redirectUrl;
|
|
504
|
+
} else {
|
|
505
|
+
import_react_hot_toast.default.error(res.error || "Device verification failed.");
|
|
506
|
+
}
|
|
507
|
+
} catch (err) {
|
|
508
|
+
if (err.name !== "NotAllowedError") import_react_hot_toast.default.error("Passkey verification interrupted.");
|
|
509
|
+
} finally {
|
|
510
|
+
setIsSubmitting(false);
|
|
511
|
+
}
|
|
512
|
+
};
|
|
494
513
|
const handleNextSignupStep = () => {
|
|
495
514
|
if (signupStep === "NAME") {
|
|
496
515
|
if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
@@ -509,7 +528,7 @@ function AuthFormInner({
|
|
|
509
528
|
}
|
|
510
529
|
return false;
|
|
511
530
|
};
|
|
512
|
-
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full max-w-md mx-auto flex flex-col items-center gap-4 relative z-10 animate-in fade-in duration-300" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "p-8 md:p-12" }, step === "INPUT" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "mb-12 text-center mt-2" }, /* @__PURE__ */ import_react6.default.createElement("h2", { className: "
|
|
531
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full max-w-md mx-auto flex flex-col items-center gap-4 relative z-10 animate-in fade-in duration-300" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "p-8 md:p-12" }, step === "INPUT" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "mb-12 text-center mt-2" }, /* @__PURE__ */ import_react6.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, mode === "LOGIN" ? `${companyName} ${workspaceLabel}` : "Create Account"), /* @__PURE__ */ import_react6.default.createElement("div", { className: "text-[13px] text-neutral-500" }, mode === "LOGIN" ? /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, "Don't have an account? ", /* @__PURE__ */ import_react6.default.createElement("button", { type: "button", onClick: () => {
|
|
513
532
|
setMode("SIGNUP");
|
|
514
533
|
setSignupStep(getInitialSignupStep());
|
|
515
534
|
}, className: "text-black transition-colors ml-1" }, "Sign up")) : /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, "Already have an account? ", /* @__PURE__ */ import_react6.default.createElement("button", { type: "button", onClick: () => setMode("LOGIN"), className: "text-black transition-colors ml-1" }, "Log in")))), /* @__PURE__ */ import_react6.default.createElement("form", { className: "space-y-6", autoComplete: "off", onSubmit: (e) => {
|
|
@@ -517,69 +536,7 @@ function AuthFormInner({
|
|
|
517
536
|
if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
|
|
518
537
|
else if (mode === "SIGNUP" && signupStep === "ORGANIZATION") handleNextSignupStep();
|
|
519
538
|
else handleAuthRequestSubmit();
|
|
520
|
-
} }, mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ import_react6.default.createElement(
|
|
521
|
-
"input",
|
|
522
|
-
{
|
|
523
|
-
type: "text",
|
|
524
|
-
value: firstName,
|
|
525
|
-
onChange: (e) => setFirstName(cleanAlpha(e.target.value)),
|
|
526
|
-
required: true,
|
|
527
|
-
autoFocus: true,
|
|
528
|
-
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300",
|
|
529
|
-
placeholder: "First name"
|
|
530
|
-
}
|
|
531
|
-
)), /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ import_react6.default.createElement(
|
|
532
|
-
"input",
|
|
533
|
-
{
|
|
534
|
-
type: "text",
|
|
535
|
-
value: lastName,
|
|
536
|
-
onChange: (e) => setLastName(cleanAlpha(e.target.value)),
|
|
537
|
-
required: true,
|
|
538
|
-
className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300",
|
|
539
|
-
placeholder: "Last name"
|
|
540
|
-
}
|
|
541
|
-
))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ import_react6.default.createElement(
|
|
542
|
-
"input",
|
|
543
|
-
{
|
|
544
|
-
type: "text",
|
|
545
|
-
value: orgName,
|
|
546
|
-
onChange: (e) => setOrgName(cleanOrgName(e.target.value)),
|
|
547
|
-
required: true,
|
|
548
|
-
autoFocus: true,
|
|
549
|
-
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300",
|
|
550
|
-
placeholder: "Acme Corporation"
|
|
551
|
-
}
|
|
552
|
-
))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "EMAIL_ID") && /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Email ID"), /* @__PURE__ */ import_react6.default.createElement(
|
|
553
|
-
"input",
|
|
554
|
-
{
|
|
555
|
-
type: "email",
|
|
556
|
-
value: emailId,
|
|
557
|
-
onChange: (e) => setEmailId(cleanEmailId(e.target.value)),
|
|
558
|
-
required: true,
|
|
559
|
-
autoFocus: true,
|
|
560
|
-
className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300",
|
|
561
|
-
placeholder: "name@company.com"
|
|
562
|
-
}
|
|
563
|
-
)), mode === "SIGNUP" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ import_react6.default.createElement(
|
|
564
|
-
"input",
|
|
565
|
-
{
|
|
566
|
-
type: "checkbox",
|
|
567
|
-
id: "zairus-terms",
|
|
568
|
-
checked: agreedToTerms,
|
|
569
|
-
onChange: (e) => setAgreedToTerms(e.target.checked),
|
|
570
|
-
className: "mt-0.5 w-4 h-4 bg-white border-neutral-300 rounded text-black focus:ring-black cursor-pointer",
|
|
571
|
-
required: true
|
|
572
|
-
}
|
|
573
|
-
), /* @__PURE__ */ import_react6.default.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ import_react6.default.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Terms of Service"), " and ", /* @__PURE__ */ import_react6.default.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Privacy Policy"), "."))), /* @__PURE__ */ import_react6.default.createElement(
|
|
574
|
-
ThreeDActionButton,
|
|
575
|
-
{
|
|
576
|
-
type: "submit",
|
|
577
|
-
disabled: isContinueDisabled(),
|
|
578
|
-
isLoading: isSubmitting,
|
|
579
|
-
className: "w-full mt-10"
|
|
580
|
-
},
|
|
581
|
-
"Continue"
|
|
582
|
-
))), step === "OTP" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "text-center mb-10 mt-2" }, /* @__PURE__ */ import_react6.default.createElement("h2", { className: " text-xl text-black mb-2 tracking-tight " }, "Security Check"), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the code sent to ", /* @__PURE__ */ import_react6.default.createElement("br", null), /* @__PURE__ */ import_react6.default.createElement("span", { className: "text-black " }, emailId))), /* @__PURE__ */ import_react6.default.createElement("form", { className: "space-y-10", autoComplete: "off", onSubmit: (e) => {
|
|
539
|
+
} }, mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "text", value: firstName, onChange: (e) => setFirstName(cleanAlpha(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300", placeholder: "First name" })), /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "text", value: lastName, onChange: (e) => setLastName(cleanAlpha(e.target.value)), required: true, className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Last name" }))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "text", value: orgName, onChange: (e) => setOrgName(cleanOrgName(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Acme Corporation" }))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "EMAIL_ID") && /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Email ID"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "email", value: emailId, onChange: (e) => setEmailId(cleanEmailId(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300", placeholder: "name@company.com" })), mode === "SIGNUP" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ import_react6.default.createElement("input", { type: "checkbox", id: "zairus-terms", checked: agreedToTerms, onChange: (e) => setAgreedToTerms(e.target.checked), className: "mt-0.5 w-4 h-4 bg-white border-neutral-300 rounded text-black focus:ring-black cursor-pointer", required: true }), /* @__PURE__ */ import_react6.default.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ import_react6.default.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Terms of Service"), " and ", /* @__PURE__ */ import_react6.default.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Privacy Policy"), "."))), /* @__PURE__ */ import_react6.default.createElement(ThreeDActionButton, { type: "submit", disabled: isContinueDisabled(), isLoading: isSubmitting, className: "w-full mt-10" }, "Continue"))), step === "OTP" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "text-center mb-10 mt-2" }, /* @__PURE__ */ import_react6.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-[13px] text-neutral-500" }, userHas2FA ? "Enter the code from your authenticator app." : `Enter the code sent to ${emailId}`)), /* @__PURE__ */ import_react6.default.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
|
|
583
540
|
e.preventDefault();
|
|
584
541
|
verifyOtpCode(otp.join(""));
|
|
585
542
|
} }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ import_react6.default.createElement(
|
|
@@ -594,17 +551,19 @@ function AuthFormInner({
|
|
|
594
551
|
maxLength: 1,
|
|
595
552
|
value: digit,
|
|
596
553
|
onChange: (e) => handleOtpChange(index, e.target.value),
|
|
597
|
-
|
|
554
|
+
onKeyDown: (e) => {
|
|
555
|
+
if (e.key === "Backspace" && !otp[index] && index > 0) inputRefs.current[index - 1]?.focus();
|
|
556
|
+
},
|
|
557
|
+
className: "w-10 h-12 text-center text-lg bg-transparent border-b-2 border-neutral-100 text-black outline-none focus:border-black transition-all duration-300"
|
|
598
558
|
}
|
|
599
|
-
))), /* @__PURE__ */ import_react6.default.createElement(
|
|
600
|
-
|
|
559
|
+
))), /* @__PURE__ */ import_react6.default.createElement(ThreeDActionButton, { type: "submit", disabled: otp.join("").length < 6, isLoading: isSubmitting, className: "w-full" }, "Verify Code")), userHasPasskey && /* @__PURE__ */ import_react6.default.createElement("div", { className: "pt-6 " }, /* @__PURE__ */ import_react6.default.createElement(
|
|
560
|
+
"button",
|
|
601
561
|
{
|
|
602
|
-
|
|
603
|
-
disabled:
|
|
604
|
-
|
|
605
|
-
className: "w-full"
|
|
562
|
+
onClick: triggerPasskeyLogin,
|
|
563
|
+
disabled: isSubmitting,
|
|
564
|
+
className: "w-full py-2.5 rounded-full text-black border border-neutral-200 hover:bg-neutral-50 text-xs font-medium tracking-wide transition-colors outline-none disabled:opacity-50"
|
|
606
565
|
},
|
|
607
|
-
"
|
|
566
|
+
"Use Passkey / Biometrics"
|
|
608
567
|
))))));
|
|
609
568
|
}
|
|
610
569
|
var PipleAuth = (props) => {
|
|
@@ -1201,7 +1160,7 @@ var UniversalProfileSettings = ({
|
|
|
1201
1160
|
type: "submit",
|
|
1202
1161
|
disabled: isPinSubmitting || newPin.length !== 4 || confirmPin.length !== 4 || hasPin && oldPin.length !== 4,
|
|
1203
1162
|
isLoading: isPinSubmitting,
|
|
1204
|
-
className: "w-full
|
|
1163
|
+
className: "w-full"
|
|
1205
1164
|
},
|
|
1206
1165
|
hasPin ? "Update PIN" : "Set PIN"
|
|
1207
1166
|
))))))));
|
|
@@ -1462,14 +1421,14 @@ var UniversalTransactionPage = ({
|
|
|
1462
1421
|
{
|
|
1463
1422
|
onClick: handleGenerateReceipt,
|
|
1464
1423
|
isLoading: isGeneratingReceipt,
|
|
1465
|
-
className: "w-full
|
|
1424
|
+
className: "w-full"
|
|
1466
1425
|
},
|
|
1467
1426
|
"Generate Receipt"
|
|
1468
1427
|
), /* @__PURE__ */ import_react23.default.createElement(
|
|
1469
1428
|
"button",
|
|
1470
1429
|
{
|
|
1471
1430
|
onClick: () => onReportTransaction && onReportTransaction(selectedTransaction),
|
|
1472
|
-
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-
|
|
1431
|
+
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-xs tracking-wide mt-2"
|
|
1473
1432
|
},
|
|
1474
1433
|
"Report Transaction"
|
|
1475
1434
|
), selectedTransaction.type === "WALLET_TRANSACTION" && /* @__PURE__ */ import_react23.default.createElement(
|
|
@@ -1478,7 +1437,7 @@ var UniversalTransactionPage = ({
|
|
|
1478
1437
|
href: `https://basescan.org/tx/${selectedTransaction.reference}`,
|
|
1479
1438
|
target: "_blank",
|
|
1480
1439
|
rel: "noopener noreferrer",
|
|
1481
|
-
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-
|
|
1440
|
+
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-xs tracking-wide mt-2"
|
|
1482
1441
|
},
|
|
1483
1442
|
"View in block explorer"
|
|
1484
1443
|
))))), isDirectionModalOpen && /* @__PURE__ */ import_react23.default.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => setIsDirectionModalOpen(false) }), /* @__PURE__ */ import_react23.default.createElement("div", { ref: directionDropdownRef, className: "relative w-72 bg-white shadow-2xl rounded-2xl flex flex-col items-center overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "p-6 text-center w-full mb-2" }, /* @__PURE__ */ import_react23.default.createElement("h3", { className: "text-[14px] text-black tracking-tight" }, "Payment Type")), /* @__PURE__ */ import_react23.default.createElement("div", { className: "w-full flex flex-col pl-2 pr-2 gap-1" }, ["ALL", "CREDIT", "DEBIT"].map((option) => /* @__PURE__ */ import_react23.default.createElement(
|
|
@@ -1578,7 +1537,7 @@ var UniversalHomeView = ({
|
|
|
1578
1537
|
ThreeDActionButton,
|
|
1579
1538
|
{
|
|
1580
1539
|
onClick: primaryAction.onClick,
|
|
1581
|
-
className: "px-6
|
|
1540
|
+
className: "px-6 sm:px-8"
|
|
1582
1541
|
},
|
|
1583
1542
|
/* @__PURE__ */ import_react25.default.createElement("span", { className: "flex items-center gap-1.5 text-[13px] tracking-wide " }, primaryAction.label, primaryAction.icon && /* @__PURE__ */ import_react25.default.createElement(import_react26.HugeiconsIcon, { icon: primaryAction.icon, size: 16 }))
|
|
1584
1543
|
), secondaryAction && /* @__PURE__ */ import_react25.default.createElement(
|
|
@@ -1690,14 +1649,14 @@ var UniversalWalletPage = ({
|
|
|
1690
1649
|
{
|
|
1691
1650
|
onClick: () => onDownloadPayId && onDownloadPayId(selectedWallet),
|
|
1692
1651
|
isLoading: isGeneratingStatement,
|
|
1693
|
-
className: "w-full
|
|
1652
|
+
className: "w-full"
|
|
1694
1653
|
},
|
|
1695
1654
|
"Generate Statement"
|
|
1696
1655
|
), /* @__PURE__ */ import_react27.default.createElement(
|
|
1697
1656
|
"button",
|
|
1698
1657
|
{
|
|
1699
1658
|
onClick: () => handleCopy(selectedWallet),
|
|
1700
|
-
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 outline-none text-
|
|
1659
|
+
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 outline-none text-xs tracking-wide transition-colors"
|
|
1701
1660
|
},
|
|
1702
1661
|
"Copy Wallet Address"
|
|
1703
1662
|
)))))));
|
|
@@ -2665,7 +2624,7 @@ var import_react45 = __toESM(require("react"));
|
|
|
2665
2624
|
var import_react_hot_toast8 = __toESM(require("react-hot-toast"));
|
|
2666
2625
|
var import_react46 = require("@hugeicons/react");
|
|
2667
2626
|
var import_core_free_icons16 = require("@hugeicons/core-free-icons");
|
|
2668
|
-
var
|
|
2627
|
+
var import_browser2 = require("@simplewebauthn/browser");
|
|
2669
2628
|
var UniversalSecurityPage = ({
|
|
2670
2629
|
has2FA,
|
|
2671
2630
|
hasPasskey,
|
|
@@ -2810,7 +2769,7 @@ var UniversalSecurityPage = ({
|
|
|
2810
2769
|
const options = await onRequestPasskeySetup();
|
|
2811
2770
|
let credentialResponse;
|
|
2812
2771
|
try {
|
|
2813
|
-
credentialResponse = await (0,
|
|
2772
|
+
credentialResponse = await (0, import_browser2.startRegistration)({ optionsJSON: options });
|
|
2814
2773
|
} catch (err) {
|
|
2815
2774
|
if (err.name === "NotAllowedError") {
|
|
2816
2775
|
throw new Error("Passkey setup was canceled or is not supported on this device.");
|
|
@@ -2861,7 +2820,15 @@ var UniversalSecurityPage = ({
|
|
|
2861
2820
|
toggleLoading: isPasskeyLoading,
|
|
2862
2821
|
isLast: true
|
|
2863
2822
|
}
|
|
2864
|
-
))), show2FASetupModal && /* @__PURE__ */ import_react45.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FASetupModal(false) }), /* @__PURE__ */ import_react45.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 max-h-[90vh]" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ import_react45.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable 2FA"), /* @__PURE__ */ import_react45.default.createElement("button", { onClick: () => !isSubmitting && setShow2FASetupModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 pt-2" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "w-full flex justify-center mb-6 mix-blend-multiply" }, twoFaQr ? /* @__PURE__ */ import_react45.default.createElement("img", { src: twoFaQr, alt: "2FA QR Code", className: "w-40 h-40 object-contain rounded-xl border border-neutral-100 p-2" }) : /* @__PURE__ */ import_react45.default.createElement("div", { className: "w-40 h-40 bg-neutral-100 rounded-xl flex items-center justify-center animate-pulse" })), /* @__PURE__ */ import_react45.default.createElement("div", { className: "
|
|
2823
|
+
))), show2FASetupModal && /* @__PURE__ */ import_react45.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FASetupModal(false) }), /* @__PURE__ */ import_react45.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 max-h-[90vh]" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ import_react45.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable 2FA"), /* @__PURE__ */ import_react45.default.createElement("button", { onClick: () => !isSubmitting && setShow2FASetupModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 pt-2" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "w-full flex justify-center mb-6 mix-blend-multiply" }, twoFaQr ? /* @__PURE__ */ import_react45.default.createElement("img", { src: twoFaQr, alt: "2FA QR Code", className: "w-40 h-40 object-contain rounded-xl border border-neutral-100 p-2" }) : /* @__PURE__ */ import_react45.default.createElement("div", { className: "w-40 h-40 bg-neutral-100 rounded-xl flex items-center justify-center animate-pulse" })), /* @__PURE__ */ import_react45.default.createElement("div", { className: "grid grid-cols-1 gap-y-6 gap-x-4 mb-8" }, /* @__PURE__ */ import_react45.default.createElement("div", null, /* @__PURE__ */ import_react45.default.createElement("span", { className: "text-[11px] tracking-[0.2em] text-neutral-400 block mb-2 uppercase" }, "Setup Key"), /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex items-center gap-2 min-w-0 bg-neutral-50 px-3 py-2.5 rounded-xl " }, /* @__PURE__ */ import_react45.default.createElement("span", { className: "text-[13px] font-mono tracking-widest text-black truncate min-w-0 block flex-1" }, twoFaSecret), /* @__PURE__ */ import_react45.default.createElement(
|
|
2824
|
+
"button",
|
|
2825
|
+
{
|
|
2826
|
+
type: "button",
|
|
2827
|
+
onClick: () => handleCopySecret(twoFaSecret),
|
|
2828
|
+
className: "text-neutral-400 hover:text-black transition-colors outline-none shrink-0 ml-2"
|
|
2829
|
+
},
|
|
2830
|
+
/* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.Copy01Icon, size: 16 })
|
|
2831
|
+
)))), /* @__PURE__ */ import_react45.default.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ import_react45.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react45.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the 6-digit code from your app")), /* @__PURE__ */ import_react45.default.createElement("form", { className: "space-y-4", autoComplete: "off", onSubmit: (e) => {
|
|
2865
2832
|
e.preventDefault();
|
|
2866
2833
|
submitEnable2FA(otp.join(""));
|
|
2867
2834
|
} }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex justify-between gap-2 pb-6", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ import_react45.default.createElement(
|
|
@@ -2897,7 +2864,7 @@ var UniversalSecurityPage = ({
|
|
|
2897
2864
|
{
|
|
2898
2865
|
type: "button",
|
|
2899
2866
|
onClick: () => handleCopySecret(twoFaSecret),
|
|
2900
|
-
className: "w-full flex items-center justify-center py-
|
|
2867
|
+
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 outline-none text-xs font-medium tracking-wide transition-colors mt-2"
|
|
2901
2868
|
},
|
|
2902
2869
|
/* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.Copy01Icon, size: 16, className: "mr-2" }),
|
|
2903
2870
|
"Copy Secret Key"
|
|
@@ -2932,7 +2899,7 @@ var UniversalSecurityPage = ({
|
|
|
2932
2899
|
className: "w-full py-3.5"
|
|
2933
2900
|
},
|
|
2934
2901
|
"Verify & Disable"
|
|
2935
|
-
))))), showPasskeyModal && /* @__PURE__ */ import_react45.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShowPasskeyModal(false) }), /* @__PURE__ */ import_react45.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0" }, /* @__PURE__ */ import_react45.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable Passkey"), /* @__PURE__ */ import_react45.default.createElement("button", { onClick: () => !isSubmitting && setShowPasskeyModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react45.default.createElement("div", { className: "p-6 text-center" }, /* @__PURE__ */ import_react45.default.createElement("p", { className: "text-[13px] text-neutral-500 mb-8 leading-relaxed" }, "Use your device's biometrics (Face ID, Touch ID, or PIN) to securely sign into your account without needing a password."), /* @__PURE__ */ import_react45.default.createElement(
|
|
2902
|
+
))))), showPasskeyModal && /* @__PURE__ */ import_react45.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShowPasskeyModal(false) }), /* @__PURE__ */ import_react45.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0" }, /* @__PURE__ */ import_react45.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable Passkey"), /* @__PURE__ */ import_react45.default.createElement("button", { onClick: () => !isSubmitting && setShowPasskeyModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react45.default.createElement("div", { className: "p-6 text-center" }, /* @__PURE__ */ import_react45.default.createElement("h2", { className: "text-lg text-black mb-2 tracking-tight" }, "Simplify your Sign In"), /* @__PURE__ */ import_react45.default.createElement("p", { className: "text-[13px] text-neutral-500 mb-8 leading-relaxed" }, "Use your device's biometrics (Face ID, Touch ID, or PIN) to securely sign into your account without needing a password."), /* @__PURE__ */ import_react45.default.createElement(
|
|
2936
2903
|
ThreeDActionButton,
|
|
2937
2904
|
{
|
|
2938
2905
|
onClick: submitEnablePasskey,
|
package/dist/index.mjs
CHANGED
|
@@ -297,6 +297,7 @@ import React5, { useState as useState3, useRef as useRef2, useEffect as useEffec
|
|
|
297
297
|
import { useSearchParams } from "next/navigation";
|
|
298
298
|
import toast from "react-hot-toast";
|
|
299
299
|
import { useGoogleReCaptcha, GoogleReCaptchaProvider } from "react-google-recaptcha-v3";
|
|
300
|
+
import { startAuthentication } from "@simplewebauthn/browser";
|
|
300
301
|
var InputSpinner = () => /* @__PURE__ */ React5.createElement("svg", { className: "animate-spin h-4 w-4 text-neutral-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ React5.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React5.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
301
302
|
function AuthFormInner({
|
|
302
303
|
companyName,
|
|
@@ -328,6 +329,9 @@ function AuthFormInner({
|
|
|
328
329
|
const [lastName, setLastName] = useState3("");
|
|
329
330
|
const [orgName, setOrgName] = useState3("");
|
|
330
331
|
const [agreedToTerms, setAgreedToTerms] = useState3(false);
|
|
332
|
+
const [userHas2FA, setUserHas2FA] = useState3(false);
|
|
333
|
+
const [userHasPasskey, setUserHasPasskey] = useState3(false);
|
|
334
|
+
const [authOptions, setAuthOptions] = useState3(null);
|
|
331
335
|
const [otp, setOtp] = useState3(["", "", "", "", "", ""]);
|
|
332
336
|
const inputRefs = useRef2([]);
|
|
333
337
|
const cleanAlpha = (val) => val.replace(/[^a-zA-Z\s-]/g, "");
|
|
@@ -345,9 +349,7 @@ function AuthFormInner({
|
|
|
345
349
|
const newOtp = [...otp];
|
|
346
350
|
newOtp[index] = cleanValue.slice(-1);
|
|
347
351
|
setOtp(newOtp);
|
|
348
|
-
if (cleanValue && index < 5)
|
|
349
|
-
inputRefs.current[index + 1]?.focus();
|
|
350
|
-
}
|
|
352
|
+
if (cleanValue && index < 5) inputRefs.current[index + 1]?.focus();
|
|
351
353
|
};
|
|
352
354
|
const handlePaste = (e) => {
|
|
353
355
|
e.preventDefault();
|
|
@@ -356,13 +358,10 @@ function AuthFormInner({
|
|
|
356
358
|
if (!numbersOnly) return;
|
|
357
359
|
const newOtp = [...otp];
|
|
358
360
|
const length = Math.min(numbersOnly.length, 6);
|
|
359
|
-
for (let i = 0; i < length; i++)
|
|
360
|
-
newOtp[i] = numbersOnly[i];
|
|
361
|
-
}
|
|
361
|
+
for (let i = 0; i < length; i++) newOtp[i] = numbersOnly[i];
|
|
362
362
|
setOtp(newOtp);
|
|
363
|
-
if (length < 6)
|
|
364
|
-
|
|
365
|
-
} else {
|
|
363
|
+
if (length < 6) inputRefs.current[length]?.focus();
|
|
364
|
+
else {
|
|
366
365
|
inputRefs.current[5]?.focus();
|
|
367
366
|
verifyOtpCode(newOtp.join(""));
|
|
368
367
|
}
|
|
@@ -389,7 +388,10 @@ function AuthFormInner({
|
|
|
389
388
|
recaptchaToken
|
|
390
389
|
});
|
|
391
390
|
if (res.success) {
|
|
392
|
-
|
|
391
|
+
setUserHas2FA(!!res.has2FA);
|
|
392
|
+
setUserHasPasskey(!!res.hasPasskey);
|
|
393
|
+
if (res.passkeyOptions) setAuthOptions(res.passkeyOptions);
|
|
394
|
+
toast.success(res.has2FA ? "Security check required" : "Verification code sent");
|
|
393
395
|
setStep("OTP");
|
|
394
396
|
setCountdown(60);
|
|
395
397
|
} else {
|
|
@@ -419,6 +421,23 @@ function AuthFormInner({
|
|
|
419
421
|
setIsSubmitting(false);
|
|
420
422
|
}
|
|
421
423
|
};
|
|
424
|
+
const triggerPasskeyLogin = async () => {
|
|
425
|
+
if (!authOptions || isSubmitting) return;
|
|
426
|
+
setIsSubmitting(true);
|
|
427
|
+
try {
|
|
428
|
+
const credentialResponse = await startAuthentication({ optionsJSON: authOptions });
|
|
429
|
+
const res = await onVerifyOtp({ email: emailId, isPasskey: true, passkeyCredential: credentialResponse });
|
|
430
|
+
if (res.success) {
|
|
431
|
+
window.location.href = res.redirect || redirectUrl;
|
|
432
|
+
} else {
|
|
433
|
+
toast.error(res.error || "Device verification failed.");
|
|
434
|
+
}
|
|
435
|
+
} catch (err) {
|
|
436
|
+
if (err.name !== "NotAllowedError") toast.error("Passkey verification interrupted.");
|
|
437
|
+
} finally {
|
|
438
|
+
setIsSubmitting(false);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
422
441
|
const handleNextSignupStep = () => {
|
|
423
442
|
if (signupStep === "NAME") {
|
|
424
443
|
if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
@@ -437,7 +456,7 @@ function AuthFormInner({
|
|
|
437
456
|
}
|
|
438
457
|
return false;
|
|
439
458
|
};
|
|
440
|
-
return /* @__PURE__ */ React5.createElement("div", { className: "w-full max-w-md mx-auto flex flex-col items-center gap-4 relative z-10 animate-in fade-in duration-300" }, /* @__PURE__ */ React5.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ React5.createElement("div", { className: "p-8 md:p-12" }, step === "INPUT" && /* @__PURE__ */ React5.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React5.createElement("div", { className: "mb-12 text-center mt-2" }, /* @__PURE__ */ React5.createElement("h2", { className: "
|
|
459
|
+
return /* @__PURE__ */ React5.createElement("div", { className: "w-full max-w-md mx-auto flex flex-col items-center gap-4 relative z-10 animate-in fade-in duration-300" }, /* @__PURE__ */ React5.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ React5.createElement("div", { className: "p-8 md:p-12" }, step === "INPUT" && /* @__PURE__ */ React5.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React5.createElement("div", { className: "mb-12 text-center mt-2" }, /* @__PURE__ */ React5.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, mode === "LOGIN" ? `${companyName} ${workspaceLabel}` : "Create Account"), /* @__PURE__ */ React5.createElement("div", { className: "text-[13px] text-neutral-500" }, mode === "LOGIN" ? /* @__PURE__ */ React5.createElement(React5.Fragment, null, "Don't have an account? ", /* @__PURE__ */ React5.createElement("button", { type: "button", onClick: () => {
|
|
441
460
|
setMode("SIGNUP");
|
|
442
461
|
setSignupStep(getInitialSignupStep());
|
|
443
462
|
}, className: "text-black transition-colors ml-1" }, "Sign up")) : /* @__PURE__ */ React5.createElement(React5.Fragment, null, "Already have an account? ", /* @__PURE__ */ React5.createElement("button", { type: "button", onClick: () => setMode("LOGIN"), className: "text-black transition-colors ml-1" }, "Log in")))), /* @__PURE__ */ React5.createElement("form", { className: "space-y-6", autoComplete: "off", onSubmit: (e) => {
|
|
@@ -445,69 +464,7 @@ function AuthFormInner({
|
|
|
445
464
|
if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
|
|
446
465
|
else if (mode === "SIGNUP" && signupStep === "ORGANIZATION") handleNextSignupStep();
|
|
447
466
|
else handleAuthRequestSubmit();
|
|
448
|
-
} }, mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ React5.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ React5.createElement(
|
|
449
|
-
"input",
|
|
450
|
-
{
|
|
451
|
-
type: "text",
|
|
452
|
-
value: firstName,
|
|
453
|
-
onChange: (e) => setFirstName(cleanAlpha(e.target.value)),
|
|
454
|
-
required: true,
|
|
455
|
-
autoFocus: true,
|
|
456
|
-
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300",
|
|
457
|
-
placeholder: "First name"
|
|
458
|
-
}
|
|
459
|
-
)), /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ React5.createElement(
|
|
460
|
-
"input",
|
|
461
|
-
{
|
|
462
|
-
type: "text",
|
|
463
|
-
value: lastName,
|
|
464
|
-
onChange: (e) => setLastName(cleanAlpha(e.target.value)),
|
|
465
|
-
required: true,
|
|
466
|
-
className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300",
|
|
467
|
-
placeholder: "Last name"
|
|
468
|
-
}
|
|
469
|
-
))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ React5.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ React5.createElement(
|
|
470
|
-
"input",
|
|
471
|
-
{
|
|
472
|
-
type: "text",
|
|
473
|
-
value: orgName,
|
|
474
|
-
onChange: (e) => setOrgName(cleanOrgName(e.target.value)),
|
|
475
|
-
required: true,
|
|
476
|
-
autoFocus: true,
|
|
477
|
-
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300",
|
|
478
|
-
placeholder: "Acme Corporation"
|
|
479
|
-
}
|
|
480
|
-
))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "EMAIL_ID") && /* @__PURE__ */ React5.createElement("div", { className: "space-y-6" }, /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Email ID"), /* @__PURE__ */ React5.createElement(
|
|
481
|
-
"input",
|
|
482
|
-
{
|
|
483
|
-
type: "email",
|
|
484
|
-
value: emailId,
|
|
485
|
-
onChange: (e) => setEmailId(cleanEmailId(e.target.value)),
|
|
486
|
-
required: true,
|
|
487
|
-
autoFocus: true,
|
|
488
|
-
className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300",
|
|
489
|
-
placeholder: "name@company.com"
|
|
490
|
-
}
|
|
491
|
-
)), mode === "SIGNUP" && /* @__PURE__ */ React5.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ React5.createElement(
|
|
492
|
-
"input",
|
|
493
|
-
{
|
|
494
|
-
type: "checkbox",
|
|
495
|
-
id: "zairus-terms",
|
|
496
|
-
checked: agreedToTerms,
|
|
497
|
-
onChange: (e) => setAgreedToTerms(e.target.checked),
|
|
498
|
-
className: "mt-0.5 w-4 h-4 bg-white border-neutral-300 rounded text-black focus:ring-black cursor-pointer",
|
|
499
|
-
required: true
|
|
500
|
-
}
|
|
501
|
-
), /* @__PURE__ */ React5.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ React5.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Terms of Service"), " and ", /* @__PURE__ */ React5.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Privacy Policy"), "."))), /* @__PURE__ */ React5.createElement(
|
|
502
|
-
ThreeDActionButton,
|
|
503
|
-
{
|
|
504
|
-
type: "submit",
|
|
505
|
-
disabled: isContinueDisabled(),
|
|
506
|
-
isLoading: isSubmitting,
|
|
507
|
-
className: "w-full mt-10"
|
|
508
|
-
},
|
|
509
|
-
"Continue"
|
|
510
|
-
))), step === "OTP" && /* @__PURE__ */ React5.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React5.createElement("div", { className: "text-center mb-10 mt-2" }, /* @__PURE__ */ React5.createElement("h2", { className: " text-xl text-black mb-2 tracking-tight " }, "Security Check"), /* @__PURE__ */ React5.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the code sent to ", /* @__PURE__ */ React5.createElement("br", null), /* @__PURE__ */ React5.createElement("span", { className: "text-black " }, emailId))), /* @__PURE__ */ React5.createElement("form", { className: "space-y-10", autoComplete: "off", onSubmit: (e) => {
|
|
467
|
+
} }, mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ React5.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ React5.createElement("input", { type: "text", value: firstName, onChange: (e) => setFirstName(cleanAlpha(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300", placeholder: "First name" })), /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ React5.createElement("input", { type: "text", value: lastName, onChange: (e) => setLastName(cleanAlpha(e.target.value)), required: true, className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Last name" }))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ React5.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ React5.createElement("input", { type: "text", value: orgName, onChange: (e) => setOrgName(cleanOrgName(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Acme Corporation" }))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "EMAIL_ID") && /* @__PURE__ */ React5.createElement("div", { className: "space-y-6" }, /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Email ID"), /* @__PURE__ */ React5.createElement("input", { type: "email", value: emailId, onChange: (e) => setEmailId(cleanEmailId(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-100 text-black outline-none focus:border-black transition-all duration-300", placeholder: "name@company.com" })), mode === "SIGNUP" && /* @__PURE__ */ React5.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ React5.createElement("input", { type: "checkbox", id: "zairus-terms", checked: agreedToTerms, onChange: (e) => setAgreedToTerms(e.target.checked), className: "mt-0.5 w-4 h-4 bg-white border-neutral-300 rounded text-black focus:ring-black cursor-pointer", required: true }), /* @__PURE__ */ React5.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ React5.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Terms of Service"), " and ", /* @__PURE__ */ React5.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Privacy Policy"), "."))), /* @__PURE__ */ React5.createElement(ThreeDActionButton, { type: "submit", disabled: isContinueDisabled(), isLoading: isSubmitting, className: "w-full mt-10" }, "Continue"))), step === "OTP" && /* @__PURE__ */ React5.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React5.createElement("div", { className: "text-center mb-10 mt-2" }, /* @__PURE__ */ React5.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ React5.createElement("p", { className: "text-[13px] text-neutral-500" }, userHas2FA ? "Enter the code from your authenticator app." : `Enter the code sent to ${emailId}`)), /* @__PURE__ */ React5.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
|
|
511
468
|
e.preventDefault();
|
|
512
469
|
verifyOtpCode(otp.join(""));
|
|
513
470
|
} }, /* @__PURE__ */ React5.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ React5.createElement(
|
|
@@ -522,17 +479,19 @@ function AuthFormInner({
|
|
|
522
479
|
maxLength: 1,
|
|
523
480
|
value: digit,
|
|
524
481
|
onChange: (e) => handleOtpChange(index, e.target.value),
|
|
525
|
-
|
|
482
|
+
onKeyDown: (e) => {
|
|
483
|
+
if (e.key === "Backspace" && !otp[index] && index > 0) inputRefs.current[index - 1]?.focus();
|
|
484
|
+
},
|
|
485
|
+
className: "w-10 h-12 text-center text-lg bg-transparent border-b-2 border-neutral-100 text-black outline-none focus:border-black transition-all duration-300"
|
|
526
486
|
}
|
|
527
|
-
))), /* @__PURE__ */ React5.createElement(
|
|
528
|
-
|
|
487
|
+
))), /* @__PURE__ */ React5.createElement(ThreeDActionButton, { type: "submit", disabled: otp.join("").length < 6, isLoading: isSubmitting, className: "w-full" }, "Verify Code")), userHasPasskey && /* @__PURE__ */ React5.createElement("div", { className: "pt-6 " }, /* @__PURE__ */ React5.createElement(
|
|
488
|
+
"button",
|
|
529
489
|
{
|
|
530
|
-
|
|
531
|
-
disabled:
|
|
532
|
-
|
|
533
|
-
className: "w-full"
|
|
490
|
+
onClick: triggerPasskeyLogin,
|
|
491
|
+
disabled: isSubmitting,
|
|
492
|
+
className: "w-full py-2.5 rounded-full text-black border border-neutral-200 hover:bg-neutral-50 text-xs font-medium tracking-wide transition-colors outline-none disabled:opacity-50"
|
|
534
493
|
},
|
|
535
|
-
"
|
|
494
|
+
"Use Passkey / Biometrics"
|
|
536
495
|
))))));
|
|
537
496
|
}
|
|
538
497
|
var PipleAuth = (props) => {
|
|
@@ -1143,7 +1102,7 @@ var UniversalProfileSettings = ({
|
|
|
1143
1102
|
type: "submit",
|
|
1144
1103
|
disabled: isPinSubmitting || newPin.length !== 4 || confirmPin.length !== 4 || hasPin && oldPin.length !== 4,
|
|
1145
1104
|
isLoading: isPinSubmitting,
|
|
1146
|
-
className: "w-full
|
|
1105
|
+
className: "w-full"
|
|
1147
1106
|
},
|
|
1148
1107
|
hasPin ? "Update PIN" : "Set PIN"
|
|
1149
1108
|
))))))));
|
|
@@ -1415,14 +1374,14 @@ var UniversalTransactionPage = ({
|
|
|
1415
1374
|
{
|
|
1416
1375
|
onClick: handleGenerateReceipt,
|
|
1417
1376
|
isLoading: isGeneratingReceipt,
|
|
1418
|
-
className: "w-full
|
|
1377
|
+
className: "w-full"
|
|
1419
1378
|
},
|
|
1420
1379
|
"Generate Receipt"
|
|
1421
1380
|
), /* @__PURE__ */ React15.createElement(
|
|
1422
1381
|
"button",
|
|
1423
1382
|
{
|
|
1424
1383
|
onClick: () => onReportTransaction && onReportTransaction(selectedTransaction),
|
|
1425
|
-
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-
|
|
1384
|
+
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-xs tracking-wide mt-2"
|
|
1426
1385
|
},
|
|
1427
1386
|
"Report Transaction"
|
|
1428
1387
|
), selectedTransaction.type === "WALLET_TRANSACTION" && /* @__PURE__ */ React15.createElement(
|
|
@@ -1431,7 +1390,7 @@ var UniversalTransactionPage = ({
|
|
|
1431
1390
|
href: `https://basescan.org/tx/${selectedTransaction.reference}`,
|
|
1432
1391
|
target: "_blank",
|
|
1433
1392
|
rel: "noopener noreferrer",
|
|
1434
|
-
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-
|
|
1393
|
+
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-xs tracking-wide mt-2"
|
|
1435
1394
|
},
|
|
1436
1395
|
"View in block explorer"
|
|
1437
1396
|
))))), isDirectionModalOpen && /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React15.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => setIsDirectionModalOpen(false) }), /* @__PURE__ */ React15.createElement("div", { ref: directionDropdownRef, className: "relative w-72 bg-white shadow-2xl rounded-2xl flex flex-col items-center overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React15.createElement("div", { className: "p-6 text-center w-full mb-2" }, /* @__PURE__ */ React15.createElement("h3", { className: "text-[14px] text-black tracking-tight" }, "Payment Type")), /* @__PURE__ */ React15.createElement("div", { className: "w-full flex flex-col pl-2 pr-2 gap-1" }, ["ALL", "CREDIT", "DEBIT"].map((option) => /* @__PURE__ */ React15.createElement(
|
|
@@ -1531,7 +1490,7 @@ var UniversalHomeView = ({
|
|
|
1531
1490
|
ThreeDActionButton,
|
|
1532
1491
|
{
|
|
1533
1492
|
onClick: primaryAction.onClick,
|
|
1534
|
-
className: "px-6
|
|
1493
|
+
className: "px-6 sm:px-8"
|
|
1535
1494
|
},
|
|
1536
1495
|
/* @__PURE__ */ React16.createElement("span", { className: "flex items-center gap-1.5 text-[13px] tracking-wide " }, primaryAction.label, primaryAction.icon && /* @__PURE__ */ React16.createElement(HugeiconsIcon10, { icon: primaryAction.icon, size: 16 }))
|
|
1537
1496
|
), secondaryAction && /* @__PURE__ */ React16.createElement(
|
|
@@ -1649,14 +1608,14 @@ var UniversalWalletPage = ({
|
|
|
1649
1608
|
{
|
|
1650
1609
|
onClick: () => onDownloadPayId && onDownloadPayId(selectedWallet),
|
|
1651
1610
|
isLoading: isGeneratingStatement,
|
|
1652
|
-
className: "w-full
|
|
1611
|
+
className: "w-full"
|
|
1653
1612
|
},
|
|
1654
1613
|
"Generate Statement"
|
|
1655
1614
|
), /* @__PURE__ */ React17.createElement(
|
|
1656
1615
|
"button",
|
|
1657
1616
|
{
|
|
1658
1617
|
onClick: () => handleCopy(selectedWallet),
|
|
1659
|
-
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 outline-none text-
|
|
1618
|
+
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 outline-none text-xs tracking-wide transition-colors"
|
|
1660
1619
|
},
|
|
1661
1620
|
"Copy Wallet Address"
|
|
1662
1621
|
)))))));
|
|
@@ -2849,7 +2808,15 @@ var UniversalSecurityPage = ({
|
|
|
2849
2808
|
toggleLoading: isPasskeyLoading,
|
|
2850
2809
|
isLast: true
|
|
2851
2810
|
}
|
|
2852
|
-
))), show2FASetupModal && /* @__PURE__ */ React27.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React27.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FASetupModal(false) }), /* @__PURE__ */ React27.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 max-h-[90vh]" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ React27.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable 2FA"), /* @__PURE__ */ React27.createElement("button", { onClick: () => !isSubmitting && setShow2FASetupModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: CancelCircleIcon6, size: 18 }))), /* @__PURE__ */ React27.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 pt-2" }, /* @__PURE__ */ React27.createElement("div", { className: "w-full flex justify-center mb-6 mix-blend-multiply" }, twoFaQr ? /* @__PURE__ */ React27.createElement("img", { src: twoFaQr, alt: "2FA QR Code", className: "w-40 h-40 object-contain rounded-xl border border-neutral-100 p-2" }) : /* @__PURE__ */ React27.createElement("div", { className: "w-40 h-40 bg-neutral-100 rounded-xl flex items-center justify-center animate-pulse" })), /* @__PURE__ */ React27.createElement("div", { className: "
|
|
2811
|
+
))), show2FASetupModal && /* @__PURE__ */ React27.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React27.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FASetupModal(false) }), /* @__PURE__ */ React27.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 max-h-[90vh]" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ React27.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable 2FA"), /* @__PURE__ */ React27.createElement("button", { onClick: () => !isSubmitting && setShow2FASetupModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: CancelCircleIcon6, size: 18 }))), /* @__PURE__ */ React27.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 pt-2" }, /* @__PURE__ */ React27.createElement("div", { className: "w-full flex justify-center mb-6 mix-blend-multiply" }, twoFaQr ? /* @__PURE__ */ React27.createElement("img", { src: twoFaQr, alt: "2FA QR Code", className: "w-40 h-40 object-contain rounded-xl border border-neutral-100 p-2" }) : /* @__PURE__ */ React27.createElement("div", { className: "w-40 h-40 bg-neutral-100 rounded-xl flex items-center justify-center animate-pulse" })), /* @__PURE__ */ React27.createElement("div", { className: "grid grid-cols-1 gap-y-6 gap-x-4 mb-8" }, /* @__PURE__ */ React27.createElement("div", null, /* @__PURE__ */ React27.createElement("span", { className: "text-[11px] tracking-[0.2em] text-neutral-400 block mb-2 uppercase" }, "Setup Key"), /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-2 min-w-0 bg-neutral-50 px-3 py-2.5 rounded-xl " }, /* @__PURE__ */ React27.createElement("span", { className: "text-[13px] font-mono tracking-widest text-black truncate min-w-0 block flex-1" }, twoFaSecret), /* @__PURE__ */ React27.createElement(
|
|
2812
|
+
"button",
|
|
2813
|
+
{
|
|
2814
|
+
type: "button",
|
|
2815
|
+
onClick: () => handleCopySecret(twoFaSecret),
|
|
2816
|
+
className: "text-neutral-400 hover:text-black transition-colors outline-none shrink-0 ml-2"
|
|
2817
|
+
},
|
|
2818
|
+
/* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: Copy01Icon3, size: 16 })
|
|
2819
|
+
)))), /* @__PURE__ */ React27.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ React27.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ React27.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the 6-digit code from your app")), /* @__PURE__ */ React27.createElement("form", { className: "space-y-4", autoComplete: "off", onSubmit: (e) => {
|
|
2853
2820
|
e.preventDefault();
|
|
2854
2821
|
submitEnable2FA(otp.join(""));
|
|
2855
2822
|
} }, /* @__PURE__ */ React27.createElement("div", { className: "flex justify-between gap-2 pb-6", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ React27.createElement(
|
|
@@ -2885,7 +2852,7 @@ var UniversalSecurityPage = ({
|
|
|
2885
2852
|
{
|
|
2886
2853
|
type: "button",
|
|
2887
2854
|
onClick: () => handleCopySecret(twoFaSecret),
|
|
2888
|
-
className: "w-full flex items-center justify-center py-
|
|
2855
|
+
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 outline-none text-xs font-medium tracking-wide transition-colors mt-2"
|
|
2889
2856
|
},
|
|
2890
2857
|
/* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: Copy01Icon3, size: 16, className: "mr-2" }),
|
|
2891
2858
|
"Copy Secret Key"
|
|
@@ -2920,7 +2887,7 @@ var UniversalSecurityPage = ({
|
|
|
2920
2887
|
className: "w-full py-3.5"
|
|
2921
2888
|
},
|
|
2922
2889
|
"Verify & Disable"
|
|
2923
|
-
))))), showPasskeyModal && /* @__PURE__ */ React27.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React27.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShowPasskeyModal(false) }), /* @__PURE__ */ React27.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center justify-between p-5 shrink-0" }, /* @__PURE__ */ React27.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable Passkey"), /* @__PURE__ */ React27.createElement("button", { onClick: () => !isSubmitting && setShowPasskeyModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: CancelCircleIcon6, size: 18 }))), /* @__PURE__ */ React27.createElement("div", { className: "p-6 text-center" }, /* @__PURE__ */ React27.createElement("p", { className: "text-[13px] text-neutral-500 mb-8 leading-relaxed" }, "Use your device's biometrics (Face ID, Touch ID, or PIN) to securely sign into your account without needing a password."), /* @__PURE__ */ React27.createElement(
|
|
2890
|
+
))))), showPasskeyModal && /* @__PURE__ */ React27.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React27.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShowPasskeyModal(false) }), /* @__PURE__ */ React27.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center justify-between p-5 shrink-0" }, /* @__PURE__ */ React27.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable Passkey"), /* @__PURE__ */ React27.createElement("button", { onClick: () => !isSubmitting && setShowPasskeyModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: CancelCircleIcon6, size: 18 }))), /* @__PURE__ */ React27.createElement("div", { className: "p-6 text-center" }, /* @__PURE__ */ React27.createElement("h2", { className: "text-lg text-black mb-2 tracking-tight" }, "Simplify your Sign In"), /* @__PURE__ */ React27.createElement("p", { className: "text-[13px] text-neutral-500 mb-8 leading-relaxed" }, "Use your device's biometrics (Face ID, Touch ID, or PIN) to securely sign into your account without needing a password."), /* @__PURE__ */ React27.createElement(
|
|
2924
2891
|
ThreeDActionButton,
|
|
2925
2892
|
{
|
|
2926
2893
|
onClick: submitEnablePasskey,
|