@retinalabsllc/zairusjs 16.0.2 → 16.0.25

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
@@ -920,4 +920,56 @@ interface PinDialerBottomSheetProps {
920
920
  }
921
921
  declare const PinDialerBottomSheet: React.FC<PinDialerBottomSheetProps>;
922
922
 
923
- export { AppBento2, type AppBento2Props, type BannerProps, type BentoFeature, type BoardMember, type CardData, CardInfoDialog, type CardInfoDialogProps, type CompanyDetails, type ConsultantProfile, ConsultantShowcase, type ConsultantShowcaseProps, ContentGridBlock, type ContentGridBlockProps, type DocumentSectionData, type EmailContact, Faq, type FaqItem, type FaqProps, FeatureScroll, type FeatureScrollProps, Footer, type FooterColumn, type FooterLink, type FooterProps, FundCardDialog, type FundCardDialogProps, GifFeatureCard, type GifFeatureCardProps, Header, type HeaderLink, type HeaderProps, type AppLogo$1 as HeroAppLogo, HeroSection, type HeroSectionProps, type HomeActionBtn, type LeaderboardItem, ManagedBoardBlock, type ManagedBoardBlockProps, ManagedContactBlock, type ManagedContactBlockProps, ManagedDocument, type ManagedDocumentProps, ManagedNewsletterSplitBlock, type ManagedNewsletterSplitBlockProps, ManagedNotFoundBlock, type ManagedNotFoundBlockProps, ManagedPricingBlock, type ManagedPricingBlockProps, ManagedProjectsBlock, type ManagedProjectsBlockProps, ManagedToaster, MedicalFeatureStatsBlock, MobileNav, type MobileNavItem, type MobileNavProps, type NavItem, type NotificationItem, NumberInput, type NumberInputProps, PageSpinner, type PageSpinnerProps, PinDialerBottomSheet, type PinDialerBottomSheetProps, PipleAuth, type PipleAuthProps, type PlatformFeatureItem, PlatformFeatures, type PlatformFeaturesProps, PortfolioHero, type PortfolioHeroProps, type AppLogo as PricingAppLogo, type PricingFeature, type PricingFeature2, type PricingPlan, type PricingTab, type ProjectItem, type ReferralProfile, type RewardItem, type RewardProfile, type ScrollFeature, type SocialContact, type SocialLink, type StatItem, TextInput, type TextInputProps, ThreeDActionButton, type ThreeDActionButtonProps, ThreeDButton, type ThreeDButtonProps, type TierOption, UniversalCardActionPage, type UniversalCardActionPageProps, UniversalCardPage, type UniversalCardPageProps, UniversalErrorView, type UniversalErrorViewProps, UniversalHomeView, type UniversalHomeViewProps, UniversalOrganizationPage, type UniversalOrganizationPageProps, UniversalProfilePage, type UniversalProfilePageProps, UniversalProfileSettings, type UniversalProfileSettingsProps, type UniversalReferralItem, UniversalReferralPage, type UniversalReferralPageProps, UniversalRewardPage, type UniversalRewardPageProps, UniversalSecurityPage, type UniversalSecurityPageProps, UniversalSidebar, type UniversalSidebarProps, type UniversalTransaction, UniversalTransactionPage, type UniversalTransactionPageProps, UniversalVerificationPage, type UniversalVerificationPageProps, type UniversalWallet, UniversalWalletPage, type UniversalWalletPageProps, type VerificationStatus, WaitlistDialog, type WaitlistDialogProps };
923
+ interface CryptoOption {
924
+ code: string;
925
+ name: string;
926
+ logoUrl: string;
927
+ networks: NetworkOption[];
928
+ }
929
+ interface NetworkOption {
930
+ id: string;
931
+ name: string;
932
+ symbol: string;
933
+ logoUrl?: string;
934
+ addressRegex?: string;
935
+ }
936
+ interface FiatCurrencyOption {
937
+ code: string;
938
+ symbol: string;
939
+ name: string;
940
+ logoUrl: string;
941
+ }
942
+ interface RateCalculationPayload {
943
+ fiatAmount: string;
944
+ cryptoAmount: string;
945
+ activeSource: 'FIAT' | 'CRYPTO';
946
+ crypto: CryptoOption;
947
+ fiat: FiatCurrencyOption;
948
+ }
949
+ interface UniversalBuyCryptoPageProps {
950
+ fiatCurrency: FiatCurrencyOption;
951
+ cryptoOptions: CryptoOption[];
952
+ defaultCryptoCode?: string;
953
+ hideBackButton?: boolean;
954
+ hideRecipientSection?: boolean;
955
+ readOnlyRecipientSection?: boolean;
956
+ defaultRecipientAddress?: string;
957
+ defaultNetworkId?: string;
958
+ onCalculateRate?: (payload: RateCalculationPayload) => Promise<{
959
+ fiatAmount: string;
960
+ cryptoAmount: string;
961
+ ratePerToken?: string;
962
+ }>;
963
+ onSubmitCheckout?: (payload: {
964
+ fiatAmount: string;
965
+ cryptoAmount: string;
966
+ selectedCrypto: CryptoOption;
967
+ selectedNetwork: NetworkOption;
968
+ recipientAddress: string;
969
+ fiatCurrency: FiatCurrencyOption;
970
+ }) => Promise<void>;
971
+ onBack?: () => void;
972
+ }
973
+ declare const UniversalBuyCryptoPage: React.FC<UniversalBuyCryptoPageProps>;
974
+
975
+ export { AppBento2, type AppBento2Props, type BannerProps, type BentoFeature, type BoardMember, type CardData, CardInfoDialog, type CardInfoDialogProps, type CompanyDetails, type ConsultantProfile, ConsultantShowcase, type ConsultantShowcaseProps, ContentGridBlock, type ContentGridBlockProps, type CryptoOption, type DocumentSectionData, type EmailContact, Faq, type FaqItem, type FaqProps, FeatureScroll, type FeatureScrollProps, type FiatCurrencyOption, Footer, type FooterColumn, type FooterLink, type FooterProps, FundCardDialog, type FundCardDialogProps, GifFeatureCard, type GifFeatureCardProps, Header, type HeaderLink, type HeaderProps, type AppLogo$1 as HeroAppLogo, HeroSection, type HeroSectionProps, type HomeActionBtn, type LeaderboardItem, ManagedBoardBlock, type ManagedBoardBlockProps, ManagedContactBlock, type ManagedContactBlockProps, ManagedDocument, type ManagedDocumentProps, ManagedNewsletterSplitBlock, type ManagedNewsletterSplitBlockProps, ManagedNotFoundBlock, type ManagedNotFoundBlockProps, ManagedPricingBlock, type ManagedPricingBlockProps, ManagedProjectsBlock, type ManagedProjectsBlockProps, ManagedToaster, MedicalFeatureStatsBlock, MobileNav, type MobileNavItem, type MobileNavProps, type NavItem, type NetworkOption, type NotificationItem, NumberInput, type NumberInputProps, PageSpinner, type PageSpinnerProps, PinDialerBottomSheet, type PinDialerBottomSheetProps, PipleAuth, type PipleAuthProps, type PlatformFeatureItem, PlatformFeatures, type PlatformFeaturesProps, PortfolioHero, type PortfolioHeroProps, type AppLogo as PricingAppLogo, type PricingFeature, type PricingFeature2, type PricingPlan, type PricingTab, type ProjectItem, type RateCalculationPayload, type ReferralProfile, type RewardItem, type RewardProfile, type ScrollFeature, type SocialContact, type SocialLink, type StatItem, TextInput, type TextInputProps, ThreeDActionButton, type ThreeDActionButtonProps, ThreeDButton, type ThreeDButtonProps, type TierOption, UniversalBuyCryptoPage, type UniversalBuyCryptoPageProps, UniversalCardActionPage, type UniversalCardActionPageProps, UniversalCardPage, type UniversalCardPageProps, UniversalErrorView, type UniversalErrorViewProps, UniversalHomeView, type UniversalHomeViewProps, UniversalOrganizationPage, type UniversalOrganizationPageProps, UniversalProfilePage, type UniversalProfilePageProps, UniversalProfileSettings, type UniversalProfileSettingsProps, type UniversalReferralItem, UniversalReferralPage, type UniversalReferralPageProps, UniversalRewardPage, type UniversalRewardPageProps, UniversalSecurityPage, type UniversalSecurityPageProps, UniversalSidebar, type UniversalSidebarProps, type UniversalTransaction, UniversalTransactionPage, type UniversalTransactionPageProps, UniversalVerificationPage, type UniversalVerificationPageProps, type UniversalWallet, UniversalWalletPage, type UniversalWalletPageProps, type VerificationStatus, WaitlistDialog, type WaitlistDialogProps };
package/dist/index.d.ts CHANGED
@@ -920,4 +920,56 @@ interface PinDialerBottomSheetProps {
920
920
  }
921
921
  declare const PinDialerBottomSheet: React.FC<PinDialerBottomSheetProps>;
922
922
 
