@doujins/payments-ui 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,26 +1,29 @@
1
1
  import * as React3 from 'react';
2
- import { createContext, useMemo, useEffect, useContext, useState, useCallback, useRef } from 'react';
3
- import { createStore } from 'zustand/vanilla';
2
+ import { createContext, useMemo, useState, useEffect, useCallback, useRef, useContext } from 'react';
3
+ import { QueryClient, useQueryClient, useQuery, useMutation, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query';
4
+ import { useWallet, ConnectionProvider, WalletProvider, useConnection } from '@solana/wallet-adapter-react';
5
+ import { WalletModalProvider, WalletMultiButton } from '@solana/wallet-adapter-react-ui';
6
+ import '@solana/wallet-adapter-react-ui/styles.css';
7
+ import { Connection, VersionedTransaction, Transaction, clusterApiUrl, PublicKey, LAMPORTS_PER_SOL } from '@solana/web3.js';
8
+ import { PhantomWalletAdapter } from '@solana/wallet-adapter-phantom';
9
+ import { SolflareWalletAdapter } from '@solana/wallet-adapter-solflare';
10
+ import { TrustWalletAdapter } from '@solana/wallet-adapter-trust';
11
+ import { CoinbaseWalletAdapter } from '@solana/wallet-adapter-coinbase';
12
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
13
+ import { X, ChevronDown, ChevronUp, Check, User, MapPin, Loader2, CreditCard, WalletCards, Trash2, ArrowLeft, CheckCircle, AlertCircle, Wallet, Ban, TriangleAlert, Star, Copy, ExternalLink, Shield, UserRound, Calendar, KeyRound, Sparkles, XCircle, RotateCcw, RefreshCw } from 'lucide-react';
14
+ import { clsx } from 'clsx';
15
+ import { twMerge } from 'tailwind-merge';
4
16
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
- import { ChevronDown, ChevronUp, Check, X, User, MapPin, Loader2, CreditCard, WalletCards, Trash2, Sparkles, Ban, TriangleAlert, Star, CheckCircle, AlertCircle, Copy, ExternalLink, Shield, Wallet, UserRound, Calendar, KeyRound, XCircle, RotateCcw, RefreshCw } from 'lucide-react';
6
17
  import countryList from 'country-list';
7
18
  import { cva } from 'class-variance-authority';
8
- import { clsx } from 'clsx';
9
- import { twMerge } from 'tailwind-merge';
10
19
  import * as LabelPrimitive from '@radix-ui/react-label';
11
20
  import * as SelectPrimitive from '@radix-ui/react-select';
12
- import { useQueryClient, useQuery, useMutation, useInfiniteQuery } from '@tanstack/react-query';
13
- import * as DialogPrimitive from '@radix-ui/react-dialog';
14
21
  import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
15
- import { useWallet, useConnection } from '@solana/wallet-adapter-react';
22
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
16
23
  import { Buffer } from 'buffer';
17
- import { Connection, VersionedTransaction, Transaction, PublicKey, LAMPORTS_PER_SOL } from '@solana/web3.js';
18
24
  import { getAssociatedTokenAddress, getAccount, TOKEN_PROGRAM_ID } from '@solana/spl-token';
19
25
  import QRCode from 'qrcode';
20
- import { useStore } from 'zustand';
21
- import * as TabsPrimitive from '@radix-ui/react-tabs';
22
26
  import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
23
- import { WalletMultiButton } from '@solana/wallet-adapter-react-ui';
24
27
  import bs58 from 'bs58';
25
28
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
26
29
 
@@ -491,141 +494,98 @@ var PaymentApp = class {
491
494
  };
492
495
  }
493
496
  };
494
- var initialState = {
495
- selectedMethodId: null,
496
- solanaModalOpen: false,
497
- savedPaymentStatus: "idle",
498
- savedPaymentError: null,
499
- newCardStatus: "idle",
500
- newCardError: null,
501
- solanaTab: "wallet",
502
- solanaStatus: "selecting",
503
- solanaError: null,
504
- solanaTransactionId: null,
505
- solanaSelectedToken: null,
506
- solanaTokenAmount: 0
507
- };
508
- var createPaymentStore = (options) => createStore((set, get) => {
509
- const notifyStatus = (status, context) => {
510
- options?.callbacks?.onStatusChange?.({ status, context });
511
- };
512
- const notifySuccess = (payload) => {
513
- if (!options?.callbacks?.onSuccess) return;
514
- options.callbacks.onSuccess(payload ?? {});
515
- };
516
- const notifyError = (error) => {
517
- options?.callbacks?.onError?.(new Error(error));
518
- };
519
- return {
520
- ...initialState,
521
- setSelectedMethod: (methodId) => {
522
- if (get().selectedMethodId === methodId) return;
523
- set({ selectedMethodId: methodId });
524
- },
525
- setSolanaModalOpen: (open) => {
526
- if (get().solanaModalOpen === open) return;
527
- set({ solanaModalOpen: open });
528
- },
529
- setSolanaTab: (tab) => {
530
- if (get().solanaTab === tab) return;
531
- set({ solanaTab: tab });
532
- },
533
- setSolanaSelectedToken: (symbol) => {
534
- if (get().solanaSelectedToken === symbol) return;
535
- set({ solanaSelectedToken: symbol });
536
- },
537
- setSolanaTokenAmount: (amount) => {
538
- if (get().solanaTokenAmount === amount) return;
539
- set({ solanaTokenAmount: amount });
540
- },
541
- setSolanaTransactionId: (txId) => {
542
- if (get().solanaTransactionId === txId) return;
543
- set({ solanaTransactionId: txId });
544
- },
545
- startSavedPayment: () => {
546
- notifyStatus("processing", { source: "saved-payment" });
547
- set({ savedPaymentStatus: "processing", savedPaymentError: null });
548
- },
549
- completeSavedPayment: () => {
550
- notifyStatus("success", { source: "saved-payment" });
551
- set({ savedPaymentStatus: "success", savedPaymentError: null });
552
- },
553
- failSavedPayment: (error) => {
554
- notifyStatus("error", { source: "saved-payment" });
555
- notifyError(error);
556
- set({ savedPaymentStatus: "error", savedPaymentError: error });
557
- },
558
- resetSavedPayment: () => set({ savedPaymentStatus: "idle", savedPaymentError: null }),
559
- startNewCardPayment: () => {
560
- notifyStatus("processing", { source: "new-card" });
561
- set({ newCardStatus: "processing", newCardError: null });
562
- },
563
- completeNewCardPayment: () => {
564
- notifyStatus("success", { source: "new-card" });
565
- set({ newCardStatus: "success", newCardError: null });
566
- },
567
- failNewCardPayment: (error) => {
568
- notifyStatus("error", { source: "new-card" });
569
- notifyError(error);
570
- set({ newCardStatus: "error", newCardError: error });
571
- },
572
- resetNewCardPayment: () => set({ newCardStatus: "idle", newCardError: null }),
573
- startSolanaPayment: () => {
574
- notifyStatus("processing", { source: "solana" });
575
- set({ solanaStatus: "processing", solanaError: null });
576
- },
577
- confirmSolanaPayment: () => set({ solanaStatus: "confirming" }),
578
- completeSolanaPayment: (payload) => {
579
- notifyStatus("success", { source: "solana" });
580
- notifySuccess(payload);
581
- set({ solanaStatus: "success", solanaError: null });
582
- },
583
- failSolanaPayment: (error) => {
584
- notifyStatus("error", { source: "solana" });
585
- notifyError(error);
586
- set({ solanaStatus: "error", solanaError: error });
497
+
498
+ // src/runtime/PaymentsRuntime.ts
499
+ var createQueryClient = () => new QueryClient({
500
+ defaultOptions: {
501
+ queries: {
502
+ staleTime: 3e4,
503
+ gcTime: 5 * 6e4,
504
+ refetchOnWindowFocus: false,
505
+ retry: 1
587
506
  },
588
- resetSolanaPayment: () => set({
589
- solanaStatus: "selecting",
590
- solanaError: null,
591
- solanaTransactionId: null
592
- }),
593
- resetAll: () => set(initialState)
594
- };
507
+ mutations: {
508
+ retry: 1
509
+ }
510
+ }
595
511
  });
596
- var PaymentContext = createContext(void 0);
597
- var PaymentProvider = ({
598
- config,
599
- children
600
- }) => {
601
- const app = useMemo(() => new PaymentApp({ config }), [config]);
602
- const store = useMemo(
603
- () => createPaymentStore({ callbacks: config.callbacks }),
604
- [config.callbacks]
605
- );
606
- const value = useMemo(() => {
607
- return {
608
- config: app.getConfig(),
609
- fetcher: app.getFetcher(),
610
- resolveAuthToken: app.resolveAuthToken,
611
- app,
612
- services: app.getServices(),
613
- store
614
- };
615
- }, [app, store]);
616
- useEffect(() => {
617
- if (!value.config.collectJsKey) return;
618
- loadCollectJs(value.config.collectJsKey);
619
- }, [value.config.collectJsKey]);
620
- return /* @__PURE__ */ jsx(PaymentContext.Provider, { value, children });
621
- };
622
- var usePaymentContext = () => {
623
- const context = useContext(PaymentContext);
624
- if (!context) {
625
- throw new Error("usePaymentContext must be used within a PaymentProvider");
512
+ var PaymentsRuntime = class {
513
+ constructor(config) {
514
+ this.config = config;
515
+ this.app = new PaymentApp({ config });
516
+ this.services = this.app.getServices();
517
+ this.queryClient = createQueryClient();
626
518
  }
627
- return context;
628
519
  };
520
+ var createPaymentsRuntime = (config) => new PaymentsRuntime(config);
521
+
522
+ // node_modules/@solana/wallet-adapter-base/lib/esm/types.js
523
+ var WalletAdapterNetwork;
524
+ (function(WalletAdapterNetwork2) {
525
+ WalletAdapterNetwork2["Mainnet"] = "mainnet-beta";
526
+ WalletAdapterNetwork2["Testnet"] = "testnet";
527
+ WalletAdapterNetwork2["Devnet"] = "devnet";
528
+ })(WalletAdapterNetwork || (WalletAdapterNetwork = {}));
529
+ function cn(...inputs) {
530
+ return twMerge(clsx(inputs));
531
+ }
532
+ var Dialog = DialogPrimitive.Root;
533
+ var DialogPortal = ({ className, ...props }) => /* @__PURE__ */ jsx(DialogPrimitive.Portal, { className: cn(className), ...props });
534
+ DialogPortal.displayName = DialogPrimitive.Portal.displayName;
535
+ var DialogOverlay = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
536
+ DialogPrimitive.Overlay,
537
+ {
538
+ ref,
539
+ className: cn(
540
+ "fixed inset-0 z-50 bg-black/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",
541
+ className
542
+ ),
543
+ ...props
544
+ }
545
+ ));
546
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
547
+ var DialogContent = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
548
+ /* @__PURE__ */ jsx(DialogOverlay, {}),
549
+ /* @__PURE__ */ jsxs(
550
+ DialogPrimitive.Content,
551
+ {
552
+ ref,
553
+ className: cn(
554
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
555
+ className
556
+ ),
557
+ ...props,
558
+ children: [
559
+ children,
560
+ /* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none", children: [
561
+ /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
562
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
563
+ ] })
564
+ ]
565
+ }
566
+ )
567
+ ] }));
568
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
569
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
570
+ DialogHeader.displayName = "DialogHeader";
571
+ var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
572
+ DialogPrimitive.Title,
573
+ {
574
+ ref,
575
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
576
+ ...props
577
+ }
578
+ ));
579
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
580
+ var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
581
+ DialogPrimitive.Description,
582
+ {
583
+ ref,
584
+ className: cn("text-sm text-muted-foreground", className),
585
+ ...props
586
+ }
587
+ ));
588
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
629
589
  var customCountries = [
630
590
  { code: "TW", name: "Taiwan, Province of China" },
631
591
  { code: "KR", name: "Korea" },
@@ -755,9 +715,6 @@ function getElementRef(element) {
755
715
  }
756
716
  return element.props.ref || element.ref;
757
717
  }
758
- function cn(...inputs) {
759
- return twMerge(clsx(inputs));
760
- }
761
718
  var buttonVariants = cva(
762
719
  "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
763
720
  {
@@ -900,7 +857,6 @@ var defaultBilling = {
900
857
  firstName: "",
901
858
  lastName: "",
902
859
  address1: "",
903
- address2: "",
904
860
  city: "",
905
861
  stateRegion: "",
906
862
  postalCode: "",
@@ -934,7 +890,6 @@ var CardDetailsForm = ({
934
890
  const [firstName, setFirstName] = useState(mergedDefaults.firstName);
935
891
  const [lastName, setLastName] = useState(mergedDefaults.lastName);
936
892
  const [address1, setAddress1] = useState(mergedDefaults.address1);
937
- const [address2, setAddress2] = useState(mergedDefaults.address2 ?? "");
938
893
  const [city, setCity] = useState(mergedDefaults.city);
939
894
  const [stateRegion, setStateRegion] = useState(mergedDefaults.stateRegion ?? "");
940
895
  const [postalCode, setPostalCode] = useState(mergedDefaults.postalCode);
@@ -953,7 +908,6 @@ var CardDetailsForm = ({
953
908
  setFirstName(mergedDefaults.firstName);
954
909
  setLastName(mergedDefaults.lastName);
955
910
  setAddress1(mergedDefaults.address1);
956
- setAddress2(mergedDefaults.address2 ?? "");
957
911
  setCity(mergedDefaults.city);
958
912
  setStateRegion(mergedDefaults.stateRegion ?? "");
959
913
  setPostalCode(mergedDefaults.postalCode);
@@ -966,7 +920,6 @@ var CardDetailsForm = ({
966
920
  firstName,
967
921
  lastName,
968
922
  address1,
969
- address2,
970
923
  city,
971
924
  stateRegion,
972
925
  postalCode,
@@ -978,7 +931,6 @@ var CardDetailsForm = ({
978
931
  firstName,
979
932
  lastName,
980
933
  address1,
981
- address2,
982
934
  city,
983
935
  stateRegion,
984
936
  postalCode,
@@ -1002,7 +954,6 @@ var CardDetailsForm = ({
1002
954
  firstName,
1003
955
  lastName,
1004
956
  address1,
1005
- address2,
1006
957
  city,
1007
958
  stateRegion,
1008
959
  postalCode,
@@ -1033,7 +984,6 @@ var CardDetailsForm = ({
1033
984
  firstName,
1034
985
  lastName,
1035
986
  address1,
1036
- address2,
1037
987
  city,
1038
988
  stateRegion,
1039
989
  postalCode,
@@ -1062,19 +1012,16 @@ var CardDetailsForm = ({
1062
1012
  window.CollectJS.startPaymentRequest();
1063
1013
  };
1064
1014
  const errorMessage = localError ?? externalError;
1065
- const collectFieldClass = "flex h-11 w-full items-center rounded-md border border-dashed border-muted-foreground/40 bg-muted/20 px-3 text-sm text-muted-foreground";
1015
+ const collectFieldClass = "flex h-11 w-full items-center rounded-md border border-border/60 bg-background px-3 text-sm text-muted-foreground";
1066
1016
  return /* @__PURE__ */ jsxs(
1067
1017
  "form",
1068
1018
  {
1069
- className: cn(
1070
- "space-y-6 rounded-2xl border border-border/60 bg-card/90 p-6 shadow-lg",
1071
- className
1072
- ),
1019
+ className: cn("space-y-5", className),
1073
1020
  onSubmit: handleSubmit,
1074
1021
  noValidate: true,
1075
1022
  children: [
1076
1023
  errorMessage && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 px-4 py-2 text-sm text-destructive", children: errorMessage }),
1077
- /* @__PURE__ */ jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
1024
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-5 md:grid-cols-2", children: [
1078
1025
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1079
1026
  /* @__PURE__ */ jsxs(Label, { htmlFor: "payments-first", className: "flex items-center gap-2 text-muted-foreground", children: [
1080
1027
  /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }),
@@ -1120,7 +1067,7 @@ var CardDetailsForm = ({
1120
1067
  )
1121
1068
  ] }),
1122
1069
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1123
- /* @__PURE__ */ jsx(Label, { htmlFor: "payments-address1", children: "Address line 1" }),
1070
+ /* @__PURE__ */ jsx(Label, { htmlFor: "payments-address1", children: "Address" }),
1124
1071
  /* @__PURE__ */ jsx(
1125
1072
  Input,
1126
1073
  {
@@ -1131,18 +1078,7 @@ var CardDetailsForm = ({
1131
1078
  }
1132
1079
  )
1133
1080
  ] }),
1134
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1135
- /* @__PURE__ */ jsx(Label, { htmlFor: "payments-address2", children: "Address line 2 (optional)" }),
1136
- /* @__PURE__ */ jsx(
1137
- Input,
1138
- {
1139
- id: "payments-address2",
1140
- value: address2,
1141
- onChange: (e) => setAddress2(e.target.value)
1142
- }
1143
- )
1144
- ] }),
1145
- /* @__PURE__ */ jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
1081
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-5 md:grid-cols-2", children: [
1146
1082
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1147
1083
  /* @__PURE__ */ jsx(Label, { htmlFor: "payments-city", children: "City" }),
1148
1084
  /* @__PURE__ */ jsx(
@@ -1167,7 +1103,7 @@ var CardDetailsForm = ({
1167
1103
  )
1168
1104
  ] })
1169
1105
  ] }),
