@retinalabsllc/zairusjs 16.0.90 → 16.1.1

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 CHANGED
@@ -1016,6 +1016,7 @@ interface UniversalMembersPageProps {
1016
1016
  actionButtonText: string;
1017
1017
  hideAction?: boolean;
1018
1018
  onRemoveMember: (memberId: string) => Promise<void>;
1019
+ onInviteMember: (email: string) => Promise<void>;
1019
1020
  }
1020
1021
  declare const UniversalMembersPage: React.FC<UniversalMembersPageProps>;
1021
1022
 
package/dist/index.d.ts CHANGED
@@ -1016,6 +1016,7 @@ interface UniversalMembersPageProps {
1016
1016
  actionButtonText: string;
1017
1017
  hideAction?: boolean;
1018
1018
  onRemoveMember: (memberId: string) => Promise<void>;
1019
+ onInviteMember: (email: string) => Promise<void>;
1019
1020
  }
1020
1021
  declare const UniversalMembersPage: React.FC<UniversalMembersPageProps>;
1021
1022
 
package/dist/index.js CHANGED
@@ -488,6 +488,33 @@ function AuthFormInner({
488
488
  setIsSubmitting(false);
489
489
  }
490
490
  };
491
+ const handleResendCode = async () => {
492
+ if (countdown > 0 || isSubmitting) return;
493
+ setIsSubmitting(true);
494
+ try {
495
+ let recaptchaToken = void 0;
496
+ if (useRecaptcha && captchaContext?.executeRecaptcha) {
497
+ recaptchaToken = await captchaContext.executeRecaptcha("auth_request");
498
+ }
499
+ const res = await onAuthRequest({
500
+ email: emailId,
501
+ mode: "LOGIN",
502
+ recaptchaToken
503
+ });
504
+ if (res.success) {
505
+ import_react_hot_toast.default.success("Verification code resent");
506
+ setOtp(["", "", "", "", "", ""]);
507
+ inputRefs.current[0]?.focus();
508
+ setCountdown(60);
509
+ } else {
510
+ import_react_hot_toast.default.error(res.error || "Failed to resend code.");
511
+ }
512
+ } catch {
513
+ import_react_hot_toast.default.error("Service unavailable. Try again later.");
514
+ } finally {
515
+ setIsSubmitting(false);
516
+ }
517
+ };
491
518
  const verifyOtpCode = async (codeToVerify) => {
492
519
  if (codeToVerify.length !== 6 || isSubmitting) return;
493
520
  setIsSubmitting(true);
@@ -549,12 +576,12 @@ function AuthFormInner({
549
576
  if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
550
577
  else if (mode === "SIGNUP" && signupStep === "ORGANIZATION") handleNextSignupStep();
551
578
  else handleAuthRequestSubmit();
552
- } }, mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "text", value: firstName, onChange: (e) => setFirstName(cleanAlpha(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "First name" })), /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "text", value: lastName, onChange: (e) => setLastName(cleanAlpha(e.target.value)), required: true, className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Last name" }))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex bg-neutral-100 p-1 rounded-lg" }, /* @__PURE__ */ import_react6.default.createElement(
579
+ } }, mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "text", value: firstName, onChange: (e) => setFirstName(cleanAlpha(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "First name" })), /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "text", value: lastName, onChange: (e) => setLastName(cleanAlpha(e.target.value)), required: true, className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Last name" }))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex bg-neutral-100 p-1 rounded-full" }, /* @__PURE__ */ import_react6.default.createElement(
553
580
  "button",
554
581
  {
555
582
  type: "button",
556
583
  onClick: () => setAccountType("INDIVIDUAL"),
557
- className: `flex-1 py-2 text-xs rounded-md transition-colors outline-none ${accountType === "INDIVIDUAL" ? "bg-white shadow-sm text-black" : "text-neutral-500 hover:text-black"}`
584
+ className: `flex-1 py-2 text-xs rounded-full transition-colors outline-none ${accountType === "INDIVIDUAL" ? "bg-white text-black" : "text-neutral-500 hover:text-black"}`
558
585
  },
559
586
  "Personal"
560
587
  ), /* @__PURE__ */ import_react6.default.createElement(
@@ -562,7 +589,7 @@ function AuthFormInner({
562
589
  {
563
590
  type: "button",
564
591
  onClick: () => setAccountType("ORGANIZATION"),
565
- className: `flex-1 py-2 text-xs rounded-md transition-colors outline-none ${accountType === "ORGANIZATION" ? "bg-white shadow-sm text-black" : "text-neutral-500 hover:text-black"}`
592
+ className: `flex-1 py-2 text-xs rounded-full transition-colors outline-none ${accountType === "ORGANIZATION" ? "bg-white text-black" : "text-neutral-500 hover:text-black"}`
566
593
  },
567
594
  "Organization"
568
595
  )), accountType === "ORGANIZATION" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5 relative animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "text", value: orgName, onChange: (e) => setOrgName(cleanOrgName(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Acme Corporation" })), accountType === "INDIVIDUAL" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "py-4 text-center animate-in fade-in duration-200" }, /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "You are creating a personal account. You can join organizations later."))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "EMAIL_ID") && /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-6" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Email ID"), /* @__PURE__ */ import_react6.default.createElement("input", { type: "email", value: emailId, onChange: (e) => setEmailId(cleanEmailId(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "name@company.com" })), mode === "SIGNUP" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ import_react6.default.createElement("input", { type: "checkbox", id: "zairus-terms", checked: agreedToTerms, onChange: (e) => setAgreedToTerms(e.target.checked), className: "mt-0.5 w-4 h-4 bg-white border-neutral-300 rounded text-black focus:ring-black cursor-pointer", required: true }), /* @__PURE__ */ import_react6.default.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ import_react6.default.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Terms of Service"), " and ", /* @__PURE__ */ import_react6.default.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Privacy Policy"), "."))), /* @__PURE__ */ import_react6.default.createElement(ThreeDActionButton, { type: "submit", disabled: isContinueDisabled(), isLoading: isSubmitting, className: "w-full mt-10" }, "Continue"))), step === "OTP" && /* @__PURE__ */ import_react6.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "text-center mb-10 mt-2" }, /* @__PURE__ */ import_react6.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-[13px] text-neutral-500" }, userHas2FA ? "Enter the code from your authenticator app." : `Enter the code sent to ${emailId}`)), /* @__PURE__ */ import_react6.default.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
