@retinalabsllc/zairusjs 10.0.2 → 10.0.9

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
@@ -404,7 +404,8 @@ interface UniversalSecurityPageProps {
404
404
  onVerifyAndDisable2FA?: (otp: string) => Promise<{
405
405
  success: boolean;
406
406
  }>;
407
- onEnablePasskey?: () => Promise<{
407
+ onRequestPasskeySetup?: () => Promise<any>;
408
+ onVerifyAndEnablePasskey?: (credential: any) => Promise<{
408
409
  success: boolean;
409
410
  }>;
410
411
  onDisablePasskey?: () => Promise<{
package/dist/index.d.ts CHANGED
@@ -404,7 +404,8 @@ interface UniversalSecurityPageProps {
404
404
  onVerifyAndDisable2FA?: (otp: string) => Promise<{
405
405
  success: boolean;
406
406
  }>;
407
- onEnablePasskey?: () => Promise<{
407
+ onRequestPasskeySetup?: () => Promise<any>;
408
+ onVerifyAndEnablePasskey?: (credential: any) => Promise<{
408
409
  success: boolean;
409
410
  }>;
410
411
  onDisablePasskey?: () => Promise<{
package/dist/index.js CHANGED
@@ -2665,6 +2665,7 @@ var import_react45 = __toESM(require("react"));
2665
2665
  var import_react_hot_toast8 = __toESM(require("react-hot-toast"));
2666
2666
  var import_react46 = require("@hugeicons/react");
2667
2667
  var import_core_free_icons16 = require("@hugeicons/core-free-icons");
2668
+ var import_browser = require("@simplewebauthn/browser");
2668
2669
  var UniversalSecurityPage = ({
2669
2670
  has2FA,
2670
2671
  hasPasskey,
@@ -2675,7 +2676,8 @@ var UniversalSecurityPage = ({
2675
2676
  onRequest2FASetup,
2676
2677
  onVerifyAndEnable2FA,
2677
2678
  onVerifyAndDisable2FA,
2678
- onEnablePasskey,
2679
+ onRequestPasskeySetup,
2680
+ onVerifyAndEnablePasskey,
2679
2681
  onDisablePasskey
2680
2682
  }) => {
2681
2683
  const [show2FASetupModal, setShow2FASetupModal] = (0, import_react45.useState)(false);
@@ -2714,9 +2716,14 @@ var UniversalSecurityPage = ({
2714
2716
  };
2715
2717
  const handleCopySecret = async (secret) => {
2716
2718
  try {
2717
- if (navigator.clipboard && window.isSecureContext) {
2719
+ if (navigator?.clipboard?.writeText && window.isSecureContext) {
2718
2720
  await navigator.clipboard.writeText(secret);
2721
+ import_react_hot_toast8.default.success("Secret copied to clipboard");
2719
2722
  } else {
2723
+ throw new Error("Clipboard API not available");
2724
+ }
2725
+ } catch (e) {
2726
+ try {
2720
2727
  const textArea = document.createElement("textarea");
2721
2728
  textArea.value = secret;
2722
2729
  textArea.style.position = "fixed";
@@ -2727,10 +2734,10 @@ var UniversalSecurityPage = ({
2727
2734
  textArea.select();
2728
2735
  document.execCommand("copy");
2729
2736
  textArea.remove();
2737
+ import_react_hot_toast8.default.success("Secret copied to clipboard");
2738
+ } catch (err) {
2739
+ import_react_hot_toast8.default.error("Unable to copy. Please manually copy the key.");
2730
2740
  }
2731
- import_react_hot_toast8.default.success("Secret copied to clipboard");
2732
- } catch {
2733
- import_react_hot_toast8.default.error("Unable to copy");
2734
2741
  }
2735
2742
  };
2736
2743
  const handleToggle2FA = async () => {
@@ -2797,36 +2804,28 @@ var UniversalSecurityPage = ({
2797
2804
  }
2798
2805
  };
2799
2806
  const submitEnablePasskey = async () => {
2800
- if (!onEnablePasskey) return;
2807
+ if (!onRequestPasskeySetup || !onVerifyAndEnablePasskey) return;
2801
2808
  setIsSubmitting(true);
2802
2809
  try {
2803
- if (!window.PublicKeyCredential) {
2804
- throw new Error("Passkeys are not supported on this device/browser.");
2810
+ const options = await onRequestPasskeySetup();
2811
+ let credentialResponse;
2812
+ try {
2813
+ credentialResponse = await (0, import_browser.startRegistration)({ optionsJSON: options });
2814
+ } catch (err) {
2815
+ if (err.name === "NotAllowedError") {
2816
+ throw new Error("Passkey setup was canceled or is not supported on this device.");
2817
+ }
2818
+ throw err;
2805
2819
  }
2806
- const challenge = window.crypto.getRandomValues ? window.crypto.getRandomValues(new Uint8Array(32)) : new Uint8Array(32).fill(1);
2807
- const userId = new Uint8Array(16).fill(2);
2808
- const publicKeyCredentialCreationOptions = {
2809
- challenge,
2810
- rp: { name: "Aeona Finance", id: window.location.hostname },
2811
- user: {
2812
- id: userId,
2813
- name: userEmail || "User",
2814
- displayName: userEmail || "User"
2815
- },
2816
- pubKeyCredParams: [{ alg: -7, type: "public-key" }, { alg: -257, type: "public-key" }],
2817
- authenticatorSelection: { authenticatorAttachment: "platform", userVerification: "required" },
2818
- timeout: 6e4,
2819
- attestation: "none"
2820
- };
2821
- const credential = await navigator.credentials.create({ publicKey: publicKeyCredentialCreationOptions });
2822
- if (!credential) throw new Error("Passkey creation was canceled.");
2823
- const res = await onEnablePasskey();
2820
+ const res = await onVerifyAndEnablePasskey(credentialResponse);
2824
2821
  if (res.success) {
2825
2822
  import_react_hot_toast8.default.success("Passkey Created Successfully");
2826
2823
  setShowPasskeyModal(false);
2824
+ } else {
2825
+ import_react_hot_toast8.default.error("Failed to verify device passkey.");
2827
2826
  }
2828
2827
  } catch (error) {
2829
- import_react_hot_toast8.default.error(error.message || "Passkey setup failed or was canceled.");
2828
+ import_react_hot_toast8.default.error(error.message || "Passkey setup interrupted.");
2830
2829
  } finally {
2831
2830
  setIsSubmitting(false);
2832
2831
  }
@@ -2862,18 +2861,10 @@ var UniversalSecurityPage = ({
2862
2861
  toggleLoading: isPasskeyLoading,
2863
2862
  isLast: true
2864
2863
  }
2865
- ))), show2FASetupModal && /* @__PURE__ */ import_react45.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FASetupModal(false) }), /* @__PURE__ */ import_react45.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 max-h-[90vh]" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ import_react45.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable 2FA"), /* @__PURE__ */ import_react45.default.createElement("button", { onClick: () => !isSubmitting && setShow2FASetupModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 pt-2" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "w-full flex justify-center mb-6 mix-blend-multiply" }, twoFaQr ? /* @__PURE__ */ import_react45.default.createElement("img", { src: twoFaQr, alt: "2FA QR Code", className: "w-40 h-40 object-contain rounded-xl border border-neutral-100 p-2" }) : /* @__PURE__ */ import_react45.default.createElement("div", { className: "w-40 h-40 bg-neutral-100 rounded-xl flex items-center justify-center animate-pulse" })), /* @__PURE__ */ import_react45.default.createElement("div", { className: "grid grid-cols-1 gap-y-6 gap-x-4 mb-8" }, /* @__PURE__ */ import_react45.default.createElement("div", null, /* @__PURE__ */ import_react45.default.createElement("span", { className: "text-[11px] tracking-[0.2em] text-neutral-400 block mb-2 uppercase" }, "Setup Key"), /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex items-center gap-2 min-w-0 bg-neutral-50 px-3 py-2.5 rounded-xl border border-neutral-100" }, /* @__PURE__ */ import_react45.default.createElement("span", { className: "text-[13px] font-mono tracking-widest text-black truncate min-w-0 block flex-1" }, twoFaSecret), /* @__PURE__ */ import_react45.default.createElement(
2866
- "button",
2867
- {
2868
- type: "button",
2869
- onClick: () => handleCopySecret(twoFaSecret),
2870
- className: "text-neutral-400 hover:text-black transition-colors outline-none shrink-0 ml-2"
2871
- },
2872
- /* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.Copy01Icon, size: 16 })
2873
- )))), /* @__PURE__ */ import_react45.default.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ import_react45.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react45.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the 6-digit code from your app")), /* @__PURE__ */ import_react45.default.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
2864
+ ))), show2FASetupModal && /* @__PURE__ */ import_react45.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FASetupModal(false) }), /* @__PURE__ */ import_react45.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 max-h-[90vh]" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ import_react45.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable 2FA"), /* @__PURE__ */ import_react45.default.createElement("button", { onClick: () => !isSubmitting && setShow2FASetupModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 pt-2" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "w-full flex justify-center mb-6 mix-blend-multiply" }, twoFaQr ? /* @__PURE__ */ import_react45.default.createElement("img", { src: twoFaQr, alt: "2FA QR Code", className: "w-40 h-40 object-contain rounded-xl border border-neutral-100 p-2" }) : /* @__PURE__ */ import_react45.default.createElement("div", { className: "w-40 h-40 bg-neutral-100 rounded-xl flex items-center justify-center animate-pulse" })), /* @__PURE__ */ import_react45.default.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ import_react45.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react45.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the 6-digit code from your app")), /* @__PURE__ */ import_react45.default.createElement("form", { className: "space-y-4", autoComplete: "off", onSubmit: (e) => {
2874
2865
  e.preventDefault();
2875
2866
  submitEnable2FA(otp.join(""));
2876
- } }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ import_react45.default.createElement(
2867
+ } }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex justify-between gap-2 pb-6", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ import_react45.default.createElement(
2877
2868
  "input",
2878
2869
  {
2879
2870
  key: index,
@@ -2906,8 +2897,9 @@ var UniversalSecurityPage = ({
2906
2897
  {
2907
2898
  type: "button",
2908
2899
  onClick: () => handleCopySecret(twoFaSecret),
2909
- className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 outline-none text-[13px] tracking-wide transition-colors mt-2"
2900
+ className: "w-full flex items-center justify-center py-3 rounded-full bg-neutral-100 text-black hover:bg-neutral-200 outline-none text-[13px] font-medium tracking-wide transition-colors mt-3"
2910
2901
  },
2902
+ /* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.Copy01Icon, size: 16, className: "mr-2" }),
2911
2903
  "Copy Secret Key"
2912
2904
  ))))), show2FADisableModal && /* @__PURE__ */ import_react45.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FADisableModal(false) }), /* @__PURE__ */ import_react45.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ import_react45.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Disable 2FA"), /* @__PURE__ */ import_react45.default.createElement("button", { onClick: () => !isSubmitting && setShow2FADisableModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react45.default.createElement(import_react46.HugeiconsIcon, { icon: import_core_free_icons16.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react45.default.createElement("div", { className: "p-6" }, /* @__PURE__ */ import_react45.default.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ import_react45.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react45.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the code from your authenticator app to disable 2FA.")), /* @__PURE__ */ import_react45.default.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
2913
2905
  e.preventDefault();
package/dist/index.mjs CHANGED
@@ -2653,6 +2653,7 @@ import {
2653
2653
  Key01Icon,
2654
2654
  ArrowRight01Icon as ArrowRight01Icon4
2655
2655
  } from "@hugeicons/core-free-icons";
2656
+ import { startRegistration } from "@simplewebauthn/browser";
2656
2657
  var UniversalSecurityPage = ({
2657
2658
  has2FA,
2658
2659
  hasPasskey,
@@ -2663,7 +2664,8 @@ var UniversalSecurityPage = ({
2663
2664
  onRequest2FASetup,
2664
2665
  onVerifyAndEnable2FA,
2665
2666
  onVerifyAndDisable2FA,
2666
- onEnablePasskey,
2667
+ onRequestPasskeySetup,
2668
+ onVerifyAndEnablePasskey,
2667
2669
  onDisablePasskey
2668
2670
  }) => {
2669
2671
  const [show2FASetupModal, setShow2FASetupModal] = useState18(false);
@@ -2702,9 +2704,14 @@ var UniversalSecurityPage = ({
2702
2704
  };
2703
2705
  const handleCopySecret = async (secret) => {
2704
2706
  try {
2705
- if (navigator.clipboard && window.isSecureContext) {
2707
+ if (navigator?.clipboard?.writeText && window.isSecureContext) {
2706
2708
  await navigator.clipboard.writeText(secret);
2709
+ toast7.success("Secret copied to clipboard");
2707
2710
  } else {
2711
+ throw new Error("Clipboard API not available");
2712
+ }
2713
+ } catch (e) {
2714
+ try {
2708
2715
  const textArea = document.createElement("textarea");
2709
2716
  textArea.value = secret;
2710
2717
  textArea.style.position = "fixed";
@@ -2715,10 +2722,10 @@ var UniversalSecurityPage = ({
2715
2722
  textArea.select();
2716
2723
  document.execCommand("copy");
2717
2724
  textArea.remove();
2725
+ toast7.success("Secret copied to clipboard");
2726
+ } catch (err) {
2727
+ toast7.error("Unable to copy. Please manually copy the key.");
2718
2728
  }
2719
- toast7.success("Secret copied to clipboard");
2720
- } catch {
2721
- toast7.error("Unable to copy");
2722
2729
  }
2723
2730
  };
2724
2731
  const handleToggle2FA = async () => {
@@ -2785,36 +2792,28 @@ var UniversalSecurityPage = ({
2785
2792
  }
2786
2793
  };
2787
2794
  const submitEnablePasskey = async () => {
2788
- if (!onEnablePasskey) return;
2795
+ if (!onRequestPasskeySetup || !onVerifyAndEnablePasskey) return;
2789
2796
  setIsSubmitting(true);
2790
2797
  try {
2791
- if (!window.PublicKeyCredential) {
2792
- throw new Error("Passkeys are not supported on this device/browser.");
2798
+ const options = await onRequestPasskeySetup();
2799
+ let credentialResponse;
2800
+ try {
2801
+ credentialResponse = await startRegistration({ optionsJSON: options });
2802
+ } catch (err) {
2803
+ if (err.name === "NotAllowedError") {
2804
+ throw new Error("Passkey setup was canceled or is not supported on this device.");
2805
+ }
2806
+ throw err;
2793
2807
  }
2794
- const challenge = window.crypto.getRandomValues ? window.crypto.getRandomValues(new Uint8Array(32)) : new Uint8Array(32).fill(1);
2795
- const userId = new Uint8Array(16).fill(2);
2796
- const publicKeyCredentialCreationOptions = {
2797
- challenge,
2798
- rp: { name: "Aeona Finance", id: window.location.hostname },
2799
- user: {
2800
- id: userId,
2801
- name: userEmail || "User",
2802
- displayName: userEmail || "User"
2803
- },
2804
- pubKeyCredParams: [{ alg: -7, type: "public-key" }, { alg: -257, type: "public-key" }],
2805
- authenticatorSelection: { authenticatorAttachment: "platform", userVerification: "required" },
2806
- timeout: 6e4,
2807
- attestation: "none"
2808
- };
2809
- const credential = await navigator.credentials.create({ publicKey: publicKeyCredentialCreationOptions });
2810
- if (!credential) throw new Error("Passkey creation was canceled.");
2811
- const res = await onEnablePasskey();
2808
+ const res = await onVerifyAndEnablePasskey(credentialResponse);
2812
2809
  if (res.success) {
2813
2810
  toast7.success("Passkey Created Successfully");
2814
2811
  setShowPasskeyModal(false);
2812
+ } else {
2813
+ toast7.error("Failed to verify device passkey.");
2815
2814
  }
2816
2815
  } catch (error) {
2817
- toast7.error(error.message || "Passkey setup failed or was canceled.");
2816
+ toast7.error(error.message || "Passkey setup interrupted.");
2818
2817
  } finally {
2819
2818
  setIsSubmitting(false);
2820
2819
  }
@@ -2850,18 +2849,10 @@ var UniversalSecurityPage = ({
2850
2849
  toggleLoading: isPasskeyLoading,
2851
2850
  isLast: true
2852
2851
  }
2853
- ))), show2FASetupModal && /* @__PURE__ */ React27.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React27.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FASetupModal(false) }), /* @__PURE__ */ React27.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 max-h-[90vh]" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ React27.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable 2FA"), /* @__PURE__ */ React27.createElement("button", { onClick: () => !isSubmitting && setShow2FASetupModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: CancelCircleIcon6, size: 18 }))), /* @__PURE__ */ React27.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 pt-2" }, /* @__PURE__ */ React27.createElement("div", { className: "w-full flex justify-center mb-6 mix-blend-multiply" }, twoFaQr ? /* @__PURE__ */ React27.createElement("img", { src: twoFaQr, alt: "2FA QR Code", className: "w-40 h-40 object-contain rounded-xl border border-neutral-100 p-2" }) : /* @__PURE__ */ React27.createElement("div", { className: "w-40 h-40 bg-neutral-100 rounded-xl flex items-center justify-center animate-pulse" })), /* @__PURE__ */ React27.createElement("div", { className: "grid grid-cols-1 gap-y-6 gap-x-4 mb-8" }, /* @__PURE__ */ React27.createElement("div", null, /* @__PURE__ */ React27.createElement("span", { className: "text-[11px] tracking-[0.2em] text-neutral-400 block mb-2 uppercase" }, "Setup Key"), /* @__PURE__ */ React27.createElement("div", { className: "flex items-center gap-2 min-w-0 bg-neutral-50 px-3 py-2.5 rounded-xl border border-neutral-100" }, /* @__PURE__ */ React27.createElement("span", { className: "text-[13px] font-mono tracking-widest text-black truncate min-w-0 block flex-1" }, twoFaSecret), /* @__PURE__ */ React27.createElement(
2854
- "button",
2855
- {
2856
- type: "button",
2857
- onClick: () => handleCopySecret(twoFaSecret),
2858
- className: "text-neutral-400 hover:text-black transition-colors outline-none shrink-0 ml-2"
2859
- },
2860
- /* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: Copy01Icon3, size: 16 })
2861
- )))), /* @__PURE__ */ React27.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ React27.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ React27.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the 6-digit code from your app")), /* @__PURE__ */ React27.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
2852
+ ))), show2FASetupModal && /* @__PURE__ */ React27.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React27.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FASetupModal(false) }), /* @__PURE__ */ React27.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 max-h-[90vh]" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ React27.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable 2FA"), /* @__PURE__ */ React27.createElement("button", { onClick: () => !isSubmitting && setShow2FASetupModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: CancelCircleIcon6, size: 18 }))), /* @__PURE__ */ React27.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 pt-2" }, /* @__PURE__ */ React27.createElement("div", { className: "w-full flex justify-center mb-6 mix-blend-multiply" }, twoFaQr ? /* @__PURE__ */ React27.createElement("img", { src: twoFaQr, alt: "2FA QR Code", className: "w-40 h-40 object-contain rounded-xl border border-neutral-100 p-2" }) : /* @__PURE__ */ React27.createElement("div", { className: "w-40 h-40 bg-neutral-100 rounded-xl flex items-center justify-center animate-pulse" })), /* @__PURE__ */ React27.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ React27.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ React27.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the 6-digit code from your app")), /* @__PURE__ */ React27.createElement("form", { className: "space-y-4", autoComplete: "off", onSubmit: (e) => {
2862
2853
  e.preventDefault();
2863
2854
  submitEnable2FA(otp.join(""));
2864
- } }, /* @__PURE__ */ React27.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ React27.createElement(
2855
+ } }, /* @__PURE__ */ React27.createElement("div", { className: "flex justify-between gap-2 pb-6", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ React27.createElement(
2865
2856
  "input",
2866
2857
  {
2867
2858
  key: index,
@@ -2894,8 +2885,9 @@ var UniversalSecurityPage = ({
2894
2885
  {
2895
2886
  type: "button",
2896
2887
  onClick: () => handleCopySecret(twoFaSecret),
2897
- className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 outline-none text-[13px] tracking-wide transition-colors mt-2"
2888
+ className: "w-full flex items-center justify-center py-3 rounded-full bg-neutral-100 text-black hover:bg-neutral-200 outline-none text-[13px] font-medium tracking-wide transition-colors mt-3"
2898
2889
  },
2890
+ /* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: Copy01Icon3, size: 16, className: "mr-2" }),
2899
2891
  "Copy Secret Key"
2900
2892
  ))))), show2FADisableModal && /* @__PURE__ */ React27.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React27.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FADisableModal(false) }), /* @__PURE__ */ React27.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React27.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ React27.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Disable 2FA"), /* @__PURE__ */ React27.createElement("button", { onClick: () => !isSubmitting && setShow2FADisableModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ React27.createElement(HugeiconsIcon19, { icon: CancelCircleIcon6, size: 18 }))), /* @__PURE__ */ React27.createElement("div", { className: "p-6" }, /* @__PURE__ */ React27.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ React27.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ React27.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the code from your authenticator app to disable 2FA.")), /* @__PURE__ */ React27.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
2901
2893
  e.preventDefault();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retinalabsllc/zairusjs",
3
- "version": "10.0.2",
3
+ "version": "10.0.9",
4
4
  "description": "A perceptive, Ai data driven Next.js UI component library.",
5
5
  "author": "Retina Labs Company",
6
6
  "license": "MIT",
@@ -39,6 +39,8 @@
39
39
  "dependencies": {
40
40
  "@hugeicons/core-free-icons": "^1.1.0",
41
41
  "@hugeicons/react": "^1.1.1",
42
+ "@simplewebauthn/browser": "^13.3.0",
43
+ "@simplewebauthn/server": "^13.3.2",
42
44
  "clsx": "^2.1.1",
43
45
  "react-google-recaptcha-v3": "^1.11.0",
44
46
  "react-hot-toast": "^2.6.0",