1170
- /* @__PURE__ */ jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
1106
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-5 md:grid-cols-2", children: [
1171
1107
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1172
1108
  /* @__PURE__ */ jsxs(Label, { htmlFor: "payments-postal", className: "flex items-center gap-2 text-muted-foreground", children: [
1173
1109
  /* @__PURE__ */ jsx(MapPin, { className: "h-4 w-4" }),
@@ -1187,7 +1123,7 @@ var CardDetailsForm = ({
1187
1123
  /* @__PURE__ */ jsx(Label, { children: "Country" }),
1188
1124
  /* @__PURE__ */ jsxs(Select, { value: country, onValueChange: setCountry, children: [
1189
1125
  /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select a country" }) }),
1190
- /* @__PURE__ */ jsx(SelectContent, { className: "max-h-64", children: countries.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.code, children: option.name }, option.code)) })
1126
+ /* @__PURE__ */ jsx(SelectContent, { className: "max-h-64 w-full", children: countries.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.code, children: option.name }, option.code)) })
1191
1127
  ] })
1192
1128
  ] })
1193
1129
  ] }),
@@ -1276,63 +1212,6 @@ var usePaymentMethods = () => {
1276
1212
  deleteMutation
1277
1213
  };
1278
1214
  };
1279
- var Dialog = DialogPrimitive.Root;
1280
- var DialogPortal = ({ className, ...props }) => /* @__PURE__ */ jsx(DialogPrimitive.Portal, { className: cn(className), ...props });
1281
- DialogPortal.displayName = DialogPrimitive.Portal.displayName;
1282
- var DialogOverlay = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1283
- DialogPrimitive.Overlay,
1284
- {
1285
- ref,
1286
- className: cn(
1287
- "fixed inset-0 z-50 bg-black/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",
1288
- className
1289
- ),
1290
- ...props
1291
- }
1292
- ));
1293
- DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
1294
- var DialogContent = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
1295
- /* @__PURE__ */ jsx(DialogOverlay, {}),
1296
- /* @__PURE__ */ jsxs(
1297
- DialogPrimitive.Content,
1298
- {
1299
- ref,
1300
- className: cn(
1301
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
1302
- className
1303
- ),
1304
- ...props,
1305
- children: [
1306
- children,
1307
- /* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none", children: [
1308
- /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
1309
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
1310
- ] })
1311
- ]
1312
- }
1313
- )
1314
- ] }));
1315
- DialogContent.displayName = DialogPrimitive.Content.displayName;
1316
- var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
1317
- DialogHeader.displayName = "DialogHeader";
1318
- var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1319
- DialogPrimitive.Title,
1320
- {
1321
- ref,
1322
- className: cn("text-lg font-semibold leading-none tracking-tight", className),
1323
- ...props
1324
- }
1325
- ));
1326
- DialogTitle.displayName = DialogPrimitive.Title.displayName;
1327
- var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1328
- DialogPrimitive.Description,
1329
- {
1330
- ref,
1331
- className: cn("text-sm text-muted-foreground", className),
1332
- ...props
1333
- }
1334
- ));
1335
- DialogDescription.displayName = DialogPrimitive.Description.displayName;
1336
1215
  var badgeVariants = cva(
1337
1216
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none",
1338
1217
  {
@@ -1382,43 +1261,6 @@ var ScrollBar = React3.forwardRef(({ className, orientation = "vertical", ...pro
1382
1261
  }
1383
1262
  ));
1384
1263
  ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
1385
- var Card = React3.forwardRef(
1386
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1387
- "div",
1388
- {
1389
- ref,
1390
- className: cn("rounded-xl border bg-card text-card-foreground shadow", className),
1391
- ...props
1392
- }
1393
- )
1394
- );
1395
- Card.displayName = "Card";
1396
- var CardHeader = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1397
- "div",
1398
- {
1399
- ref,
1400
- className: cn("flex flex-col space-y-1.5 p-6", className),
1401
- ...props
1402
- }
1403
- ));
1404
- CardHeader.displayName = "CardHeader";
1405
- var CardTitle = React3.forwardRef(
1406
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx("h3", { ref, className: cn("text-2xl font-semibold leading-none tracking-tight", className), ...props })
1407
- );
1408
- CardTitle.displayName = "CardTitle";
1409
- var CardDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
1410
- CardDescription.displayName = "CardDescription";
1411
- var CardContent = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
1412
- CardContent.displayName = "CardContent";
1413
- var CardFooter = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1414
- "div",
1415
- {
1416
- ref,
1417
- className: cn("flex items-center p-6 pt-0", className),
1418
- ...props
1419
- }
1420
- ));
1421
- CardFooter.displayName = "CardFooter";
1422
1264
  var formatCardLabel = (method) => {
1423
1265
  const brand = method.card_type ? method.card_type.toUpperCase() : "CARD";
1424
1266
  const lastFour = method.last_four ? `\u2022\u2022\u2022\u2022 ${method.last_four}` : "";
@@ -1447,22 +1289,22 @@ var StoredPaymentMethods = ({
1447
1289
  }
1448
1290
  );
1449
1291
  };
1450
- return /* @__PURE__ */ jsxs(Card, { className: "border-border/60 bg-card/95", children: [
1451
- /* @__PURE__ */ jsxs(CardHeader, { className: "flex flex-row items-start justify-between space-y-0", children: [
1452
- /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1453
- /* @__PURE__ */ jsx(CardTitle, { className: "text-base font-semibold text-foreground", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-sm font-medium text-muted-foreground", children: [
1292
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
1293
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
1294
+ /* @__PURE__ */ jsxs("div", { children: [
1295
+ /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm font-medium text-muted-foreground", children: [
1454
1296
  /* @__PURE__ */ jsx(WalletCards, { className: "h-4 w-4" }),
1455
1297
  " ",
1456
1298
  heading
1457
- ] }) }),
1458
- /* @__PURE__ */ jsx(CardDescription, { children: description })
1299
+ ] }),
1300
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: description })
1459
1301
  ] }),
1460
- showAddButton && /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => setIsModalOpen(true), children: [
1302
+ showAddButton && /* @__PURE__ */ jsxs(Button, { size: "sm", variant: "outline", onClick: () => setIsModalOpen(true), children: [
1461
1303
  /* @__PURE__ */ jsx(CreditCard, { className: "mr-2 h-4 w-4" }),
1462
1304
  " Add card"
1463
1305
  ] })
1464
1306
  ] }),
1465
- /* @__PURE__ */ jsx(CardContent, { children: listQuery.isLoading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center rounded-lg border border-dashed border-border/60 bg-muted/10 py-8 text-sm text-muted-foreground", children: [
1307
+ listQuery.isLoading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center rounded-lg border border-dashed border-border/60 bg-muted/10 py-8 text-sm text-muted-foreground", children: [
1466
1308
  /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
1467
1309
  " Loading cards\u2026"
1468
1310
  ] }) : payments.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-dashed border-border/60 bg-muted/10 px-4 py-6 text-sm text-muted-foreground", children: "No saved payment methods yet." }) : /* @__PURE__ */ jsx(ScrollArea, { className: "max-h-[320px] pr-2", children: /* @__PURE__ */ jsx("div", { className: "space-y-3", children: payments.map((method) => {
@@ -1520,8 +1362,8 @@ var StoredPaymentMethods = ({
1520
1362
  },
1521
1363
  method.id
1522
1364
  );
1523
- }) }) }) }),
1524
- /* @__PURE__ */ jsx(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-h-[90vh] overflow-y-auto", children: [
1365
+ }) }) }),
1366
+ /* @__PURE__ */ jsx(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-h-[85vh] overflow-y-auto", children: [
1525
1367
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
1526
1368
  /* @__PURE__ */ jsx(DialogTitle, { children: "Add a new card" }),
1527
1369
  /* @__PURE__ */ jsx(DialogDescription, { children: "Your card details are tokenized securely via our payment provider." })
@@ -1540,26 +1382,91 @@ var StoredPaymentMethods = ({
1540
1382
  ] }) })
1541
1383
  ] });
1542
1384
  };
