@retinalabsllc/zairusjs 16.0.50 → 16.0.70
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 +3 -7
- package/dist/index.d.ts +3 -7
- package/dist/index.js +163 -301
- package/dist/index.mjs +159 -297
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -293,141 +293,17 @@ var Header = ({
|
|
|
293
293
|
};
|
|
294
294
|
|
|
295
295
|
// src/components/PipleAuth.tsx
|
|
296
|
-
import
|
|
296
|
+
import React5, { useState as useState3, useRef as useRef2, useEffect as useEffect3, Suspense } from "react";
|
|
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
300
|
import { startAuthentication } from "@simplewebauthn/browser";
|
|
301
|
-
|
|
302
|
-
// src/components/TextInput.tsx
|
|
303
|
-
import React5, { useState as useState3 } from "react";
|
|
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
|
-
var getCustomFlagUrl = (code) => {
|
|
306
|
-
const map = {
|
|
307
|
-
"NG": "https://retinalabs.company/assets/images/ng.avif",
|
|
308
|
-
"GH": "https://retinalabs.company/assets/images/gh.avif",
|
|
309
|
-
"KE": "https://retinalabs.company/assets/images/ksh.avif",
|
|
310
|
-
"UG": "https://retinalabs.company/assets/images/ugx.avif"
|
|
311
|
-
};
|
|
312
|
-
return map[code?.toUpperCase()] || map["NG"];
|
|
313
|
-
};
|
|
314
|
-
var FlagImage = ({ countryCode }) => {
|
|
315
|
-
const [loaded, setLoaded] = useState3(false);
|
|
316
|
-
return /* @__PURE__ */ React5.createElement("div", { className: "relative w-5 h-5 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(
|
|
317
|
-
"img",
|
|
318
|
-
{
|
|
319
|
-
src: getCustomFlagUrl(countryCode),
|
|
320
|
-
alt: countryCode,
|
|
321
|
-
className: `object-cover w-full h-full transition-opacity duration-300 ${loaded ? "opacity-100" : "opacity-0"}`,
|
|
322
|
-
onLoad: () => setLoaded(true)
|
|
323
|
-
}
|
|
324
|
-
));
|
|
325
|
-
};
|
|
326
|
-
var TextInput = ({
|
|
327
|
-
label,
|
|
328
|
-
value,
|
|
329
|
-
onChange,
|
|
330
|
-
placeholder,
|
|
331
|
-
maxLength,
|
|
332
|
-
disabled,
|
|
333
|
-
readOnly,
|
|
334
|
-
type = "text",
|
|
335
|
-
onClick
|
|
336
|
-
}) => /* @__PURE__ */ React5.createElement("div", { className: "space-y-2 flex-1 w-full", onClick }, label && /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, label), /* @__PURE__ */ React5.createElement(
|
|
337
|
-
"input",
|
|
338
|
-
{
|
|
339
|
-
type,
|
|
340
|
-
value,
|
|
341
|
-
onChange: (e) => onChange(e.target.value.substring(0, maxLength || 100)),
|
|
342
|
-
placeholder,
|
|
343
|
-
disabled,
|
|
344
|
-
readOnly,
|
|
345
|
-
autoComplete: "off",
|
|
346
|
-
spellCheck: "false",
|
|
347
|
-
className: `w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black transition-all outline-none focus:border-black disabled:opacity-50 ${readOnly ? "cursor-pointer" : ""}`
|
|
348
|
-
}
|
|
349
|
-
));
|
|
350
|
-
var NumberInput = ({
|
|
351
|
-
label,
|
|
352
|
-
value,
|
|
353
|
-
onChange,
|
|
354
|
-
placeholder,
|
|
355
|
-
maxLength,
|
|
356
|
-
disabled
|
|
357
|
-
}) => /* @__PURE__ */ React5.createElement("div", { className: "space-y-2 flex-1 w-full" }, label && /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, label), /* @__PURE__ */ React5.createElement(
|
|
358
|
-
"input",
|
|
359
|
-
{
|
|
360
|
-
type: "text",
|
|
361
|
-
value,
|
|
362
|
-
onChange: (e) => {
|
|
363
|
-
const numOnly = e.target.value.replace(/[^0-9]/g, "");
|
|
364
|
-
onChange(numOnly.substring(0, maxLength || 20));
|
|
365
|
-
},
|
|
366
|
-
placeholder,
|
|
367
|
-
disabled,
|
|
368
|
-
autoComplete: "off",
|
|
369
|
-
spellCheck: "false",
|
|
370
|
-
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black transition-all outline-none focus:border-black disabled:opacity-50"
|
|
371
|
-
}
|
|
372
|
-
));
|
|
373
|
-
var PhoneInput = ({
|
|
374
|
-
label,
|
|
375
|
-
value,
|
|
376
|
-
onChange,
|
|
377
|
-
selectedCountry,
|
|
378
|
-
onCountryClick,
|
|
379
|
-
placeholder,
|
|
380
|
-
disabled
|
|
381
|
-
}) => /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5 flex-1 w-full" }, label && /* @__PURE__ */ React5.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, label), /* @__PURE__ */ React5.createElement("div", { className: `flex items-center gap-3 border-b border-neutral-200 focus-within:border-black transition-all duration-300 pb-2 ${disabled ? "opacity-50" : ""}` }, /* @__PURE__ */ React5.createElement(
|
|
382
|
-
"button",
|
|
383
|
-
{
|
|
384
|
-
type: "button",
|
|
385
|
-
disabled,
|
|
386
|
-
onClick: onCountryClick,
|
|
387
|
-
className: "flex items-center gap-1.5 outline-none hover:opacity-80 transition-opacity"
|
|
388
|
-
},
|
|
389
|
-
/* @__PURE__ */ React5.createElement(FlagImage, { countryCode: selectedCountry.code }),
|
|
390
|
-
/* @__PURE__ */ React5.createElement("span", { className: "text-sm text-black pl-1" }, selectedCountry.dialCode),
|
|
391
|
-
/* @__PURE__ */ React5.createElement("svg", { className: "w-3 h-3 text-neutral-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React5.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))
|
|
392
|
-
), /* @__PURE__ */ React5.createElement(
|
|
393
|
-
"input",
|
|
394
|
-
{
|
|
395
|
-
type: "tel",
|
|
396
|
-
value,
|
|
397
|
-
onChange: (e) => {
|
|
398
|
-
const numOnly = e.target.value.replace(/[^0-9]/g, "");
|
|
399
|
-
onChange(numOnly.substring(0, 15));
|
|
400
|
-
},
|
|
401
|
-
disabled,
|
|
402
|
-
required: true,
|
|
403
|
-
autoFocus: true,
|
|
404
|
-
autoComplete: "off",
|
|
405
|
-
spellCheck: "false",
|
|
406
|
-
className: "w-full text-sm bg-transparent text-black outline-none pt-1",
|
|
407
|
-
placeholder: placeholder || "0801 234 5678"
|
|
408
|
-
}
|
|
409
|
-
)));
|
|
410
|
-
|
|
411
|
-
// src/components/PipleAuth.tsx
|
|
412
|
-
var SUPPORTED_COUNTRIES = [
|
|
413
|
-
{ code: "NG", dialCode: "+234", name: "Nigeria" },
|
|
414
|
-
{ code: "GH", dialCode: "+233", name: "Ghana" },
|
|
415
|
-
{ code: "KE", dialCode: "+254", name: "Kenya" },
|
|
416
|
-
{ code: "UG", dialCode: "+256", name: "Uganda" }
|
|
417
|
-
];
|
|
418
|
-
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" }));
|
|
419
|
-
var CountrySelectorDialog = ({ isOpen, onClose, onSelect }) => {
|
|
420
|
-
if (!isOpen) return null;
|
|
421
|
-
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("button", { onClick: onClose, className: "absolute top-4 right-4 p-2 text-neutral-700 hover:text-neutral-400 transition-colors outline-none" }, /* @__PURE__ */ React6.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React6.createElement("path", { d: "M18 6 6 18" }), /* @__PURE__ */ React6.createElement("path", { d: "m6 6 12 12" }))), /* @__PURE__ */ React6.createElement("div", { className: "p-6 sm:p-8" }, /* @__PURE__ */ React6.createElement("div", { className: "mb-6 mt-2" }, /* @__PURE__ */ React6.createElement("h2", { className: "text-xl text-black tracking-tight mb-2" }, "Select Country"), /* @__PURE__ */ React6.createElement("p", { className: "text-[13px] text-neutral-500 leading-relaxed" }, "Choose your region to continue.")), /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col gap-2" }, SUPPORTED_COUNTRIES.map((c) => /* @__PURE__ */ React6.createElement("button", { key: c.code, onClick: () => {
|
|
422
|
-
onSelect(c);
|
|
423
|
-
onClose();
|
|
424
|
-
}, className: "flex items-center gap-4 p-3 rounded-xl hover:bg-neutral-50 transition-colors text-left outline-none" }, /* @__PURE__ */ React6.createElement(FlagImage, { countryCode: c.code }), /* @__PURE__ */ React6.createElement("span", { className: "text-sm text-black flex-1 " }, c.name), /* @__PURE__ */ React6.createElement("span", { className: "text-sm text-neutral-400 " }, c.dialCode)))))));
|
|
425
|
-
};
|
|
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" }));
|
|
426
302
|
function AuthFormInner({
|
|
427
303
|
companyName,
|
|
428
304
|
workspaceLabel = "Workspace",
|
|
429
|
-
termsUrl = "https://
|
|
430
|
-
privacyUrl = "https://
|
|
305
|
+
termsUrl = "https://truhuddle.com/terms-of-service",
|
|
306
|
+
privacyUrl = "https://truhuddle.com/privacy-policy",
|
|
431
307
|
requireNames = true,
|
|
432
308
|
requireOrganization = true,
|
|
433
309
|
useRecaptcha = false,
|
|
@@ -438,76 +314,64 @@ function AuthFormInner({
|
|
|
438
314
|
const searchParams = useSearchParams();
|
|
439
315
|
const redirectUrl = searchParams.get("redirect") || defaultRedirectPath;
|
|
440
316
|
const captchaContext = useRecaptcha ? useGoogleReCaptcha() : null;
|
|
441
|
-
const [mode, setMode] =
|
|
442
|
-
const [step, setStep] =
|
|
317
|
+
const [mode, setMode] = useState3("LOGIN");
|
|
318
|
+
const [step, setStep] = useState3("INPUT");
|
|
443
319
|
const getInitialSignupStep = () => {
|
|
444
|
-
|
|
445
|
-
if (requireOrganization) return "ORGANIZATION";
|
|
446
|
-
return "PHONE_ID";
|
|
320
|
+
return "INVITATION";
|
|
447
321
|
};
|
|
448
|
-
const [signupStep, setSignupStep] =
|
|
449
|
-
const [isSubmitting, setIsSubmitting] =
|
|
450
|
-
const [countdown, setCountdown] =
|
|
451
|
-
const [invitationCode, setInvitationCode] =
|
|
452
|
-
const [
|
|
453
|
-
const [
|
|
454
|
-
const [
|
|
455
|
-
const [
|
|
456
|
-
const [
|
|
457
|
-
const [
|
|
458
|
-
const [
|
|
459
|
-
const [
|
|
460
|
-
const [
|
|
461
|
-
const
|
|
462
|
-
const [passcode, setPasscode] = useState4(["", "", "", "", "", ""]);
|
|
463
|
-
const otpRefs = useRef2([]);
|
|
464
|
-
const passRefs = useRef2([]);
|
|
322
|
+
const [signupStep, setSignupStep] = useState3(getInitialSignupStep());
|
|
323
|
+
const [isSubmitting, setIsSubmitting] = useState3(false);
|
|
324
|
+
const [countdown, setCountdown] = useState3(0);
|
|
325
|
+
const [invitationCode, setInvitationCode] = useState3("");
|
|
326
|
+
const [emailId, setEmailId] = useState3("");
|
|
327
|
+
const [firstName, setFirstName] = useState3("");
|
|
328
|
+
const [lastName, setLastName] = useState3("");
|
|
329
|
+
const [orgName, setOrgName] = useState3("");
|
|
330
|
+
const [agreedToTerms, setAgreedToTerms] = useState3(false);
|
|
331
|
+
const [userHas2FA, setUserHas2FA] = useState3(false);
|
|
332
|
+
const [userHasPasskey, setUserHasPasskey] = useState3(false);
|
|
333
|
+
const [authOptions, setAuthOptions] = useState3(null);
|
|
334
|
+
const [otp, setOtp] = useState3(["", "", "", "", "", ""]);
|
|
335
|
+
const inputRefs = useRef2([]);
|
|
465
336
|
const cleanAlpha = (val) => val.replace(/[^a-zA-Z]/g, "").substring(0, 50);
|
|
466
337
|
const cleanOrgName = (val) => val.replace(/[^a-zA-Z0-9\s]/g, "").substring(0, 50);
|
|
338
|
+
const cleanEmailId = (val) => val.toLowerCase().replace(/[^a-z0-9@._-]/g, "");
|
|
467
339
|
useEffect3(() => {
|
|
468
340
|
if (countdown > 0) {
|
|
469
341
|
const timer = setTimeout(() => setCountdown(countdown - 1), 1e3);
|
|
470
342
|
return () => clearTimeout(timer);
|
|
471
343
|
}
|
|
472
344
|
}, [countdown]);
|
|
473
|
-
const
|
|
345
|
+
const handleOtpChange = (index, value) => {
|
|
474
346
|
const cleanValue = value.replace(/[^0-9]/g, "");
|
|
475
347
|
if (!cleanValue && value !== "") return;
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
setArr(arr);
|
|
481
|
-
if (cleanValue && index < 5) refs.current[index + 1]?.focus();
|
|
348
|
+
const newOtp = [...otp];
|
|
349
|
+
newOtp[index] = cleanValue.slice(-1);
|
|
350
|
+
setOtp(newOtp);
|
|
351
|
+
if (cleanValue && index < 5) inputRefs.current[index + 1]?.focus();
|
|
482
352
|
};
|
|
483
|
-
const
|
|
353
|
+
const handlePaste = (e) => {
|
|
484
354
|
e.preventDefault();
|
|
485
355
|
const pastedData = e.clipboardData.getData("text/plain");
|
|
486
356
|
const numbersOnly = pastedData.replace(/[^0-9]/g, "");
|
|
487
357
|
if (!numbersOnly) return;
|
|
488
|
-
const
|
|
489
|
-
const setArr = isPasscode ? setPasscode : setOtp;
|
|
490
|
-
const refs = isPasscode ? passRefs : otpRefs;
|
|
358
|
+
const newOtp = [...otp];
|
|
491
359
|
const length = Math.min(numbersOnly.length, 6);
|
|
492
|
-
for (let i = 0; i < length; i++)
|
|
493
|
-
|
|
494
|
-
if (length < 6)
|
|
360
|
+
for (let i = 0; i < length; i++) newOtp[i] = numbersOnly[i];
|
|
361
|
+
setOtp(newOtp);
|
|
362
|
+
if (length < 6) inputRefs.current[length]?.focus();
|
|
495
363
|
else {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
else verifyOtpCode(arr.join(""));
|
|
364
|
+
inputRefs.current[5]?.focus();
|
|
365
|
+
verifyOtpCode(newOtp.join(""));
|
|
499
366
|
}
|
|
500
367
|
};
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
return `${selectedCountry.dialCode}${cleanNumber}`;
|
|
504
|
-
};
|
|
505
|
-
const handleAuthRequestSubmit = async (forceOtp = false) => {
|
|
368
|
+
const handleAuthRequestSubmit = async (e) => {
|
|
369
|
+
if (e) e.preventDefault();
|
|
506
370
|
if (mode === "SIGNUP" && !agreedToTerms) {
|
|
507
371
|
toast.error("You must agree to the Terms and Privacy Policy.");
|
|
508
372
|
return;
|
|
509
373
|
}
|
|
510
|
-
if (isSubmitting) return;
|
|
374
|
+
if (isSubmitting || countdown > 0) return;
|
|
511
375
|
setIsSubmitting(true);
|
|
512
376
|
try {
|
|
513
377
|
let recaptchaToken = void 0;
|
|
@@ -515,28 +379,21 @@ function AuthFormInner({
|
|
|
515
379
|
recaptchaToken = await captchaContext.executeRecaptcha("auth_request");
|
|
516
380
|
}
|
|
517
381
|
const res = await onAuthRequest({
|
|
518
|
-
|
|
519
|
-
country: selectedCountry.code,
|
|
382
|
+
email: emailId,
|
|
520
383
|
firstName: mode === "SIGNUP" && requireNames ? firstName : void 0,
|
|
521
384
|
lastName: mode === "SIGNUP" && requireNames ? lastName : void 0,
|
|
522
385
|
organizationName: mode === "SIGNUP" && requireOrganization ? orgName : void 0,
|
|
523
386
|
r_c: mode === "SIGNUP" && invitationCode.trim() ? invitationCode.trim().toUpperCase() : void 0,
|
|
524
387
|
mode,
|
|
525
|
-
recaptchaToken
|
|
526
|
-
forceOtp
|
|
388
|
+
recaptchaToken
|
|
527
389
|
});
|
|
528
390
|
if (res.success) {
|
|
391
|
+
setUserHas2FA(!!res.has2FA);
|
|
529
392
|
setUserHasPasskey(!!res.hasPasskey);
|
|
530
393
|
if (res.passkeyOptions) setAuthOptions(res.passkeyOptions);
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
} else {
|
|
535
|
-
setStep("OTP");
|
|
536
|
-
setCountdown(60);
|
|
537
|
-
toast.success("Verification code sent");
|
|
538
|
-
setTimeout(() => otpRefs.current[0]?.focus(), 100);
|
|
539
|
-
}
|
|
394
|
+
toast.success(res.has2FA ? "Security check required" : "Verification code sent");
|
|
395
|
+
setStep("OTP");
|
|
396
|
+
setCountdown(60);
|
|
540
397
|
} else {
|
|
541
398
|
toast.error(res.error || "Authentication failed.");
|
|
542
399
|
}
|
|
@@ -550,29 +407,13 @@ function AuthFormInner({
|
|
|
550
407
|
if (codeToVerify.length !== 6 || isSubmitting) return;
|
|
551
408
|
setIsSubmitting(true);
|
|
552
409
|
try {
|
|
553
|
-
const res = await onVerifyOtp({
|
|
554
|
-
if (res.success)
|
|
555
|
-
|
|
410
|
+
const res = await onVerifyOtp({ email: emailId, code: codeToVerify });
|
|
411
|
+
if (res.success) {
|
|
412
|
+
window.location.href = res.redirect || redirectUrl;
|
|
413
|
+
} else {
|
|
556
414
|
toast.error(res.error || "Invalid code.");
|
|
557
415
|
setOtp(["", "", "", "", "", ""]);
|
|
558
|
-
|
|
559
|
-
}
|
|
560
|
-
} catch {
|
|
561
|
-
toast.error("Verification failed.");
|
|
562
|
-
} finally {
|
|
563
|
-
setIsSubmitting(false);
|
|
564
|
-
}
|
|
565
|
-
};
|
|
566
|
-
const verifyPasscodeSubmit = async (passToVerify) => {
|
|
567
|
-
if (passToVerify.length !== 6 || isSubmitting) return;
|
|
568
|
-
setIsSubmitting(true);
|
|
569
|
-
try {
|
|
570
|
-
const res = await onVerifyOtp({ phoneNumber: getFormattedPhoneNumber(), passcode: passToVerify });
|
|
571
|
-
if (res.success) window.location.href = res.redirect || redirectUrl;
|
|
572
|
-
else {
|
|
573
|
-
toast.error(res.error || "Invalid passcode.");
|
|
574
|
-
setPasscode(["", "", "", "", "", ""]);
|
|
575
|
-
passRefs.current[0]?.focus();
|
|
416
|
+
inputRefs.current[0]?.focus();
|
|
576
417
|
}
|
|
577
418
|
} catch {
|
|
578
419
|
toast.error("Verification failed.");
|
|
@@ -585,9 +426,12 @@ function AuthFormInner({
|
|
|
585
426
|
setIsSubmitting(true);
|
|
586
427
|
try {
|
|
587
428
|
const credentialResponse = await startAuthentication({ optionsJSON: authOptions });
|
|
588
|
-
const res = await onVerifyOtp({
|
|
589
|
-
if (res.success)
|
|
590
|
-
|
|
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
|
+
}
|
|
591
435
|
} catch (err) {
|
|
592
436
|
if (err.name !== "NotAllowedError") toast.error("Passkey verification interrupted.");
|
|
593
437
|
} finally {
|
|
@@ -595,46 +439,38 @@ function AuthFormInner({
|
|
|
595
439
|
}
|
|
596
440
|
};
|
|
597
441
|
const handleNextSignupStep = () => {
|
|
598
|
-
if (signupStep === "
|
|
442
|
+
if (signupStep === "INVITATION") {
|
|
443
|
+
if (requireNames) setSignupStep("NAME");
|
|
444
|
+
else if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
445
|
+
else setSignupStep("EMAIL_ID");
|
|
446
|
+
} else if (signupStep === "NAME") {
|
|
599
447
|
if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
600
|
-
else setSignupStep("
|
|
448
|
+
else setSignupStep("EMAIL_ID");
|
|
601
449
|
} else if (signupStep === "ORGANIZATION") {
|
|
602
|
-
setSignupStep("
|
|
603
|
-
} else if (signupStep === "PHONE_ID") {
|
|
604
|
-
setSignupStep("INVITATION");
|
|
450
|
+
setSignupStep("EMAIL_ID");
|
|
605
451
|
}
|
|
606
452
|
};
|
|
607
453
|
const isContinueDisabled = () => {
|
|
608
454
|
if (isSubmitting) return true;
|
|
609
|
-
if (mode === "LOGIN") return
|
|
455
|
+
if (mode === "LOGIN") return emailId.length < 3;
|
|
610
456
|
if (mode === "SIGNUP") {
|
|
457
|
+
if (signupStep === "INVITATION") return invitationCode.trim().length > 0 && invitationCode.trim().length < 3;
|
|
611
458
|
if (signupStep === "NAME") return firstName.trim() === "" || lastName.trim() === "";
|
|
612
459
|
if (signupStep === "ORGANIZATION") return orgName.trim().length < 3;
|
|
613
|
-
if (signupStep === "
|
|
614
|
-
if (signupStep === "INVITATION") return invitationCode.trim().length > 0 && invitationCode.trim().length < 3;
|
|
460
|
+
if (signupStep === "EMAIL_ID") return emailId.length < 3 || !agreedToTerms;
|
|
615
461
|
}
|
|
616
462
|
return false;
|
|
617
463
|
};
|
|
618
|
-
return /* @__PURE__ */
|
|
464
|
+
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: () => {
|
|
619
465
|
setMode("SIGNUP");
|
|
620
466
|
setSignupStep(getInitialSignupStep());
|
|
621
|
-
}, className: "text-black transition-colors ml-1
|
|
467
|
+
}, 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) => {
|
|
622
468
|
e.preventDefault();
|
|
623
|
-
if (mode === "SIGNUP" && signupStep === "
|
|
469
|
+
if (mode === "SIGNUP" && signupStep === "INVITATION") handleNextSignupStep();
|
|
470
|
+
else if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
|
|
624
471
|
else if (mode === "SIGNUP" && signupStep === "ORGANIZATION") handleNextSignupStep();
|
|
625
|
-
else
|
|
626
|
-
|
|
627
|
-
} }, 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(
|
|
628
|
-
PhoneInput,
|
|
629
|
-
{
|
|
630
|
-
label: "Phone Number",
|
|
631
|
-
value: phoneNumber,
|
|
632
|
-
onChange: setPhoneNumber,
|
|
633
|
-
selectedCountry,
|
|
634
|
-
onCountryClick: () => setIsCountryDialogOpen(true),
|
|
635
|
-
disabled: isSubmitting
|
|
636
|
-
}
|
|
637
|
-
), 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"), "."))), 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(
|
|
472
|
+
else handleAuthRequestSubmit();
|
|
473
|
+
} }, mode === "SIGNUP" && signupStep === "INVITATION" && /* @__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 " }, "Referral Code"), /* @__PURE__ */ React5.createElement(
|
|
638
474
|
"input",
|
|
639
475
|
{
|
|
640
476
|
type: "text",
|
|
@@ -644,65 +480,45 @@ function AuthFormInner({
|
|
|
644
480
|
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",
|
|
645
481
|
placeholder: "Referral Code (Optional)"
|
|
646
482
|
}
|
|
647
|
-
))), /* @__PURE__ */
|
|
648
|
-
e.preventDefault();
|
|
649
|
-
verifyPasscodeSubmit(passcode.join(""));
|
|
650
|
-
} }, /* @__PURE__ */ React6.createElement("div", { className: "flex justify-between gap-2", onPaste: (e) => handleArrayPaste(e, true) }, passcode.map((digit, index) => /* @__PURE__ */ React6.createElement(
|
|
651
|
-
"input",
|
|
652
|
-
{
|
|
653
|
-
key: index,
|
|
654
|
-
ref: (el) => {
|
|
655
|
-
passRefs.current[index] = el;
|
|
656
|
-
},
|
|
657
|
-
type: "password",
|
|
658
|
-
inputMode: "numeric",
|
|
659
|
-
maxLength: 1,
|
|
660
|
-
value: digit,
|
|
661
|
-
onChange: (e) => handleArrayChange(index, e.target.value, true),
|
|
662
|
-
onKeyDown: (e) => {
|
|
663
|
-
if (e.key === "Backspace" && !passcode[index] && index > 0) passRefs.current[index - 1]?.focus();
|
|
664
|
-
},
|
|
665
|
-
className: "w-7 h-10 text-center text-lg bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300"
|
|
666
|
-
}
|
|
667
|
-
))), /* @__PURE__ */ React6.createElement(ThreeDActionButton, { type: "submit", disabled: passcode.join("").length < 6, isLoading: isSubmitting, className: "w-full" }, "Login")), /* @__PURE__ */ React6.createElement("div", { className: "pt-6 flex flex-col gap-3" }, userHasPasskey && /* @__PURE__ */ React6.createElement("button", { onClick: triggerPasskeyLogin, disabled: isSubmitting, className: "w-full py-2.5 rounded-full text-black border border-neutral-200 hover:bg-neutral-50 text-[11px] tracking-wide transition-colors outline-none disabled:opacity-50" }, "Use Passkey / Biometrics"), /* @__PURE__ */ React6.createElement("button", { onClick: () => handleAuthRequestSubmit(true), disabled: isSubmitting, className: "w-full text-center text-[12px] text-neutral-500 hover:text-black transition-colors outline-none mt-2" }, "Use OTP instead"))), 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) => {
|
|
483
|
+
))), 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-200 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-200 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-200 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-200 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) => {
|
|
668
484
|
e.preventDefault();
|
|
669
485
|
verifyOtpCode(otp.join(""));
|
|
670
|
-
} }, /* @__PURE__ */
|
|
486
|
+
} }, /* @__PURE__ */ React5.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ React5.createElement(
|
|
671
487
|
"input",
|
|
672
488
|
{
|
|
673
489
|
key: index,
|
|
674
490
|
ref: (el) => {
|
|
675
|
-
|
|
491
|
+
inputRefs.current[index] = el;
|
|
676
492
|
},
|
|
677
493
|
type: "text",
|
|
678
494
|
inputMode: "numeric",
|
|
679
495
|
maxLength: 1,
|
|
680
496
|
value: digit,
|
|
681
|
-
onChange: (e) =>
|
|
497
|
+
onChange: (e) => handleOtpChange(index, e.target.value),
|
|
682
498
|
onKeyDown: (e) => {
|
|
683
|
-
if (e.key === "Backspace" && !otp[index] && index > 0)
|
|
499
|
+
if (e.key === "Backspace" && !otp[index] && index > 0) inputRefs.current[index - 1]?.focus();
|
|
684
500
|
},
|
|
685
|
-
className: "w-
|
|
501
|
+
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"
|
|
686
502
|
}
|
|
687
|
-
))), /* @__PURE__ */
|
|
503
|
+
))), /* @__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(
|
|
688
504
|
"button",
|
|
689
505
|
{
|
|
690
|
-
onClick:
|
|
691
|
-
disabled:
|
|
692
|
-
className: "w-full
|
|
506
|
+
onClick: triggerPasskeyLogin,
|
|
507
|
+
disabled: isSubmitting,
|
|
508
|
+
className: "w-full py-2.5 rounded-full text-black border border-neutral-200 hover:bg-neutral-50 text-xs tracking-wide transition-colors outline-none disabled:opacity-50"
|
|
693
509
|
},
|
|
694
|
-
|
|
695
|
-
)
|
|
510
|
+
"Use Passkey / Biometrics"
|
|
511
|
+
))))));
|
|
696
512
|
}
|
|
697
513
|
var PipleAuth = (props) => {
|
|
698
514
|
if (props.useRecaptcha && props.recaptchaSiteKey) {
|
|
699
|
-
return /* @__PURE__ */
|
|
515
|
+
return /* @__PURE__ */ React5.createElement(GoogleReCaptchaProvider, { reCaptchaKey: props.recaptchaSiteKey }, /* @__PURE__ */ React5.createElement(Suspense, { fallback: /* @__PURE__ */ React5.createElement("div", { className: "h-64 flex items-center justify-center" }, /* @__PURE__ */ React5.createElement(InputSpinner, null)) }, /* @__PURE__ */ React5.createElement(AuthFormInner, { ...props })));
|
|
700
516
|
}
|
|
701
|
-
return /* @__PURE__ */
|
|
517
|
+
return /* @__PURE__ */ React5.createElement(Suspense, { fallback: /* @__PURE__ */ React5.createElement("div", { className: "h-64 flex items-center justify-center" }, /* @__PURE__ */ React5.createElement(InputSpinner, null)) }, /* @__PURE__ */ React5.createElement(AuthFormInner, { ...props }));
|
|
702
518
|
};
|
|
703
519
|
|
|
704
520
|
// src/components/Footer.tsx
|
|
705
|
-
import
|
|
521
|
+
import React6, { useState as useState4 } from "react";
|
|
706
522
|
import Link3 from "next/link";
|
|
707
523
|
import { HugeiconsIcon as HugeiconsIcon2 } from "@hugeicons/react";
|
|
708
524
|
var Footer = ({
|
|
@@ -712,20 +528,20 @@ var Footer = ({
|
|
|
712
528
|
copyrightText,
|
|
713
529
|
topSection
|
|
714
530
|
}) => {
|
|
715
|
-
const [openCol, setOpenCol] =
|
|
531
|
+
const [openCol, setOpenCol] = useState4(null);
|
|
716
532
|
const toggleColumn = (idx) => {
|
|
717
533
|
setOpenCol(openCol === idx ? null : idx);
|
|
718
534
|
};
|
|
719
|
-
return /* @__PURE__ */
|
|
535
|
+
return /* @__PURE__ */ React6.createElement("div", { className: "" }, topSection && topSection, /* @__PURE__ */ React6.createElement("footer", { className: "relative px-6 overflow-hidden flex flex-col" }, /* @__PURE__ */ React6.createElement("div", { className: "relative w-full max-w-7xl mx-auto z-20 flex flex-col" }, /* @__PURE__ */ React6.createElement("div", { className: "relative py-12 md:py-16" }, /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col lg:flex-row justify-between items-start gap-12 lg:gap-16 mb-12 text-left" }, /* @__PURE__ */ React6.createElement("div", { className: "w-full lg:max-w-sm flex flex-col items-start justify-between shrink-0" }, /* @__PURE__ */ React6.createElement("div", { className: "flex items-center gap-4 mb-4" }, /* @__PURE__ */ React6.createElement("img", { src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/ndpr.avif", alt: "NDPR", className: "w-28 h-auto object-contain filter grayscale opacity-80" }), /* @__PURE__ */ React6.createElement("img", { src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/gdpr.avif", alt: "GDPR", className: "w-12 h-12 object-contain filter grayscale opacity-80" })), /* @__PURE__ */ React6.createElement("div", null, /* @__PURE__ */ React6.createElement("p", { className: "text-[11px] text-neutral-600 leading-relaxed pr-4" }, description))), /* @__PURE__ */ React6.createElement("div", { className: "w-full lg:flex-1 lg:max-w-2xl" }, /* @__PURE__ */ React6.createElement("div", { className: "hidden md:grid grid-cols-2 gap-x-16 lg:gap-x-24 gap-y-12" }, columns.map((col, idx) => /* @__PURE__ */ React6.createElement("div", { key: idx, className: "flex flex-col" }, /* @__PURE__ */ React6.createElement("h4", { className: "text-[11px] tracking-[0.2em] text-black mb-6 " }, col.title), /* @__PURE__ */ React6.createElement("ul", { className: "space-y-4 text-[13px] text-neutral-500" }, col.links.map((link, lIdx) => /* @__PURE__ */ React6.createElement("li", { key: lIdx }, link.isExternal ? /* @__PURE__ */ React6.createElement("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", className: "hover:text-black transition-colors block truncate" }, link.label) : /* @__PURE__ */ React6.createElement(Link3, { href: link.href, className: "hover:text-black transition-colors block truncate" }, link.label))))))), /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col md:hidden w-full border-t border-neutral-200 mt-4" }, columns.map((col, idx) => {
|
|
720
536
|
const isOpen = openCol === idx;
|
|
721
|
-
return /* @__PURE__ */
|
|
537
|
+
return /* @__PURE__ */ React6.createElement("div", { key: idx, className: "border-b border-neutral-200" }, /* @__PURE__ */ React6.createElement(
|
|
722
538
|
"button",
|
|
723
539
|
{
|
|
724
540
|
onClick: () => toggleColumn(idx),
|
|
725
541
|
className: "w-full flex items-center justify-between py-5 text-left outline-none"
|
|
726
542
|
},
|
|
727
|
-
/* @__PURE__ */
|
|
728
|
-
/* @__PURE__ */
|
|
543
|
+
/* @__PURE__ */ React6.createElement("span", { className: "text-[11px] tracking-[0.2em] text-black " }, col.title),
|
|
544
|
+
/* @__PURE__ */ React6.createElement(
|
|
729
545
|
"svg",
|
|
730
546
|
{
|
|
731
547
|
className: `w-4 h-4 text-neutral-400 transition-transform duration-300 ${isOpen ? "rotate-180" : ""}`,
|
|
@@ -733,10 +549,10 @@ var Footer = ({
|
|
|
733
549
|
viewBox: "0 0 24 24",
|
|
734
550
|
stroke: "currentColor"
|
|
735
551
|
},
|
|
736
|
-
/* @__PURE__ */
|
|
552
|
+
/* @__PURE__ */ React6.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M19 9l-7 7-7-7" })
|
|
737
553
|
)
|
|
738
|
-
), /* @__PURE__ */
|
|
739
|
-
})))), /* @__PURE__ */
|
|
554
|
+
), /* @__PURE__ */ React6.createElement("div", { className: `grid transition-all duration-300 ease-in-out ${isOpen ? "grid-rows-[1fr] pb-6 opacity-100" : "grid-rows-[0fr] opacity-0"}` }, /* @__PURE__ */ React6.createElement("div", { className: "overflow-hidden" }, /* @__PURE__ */ React6.createElement("ul", { className: "space-y-4 text-[13px] text-neutral-500 pt-2" }, col.links.map((link, lIdx) => /* @__PURE__ */ React6.createElement("li", { key: lIdx }, link.isExternal ? /* @__PURE__ */ React6.createElement("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", className: "hover:text-black transition-colors" }, link.label) : /* @__PURE__ */ React6.createElement(Link3, { href: link.href, className: "hover:text-black transition-colors" }, link.label)))))));
|
|
555
|
+
})))), /* @__PURE__ */ React6.createElement("div", { className: "pt-8 mt-4 flex flex-col-reverse md:flex-row justify-between items-start md:items-center gap-6 relative z-20" }, /* @__PURE__ */ React6.createElement("p", { className: "text-[11px] text-neutral-400 tracking-widest text-left" }, copyrightText), socialLinks && socialLinks.length > 0 && /* @__PURE__ */ React6.createElement("div", { className: "flex items-center gap-6" }, socialLinks.map((social, idx) => /* @__PURE__ */ React6.createElement(
|
|
740
556
|
"a",
|
|
741
557
|
{
|
|
742
558
|
key: idx,
|
|
@@ -745,12 +561,12 @@ var Footer = ({
|
|
|
745
561
|
rel: "noopener noreferrer",
|
|
746
562
|
className: "text-neutral-400 hover:text-black transition-colors"
|
|
747
563
|
},
|
|
748
|
-
/* @__PURE__ */
|
|
564
|
+
/* @__PURE__ */ React6.createElement(HugeiconsIcon2, { icon: social.icon, size: 20 })
|
|
749
565
|
))))))));
|
|
750
566
|
};
|
|
751
567
|
|
|
752
568
|
// src/components/MobileNav.tsx
|
|
753
|
-
import
|
|
569
|
+
import React7 from "react";
|
|
754
570
|
import Link4 from "next/link";
|
|
755
571
|
import { usePathname as usePathname2 } from "next/navigation";
|
|
756
572
|
import { HugeiconsIcon as HugeiconsIcon3 } from "@hugeicons/react";
|
|
@@ -760,23 +576,23 @@ var MobileNav = ({ items }) => {
|
|
|
760
576
|
const pathMatches = items.some((item) => {
|
|
761
577
|
return item.href === "/" || item.href === "/app" ? pathname === "/" || pathname === "/app" : pathname === item.href || pathname?.startsWith(`${item.href}/`);
|
|
762
578
|
});
|
|
763
|
-
return /* @__PURE__ */
|
|
579
|
+
return /* @__PURE__ */ React7.createElement("div", { className: "fixed bottom-6 inset-x-0 z-100 flex justify-center pointer-events-none px-3 animate-in slide-in-from-bottom-8 fade-in duration-500 md:hidden" }, /* @__PURE__ */ React7.createElement("nav", { className: "pointer-events-auto w-full max-w-sm bg-white/50 backdrop-blur-xl shadow-[0_8px_30px_rgb(0,0,0,0.08)] rounded-full px-6 py-2.5 flex items-center justify-between" }, items.map((item, index) => {
|
|
764
580
|
const isActive = !pathMatches && index === 0 ? true : item.href === "/" || item.href === "/app" ? pathname === "/" || pathname === "/app" : pathname === item.href || pathname?.startsWith(`${item.href}/`);
|
|
765
|
-
return /* @__PURE__ */
|
|
581
|
+
return /* @__PURE__ */ React7.createElement(
|
|
766
582
|
Link4,
|
|
767
583
|
{
|
|
768
584
|
key: item.label,
|
|
769
585
|
href: item.href,
|
|
770
586
|
className: "flex flex-col items-center justify-center gap-1 min-w-14 transition-transform active:scale-95 outline-none"
|
|
771
587
|
},
|
|
772
|
-
/* @__PURE__ */
|
|
588
|
+
/* @__PURE__ */ React7.createElement("div", { className: `transition-colors duration-300 ${isActive ? "text-black" : "text-neutral-400 hover:text-neutral-600"}` }, /* @__PURE__ */ React7.createElement(
|
|
773
589
|
HugeiconsIcon3,
|
|
774
590
|
{
|
|
775
591
|
icon: item.icon,
|
|
776
592
|
size: 20
|
|
777
593
|
}
|
|
778
594
|
)),
|
|
779
|
-
/* @__PURE__ */
|
|
595
|
+
/* @__PURE__ */ React7.createElement(
|
|
780
596
|
"span",
|
|
781
597
|
{
|
|
782
598
|
className: `text-[9px] tracking-wide transition-colors duration-300 ${isActive ? "text-black" : "text-neutral-400"}`
|
|
@@ -792,10 +608,10 @@ import React11, { useState as useState7, useEffect as useEffect4 } from "react";
|
|
|
792
608
|
import toast2 from "react-hot-toast";
|
|
793
609
|
|
|
794
610
|
// src/components/ManagedToaster.tsx
|
|
795
|
-
import
|
|
611
|
+
import React8 from "react";
|
|
796
612
|
import { Toaster } from "react-hot-toast";
|
|
797
613
|
var ManagedToaster = () => {
|
|
798
|
-
return /* @__PURE__ */
|
|
614
|
+
return /* @__PURE__ */ React8.createElement(
|
|
799
615
|
Toaster,
|
|
800
616
|
{
|
|
801
617
|
position: "top-right",
|
|
@@ -826,6 +642,56 @@ var ManagedToaster = () => {
|
|
|
826
642
|
);
|
|
827
643
|
};
|
|
828
644
|
|
|
645
|
+
// src/components/TextInput.tsx
|
|
646
|
+
import React9, { useState as useState5 } from "react";
|
|
647
|
+
var TextInput = ({
|
|
648
|
+
label,
|
|
649
|
+
value,
|
|
650
|
+
onChange,
|
|
651
|
+
placeholder,
|
|
652
|
+
maxLength,
|
|
653
|
+
disabled,
|
|
654
|
+
readOnly,
|
|
655
|
+
type = "text",
|
|
656
|
+
onClick
|
|
657
|
+
}) => /* @__PURE__ */ React9.createElement("div", { className: "space-y-2 flex-1 w-full", onClick }, label && /* @__PURE__ */ React9.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, label), /* @__PURE__ */ React9.createElement(
|
|
658
|
+
"input",
|
|
659
|
+
{
|
|
660
|
+
type,
|
|
661
|
+
value,
|
|
662
|
+
onChange: (e) => onChange(e.target.value.substring(0, maxLength || 100)),
|
|
663
|
+
placeholder,
|
|
664
|
+
disabled,
|
|
665
|
+
readOnly,
|
|
666
|
+
autoComplete: "off",
|
|
667
|
+
spellCheck: "false",
|
|
668
|
+
className: `w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black transition-all outline-none focus:border-black disabled:opacity-50 ${readOnly ? "cursor-pointer" : ""}`
|
|
669
|
+
}
|
|
670
|
+
));
|
|
671
|
+
var NumberInput = ({
|
|
672
|
+
label,
|
|
673
|
+
value,
|
|
674
|
+
onChange,
|
|
675
|
+
placeholder,
|
|
676
|
+
maxLength,
|
|
677
|
+
disabled
|
|
678
|
+
}) => /* @__PURE__ */ React9.createElement("div", { className: "space-y-2 flex-1 w-full" }, label && /* @__PURE__ */ React9.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, label), /* @__PURE__ */ React9.createElement(
|
|
679
|
+
"input",
|
|
680
|
+
{
|
|
681
|
+
type: "text",
|
|
682
|
+
value,
|
|
683
|
+
onChange: (e) => {
|
|
684
|
+
const numOnly = e.target.value.replace(/[^0-9]/g, "");
|
|
685
|
+
onChange(numOnly.substring(0, maxLength || 20));
|
|
686
|
+
},
|
|
687
|
+
placeholder,
|
|
688
|
+
disabled,
|
|
689
|
+
autoComplete: "off",
|
|
690
|
+
spellCheck: "false",
|
|
691
|
+
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black transition-all outline-none focus:border-black disabled:opacity-50"
|
|
692
|
+
}
|
|
693
|
+
));
|
|
694
|
+
|
|
829
695
|
// src/components/Banner.tsx
|
|
830
696
|
import React10, { useState as useState6 } from "react";
|
|
831
697
|
import { HugeiconsIcon as HugeiconsIcon4 } from "@hugeicons/react";
|
|
@@ -893,7 +759,7 @@ import {
|
|
|
893
759
|
ArrowLeft01Icon,
|
|
894
760
|
CircleLock02Icon
|
|
895
761
|
} from "@hugeicons/core-free-icons";
|
|
896
|
-
var
|
|
762
|
+
var InputSpinner2 = () => /* @__PURE__ */ React11.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__ */ React11.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React11.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" }));
|
|
897
763
|
var UniversalOrganizationPage = ({
|
|
898
764
|
initialOrgName,
|
|
899
765
|
initialSlug,
|
|
@@ -1025,7 +891,7 @@ var UniversalOrganizationPage = ({
|
|
|
1025
891
|
className: "w-full px-2 py-3 text-sm bg-transparent text-black outline-none disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1026
892
|
placeholder: "sovereign-user-handle"
|
|
1027
893
|
}
|
|
1028
|
-
), /* @__PURE__ */ React11.createElement("span", { className: "text-neutral-400 text-sm py-3 pr-8 shrink-0 whitespace-nowrap" }, slugPrefixUrl), /* @__PURE__ */ React11.createElement("div", { className: "absolute right-2 top-1/2 -translate-y-1/2" }, isCheckingSlug && /* @__PURE__ */ React11.createElement(
|
|
894
|
+
), /* @__PURE__ */ React11.createElement("span", { className: "text-neutral-400 text-sm py-3 pr-8 shrink-0 whitespace-nowrap" }, slugPrefixUrl), /* @__PURE__ */ React11.createElement("div", { className: "absolute right-2 top-1/2 -translate-y-1/2" }, isCheckingSlug && /* @__PURE__ */ React11.createElement(InputSpinner2, null), !isCheckingSlug && !isReadOnly && slug !== initialSlug && slug.length >= 3 && slugAvailable === false && /* @__PURE__ */ React11.createElement("span", { className: "inline-flex items-center justify-center w-4 h-4 rounded-full bg-red-100" }, /* @__PURE__ */ React11.createElement("svg", { className: "w-2 h-2 text-red-600", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React11.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" }))), !isCheckingSlug && !isReadOnly && slug !== initialSlug && slug.length >= 3 && slugAvailable === true && /* @__PURE__ */ React11.createElement("span", { className: "inline-flex items-center justify-center w-4 h-4 rounded-full bg-green-100" }, /* @__PURE__ */ React11.createElement("svg", { className: "w-2 h-2 text-green-600", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React11.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M16.707 5.293a1 1 0 00-1.414 0L8 12.586 4.707 9.293a1 1 0 10-1.414 1.414l4 4a1 1 0 001.414 0l8-8a1 1 0 000-1.414z" })))))), /* @__PURE__ */ React11.createElement("div", { className: "pt-8 mt-2 flex items-center gap-4" }, /* @__PURE__ */ React11.createElement(
|
|
1029
895
|
ThreeDActionButton,
|
|
1030
896
|
{
|
|
1031
897
|
type: "submit",
|
|
@@ -1644,7 +1510,7 @@ var UniversalHomeView = ({
|
|
|
1644
1510
|
/* @__PURE__ */ React16.createElement(
|
|
1645
1511
|
"img",
|
|
1646
1512
|
{
|
|
1647
|
-
src: "https://
|
|
1513
|
+
src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/save_box.avif",
|
|
1648
1514
|
alt: "Buy Crypto",
|
|
1649
1515
|
className: "absolute bottom-4 right-2 translate-x-1/4 translate-y-1/2 w-32 h-auto object-contain z-0 pointer-events-none drop-shadow-md"
|
|
1650
1516
|
}
|
|
@@ -1659,7 +1525,7 @@ var UniversalHomeView = ({
|
|
|
1659
1525
|
/* @__PURE__ */ React16.createElement(
|
|
1660
1526
|
"img",
|
|
1661
1527
|
{
|
|
1662
|
-
src: "https://
|
|
1528
|
+
src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/gift_box.avif",
|
|
1663
1529
|
alt: "Referral",
|
|
1664
1530
|
className: "absolute bottom-4 right-2 translate-x-1/4 translate-y-1/2 w-32 h-auto object-contain z-0 pointer-events-none drop-shadow-md"
|
|
1665
1531
|
}
|
|
@@ -2516,7 +2382,7 @@ var WaitlistDialog = ({ isOpen, onClose }) => {
|
|
|
2516
2382
|
/* @__PURE__ */ React22.createElement("path", { d: "m6 6 12 12" })
|
|
2517
2383
|
)
|
|
2518
2384
|
),
|
|
2519
|
-
/* @__PURE__ */ React22.createElement("div", { className: "p-6 sm:p-8" }, /* @__PURE__ */ React22.createElement("div", { className: "mb-8 mt-2" }, /* @__PURE__ */ React22.createElement("h2", { className: "text-2xl text-black tracking-tight mb-2" }, "Join the Waitlist"), /* @__PURE__ */ React22.createElement("p", { className: "text-[13px] text-neutral-500 leading-relaxed" }, "Be the first to
|
|
2385
|
+
/* @__PURE__ */ React22.createElement("div", { className: "p-6 sm:p-8" }, /* @__PURE__ */ React22.createElement("div", { className: "mb-8 mt-2" }, /* @__PURE__ */ React22.createElement("h2", { className: "text-2xl text-black tracking-tight mb-2" }, "Join the Waitlist"), /* @__PURE__ */ React22.createElement("p", { className: "text-[13px] text-neutral-500 leading-relaxed" }, "Be the first to be notified when we launch. Secure your early access spot today.")), /* @__PURE__ */ React22.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col gap-8" }, /* @__PURE__ */ React22.createElement(
|
|
2520
2386
|
TextInput,
|
|
2521
2387
|
{
|
|
2522
2388
|
label: "Email ID",
|
|
@@ -2541,10 +2407,8 @@ var WaitlistDialog = ({ isOpen, onClose }) => {
|
|
|
2541
2407
|
|
|
2542
2408
|
// src/components/HeroSection.tsx
|
|
2543
2409
|
var HeroSection = ({
|
|
2544
|
-
badgeText,
|
|
2545
2410
|
titlePrefix,
|
|
2546
2411
|
highlightText = "Retina",
|
|
2547
|
-
cursorLabel,
|
|
2548
2412
|
subtitle,
|
|
2549
2413
|
ctaText,
|
|
2550
2414
|
ctaHref,
|
|
@@ -2553,8 +2417,6 @@ var HeroSection = ({
|
|
|
2553
2417
|
showApps = false,
|
|
2554
2418
|
appsText,
|
|
2555
2419
|
appLogos,
|
|
2556
|
-
showImage = false,
|
|
2557
|
-
imageSrc = "/assets/ai.avif",
|
|
2558
2420
|
bgVideoSrc,
|
|
2559
2421
|
bgImageSrc,
|
|
2560
2422
|
isWaitlist = false
|
|
@@ -3002,9 +2864,9 @@ var FeatureScroll = ({ tagline, headline, features }) => {
|
|
|
3002
2864
|
}
|
|
3003
2865
|
};
|
|
3004
2866
|
const bgImages = [
|
|
3005
|
-
"https://
|
|
3006
|
-
"https://
|
|
3007
|
-
"https://
|
|
2867
|
+
"https://storage.googleapis.com/retina-cloud-v2/assets/images/bg_7.avif",
|
|
2868
|
+
"https://storage.googleapis.com/retina-cloud-v2/assets/images/bg_6.avif",
|
|
2869
|
+
"https://storage.googleapis.com/retina-cloud-v2/assets/images/bg_1.avif"
|
|
3008
2870
|
];
|
|
3009
2871
|
return /* @__PURE__ */ React26.createElement("section", { className: "py-24 w-full flex justify-center relative z-10 overflow-hidden" }, /* @__PURE__ */ React26.createElement("div", { className: "max-w-6xl w-full flex flex-col px-4 md:px-8" }, /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col md:flex-row md:items-end justify-between gap-6 mb-12" }, /* @__PURE__ */ React26.createElement("div", { className: "relative z-10 text-left" }, /* @__PURE__ */ React26.createElement("span", { className: "text-[11px] tracking-[0.4em] text-neutral-500 block mb-4" }, tagline), /* @__PURE__ */ React26.createElement("h2", { className: " text-3xl tracking-tight text-black leading-[1.05]" }, headline)), /* @__PURE__ */ React26.createElement("div", { className: "hidden md:flex items-center gap-3" }, /* @__PURE__ */ React26.createElement(
|
|
3010
2872
|
"button",
|