@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 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 border border-neutral-200" }, !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(
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 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
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-500 font-mono" }, c.dialCode)
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 = () => "INVITATION";
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 === "INVITATION") {
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-8 md:p-12" }, step === "INPUT" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "mb-12 text-center mt-2" }, /* @__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: () => {
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 === "INVITATION") handleNextSignupStep();
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 === "INVITATION" && /* @__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 " }, "Referral Code"), /* @__PURE__ */ import_react7.default.createElement(
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"), "."))), /* @__PURE__ */ import_react7.default.createElement(ThreeDActionButton, { type: "submit", disabled: isContinueDisabled(), isLoading: isSubmitting, className: "w-full mt-10" }, "Continue"))), step === "OTP" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center 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 security passcode or OTP.")), /* @__PURE__ */ import_react7.default.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
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-10 h-12 text-center text-lg bg-transparent border-b-2 border-neutral-200 text-black outline-none focus:border-black transition-all duration-300"
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 border border-neutral-200" }, !loaded && /* @__PURE__ */ React5.createElement("div", { className: "absolute inset-0 flex items-center justify-center" }, /* @__PURE__ */ React5.createElement(InputSpinner, null)), /* @__PURE__ */ React5.createElement(
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 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
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-500 font-mono" }, c.dialCode)
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 = () => "INVITATION";
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 === "INVITATION") {
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-8 md:p-12" }, step === "INPUT" && /* @__PURE__ */ React6.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React6.createElement("div", { className: "mb-12 text-center mt-2" }, /* @__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: () => {
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 === "INVITATION") handleNextSignupStep();
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 === "INVITATION" && /* @__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 " }, "Referral Code"), /* @__PURE__ */ React6.createElement(
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"), "."))), /* @__PURE__ */ React6.createElement(ThreeDActionButton, { type: "submit", disabled: isContinueDisabled(), isLoading: isSubmitting, className: "w-full mt-10" }, "Continue"))), step === "OTP" && /* @__PURE__ */ React6.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React6.createElement("div", { className: "text-center 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 security passcode or OTP.")), /* @__PURE__ */ React6.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
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-10 h-12 text-center text-lg bg-transparent border-b-2 border-neutral-200 text-black outline-none focus:border-black transition-all duration-300"
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",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retinalabsllc/zairusjs",
3
- "version": "15.1.2",
3
+ "version": "15.1.15",
4
4
  "description": "A perceptive, Ai data driven Next.js UI component library.",
5
5
  "author": "Retina Labs Company",
6
6
  "license": "MIT",