1543
- var useSolanaService = () => {
1544
- const { services } = usePaymentContext();
1545
- return useMemo(() => services.solanaPayments, [services]);
1546
- };
1547
- var getSolBalance = async (connection, publicKey) => {
1548
- try {
1549
- const lamports = await connection.getBalance(publicKey);
1550
- return lamports / LAMPORTS_PER_SOL;
1551
- } catch (error) {
1552
- console.error("Failed to fetch SOL balance:", error);
1553
- return 0;
1554
- }
1555
- };
1556
- var fetchAllTokenBalances = async (connection, publicKey) => {
1557
- const balances = /* @__PURE__ */ new Map();
1558
- try {
1559
- const tokenAccounts = await connection.getParsedProgramAccounts(
1560
- TOKEN_PROGRAM_ID,
1561
- {
1562
- filters: [
1385
+ var Tabs = TabsPrimitive.Root;
1386
+ var TabsList = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1387
+ TabsPrimitive.List,
1388
+ {
1389
+ ref,
1390
+ className: cn(
1391
+ "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
1392
+ className
1393
+ ),
1394
+ ...props
1395
+ }
1396
+ ));
1397
+ TabsList.displayName = TabsPrimitive.List.displayName;
1398
+ var TabsTrigger = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1399
+ TabsPrimitive.Trigger,
1400
+ {
1401
+ ref,
1402
+ className: cn(
1403
+ "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
1404
+ className
1405
+ ),
1406
+ ...props
1407
+ }
1408
+ ));
1409
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
1410
+ var TabsContent = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1411
+ TabsPrimitive.Content,
1412
+ {
1413
+ ref,
1414
+ className: cn(
1415
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
1416
+ className
1417
+ ),
1418
+ ...props
1419
+ }
1420
+ ));
1421
+ TabsContent.displayName = TabsPrimitive.Content.displayName;
1422
+ var usePaymentNotifications = () => {
1423
+ const { config } = usePaymentContext();
1424
+ const notifyStatus = useCallback(
1425
+ (status, context) => {
1426
+ config.callbacks?.onStatusChange?.({ status, context });
1427
+ },
1428
+ [config.callbacks]
1429
+ );
1430
+ const notifySuccess = useCallback(
1431
+ (payload) => {
1432
+ config.callbacks?.onSuccess?.(payload ?? {});
1433
+ },
1434
+ [config.callbacks]
1435
+ );
1436
+ const notifyError = useCallback(
1437
+ (error) => {
1438
+ config.callbacks?.onError?.(
1439
+ typeof error === "string" ? new Error(error) : error
1440
+ );
1441
+ },
1442
+ [config.callbacks]
1443
+ );
1444
+ return {
1445
+ notifyStatus,
1446
+ notifySuccess,
1447
+ notifyError
1448
+ };
1449
+ };
1450
+ var useSolanaService = () => {
1451
+ const { services } = usePaymentContext();
1452
+ return useMemo(() => services.solanaPayments, [services]);
1453
+ };
1454
+ var getSolBalance = async (connection, publicKey) => {
1455
+ try {
1456
+ const lamports = await connection.getBalance(publicKey);
1457
+ return lamports / LAMPORTS_PER_SOL;
1458
+ } catch (error) {
1459
+ console.error("Failed to fetch SOL balance:", error);
1460
+ return 0;
1461
+ }
1462
+ };
1463
+ var fetchAllTokenBalances = async (connection, publicKey) => {
1464
+ const balances = /* @__PURE__ */ new Map();
1465
+ try {
1466
+ const tokenAccounts = await connection.getParsedProgramAccounts(
1467
+ TOKEN_PROGRAM_ID,
1468
+ {
1469
+ filters: [
1563
1470
  {
1564
1471
  dataSize: 165
1565
1472
  // Size of token account
@@ -1816,6 +1723,43 @@ var useSolanaDirectPayment = (options) => {
1816
1723
  pay
1817
1724
  };
1818
1725
  };
1726
+ var Card = React3.forwardRef(
1727
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1728
+ "div",
1729
+ {
1730
+ ref,
1731
+ className: cn("rounded-xl border bg-card text-card-foreground shadow", className),
1732
+ ...props
1733
+ }
1734
+ )
1735
+ );
1736
+ Card.displayName = "Card";
1737
+ var CardHeader = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1738
+ "div",
1739
+ {
1740
+ ref,
1741
+ className: cn("flex flex-col space-y-1.5 p-6", className),
1742
+ ...props
1743
+ }
1744
+ ));
1745
+ CardHeader.displayName = "CardHeader";
1746
+ var CardTitle = React3.forwardRef(
1747
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("h3", { ref, className: cn("text-2xl font-semibold leading-none tracking-tight", className), ...props })
1748
+ );
1749
+ CardTitle.displayName = "CardTitle";
1750
+ var CardDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
1751
+ CardDescription.displayName = "CardDescription";
1752
+ var CardContent = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
1753
+ CardContent.displayName = "CardContent";
1754
+ var CardFooter = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1755
+ "div",
1756
+ {
1757
+ ref,
1758
+ className: cn("flex items-center p-6 pt-0", className),
1759
+ ...props
1760
+ }
1761
+ ));
1762
+ CardFooter.displayName = "CardFooter";
1819
1763
  var DirectPayment = ({
1820
1764
  priceId,
1821
1765
  tokenAmount,
@@ -1836,7 +1780,7 @@ var DirectPayment = ({
1836
1780
  onSuccess: onPaymentSuccess,
1837
1781
  onError: onPaymentError
1838
1782
  });
1839
- return /* @__PURE__ */ jsxs(Card, { className: "space-y-4 border border-border/60 bg-background/80 p-6", children: [
1783
+ return /* @__PURE__ */ jsxs(Card, { className: "space-y-4 rounded-md border border-border/60 bg-background/80 shadow-none p-6", children: [
1840
1784
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1841
1785
  /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: [
1842
1786
  /* @__PURE__ */ jsx(Wallet, { className: "h-4 w-4" }),
@@ -2068,9 +2012,9 @@ var QRCodePayment = ({
2068
2012
  onSuccess: onPaymentSuccess
2069
2013
  });
2070
2014
  if (!selectedToken) {
2071
- return /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-dashed border-border/60 bg-muted/10 px-4 py-6 text-center text-sm text-muted-foreground", children: "Select a token to continue." });
2015
+ return /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border/60 bg-muted/10 px-4 py-6 text-center text-sm text-muted-foreground", children: "Select a token to continue." });
2072
2016
  }
2073
- return /* @__PURE__ */ jsxs(Card, { className: "space-y-4 border border-border/60 bg-background/80 p-6", children: [
2017
+ return /* @__PURE__ */ jsxs(Card, { className: "space-y-4 border border-border/60 bg-background/80 p-6 shadow-none rounded-md", children: [
2074
2018
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
2075
2019
  /* @__PURE__ */ jsxs("div", { children: [
2076
2020
  /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: "Scan with Solana Pay" }),
@@ -2299,109 +2243,21 @@ var useSupportedTokens = () => {
2299
2243
  tokenCount: tokens.length
2300
2244
  };
2301
2245
  };
2302
- var usePaymentStore = (selector) => {
2303
- const { store } = usePaymentContext();
2304
- return useStore(store, selector);
2305
- };
2306
-
2307
- // src/state/selectors.ts
2308
- var selectCheckoutFlow = (state) => ({
2309
- selectedMethodId: state.selectedMethodId,
2310
- savedStatus: state.savedPaymentStatus,
2311
- savedError: state.savedPaymentError,
2312
- newCardStatus: state.newCardStatus,
2313
- newCardError: state.newCardError,
2314
- solanaModalOpen: state.solanaModalOpen,
2315
- setSelectedMethod: state.setSelectedMethod,
2316
- setSolanaModalOpen: state.setSolanaModalOpen,
2317
- startSavedPayment: state.startSavedPayment,
2318
- completeSavedPayment: state.completeSavedPayment,
2319
- failSavedPayment: state.failSavedPayment,
2320
- startNewCardPayment: state.startNewCardPayment,
2321
- completeNewCardPayment: state.completeNewCardPayment,
2322
- failNewCardPayment: state.failNewCardPayment,
2323
- resetSavedPayment: state.resetSavedPayment
2324
- });
2325
- var selectSolanaFlow = (state) => ({
2326
- tab: state.solanaTab,
2327
- status: state.solanaStatus,
2328
- error: state.solanaError,
2329
- transactionId: state.solanaTransactionId,
2330
- tokenAmount: state.solanaTokenAmount,
2331
- selectedTokenSymbol: state.solanaSelectedToken,
2332
- setTab: state.setSolanaTab,
2333
- setTokenAmount: state.setSolanaTokenAmount,
2334
- setTransactionId: state.setSolanaTransactionId,
2335
- setSelectedTokenSymbol: state.setSolanaSelectedToken,
2336
- startSolanaPayment: state.startSolanaPayment,
2337
- confirmSolanaPayment: state.confirmSolanaPayment,
2338
- completeSolanaPayment: state.completeSolanaPayment,
2339
- failSolanaPayment: state.failSolanaPayment,
2340
- resetSolanaPayment: state.resetSolanaPayment
2341
- });
2342
- var Tabs = TabsPrimitive.Root;
2343
- var TabsList = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2344
- TabsPrimitive.List,
2345
- {
2346
- ref,
2347
- className: cn(
2348
- "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
2349
- className
2350
- ),
2351
- ...props
2352
- }
2353
- ));
2354
- TabsList.displayName = TabsPrimitive.List.displayName;
2355
- var TabsTrigger = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2356
- TabsPrimitive.Trigger,
2357
- {
2358
- ref,
2359
- className: cn(
2360
- "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
2361
- className
2362
- ),
2363
- ...props
2364
- }
2365
- ));
2366
- TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
2367
- var TabsContent = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2368
- TabsPrimitive.Content,
2369
- {
2370
- ref,
2371
- className: cn(
2372
- "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
2373
- className
2374
- ),
2375
- ...props
2376
- }
2377
- ));
2378
- TabsContent.displayName = TabsPrimitive.Content.displayName;
2379
- var SolanaPaymentSelector = ({
2380
- isOpen,
2381
- onClose,
2246
+ var SolanaPaymentView = ({
2382
2247
  priceId,
2383
2248
  usdAmount,
2384
2249
  onSuccess,
2385
- onError
2250
+ onError,
2251
+ onClose
2386
2252
  }) => {
2387
2253
  const { connected } = useWallet();
2388
- const {
2389
- tab: activeTab,
2390
- status: paymentState,
2391
- error: errorMessage,
2392
- transactionId,
2393
- tokenAmount,
2394
- selectedTokenSymbol,
2395
- setTab,
2396
- setTokenAmount,
2397
- setTransactionId,
2398
- setSelectedTokenSymbol,
2399
- startSolanaPayment,
2400
- confirmSolanaPayment,
2401
- completeSolanaPayment,
2402
- failSolanaPayment,
2403
- resetSolanaPayment
2404
- } = usePaymentStore(selectSolanaFlow);
2254
+ const { notifyStatus, notifyError, notifySuccess } = usePaymentNotifications();
2255
+ const [activeTab, setActiveTab] = useState("wallet");
2256
+ const [paymentState, setPaymentState] = useState("selecting");
2257
+ const [errorMessage, setErrorMessage] = useState(null);
2258
+ const [transactionId, setTransactionId] = useState(null);
2259
+ const [tokenAmount, setTokenAmount] = useState(0);
2260
+ const [selectedTokenSymbol, setSelectedTokenSymbol] = useState(null);
2405
2261
  const {
2406
2262
  tokens,
2407
2263
  isLoading: tokensLoading,
@@ -2417,60 +2273,70 @@ var SolanaPaymentSelector = ({
2417
2273
  const defaultToken = tokens.find((token) => token.symbol === "SOL") || tokens[0];
2418
2274
  setSelectedTokenSymbol(defaultToken.symbol);
2419
2275
  }
2420
- }, [tokens, selectedTokenSymbol, setSelectedTokenSymbol]);
2276
+ }, [tokens, selectedTokenSymbol]);
2421
2277
  const handlePaymentStart = useCallback(() => {
2422
- startSolanaPayment();
2423
- }, [startSolanaPayment]);
2278
+ setPaymentState("processing");
2279
+ setErrorMessage(null);
2280
+ notifyStatus("processing", { source: "solana" });
2281
+ }, [notifyStatus]);
2424
2282
  const handlePaymentConfirming = useCallback(() => {
2425
- confirmSolanaPayment();
2426
- }, [confirmSolanaPayment]);
2283
+ setPaymentState("confirming");
2284
+ }, []);
2427
2285
  const handlePaymentSuccess = useCallback(
2428
2286
  (result, txId) => {
2429
2287
  const resolvedTx = txId || (typeof result === "string" ? result : result.transaction_id);
2430
2288
  setTransactionId(resolvedTx);
2431
- completeSolanaPayment(
2432
- typeof result === "string" ? {
2433
- transactionId: resolvedTx,
2434
- processor: "solana",
2435
- metadata: { source: "solana-pay" }
2436
- } : {
2437
- transactionId: result.transaction_id,
2438
- intentId: result.intent_id,
2439
- processor: "solana",
2440
- metadata: {
2441
- purchaseId: result.purchase_id,
2442
- amount: result.amount,
2443
- currency: result.currency
2444
- }
2289
+ setPaymentState("success");
2290
+ setErrorMessage(null);
2291
+ const payload = typeof result === "string" ? {
2292
+ transactionId: resolvedTx,
2293
+ processor: "solana",
2294
+ metadata: { source: "solana-pay" }
2295
+ } : {
2296
+ transactionId: result.transaction_id,
2297
+ intentId: result.intent_id,
2298
+ processor: "solana",
2299
+ metadata: {
2300
+ purchaseId: result.purchase_id,
2301
+ amount: result.amount,
2302
+ currency: result.currency
2445
2303
  }
2446
- );
2304
+ };
2305
+ notifyStatus("success", { source: "solana" });
2306
+ notifySuccess(payload);
2447
2307
  setTimeout(() => {
2448
2308
  onSuccess(result);
2449
2309
  }, 1500);
2450
2310
  },
2451
- [completeSolanaPayment, onSuccess, setTransactionId]
2311
+ [notifyStatus, notifySuccess, onSuccess]
2452
2312
  );
2453
2313
  const handlePaymentError = useCallback(
2454
2314
  (error) => {
2455
- failSolanaPayment(error);
2315
+ setPaymentState("error");
2316
+ setErrorMessage(error);
2317
+ notifyStatus("error", { source: "solana" });
2318
+ notifyError(error);
2456
2319
  onError?.(error);
2457
2320
  },
2458
- [failSolanaPayment, onError]
2321
+ [notifyError, notifyStatus, onError]
2459
2322
  );
2460
- const handleRetry = useCallback(() => {
2461
- resetSolanaPayment();
2323
+ const resetState = useCallback(() => {
2324
+ setPaymentState("selecting");
2325
+ setErrorMessage(null);
2462
2326
  setTransactionId(null);
2463
- }, [resetSolanaPayment, setTransactionId]);
2327
+ }, []);
2328
+ const handleRetry = useCallback(() => {
2329
+ resetState();
2330
+ }, [resetState]);
2464
2331
  const handleClose = useCallback(() => {
2465
2332
  if (paymentState === "processing" || paymentState === "confirming") {
2466
2333
  return;
2467
2334
  }
2468
- resetSolanaPayment();
2469
- setTransactionId(null);
2470
- onClose();
2471
- }, [paymentState, resetSolanaPayment, setTransactionId, onClose]);
2335
+ resetState();
2336
+ onClose?.();
2337
+ }, [paymentState, onClose, resetState]);
2472
2338
  useEffect(() => {
2473
- if (!isOpen || !selectedToken || usdAmount === 0) {
2339
+ if (!selectedToken || usdAmount === 0) {
2474
2340
  setTokenAmount(0);
2475
2341
  return;
2476
2342
  }
@@ -2480,23 +2346,20 @@ var SolanaPaymentSelector = ({
2480
2346
  return;
2481
2347
  }
2482
2348
  setTokenAmount(usdAmount / price);
2483
- }, [isOpen, usdAmount, selectedToken, setTokenAmount]);
2484
- const handleTokenChange = useCallback(
2485
- (value) => {
2486
- setSelectedTokenSymbol(value);
2487
- },
2488
- [setSelectedTokenSymbol]
2489
- );
2349
+ }, [usdAmount, selectedToken]);
2350
+ const handleTokenChange = useCallback((value) => {
2351
+ setSelectedTokenSymbol(value);
2352
+ }, []);
2490
2353
  const wasConnectedRef = useRef(connected);
2491
2354
  useEffect(() => {
2492
2355
  if (connected && !wasConnectedRef.current) {
2493
- setTab("wallet");
2356
+ setActiveTab("wallet");
2494
2357
  }
2495
2358
  if (!connected && wasConnectedRef.current) {
2496
- setTab("qr");
2359
+ setActiveTab("qr");
2497
2360
  }
2498
2361
  wasConnectedRef.current = connected;
2499
- }, [connected, setTab]);
2362
+ }, [connected]);
2500
2363
  const renderBody = () => {
2501
2364
  if (paymentState !== "selecting") {
2502
2365
  return /* @__PURE__ */ jsx(
@@ -2512,63 +2375,79 @@ var SolanaPaymentSelector = ({
2512
2375
  }
2513
2376
  );
2514
2377
  }
2515
- return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: tokensLoading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center rounded-lg border border-dashed border-border/60 bg-muted/10 py-8 text-sm text-muted-foreground", children: [
2516
- /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
2517
- " Loading supported tokens\u2026"
2518
- ] }) : tokensError ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: tokensError }) : !tokens.length ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-dashed border-border/60 bg-muted/10 px-4 py-6 text-sm text-muted-foreground", children: "No payment tokens available." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2519
- /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border/60 bg-muted/10 p-4 text-center", children: [
2520
- /* @__PURE__ */ jsxs("div", { className: "text-2xl font-semibold text-foreground", children: [
2378
+ if (tokensLoading) {
2379
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-10 text-sm text-muted-foreground", children: [
2380
+ /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
2381
+ " Loading supported tokens\u2026"
2382
+ ] });
2383
+ }
2384
+ if (tokensError) {
2385
+ return /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: tokensError });
2386
+ }
2387
+ if (!tokens.length) {
2388
+ return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No payment tokens available." });
2389
+ }
2390
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
2391
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1 text-center", children: [
2392
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Amount due" }),
2393
+ /* @__PURE__ */ jsxs("p", { className: "text-3xl font-semibold text-foreground", children: [
2521
2394
  "$",
2522
2395
  usdAmount.toFixed(2),
2523
2396
  " USD"
2524
2397
  ] }),