@@ -585,7 +612,16 @@ function AuthFormInner({
585
612
  },
586
613
  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"
587
614
  }
588
- ))), /* @__PURE__ */ import_react6.default.createElement(ThreeDActionButton, { type: "submit", disabled: otp.join("").length < 6, isLoading: isSubmitting, className: "w-full" }, "Verify Code")), userHasPasskey && /* @__PURE__ */ import_react6.default.createElement("div", { className: "pt-6 " }, /* @__PURE__ */ import_react6.default.createElement(
615
+ ))), /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col gap-4" }, /* @__PURE__ */ import_react6.default.createElement(ThreeDActionButton, { type: "submit", disabled: otp.join("").length < 6, isLoading: isSubmitting, className: "w-full" }, "Verify Code"), !userHas2FA && /* @__PURE__ */ import_react6.default.createElement(
616
+ "button",
617
+ {
618
+ type: "button",
619
+ onClick: handleResendCode,
620
+ disabled: countdown > 0 || isSubmitting,
621
+ className: "text-[12px] text-neutral-500 hover:text-black transition-colors outline-none disabled:opacity-50"
622
+ },
623
+ countdown > 0 ? `Resend code in ${countdown}s` : "Resend verification code"
624
+ ))), userHasPasskey && /* @__PURE__ */ import_react6.default.createElement("div", { className: "pt-6 " }, /* @__PURE__ */ import_react6.default.createElement(
589
625
  "button",
590
626
  {
591
627
  onClick: triggerPasskeyLogin,
@@ -4537,7 +4573,7 @@ var MemberAvatar = ({ src, status }) => {
4537
4573
  return "bg-neutral-200";
4538
4574
  }
4539
4575
  };
4540
- return /* @__PURE__ */ import_react79.default.createElement("div", { className: "relative w-10 h-10 shrink-0" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "w-full h-full rounded-lg bg-neutral-100 flex items-center justify-center overflow-hidden border border-neutral-200" }, !loaded && !error && /* @__PURE__ */ import_react79.default.createElement(import_react80.HugeiconsIcon, { icon: import_core_free_icons28.Loading03Icon, className: "animate-spin text-neutral-400 absolute", size: 14 }), /* @__PURE__ */ import_react79.default.createElement(
4576
+ return /* @__PURE__ */ import_react79.default.createElement("div", { className: "relative w-10 h-10 shrink-0" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "w-full h-full rounded-lg bg-neutral-100 flex items-center justify-center overflow-hidden" }, !loaded && !error && /* @__PURE__ */ import_react79.default.createElement(import_react80.HugeiconsIcon, { icon: import_core_free_icons28.Loading03Icon, className: "animate-spin text-neutral-400 absolute", size: 14 }), /* @__PURE__ */ import_react79.default.createElement(
4541
4577
  "img",
4542
4578
  {
4543
4579
  src: finalSrc,
@@ -4546,7 +4582,7 @@ var MemberAvatar = ({ src, status }) => {
4546
4582
  onLoad: () => setLoaded(true),
4547
4583
  onError: () => setError(true)
4548
4584
  }
4549
- )), /* @__PURE__ */ import_react79.default.createElement("div", { className: `absolute -bottom-1 -right-1 w-3.5 h-3.5 rounded-full border-2 border-white z-10 ${getStatusColor()}` }));
4585
+ )), /* @__PURE__ */ import_react79.default.createElement("div", { className: `absolute -bottom-1 -right-1 w-2.5 h-2.5 rounded-full border-2 border-white z-10 ${getStatusColor()}` }));
4550
4586
  };
4551
4587
  var PageSpinner7 = () => /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex justify-center items-center py-12" }, /* @__PURE__ */ import_react79.default.createElement(import_react80.HugeiconsIcon, { icon: import_core_free_icons28.Loading03Icon, size: 32, className: "animate-spin mb-4 text-black" }));