923
- export { AppBento2, type AppBento2Props, type BannerProps, type BentoFeature, type BoardMember, type CardData, CardInfoDialog, type CardInfoDialogProps, type CompanyDetails, type ConsultantProfile, ConsultantShowcase, type ConsultantShowcaseProps, ContentGridBlock, type ContentGridBlockProps, type DocumentSectionData, type EmailContact, Faq, type FaqItem, type FaqProps, FeatureScroll, type FeatureScrollProps, Footer, type FooterColumn, type FooterLink, type FooterProps, FundCardDialog, type FundCardDialogProps, GifFeatureCard, type GifFeatureCardProps, Header, type HeaderLink, type HeaderProps, type AppLogo$1 as HeroAppLogo, HeroSection, type HeroSectionProps, type HomeActionBtn, type LeaderboardItem, ManagedBoardBlock, type ManagedBoardBlockProps, ManagedContactBlock, type ManagedContactBlockProps, ManagedDocument, type ManagedDocumentProps, ManagedNewsletterSplitBlock, type ManagedNewsletterSplitBlockProps, ManagedNotFoundBlock, type ManagedNotFoundBlockProps, ManagedPricingBlock, type ManagedPricingBlockProps, ManagedProjectsBlock, type ManagedProjectsBlockProps, ManagedToaster, MedicalFeatureStatsBlock, MobileNav, type MobileNavItem, type MobileNavProps, type NavItem, type NotificationItem, NumberInput, type NumberInputProps, PageSpinner, type PageSpinnerProps, PinDialerBottomSheet, type PinDialerBottomSheetProps, PipleAuth, type PipleAuthProps, type PlatformFeatureItem, PlatformFeatures, type PlatformFeaturesProps, PortfolioHero, type PortfolioHeroProps, type AppLogo as PricingAppLogo, type PricingFeature, type PricingFeature2, type PricingPlan, type PricingTab, type ProjectItem, type ReferralProfile, type RewardItem, type RewardProfile, type ScrollFeature, type SocialContact, type SocialLink, type StatItem, TextInput, type TextInputProps, ThreeDActionButton, type ThreeDActionButtonProps, ThreeDButton, type ThreeDButtonProps, type TierOption, UniversalCardActionPage, type UniversalCardActionPageProps, UniversalCardPage, type UniversalCardPageProps, UniversalErrorView, type UniversalErrorViewProps, UniversalHomeView, type UniversalHomeViewProps, UniversalOrganizationPage, type UniversalOrganizationPageProps, UniversalProfilePage, type UniversalProfilePageProps, UniversalProfileSettings, type UniversalProfileSettingsProps, type UniversalReferralItem, UniversalReferralPage, type UniversalReferralPageProps, UniversalRewardPage, type UniversalRewardPageProps, UniversalSecurityPage, type UniversalSecurityPageProps, UniversalSidebar, type UniversalSidebarProps, type UniversalTransaction, UniversalTransactionPage, type UniversalTransactionPageProps, UniversalVerificationPage, type UniversalVerificationPageProps, type UniversalWallet, UniversalWalletPage, type UniversalWalletPageProps, type VerificationStatus, WaitlistDialog, type WaitlistDialogProps };
923
+ interface CryptoOption {
924
+ code: string;
925
+ name: string;
926
+ logoUrl: string;
927
+ networks: NetworkOption[];
928
+ }
929
+ interface NetworkOption {
930
+ id: string;
931
+ name: string;
932
+ symbol: string;
933
+ logoUrl?: string;
934
+ addressRegex?: string;
935
+ }
936
+ interface FiatCurrencyOption {
937
+ code: string;
938
+ symbol: string;
939
+ name: string;
940
+ logoUrl: string;
941
+ }
942
+ interface RateCalculationPayload {
943
+ fiatAmount: string;
944
+ cryptoAmount: string;
945
+ activeSource: 'FIAT' | 'CRYPTO';
946
+ crypto: CryptoOption;
947
+ fiat: FiatCurrencyOption;
948
+ }
949
+ interface UniversalBuyCryptoPageProps {
950
+ fiatCurrency: FiatCurrencyOption;
951
+ cryptoOptions: CryptoOption[];
952
+ defaultCryptoCode?: string;
953
+ hideBackButton?: boolean;
954
+ hideRecipientSection?: boolean;
955
+ readOnlyRecipientSection?: boolean;
956
+ defaultRecipientAddress?: string;
957
+ defaultNetworkId?: string;
958
+ onCalculateRate?: (payload: RateCalculationPayload) => Promise<{
959
+ fiatAmount: string;
960
+ cryptoAmount: string;
961
+ ratePerToken?: string;
962
+ }>;
963
+ onSubmitCheckout?: (payload: {
964
+ fiatAmount: string;
965
+ cryptoAmount: string;
966
+ selectedCrypto: CryptoOption;
967
+ selectedNetwork: NetworkOption;
968
+ recipientAddress: string;
969
+ fiatCurrency: FiatCurrencyOption;
970
+ }) => Promise<void>;
971
+ onBack?: () => void;
972
+ }
973
+ declare const UniversalBuyCryptoPage: React.FC<UniversalBuyCryptoPageProps>;
974
+
975
+ export { AppBento2, type AppBento2Props, type BannerProps, type BentoFeature, type BoardMember, type CardData, CardInfoDialog, type CardInfoDialogProps, type CompanyDetails, type ConsultantProfile, ConsultantShowcase, type ConsultantShowcaseProps, ContentGridBlock, type ContentGridBlockProps, type CryptoOption, type DocumentSectionData, type EmailContact, Faq, type FaqItem, type FaqProps, FeatureScroll, type FeatureScrollProps, type FiatCurrencyOption, Footer, type FooterColumn, type FooterLink, type FooterProps, FundCardDialog, type FundCardDialogProps, GifFeatureCard, type GifFeatureCardProps, Header, type HeaderLink, type HeaderProps, type AppLogo$1 as HeroAppLogo, HeroSection, type HeroSectionProps, type HomeActionBtn, type LeaderboardItem, ManagedBoardBlock, type ManagedBoardBlockProps, ManagedContactBlock, type ManagedContactBlockProps, ManagedDocument, type ManagedDocumentProps, ManagedNewsletterSplitBlock, type ManagedNewsletterSplitBlockProps, ManagedNotFoundBlock, type ManagedNotFoundBlockProps, ManagedPricingBlock, type ManagedPricingBlockProps, ManagedProjectsBlock, type ManagedProjectsBlockProps, ManagedToaster, MedicalFeatureStatsBlock, MobileNav, type MobileNavItem, type MobileNavProps, type NavItem, type NetworkOption, type NotificationItem, NumberInput, type NumberInputProps, PageSpinner, type PageSpinnerProps, PinDialerBottomSheet, type PinDialerBottomSheetProps, PipleAuth, type PipleAuthProps, type PlatformFeatureItem, PlatformFeatures, type PlatformFeaturesProps, PortfolioHero, type PortfolioHeroProps, type AppLogo as PricingAppLogo, type PricingFeature, type PricingFeature2, type PricingPlan, type PricingTab, type ProjectItem, type RateCalculationPayload, type ReferralProfile, type RewardItem, type RewardProfile, type ScrollFeature, type SocialContact, type SocialLink, type StatItem, TextInput, type TextInputProps, ThreeDActionButton, type ThreeDActionButtonProps, ThreeDButton, type ThreeDButtonProps, type TierOption, UniversalBuyCryptoPage, type UniversalBuyCryptoPageProps, UniversalCardActionPage, type UniversalCardActionPageProps, UniversalCardPage, type UniversalCardPageProps, UniversalErrorView, type UniversalErrorViewProps, UniversalHomeView, type UniversalHomeViewProps, UniversalOrganizationPage, type UniversalOrganizationPageProps, UniversalProfilePage, type UniversalProfilePageProps, UniversalProfileSettings, type UniversalProfileSettingsProps, type UniversalReferralItem, UniversalReferralPage, type UniversalReferralPageProps, UniversalRewardPage, type UniversalRewardPageProps, UniversalSecurityPage, type UniversalSecurityPageProps, UniversalSidebar, type UniversalSidebarProps, type UniversalTransaction, UniversalTransactionPage, type UniversalTransactionPageProps, UniversalVerificationPage, type UniversalVerificationPageProps, type UniversalWallet, UniversalWalletPage, type UniversalWalletPageProps, type VerificationStatus, WaitlistDialog, type WaitlistDialogProps };
package/dist/index.js CHANGED
@@ -61,6 +61,7 @@ __export(index_exports, {
61
61
  TextInput: () => TextInput,
62
62
  ThreeDActionButton: () => ThreeDActionButton,
63
63
  ThreeDButton: () => ThreeDButton,
64
+ UniversalBuyCryptoPage: () => UniversalBuyCryptoPage,
64
65
  UniversalCardActionPage: () => UniversalCardActionPage,
65
66
  UniversalCardPage: () => UniversalCardPage,
66
67
  UniversalErrorView: () => UniversalErrorView,
@@ -4009,14 +4010,14 @@ var UniversalReferralPage = ({
4009
4010
  const finalSrc = src || fallbackUrl;
4010
4011
  return /* @__PURE__ */ import_react69.default.createElement("div", { className: `relative shrink-0 rounded-full bg-neutral-100 flex items-center justify-center overflow-hidden border-2 border-white ${sizeClass}` }, !isLoaded && /* @__PURE__ */ import_react69.default.createElement(import_react70.HugeiconsIcon, { icon: import_core_free_icons23.Loading03Icon, size: 16, className: "animate-spin text-neutral-400 absolute" }), /* @__PURE__ */ import_react69.default.createElement("img", { src: finalSrc, alt, onLoad: () => setIsLoaded(true), className: `w-full h-full object-cover transition-opacity duration-300 ${isLoaded ? "opacity-100" : "opacity-0"}` }));
4011
4012
  };
4012
- return /* @__PURE__ */ import_react69.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ import_react69.default.createElement(ManagedToaster, null), /* @__PURE__ */ import_react69.default.createElement("div", { className: "mb-6 flex w-full items-center px-1" }, /* @__PURE__ */ import_react69.default.createElement("button", { onClick: onBackHandler, className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px] outline-none" }, /* @__PURE__ */ import_react69.default.createElement(import_react70.HugeiconsIcon, { icon: import_core_free_icons23.ArrowLeft01Icon, size: 16 }), " Back")), /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-4 mb-6 px-1" }, /* @__PURE__ */ import_react69.default.createElement("div", null, /* @__PURE__ */ import_react69.default.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, "Your Referrals"), /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-xs text-neutral-500" }, "Invite friends and earn rewards when they verify and activate cards.")), /* @__PURE__ */ import_react69.default.createElement("div", { className: "bg-[#ceff8a] rounded-3xl p-4 relative overflow-hidden flex flex-col min-h-25 w-full mt-2" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "relative z-10 flex flex-col items-start" }, /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-[14px] text-black leading-tight mb-1" }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-black/60" }, "AFT Balance")), isLoading ? /* @__PURE__ */ import_react69.default.createElement("div", { className: "h-8 w-32 bg-black/10 animate-pulse rounded mt-2" }) : /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-lg text-black tracking-tight mt-1" }, referralCoins)), /* @__PURE__ */ import_react69.default.createElement(
4013
+ return /* @__PURE__ */ import_react69.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ import_react69.default.createElement(ManagedToaster, null), /* @__PURE__ */ import_react69.default.createElement("div", { className: "mb-6 flex w-full items-center px-1" }, /* @__PURE__ */ import_react69.default.createElement("button", { onClick: onBackHandler, className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px] outline-none" }, /* @__PURE__ */ import_react69.default.createElement(import_react70.HugeiconsIcon, { icon: import_core_free_icons23.ArrowLeft01Icon, size: 16 }), " Back")), /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-4 mb-6 px-1" }, /* @__PURE__ */ import_react69.default.createElement("div", null, /* @__PURE__ */ import_react69.default.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, "Your Referrals"), /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-xs text-neutral-500" }, "Invite friends and earn rewards when they verify and activate cards.")), /* @__PURE__ */ import_react69.default.createElement("div", { className: "bg-[#ceff8a] rounded-3xl p-4 relative overflow-hidden flex flex-col min-h-25 w-full mt-2" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "relative z-10 flex flex-col items-start" }, /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-[11px] text-black leading-tight mb-1" }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-black/60" }, "AFT Balance")), isLoading ? /* @__PURE__ */ import_react69.default.createElement("div", { className: "h-8 w-32 bg-black/10 animate-pulse rounded mt-2" }) : /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[16px] text-black tracking-tight mt-1" }, referralCoins)), /* @__PURE__ */ import_react69.default.createElement(
4013
4014
  "img",
4014
4015
  {
4015
4016
  src: "https://retinalabs.company/assets/images/gift_box.avif",
4016
4017
  alt: "Rewards",
4017
- className: "absolute bottom-1 right-2 translate-x-1/4 translate-y-[16%] w-36 sm:w-44 h-auto object-contain z-0 pointer-events-none drop-shadow-md"
4018
+ className: "absolute bottom-0 right-2 translate-x-1/4 translate-y-[16%] w-28 h-auto object-contain z-0 pointer-events-none drop-shadow-md"
4018
4019
  }
4019
- ))), /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-6 p-4 rounded-3xl bg-white w-full" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-3" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "border border-neutral-200 rounded-xl p-4 flex items-center justify-between" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400 " }, "Invitation Code"), isLoading && !referralCode ? /* @__PURE__ */ import_react69.default.createElement("div", { className: "h-6 w-24 bg-neutral-50 animate-pulse rounded mt-1" }) : /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-lg text-black tracking-widest" }, referralCode)), /* @__PURE__ */ import_react69.default.createElement(
4020
+ ))), /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-6 p-4 rounded-3xl bg-white w-full" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-3" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "border border-neutral-200 rounded-xl p-4 flex items-center justify-between" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400 " }, "Invitation Code"), isLoading && !referralCode ? /* @__PURE__ */ import_react69.default.createElement("div", { className: "h-6 w-24 bg-neutral-50 animate-pulse rounded mt-1" }) : /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-sm text-black tracking-widest" }, referralCode)), /* @__PURE__ */ import_react69.default.createElement(
4020
4021
  "button",
4021
4022
  {
4022
4023
  onClick: handleCopyCode,
@@ -4309,6 +4310,315 @@ var PinDialerBottomSheet = ({
4309
4310
  "Confirm Action"
4310
4311
  ))))));