2525
- selectedToken && tokenAmount > 0 && /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
2398
+ selectedToken && tokenAmount > 0 && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
2526
2399
  "\u2248 ",
2527
2400
  tokenAmount.toFixed(selectedToken.symbol === "SOL" ? 4 : 2),
2528
2401
  " ",
2529
2402
  selectedToken.symbol
2530
2403
  ] })
2531
2404
  ] }),
2532
- /* @__PURE__ */ jsxs(Select, { value: selectedToken?.symbol ?? "", onValueChange: handleTokenChange, children: [
2533
- /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select token" }) }),
2534
- /* @__PURE__ */ jsx(SelectContent, { className: "max-h-64", children: tokens.map((token) => /* @__PURE__ */ jsxs(SelectItem, { value: token.symbol, children: [
2535
- token.name,
2536
- " (",
2537
- token.symbol,
2538
- ")"
2539
- ] }, token.symbol)) })
2405
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
2406
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "Select token" }),
2407
+ /* @__PURE__ */ jsxs(Select, { value: selectedToken?.symbol ?? "", onValueChange: handleTokenChange, children: [
2408
+ /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select token" }) }),
2409
+ /* @__PURE__ */ jsx(SelectContent, { className: "max-h-64", children: tokens.map((token) => /* @__PURE__ */ jsxs(SelectItem, { value: token.symbol, children: [
2410
+ token.name,
2411
+ " (",
2412
+ token.symbol,
2413
+ ")"
2414
+ ] }, token.symbol)) })
2415
+ ] })
2540
2416
  ] }),
2541
- /* @__PURE__ */ jsxs(
2417
+ /* @__PURE__ */ jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxs(
2542
2418
  Tabs,
2543
2419
  {
2544
2420
  value: activeTab,
2545
- onValueChange: (value) => setTab(value),
2546
- className: "w-full",
2421
+ onValueChange: (value) => setActiveTab(value),
2422
+ className: "w-full space-y-3",
2547
2423
  children: [
2548
- /* @__PURE__ */ jsxs(TabsList, { className: "grid w-full grid-cols-2 bg-muted/20", children: [
2424
+ /* @__PURE__ */ jsxs(TabsList, { className: "grid w-full grid-cols-2 bg-muted/10", children: [
2549
2425
  /* @__PURE__ */ jsxs(TabsTrigger, { value: "wallet", disabled: !connected, children: [
2550
2426
  /* @__PURE__ */ jsx(Wallet, { className: "mr-2 h-4 w-4" }),
2551
- " Pay with Wallet"
2427
+ " Wallet"
2552
2428
  ] }),
2553
2429
  /* @__PURE__ */ jsxs(TabsTrigger, { value: "qr", children: [
2554
2430
  /* @__PURE__ */ jsx(CreditCard, { className: "mr-2 h-4 w-4" }),
2555
- " Scan QR Code"
2431
+ " QR Code"
2556
2432
  ] })
2557
2433
  ] }),
2558
- /* @__PURE__ */ jsx(TabsContent, { value: "wallet", className: "mt-4", children: activeTab === "wallet" && /* @__PURE__ */ jsx(
2559
- DirectPayment,
2560
- {
2561
- priceId,
2562
- tokenAmount,
2563
- selectedToken,
2564
- supportedTokens: tokens,
2565
- onPaymentStart: handlePaymentStart,
2566
- onPaymentConfirming: handlePaymentConfirming,
2567
- onPaymentSuccess: handlePaymentSuccess,
2568
- onPaymentError: handlePaymentError
2569
- }
2570
- ) }),
2571
- /* @__PURE__ */ jsx(TabsContent, { value: "qr", className: "mt-4", children: activeTab === "qr" && /* @__PURE__ */ jsx(
2434
+ /* @__PURE__ */ jsxs(TabsContent, { value: "wallet", className: "space-y-4", children: [
2435
+ activeTab === "wallet" && /* @__PURE__ */ jsx(
2436
+ DirectPayment,
2437
+ {
2438
+ priceId,
2439
+ tokenAmount,
2440
+ selectedToken,
2441
+ supportedTokens: tokens,
2442
+ onPaymentStart: handlePaymentStart,
2443
+ onPaymentConfirming: handlePaymentConfirming,
2444
+ onPaymentSuccess: handlePaymentSuccess,
2445
+ onPaymentError: handlePaymentError
2446
+ }
2447
+ ),
2448
+ !connected && /* @__PURE__ */ jsx("div", { className: "text-sm text-amber-100", children: "Connect your Solana wallet to continue or switch to QR mode." })
2449
+ ] }),
2450
+ /* @__PURE__ */ jsx(TabsContent, { value: "qr", children: activeTab === "qr" && /* @__PURE__ */ jsx(
2572
2451
  QRCodePayment,
2573
2452
  {
2574
2453
  priceId,
@@ -2579,162 +2458,738 @@ var SolanaPaymentSelector = ({
2579
2458
  ) })
2580
2459
  ]
2581
2460
  }
2582
- ),
2583
- !connected && activeTab === "wallet" && /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-amber-500/40 bg-amber-500/10 p-4 text-sm text-amber-100", children: "Please connect your Solana wallet to complete this payment, or switch to QR mode." })
2584
- ] }) });
2461
+ ) })
2462
+ ] });
2585
2463
  };
2586
- return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
2587
- /* @__PURE__ */ jsxs(DialogHeader, { className: "space-y-1", children: [
2588
- /* @__PURE__ */ jsx(DialogTitle, { children: "Complete your payment" }),
2589
- /* @__PURE__ */ jsx(DialogDescription, { children: "Select a token and preferred method. We\u2019ll guide you through the rest." })
2464
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
2465
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
2466
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2467
+ /* @__PURE__ */ jsx("p", { className: "text-xs uppercase tracking-wide text-muted-foreground", children: "Solana Pay checkout" }),
2468
+ /* @__PURE__ */ jsx("p", { className: "text-2xl font-semibold text-foreground", children: "Pay with Solana" }),
2469
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Choose a supported token and send the payment with your wallet or a QR code." })
2470
+ ] }),
2471
+ onClose && /* @__PURE__ */ jsxs(
2472
+ Button,
2473
+ {
2474
+ type: "button",
2475
+ size: "sm",
2476
+ variant: "ghost",
2477
+ onClick: handleClose,
2478
+ disabled: paymentState === "processing" || paymentState === "confirming",
2479
+ className: "h-8 px-2 text-sm",
2480
+ children: [
2481
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }),
2482
+ " Back"
2483
+ ]
2484
+ }
2485
+ )
2590
2486
  ] }),
2591
2487
  renderBody()
2592
- ] }) });
2488
+ ] });
2593
2489
  };