4552
4588
  var UniversalMembersPage = ({
@@ -4565,17 +4601,22 @@ var UniversalMembersPage = ({
4565
4601
  onRoleFilterChange,
4566
4602
  actionButtonText,
4567
4603
  hideAction = false,
4568
- onRemoveMember
4604
+ onRemoveMember,
4605
+ onInviteMember
4569
4606
  }) => {
4570
4607
  const [expandedId, setExpandedId] = (0, import_react79.useState)(null);
4571
4608
  const [memberToRemove, setMemberToRemove] = (0, import_react79.useState)(null);
4572
4609
  const [isRemoving, setIsRemoving] = (0, import_react79.useState)(false);
4610
+ const [isInviteMode, setIsInviteMode] = (0, import_react79.useState)(false);
4611
+ const [inviteEmail, setInviteEmail] = (0, import_react79.useState)("");
4612
+ const [isInviting, setIsInviting] = (0, import_react79.useState)(false);
4573
4613
  const [localSearchQuery, setLocalSearchQuery] = (0, import_react79.useState)(searchQuery);
4574
4614
  const [isTyping, setIsTyping] = (0, import_react79.useState)(false);
4575
4615
  const [isStatusModalOpen, setIsStatusModalOpen] = (0, import_react79.useState)(false);
4576
4616
  const [isRoleModalOpen, setIsRoleModalOpen] = (0, import_react79.useState)(false);
4577
4617
  const statusDropdownRef = (0, import_react79.useRef)(null);
4578
4618
  const roleDropdownRef = (0, import_react79.useRef)(null);
4619
+ const cleanEmailId = (val) => val.toLowerCase().replace(/[^a-z0-9@._-]/g, "");
4579
4620
  (0, import_react79.useEffect)(() => {
4580
4621
  function handleClickOutside(event) {
4581
4622
  if (statusDropdownRef.current && !statusDropdownRef.current.contains(event.target)) {
@@ -4615,6 +4656,20 @@ var UniversalMembersPage = ({
4615
4656
  setIsRemoving(false);
4616
4657
  }
4617
4658
  };
4659
+ const handleInviteSubmit = async (e) => {
4660
+ e.preventDefault();
4661
+ if (inviteEmail.length < 5 || isInviting) return;
4662
+ setIsInviting(true);
4663
+ try {
4664
+ await onInviteMember(inviteEmail);
4665
+ setInviteEmail("");
4666
+ setIsInviteMode(false);
4667
+ } catch (error) {
4668
+ import_react_hot_toast13.default.error(error.message || "Failed to send invitation.");
4669
+ } finally {
4670
+ setIsInviting(false);
4671
+ }
4672
+ };
4618
4673
  const isListLoading = isLoading || isTyping;
4619
4674
  return /* @__PURE__ */ import_react79.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ import_react79.default.createElement(ManagedToaster, null), /* @__PURE__ */ import_react79.default.createElement(
4620
4675
  ConfirmationDialog,
@@ -4629,7 +4684,7 @@ var UniversalMembersPage = ({
4629
4684
  onClose: () => setMemberToRemove(null),
4630
4685
  onConfirm: handleConfirmRemove
4631
4686
  }
4632
- ), /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-row flex-nowrap mb-4 items-center justify-between gap-4 w-full" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "relative flex-1 min-w-0 max-w-full" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none" }, /* @__PURE__ */ import_react79.default.createElement(import_react80.HugeiconsIcon, { icon: import_core_free_icons28.Search01Icon, size: 16, className: "text-neutral-400" })), /* @__PURE__ */ import_react79.default.createElement(
4687
+ ), !isInviteMode && /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-row flex-nowrap mb-4 items-center justify-between gap-4 w-full animate-in fade-in duration-300" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "relative flex-1 min-w-0 max-w-full" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none" }, /* @__PURE__ */ import_react79.default.createElement(import_react80.HugeiconsIcon, { icon: import_core_free_icons28.Search01Icon, size: 16, className: "text-neutral-400" })), /* @__PURE__ */ import_react79.default.createElement(
4633
4688
  "input",
4634
4689
  {
4635
4690
  type: "text",
@@ -4652,7 +4707,46 @@ var UniversalMembersPage = ({
4652
4707
  className: "flex items-center justify-center bg-white w-9 h-9 rounded-full text-neutral-500 hover:text-black transition-colors outline-none"
4653
4708
  },
4654
4709
  /* @__PURE__ */ import_react79.default.createElement(import_react80.HugeiconsIcon, { icon: import_core_free_icons28.ListSettingIcon, size: 16 })
4655
- ))), /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col gap-8 p-6 rounded-2xl bg-white w-full" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col sm:flex-row sm:items-start justify-between gap-4" }, /* @__PURE__ */ import_react79.default.createElement("div", null, /* @__PURE__ */ import_react79.default.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, headerTitle), headerDescription && /* @__PURE__ */ import_react79.default.createElement("p", { className: "text-[12px] text-neutral-500" }, headerDescription))), /* @__PURE__ */ import_react79.default.createElement("div", { className: "w-full overflow-hidden" }, isListLoading ? /* @__PURE__ */ import_react79.default.createElement(PageSpinner7, null) : /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react79.default.createElement("div", null, members.length === 0 ? /* @__PURE__ */ import_react79.default.createElement("p", { className: "text-[12px] text-neutral-400 py-6 text-center" }, "No members found") : members.map((member) => /* @__PURE__ */ import_react79.default.createElement(import_react79.default.Fragment, { key: member.id }, expandedId === member.id ? /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col p-5 bg-neutral-50 rounded-xl animate-in fade-in zoom-in-95 duration-200 gap-5 my-2" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react79.default.createElement(MemberAvatar, { src: member.avatarUrl, status: member.status }), /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react79.default.createElement("span", { className: "text-[14px] text-black tracking-tight truncate" }, member.name), /* @__PURE__ */ import_react79.default.createElement("span", { className: "text-[12px] text-neutral-500 capitalize" }, member.role.toLowerCase()))), member.departmentName && /* @__PURE__ */ import_react79.default.createElement("div", { className: "pt-3 border-t border-neutral-200" }, /* @__PURE__ */ import_react79.default.createElement("span", { className: "text-[10px] tracking-[0.2em] text-neutral-400 block mb-1" }, "Department"), /* @__PURE__ */ import_react79.default.createElement("span", { className: "text-[13px] text-black truncate block" }, member.departmentName)), /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex gap-3 pt-2" }, !hideAction && /* @__PURE__ */ import_react79.default.createElement(
4710
+ ))), /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col gap-8 p-6 rounded-2xl bg-white w-full" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-row items-start justify-between gap-4" }, /* @__PURE__ */ import_react79.default.createElement("div", null, /* @__PURE__ */ import_react79.default.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, isInviteMode ? "Add Member" : headerTitle), headerDescription && !isInviteMode && /* @__PURE__ */ import_react79.default.createElement("p", { className: "text-[12px] text-neutral-500" }, headerDescription)), !isInviteMode && /* @__PURE__ */ import_react79.default.createElement(
4711
+ "button",
4712
+ {
4713
+ onClick: () => setIsInviteMode(true),
4714
+ className: "shrink-0 px-4 py-2 border border-neutral-200 text-black text-[12px] tracking-wide rounded-full hover:bg-neutral-50 transition-colors outline-none"
4715
+ },
4716
+ "Invite Team"
4717
+ )), /* @__PURE__ */ import_react79.default.createElement("div", { className: "w-full overflow-hidden" }, isInviteMode ? /* @__PURE__ */ import_react79.default.createElement("form", { onSubmit: handleInviteSubmit, className: "flex flex-col gap-8 animate-in fade-in duration-300" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "space-y-1.5 mt-2" }, /* @__PURE__ */ import_react79.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, "Email Address"), /* @__PURE__ */ import_react79.default.createElement(
4718
+ "input",
4719
+ {
4720
+ type: "email",
4721
+ value: inviteEmail,
4722
+ onChange: (e) => setInviteEmail(cleanEmailId(e.target.value)),
4723
+ required: true,
4724
+ autoFocus: true,
4725
+ 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",
4726
+ placeholder: "name@company.com"
4727
+ }
4728
+ )), /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col gap-3" }, /* @__PURE__ */ import_react79.default.createElement(
4729
+ ThreeDActionButton,
4730
+ {
4731
+ type: "submit",
4732
+ disabled: inviteEmail.length < 5 || isInviting,
4733
+ isLoading: isInviting,
4734
+ className: "w-full"
4735
+ },
4736
+ "Send Invitation"
4737
+ ), /* @__PURE__ */ import_react79.default.createElement(
4738
+ "button",
4739
+ {
4740
+ type: "button",
4741
+ onClick: () => {
4742
+ setIsInviteMode(false);
4743
+ setInviteEmail("");
4744
+ },
4745
+ disabled: isInviting,
4746
+ className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-xs tracking-wide"
4747
+ },
4748
+ "Cancel"
4749
+ ))) : isListLoading ? /* @__PURE__ */ import_react79.default.createElement(PageSpinner7, null) : /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col min-w-0 animate-in fade-in duration-300" }, /* @__PURE__ */ import_react79.default.createElement("div", null, members.length === 0 ? /* @__PURE__ */ import_react79.default.createElement("p", { className: "text-[12px] text-neutral-400 py-6 text-center" }, "No members found") : members.map((member) => /* @__PURE__ */ import_react79.default.createElement(import_react79.default.Fragment, { key: member.id }, expandedId === member.id ? /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col p-5 bg-neutral-50 rounded-xl animate-in fade-in zoom-in-95 duration-200 gap-5 my-2" }, /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react79.default.createElement(MemberAvatar, { src: member.avatarUrl, status: member.status }), /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react79.default.createElement("span", { className: "text-[14px] text-black tracking-tight truncate" }, member.name), /* @__PURE__ */ import_react79.default.createElement("span", { className: "text-[12px] text-neutral-500 capitalize" }, member.role.toLowerCase()))), member.departmentName && /* @__PURE__ */ import_react79.default.createElement("div", { className: "pt-3 border-t border-neutral-200" }, /* @__PURE__ */ import_react79.default.createElement("span", { className: "text-[10px] tracking-[0.2em] text-neutral-400 block mb-1" }, "Department"), /* @__PURE__ */ import_react79.default.createElement("span", { className: "text-[13px] text-black truncate block" }, member.departmentName)), /* @__PURE__ */ import_react79.default.createElement("div", { className: "flex gap-3 pt-2" }, !hideAction && /* @__PURE__ */ import_react79.default.createElement(
4656
4750
  "button",
4657
4751
  {
4658
4752
  onClick: () => setMemberToRemove(member),
@@ -4741,7 +4835,7 @@ var UniversalHome2 = ({
4741
4835
  const fallbackAvatarUrl = "https://storage.googleapis.com/retina-cloud-v2/assets/images/avatar.avif";
4742
4836
  const finalAvatarSrc = avatarSrc || fallbackAvatarUrl;
4743
4837
  const hasUnreadNotifs = notifications.some((n) => !n.isRead);
4744
- return /* @__PURE__ */ import_react81.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative" }, /* @__PURE__ */ import_react81.default.createElement("div", { className: "flex items-center justify-between w-full pb-4" }, /* @__PURE__ */ import_react81.default.createElement("div", { className: "w-10 h-10 shrink-0 cursor-pointer", onClick: () => router.push("/app/account/me") }, /* @__PURE__ */ import_react81.default.createElement("div", { className: "relative w-full h-full rounded-lg overflow-hidden bg-neutral-100 flex items-center justify-center border border-neutral-200" }, !isAvatarLoaded && /* @__PURE__ */ import_react81.default.createElement("div", { className: "absolute inset-0 flex items-center justify-center z-10 bg-neutral-100" }, /* @__PURE__ */ import_react81.default.createElement(import_react82.HugeiconsIcon, { icon: import_core_free_icons29.Loading03Icon, size: 16, className: "animate-spin text-black" })), /* @__PURE__ */ import_react81.default.createElement(
4838
+ return /* @__PURE__ */ import_react81.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative" }, /* @__PURE__ */ import_react81.default.createElement("div", { className: "flex items-center justify-between w-full pb-4" }, /* @__PURE__ */ import_react81.default.createElement("div", { className: "w-10 h-10 shrink-0 cursor-pointer", onClick: () => router.push("/app/account/me") }, /* @__PURE__ */ import_react81.default.createElement("div", { className: "relative w-full h-full rounded-lg overflow-hidden bg-white flex items-center justify-center" }, !isAvatarLoaded && /* @__PURE__ */ import_react81.default.createElement("div", { className: "absolute inset-0 flex items-center justify-center z-10 bg-white" }, /* @__PURE__ */ import_react81.default.createElement(import_react82.HugeiconsIcon, { icon: import_core_free_icons29.Loading03Icon, size: 16, className: "animate-spin text-black" })), /* @__PURE__ */ import_react81.default.createElement(
4745
4839
  "img",
4746
4840
  {
4747
4841
  src: finalAvatarSrc,
@@ -4772,7 +4866,7 @@ var UniversalHome2 = ({
4772
4866
  {
4773
4867
  src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/cal_a.avif",
4774
4868
  alt: "Create Huddle",
4775
- 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"
4869
+ 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 "
4776
4870
  }
4777
4871
  )
4778
4872
  ), /* @__PURE__ */ import_react81.default.createElement(
@@ -4787,7 +4881,7 @@ var UniversalHome2 = ({
4787
4881
  {
4788
4882
  src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/cam_a.avif",
4789
4883
  alt: "Join Huddle",
4790
- 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"
4884
+ 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 "
4791
4885
  }
4792
4886
  )
4793
4887
  ))), customContent && /* @__PURE__ */ import_react81.default.createElement("div", { className: "w-full" }, customContent), /* @__PURE__ */ import_react81.default.createElement("div", { className: "w-full mt-2" }, /* @__PURE__ */ import_react81.default.createElement(
package/dist/index.mjs CHANGED
@@ -405,6 +405,33 @@ function AuthFormInner({
405
405
  setIsSubmitting(false);
406
406
  }
407
407
  };
408
+ const handleResendCode = async () => {
409
+ if (countdown > 0 || isSubmitting) return;
410
+ setIsSubmitting(true);
411
+ try {
412
+ let recaptchaToken = void 0;
413
+ if (useRecaptcha && captchaContext?.executeRecaptcha) {
414
+ recaptchaToken = await captchaContext.executeRecaptcha("auth_request");
415
+ }
416
+ const res = await onAuthRequest({
417
+ email: emailId,
418
+ mode: "LOGIN",
419
+ recaptchaToken
420
+ });
421
+ if (res.success) {
422
+ toast.success("Verification code resent");
423
+ setOtp(["", "", "", "", "", ""]);
424
+ inputRefs.current[0]?.focus();
425
+ setCountdown(60);
426
+ } else {
427
+ toast.error(res.error || "Failed to resend code.");
428
+ }
429
+ } catch {
430
+ toast.error("Service unavailable. Try again later.");
431
+ } finally {
432
+ setIsSubmitting(false);
433
+ }
434
+ };
408
435
  const verifyOtpCode = async (codeToVerify) => {
409
436
  if (codeToVerify.length !== 6 || isSubmitting) return;
410
437
  setIsSubmitting(true);
@@ -466,12 +493,12 @@ function AuthFormInner({
466
493
  if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
467
494
  else if (mode === "SIGNUP" && signupStep === "ORGANIZATION") handleNextSignupStep();
468
495
  else handleAuthRequestSubmit();
469
- } }, 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: "flex bg-neutral-100 p-1 rounded-lg" }, /* @__PURE__ */ React5.createElement(
496
+ } }, 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: "flex bg-neutral-100 p-1 rounded-full" }, /* @__PURE__ */ React5.createElement(
470
497
  "button",
471
498
  {
472
499
  type: "button",
473
500
  onClick: () => setAccountType("INDIVIDUAL"),
474
- className: `flex-1 py-2 text-xs rounded-md transition-colors outline-none ${accountType === "INDIVIDUAL" ? "bg-white shadow-sm text-black" : "text-neutral-500 hover:text-black"}`
501
+ className: `flex-1 py-2 text-xs rounded-full transition-colors outline-none ${accountType === "INDIVIDUAL" ? "bg-white text-black" : "text-neutral-500 hover:text-black"}`
475
502
  },
476
503
  "Personal"
477
504
  ), /* @__PURE__ */ React5.createElement(
@@ -479,7 +506,7 @@ function AuthFormInner({
479
506
  {
480
507
  type: "button",
481
508
  onClick: () => setAccountType("ORGANIZATION"),
482
- className: `flex-1 py-2 text-xs rounded-md transition-colors outline-none ${accountType === "ORGANIZATION" ? "bg-white shadow-sm text-black" : "text-neutral-500 hover:text-black"}`
509
+ className: `flex-1 py-2 text-xs rounded-full transition-colors outline-none ${accountType === "ORGANIZATION" ? "bg-white text-black" : "text-neutral-500 hover:text-black"}`
483
510
  },
484
511
  "Organization"
485
512
  )), accountType === "ORGANIZATION" && /* @__PURE__ */ React5.createElement("div", { className: "space-y-1.5 relative animate-in fade-in zoom-in-95 duration-200" }, /* @__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" })), accountType === "INDIVIDUAL" && /* @__PURE__ */ React5.createElement("div", { className: "py-4 text-center animate-in fade-in duration-200" }, /* @__PURE__ */ React5.createElement("p", { className: "text-[13px] text-neutral-500" }, "You are creating a personal account. You can join organizations later."))), (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) => {
@@ -502,7 +529,16 @@ function AuthFormInner({
502
529
  },
503
530
  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"
504
531
  }
505
- ))), /* @__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(
532
+ ))), /* @__PURE__ */ React5.createElement("div", { className: "flex flex-col gap-4" }, /* @__PURE__ */ React5.createElement(ThreeDActionButton, { type: "submit", disabled: otp.join("").length < 6, isLoading: isSubmitting, className: "w-full" }, "Verify Code"), !userHas2FA && /* @__PURE__ */ React5.createElement(
533
+ "button",
534
+ {
535
+ type: "button",
536
+ onClick: handleResendCode,
537
+ disabled: countdown > 0 || isSubmitting,
538
+ className: "text-[12px] text-neutral-500 hover:text-black transition-colors outline-none disabled:opacity-50"
539
+ },
540
+ countdown > 0 ? `Resend code in ${countdown}s` : "Resend verification code"
541
+ ))), userHasPasskey && /* @__PURE__ */ React5.createElement("div", { className: "pt-6 " }, /* @__PURE__ */ React5.createElement(
506
542
  "button",
507
543
  {
508
544
  onClick: triggerPasskeyLogin,
@@ -4557,7 +4593,7 @@ var MemberAvatar = ({ src, status }) => {
4557
4593
  return "bg-neutral-200";
4558
4594
  }
4559
4595
  };
4560
- return /* @__PURE__ */ React47.createElement("div", { className: "relative w-10 h-10 shrink-0" }, /* @__PURE__ */ React47.createElement("div", { className: "w-full h-full rounded-lg bg-neutral-100 flex items-center justify-center overflow-hidden border border-neutral-200" }, !loaded && !error && /* @__PURE__ */ React47.createElement(HugeiconsIcon33, { icon: Loading03Icon21, className: "animate-spin text-neutral-400 absolute", size: 14 }), /* @__PURE__ */ React47.createElement(
4596
+ return /* @__PURE__ */ React47.createElement("div", { className: "relative w-10 h-10 shrink-0" }, /* @__PURE__ */ React47.createElement("div", { className: "w-full h-full rounded-lg bg-neutral-100 flex items-center justify-center overflow-hidden" }, !loaded && !error && /* @__PURE__ */ React47.createElement(HugeiconsIcon33, { icon: Loading03Icon21, className: "animate-spin text-neutral-400 absolute", size: 14 }), /* @__PURE__ */ React47.createElement(
4561
4597
  "img",
4562
4598
  {
4563
4599
  src: finalSrc,
@@ -4566,7 +4602,7 @@ var MemberAvatar = ({ src, status }) => {
4566
4602
  onLoad: () => setLoaded(true),
4567
4603
  onError: () => setError(true)
4568
4604
  }
4569
- )), /* @__PURE__ */ React47.createElement("div", { className: `absolute -bottom-1 -right-1 w-3.5 h-3.5 rounded-full border-2 border-white z-10 ${getStatusColor()}` }));
4605
+ )), /* @__PURE__ */ React47.createElement("div", { className: `absolute -bottom-1 -right-1 w-2.5 h-2.5 rounded-full border-2 border-white z-10 ${getStatusColor()}` }));
4570
4606
  };
4571
4607
  var PageSpinner7 = () => /* @__PURE__ */ React47.createElement("div", { className: "flex justify-center items-center py-12" }, /* @__PURE__ */ React47.createElement(HugeiconsIcon33, { icon: Loading03Icon21, size: 32, className: "animate-spin mb-4 text-black" }));
4572
4608
  var UniversalMembersPage = ({
@@ -4585,17 +4621,22 @@ var UniversalMembersPage = ({
4585
4621
  onRoleFilterChange,
4586
4622
  actionButtonText,
4587
4623
  hideAction = false,
4588
- onRemoveMember
4624
+ onRemoveMember,
4625
+ onInviteMember
4589
4626
  }) => {
4590
4627
  const [expandedId, setExpandedId] = useState32(null);
4591
4628
  const [memberToRemove, setMemberToRemove] = useState32(null);
4592
4629
  const [isRemoving, setIsRemoving] = useState32(false);
4630
+ const [isInviteMode, setIsInviteMode] = useState32(false);
4631
+ const [inviteEmail, setInviteEmail] = useState32("");
4632
+ const [isInviting, setIsInviting] = useState32(false);
4593
4633
  const [localSearchQuery, setLocalSearchQuery] = useState32(searchQuery);
4594
4634
  const [isTyping, setIsTyping] = useState32(false);
4595
4635
  const [isStatusModalOpen, setIsStatusModalOpen] = useState32(false);
4596
4636
  const [isRoleModalOpen, setIsRoleModalOpen] = useState32(false);
4597
4637
  const statusDropdownRef = useRef12(null);
4598
4638
  const roleDropdownRef = useRef12(null);
4639
+ const cleanEmailId = (val) => val.toLowerCase().replace(/[^a-z0-9@._-]/g, "");
4599
4640
  useEffect18(() => {
4600
4641
  function handleClickOutside(event) {
4601
4642
  if (statusDropdownRef.current && !statusDropdownRef.current.contains(event.target)) {
@@ -4635,6 +4676,20 @@ var UniversalMembersPage = ({
4635
4676
  setIsRemoving(false);
4636
4677
  }
4637
4678
  };
4679
+ const handleInviteSubmit = async (e) => {
4680
+ e.preventDefault();
4681
+ if (inviteEmail.length < 5 || isInviting) return;
4682
+ setIsInviting(true);
4683
+ try {
4684
+ await onInviteMember(inviteEmail);
4685
+ setInviteEmail("");
4686
+ setIsInviteMode(false);
4687
+ } catch (error) {
4688
+ toast12.error(error.message || "Failed to send invitation.");
4689
+ } finally {
4690
+ setIsInviting(false);
4691
+ }
4692
+ };
4638
4693
  const isListLoading = isLoading || isTyping;
4639
4694
  return /* @__PURE__ */ React47.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ React47.createElement(ManagedToaster, null), /* @__PURE__ */ React47.createElement(
4640
4695
  ConfirmationDialog,
@@ -4649,7 +4704,7 @@ var UniversalMembersPage = ({
4649
4704
  onClose: () => setMemberToRemove(null),
4650
4705
  onConfirm: handleConfirmRemove
4651
4706
  }
4652
- ), /* @__PURE__ */ React47.createElement("div", { className: "flex flex-row flex-nowrap mb-4 items-center justify-between gap-4 w-full" }, /* @__PURE__ */ React47.createElement("div", { className: "relative flex-1 min-w-0 max-w-full" }, /* @__PURE__ */ React47.createElement("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none" }, /* @__PURE__ */ React47.createElement(HugeiconsIcon33, { icon: Search01Icon3, size: 16, className: "text-neutral-400" })), /* @__PURE__ */ React47.createElement(
4707
+ ), !isInviteMode && /* @__PURE__ */ React47.createElement("div", { className: "flex flex-row flex-nowrap mb-4 items-center justify-between gap-4 w-full animate-in fade-in duration-300" }, /* @__PURE__ */ React47.createElement("div", { className: "relative flex-1 min-w-0 max-w-full" }, /* @__PURE__ */ React47.createElement("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none" }, /* @__PURE__ */ React47.createElement(HugeiconsIcon33, { icon: Search01Icon3, size: 16, className: "text-neutral-400" })), /* @__PURE__ */ React47.createElement(
4653
4708
  "input",
4654
4709
  {
4655
4710
  type: "text",
@@ -4672,7 +4727,46 @@ var UniversalMembersPage = ({
4672
4727
  className: "flex items-center justify-center bg-white w-9 h-9 rounded-full text-neutral-500 hover:text-black transition-colors outline-none"
4673
4728
  },
4674
4729
  /* @__PURE__ */ React47.createElement(HugeiconsIcon33, { icon: ListSettingIcon2, size: 16 })
4675
- ))), /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col gap-8 p-6 rounded-2xl bg-white w-full" }, /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col sm:flex-row sm:items-start justify-between gap-4" }, /* @__PURE__ */ React47.createElement("div", null, /* @__PURE__ */ React47.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, headerTitle), headerDescription && /* @__PURE__ */ React47.createElement("p", { className: "text-[12px] text-neutral-500" }, headerDescription))), /* @__PURE__ */ React47.createElement("div", { className: "w-full overflow-hidden" }, isListLoading ? /* @__PURE__ */ React47.createElement(PageSpinner7, null) : /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React47.createElement("div", null, members.length === 0 ? /* @__PURE__ */ React47.createElement("p", { className: "text-[12px] text-neutral-400 py-6 text-center" }, "No members found") : members.map((member) => /* @__PURE__ */ React47.createElement(React47.Fragment, { key: member.id }, expandedId === member.id ? /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col p-5 bg-neutral-50 rounded-xl animate-in fade-in zoom-in-95 duration-200 gap-5 my-2" }, /* @__PURE__ */ React47.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React47.createElement(MemberAvatar, { src: member.avatarUrl, status: member.status }), /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React47.createElement("span", { className: "text-[14px] text-black tracking-tight truncate" }, member.name), /* @__PURE__ */ React47.createElement("span", { className: "text-[12px] text-neutral-500 capitalize" }, member.role.toLowerCase()))), member.departmentName && /* @__PURE__ */ React47.createElement("div", { className: "pt-3 border-t border-neutral-200" }, /* @__PURE__ */ React47.createElement("span", { className: "text-[10px] tracking-[0.2em] text-neutral-400 block mb-1" }, "Department"), /* @__PURE__ */ React47.createElement("span", { className: "text-[13px] text-black truncate block" }, member.departmentName)), /* @__PURE__ */ React47.createElement("div", { className: "flex gap-3 pt-2" }, !hideAction && /* @__PURE__ */ React47.createElement(
4730
+ ))), /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col gap-8 p-6 rounded-2xl bg-white w-full" }, /* @__PURE__ */ React47.createElement("div", { className: "flex flex-row items-start justify-between gap-4" }, /* @__PURE__ */ React47.createElement("div", null, /* @__PURE__ */ React47.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, isInviteMode ? "Add Member" : headerTitle), headerDescription && !isInviteMode && /* @__PURE__ */ React47.createElement("p", { className: "text-[12px] text-neutral-500" }, headerDescription)), !isInviteMode && /* @__PURE__ */ React47.createElement(
4731
+ "button",
4732
+ {
4733
+ onClick: () => setIsInviteMode(true),
4734
+ className: "shrink-0 px-4 py-2 border border-neutral-200 text-black text-[12px] tracking-wide rounded-full hover:bg-neutral-50 transition-colors outline-none"
4735
+ },
4736
+ "Invite Team"
4737
+ )), /* @__PURE__ */ React47.createElement("div", { className: "w-full overflow-hidden" }, isInviteMode ? /* @__PURE__ */ React47.createElement("form", { onSubmit: handleInviteSubmit, className: "flex flex-col gap-8 animate-in fade-in duration-300" }, /* @__PURE__ */ React47.createElement("div", { className: "space-y-1.5 mt-2" }, /* @__PURE__ */ React47.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, "Email Address"), /* @__PURE__ */ React47.createElement(
4738
+ "input",
4739
+ {
4740
+ type: "email",
4741
+ value: inviteEmail,
4742
+ onChange: (e) => setInviteEmail(cleanEmailId(e.target.value)),
4743
+ required: true,
4744
+ autoFocus: true,
4745
+ 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",
4746
+ placeholder: "name@company.com"
4747
+ }
4748
+ )), /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col gap-3" }, /* @__PURE__ */ React47.createElement(
4749
+ ThreeDActionButton,
4750
+ {
4751
+ type: "submit",
4752
+ disabled: inviteEmail.length < 5 || isInviting,
4753
+ isLoading: isInviting,
4754
+ className: "w-full"
4755
+ },
4756
+ "Send Invitation"
4757
+ ), /* @__PURE__ */ React47.createElement(
4758
+ "button",
4759
+ {
4760
+ type: "button",
4761
+ onClick: () => {
4762
+ setIsInviteMode(false);
4763
+ setInviteEmail("");
4764
+ },
4765
+ disabled: isInviting,
4766
+ className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 transition-colors outline-none text-xs tracking-wide"
4767
+ },
4768
+ "Cancel"
4769
+ ))) : isListLoading ? /* @__PURE__ */ React47.createElement(PageSpinner7, null) : /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col min-w-0 animate-in fade-in duration-300" }, /* @__PURE__ */ React47.createElement("div", null, members.length === 0 ? /* @__PURE__ */ React47.createElement("p", { className: "text-[12px] text-neutral-400 py-6 text-center" }, "No members found") : members.map((member) => /* @__PURE__ */ React47.createElement(React47.Fragment, { key: member.id }, expandedId === member.id ? /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col p-5 bg-neutral-50 rounded-xl animate-in fade-in zoom-in-95 duration-200 gap-5 my-2" }, /* @__PURE__ */ React47.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React47.createElement(MemberAvatar, { src: member.avatarUrl, status: member.status }), /* @__PURE__ */ React47.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React47.createElement("span", { className: "text-[14px] text-black tracking-tight truncate" }, member.name), /* @__PURE__ */ React47.createElement("span", { className: "text-[12px] text-neutral-500 capitalize" }, member.role.toLowerCase()))), member.departmentName && /* @__PURE__ */ React47.createElement("div", { className: "pt-3 border-t border-neutral-200" }, /* @__PURE__ */ React47.createElement("span", { className: "text-[10px] tracking-[0.2em] text-neutral-400 block mb-1" }, "Department"), /* @__PURE__ */ React47.createElement("span", { className: "text-[13px] text-black truncate block" }, member.departmentName)), /* @__PURE__ */ React47.createElement("div", { className: "flex gap-3 pt-2" }, !hideAction && /* @__PURE__ */ React47.createElement(
4676
4770
  "button",
4677
4771
  {
4678
4772
  onClick: () => setMemberToRemove(member),
@@ -4768,7 +4862,7 @@ var UniversalHome2 = ({
4768
4862
  const fallbackAvatarUrl = "https://storage.googleapis.com/retina-cloud-v2/assets/images/avatar.avif";
4769
4863
  const finalAvatarSrc = avatarSrc || fallbackAvatarUrl;
4770
4864
  const hasUnreadNotifs = notifications.some((n) => !n.isRead);
4771
- return /* @__PURE__ */ React48.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative" }, /* @__PURE__ */ React48.createElement("div", { className: "flex items-center justify-between w-full pb-4" }, /* @__PURE__ */ React48.createElement("div", { className: "w-10 h-10 shrink-0 cursor-pointer", onClick: () => router.push("/app/account/me") }, /* @__PURE__ */ React48.createElement("div", { className: "relative w-full h-full rounded-lg overflow-hidden bg-neutral-100 flex items-center justify-center border border-neutral-200" }, !isAvatarLoaded && /* @__PURE__ */ React48.createElement("div", { className: "absolute inset-0 flex items-center justify-center z-10 bg-neutral-100" }, /* @__PURE__ */ React48.createElement(HugeiconsIcon34, { icon: Loading03Icon22, size: 16, className: "animate-spin text-black" })), /* @__PURE__ */ React48.createElement(
4865
+ return /* @__PURE__ */ React48.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative" }, /* @__PURE__ */ React48.createElement("div", { className: "flex items-center justify-between w-full pb-4" }, /* @__PURE__ */ React48.createElement("div", { className: "w-10 h-10 shrink-0 cursor-pointer", onClick: () => router.push("/app/account/me") }, /* @__PURE__ */ React48.createElement("div", { className: "relative w-full h-full rounded-lg overflow-hidden bg-white flex items-center justify-center" }, !isAvatarLoaded && /* @__PURE__ */ React48.createElement("div", { className: "absolute inset-0 flex items-center justify-center z-10 bg-white" }, /* @__PURE__ */ React48.createElement(HugeiconsIcon34, { icon: Loading03Icon22, size: 16, className: "animate-spin text-black" })), /* @__PURE__ */ React48.createElement(
4772
4866
  "img",
4773
4867
  {
4774
4868
  src: finalAvatarSrc,
@@ -4799,7 +4893,7 @@ var UniversalHome2 = ({
4799
4893
  {
4800
4894
  src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/cal_a.avif",
4801
4895
  alt: "Create Huddle",
4802
- 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"
4896
+ 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 "
4803
4897
  }
4804
4898
  )
4805
4899
  ), /* @__PURE__ */ React48.createElement(
@@ -4814,7 +4908,7 @@ var UniversalHome2 = ({
4814
4908
  {
4815
4909
  src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/cam_a.avif",
4816
4910
  alt: "Join Huddle",
4817
- 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"
4911
+ 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 "
4818
4912
  }
4819
4913
  )
4820
4914
  ))), customContent && /* @__PURE__ */ React48.createElement("div", { className: "w-full" }, customContent), /* @__PURE__ */ React48.createElement("div", { className: "w-full mt-2" }, /* @__PURE__ */ React48.createElement(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retinalabsllc/zairusjs",
3
- "version": "16.0.90",
3
+ "version": "16.1.1",
4
4
  "description": "A perceptive, Ai data driven Next.js UI component library.",
5
5
  "author": "Retina Labs Company",
6
6
  "license": "MIT",