@retinalabsllc/zairusjs 15.1.2 → 15.1.15
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.js +29 -27
- package/dist/index.mjs +29 -27
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -383,7 +383,7 @@ var import_react6 = __toESM(require("react"));
|
|
|
383
383
|
var InputSpinner = () => /* @__PURE__ */ import_react6.default.createElement("svg", { className: "animate-spin h-3 w-3 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" }));
|
|
384
384
|
var FlagImage = ({ countryCode }) => {
|
|
385
385
|
const [loaded, setLoaded] = (0, import_react6.useState)(false);
|
|
386
|
-
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "relative w-6 h-6 rounded-full overflow-hidden flex items-center justify-center bg-neutral-100 shrink-0
|
|
386
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "relative w-6 h-6 rounded-full overflow-hidden flex items-center justify-center bg-neutral-100 shrink-0" }, !loaded && /* @__PURE__ */ import_react6.default.createElement("div", { className: "absolute inset-0 flex items-center justify-center" }, /* @__PURE__ */ import_react6.default.createElement(InputSpinner, null)), /* @__PURE__ */ import_react6.default.createElement(
|
|
387
387
|
"img",
|
|
388
388
|
{
|
|
389
389
|
src: `https://flagcdn.com/w40/${countryCode.toLowerCase()}.png`,
|
|
@@ -484,7 +484,7 @@ var SUPPORTED_COUNTRIES = [
|
|
|
484
484
|
{ code: "GH", dialCode: "+233", name: "Ghana" },
|
|
485
485
|
{ code: "KE", dialCode: "+254", name: "Kenya" }
|
|
486
486
|
];
|
|
487
|
-
var InputSpinner2 = () => /* @__PURE__ */ import_react7.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_react7.default.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ import_react7.default.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0
|
|
487
|
+
var InputSpinner2 = () => /* @__PURE__ */ import_react7.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_react7.default.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ import_react7.default.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
488
488
|
var CountrySelectorDialog = ({ isOpen, onClose, onSelect }) => {
|
|
489
489
|
if (!isOpen) return null;
|
|
490
490
|
return /* @__PURE__ */ import_react7.default.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "absolute inset-0", onClick: onClose }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "w-full max-w-sm bg-white rounded-2xl shadow-2xl overflow-hidden relative z-10 animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
@@ -506,7 +506,7 @@ var CountrySelectorDialog = ({ isOpen, onClose, onSelect }) => {
|
|
|
506
506
|
},
|
|
507
507
|
/* @__PURE__ */ import_react7.default.createElement(FlagImage, { countryCode: c.code }),
|
|
508
508
|
/* @__PURE__ */ import_react7.default.createElement("span", { className: "text-sm text-black flex-1 font-medium" }, c.name),
|
|
509
|
-
/* @__PURE__ */ import_react7.default.createElement("span", { className: "text-sm text-neutral-
|
|
509
|
+
/* @__PURE__ */ import_react7.default.createElement("span", { className: "text-sm text-neutral-400 " }, c.dialCode)
|
|
510
510
|
))))));
|
|
511
511
|
};
|
|
512
512
|
function AuthFormInner({
|
|
@@ -526,7 +526,11 @@ function AuthFormInner({
|
|
|
526
526
|
const captchaContext = useRecaptcha ? (0, import_react_google_recaptcha_v3.useGoogleReCaptcha)() : null;
|
|
527
527
|
const [mode, setMode] = (0, import_react7.useState)("LOGIN");
|
|
528
528
|
const [step, setStep] = (0, import_react7.useState)("INPUT");
|
|
529
|
-
const getInitialSignupStep = () =>
|
|
529
|
+
const getInitialSignupStep = () => {
|
|
530
|
+
if (requireNames) return "NAME";
|
|
531
|
+
if (requireOrganization) return "ORGANIZATION";
|
|
532
|
+
return "PHONE_ID";
|
|
533
|
+
};
|
|
530
534
|
const [signupStep, setSignupStep] = (0, import_react7.useState)(getInitialSignupStep());
|
|
531
535
|
const [isSubmitting, setIsSubmitting] = (0, import_react7.useState)(false);
|
|
532
536
|
const [countdown, setCountdown] = (0, import_react7.useState)(0);
|
|
@@ -658,25 +662,23 @@ function AuthFormInner({
|
|
|
658
662
|
}
|
|
659
663
|
};
|
|
660
664
|
const handleNextSignupStep = () => {
|
|
661
|
-
if (signupStep === "
|
|
662
|
-
if (requireNames) setSignupStep("NAME");
|
|
663
|
-
else if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
664
|
-
else setSignupStep("PHONE_ID");
|
|
665
|
-
} else if (signupStep === "NAME") {
|
|
665
|
+
if (signupStep === "NAME") {
|
|
666
666
|
if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
667
667
|
else setSignupStep("PHONE_ID");
|
|
668
668
|
} else if (signupStep === "ORGANIZATION") {
|
|
669
669
|
setSignupStep("PHONE_ID");
|
|
670
|
+
} else if (signupStep === "PHONE_ID") {
|
|
671
|
+
setSignupStep("INVITATION");
|
|
670
672
|
}
|
|
671
673
|
};
|
|
672
674
|
const isContinueDisabled = () => {
|
|
673
675
|
if (isSubmitting) return true;
|
|
674
676
|
if (mode === "LOGIN") return phoneNumber.length < 5;
|
|
675
677
|
if (mode === "SIGNUP") {
|
|
676
|
-
if (signupStep === "INVITATION") return invitationCode.trim().length > 0 && invitationCode.trim().length < 3;
|
|
677
678
|
if (signupStep === "NAME") return firstName.trim() === "" || lastName.trim() === "";
|
|
678
679
|
if (signupStep === "ORGANIZATION") return orgName.trim().length < 3;
|
|
679
680
|
if (signupStep === "PHONE_ID") return phoneNumber.length < 5 || !agreedToTerms;
|
|
681
|
+
if (signupStep === "INVITATION") return invitationCode.trim().length > 0 && invitationCode.trim().length < 3;
|
|
680
682
|
}
|
|
681
683
|
return false;
|
|
682
684
|
};
|
|
@@ -687,26 +689,16 @@ function AuthFormInner({
|
|
|
687
689
|
onClose: () => setIsCountryDialogOpen(false),
|
|
688
690
|
onSelect: setSelectedCountry
|
|
689
691
|
}
|
|
690
|
-
), /* @__PURE__ */ import_react7.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_react7.default.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "p-
|
|
692
|
+
), /* @__PURE__ */ import_react7.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_react7.default.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "p-6" }, step === "INPUT" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "mb-12 mt-2 text-left" }, /* @__PURE__ */ import_react7.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, mode === "LOGIN" ? `${companyName} ${workspaceLabel}` : "Create Account"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-[13px] text-neutral-500" }, mode === "LOGIN" ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, "Don't have an account? ", /* @__PURE__ */ import_react7.default.createElement("button", { type: "button", onClick: () => {
|
|
691
693
|
setMode("SIGNUP");
|
|
692
694
|
setSignupStep(getInitialSignupStep());
|
|
693
|
-
}, className: "text-black transition-colors ml-1" }, "Sign up")) : /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, "Already have an account? ", /* @__PURE__ */ import_react7.default.createElement("button", { type: "button", onClick: () => setMode("LOGIN"), className: "text-black transition-colors ml-1" }, "Log in")))), /* @__PURE__ */ import_react7.default.createElement("form", { className: "space-y-6", autoComplete: "off", onSubmit: (e) => {
|
|
695
|
+
}, className: "text-black transition-colors ml-1 font-medium" }, "Sign up")) : /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, "Already have an account? ", /* @__PURE__ */ import_react7.default.createElement("button", { type: "button", onClick: () => setMode("LOGIN"), className: "text-black transition-colors ml-1 font-medium" }, "Log in")))), /* @__PURE__ */ import_react7.default.createElement("form", { className: "space-y-6", autoComplete: "off", onSubmit: (e) => {
|
|
694
696
|
e.preventDefault();
|
|
695
|
-
if (mode === "SIGNUP" && signupStep === "
|
|
696
|
-
else if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
|
|
697
|
+
if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
|
|
697
698
|
else if (mode === "SIGNUP" && signupStep === "ORGANIZATION") handleNextSignupStep();
|
|
699
|
+
else if (mode === "SIGNUP" && signupStep === "PHONE_ID") handleNextSignupStep();
|
|
698
700
|
else handleAuthRequestSubmit();
|
|
699
|
-
} }, mode === "SIGNUP" && signupStep === "
|
|
700
|
-
"input",
|
|
701
|
-
{
|
|
702
|
-
type: "text",
|
|
703
|
-
value: invitationCode,
|
|
704
|
-
onChange: (e) => setInvitationCode(e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, "")),
|
|
705
|
-
autoFocus: true,
|
|
706
|
-
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300 tracking-widest",
|
|
707
|
-
placeholder: "Referral Code (Optional)"
|
|
708
|
-
}
|
|
709
|
-
))), mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ import_react7.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "First name" })), /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ import_react7.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Last name" }))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ import_react7.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Acme Corporation" }))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "PHONE_ID") && /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-6 animate-in fade-in duration-300" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
701
|
+
} }, mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in slide-in-from-right-4 duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ import_react7.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "First name" })), /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ import_react7.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Last name" }))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in slide-in-from-right-4 duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ import_react7.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Acme Corporation" }))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "PHONE_ID") && /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-6 animate-in fade-in slide-in-from-right-4 duration-300" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
710
702
|
PhoneInput,
|
|
711
703
|
{
|
|
712
704
|
label: "Phone Number",
|
|
@@ -716,7 +708,17 @@ function AuthFormInner({
|
|
|
716
708
|
onCountryClick: () => setIsCountryDialogOpen(true),
|
|
717
709
|
disabled: isSubmitting
|
|
718
710
|
}
|
|
719
|
-
), mode === "SIGNUP" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ import_react7.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_react7.default.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ import_react7.default.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Terms of Service"), " and ", /* @__PURE__ */ import_react7.default.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Privacy Policy"), "."))),
|
|
711
|
+
), mode === "SIGNUP" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ import_react7.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_react7.default.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ import_react7.default.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline font-medium" }, "Terms of Service"), " and ", /* @__PURE__ */ import_react7.default.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline font-medium" }, "Privacy Policy"), "."))), mode === "SIGNUP" && signupStep === "INVITATION" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in slide-in-from-right-4 duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Referral Code"), /* @__PURE__ */ import_react7.default.createElement(
|
|
712
|
+
"input",
|
|
713
|
+
{
|
|
714
|
+
type: "text",
|
|
715
|
+
value: invitationCode,
|
|
716
|
+
onChange: (e) => setInvitationCode(e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, "")),
|
|
717
|
+
autoFocus: true,
|
|
718
|
+
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300 tracking-widest",
|
|
719
|
+
placeholder: "Referral Code (Optional)"
|
|
720
|
+
}
|
|
721
|
+
))), /* @__PURE__ */ import_react7.default.createElement(ThreeDActionButton, { type: "submit", disabled: isContinueDisabled(), isLoading: isSubmitting, className: "w-full mt-10" }, mode === "SIGNUP" && signupStep === "INVITATION" ? "Complete Setup" : "Continue"))), step === "OTP" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-left mb-10 mt-2" }, /* @__PURE__ */ import_react7.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react7.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter your 6-digit verification code.")), /* @__PURE__ */ import_react7.default.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
|
|
720
722
|
e.preventDefault();
|
|
721
723
|
verifyOtpCode(otp.join(""));
|
|
722
724
|
} }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ import_react7.default.createElement(
|
|
@@ -734,7 +736,7 @@ function AuthFormInner({
|
|
|
734
736
|
onKeyDown: (e) => {
|
|
735
737
|
if (e.key === "Backspace" && !otp[index] && index > 0) inputRefs.current[index - 1]?.focus();
|
|
736
738
|
},
|
|
737
|
-
className: "w-
|
|
739
|
+
className: "w-7 h-12 text-center text-sm bg-transparent border-b-2 border-neutral-200 text-black outline-none focus:border-black transition-all duration-300"
|
|
738
740
|
}
|
|
739
741
|
))), /* @__PURE__ */ import_react7.default.createElement(ThreeDActionButton, { type: "submit", disabled: otp.join("").length < 6, isLoading: isSubmitting, className: "w-full" }, "Verify Code")), userHasPasskey && /* @__PURE__ */ import_react7.default.createElement("div", { className: "pt-6" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
740
742
|
"button",
|
package/dist/index.mjs
CHANGED
|
@@ -304,7 +304,7 @@ import React5, { useState as useState3 } from "react";
|
|
|
304
304
|
var InputSpinner = () => /* @__PURE__ */ React5.createElement("svg", { className: "animate-spin h-3 w-3 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" }));
|
|
305
305
|
var FlagImage = ({ countryCode }) => {
|
|
306
306
|
const [loaded, setLoaded] = useState3(false);
|
|
307
|
-
return /* @__PURE__ */ React5.createElement("div", { className: "relative w-6 h-6 rounded-full overflow-hidden flex items-center justify-center bg-neutral-100 shrink-0
|
|
307
|
+
return /* @__PURE__ */ React5.createElement("div", { className: "relative w-6 h-6 rounded-full overflow-hidden flex items-center justify-center bg-neutral-100 shrink-0" }, !loaded && /* @__PURE__ */ React5.createElement("div", { className: "absolute inset-0 flex items-center justify-center" }, /* @__PURE__ */ React5.createElement(InputSpinner, null)), /* @__PURE__ */ React5.createElement(
|
|
308
308
|
"img",
|
|
309
309
|
{
|
|
310
310
|
src: `https://flagcdn.com/w40/${countryCode.toLowerCase()}.png`,
|
|
@@ -405,7 +405,7 @@ var SUPPORTED_COUNTRIES = [
|
|
|
405
405
|
{ code: "GH", dialCode: "+233", name: "Ghana" },
|
|
406
406
|
{ code: "KE", dialCode: "+254", name: "Kenya" }
|
|
407
407
|
];
|
|
408
|
-
var InputSpinner2 = () => /* @__PURE__ */ React6.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__ */ React6.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React6.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0
|
|
408
|
+
var InputSpinner2 = () => /* @__PURE__ */ React6.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__ */ React6.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React6.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
409
409
|
var CountrySelectorDialog = ({ isOpen, onClose, onSelect }) => {
|
|
410
410
|
if (!isOpen) return null;
|
|
411
411
|
return /* @__PURE__ */ React6.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40" }, /* @__PURE__ */ React6.createElement("div", { className: "absolute inset-0", onClick: onClose }), /* @__PURE__ */ React6.createElement("div", { className: "w-full max-w-sm bg-white rounded-2xl shadow-2xl overflow-hidden relative z-10 animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ React6.createElement(
|
|
@@ -427,7 +427,7 @@ var CountrySelectorDialog = ({ isOpen, onClose, onSelect }) => {
|
|
|
427
427
|
},
|
|
428
428
|
/* @__PURE__ */ React6.createElement(FlagImage, { countryCode: c.code }),
|
|
429
429
|
/* @__PURE__ */ React6.createElement("span", { className: "text-sm text-black flex-1 font-medium" }, c.name),
|
|
430
|
-
/* @__PURE__ */ React6.createElement("span", { className: "text-sm text-neutral-
|
|
430
|
+
/* @__PURE__ */ React6.createElement("span", { className: "text-sm text-neutral-400 " }, c.dialCode)
|
|
431
431
|
))))));
|
|
432
432
|
};
|
|
433
433
|
function AuthFormInner({
|
|
@@ -447,7 +447,11 @@ function AuthFormInner({
|
|
|
447
447
|
const captchaContext = useRecaptcha ? useGoogleReCaptcha() : null;
|
|
448
448
|
const [mode, setMode] = useState4("LOGIN");
|
|
449
449
|
const [step, setStep] = useState4("INPUT");
|
|
450
|
-
const getInitialSignupStep = () =>
|
|
450
|
+
const getInitialSignupStep = () => {
|
|
451
|
+
if (requireNames) return "NAME";
|
|
452
|
+
if (requireOrganization) return "ORGANIZATION";
|
|
453
|
+
return "PHONE_ID";
|
|
454
|
+
};
|
|
451
455
|
const [signupStep, setSignupStep] = useState4(getInitialSignupStep());
|
|
452
456
|
const [isSubmitting, setIsSubmitting] = useState4(false);
|
|
453
457
|
const [countdown, setCountdown] = useState4(0);
|
|
@@ -579,25 +583,23 @@ function AuthFormInner({
|
|
|
579
583
|
}
|
|
580
584
|
};
|
|
581
585
|
const handleNextSignupStep = () => {
|
|
582
|
-
if (signupStep === "
|
|
583
|
-
if (requireNames) setSignupStep("NAME");
|
|
584
|
-
else if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
585
|
-
else setSignupStep("PHONE_ID");
|
|
586
|
-
} else if (signupStep === "NAME") {
|
|
586
|
+
if (signupStep === "NAME") {
|
|
587
587
|
if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
588
588
|
else setSignupStep("PHONE_ID");
|
|
589
589
|
} else if (signupStep === "ORGANIZATION") {
|
|
590
590
|
setSignupStep("PHONE_ID");
|
|
591
|
+
} else if (signupStep === "PHONE_ID") {
|
|
592
|
+
setSignupStep("INVITATION");
|
|
591
593
|
}
|
|
592
594
|
};
|
|
593
595
|
const isContinueDisabled = () => {
|
|
594
596
|
if (isSubmitting) return true;
|
|
595
597
|
if (mode === "LOGIN") return phoneNumber.length < 5;
|
|
596
598
|
if (mode === "SIGNUP") {
|
|
597
|
-
if (signupStep === "INVITATION") return invitationCode.trim().length > 0 && invitationCode.trim().length < 3;
|
|
598
599
|
if (signupStep === "NAME") return firstName.trim() === "" || lastName.trim() === "";
|
|
599
600
|
if (signupStep === "ORGANIZATION") return orgName.trim().length < 3;
|
|
600
601
|
if (signupStep === "PHONE_ID") return phoneNumber.length < 5 || !agreedToTerms;
|
|
602
|
+
if (signupStep === "INVITATION") return invitationCode.trim().length > 0 && invitationCode.trim().length < 3;
|
|
601
603
|
}
|
|
602
604
|
return false;
|
|
603
605
|
};
|
|
@@ -608,26 +610,16 @@ function AuthFormInner({
|
|
|
608
610
|
onClose: () => setIsCountryDialogOpen(false),
|
|
609
611
|
onSelect: setSelectedCountry
|
|
610
612
|
}
|
|
611
|
-
), /* @__PURE__ */ React6.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__ */ React6.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ React6.createElement("div", { className: "p-
|
|
613
|
+
), /* @__PURE__ */ React6.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__ */ React6.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ React6.createElement("div", { className: "p-6" }, step === "INPUT" && /* @__PURE__ */ React6.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React6.createElement("div", { className: "mb-12 mt-2 text-left" }, /* @__PURE__ */ React6.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, mode === "LOGIN" ? `${companyName} ${workspaceLabel}` : "Create Account"), /* @__PURE__ */ React6.createElement("div", { className: "text-[13px] text-neutral-500" }, mode === "LOGIN" ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, "Don't have an account? ", /* @__PURE__ */ React6.createElement("button", { type: "button", onClick: () => {
|
|
612
614
|
setMode("SIGNUP");
|
|
613
615
|
setSignupStep(getInitialSignupStep());
|
|
614
|
-
}, className: "text-black transition-colors ml-1" }, "Sign up")) : /* @__PURE__ */ React6.createElement(React6.Fragment, null, "Already have an account? ", /* @__PURE__ */ React6.createElement("button", { type: "button", onClick: () => setMode("LOGIN"), className: "text-black transition-colors ml-1" }, "Log in")))), /* @__PURE__ */ React6.createElement("form", { className: "space-y-6", autoComplete: "off", onSubmit: (e) => {
|
|
616
|
+
}, className: "text-black transition-colors ml-1 font-medium" }, "Sign up")) : /* @__PURE__ */ React6.createElement(React6.Fragment, null, "Already have an account? ", /* @__PURE__ */ React6.createElement("button", { type: "button", onClick: () => setMode("LOGIN"), className: "text-black transition-colors ml-1 font-medium" }, "Log in")))), /* @__PURE__ */ React6.createElement("form", { className: "space-y-6", autoComplete: "off", onSubmit: (e) => {
|
|
615
617
|
e.preventDefault();
|
|
616
|
-
if (mode === "SIGNUP" && signupStep === "
|
|
617
|
-
else if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
|
|
618
|
+
if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
|
|
618
619
|
else if (mode === "SIGNUP" && signupStep === "ORGANIZATION") handleNextSignupStep();
|
|
620
|
+
else if (mode === "SIGNUP" && signupStep === "PHONE_ID") handleNextSignupStep();
|
|
619
621
|
else handleAuthRequestSubmit();
|
|
620
|
-
} }, mode === "SIGNUP" && signupStep === "
|
|
621
|
-
"input",
|
|
622
|
-
{
|
|
623
|
-
type: "text",
|
|
624
|
-
value: invitationCode,
|
|
625
|
-
onChange: (e) => setInvitationCode(e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, "")),
|
|
626
|
-
autoFocus: true,
|
|
627
|
-
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300 tracking-widest",
|
|
628
|
-
placeholder: "Referral Code (Optional)"
|
|
629
|
-
}
|
|
630
|
-
))), mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ React6.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React6.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ React6.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "First name" })), /* @__PURE__ */ React6.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React6.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ React6.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Last name" }))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ React6.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React6.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ React6.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Acme Corporation" }))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "PHONE_ID") && /* @__PURE__ */ React6.createElement("div", { className: "space-y-6 animate-in fade-in duration-300" }, /* @__PURE__ */ React6.createElement(
|
|
622
|
+
} }, mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in slide-in-from-right-4 duration-300" }, /* @__PURE__ */ React6.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React6.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ React6.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "First name" })), /* @__PURE__ */ React6.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React6.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ React6.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Last name" }))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in slide-in-from-right-4 duration-300" }, /* @__PURE__ */ React6.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React6.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ React6.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-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Acme Corporation" }))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "PHONE_ID") && /* @__PURE__ */ React6.createElement("div", { className: "space-y-6 animate-in fade-in slide-in-from-right-4 duration-300" }, /* @__PURE__ */ React6.createElement(
|
|
631
623
|
PhoneInput,
|
|
632
624
|
{
|
|
633
625
|
label: "Phone Number",
|
|
@@ -637,7 +629,17 @@ function AuthFormInner({
|
|
|
637
629
|
onCountryClick: () => setIsCountryDialogOpen(true),
|
|
638
630
|
disabled: isSubmitting
|
|
639
631
|
}
|
|
640
|
-
), mode === "SIGNUP" && /* @__PURE__ */ React6.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ React6.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__ */ React6.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ React6.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Terms of Service"), " and ", /* @__PURE__ */ React6.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Privacy Policy"), "."))),
|
|
632
|
+
), mode === "SIGNUP" && /* @__PURE__ */ React6.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ React6.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__ */ React6.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ React6.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline font-medium" }, "Terms of Service"), " and ", /* @__PURE__ */ React6.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline font-medium" }, "Privacy Policy"), "."))), mode === "SIGNUP" && signupStep === "INVITATION" && /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in slide-in-from-right-4 duration-300" }, /* @__PURE__ */ React6.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React6.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Referral Code"), /* @__PURE__ */ React6.createElement(
|
|
633
|
+
"input",
|
|
634
|
+
{
|
|
635
|
+
type: "text",
|
|
636
|
+
value: invitationCode,
|
|
637
|
+
onChange: (e) => setInvitationCode(e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, "")),
|
|
638
|
+
autoFocus: true,
|
|
639
|
+
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300 tracking-widest",
|
|
640
|
+
placeholder: "Referral Code (Optional)"
|
|
641
|
+
}
|
|
642
|
+
))), /* @__PURE__ */ React6.createElement(ThreeDActionButton, { type: "submit", disabled: isContinueDisabled(), isLoading: isSubmitting, className: "w-full mt-10" }, mode === "SIGNUP" && signupStep === "INVITATION" ? "Complete Setup" : "Continue"))), step === "OTP" && /* @__PURE__ */ React6.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React6.createElement("div", { className: "text-left mb-10 mt-2" }, /* @__PURE__ */ React6.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ React6.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter your 6-digit verification code.")), /* @__PURE__ */ React6.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
|
|
641
643
|
e.preventDefault();
|
|
642
644
|
verifyOtpCode(otp.join(""));
|
|
643
645
|
} }, /* @__PURE__ */ React6.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ React6.createElement(
|
|
@@ -655,7 +657,7 @@ function AuthFormInner({
|
|
|
655
657
|
onKeyDown: (e) => {
|
|
656
658
|
if (e.key === "Backspace" && !otp[index] && index > 0) inputRefs.current[index - 1]?.focus();
|
|
657
659
|
},
|
|
658
|
-
className: "w-
|
|
660
|
+
className: "w-7 h-12 text-center text-sm bg-transparent border-b-2 border-neutral-200 text-black outline-none focus:border-black transition-all duration-300"
|
|
659
661
|
}
|
|
660
662
|
))), /* @__PURE__ */ React6.createElement(ThreeDActionButton, { type: "submit", disabled: otp.join("").length < 6, isLoading: isSubmitting, className: "w-full" }, "Verify Code")), userHasPasskey && /* @__PURE__ */ React6.createElement("div", { className: "pt-6" }, /* @__PURE__ */ React6.createElement(
|
|
661
663
|
"button",
|