2594
- var PaymentExperience = ({
2595
- priceId,
2596
- usdAmount,
2597
- onNewCardPayment,
2598
- onSavedMethodPayment,
2599
- enableNewCard = true,
2600
- enableStoredMethods = true,
2601
- enableSolanaPay = true,
2602
- checkoutSummary,
2603
- onSolanaSuccess,
2604
- onSolanaError
2605
- }) => {
2606
- const showNewCard = enableNewCard && Boolean(onNewCardPayment);
2607
- const showStored = enableStoredMethods;
2608
- const {
2609
- selectedMethodId,
2610
- savedStatus,
2611
- savedError,
2612
- newCardStatus,
2613
- newCardError,
2614
- solanaModalOpen,
2615
- setSelectedMethod,
2616
- setSolanaModalOpen,
2617
- startSavedPayment,
2618
- completeSavedPayment,
2619
- failSavedPayment,
2620
- startNewCardPayment,
2621
- completeNewCardPayment,
2622
- failNewCardPayment,
2623
- resetSavedPayment
2624
- } = usePaymentStore(selectCheckoutFlow);
2625
- const handleMethodSelect = (method) => {
2626
- setSelectedMethod(method.id);
2627
- resetSavedPayment();
2628
- };
2629
- const handleNewCardTokenize = async (token, billing) => {
2630
- if (!onNewCardPayment) return;
2631
- try {
2632
- startNewCardPayment();
2633
- await onNewCardPayment({ token, billing });
2634
- completeNewCardPayment();
2635
- } catch (error) {
2636
- const message = error instanceof Error ? error.message : "Unable to complete payment";
2637
- failNewCardPayment(message);
2638
- }
2639
- };
2640
- const handleSavedPayment = async () => {
2641
- if (!onSavedMethodPayment || !selectedMethodId) return;
2642
- try {
2643
- startSavedPayment();
2644
- await onSavedMethodPayment({
2645
- paymentMethodId: selectedMethodId,
2646
- amount: usdAmount
2647
- });
2648
- completeSavedPayment();
2649
- } catch (error) {
2650
- const message = error instanceof Error ? error.message : "Unable to complete payment with saved card";
2651
- failSavedPayment(message);
2490
+ var useSubscriptionActions = () => {
2491
+ const { services } = usePaymentContext();
2492
+ const ensurePrice = (priceId) => {
2493
+ if (!priceId) {
2494
+ throw new Error("payments-ui: priceId is required for subscription actions");
2652
2495
  }
2496
+ return priceId;
2653
2497
  };
2654
- return /* @__PURE__ */ jsxs("div", { className: "space-y-8", children: [
2655
- /* @__PURE__ */ jsxs(Card, { className: "border-border/60 bg-card/95", children: [
2656
- /* @__PURE__ */ jsxs(CardHeader, { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
2657
- /* @__PURE__ */ jsxs("div", { children: [
2658
- /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2 text-lg text-foreground", children: [
2659
- /* @__PURE__ */ jsx(CreditCard, { className: "h-5 w-5 text-primary" }),
2660
- " Secure checkout"
2661
- ] }),
2662
- /* @__PURE__ */ jsxs(CardDescription, { children: [
2663
- "Amount due: $",
2664
- usdAmount.toFixed(2)
2665
- ] })
2666
- ] }),
2667
- checkoutSummary && /* @__PURE__ */ jsx("div", { children: checkoutSummary })
2668
- ] }),
2669
- /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs("div", { className: "grid gap-8 lg:grid-cols-2", children: [
2670
- showStored && /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
2671
- /* @__PURE__ */ jsx(
2672
- StoredPaymentMethods,
2673
- {
2674
- selectedMethodId,
2675
- onMethodSelect: handleMethodSelect,
2676
- heading: "Saved cards",
2677
- description: "Use or manage your saved payment methods."
2678
- }
2679
- ),
2680
- onSavedMethodPayment && /* @__PURE__ */ jsx(
2681
- Button,
2682
- {
2683
- className: "w-full",
2684
- disabled: !selectedMethodId || savedStatus === "processing",
2685
- onClick: handleSavedPayment,
2686
- children: savedStatus === "processing" ? "Processing\u2026" : "Pay with selected card"
2687
- }
2688
- ),
2689
- savedError && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: savedError })
2690
- ] }),
2691
- showNewCard && /* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border/60 bg-background/80 p-6", children: [
2692
- /* @__PURE__ */ jsxs("div", { className: "mb-4 space-y-1", children: [
2693
- /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: [
2694
- /* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4" }),
2695
- " Pay with a new card"
2696
- ] }),
2697
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Card details are tokenized via Collect.js and never hit your server." })
2698
- ] }),
2699
- /* @__PURE__ */ jsx(
2700
- CardDetailsForm,
2701
- {
2702
- visible: true,
2703
- submitLabel: "Pay now",
2704
- submitting: newCardStatus === "processing",
2705
- externalError: newCardError,
2706
- onTokenize: handleNewCardTokenize
2707
- }
2708
- )
2709
- ] }) })
2710
- ] }) })
2711
- ] }),
2712
- enableSolanaPay && /* @__PURE__ */ jsx(Card, { className: "border border-primary/40 bg-primary/5", children: /* @__PURE__ */ jsxs(CardContent, { className: "flex flex-col gap-4 text-sm text-primary md:flex-row md:items-center md:justify-between", children: [
2713
- /* @__PURE__ */ jsxs("div", { children: [
2714
- /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-base font-semibold text-primary", children: [
2715
- /* @__PURE__ */ jsx(Sparkles, { className: "h-4 w-4" }),
2716
- " Prefer Solana Pay?"
2717
- ] }),
2718
- /* @__PURE__ */ jsx("p", { className: "text-sm text-primary/80", children: "Use a Solana wallet or QR code for instant settlement." })
2719
- ] }),
2720
- /* @__PURE__ */ jsx(Button, { onClick: () => setSolanaModalOpen(true), children: "Open Solana Pay" })
2721
- ] }) }),
2722
- enableSolanaPay && /* @__PURE__ */ jsx(
2723
- SolanaPaymentSelector,
2498
+ const subscribeWithCard = useCallback(
2499
+ async ({
2500
+ priceId,
2501
+ processor = "nmi",
2502
+ provider,
2503
+ paymentToken,
2504
+ billing
2505
+ }) => {
2506
+ const payload = {
2507
+ priceId: ensurePrice(priceId),
2508
+ paymentToken,
2509
+ processor,
2510
+ provider,
2511
+ email: billing.email,
2512
+ firstName: billing.firstName,
2513
+ lastName: billing.lastName,
2514
+ address1: billing.address1,
2515
+ city: billing.city,
2516
+ state: billing.stateRegion,
2517
+ zipCode: billing.postalCode,
2518
+ country: billing.country
2519
+ };
2520
+ return services.subscriptions.subscribe("nmi", payload);
2521
+ },
2522
+ [services]
2523
+ );
2524
+ const subscribeWithSavedMethod = useCallback(
2525
+ async ({
2526
+ priceId,
2527
+ processor = "nmi",
2528
+ provider,
2529
+ paymentMethodId,
2530
+ email
2531
+ }) => {
2532
+ const payload = {
2533
+ priceId: ensurePrice(priceId),
2534
+ paymentMethodId,
2535
+ processor,
2536
+ provider,
2537
+ email
2538
+ };
2539
+ return services.subscriptions.subscribe("nmi", payload);
2540
+ },
2541
+ [services]
2542
+ );
2543
+ const subscribeWithCCBill = useCallback(
2544
+ async ({
2545
+ priceId,
2546
+ email,
2547
+ firstName,
2548
+ lastName,
2549
+ zipCode,
2550
+ country,
2551
+ processor = "ccbill"
2552
+ }) => {
2553
+ const payload = {
2554
+ priceId: ensurePrice(priceId),
2555
+ email,
2556
+ firstName,
2557
+ lastName,
2558
+ zipCode,
2559
+ country,
2560
+ processor
2561
+ };
2562
+ return services.subscriptions.subscribe("ccbill", payload);
2563
+ },
2564
+ [services]
2565
+ );
2566
+ const generateFlexFormUrl = useCallback(
2567
+ async ({
2568
+ priceId,
2569
+ firstName,
2570
+ lastName,
2571
+ address1,
2572
+ city,
2573
+ state,
2574
+ zipCode,
2575
+ country
2576
+ }) => {
2577
+ const payload = {
2578
+ price_id: ensurePrice(priceId),
2579
+ first_name: firstName,
2580
+ last_name: lastName,
2581
+ address1,
2582
+ city,
2583
+ state,
2584
+ zip_code: zipCode,
2585
+ country
2586
+ };
2587
+ return services.subscriptions.generateFlexFormUrl(payload);
2588
+ },
2589
+ [services]
2590
+ );
2591
+ return {
2592
+ subscribeWithCard,
2593
+ subscribeWithSavedMethod,
2594
+ subscribeWithCCBill,
2595
+ generateFlexFormUrl
2596
+ };
2597
+ };
2598
+
2599
+ // src/hooks/useAlternativePaymentProvider.ts
2600
+ var useAlternativePaymentProvider = () => {
2601
+ const [isLoading, setIsLoading] = useState(false);
2602
+ const [error, setError] = useState(null);
2603
+ const { generateFlexFormUrl } = useSubscriptionActions();
2604
+ const openFlexForm = useCallback(
2605
+ async (payload) => {
2606
+ setIsLoading(true);
2607
+ setError(null);
2608
+ try {
2609
+ const response = await generateFlexFormUrl(payload);
2610
+ if (response?.iframe_url) {
2611
+ window.location.href = response.iframe_url;
2612
+ } else {
2613
+ throw new Error("Unable to launch payment provider.");
2614
+ }
2615
+ } catch (err) {
2616
+ const message = err instanceof Error ? err.message : "Failed to open payment provider.";
2617
+ setError(message);
2618
+ console.error("[payments-ui] failed to open alternative payment provider", err);
2619
+ } finally {
2620
+ setIsLoading(false);
2621
+ }
2622
+ },
2623
+ [generateFlexFormUrl]
2624
+ );
2625
+ return { openFlexForm, isLoading, error };
2626
+ };
2627
+ var PaymentExperience = ({
2628
+ priceId,
2629
+ usdAmount,
2630
+ onNewCardPayment,
2631
+ onSavedMethodPayment,
2632
+ enableNewCard = true,
2633
+ enableStoredMethods = true,
2634
+ enableSolanaPay = true,
2635
+ enableAlternativePayments = true,
2636
+ onSolanaSuccess,
2637
+ onSolanaError,
2638
+ initialMode = "cards"
2639
+ }) => {
2640
+ const showNewCard = enableNewCard && Boolean(onNewCardPayment);
2641
+ const showStored = enableStoredMethods && Boolean(onSavedMethodPayment);
2642
+ const defaultTab = showStored ? "saved" : "new";
2643
+ const [activeTab, setActiveTab] = useState(defaultTab);
2644
+ const [mode, setMode] = useState(
2645
+ () => initialMode === "solana" && enableSolanaPay ? "solana" : "cards"
2646
+ );
2647
+ const [selectedMethodId, setSelectedMethodId] = useState(null);
2648
+ const [savedStatus, setSavedStatus] = useState("idle");
2649
+ const [savedError, setSavedError] = useState(null);
2650
+ const [newCardStatus, setNewCardStatus] = useState("idle");
2651
+ const [newCardError, setNewCardError] = useState(null);
2652
+ const [billingDetails, setBillingDetails] = useState(null);
2653
+ const [alternativePaymentError, setAlternativePaymentError] = useState(null);
2654
+ const { notifyStatus, notifySuccess, notifyError } = usePaymentNotifications();
2655
+ const {
2656
+ openFlexForm,
2657
+ isLoading: flexFormLoading,
2658
+ error: flexFormError
2659
+ } = useAlternativePaymentProvider();
2660
+ useEffect(() => {
2661
+ setActiveTab(showStored ? "saved" : "new");
2662
+ }, [showStored]);
2663
+ useEffect(() => {
2664
+ if (!enableSolanaPay) {
2665
+ setMode("cards");
2666
+ return;
2667
+ }
2668
+ if (initialMode === "solana") {
2669
+ setMode("solana");
2670
+ } else {
2671
+ setMode("cards");
2672
+ }
2673
+ }, [enableSolanaPay, initialMode]);
2674
+ const handleMethodSelect = useCallback((method) => {
2675
+ setSelectedMethodId(method.id);
2676
+ setSavedStatus("idle");
2677
+ setSavedError(null);
2678
+ }, []);
2679
+ const handleSavedPayment = useCallback(async () => {
2680
+ if (!onSavedMethodPayment || !selectedMethodId) return;
2681
+ try {
2682
+ setSavedStatus("processing");
2683
+ setSavedError(null);
2684
+ notifyStatus("processing", { source: "saved-payment" });
2685
+ await onSavedMethodPayment({
2686
+ paymentMethodId: selectedMethodId,
2687
+ amount: usdAmount
2688
+ });
2689
+ setSavedStatus("success");
2690
+ notifyStatus("success", { source: "saved-payment" });
2691
+ } catch (error) {
2692
+ const message = error instanceof Error ? error.message : "Unable to complete payment with saved card";
2693
+ setSavedStatus("error");
2694
+ setSavedError(message);
2695
+ notifyStatus("error", { source: "saved-payment" });
2696
+ notifyError(message);
2697
+ }
2698
+ }, [notifyError, notifyStatus, onSavedMethodPayment, selectedMethodId, usdAmount]);
2699
+ const handleNewCardTokenize = useCallback(
2700
+ async (token, billing) => {
2701
+ if (!onNewCardPayment) return;
2702
+ try {
2703
+ setNewCardStatus("processing");
2704
+ setNewCardError(null);
2705
+ notifyStatus("processing", { source: "new-card" });
2706
+ await onNewCardPayment({ token, billing });
2707
+ setNewCardStatus("success");
2708
+ notifyStatus("success", { source: "new-card" });
2709
+ } catch (error) {
2710
+ const message = error instanceof Error ? error.message : "Unable to complete payment";
2711
+ setNewCardStatus("error");
2712
+ setNewCardError(message);
2713
+ notifyStatus("error", { source: "new-card" });
2714
+ notifyError(message);
2715
+ }
2716
+ },
2717
+ [notifyError, notifyStatus, onNewCardPayment]
2718
+ );
2719
+ const showSolanaView = useCallback(() => {
2720
+ if (!enableSolanaPay) return;
2721
+ setMode("solana");
2722
+ }, [enableSolanaPay]);
2723
+ const exitSolanaView = useCallback(() => {
2724
+ setMode("cards");
2725
+ }, []);
2726
+ const handleSolanaSuccess = useCallback(
2727
+ (result) => {
2728
+ onSolanaSuccess?.(result);
2729
+ exitSolanaView();
2730
+ },
2731
+ [exitSolanaView, onSolanaSuccess]
2732
+ );
2733
+ const handleSolanaError = useCallback(
2734
+ (error) => {
2735
+ onSolanaError?.(error);
2736
+ },
2737
+ [onSolanaError]
2738
+ );
2739
+ const handleAlternativePayment = useCallback(() => {
2740
+ if (!enableAlternativePayments || !priceId) {
2741
+ return;
2742
+ }
2743
+ if (!billingDetails) {
2744
+ setAlternativePaymentError("Enter your billing details first.");
2745
+ return;
2746
+ }
2747
+ const requiredFields = [
2748
+ "firstName",
2749
+ "lastName",
2750
+ "address1",
2751
+ "city",
2752
+ "stateRegion",
2753
+ "postalCode",
2754
+ "country"
2755
+ ];
2756
+ const missingField = requiredFields.find((field) => {
2757
+ const value = billingDetails[field];
2758
+ return typeof value !== "string" || value.trim().length === 0;
2759
+ });
2760
+ if (missingField) {
2761
+ setAlternativePaymentError("Please complete your billing address before continuing.");
2762
+ return;
2763
+ }
2764
+ setAlternativePaymentError(null);
2765
+ openFlexForm({
2766
+ priceId,
2767
+ firstName: billingDetails.firstName,
2768
+ lastName: billingDetails.lastName,
2769
+ address1: billingDetails.address1,
2770
+ city: billingDetails.city,
2771
+ state: billingDetails.stateRegion ?? "",
2772
+ zipCode: billingDetails.postalCode,
2773
+ country: billingDetails.country
2774
+ });
2775
+ }, [
2776
+ billingDetails,
2777
+ enableAlternativePayments,
2778
+ openFlexForm,
2779
+ priceId
2780
+ ]);
2781
+ const renderSavedTab = () => {
2782
+ if (!showStored) {
2783
+ return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Saved payment methods are unavailable right now. Add a new card to get started." });
2784
+ }
2785
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
2786
+ /* @__PURE__ */ jsx(
2787
+ StoredPaymentMethods,
2788
+ {
2789
+ heading: "Saved cards",
2790
+ selectedMethodId,
2791
+ onMethodSelect: handleMethodSelect,
2792
+ description: "Select one of your stored payment methods.",
2793
+ showAddButton: false
2794
+ }
2795
+ ),
2796
+ /* @__PURE__ */ jsx(
2797
+ Button,
2798
+ {
2799
+ className: "w-full",
2800
+ disabled: !selectedMethodId || savedStatus === "processing",
2801
+ onClick: handleSavedPayment,
2802
+ children: savedStatus === "processing" ? "Processing\u2026" : "Pay with selected card"
2803
+ }
2804
+ ),
2805
+ savedError && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: savedError })
2806
+ ] });
2807
+ };
2808
+ const renderNewTab = () => {
2809
+ if (!showNewCard) {
2810
+ return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Select a subscription plan to add a new card." });
2811
+ }
2812
+ return /* @__PURE__ */ jsx(
2813
+ CardDetailsForm,
2814
+ {
2815
+ visible: true,
2816
+ submitLabel: "Pay now",
2817
+ externalError: newCardError,
2818
+ onTokenize: handleNewCardTokenize,
2819
+ submitting: newCardStatus === "processing",
2820
+ onBillingChange: setBillingDetails
2821
+ }
2822
+ );
2823
+ };
2824
+ const renderCardExperience = () => /* @__PURE__ */ jsxs(Fragment, { children: [
2825
+ /* @__PURE__ */ jsxs(
2826
+ Tabs,
2827
+ {
2828
+ value: activeTab,
2829
+ onValueChange: (value) => setActiveTab(value),
2830
+ className: "space-y-3",
2831
+ children: [
2832
+ /* @__PURE__ */ jsxs(TabsList, { className: "grid w-full grid-cols-2 border border-border/60", children: [
2833
+ /* @__PURE__ */ jsx(TabsTrigger, { value: "saved", disabled: !showStored, children: "Use saved card" }),
2834
+ /* @__PURE__ */ jsx(TabsTrigger, { value: "new", disabled: !showNewCard, children: "Add new card" })
2835
+ ] }),
2836
+ /* @__PURE__ */ jsx(TabsContent, { value: "saved", className: "space-y-4", children: renderSavedTab() }),
2837
+ /* @__PURE__ */ jsx(TabsContent, { value: "new", className: "space-y-4", children: renderNewTab() })
2838
+ ]
2839
+ }
2840
+ ),
2841
+ enableSolanaPay && /* @__PURE__ */ jsxs(Button, { className: "w-full", variant: "secondary", onClick: showSolanaView, children: [
2842
+ /* @__PURE__ */ jsx(Sparkles, { className: "mr-2 h-4 w-4" }),
2843
+ " Pay with Solana"
2844
+ ] })
2845
+ ] });
2846
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6 pt-4", children: [
2847
+ mode === "cards" && renderCardExperience(),
2848
+ mode === "cards" && enableAlternativePayments && /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-center text-sm text-muted-foreground", children: [
2849
+ /* @__PURE__ */ jsx(
2850
+ "button",
2851
+ {
2852
+ type: "button",
2853
+ className: "text-primary underline-offset-4 hover:underline disabled:opacity-60",
2854
+ onClick: handleAlternativePayment,
2855
+ disabled: flexFormLoading || !priceId,
2856
+ children: flexFormLoading ? "Preparing alternative checkout\u2026" : "Prefer a different processor? Pay with CCBill"
2857
+ }
2858
+ ),
2859
+ (alternativePaymentError || flexFormError) && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: alternativePaymentError || flexFormError })
2860
+ ] }),
2861
+ mode === "solana" && enableSolanaPay && /* @__PURE__ */ jsx(
2862
+ SolanaPaymentView,
2724
2863
  {
2725
- isOpen: solanaModalOpen,
2726
- onClose: () => setSolanaModalOpen(false),
2727
2864
  priceId,
2728
2865
  usdAmount,
2729
- onSuccess: (result) => {
2730
- setSolanaModalOpen(false);
2731
- onSolanaSuccess?.(result);
2866
+ onSuccess: handleSolanaSuccess,
2867
+ onError: handleSolanaError,
2868
+ onClose: exitSolanaView
2869
+ }
2870
+ )
2871
+ ] });
2872
+ };
2873
+ var SubscriptionSuccessDialog = ({
2874
+ open,
2875
+ planName = "Premium Plan",
2876
+ amountLabel = "$0.00",
2877
+ billingPeriodLabel = "billing period",
2878
+ onClose
2879
+ }) => {
2880
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (value) => {
2881
+ if (!value) onClose();
2882
+ }, children: /* @__PURE__ */ jsxs(DialogContent, { className: "w-full max-w-md overflow-hidden border border-border/70 bg-background/95 p-0 shadow-2xl", children: [
2883
+ /* @__PURE__ */ jsxs("div", { className: "bg-gradient-to-b from-primary/25 via-primary/10 to-background px-6 py-8 text-center", children: [
2884
+ /* @__PURE__ */ jsx("div", { className: "mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-background/60", children: /* @__PURE__ */ jsx(CheckCircle, { className: "h-10 w-10 text-primary" }) }),
2885
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
2886
+ /* @__PURE__ */ jsx(DialogTitle, { className: "text-2xl font-semibold text-foreground", children: "Subscription activated" }),
2887
+ /* @__PURE__ */ jsxs(DialogDescription, { className: "text-base text-muted-foreground", children: [
2888
+ "You now have access to ",
2889
+ planName,
2890
+ ". Billing: ",
2891
+ amountLabel,
2892
+ " / ",
2893
+ billingPeriodLabel,
2894
+ "."
2895
+ ] })
2896
+ ] })
2897
+ ] }),
2898
+ /* @__PURE__ */ jsx("div", { className: "px-6 py-6", children: /* @__PURE__ */ jsx(Button, { className: "w-full", onClick: onClose, children: "Continue exploring" }) })
2899
+ ] }) });
2900
+ };
2901
+ var SubscriptionCheckoutModal = ({
2902
+ open,
2903
+ onOpenChange,
2904
+ priceId,
2905
+ usdAmount = 0,
2906
+ planName,
2907
+ amountLabel,
2908
+ billingPeriodLabel,
2909
+ userEmail,
2910
+ provider = "mobius",
2911
+ onSuccess,
2912
+ enableSolanaPay = true,
2913
+ onSolanaSuccess,
2914
+ onSolanaError,
2915
+ initialMode = "cards"
2916
+ }) => {
2917
+ const [showSuccess, setShowSuccess] = useState(false);
2918
+ const { subscribeWithCard, subscribeWithSavedMethod } = useSubscriptionActions();
2919
+ const handleClose = useCallback(
2920
+ (nextOpen) => {
2921
+ onOpenChange(nextOpen);
2922
+ if (!nextOpen) setShowSuccess(false);
2923
+ },
2924
+ [onOpenChange]
2925
+ );
2926
+ const ensurePrice = () => {
2927
+ if (!priceId) throw new Error("Select a plan before subscribing.");
2928
+ return priceId;
2929
+ };
2930
+ const notifySuccess = (result) => {
2931
+ setShowSuccess(true);
2932
+ onSuccess?.();
2933
+ if (result && typeof window !== "undefined") {
2934
+ console.debug("[payments-ui] subscription success", result);
2935
+ }
2936
+ };
2937
+ const handleNewCardPayment = async ({ token, billing }) => {
2938
+ await subscribeWithCard({
2939
+ priceId: ensurePrice(),
2940
+ provider,
2941
+ paymentToken: token,
2942
+ billing
2943
+ });
2944
+ notifySuccess();
2945
+ };
2946
+ const handleSavedMethodPayment = async ({ paymentMethodId }) => {
2947
+ await subscribeWithSavedMethod({
2948
+ priceId: ensurePrice(),
2949
+ provider,
2950
+ paymentMethodId,
2951
+ email: userEmail ?? ""
2952
+ });
2953
+ notifySuccess();
2954
+ };
2955
+ const solanaSuccess = (result) => {
2956
+ notifySuccess(result);
2957
+ onSolanaSuccess?.(result);
2958
+ onOpenChange(false);
2959
+ };
2960
+ const solanaError = (error) => {
2961
+ onSolanaError?.(error);
2962
+ };
2963
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2964
+ /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsx(DialogContent, { className: "w-full max-w-3xl max-h-[90vh] overflow-y-auto rounded-md border border-border/60 bg-background p-0 [&::-webkit-scrollbar]:hidden", children: /* @__PURE__ */ jsxs("div", { className: "p-6 space-y-6", children: [
2965
+ !priceId && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [
2966
+ /* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
2967
+ " Select a subscription plan to continue."
2968
+ ] }),
2969
+ /* @__PURE__ */ jsx(
2970
+ PaymentExperience,
2971
+ {
2972
+ usdAmount,
2973
+ priceId: priceId ?? "",
2974
+ onSolanaSuccess: solanaSuccess,
2975
+ onSolanaError: solanaError,
2976
+ enableNewCard: Boolean(priceId),
2977
+ enableStoredMethods: Boolean(priceId),
2978
+ enableSolanaPay: enableSolanaPay && Boolean(priceId),
2979
+ onNewCardPayment: priceId ? handleNewCardPayment : void 0,
2980
+ onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
2981
+ initialMode
2982
+ }
2983
+ )
2984
+ ] }) }) }),
2985
+ /* @__PURE__ */ jsx(
2986
+ SubscriptionSuccessDialog,
2987
+ {
2988
+ open: showSuccess,
2989
+ onClose: () => setShowSuccess(false),
2990
+ planName,
2991
+ amountLabel: amountLabel ?? `$${usdAmount.toFixed(2)}`,
2992
+ billingPeriodLabel
2993
+ }
2994
+ )
2995
+ ] });
2996
+ };
2997
+ var wallets = [
2998
+ {
2999
+ id: "phantom",
3000
+ name: "Phantom",
3001
+ icon: "https://phantom.app/img/logo.png"
3002
+ },
3003
+ {
3004
+ id: "solflare",
3005
+ name: "Solflare",
3006
+ icon: "https://solflare.com/favicon.ico"
3007
+ }
3008
+ ];
3009
+ var WalletModal = ({ open, onOpenChange }) => {
3010
+ const [expandedWallet, setExpandedWallet] = useState(null);
3011
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "w-full max-w-lg max-h-[90vh] overflow-y-auto rounded-md border border-border/70 bg-background/95 p-0 shadow-2xl [&::-webkit-scrollbar]:hidden", children: [
3012
+ /* @__PURE__ */ jsxs(DialogHeader, { className: "border-b border-border/40 bg-gradient-to-r from-primary/10 via-background to-background px-6 py-5 text-left", children: [
3013
+ /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2 text-foreground", children: [
3014
+ /* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5 text-primary" }),
3015
+ " Connect a Solana wallet"
3016
+ ] }),
3017
+ /* @__PURE__ */ jsx(DialogDescription, { className: "text-sm text-muted-foreground", children: "Pick a supported wallet to link with Doujins. Verified wallets unlock Solana payments and withdrawals." })
3018
+ ] }),
3019
+ /* @__PURE__ */ jsxs("div", { className: "p-6 space-y-4", children: [
3020
+ wallets.map((wallet) => /* @__PURE__ */ jsxs(
3021
+ "div",
3022
+ {
3023
+ className: "rounded-2xl border border-border/60 bg-background/80 p-4 shadow-sm",
3024
+ children: [
3025
+ /* @__PURE__ */ jsxs(
3026
+ "button",
3027
+ {
3028
+ className: "flex w-full items-center justify-between",
3029
+ onClick: () => setExpandedWallet((prev) => prev === wallet.id ? null : wallet.id),
3030
+ children: [
3031
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-left", children: [
3032
+ /* @__PURE__ */ jsx("img", { src: wallet.icon, alt: wallet.name, className: "h-10 w-10 rounded-full" }),
3033
+ /* @__PURE__ */ jsxs("div", { children: [
3034
+ /* @__PURE__ */ jsx("p", { className: "text-base font-semibold text-foreground", children: wallet.name }),
3035
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Browser extension or mobile app" })
3036
+ ] })
3037
+ ] }),
3038
+ expandedWallet === wallet.id ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4 text-muted-foreground" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 text-muted-foreground" })
3039
+ ]
3040
+ }
3041
+ ),
3042
+ expandedWallet === wallet.id && /* @__PURE__ */ jsxs("div", { className: "mt-4 space-y-3 text-sm text-muted-foreground", children: [
3043
+ /* @__PURE__ */ jsxs("p", { children: [
3044
+ "Open the ",
3045
+ wallet.name,
3046
+ " wallet, approve the connection request, and confirm the signature prompt to finish linking."
3047
+ ] }),
3048
+ /* @__PURE__ */ jsxs(Button, { className: "w-full", variant: "outline", disabled: true, children: [
3049
+ "Connect with ",
3050
+ wallet.name,
3051
+ " (coming soon)"
3052
+ ] })
3053
+ ] })
3054
+ ]
2732
3055
  },
2733
- onError: onSolanaError
3056
+ wallet.id
3057
+ )),
3058
+ /* @__PURE__ */ jsx("div", { className: "rounded-2xl border border-border/60 bg-muted/10 p-4 text-xs text-muted-foreground", children: "Don\u2019t see your wallet? Additional providers will be added soon. Contact support if you need manual verification." })
3059
+ ] })
3060
+ ] }) });
3061
+ };
3062
+ var createDialogState = () => ({
3063
+ isOpen: false,
3064
+ props: null
3065
+ });
3066
+ var PaymentsDialogContext = createContext(void 0);
3067
+ var PaymentsDialogProvider = ({
3068
+ children
3069
+ }) => {
3070
+ const [checkoutState, setCheckoutState] = useState(
3071
+ () => createDialogState()
3072
+ );
3073
+ const [walletState, setWalletState] = useState(
3074
+ () => createDialogState()
3075
+ );
3076
+ const contextValue = useMemo(() => {
3077
+ const openCheckout = (options) => setCheckoutState({
3078
+ isOpen: true,
3079
+ props: options
3080
+ });
3081
+ return {
3082
+ checkout: {
3083
+ isOpen: checkoutState.isOpen,
3084
+ open: openCheckout,
3085
+ close: () => setCheckoutState(createDialogState())
3086
+ },
3087
+ solana: {
3088
+ isOpen: checkoutState.isOpen && checkoutState.props?.initialMode === "solana",
3089
+ open: (options) => openCheckout({
3090
+ priceId: options.priceId,
3091
+ usdAmount: options.usdAmount,
3092
+ enableSolanaPay: true,
3093
+ initialMode: "solana",
3094
+ onSolanaSuccess: options.onSuccess,
3095
+ onSolanaError: options.onError
3096
+ }),
3097
+ close: () => setCheckoutState(createDialogState())
3098
+ },
3099
+ wallet: {
3100
+ isOpen: walletState.isOpen,
3101
+ open: (options) => setWalletState({
3102
+ isOpen: true,
3103
+ props: options ?? null
3104
+ }),
3105
+ close: () => setWalletState(createDialogState())
3106
+ }
3107
+ };
3108
+ }, [checkoutState, walletState.isOpen]);
3109
+ return /* @__PURE__ */ jsxs(PaymentsDialogContext.Provider, { value: contextValue, children: [
3110
+ children,
3111
+ checkoutState.props && /* @__PURE__ */ jsx(
3112
+ SubscriptionCheckoutModal,
3113
+ {
3114
+ open: checkoutState.isOpen,
3115
+ onOpenChange: (open) => open ? setCheckoutState((prev) => ({ ...prev, isOpen: true })) : setCheckoutState(createDialogState()),
3116
+ ...checkoutState.props
3117
+ }
3118
+ ),
3119
+ /* @__PURE__ */ jsx(
3120
+ WalletModal,
3121
+ {
3122
+ open: walletState.isOpen,
3123
+ onOpenChange: (open) => open ? setWalletState((prev) => ({ ...prev, isOpen: true })) : setWalletState(createDialogState()),
3124
+ ...walletState.props ?? {}
2734
3125
  }
2735
3126
  )
2736
3127
  ] });
2737
3128
  };