4311
4312
  };
4313
+
4314
+ // src/components/UniversalBuyCryptoPage.tsx
4315
+ var import_react75 = __toESM(require("react"));
4316
+ var import_react_hot_toast12 = __toESM(require("react-hot-toast"));
4317
+ var import_react76 = require("@hugeicons/react");
4318
+ var import_core_free_icons26 = require("@hugeicons/core-free-icons");
4319
+ var CircularLogo = ({ src, alt, fallbackText }) => {
4320
+ const [isLoaded, setIsLoaded] = (0, import_react75.useState)(false);
4321
+ const [hasError, setHasError] = (0, import_react75.useState)(false);
4322
+ return /* @__PURE__ */ import_react75.default.createElement("div", { className: "relative w-6 h-6 rounded-full overflow-hidden bg-neutral-100 flex items-center justify-center shrink-0 border border-neutral-200" }, !hasError && src ? /* @__PURE__ */ import_react75.default.createElement(import_react75.default.Fragment, null, !isLoaded && /* @__PURE__ */ import_react75.default.createElement("div", { className: "absolute inset-0 bg-neutral-200 animate-pulse" }), /* @__PURE__ */ import_react75.default.createElement(
4323
+ "img",
4324
+ {
4325
+ src,
4326
+ alt,
4327
+ onLoad: () => setIsLoaded(true),
4328
+ onError: () => setHasError(true),
4329
+ className: `w-full h-full object-cover transition-opacity duration-300 ${isLoaded ? "opacity-100" : "opacity-0"}`
4330
+ }
4331
+ )) : /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-[10px] text-black uppercase" }, fallbackText.substring(0, 2)));
4332
+ };
4333
+ var DEFAULT_NETWORK_REGEX = {
4334
+ EVM: /^0x[a-fA-F0-9]{40}$/,
4335
+ // Ethereum, Polygon, BSC, Arbitrum, Base
4336
+ SOLANA: /^[1-9A-HJ-NP-Za-km-z]{32,44}$/,
4337
+ TRON: /^T[a-zA-Z0-9]{33}$/,
4338
+ BITCOIN: /^(1|3|bc1)[a-zA-Z0-9]{25,62}$/
4339
+ };
4340
+ var validateWalletAddress = (address, network) => {
4341
+ if (!address || !address.trim()) return false;
4342
+ const cleanAddr = address.trim();
4343
+ if (network.addressRegex) {
4344
+ try {
4345
+ return new RegExp(network.addressRegex).test(cleanAddr);
4346
+ } catch {
4347
+ }
4348
+ }
4349
+ const netId = network.id.toUpperCase();
4350
+ if (netId.includes("SOL")) return DEFAULT_NETWORK_REGEX.SOLANA.test(cleanAddr);
4351
+ if (netId.includes("TRC") || netId.includes("TRON")) return DEFAULT_NETWORK_REGEX.TRON.test(cleanAddr);
4352
+ if (netId.includes("BTC") || netId.includes("BITCOIN")) return DEFAULT_NETWORK_REGEX.BITCOIN.test(cleanAddr);
4353
+ return DEFAULT_NETWORK_REGEX.EVM.test(cleanAddr);
4354
+ };
4355
+ var UniversalBuyCryptoPage = ({
4356
+ fiatCurrency,
4357
+ cryptoOptions = [],
4358
+ defaultCryptoCode,
4359
+ hideBackButton = false,
4360
+ hideRecipientSection = false,
4361
+ readOnlyRecipientSection = false,
4362
+ defaultRecipientAddress = "",
4363
+ defaultNetworkId,
4364
+ onCalculateRate,
4365
+ onSubmitCheckout,
4366
+ onBack
4367
+ }) => {
4368
+ const onBackHandler = onBack ?? (() => {
4369
+ if (typeof window !== "undefined") window.history.back();
4370
+ });
4371
+ const [selectedCrypto, setSelectedCrypto] = (0, import_react75.useState)(() => {
4372
+ if (defaultCryptoCode) {
4373
+ const found = cryptoOptions.find((c) => c.code === defaultCryptoCode);
4374
+ if (found) return found;
4375
+ }
4376
+ return cryptoOptions[0] || {
4377
+ code: "USDC",
4378
+ name: "USD Coin",
4379
+ logoUrl: "https://cryptologos.cc/logos/usd-coin-usdc-logo.png",
4380
+ networks: [{ id: "POLYGON", name: "Polygon (MATIC)", symbol: "POLYGON" }]
4381
+ };
4382
+ });
4383
+ const [selectedNetwork, setSelectedNetwork] = (0, import_react75.useState)(() => {
4384
+ if (defaultNetworkId && selectedCrypto?.networks) {
4385
+ const foundNet = selectedCrypto.networks.find((n) => n.id === defaultNetworkId);
4386
+ if (foundNet) return foundNet;
4387
+ }
4388
+ return selectedCrypto?.networks?.[0] || { id: "POLYGON", name: "Polygon (MATIC)", symbol: "POLYGON" };
4389
+ });
4390
+ const [fiatAmount, setFiatAmount] = (0, import_react75.useState)("");
4391
+ const [cryptoAmount, setCryptoAmount] = (0, import_react75.useState)("");
4392
+ const [activeSource, setActiveSource] = (0, import_react75.useState)("FIAT");
4393
+ const [isCalculating, setIsCalculating] = (0, import_react75.useState)(false);
4394
+ const [rateDisplay, setRateDisplay] = (0, import_react75.useState)(null);
4395
+ const [recipientAddress, setRecipientAddress] = (0, import_react75.useState)(defaultRecipientAddress);
4396
+ const [isAddressValid, setIsAddressValid] = (0, import_react75.useState)(null);
4397
+ const [isCryptoDialogOpen, setIsCryptoDialogOpen] = (0, import_react75.useState)(false);
4398
+ const [isNetworkDialogOpen, setIsNetworkDialogOpen] = (0, import_react75.useState)(false);
4399
+ const [isSubmitting, setIsSubmitting] = (0, import_react75.useState)(false);
4400
+ const debounceTimerRef = (0, import_react75.useRef)(null);
4401
+ (0, import_react75.useEffect)(() => {
4402
+ if (selectedCrypto?.networks?.length > 0) {
4403
+ const exists = selectedCrypto.networks.find((n) => n.id === selectedNetwork.id);
4404
+ if (!exists) {
4405
+ setSelectedNetwork(selectedCrypto.networks[0]);
4406
+ }
4407
+ }
4408
+ }, [selectedCrypto]);
4409
+ (0, import_react75.useEffect)(() => {
4410
+ if (!recipientAddress.trim()) {
4411
+ setIsAddressValid(null);
4412
+ return;
4413
+ }
4414
+ const valid = validateWalletAddress(recipientAddress, selectedNetwork);
4415
+ setIsAddressValid(valid);
4416
+ }, [recipientAddress, selectedNetwork]);
4417
+ const triggerRateCalculation = (0, import_react75.useCallback)((source, valFiat, valCrypto, currentCrypto) => {
4418
+ if (debounceTimerRef.current) {
4419
+ clearTimeout(debounceTimerRef.current);
4420
+ }
4421
+ const targetVal = source === "FIAT" ? valFiat : valCrypto;
4422
+ const numericVal = parseFloat(targetVal) || 0;
4423
+ if (numericVal <= 0) {
4424
+ setIsCalculating(false);
4425
+ if (source === "FIAT") setCryptoAmount("");
4426
+ else setFiatAmount("");
4427
+ return;
4428
+ }
4429
+ setIsCalculating(true);
4430
+ debounceTimerRef.current = setTimeout(async () => {
4431
+ if (onCalculateRate) {
4432
+ try {
4433
+ const result = await onCalculateRate({
4434
+ fiatAmount: valFiat,
4435
+ cryptoAmount: valCrypto,
4436
+ activeSource: source,
4437
+ crypto: currentCrypto,
4438
+ fiat: fiatCurrency
4439
+ });
4440
+ if (source === "FIAT") {
4441
+ setCryptoAmount(result.cryptoAmount || "");
4442
+ } else {
4443
+ setFiatAmount(result.fiatAmount || "");
4444
+ }
4445
+ if (result.ratePerToken) {
4446
+ setRateDisplay(result.ratePerToken);
4447
+ }
4448
+ } catch {
4449
+ import_react_hot_toast12.default.error("Failed to calculate rate.");
4450
+ } finally {
4451
+ setIsCalculating(false);
4452
+ }
4453
+ } else {
4454
+ if (source === "FIAT") {
4455
+ setCryptoAmount((numericVal / 1600).toFixed(2));
4456
+ } else {
4457
+ setFiatAmount((numericVal * 1600).toFixed(2));
4458
+ }
4459
+ setIsCalculating(false);
4460
+ }
4461
+ }, 2e3);
4462
+ }, [fiatCurrency, onCalculateRate]);
4463
+ const handleFiatInputChange = (e) => {
4464
+ const cleanVal = e.target.value.replace(/[^0-9.]/g, "");
4465
+ if ((cleanVal.match(/\./g) || []).length > 1) return;
4466
+ setFiatAmount(cleanVal);
4467
+ setActiveSource("FIAT");
4468
+ triggerRateCalculation("FIAT", cleanVal, cryptoAmount, selectedCrypto);
4469
+ };
4470
+ const handleCryptoInputChange = (e) => {
4471
+ const cleanVal = e.target.value.replace(/[^0-9.]/g, "");
4472
+ if ((cleanVal.match(/\./g) || []).length > 1) return;
4473
+ setCryptoAmount(cleanVal);
4474
+ setActiveSource("CRYPTO");
4475
+ triggerRateCalculation("CRYPTO", fiatAmount, cleanVal, selectedCrypto);
4476
+ };
4477
+ const handleCryptoSelect = (crypto) => {
4478
+ setSelectedCrypto(crypto);
4479
+ setIsCryptoDialogOpen(false);
4480
+ triggerRateCalculation(activeSource, fiatAmount, cryptoAmount, crypto);
4481
+ };
4482
+ const handleCheckout = async () => {
4483
+ const numFiat = parseFloat(fiatAmount) || 0;
4484
+ const numCrypto = parseFloat(cryptoAmount) || 0;
4485
+ if (numFiat <= 0 || numCrypto <= 0) {
4486
+ return import_react_hot_toast12.default.error("Please enter a valid purchase amount.");
4487
+ }
4488
+ if (!recipientAddress.trim() || !isAddressValid) {
4489
+ return import_react_hot_toast12.default.error("Please enter a valid recipient wallet address.");
4490
+ }
4491
+ if (onSubmitCheckout) {
4492
+ setIsSubmitting(true);
4493
+ try {
4494
+ await onSubmitCheckout({
4495
+ fiatAmount,
4496
+ cryptoAmount,
4497
+ selectedCrypto,
4498
+ selectedNetwork,
4499
+ recipientAddress: recipientAddress.trim(),
4500
+ fiatCurrency
4501
+ });
4502
+ } catch (err) {
4503
+ import_react_hot_toast12.default.error(err?.message || "Failed to process purchase.");
4504
+ } finally {
4505
+ setIsSubmitting(false);
4506
+ }
4507
+ }
4508
+ };
4509
+ const isButtonDisabled = isSubmitting || isCalculating || !fiatAmount || !cryptoAmount || !isAddressValid;
4510
+ return /* @__PURE__ */ import_react75.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ import_react75.default.createElement(ManagedToaster, null), !hideBackButton && /* @__PURE__ */ import_react75.default.createElement("div", { className: "mb-6 flex w-full items-center px-1" }, /* @__PURE__ */ import_react75.default.createElement("button", { onClick: onBackHandler, className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px] outline-none" }, /* @__PURE__ */ import_react75.default.createElement(import_react76.HugeiconsIcon, { icon: import_core_free_icons26.ArrowLeft01Icon, size: 16 }), " Back")), /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col gap-1 mb-6 px-1" }, /* @__PURE__ */ import_react75.default.createElement("h1", { className: "text-black text-xl tracking-tight" }, "Buy Crypto"), /* @__PURE__ */ import_react75.default.createElement("p", { className: "text-xs text-neutral-500" }, "Purchase digital assets instantly in your local currency with direct wallet delivery.")), /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col gap-6 p-6 sm:p-8 rounded-3xl bg-white w-full" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "relative flex flex-col gap-3" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "border border-neutral-200 rounded-2xl p-4 flex items-center justify-between transition-all focus-within:border-black" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col gap-1 flex-1 pr-3 min-w-0" }, /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400" }, "You Pay (", fiatCurrency.code, ")"), isCalculating && activeSource === "CRYPTO" ? /* @__PURE__ */ import_react75.default.createElement("div", { className: "h-7 w-32 bg-neutral-100 animate-pulse rounded-md mt-1" }) : /* @__PURE__ */ import_react75.default.createElement(
4511
+ "input",
4512
+ {
4513
+ type: "text",
4514
+ inputMode: "decimal",
4515
+ value: fiatAmount,
4516
+ onChange: handleFiatInputChange,
4517
+ placeholder: "0.00",
4518
+ disabled: isSubmitting,
4519
+ className: "text-xl sm:text-2xl text-black bg-transparent outline-none w-full placeholder-neutral-300 "
4520
+ }
4521
+ )), /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex items-center gap-2 bg-neutral-50 rounded-full px-3 py-1.5 shrink-0 select-none" }, /* @__PURE__ */ import_react75.default.createElement(CircularLogo, { src: fiatCurrency.logoUrl, alt: fiatCurrency.code, fallbackText: fiatCurrency.code }), /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-xs text-black" }, fiatCurrency.code))), /* @__PURE__ */ import_react75.default.createElement("div", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "w-10 h-10 rounded-full bg-white border border-neutral-200 flex items-center justify-center " }, /* @__PURE__ */ import_react75.default.createElement("svg", { className: "w-4 h-4 text-black", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ import_react75.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" })))), /* @__PURE__ */ import_react75.default.createElement("div", { className: "border border-neutral-200 rounded-2xl p-4 flex items-center justify-between transition-all focus-within:border-black" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col gap-1 flex-1 pr-3 min-w-0" }, /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400" }, "You Receive"), isCalculating && activeSource === "FIAT" ? /* @__PURE__ */ import_react75.default.createElement("div", { className: "h-7 w-32 bg-neutral-100 animate-pulse rounded-md mt-1" }) : /* @__PURE__ */ import_react75.default.createElement(
4522
+ "input",
4523
+ {
4524
+ type: "text",
4525
+ inputMode: "decimal",
4526
+ value: cryptoAmount,
4527
+ onChange: handleCryptoInputChange,
4528
+ placeholder: "0.00",
4529
+ disabled: isSubmitting,
4530
+ className: "text-xl sm:text-2xl text-black bg-transparent outline-none w-full placeholder-neutral-300 "
4531
+ }
4532
+ )), /* @__PURE__ */ import_react75.default.createElement(
4533
+ "button",
4534
+ {
4535
+ type: "button",
4536
+ onClick: () => setIsCryptoDialogOpen(true),
4537
+ disabled: isSubmitting,
4538
+ className: "flex items-center gap-2 bg-neutral-100 hover:bg-neutral-200 transition-colors rounded-full px-3 py-1.5 shrink-0 outline-none"
4539
+ },
4540
+ /* @__PURE__ */ import_react75.default.createElement(CircularLogo, { src: selectedCrypto.logoUrl, alt: selectedCrypto.code, fallbackText: selectedCrypto.code }),
4541
+ /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-xs text-black" }, selectedCrypto.code),
4542
+ /* @__PURE__ */ import_react75.default.createElement("svg", { className: "w-3.5 h-3.5 text-neutral-500 ml-0.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ import_react75.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))
4543
+ ))), rateDisplay && /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex items-center justify-between text-[11px] text-neutral-500 px-1 -mt-2" }, /* @__PURE__ */ import_react75.default.createElement("span", null, "Exchange Rate"), /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-black " }, rateDisplay)), !hideRecipientSection && /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col gap-4 pt-2" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col gap-1.5" }, /* @__PURE__ */ import_react75.default.createElement("label", { className: "text-[11px] tracking-widest text-neutral-400" }, "Network / Blockchain"), /* @__PURE__ */ import_react75.default.createElement(
4544
+ "button",
4545
+ {
4546
+ type: "button",
4547
+ onClick: () => !readOnlyRecipientSection && setIsNetworkDialogOpen(true),
4548
+ disabled: isSubmitting || selectedCrypto?.networks?.length <= 1 || readOnlyRecipientSection,
4549
+ className: `border rounded-xl p-3.5 flex items-center justify-between transition-colors text-left outline-none bg-white ${readOnlyRecipientSection ? "border-neutral-100 opacity-80 cursor-not-allowed" : "border-neutral-200 hover:border-black"}`
4550
+ },
4551
+ /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react75.default.createElement(CircularLogo, { src: selectedNetwork.logoUrl || selectedCrypto.logoUrl, alt: selectedNetwork.name, fallbackText: selectedNetwork.symbol }), /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-xs text-black " }, selectedNetwork.name)),
4552
+ !readOnlyRecipientSection && selectedCrypto?.networks?.length > 1 && /* @__PURE__ */ import_react75.default.createElement("svg", { className: "w-4 h-4 text-neutral-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ import_react75.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))
4553
+ )), /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col gap-1.5" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react75.default.createElement("label", { className: "text-[11px] tracking-widest text-neutral-400" }, "Recipient Wallet Address"), isAddressValid !== null && /* @__PURE__ */ import_react75.default.createElement("span", { className: `text-[10px] flex items-center gap-1 ${isAddressValid ? "text-green-600" : "text-red-500"}` }, isAddressValid ? /* @__PURE__ */ import_react75.default.createElement(import_react75.default.Fragment, null, /* @__PURE__ */ import_react75.default.createElement(import_react76.HugeiconsIcon, { icon: import_core_free_icons26.CheckmarkCircle01Icon, size: 12 }), " Valid Address") : "Invalid Address Format")), /* @__PURE__ */ import_react75.default.createElement("div", { className: `border rounded-xl p-3.5 flex items-center justify-between transition-all bg-white ${readOnlyRecipientSection ? "border-neutral-100 opacity-80" : isAddressValid === true ? "border-green-500" : isAddressValid === false ? "border-red-400" : "border-neutral-200 focus-within:border-black"}` }, /* @__PURE__ */ import_react75.default.createElement(
4554
+ "input",
4555
+ {
4556
+ type: "text",
4557
+ value: recipientAddress,
4558
+ onChange: (e) => setRecipientAddress(e.target.value),
4559
+ placeholder: `Enter your ${selectedNetwork.symbol} address`,
4560
+ disabled: isSubmitting || readOnlyRecipientSection,
4561
+ spellCheck: "false",
4562
+ autoComplete: "off",
4563
+ className: `text-xs text-black bg-transparent outline-none w-full placeholder-neutral-300 ${readOnlyRecipientSection ? "cursor-not-allowed" : ""}`
4564
+ }
4565
+ )))), /* @__PURE__ */ import_react75.default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ import_react75.default.createElement(
4566
+ ThreeDActionButton,
4567
+ {
4568
+ type: "button",
4569
+ onClick: handleCheckout,
4570
+ disabled: isButtonDisabled,
4571
+ isLoading: isSubmitting,
4572
+ className: "w-full"
4573
+ },
4574
+ "Buy ",
4575
+ selectedCrypto.code,
4576
+ " Now"
4577
+ ))), isCryptoDialogOpen && /* @__PURE__ */ import_react75.default.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "absolute inset-0", onClick: () => setIsCryptoDialogOpen(false) }), /* @__PURE__ */ import_react75.default.createElement("div", { className: "w-full max-w-sm bg-white rounded-2xl shadow-2xl overflow-hidden relative z-10 animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react75.default.createElement(
4578
+ "button",
4579
+ {
4580
+ onClick: () => setIsCryptoDialogOpen(false),
4581
+ className: "absolute top-4 right-4 p-2 text-neutral-700 hover:text-neutral-400 transition-colors outline-none"
4582
+ },
4583
+ /* @__PURE__ */ import_react75.default.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__ */ import_react75.default.createElement("path", { d: "M18 6 6 18" }), /* @__PURE__ */ import_react75.default.createElement("path", { d: "m6 6 12 12" }))
4584
+ ), /* @__PURE__ */ import_react75.default.createElement("div", { className: "p-6 sm:p-8" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "mb-6 mt-2" }, /* @__PURE__ */ import_react75.default.createElement("h2", { className: "text-xl text-black tracking-tight mb-2" }, "Select Cryptocurrency"), /* @__PURE__ */ import_react75.default.createElement("p", { className: "text-[13px] text-neutral-500 leading-relaxed" }, "Choose the digital asset you want to purchase.")), /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col gap-2 max-h-72 overflow-y-auto custom-scrollbar pr-1" }, cryptoOptions.map((c) => {
4585
+ const isSelected = c.code === selectedCrypto.code;
4586
+ return /* @__PURE__ */ import_react75.default.createElement(
4587
+ "button",
4588
+ {
4589
+ key: c.code,
4590
+ onClick: () => handleCryptoSelect(c),
4591
+ className: `flex items-center gap-4 p-3 rounded-xl hover:bg-neutral-50 transition-colors text-left outline-none border ${isSelected ? "border-black bg-neutral-50/50" : "border-transparent"}`
4592
+ },
4593
+ /* @__PURE__ */ import_react75.default.createElement(CircularLogo, { src: c.logoUrl, alt: c.name, fallbackText: c.code }),
4594
+ /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-xs text-black truncate" }, c.name), /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-[11px] text-neutral-400" }, c.code)),
4595
+ isSelected && /* @__PURE__ */ import_react75.default.createElement(import_react76.HugeiconsIcon, { icon: import_core_free_icons26.Tick02Icon, size: 16, className: "text-black" })
4596
+ );
4597
+ }))))), isNetworkDialogOpen && /* @__PURE__ */ import_react75.default.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "absolute inset-0", onClick: () => setIsNetworkDialogOpen(false) }), /* @__PURE__ */ import_react75.default.createElement("div", { className: "w-full max-w-sm bg-white rounded-2xl shadow-2xl overflow-hidden relative z-10 animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react75.default.createElement(
4598
+ "button",
4599
+ {
4600
+ onClick: () => setIsNetworkDialogOpen(false),
4601
+ className: "absolute top-4 right-4 p-2 text-neutral-700 hover:text-neutral-400 transition-colors outline-none"
4602
+ },
4603
+ /* @__PURE__ */ import_react75.default.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__ */ import_react75.default.createElement("path", { d: "M18 6 6 18" }), /* @__PURE__ */ import_react75.default.createElement("path", { d: "m6 6 12 12" }))
4604
+ ), /* @__PURE__ */ import_react75.default.createElement("div", { className: "p-6 sm:p-8" }, /* @__PURE__ */ import_react75.default.createElement("div", { className: "mb-6 mt-2" }, /* @__PURE__ */ import_react75.default.createElement("h2", { className: "text-xl text-black tracking-tight mb-2" }, "Select Network"), /* @__PURE__ */ import_react75.default.createElement("p", { className: "text-[13px] text-neutral-500 leading-relaxed" }, "Ensure your receiving wallet supports this network.")), /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col gap-2 max-h-72 overflow-y-auto custom-scrollbar pr-1" }, selectedCrypto?.networks?.map((net) => {
4605
+ const isSelected = net.id === selectedNetwork.id;
4606
+ return /* @__PURE__ */ import_react75.default.createElement(
4607
+ "button",
4608
+ {
4609
+ key: net.id,
4610
+ onClick: () => {
4611
+ setSelectedNetwork(net);
4612
+ setIsNetworkDialogOpen(false);
4613
+ },
4614
+ className: `flex items-center gap-4 p-3 rounded-xl hover:bg-neutral-50 transition-colors text-left outline-none border ${isSelected ? "border-black bg-neutral-50/50" : "border-transparent"}`
4615
+ },
4616
+ /* @__PURE__ */ import_react75.default.createElement(CircularLogo, { src: net.logoUrl || selectedCrypto.logoUrl, alt: net.name, fallbackText: net.symbol }),
4617
+ /* @__PURE__ */ import_react75.default.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-xs text-black truncate" }, net.name), /* @__PURE__ */ import_react75.default.createElement("span", { className: "text-[11px] text-neutral-400" }, net.symbol)),
4618
+ isSelected && /* @__PURE__ */ import_react75.default.createElement(import_react76.HugeiconsIcon, { icon: import_core_free_icons26.Tick02Icon, size: 16, className: "text-black" })
4619
+ );
4620
+ }))))));
4621
+ };
4312
4622
  // Annotate the CommonJS export names for ESM import in node:
4313
4623
  0 && (module.exports = {
4314
4624
  AppBento2,
@@ -4341,6 +4651,7 @@ var PinDialerBottomSheet = ({
4341
4651
  TextInput,
4342
4652
  ThreeDActionButton,
4343
4653
  ThreeDButton,
4654
+ UniversalBuyCryptoPage,
4344
4655
  UniversalCardActionPage,
4345
4656
  UniversalCardPage,
4346
4657
  UniversalErrorView,
package/dist/index.mjs CHANGED
@@ -4019,14 +4019,14 @@ var UniversalReferralPage = ({
4019
4019
  const finalSrc = src || fallbackUrl;
4020
4020
  return /* @__PURE__ */ React42.createElement("div", { className: `relative shrink-0 rounded-full bg-neutral-100 flex items-center justify-center overflow-hidden border-2 border-white ${sizeClass}` }, !isLoaded && /* @__PURE__ */ React42.createElement(HugeiconsIcon28, { icon: Loading03Icon17, size: 16, className: "animate-spin text-neutral-400 absolute" }), /* @__PURE__ */ React42.createElement("img", { src: finalSrc, alt, onLoad: () => setIsLoaded(true), className: `w-full h-full object-cover transition-opacity duration-300 ${isLoaded ? "opacity-100" : "opacity-0"}` }));
4021
4021
  };
4022
- return /* @__PURE__ */ React42.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ React42.createElement(ManagedToaster, null), /* @__PURE__ */ React42.createElement("div", { className: "mb-6 flex w-full items-center px-1" }, /* @__PURE__ */ React42.createElement("button", { onClick: onBackHandler, className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px] outline-none" }, /* @__PURE__ */ React42.createElement(HugeiconsIcon28, { icon: ArrowLeft01Icon10, size: 16 }), " Back")), /* @__PURE__ */ React42.createElement("div", { className: "flex flex-col gap-4 mb-6 px-1" }, /* @__PURE__ */ React42.createElement("div", null, /* @__PURE__ */ React42.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, "Your Referrals"), /* @__PURE__ */ React42.createElement("p", { className: "text-xs text-neutral-500" }, "Invite friends and earn rewards when they verify and activate cards.")), /* @__PURE__ */ React42.createElement("div", { className: "bg-[#ceff8a] rounded-3xl p-4 relative overflow-hidden flex flex-col min-h-25 w-full mt-2" }, /* @__PURE__ */ React42.createElement("div", { className: "relative z-10 flex flex-col items-start" }, /* @__PURE__ */ React42.createElement("p", { className: "text-[14px] text-black leading-tight mb-1" }, /* @__PURE__ */ React42.createElement("span", { className: "text-black/60" }, "AFT Balance")), isLoading ? /* @__PURE__ */ React42.createElement("div", { className: "h-8 w-32 bg-black/10 animate-pulse rounded mt-2" }) : /* @__PURE__ */ React42.createElement("span", { className: "text-lg text-black tracking-tight mt-1" }, referralCoins)), /* @__PURE__ */ React42.createElement(
4022
+ return /* @__PURE__ */ React42.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ React42.createElement(ManagedToaster, null), /* @__PURE__ */ React42.createElement("div", { className: "mb-6 flex w-full items-center px-1" }, /* @__PURE__ */ React42.createElement("button", { onClick: onBackHandler, className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px] outline-none" }, /* @__PURE__ */ React42.createElement(HugeiconsIcon28, { icon: ArrowLeft01Icon10, size: 16 }), " Back")), /* @__PURE__ */ React42.createElement("div", { className: "flex flex-col gap-4 mb-6 px-1" }, /* @__PURE__ */ React42.createElement("div", null, /* @__PURE__ */ React42.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, "Your Referrals"), /* @__PURE__ */ React42.createElement("p", { className: "text-xs text-neutral-500" }, "Invite friends and earn rewards when they verify and activate cards.")), /* @__PURE__ */ React42.createElement("div", { className: "bg-[#ceff8a] rounded-3xl p-4 relative overflow-hidden flex flex-col min-h-25 w-full mt-2" }, /* @__PURE__ */ React42.createElement("div", { className: "relative z-10 flex flex-col items-start" }, /* @__PURE__ */ React42.createElement("p", { className: "text-[11px] text-black leading-tight mb-1" }, /* @__PURE__ */ React42.createElement("span", { className: "text-black/60" }, "AFT Balance")), isLoading ? /* @__PURE__ */ React42.createElement("div", { className: "h-8 w-32 bg-black/10 animate-pulse rounded mt-2" }) : /* @__PURE__ */ React42.createElement("span", { className: "text-[16px] text-black tracking-tight mt-1" }, referralCoins)), /* @__PURE__ */ React42.createElement(
4023
4023
  "img",
4024
4024
  {
4025
4025
  src: "https://retinalabs.company/assets/images/gift_box.avif",
4026
4026
  alt: "Rewards",
4027
- className: "absolute bottom-1 right-2 translate-x-1/4 translate-y-[16%] w-36 sm:w-44 h-auto object-contain z-0 pointer-events-none drop-shadow-md"
4027
+ className: "absolute bottom-0 right-2 translate-x-1/4 translate-y-[16%] w-28 h-auto object-contain z-0 pointer-events-none drop-shadow-md"
4028
4028
  }
4029
- ))), /* @__PURE__ */ React42.createElement("div", { className: "flex flex-col gap-6 p-4 rounded-3xl bg-white w-full" }, /* @__PURE__ */ React42.createElement("div", { className: "flex flex-col gap-3" }, /* @__PURE__ */ React42.createElement("div", { className: "border border-neutral-200 rounded-xl p-4 flex items-center justify-between" }, /* @__PURE__ */ React42.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React42.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400 " }, "Invitation Code"), isLoading && !referralCode ? /* @__PURE__ */ React42.createElement("div", { className: "h-6 w-24 bg-neutral-50 animate-pulse rounded mt-1" }) : /* @__PURE__ */ React42.createElement("span", { className: "text-lg text-black tracking-widest" }, referralCode)), /* @__PURE__ */ React42.createElement(
4029
+ ))), /* @__PURE__ */ React42.createElement("div", { className: "flex flex-col gap-6 p-4 rounded-3xl bg-white w-full" }, /* @__PURE__ */ React42.createElement("div", { className: "flex flex-col gap-3" }, /* @__PURE__ */ React42.createElement("div", { className: "border border-neutral-200 rounded-xl p-4 flex items-center justify-between" }, /* @__PURE__ */ React42.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React42.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400 " }, "Invitation Code"), isLoading && !referralCode ? /* @__PURE__ */ React42.createElement("div", { className: "h-6 w-24 bg-neutral-50 animate-pulse rounded mt-1" }) : /* @__PURE__ */ React42.createElement("span", { className: "text-sm text-black tracking-widest" }, referralCode)), /* @__PURE__ */ React42.createElement(
4030
4030
  "button",
4031
4031
  {
4032
4032
  onClick: handleCopyCode,
@@ -4323,6 +4323,319 @@ var PinDialerBottomSheet = ({
4323
4323
  "Confirm Action"
4324
4324
  ))))));
4325
4325
  };
4326
+
4327
+ // src/components/UniversalBuyCryptoPage.tsx
4328
+ import React45, { useState as useState31, useEffect as useEffect17, useRef as useRef11, useCallback } from "react";
4329
+ import toast11 from "react-hot-toast";
4330
+ import { HugeiconsIcon as HugeiconsIcon31 } from "@hugeicons/react";
4331
+ import {
4332
+ ArrowLeft01Icon as ArrowLeft01Icon12,
4333
+ CheckmarkCircle01Icon as CheckmarkCircle01Icon2,
4334
+ Tick02Icon
4335
+ } from "@hugeicons/core-free-icons";
4336
+ var CircularLogo = ({ src, alt, fallbackText }) => {
4337
+ const [isLoaded, setIsLoaded] = useState31(false);
4338
+ const [hasError, setHasError] = useState31(false);
4339
+ return /* @__PURE__ */ React45.createElement("div", { className: "relative w-6 h-6 rounded-full overflow-hidden bg-neutral-100 flex items-center justify-center shrink-0 border border-neutral-200" }, !hasError && src ? /* @__PURE__ */ React45.createElement(React45.Fragment, null, !isLoaded && /* @__PURE__ */ React45.createElement("div", { className: "absolute inset-0 bg-neutral-200 animate-pulse" }), /* @__PURE__ */ React45.createElement(
4340
+ "img",
4341
+ {
4342
+ src,
4343
+ alt,
4344
+ onLoad: () => setIsLoaded(true),
4345
+ onError: () => setHasError(true),
4346
+ className: `w-full h-full object-cover transition-opacity duration-300 ${isLoaded ? "opacity-100" : "opacity-0"}`
4347
+ }
4348
+ )) : /* @__PURE__ */ React45.createElement("span", { className: "text-[10px] text-black uppercase" }, fallbackText.substring(0, 2)));
4349
+ };
4350
+ var DEFAULT_NETWORK_REGEX = {
4351
+ EVM: /^0x[a-fA-F0-9]{40}$/,
4352
+ // Ethereum, Polygon, BSC, Arbitrum, Base
4353
+ SOLANA: /^[1-9A-HJ-NP-Za-km-z]{32,44}$/,
4354
+ TRON: /^T[a-zA-Z0-9]{33}$/,
4355
+ BITCOIN: /^(1|3|bc1)[a-zA-Z0-9]{25,62}$/
4356
+ };
4357
+ var validateWalletAddress = (address, network) => {
4358
+ if (!address || !address.trim()) return false;
4359
+ const cleanAddr = address.trim();
4360
+ if (network.addressRegex) {
4361
+ try {
4362
+ return new RegExp(network.addressRegex).test(cleanAddr);
4363
+ } catch {
4364
+ }
4365
+ }
4366
+ const netId = network.id.toUpperCase();
4367
+ if (netId.includes("SOL")) return DEFAULT_NETWORK_REGEX.SOLANA.test(cleanAddr);
4368
+ if (netId.includes("TRC") || netId.includes("TRON")) return DEFAULT_NETWORK_REGEX.TRON.test(cleanAddr);
4369
+ if (netId.includes("BTC") || netId.includes("BITCOIN")) return DEFAULT_NETWORK_REGEX.BITCOIN.test(cleanAddr);
4370
+ return DEFAULT_NETWORK_REGEX.EVM.test(cleanAddr);
4371
+ };
4372
+ var UniversalBuyCryptoPage = ({
4373
+ fiatCurrency,
4374
+ cryptoOptions = [],
4375
+ defaultCryptoCode,
4376
+ hideBackButton = false,
4377
+ hideRecipientSection = false,
4378
+ readOnlyRecipientSection = false,
4379
+ defaultRecipientAddress = "",
4380
+ defaultNetworkId,
4381
+ onCalculateRate,
4382
+ onSubmitCheckout,
4383
+ onBack
4384
+ }) => {
4385
+ const onBackHandler = onBack ?? (() => {
4386
+ if (typeof window !== "undefined") window.history.back();
4387
+ });
4388
+ const [selectedCrypto, setSelectedCrypto] = useState31(() => {
4389
+ if (defaultCryptoCode) {
4390
+ const found = cryptoOptions.find((c) => c.code === defaultCryptoCode);
4391
+ if (found) return found;
4392
+ }
4393
+ return cryptoOptions[0] || {
4394
+ code: "USDC",
4395
+ name: "USD Coin",
4396
+ logoUrl: "https://cryptologos.cc/logos/usd-coin-usdc-logo.png",
4397
+ networks: [{ id: "POLYGON", name: "Polygon (MATIC)", symbol: "POLYGON" }]
4398
+ };
4399
+ });
4400
+ const [selectedNetwork, setSelectedNetwork] = useState31(() => {
4401
+ if (defaultNetworkId && selectedCrypto?.networks) {
4402
+ const foundNet = selectedCrypto.networks.find((n) => n.id === defaultNetworkId);
4403
+ if (foundNet) return foundNet;
4404
+ }
4405
+ return selectedCrypto?.networks?.[0] || { id: "POLYGON", name: "Polygon (MATIC)", symbol: "POLYGON" };
4406
+ });
4407
+ const [fiatAmount, setFiatAmount] = useState31("");
4408
+ const [cryptoAmount, setCryptoAmount] = useState31("");
4409
+ const [activeSource, setActiveSource] = useState31("FIAT");
4410
+ const [isCalculating, setIsCalculating] = useState31(false);
4411
+ const [rateDisplay, setRateDisplay] = useState31(null);
4412
+ const [recipientAddress, setRecipientAddress] = useState31(defaultRecipientAddress);
4413
+ const [isAddressValid, setIsAddressValid] = useState31(null);
4414
+ const [isCryptoDialogOpen, setIsCryptoDialogOpen] = useState31(false);
4415
+ const [isNetworkDialogOpen, setIsNetworkDialogOpen] = useState31(false);
4416
+ const [isSubmitting, setIsSubmitting] = useState31(false);
4417
+ const debounceTimerRef = useRef11(null);
4418
+ useEffect17(() => {
4419
+ if (selectedCrypto?.networks?.length > 0) {
4420
+ const exists = selectedCrypto.networks.find((n) => n.id === selectedNetwork.id);
4421
+ if (!exists) {
4422
+ setSelectedNetwork(selectedCrypto.networks[0]);
4423
+ }
4424
+ }
4425
+ }, [selectedCrypto]);
4426
+ useEffect17(() => {
4427
+ if (!recipientAddress.trim()) {
4428
+ setIsAddressValid(null);
4429
+ return;
4430
+ }
4431
+ const valid = validateWalletAddress(recipientAddress, selectedNetwork);
4432
+ setIsAddressValid(valid);
4433
+ }, [recipientAddress, selectedNetwork]);
4434
+ const triggerRateCalculation = useCallback((source, valFiat, valCrypto, currentCrypto) => {
4435
+ if (debounceTimerRef.current) {
4436
+ clearTimeout(debounceTimerRef.current);
4437
+ }
4438
+ const targetVal = source === "FIAT" ? valFiat : valCrypto;
4439
+ const numericVal = parseFloat(targetVal) || 0;
4440
+ if (numericVal <= 0) {
4441
+ setIsCalculating(false);
4442
+ if (source === "FIAT") setCryptoAmount("");
4443
+ else setFiatAmount("");
4444
+ return;
4445
+ }
4446
+ setIsCalculating(true);
4447
+ debounceTimerRef.current = setTimeout(async () => {
4448
+ if (onCalculateRate) {
4449
+ try {
4450
+ const result = await onCalculateRate({
4451
+ fiatAmount: valFiat,
4452
+ cryptoAmount: valCrypto,
4453
+ activeSource: source,
4454
+ crypto: currentCrypto,
4455
+ fiat: fiatCurrency
4456
+ });
4457
+ if (source === "FIAT") {
4458
+ setCryptoAmount(result.cryptoAmount || "");
4459
+ } else {
4460
+ setFiatAmount(result.fiatAmount || "");
4461
+ }
4462
+ if (result.ratePerToken) {
4463
+ setRateDisplay(result.ratePerToken);
4464
+ }
4465
+ } catch {
4466
+ toast11.error("Failed to calculate rate.");
4467
+ } finally {
4468
+ setIsCalculating(false);
4469
+ }
4470
+ } else {
4471
+ if (source === "FIAT") {
4472
+ setCryptoAmount((numericVal / 1600).toFixed(2));
4473
+ } else {
4474
+ setFiatAmount((numericVal * 1600).toFixed(2));
4475
+ }
4476
+ setIsCalculating(false);
4477
+ }
4478
+ }, 2e3);
4479
+ }, [fiatCurrency, onCalculateRate]);
4480
+ const handleFiatInputChange = (e) => {
4481
+ const cleanVal = e.target.value.replace(/[^0-9.]/g, "");
4482
+ if ((cleanVal.match(/\./g) || []).length > 1) return;
4483
+ setFiatAmount(cleanVal);
4484
+ setActiveSource("FIAT");
4485
+ triggerRateCalculation("FIAT", cleanVal, cryptoAmount, selectedCrypto);
4486
+ };
4487
+ const handleCryptoInputChange = (e) => {
4488
+ const cleanVal = e.target.value.replace(/[^0-9.]/g, "");
4489
+ if ((cleanVal.match(/\./g) || []).length > 1) return;
4490
+ setCryptoAmount(cleanVal);
4491
+ setActiveSource("CRYPTO");
4492
+ triggerRateCalculation("CRYPTO", fiatAmount, cleanVal, selectedCrypto);
4493
+ };
4494
+ const handleCryptoSelect = (crypto) => {
4495
+ setSelectedCrypto(crypto);
4496
+ setIsCryptoDialogOpen(false);
4497
+ triggerRateCalculation(activeSource, fiatAmount, cryptoAmount, crypto);
4498
+ };
4499
+ const handleCheckout = async () => {
4500
+ const numFiat = parseFloat(fiatAmount) || 0;
4501
+ const numCrypto = parseFloat(cryptoAmount) || 0;
4502
+ if (numFiat <= 0 || numCrypto <= 0) {
4503
+ return toast11.error("Please enter a valid purchase amount.");
4504
+ }
4505
+ if (!recipientAddress.trim() || !isAddressValid) {
4506
+ return toast11.error("Please enter a valid recipient wallet address.");
4507
+ }
4508
+ if (onSubmitCheckout) {
4509
+ setIsSubmitting(true);
4510
+ try {
4511
+ await onSubmitCheckout({
4512
+ fiatAmount,
4513
+ cryptoAmount,
4514
+ selectedCrypto,
4515
+ selectedNetwork,
4516
+ recipientAddress: recipientAddress.trim(),
4517
+ fiatCurrency
4518
+ });
4519
+ } catch (err) {
4520
+ toast11.error(err?.message || "Failed to process purchase.");
4521
+ } finally {
4522
+ setIsSubmitting(false);
4523
+ }
4524
+ }
4525
+ };
4526
+ const isButtonDisabled = isSubmitting || isCalculating || !fiatAmount || !cryptoAmount || !isAddressValid;
4527
+ return /* @__PURE__ */ React45.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ React45.createElement(ManagedToaster, null), !hideBackButton && /* @__PURE__ */ React45.createElement("div", { className: "mb-6 flex w-full items-center px-1" }, /* @__PURE__ */ React45.createElement("button", { onClick: onBackHandler, className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px] outline-none" }, /* @__PURE__ */ React45.createElement(HugeiconsIcon31, { icon: ArrowLeft01Icon12, size: 16 }), " Back")), /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col gap-1 mb-6 px-1" }, /* @__PURE__ */ React45.createElement("h1", { className: "text-black text-xl tracking-tight" }, "Buy Crypto"), /* @__PURE__ */ React45.createElement("p", { className: "text-xs text-neutral-500" }, "Purchase digital assets instantly in your local currency with direct wallet delivery.")), /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col gap-6 p-6 sm:p-8 rounded-3xl bg-white w-full" }, /* @__PURE__ */ React45.createElement("div", { className: "relative flex flex-col gap-3" }, /* @__PURE__ */ React45.createElement("div", { className: "border border-neutral-200 rounded-2xl p-4 flex items-center justify-between transition-all focus-within:border-black" }, /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col gap-1 flex-1 pr-3 min-w-0" }, /* @__PURE__ */ React45.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400" }, "You Pay (", fiatCurrency.code, ")"), isCalculating && activeSource === "CRYPTO" ? /* @__PURE__ */ React45.createElement("div", { className: "h-7 w-32 bg-neutral-100 animate-pulse rounded-md mt-1" }) : /* @__PURE__ */ React45.createElement(
4528
+ "input",
4529
+ {
4530
+ type: "text",
4531
+ inputMode: "decimal",
4532
+ value: fiatAmount,
4533
+ onChange: handleFiatInputChange,
4534
+ placeholder: "0.00",
4535
+ disabled: isSubmitting,
4536
+ className: "text-xl sm:text-2xl text-black bg-transparent outline-none w-full placeholder-neutral-300 "
4537
+ }
4538
+ )), /* @__PURE__ */ React45.createElement("div", { className: "flex items-center gap-2 bg-neutral-50 rounded-full px-3 py-1.5 shrink-0 select-none" }, /* @__PURE__ */ React45.createElement(CircularLogo, { src: fiatCurrency.logoUrl, alt: fiatCurrency.code, fallbackText: fiatCurrency.code }), /* @__PURE__ */ React45.createElement("span", { className: "text-xs text-black" }, fiatCurrency.code))), /* @__PURE__ */ React45.createElement("div", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10" }, /* @__PURE__ */ React45.createElement("div", { className: "w-10 h-10 rounded-full bg-white border border-neutral-200 flex items-center justify-center " }, /* @__PURE__ */ React45.createElement("svg", { className: "w-4 h-4 text-black", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React45.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" })))), /* @__PURE__ */ React45.createElement("div", { className: "border border-neutral-200 rounded-2xl p-4 flex items-center justify-between transition-all focus-within:border-black" }, /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col gap-1 flex-1 pr-3 min-w-0" }, /* @__PURE__ */ React45.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400" }, "You Receive"), isCalculating && activeSource === "FIAT" ? /* @__PURE__ */ React45.createElement("div", { className: "h-7 w-32 bg-neutral-100 animate-pulse rounded-md mt-1" }) : /* @__PURE__ */ React45.createElement(
4539
+ "input",
4540
+ {
4541
+ type: "text",
4542
+ inputMode: "decimal",
4543
+ value: cryptoAmount,
4544
+ onChange: handleCryptoInputChange,
4545
+ placeholder: "0.00",
4546
+ disabled: isSubmitting,
4547
+ className: "text-xl sm:text-2xl text-black bg-transparent outline-none w-full placeholder-neutral-300 "
4548
+ }
4549
+ )), /* @__PURE__ */ React45.createElement(
4550
+ "button",
4551
+ {
4552
+ type: "button",
4553
+ onClick: () => setIsCryptoDialogOpen(true),
4554
+ disabled: isSubmitting,
4555
+ className: "flex items-center gap-2 bg-neutral-100 hover:bg-neutral-200 transition-colors rounded-full px-3 py-1.5 shrink-0 outline-none"
4556
+ },
4557
+ /* @__PURE__ */ React45.createElement(CircularLogo, { src: selectedCrypto.logoUrl, alt: selectedCrypto.code, fallbackText: selectedCrypto.code }),
4558
+ /* @__PURE__ */ React45.createElement("span", { className: "text-xs text-black" }, selectedCrypto.code),
4559
+ /* @__PURE__ */ React45.createElement("svg", { className: "w-3.5 h-3.5 text-neutral-500 ml-0.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React45.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))
4560
+ ))), rateDisplay && /* @__PURE__ */ React45.createElement("div", { className: "flex items-center justify-between text-[11px] text-neutral-500 px-1 -mt-2" }, /* @__PURE__ */ React45.createElement("span", null, "Exchange Rate"), /* @__PURE__ */ React45.createElement("span", { className: "text-black " }, rateDisplay)), !hideRecipientSection && /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col gap-4 pt-2" }, /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col gap-1.5" }, /* @__PURE__ */ React45.createElement("label", { className: "text-[11px] tracking-widest text-neutral-400" }, "Network / Blockchain"), /* @__PURE__ */ React45.createElement(
4561
+ "button",
4562
+ {
4563
+ type: "button",
4564
+ onClick: () => !readOnlyRecipientSection && setIsNetworkDialogOpen(true),
4565
+ disabled: isSubmitting || selectedCrypto?.networks?.length <= 1 || readOnlyRecipientSection,
4566
+ className: `border rounded-xl p-3.5 flex items-center justify-between transition-colors text-left outline-none bg-white ${readOnlyRecipientSection ? "border-neutral-100 opacity-80 cursor-not-allowed" : "border-neutral-200 hover:border-black"}`
4567
+ },
4568
+ /* @__PURE__ */ React45.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React45.createElement(CircularLogo, { src: selectedNetwork.logoUrl || selectedCrypto.logoUrl, alt: selectedNetwork.name, fallbackText: selectedNetwork.symbol }), /* @__PURE__ */ React45.createElement("span", { className: "text-xs text-black " }, selectedNetwork.name)),
4569
+ !readOnlyRecipientSection && selectedCrypto?.networks?.length > 1 && /* @__PURE__ */ React45.createElement("svg", { className: "w-4 h-4 text-neutral-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ React45.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))
4570
+ )), /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col gap-1.5" }, /* @__PURE__ */ React45.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React45.createElement("label", { className: "text-[11px] tracking-widest text-neutral-400" }, "Recipient Wallet Address"), isAddressValid !== null && /* @__PURE__ */ React45.createElement("span", { className: `text-[10px] flex items-center gap-1 ${isAddressValid ? "text-green-600" : "text-red-500"}` }, isAddressValid ? /* @__PURE__ */ React45.createElement(React45.Fragment, null, /* @__PURE__ */ React45.createElement(HugeiconsIcon31, { icon: CheckmarkCircle01Icon2, size: 12 }), " Valid Address") : "Invalid Address Format")), /* @__PURE__ */ React45.createElement("div", { className: `border rounded-xl p-3.5 flex items-center justify-between transition-all bg-white ${readOnlyRecipientSection ? "border-neutral-100 opacity-80" : isAddressValid === true ? "border-green-500" : isAddressValid === false ? "border-red-400" : "border-neutral-200 focus-within:border-black"}` }, /* @__PURE__ */ React45.createElement(
4571
+ "input",
4572
+ {
4573
+ type: "text",
4574
+ value: recipientAddress,
4575
+ onChange: (e) => setRecipientAddress(e.target.value),
4576
+ placeholder: `Enter your ${selectedNetwork.symbol} address`,
4577
+ disabled: isSubmitting || readOnlyRecipientSection,
4578
+ spellCheck: "false",
4579
+ autoComplete: "off",
4580
+ className: `text-xs text-black bg-transparent outline-none w-full placeholder-neutral-300 ${readOnlyRecipientSection ? "cursor-not-allowed" : ""}`
4581
+ }
4582
+ )))), /* @__PURE__ */ React45.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React45.createElement(
4583
+ ThreeDActionButton,
4584
+ {
4585
+ type: "button",
4586
+ onClick: handleCheckout,
4587
+ disabled: isButtonDisabled,
4588
+ isLoading: isSubmitting,
4589
+ className: "w-full"
4590
+ },
4591
+ "Buy ",
4592
+ selectedCrypto.code,
4593
+ " Now"
4594
+ ))), isCryptoDialogOpen && /* @__PURE__ */ React45.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40" }, /* @__PURE__ */ React45.createElement("div", { className: "absolute inset-0", onClick: () => setIsCryptoDialogOpen(false) }), /* @__PURE__ */ React45.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__ */ React45.createElement(
4595
+ "button",
4596
+ {
4597
+ onClick: () => setIsCryptoDialogOpen(false),
4598
+ className: "absolute top-4 right-4 p-2 text-neutral-700 hover:text-neutral-400 transition-colors outline-none"
4599
+ },
4600
+ /* @__PURE__ */ React45.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__ */ React45.createElement("path", { d: "M18 6 6 18" }), /* @__PURE__ */ React45.createElement("path", { d: "m6 6 12 12" }))
4601
+ ), /* @__PURE__ */ React45.createElement("div", { className: "p-6 sm:p-8" }, /* @__PURE__ */ React45.createElement("div", { className: "mb-6 mt-2" }, /* @__PURE__ */ React45.createElement("h2", { className: "text-xl text-black tracking-tight mb-2" }, "Select Cryptocurrency"), /* @__PURE__ */ React45.createElement("p", { className: "text-[13px] text-neutral-500 leading-relaxed" }, "Choose the digital asset you want to purchase.")), /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col gap-2 max-h-72 overflow-y-auto custom-scrollbar pr-1" }, cryptoOptions.map((c) => {
4602
+ const isSelected = c.code === selectedCrypto.code;
4603
+ return /* @__PURE__ */ React45.createElement(
4604
+ "button",
4605
+ {
4606
+ key: c.code,
4607
+ onClick: () => handleCryptoSelect(c),
4608
+ className: `flex items-center gap-4 p-3 rounded-xl hover:bg-neutral-50 transition-colors text-left outline-none border ${isSelected ? "border-black bg-neutral-50/50" : "border-transparent"}`
4609
+ },
4610
+ /* @__PURE__ */ React45.createElement(CircularLogo, { src: c.logoUrl, alt: c.name, fallbackText: c.code }),
4611
+ /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React45.createElement("span", { className: "text-xs text-black truncate" }, c.name), /* @__PURE__ */ React45.createElement("span", { className: "text-[11px] text-neutral-400" }, c.code)),
4612
+ isSelected && /* @__PURE__ */ React45.createElement(HugeiconsIcon31, { icon: Tick02Icon, size: 16, className: "text-black" })
4613
+ );
4614
+ }))))), isNetworkDialogOpen && /* @__PURE__ */ React45.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40" }, /* @__PURE__ */ React45.createElement("div", { className: "absolute inset-0", onClick: () => setIsNetworkDialogOpen(false) }), /* @__PURE__ */ React45.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__ */ React45.createElement(
4615
+ "button",
4616
+ {
4617
+ onClick: () => setIsNetworkDialogOpen(false),
4618
+ className: "absolute top-4 right-4 p-2 text-neutral-700 hover:text-neutral-400 transition-colors outline-none"
4619
+ },
4620
+ /* @__PURE__ */ React45.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__ */ React45.createElement("path", { d: "M18 6 6 18" }), /* @__PURE__ */ React45.createElement("path", { d: "m6 6 12 12" }))
4621
+ ), /* @__PURE__ */ React45.createElement("div", { className: "p-6 sm:p-8" }, /* @__PURE__ */ React45.createElement("div", { className: "mb-6 mt-2" }, /* @__PURE__ */ React45.createElement("h2", { className: "text-xl text-black tracking-tight mb-2" }, "Select Network"), /* @__PURE__ */ React45.createElement("p", { className: "text-[13px] text-neutral-500 leading-relaxed" }, "Ensure your receiving wallet supports this network.")), /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col gap-2 max-h-72 overflow-y-auto custom-scrollbar pr-1" }, selectedCrypto?.networks?.map((net) => {
4622
+ const isSelected = net.id === selectedNetwork.id;
4623
+ return /* @__PURE__ */ React45.createElement(
4624
+ "button",
4625
+ {
4626
+ key: net.id,
4627
+ onClick: () => {
4628
+ setSelectedNetwork(net);
4629
+ setIsNetworkDialogOpen(false);
4630
+ },
4631
+ className: `flex items-center gap-4 p-3 rounded-xl hover:bg-neutral-50 transition-colors text-left outline-none border ${isSelected ? "border-black bg-neutral-50/50" : "border-transparent"}`
4632
+ },
4633
+ /* @__PURE__ */ React45.createElement(CircularLogo, { src: net.logoUrl || selectedCrypto.logoUrl, alt: net.name, fallbackText: net.symbol }),
4634
+ /* @__PURE__ */ React45.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React45.createElement("span", { className: "text-xs text-black truncate" }, net.name), /* @__PURE__ */ React45.createElement("span", { className: "text-[11px] text-neutral-400" }, net.symbol)),
4635
+ isSelected && /* @__PURE__ */ React45.createElement(HugeiconsIcon31, { icon: Tick02Icon, size: 16, className: "text-black" })
4636
+ );
4637
+ }))))));
4638
+ };
4326
4639
  export {
4327
4640
  AppBento2,
4328
4641
  CardInfoDialog,
@@ -4354,6 +4667,7 @@ export {
4354
4667
  TextInput,
4355
4668
  ThreeDActionButton,
4356
4669
  ThreeDButton,
4670
+ UniversalBuyCryptoPage,
4357
4671
  UniversalCardActionPage,
4358
4672
  UniversalCardPage,
4359
4673
  UniversalErrorView,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retinalabsllc/zairusjs",
3
- "version": "16.0.2",
3
+ "version": "16.0.25",
4
4
  "description": "A perceptive, Ai data driven Next.js UI component library.",
5
5
  "author": "Retina Labs Company",
6
6
  "license": "MIT",