3129
+ var usePaymentDialogs = () => {
3130
+ const context = useContext(PaymentsDialogContext);
3131
+ if (!context) {
3132
+ throw new Error("usePaymentDialogs must be used within PaymentProvider");
3133
+ }
3134
+ return context;
3135
+ };
3136
+ var PaymentContext = createContext(void 0);
3137
+ var PaymentProvider = ({
3138
+ config,
3139
+ runtime: runtimeProp,
3140
+ children
3141
+ }) => {
3142
+ const runtime = useMemo(
3143
+ () => runtimeProp ?? createPaymentsRuntime(config),
3144
+ [runtimeProp, config]
3145
+ );
3146
+ const solanaEndpoint = useMemo(() => {
3147
+ if (config.solana?.endpoint) return config.solana.endpoint;
3148
+ const network = config.solana?.network ?? WalletAdapterNetwork.Mainnet;
3149
+ return clusterApiUrl(network);
3150
+ }, [config.solana?.endpoint, config.solana?.network]);
3151
+ const walletAdapters = useMemo(() => {
3152
+ if (config.solana?.wallets?.length) {
3153
+ return config.solana.wallets;
3154
+ }
3155
+ return [
3156
+ new PhantomWalletAdapter(),
3157
+ new SolflareWalletAdapter(),
3158
+ new TrustWalletAdapter(),
3159
+ new CoinbaseWalletAdapter()
3160
+ ];
3161
+ }, [config.solana?.wallets]);
3162
+ const autoConnect = config.solana?.autoConnect ?? true;
3163
+ const value = useMemo(() => {
3164
+ return {
3165
+ config: runtime.config,
3166
+ fetcher: runtime.app.getFetcher(),
3167
+ resolveAuthToken: runtime.app.resolveAuthToken,
3168
+ app: runtime.app,
3169
+ services: runtime.services,
3170
+ queryClient: runtime.queryClient
3171
+ };
3172
+ }, [runtime]);
3173
+ useEffect(() => {
3174
+ if (!config.collectJsKey) return;
3175
+ loadCollectJs(config.collectJsKey);
3176
+ }, [config.collectJsKey]);
3177
+ return /* @__PURE__ */ jsx(PaymentContext.Provider, { value, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: runtime.queryClient, children: /* @__PURE__ */ jsx(ConnectionProvider, { endpoint: solanaEndpoint, config: { commitment: "confirmed" }, children: /* @__PURE__ */ jsx(WalletProvider, { wallets: walletAdapters, autoConnect, children: /* @__PURE__ */ jsx(WalletModalProvider, { children: /* @__PURE__ */ jsx(PaymentsDialogProvider, { children }) }) }) }) }) });
3178
+ };
3179
+ var usePaymentContext = () => {
3180
+ const context = useContext(PaymentContext);
3181
+ if (!context) {
3182
+ throw new Error("usePaymentContext must be used within a PaymentProvider");
3183
+ }
3184
+ return context;
3185
+ };
3186
+ var SolanaPaymentSelector = ({
3187
+ isOpen,
3188
+ onClose,
3189
+ ...props
3190
+ }) => {
3191
+ return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: (value) => value ? void 0 : onClose(), children: /* @__PURE__ */ jsx(DialogContent, { className: "w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-md border border-border/70 bg-background/95 p-0 shadow-2xl [&::-webkit-scrollbar]:hidden", children: /* @__PURE__ */ jsx(SolanaPaymentView, { ...props, onClose }) }) });
3192
+ };
2738
3193
  var Table = React3.forwardRef(
2739
3194
  ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2740
3195
  "table",
@@ -2919,7 +3374,7 @@ var CancelMembershipDialog = ({
2919
3374
  /* @__PURE__ */ jsx(Ban, { className: "mr-2 h-4 w-4" }),
2920
3375
  " Cancel Membership"
2921
3376
  ] }) }),
2922
- /* @__PURE__ */ jsxs(AlertDialogContent, { className: "max-h-[90vh] overflow-y-auto rounded-xl border border-border bg-background", children: [
3377
+ /* @__PURE__ */ jsxs(AlertDialogContent, { className: "max-h-[90vh] overflow-y-auto rounded-md border border-border bg-background", children: [
2923
3378
  /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
2924
3379
  /* @__PURE__ */ jsxs(AlertDialogTitle, { className: "flex items-center gap-2 text-lg font-semibold", children: [
2925
3380
  /* @__PURE__ */ jsx(TriangleAlert, { className: "h-5 w-5 text-destructive" }),
@@ -3860,65 +4315,26 @@ var SolanaWalletSection = ({
3860
4315
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
3861
4316
  /* @__PURE__ */ jsx(Button, { onClick: registerWallet, disabled: isRegistering || walletConnection.isConnecting, className: "flex-1 bg-primary text-primary-foreground", children: isRegistering ? /* @__PURE__ */ jsxs(Fragment, { children: [
3862
4317
  /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
3863
- " Registering..."
3864
- ] }) : "Register This Wallet" }),
3865
- /* @__PURE__ */ jsx(Button, { onClick: () => disconnect(), variant: "outline", className: "border-border", children: "Disconnect" })
3866
- ] })
3867
- ] }) : /* @__PURE__ */ jsx(WalletMultiButton, { className: "w-full !bg-primary text-primary-foreground" }) })
3868
- ] }) })
3869
- ] }),
3870
- /* @__PURE__ */ jsx(AlertDialog, { open: !!walletToDelete, onOpenChange: () => setWalletToDelete(null), children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [
3871
- /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
3872
- /* @__PURE__ */ jsx(AlertDialogTitle, { children: "Remove Wallet" }),
3873
- /* @__PURE__ */ jsx(AlertDialogDescription, { children: "Are you sure you want to remove this wallet from your account? This action cannot be undone." })
3874
- ] }),
3875
- /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [
3876
- /* @__PURE__ */ jsx(AlertDialogCancel, { children: "Cancel" }),
3877
- /* @__PURE__ */ jsx(AlertDialogAction, { onClick: () => walletToDelete && handleDeleteWallet(walletToDelete.id), className: "bg-destructive text-destructive-foreground", children: "Remove" })
3878
- ] })
3879
- ] }) })
3880
- ] });
3881
- };
3882
- var WalletManagement = (props) => /* @__PURE__ */ jsx(SolanaWalletSection, { ...props });
3883
- var wallets = [
3884
- {
3885
- id: "phantom",
3886
- name: "Phantom",
3887
- icon: "https://phantom.app/img/logo.png"
3888
- },
3889
- {
3890
- id: "solflare",
3891
- name: "Solflare",
3892
- icon: "https://solflare.com/favicon.ico"
3893
- }
3894
- ];
3895
- var WalletModal = ({ open, onOpenChange }) => {
3896
- const [expandedWallet, setExpandedWallet] = useState(null);
3897
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx(DialogContent, { className: "max-w-md border border-border bg-background", children: /* @__PURE__ */ jsx("div", { className: "space-y-4", children: wallets.map((wallet) => /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border/80", children: [
3898
- /* @__PURE__ */ jsxs(
3899
- "button",
3900
- {
3901
- className: "flex w-full items-center justify-between px-4 py-3",
3902
- onClick: () => setExpandedWallet((prev) => prev === wallet.id ? null : wallet.id),
3903
- children: [
3904
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-left", children: [
3905
- /* @__PURE__ */ jsx("img", { src: wallet.icon, alt: wallet.name, className: "h-8 w-8 rounded-full" }),
3906
- /* @__PURE__ */ jsxs("div", { children: [
3907
- /* @__PURE__ */ jsx("p", { className: "font-semibold", children: wallet.name }),
3908
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Connect via browser extension" })
3909
- ] })
3910
- ] }),
3911
- expandedWallet === wallet.id ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4 text-muted-foreground" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 text-muted-foreground" })
3912
- ]
3913
- }
3914
- ),
3915
- expandedWallet === wallet.id && /* @__PURE__ */ jsxs("div", { className: "border-t border-border/60 px-4 py-3 text-sm text-muted-foreground", children: [
3916
- "Follow the prompts in your ",
3917
- wallet.name,
3918
- " wallet to approve access."
3919
- ] })
3920
- ] }, wallet.id)) }) }) });
4318
+ " Registering..."
4319
+ ] }) : "Register This Wallet" }),
4320
+ /* @__PURE__ */ jsx(Button, { onClick: () => disconnect(), variant: "outline", className: "border-border", children: "Disconnect" })
4321
+ ] })
4322
+ ] }) : /* @__PURE__ */ jsx(WalletMultiButton, { className: "w-full !bg-primary text-primary-foreground" }) })
4323
+ ] }) })
4324
+ ] }),
4325
+ /* @__PURE__ */ jsx(AlertDialog, { open: !!walletToDelete, onOpenChange: () => setWalletToDelete(null), children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [
4326
+ /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
4327
+ /* @__PURE__ */ jsx(AlertDialogTitle, { children: "Remove Wallet" }),
4328
+ /* @__PURE__ */ jsx(AlertDialogDescription, { children: "Are you sure you want to remove this wallet from your account? This action cannot be undone." })
4329
+ ] }),
4330
+ /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [
4331
+ /* @__PURE__ */ jsx(AlertDialogCancel, { children: "Cancel" }),
4332
+ /* @__PURE__ */ jsx(AlertDialogAction, { onClick: () => walletToDelete && handleDeleteWallet(walletToDelete.id), className: "bg-destructive text-destructive-foreground", children: "Remove" })
4333
+ ] })
4334
+ ] }) })
4335
+ ] });
3921
4336
  };
4337
+ var WalletManagement = (props) => /* @__PURE__ */ jsx(SolanaWalletSection, { ...props });
3922
4338
  var Checkbox = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3923
4339
  CheckboxPrimitive.Root,
3924
4340
  {
@@ -3938,7 +4354,7 @@ var Checkbox = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__
3938
4354
  }
3939
4355
  ));
3940
4356
  Checkbox.displayName = CheckboxPrimitive.Root.displayName;
3941
- var initialState2 = {
4357
+ var initialState = {
3942
4358
  nameOnCard: "",
3943
4359
  cardNumber: "",
3944
4360
  expiration: "",
@@ -3946,7 +4362,7 @@ var initialState2 = {
3946
4362
  termsAccepted: false
3947
4363
  };
3948
4364
  var WalletDialog = ({ open, onOpenChange }) => {
3949
- const [form, setForm] = useState(initialState2);
4365
+ const [form, setForm] = useState(initialState);
3950
4366
  const [errors, setErrors] = useState({});
3951
4367
  const validators = useMemo(
3952
4368
  () => ({
@@ -3979,7 +4395,7 @@ var WalletDialog = ({ open, onOpenChange }) => {
3979
4395
  if (!validate()) return;
3980
4396
  console.log("[payments-ui] wallet dialog submit", form);
3981
4397
  onOpenChange(false);
3982
- setForm(initialState2);
4398
+ setForm(initialState);
3983
4399
  };
3984
4400
  return /* @__PURE__ */ jsx(AlertDialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(AlertDialogContent, { className: "max-h-[95vh] max-w-lg overflow-y-auto rounded-2xl border border-border bg-background", children: [
3985
4401
  /* @__PURE__ */ jsxs(AlertDialogHeader, { className: "border-b border-border/60 pb-4", children: [
@@ -4026,7 +4442,7 @@ var WalletDialog = ({ open, onOpenChange }) => {
4026
4442
  ] })
4027
4443
  ] })
4028
4444
  ] }),
4029
- /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-xl border border-border/70 bg-muted/10 p-4", children: [
4445
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-md border border-border/70 bg-muted/10 p-4", children: [
4030
4446
  /* @__PURE__ */ jsx(Checkbox, { id: "terms-agree", checked: form.termsAccepted, onCheckedChange: (checked) => updateField("termsAccepted", Boolean(checked)) }),
4031
4447
  /* @__PURE__ */ jsx(Label, { htmlFor: "terms-agree", className: "text-sm text-muted-foreground", children: "By completing this order, I confirm that I am 18 years or older and agree to your privacy policy and terms." })
4032
4448
  ] }),
@@ -4038,245 +4454,6 @@ var WalletDialog = ({ open, onOpenChange }) => {
4038
4454
  ] })
4039
4455
  ] }) });
4040
4456
  };
4041
- var SubscriptionSuccessDialog = ({
4042
- open,
4043
- planName = "Premium Plan",
4044
- amountLabel = "$0.00",
4045
- billingPeriodLabel = "billing period",
4046
- onClose
4047
- }) => {
4048
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (value) => {
4049
- if (!value) onClose();
4050
- }, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-sm text-center", children: [
4051
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
4052
- /* @__PURE__ */ jsxs(DialogTitle, { className: "flex flex-col items-center gap-3 text-foreground", children: [
4053
- /* @__PURE__ */ jsx(CheckCircle, { className: "h-10 w-10 text-primary" }),
4054
- "Subscription activated"
4055
- ] }),
4056
- /* @__PURE__ */ jsxs(DialogDescription, { className: "text-base text-muted-foreground", children: [
4057
- "You now have access to ",
4058
- planName,
4059
- ". Billing: ",
4060
- amountLabel,
4061
- " / ",
4062
- billingPeriodLabel,
4063
- "."
4064
- ] })
4065
- ] }),
4066
- /* @__PURE__ */ jsx(Button, { className: "mt-6 w-full", onClick: onClose, children: "Continue" })
4067
- ] }) });
4068
- };
4069
- var useSubscriptionActions = () => {
4070
- const { services } = usePaymentContext();
4071
- const ensurePrice = (priceId) => {
4072
- if (!priceId) {
4073
- throw new Error("payments-ui: priceId is required for subscription actions");
4074
- }
4075
- return priceId;
4076
- };
4077
- const subscribeWithCard = useCallback(
4078
- async ({
4079
- priceId,
4080
- processor = "nmi",
4081
- provider,
4082
- paymentToken,
4083
- billing
4084
- }) => {
4085
- const payload = {
4086
- priceId: ensurePrice(priceId),
4087
- paymentToken,
4088
- processor,
4089
- provider,
4090
- email: billing.email,
4091
- firstName: billing.firstName,
4092
- lastName: billing.lastName,
4093
- address1: billing.address1,
4094
- city: billing.city,
4095
- state: billing.stateRegion,
4096
- zipCode: billing.postalCode,
4097
- country: billing.country
4098
- };
4099
- return services.subscriptions.subscribe("nmi", payload);
4100
- },
4101
- [services]
4102
- );
4103
- const subscribeWithSavedMethod = useCallback(
4104
- async ({
4105
- priceId,
4106
- processor = "nmi",
4107
- provider,
4108
- paymentMethodId,
4109
- email
4110
- }) => {
4111
- const payload = {
4112
- priceId: ensurePrice(priceId),
4113
- paymentMethodId,
4114
- processor,
4115
- provider,
4116
- email
4117
- };
4118
- return services.subscriptions.subscribe("nmi", payload);
4119
- },
4120
- [services]
4121
- );
4122
- const subscribeWithCCBill = useCallback(
4123
- async ({
4124
- priceId,
4125
- email,
4126
- firstName,
4127
- lastName,
4128
- zipCode,
4129
- country,
4130
- processor = "ccbill"
4131
- }) => {
4132
- const payload = {
4133
- priceId: ensurePrice(priceId),
4134
- email,
4135
- firstName,
4136
- lastName,
4137
- zipCode,
4138
- country,
4139
- processor
4140
- };
4141
- return services.subscriptions.subscribe("ccbill", payload);
4142
- },
4143
- [services]
4144
- );
4145
- const generateFlexFormUrl = useCallback(
4146
- async ({
4147
- priceId,
4148
- firstName,
4149
- lastName,
4150
- address1,
4151
- city,
4152
- state,
4153
- zipCode,
4154
- country
4155
- }) => {
4156
- const payload = {
4157
- price_id: ensurePrice(priceId),
4158
- first_name: firstName,
4159
- last_name: lastName,
4160
- address1,
4161
- city,
4162
- state,
4163
- zip_code: zipCode,
4164
- country
4165
- };
4166
- return services.subscriptions.generateFlexFormUrl(payload);
4167
- },
4168
- [services]
4169
- );
4170
- return {
4171
- subscribeWithCard,
4172
- subscribeWithSavedMethod,
4173
- subscribeWithCCBill,
4174
- generateFlexFormUrl
4175
- };
4176
- };
4177
- var SubscriptionCheckoutModal = ({
4178
- open,
4179
- onOpenChange,
4180
- priceId,
4181
- usdAmount = 0,
4182
- planName,
4183
- amountLabel,
4184
- billingPeriodLabel,
4185
- userEmail,
4186
- provider = "mobius",
4187
- onSuccess,
4188
- enableSolanaPay = true
4189
- }) => {
4190
- const [showSuccess, setShowSuccess] = useState(false);
4191
- const { subscribeWithCard, subscribeWithSavedMethod } = useSubscriptionActions();
4192
- const handleClose = useCallback(
4193
- (nextOpen) => {
4194
- onOpenChange(nextOpen);
4195
- if (!nextOpen) {
4196
- setShowSuccess(false);
4197
- }
4198
- },
4199
- [onOpenChange]
4200
- );
4201
- const ensurePrice = () => {
4202
- if (!priceId) {
4203
- throw new Error("Select a plan before subscribing.");
4204
- }
4205
- return priceId;
4206
- };
4207
- const notifySuccess = (result) => {
4208
- setShowSuccess(true);
4209
- onSuccess?.();
4210
- if (result && typeof window !== "undefined") {
4211
- console.debug("[payments-ui] subscription success", result);
4212
- }
4213
- };
4214
- const handleNewCardPayment = async ({ token, billing }) => {
4215
- await subscribeWithCard({
4216
- priceId: ensurePrice(),
4217
- provider,
4218
- paymentToken: token,
4219
- billing
4220
- });
4221
- notifySuccess();
4222
- };
4223
- const handleSavedMethodPayment = async ({ paymentMethodId }) => {
4224
- await subscribeWithSavedMethod({
4225
- priceId: ensurePrice(),
4226
- provider,
4227
- paymentMethodId,
4228
- email: userEmail ?? ""
4229
- });
4230
- notifySuccess();
4231
- };
4232
- const solanaSuccess = (result) => {
4233
- notifySuccess(result);
4234
- onOpenChange(false);
4235
- };
4236
- const summary = useMemo(() => {
4237
- if (!planName && !amountLabel) return null;
4238
- return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border/60 bg-muted/10 p-3 text-sm text-muted-foreground", children: [
4239
- /* @__PURE__ */ jsx("p", { className: "font-medium text-foreground", children: planName ?? "Selected plan" }),
4240
- /* @__PURE__ */ jsxs("p", { children: [
4241
- amountLabel ?? `$${usdAmount.toFixed(2)}`,
4242
- " ",
4243
- billingPeriodLabel ? `/ ${billingPeriodLabel}` : ""
4244
- ] })
4245
- ] });
4246
- }, [planName, amountLabel, billingPeriodLabel, usdAmount]);
4247
- return /* @__PURE__ */ jsxs(Fragment, { children: [
4248
- /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-3xl", children: [
4249
- !priceId && /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [
4250
- /* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
4251
- " Select a subscription plan to continue."
4252
- ] }),
4253
- /* @__PURE__ */ jsx(
4254
- PaymentExperience,
4255
- {
4256
- priceId: priceId ?? "",
4257
- usdAmount,
4258
- checkoutSummary: summary,
4259
- onNewCardPayment: priceId ? handleNewCardPayment : void 0,
4260
- onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
4261
- enableNewCard: Boolean(priceId),
4262
- enableStoredMethods: Boolean(priceId),
4263
- enableSolanaPay: enableSolanaPay && Boolean(priceId),
4264
- onSolanaSuccess: solanaSuccess
4265
- }
4266
- )
4267
- ] }) }),
4268
- /* @__PURE__ */ jsx(
4269
- SubscriptionSuccessDialog,
4270
- {
4271
- open: showSuccess,
4272
- onClose: () => setShowSuccess(false),
4273
- planName,
4274
- amountLabel: amountLabel ?? `$${usdAmount.toFixed(2)}`,
4275
- billingPeriodLabel
4276
- }
4277
- )
4278
- ] });
4279
- };
4280
4457
  var useTokenBalance = (tokens) => {
4281
4458
  const { publicKey } = useWallet();
4282
4459
  const { connection } = useConnection();
@@ -4768,34 +4945,7 @@ var usePaymentStatus = (options = {}) => {
4768
4945
  isPending: getConfirmationStatus() === "pending"
4769
4946
  };
4770
4947
  };
4771
- var useAlternativePaymentProvider = () => {
4772
- const [isLoading, setIsLoading] = useState(false);
4773
- const [error, setError] = useState(null);
4774
- const { generateFlexFormUrl } = useSubscriptionActions();
4775
- const openFlexForm = useCallback(
4776
- async (payload) => {
4777
- setIsLoading(true);
4778
- setError(null);
4779
- try {
4780
- const response = await generateFlexFormUrl(payload);
4781
- if (response?.iframe_url) {
4782
- window.location.href = response.iframe_url;
4783
- } else {
4784
- throw new Error("Unable to launch payment provider.");
4785
- }
4786
- } catch (err) {
4787
- const message = err instanceof Error ? err.message : "Failed to open payment provider.";
4788
- setError(message);
4789
- console.error("[payments-ui] failed to open alternative payment provider", err);
4790
- } finally {
4791
- setIsLoading(false);
4792
- }
4793
- },
4794
- [generateFlexFormUrl]
4795
- );
4796
- return { openFlexForm, isLoading, error };
4797
- };
4798
4948
 
4799
- export { BillingHistory, CancelMembershipDialog, CardDetailsForm, CardPaymentService, EmptyWalletState, PaymentApp, PaymentExperience, PaymentMethodService, PaymentMethodsSection, PaymentProvider, SolanaPaymentSelector, SolanaPaymentService, SolanaWalletSection, SolanaWalletService, StoredPaymentMethods, SubscriptionCheckoutModal, SubscriptionService, SubscriptionSuccessDialog, TokenCatalog, WalletCard, WalletDialog, WalletGateway, WalletManagement, WalletModal, createPaymentStore, useAlternativePaymentProvider, useDirectWalletPayment, usePaymentContext, usePaymentMethodService, usePaymentMethods, usePaymentStatus, usePaymentStore, useSolanaDirectPayment, useSolanaQrPayment, useSolanaService, useSubscriptionActions, useSupportedTokens, useTokenBalance, useWalletConnection, useWalletList, useWalletVerification };
4949
+ export { BillingHistory, CancelMembershipDialog, CardDetailsForm, CardPaymentService, EmptyWalletState, PaymentApp, PaymentExperience, PaymentMethodService, PaymentMethodsSection, PaymentProvider, PaymentsDialogProvider, PaymentsRuntime, SolanaPaymentSelector, SolanaPaymentService, SolanaPaymentView, SolanaWalletSection, SolanaWalletService, StoredPaymentMethods, SubscriptionCheckoutModal, SubscriptionService, SubscriptionSuccessDialog, TokenCatalog, WalletCard, WalletDialog, WalletGateway, WalletManagement, WalletModal, createPaymentsRuntime, useAlternativePaymentProvider, useDirectWalletPayment, usePaymentContext, usePaymentDialogs, usePaymentMethodService, usePaymentMethods, usePaymentNotifications, usePaymentStatus, useSolanaDirectPayment, useSolanaQrPayment, useSolanaService, useSubscriptionActions, useSupportedTokens, useTokenBalance, useWalletConnection, useWalletList, useWalletVerification };
4800
4950
  //# sourceMappingURL=index.js.map
4801
4951
  //# sourceMappingURL=index.js.map