@doujins/payments-ui 0.0.12 → 0.0.13
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.cjs +960 -872
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +89 -78
- package/dist/index.d.ts +89 -78
- package/dist/index.js +964 -880
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
import * as React3 from 'react';
|
|
2
|
-
import { createContext, useMemo,
|
|
3
|
-
import {
|
|
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
|
|
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
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
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
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
}),
|
|
593
|
-
resetAll: () => set(initialState)
|
|
594
|
-
};
|
|
507
|
+
mutations: {
|
|
508
|
+
retry: 1
|
|
509
|
+
}
|
|
510
|
+
}
|
|
595
511
|
});
|
|
596
|
-
var
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
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-
|
|
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-
|
|
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
|
|
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: "
|
|
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-
|
|
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(
|
|
1451
|
-
/* @__PURE__ */ jsxs(
|
|
1452
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1453
|
-
/* @__PURE__ */
|
|
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(
|
|
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
|
-
|
|
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-[
|
|
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
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
var
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
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-
|
|
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
|
|
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
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
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
|
|
2276
|
+
}, [tokens, selectedTokenSymbol]);
|
|
2421
2277
|
const handlePaymentStart = useCallback(() => {
|
|
2422
|
-
|
|
2423
|
-
|
|
2278
|
+
setPaymentState("processing");
|
|
2279
|
+
setErrorMessage(null);
|
|
2280
|
+
notifyStatus("processing", { source: "solana" });
|
|
2281
|
+
}, [notifyStatus]);
|
|
2424
2282
|
const handlePaymentConfirming = useCallback(() => {
|
|
2425
|
-
|
|
2426
|
-
}, [
|
|
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
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
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
|
-
[
|
|
2311
|
+
[notifyStatus, notifySuccess, onSuccess]
|
|
2452
2312
|
);
|
|
2453
2313
|
const handlePaymentError = useCallback(
|
|
2454
2314
|
(error) => {
|
|
2455
|
-
|
|
2315
|
+
setPaymentState("error");
|
|
2316
|
+
setErrorMessage(error);
|
|
2317
|
+
notifyStatus("error", { source: "solana" });
|
|
2318
|
+
notifyError(error);
|
|
2456
2319
|
onError?.(error);
|
|
2457
2320
|
},
|
|
2458
|
-
[
|
|
2321
|
+
[notifyError, notifyStatus, onError]
|
|
2459
2322
|
);
|
|
2460
|
-
const
|
|
2461
|
-
|
|
2323
|
+
const resetState = useCallback(() => {
|
|
2324
|
+
setPaymentState("selecting");
|
|
2325
|
+
setErrorMessage(null);
|
|
2462
2326
|
setTransactionId(null);
|
|
2463
|
-
}, [
|
|
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
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
}, [paymentState, resetSolanaPayment, setTransactionId, onClose]);
|
|
2335
|
+
resetState();
|
|
2336
|
+
onClose?.();
|
|
2337
|
+
}, [paymentState, onClose, resetState]);
|
|
2472
2338
|
useEffect(() => {
|
|
2473
|
-
if (!
|
|
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
|
-
}, [
|
|
2484
|
-
const handleTokenChange = useCallback(
|
|
2485
|
-
(value)
|
|
2486
|
-
|
|
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
|
-
|
|
2356
|
+
setActiveTab("wallet");
|
|
2494
2357
|
}
|
|
2495
2358
|
if (!connected && wasConnectedRef.current) {
|
|
2496
|
-
|
|
2359
|
+
setActiveTab("qr");
|
|
2497
2360
|
}
|
|
2498
2361
|
wasConnectedRef.current = connected;
|
|
2499
|
-
}, [connected
|
|
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
|
-
|
|
2516
|
-
/* @__PURE__ */
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
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("
|
|
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(
|
|
2533
|
-
/* @__PURE__ */ jsx(
|
|
2534
|
-
/* @__PURE__ */
|
|
2535
|
-
token
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
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) =>
|
|
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/
|
|
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
|
-
"
|
|
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
|
-
"
|
|
2431
|
+
" QR Code"
|
|
2556
2432
|
] })
|
|
2557
2433
|
] }),
|
|
2558
|
-
/* @__PURE__ */
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
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,17 +2458,34 @@ var SolanaPaymentSelector = ({
|
|
|
2579
2458
|
) })
|
|
2580
2459
|
]
|
|
2581
2460
|
}
|
|
2582
|
-
)
|
|
2583
|
-
|
|
2584
|
-
] }) });
|
|
2461
|
+
) })
|
|
2462
|
+
] });
|
|
2585
2463
|
};
|
|
2586
|
-
return /* @__PURE__ */
|
|
2587
|
-
/* @__PURE__ */ jsxs(
|
|
2588
|
-
/* @__PURE__ */
|
|
2589
|
-
|
|
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
2490
|
var PaymentExperience = ({
|
|
2595
2491
|
priceId,
|
|
@@ -2599,142 +2495,608 @@ var PaymentExperience = ({
|
|
|
2599
2495
|
enableNewCard = true,
|
|
2600
2496
|
enableStoredMethods = true,
|
|
2601
2497
|
enableSolanaPay = true,
|
|
2602
|
-
checkoutSummary,
|
|
2603
2498
|
onSolanaSuccess,
|
|
2604
|
-
onSolanaError
|
|
2499
|
+
onSolanaError,
|
|
2500
|
+
initialMode = "cards"
|
|
2605
2501
|
}) => {
|
|
2606
2502
|
const showNewCard = enableNewCard && Boolean(onNewCardPayment);
|
|
2607
|
-
const showStored = enableStoredMethods;
|
|
2608
|
-
const
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
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);
|
|
2503
|
+
const showStored = enableStoredMethods && Boolean(onSavedMethodPayment);
|
|
2504
|
+
const defaultTab = showStored ? "saved" : "new";
|
|
2505
|
+
const [activeTab, setActiveTab] = useState(defaultTab);
|
|
2506
|
+
const [mode, setMode] = useState(
|
|
2507
|
+
() => initialMode === "solana" && enableSolanaPay ? "solana" : "cards"
|
|
2508
|
+
);
|
|
2509
|
+
const [selectedMethodId, setSelectedMethodId] = useState(null);
|
|
2510
|
+
const [savedStatus, setSavedStatus] = useState("idle");
|
|
2511
|
+
const [savedError, setSavedError] = useState(null);
|
|
2512
|
+
const [newCardStatus, setNewCardStatus] = useState("idle");
|
|
2513
|
+
const [newCardError, setNewCardError] = useState(null);
|
|
2514
|
+
const { notifyStatus, notifySuccess, notifyError } = usePaymentNotifications();
|
|
2515
|
+
useEffect(() => {
|
|
2516
|
+
setActiveTab(showStored ? "saved" : "new");
|
|
2517
|
+
}, [showStored]);
|
|
2518
|
+
useEffect(() => {
|
|
2519
|
+
if (!enableSolanaPay) {
|
|
2520
|
+
setMode("cards");
|
|
2521
|
+
return;
|
|
2638
2522
|
}
|
|
2639
|
-
|
|
2640
|
-
|
|
2523
|
+
if (initialMode === "solana") {
|
|
2524
|
+
setMode("solana");
|
|
2525
|
+
} else {
|
|
2526
|
+
setMode("cards");
|
|
2527
|
+
}
|
|
2528
|
+
}, [enableSolanaPay, initialMode]);
|
|
2529
|
+
const handleMethodSelect = useCallback((method) => {
|
|
2530
|
+
setSelectedMethodId(method.id);
|
|
2531
|
+
setSavedStatus("idle");
|
|
2532
|
+
setSavedError(null);
|
|
2533
|
+
}, []);
|
|
2534
|
+
const handleSavedPayment = useCallback(async () => {
|
|
2641
2535
|
if (!onSavedMethodPayment || !selectedMethodId) return;
|
|
2642
2536
|
try {
|
|
2643
|
-
|
|
2537
|
+
setSavedStatus("processing");
|
|
2538
|
+
setSavedError(null);
|
|
2539
|
+
notifyStatus("processing", { source: "saved-payment" });
|
|
2644
2540
|
await onSavedMethodPayment({
|
|
2645
2541
|
paymentMethodId: selectedMethodId,
|
|
2646
2542
|
amount: usdAmount
|
|
2647
2543
|
});
|
|
2648
|
-
|
|
2544
|
+
setSavedStatus("success");
|
|
2545
|
+
notifyStatus("success", { source: "saved-payment" });
|
|
2649
2546
|
} catch (error) {
|
|
2650
2547
|
const message = error instanceof Error ? error.message : "Unable to complete payment with saved card";
|
|
2651
|
-
|
|
2548
|
+
setSavedStatus("error");
|
|
2549
|
+
setSavedError(message);
|
|
2550
|
+
notifyStatus("error", { source: "saved-payment" });
|
|
2551
|
+
notifyError(message);
|
|
2552
|
+
}
|
|
2553
|
+
}, [notifyError, notifyStatus, onSavedMethodPayment, selectedMethodId, usdAmount]);
|
|
2554
|
+
const handleNewCardTokenize = useCallback(
|
|
2555
|
+
async (token, billing) => {
|
|
2556
|
+
if (!onNewCardPayment) return;
|
|
2557
|
+
try {
|
|
2558
|
+
setNewCardStatus("processing");
|
|
2559
|
+
setNewCardError(null);
|
|
2560
|
+
notifyStatus("processing", { source: "new-card" });
|
|
2561
|
+
await onNewCardPayment({ token, billing });
|
|
2562
|
+
setNewCardStatus("success");
|
|
2563
|
+
notifyStatus("success", { source: "new-card" });
|
|
2564
|
+
} catch (error) {
|
|
2565
|
+
const message = error instanceof Error ? error.message : "Unable to complete payment";
|
|
2566
|
+
setNewCardStatus("error");
|
|
2567
|
+
setNewCardError(message);
|
|
2568
|
+
notifyStatus("error", { source: "new-card" });
|
|
2569
|
+
notifyError(message);
|
|
2570
|
+
}
|
|
2571
|
+
},
|
|
2572
|
+
[notifyError, notifyStatus, onNewCardPayment]
|
|
2573
|
+
);
|
|
2574
|
+
const showSolanaView = useCallback(() => {
|
|
2575
|
+
if (!enableSolanaPay) return;
|
|
2576
|
+
setMode("solana");
|
|
2577
|
+
}, [enableSolanaPay]);
|
|
2578
|
+
const exitSolanaView = useCallback(() => {
|
|
2579
|
+
setMode("cards");
|
|
2580
|
+
}, []);
|
|
2581
|
+
const handleSolanaSuccess = useCallback(
|
|
2582
|
+
(result) => {
|
|
2583
|
+
onSolanaSuccess?.(result);
|
|
2584
|
+
exitSolanaView();
|
|
2585
|
+
},
|
|
2586
|
+
[exitSolanaView, onSolanaSuccess]
|
|
2587
|
+
);
|
|
2588
|
+
const handleSolanaError = useCallback(
|
|
2589
|
+
(error) => {
|
|
2590
|
+
onSolanaError?.(error);
|
|
2591
|
+
},
|
|
2592
|
+
[onSolanaError]
|
|
2593
|
+
);
|
|
2594
|
+
const renderSavedTab = () => {
|
|
2595
|
+
if (!showStored) {
|
|
2596
|
+
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." });
|
|
2652
2597
|
}
|
|
2598
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
2599
|
+
/* @__PURE__ */ jsx(
|
|
2600
|
+
StoredPaymentMethods,
|
|
2601
|
+
{
|
|
2602
|
+
heading: "Saved cards",
|
|
2603
|
+
selectedMethodId,
|
|
2604
|
+
onMethodSelect: handleMethodSelect,
|
|
2605
|
+
description: "Select one of your stored payment methods.",
|
|
2606
|
+
showAddButton: false
|
|
2607
|
+
}
|
|
2608
|
+
),
|
|
2609
|
+
/* @__PURE__ */ jsx(
|
|
2610
|
+
Button,
|
|
2611
|
+
{
|
|
2612
|
+
className: "w-full",
|
|
2613
|
+
disabled: !selectedMethodId || savedStatus === "processing",
|
|
2614
|
+
onClick: handleSavedPayment,
|
|
2615
|
+
children: savedStatus === "processing" ? "Processing\u2026" : "Pay with selected card"
|
|
2616
|
+
}
|
|
2617
|
+
),
|
|
2618
|
+
savedError && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: savedError })
|
|
2619
|
+
] });
|
|
2653
2620
|
};
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
/* @__PURE__ */
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2621
|
+
const renderNewTab = () => {
|
|
2622
|
+
if (!showNewCard) {
|
|
2623
|
+
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Select a subscription plan to add a new card." });
|
|
2624
|
+
}
|
|
2625
|
+
return /* @__PURE__ */ jsx(
|
|
2626
|
+
CardDetailsForm,
|
|
2627
|
+
{
|
|
2628
|
+
visible: true,
|
|
2629
|
+
submitLabel: "Pay now",
|
|
2630
|
+
externalError: newCardError,
|
|
2631
|
+
onTokenize: handleNewCardTokenize,
|
|
2632
|
+
submitting: newCardStatus === "processing"
|
|
2633
|
+
}
|
|
2634
|
+
);
|
|
2635
|
+
};
|
|
2636
|
+
const renderCardExperience = () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2637
|
+
/* @__PURE__ */ jsxs(
|
|
2638
|
+
Tabs,
|
|
2639
|
+
{
|
|
2640
|
+
value: activeTab,
|
|
2641
|
+
onValueChange: (value) => setActiveTab(value),
|
|
2642
|
+
className: "space-y-3",
|
|
2643
|
+
children: [
|
|
2644
|
+
/* @__PURE__ */ jsxs(TabsList, { className: "grid w-full grid-cols-2 border border-border/60", children: [
|
|
2645
|
+
/* @__PURE__ */ jsx(TabsTrigger, { value: "saved", disabled: !showStored, children: "Use saved card" }),
|
|
2646
|
+
/* @__PURE__ */ jsx(TabsTrigger, { value: "new", disabled: !showNewCard, children: "Add new card" })
|
|
2661
2647
|
] }),
|
|
2662
|
-
/* @__PURE__ */
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
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,
|
|
2648
|
+
/* @__PURE__ */ jsx(TabsContent, { value: "saved", className: "space-y-4", children: renderSavedTab() }),
|
|
2649
|
+
/* @__PURE__ */ jsx(TabsContent, { value: "new", className: "space-y-4", children: renderNewTab() })
|
|
2650
|
+
]
|
|
2651
|
+
}
|
|
2652
|
+
),
|
|
2653
|
+
enableSolanaPay && /* @__PURE__ */ jsxs(Button, { className: "w-full", variant: "secondary", onClick: showSolanaView, children: [
|
|
2654
|
+
/* @__PURE__ */ jsx(Sparkles, { className: "mr-2 h-4 w-4" }),
|
|
2655
|
+
" Pay with Solana"
|
|
2656
|
+
] })
|
|
2657
|
+
] });
|
|
2658
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6 pt-4", children: [
|
|
2659
|
+
mode === "cards" && renderCardExperience(),
|
|
2660
|
+
mode === "solana" && enableSolanaPay && /* @__PURE__ */ jsx(
|
|
2661
|
+
SolanaPaymentView,
|
|
2724
2662
|
{
|
|
2725
|
-
isOpen: solanaModalOpen,
|
|
2726
|
-
onClose: () => setSolanaModalOpen(false),
|
|
2727
2663
|
priceId,
|
|
2728
2664
|
usdAmount,
|
|
2729
|
-
onSuccess:
|
|
2730
|
-
|
|
2731
|
-
|
|
2665
|
+
onSuccess: handleSolanaSuccess,
|
|
2666
|
+
onError: handleSolanaError,
|
|
2667
|
+
onClose: exitSolanaView
|
|
2668
|
+
}
|
|
2669
|
+
)
|
|
2670
|
+
] });
|
|
2671
|
+
};
|
|
2672
|
+
var SubscriptionSuccessDialog = ({
|
|
2673
|
+
open,
|
|
2674
|
+
planName = "Premium Plan",
|
|
2675
|
+
amountLabel = "$0.00",
|
|
2676
|
+
billingPeriodLabel = "billing period",
|
|
2677
|
+
onClose
|
|
2678
|
+
}) => {
|
|
2679
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (value) => {
|
|
2680
|
+
if (!value) onClose();
|
|
2681
|
+
}, children: /* @__PURE__ */ jsxs(DialogContent, { className: "w-full max-w-md overflow-hidden border border-border/70 bg-background/95 p-0 shadow-2xl", children: [
|
|
2682
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-gradient-to-b from-primary/25 via-primary/10 to-background px-6 py-8 text-center", children: [
|
|
2683
|
+
/* @__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" }) }),
|
|
2684
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2685
|
+
/* @__PURE__ */ jsx(DialogTitle, { className: "text-2xl font-semibold text-foreground", children: "Subscription activated" }),
|
|
2686
|
+
/* @__PURE__ */ jsxs(DialogDescription, { className: "text-base text-muted-foreground", children: [
|
|
2687
|
+
"You now have access to ",
|
|
2688
|
+
planName,
|
|
2689
|
+
". Billing: ",
|
|
2690
|
+
amountLabel,
|
|
2691
|
+
" / ",
|
|
2692
|
+
billingPeriodLabel,
|
|
2693
|
+
"."
|
|
2694
|
+
] })
|
|
2695
|
+
] })
|
|
2696
|
+
] }),
|
|
2697
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-6", children: /* @__PURE__ */ jsx(Button, { className: "w-full", onClick: onClose, children: "Continue exploring" }) })
|
|
2698
|
+
] }) });
|
|
2699
|
+
};
|
|
2700
|
+
var useSubscriptionActions = () => {
|
|
2701
|
+
const { services } = usePaymentContext();
|
|
2702
|
+
const ensurePrice = (priceId) => {
|
|
2703
|
+
if (!priceId) {
|
|
2704
|
+
throw new Error("payments-ui: priceId is required for subscription actions");
|
|
2705
|
+
}
|
|
2706
|
+
return priceId;
|
|
2707
|
+
};
|
|
2708
|
+
const subscribeWithCard = useCallback(
|
|
2709
|
+
async ({
|
|
2710
|
+
priceId,
|
|
2711
|
+
processor = "nmi",
|
|
2712
|
+
provider,
|
|
2713
|
+
paymentToken,
|
|
2714
|
+
billing
|
|
2715
|
+
}) => {
|
|
2716
|
+
const payload = {
|
|
2717
|
+
priceId: ensurePrice(priceId),
|
|
2718
|
+
paymentToken,
|
|
2719
|
+
processor,
|
|
2720
|
+
provider,
|
|
2721
|
+
email: billing.email,
|
|
2722
|
+
firstName: billing.firstName,
|
|
2723
|
+
lastName: billing.lastName,
|
|
2724
|
+
address1: billing.address1,
|
|
2725
|
+
city: billing.city,
|
|
2726
|
+
state: billing.stateRegion,
|
|
2727
|
+
zipCode: billing.postalCode,
|
|
2728
|
+
country: billing.country
|
|
2729
|
+
};
|
|
2730
|
+
return services.subscriptions.subscribe("nmi", payload);
|
|
2731
|
+
},
|
|
2732
|
+
[services]
|
|
2733
|
+
);
|
|
2734
|
+
const subscribeWithSavedMethod = useCallback(
|
|
2735
|
+
async ({
|
|
2736
|
+
priceId,
|
|
2737
|
+
processor = "nmi",
|
|
2738
|
+
provider,
|
|
2739
|
+
paymentMethodId,
|
|
2740
|
+
email
|
|
2741
|
+
}) => {
|
|
2742
|
+
const payload = {
|
|
2743
|
+
priceId: ensurePrice(priceId),
|
|
2744
|
+
paymentMethodId,
|
|
2745
|
+
processor,
|
|
2746
|
+
provider,
|
|
2747
|
+
email
|
|
2748
|
+
};
|
|
2749
|
+
return services.subscriptions.subscribe("nmi", payload);
|
|
2750
|
+
},
|
|
2751
|
+
[services]
|
|
2752
|
+
);
|
|
2753
|
+
const subscribeWithCCBill = useCallback(
|
|
2754
|
+
async ({
|
|
2755
|
+
priceId,
|
|
2756
|
+
email,
|
|
2757
|
+
firstName,
|
|
2758
|
+
lastName,
|
|
2759
|
+
zipCode,
|
|
2760
|
+
country,
|
|
2761
|
+
processor = "ccbill"
|
|
2762
|
+
}) => {
|
|
2763
|
+
const payload = {
|
|
2764
|
+
priceId: ensurePrice(priceId),
|
|
2765
|
+
email,
|
|
2766
|
+
firstName,
|
|
2767
|
+
lastName,
|
|
2768
|
+
zipCode,
|
|
2769
|
+
country,
|
|
2770
|
+
processor
|
|
2771
|
+
};
|
|
2772
|
+
return services.subscriptions.subscribe("ccbill", payload);
|
|
2773
|
+
},
|
|
2774
|
+
[services]
|
|
2775
|
+
);
|
|
2776
|
+
const generateFlexFormUrl = useCallback(
|
|
2777
|
+
async ({
|
|
2778
|
+
priceId,
|
|
2779
|
+
firstName,
|
|
2780
|
+
lastName,
|
|
2781
|
+
address1,
|
|
2782
|
+
city,
|
|
2783
|
+
state,
|
|
2784
|
+
zipCode,
|
|
2785
|
+
country
|
|
2786
|
+
}) => {
|
|
2787
|
+
const payload = {
|
|
2788
|
+
price_id: ensurePrice(priceId),
|
|
2789
|
+
first_name: firstName,
|
|
2790
|
+
last_name: lastName,
|
|
2791
|
+
address1,
|
|
2792
|
+
city,
|
|
2793
|
+
state,
|
|
2794
|
+
zip_code: zipCode,
|
|
2795
|
+
country
|
|
2796
|
+
};
|
|
2797
|
+
return services.subscriptions.generateFlexFormUrl(payload);
|
|
2798
|
+
},
|
|
2799
|
+
[services]
|
|
2800
|
+
);
|
|
2801
|
+
return {
|
|
2802
|
+
subscribeWithCard,
|
|
2803
|
+
subscribeWithSavedMethod,
|
|
2804
|
+
subscribeWithCCBill,
|
|
2805
|
+
generateFlexFormUrl
|
|
2806
|
+
};
|
|
2807
|
+
};
|
|
2808
|
+
var SubscriptionCheckoutModal = ({
|
|
2809
|
+
open,
|
|
2810
|
+
onOpenChange,
|
|
2811
|
+
priceId,
|
|
2812
|
+
usdAmount = 0,
|
|
2813
|
+
planName,
|
|
2814
|
+
amountLabel,
|
|
2815
|
+
billingPeriodLabel,
|
|
2816
|
+
userEmail,
|
|
2817
|
+
provider = "mobius",
|
|
2818
|
+
onSuccess,
|
|
2819
|
+
enableSolanaPay = true,
|
|
2820
|
+
onSolanaSuccess,
|
|
2821
|
+
onSolanaError,
|
|
2822
|
+
initialMode = "cards"
|
|
2823
|
+
}) => {
|
|
2824
|
+
const [showSuccess, setShowSuccess] = useState(false);
|
|
2825
|
+
const { subscribeWithCard, subscribeWithSavedMethod } = useSubscriptionActions();
|
|
2826
|
+
const handleClose = useCallback(
|
|
2827
|
+
(nextOpen) => {
|
|
2828
|
+
onOpenChange(nextOpen);
|
|
2829
|
+
if (!nextOpen) setShowSuccess(false);
|
|
2830
|
+
},
|
|
2831
|
+
[onOpenChange]
|
|
2832
|
+
);
|
|
2833
|
+
const ensurePrice = () => {
|
|
2834
|
+
if (!priceId) throw new Error("Select a plan before subscribing.");
|
|
2835
|
+
return priceId;
|
|
2836
|
+
};
|
|
2837
|
+
const notifySuccess = (result) => {
|
|
2838
|
+
setShowSuccess(true);
|
|
2839
|
+
onSuccess?.();
|
|
2840
|
+
if (result && typeof window !== "undefined") {
|
|
2841
|
+
console.debug("[payments-ui] subscription success", result);
|
|
2842
|
+
}
|
|
2843
|
+
};
|
|
2844
|
+
const handleNewCardPayment = async ({ token, billing }) => {
|
|
2845
|
+
await subscribeWithCard({
|
|
2846
|
+
priceId: ensurePrice(),
|
|
2847
|
+
provider,
|
|
2848
|
+
paymentToken: token,
|
|
2849
|
+
billing
|
|
2850
|
+
});
|
|
2851
|
+
notifySuccess();
|
|
2852
|
+
};
|
|
2853
|
+
const handleSavedMethodPayment = async ({ paymentMethodId }) => {
|
|
2854
|
+
await subscribeWithSavedMethod({
|
|
2855
|
+
priceId: ensurePrice(),
|
|
2856
|
+
provider,
|
|
2857
|
+
paymentMethodId,
|
|
2858
|
+
email: userEmail ?? ""
|
|
2859
|
+
});
|
|
2860
|
+
notifySuccess();
|
|
2861
|
+
};
|
|
2862
|
+
const solanaSuccess = (result) => {
|
|
2863
|
+
notifySuccess(result);
|
|
2864
|
+
onSolanaSuccess?.(result);
|
|
2865
|
+
onOpenChange(false);
|
|
2866
|
+
};
|
|
2867
|
+
const solanaError = (error) => {
|
|
2868
|
+
onSolanaError?.(error);
|
|
2869
|
+
};
|
|
2870
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2871
|
+
/* @__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: [
|
|
2872
|
+
!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: [
|
|
2873
|
+
/* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
|
|
2874
|
+
" Select a subscription plan to continue."
|
|
2875
|
+
] }),
|
|
2876
|
+
/* @__PURE__ */ jsx(
|
|
2877
|
+
PaymentExperience,
|
|
2878
|
+
{
|
|
2879
|
+
usdAmount,
|
|
2880
|
+
priceId: priceId ?? "",
|
|
2881
|
+
onSolanaSuccess: solanaSuccess,
|
|
2882
|
+
onSolanaError: solanaError,
|
|
2883
|
+
enableNewCard: Boolean(priceId),
|
|
2884
|
+
enableStoredMethods: Boolean(priceId),
|
|
2885
|
+
enableSolanaPay: enableSolanaPay && Boolean(priceId),
|
|
2886
|
+
onNewCardPayment: priceId ? handleNewCardPayment : void 0,
|
|
2887
|
+
onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
|
|
2888
|
+
initialMode
|
|
2889
|
+
}
|
|
2890
|
+
)
|
|
2891
|
+
] }) }) }),
|
|
2892
|
+
/* @__PURE__ */ jsx(
|
|
2893
|
+
SubscriptionSuccessDialog,
|
|
2894
|
+
{
|
|
2895
|
+
open: showSuccess,
|
|
2896
|
+
onClose: () => setShowSuccess(false),
|
|
2897
|
+
planName,
|
|
2898
|
+
amountLabel: amountLabel ?? `$${usdAmount.toFixed(2)}`,
|
|
2899
|
+
billingPeriodLabel
|
|
2900
|
+
}
|
|
2901
|
+
)
|
|
2902
|
+
] });
|
|
2903
|
+
};
|
|
2904
|
+
var wallets = [
|
|
2905
|
+
{
|
|
2906
|
+
id: "phantom",
|
|
2907
|
+
name: "Phantom",
|
|
2908
|
+
icon: "https://phantom.app/img/logo.png"
|
|
2909
|
+
},
|
|
2910
|
+
{
|
|
2911
|
+
id: "solflare",
|
|
2912
|
+
name: "Solflare",
|
|
2913
|
+
icon: "https://solflare.com/favicon.ico"
|
|
2914
|
+
}
|
|
2915
|
+
];
|
|
2916
|
+
var WalletModal = ({ open, onOpenChange }) => {
|
|
2917
|
+
const [expandedWallet, setExpandedWallet] = useState(null);
|
|
2918
|
+
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: [
|
|
2919
|
+
/* @__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: [
|
|
2920
|
+
/* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2 text-foreground", children: [
|
|
2921
|
+
/* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5 text-primary" }),
|
|
2922
|
+
" Connect a Solana wallet"
|
|
2923
|
+
] }),
|
|
2924
|
+
/* @__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." })
|
|
2925
|
+
] }),
|
|
2926
|
+
/* @__PURE__ */ jsxs("div", { className: "p-6 space-y-4", children: [
|
|
2927
|
+
wallets.map((wallet) => /* @__PURE__ */ jsxs(
|
|
2928
|
+
"div",
|
|
2929
|
+
{
|
|
2930
|
+
className: "rounded-2xl border border-border/60 bg-background/80 p-4 shadow-sm",
|
|
2931
|
+
children: [
|
|
2932
|
+
/* @__PURE__ */ jsxs(
|
|
2933
|
+
"button",
|
|
2934
|
+
{
|
|
2935
|
+
className: "flex w-full items-center justify-between",
|
|
2936
|
+
onClick: () => setExpandedWallet((prev) => prev === wallet.id ? null : wallet.id),
|
|
2937
|
+
children: [
|
|
2938
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-left", children: [
|
|
2939
|
+
/* @__PURE__ */ jsx("img", { src: wallet.icon, alt: wallet.name, className: "h-10 w-10 rounded-full" }),
|
|
2940
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2941
|
+
/* @__PURE__ */ jsx("p", { className: "text-base font-semibold text-foreground", children: wallet.name }),
|
|
2942
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Browser extension or mobile app" })
|
|
2943
|
+
] })
|
|
2944
|
+
] }),
|
|
2945
|
+
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" })
|
|
2946
|
+
]
|
|
2947
|
+
}
|
|
2948
|
+
),
|
|
2949
|
+
expandedWallet === wallet.id && /* @__PURE__ */ jsxs("div", { className: "mt-4 space-y-3 text-sm text-muted-foreground", children: [
|
|
2950
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
2951
|
+
"Open the ",
|
|
2952
|
+
wallet.name,
|
|
2953
|
+
" wallet, approve the connection request, and confirm the signature prompt to finish linking."
|
|
2954
|
+
] }),
|
|
2955
|
+
/* @__PURE__ */ jsxs(Button, { className: "w-full", variant: "outline", disabled: true, children: [
|
|
2956
|
+
"Connect with ",
|
|
2957
|
+
wallet.name,
|
|
2958
|
+
" (coming soon)"
|
|
2959
|
+
] })
|
|
2960
|
+
] })
|
|
2961
|
+
]
|
|
2732
2962
|
},
|
|
2733
|
-
|
|
2963
|
+
wallet.id
|
|
2964
|
+
)),
|
|
2965
|
+
/* @__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." })
|
|
2966
|
+
] })
|
|
2967
|
+
] }) });
|
|
2968
|
+
};
|
|
2969
|
+
var createDialogState = () => ({
|
|
2970
|
+
isOpen: false,
|
|
2971
|
+
props: null
|
|
2972
|
+
});
|
|
2973
|
+
var PaymentsDialogContext = createContext(void 0);
|
|
2974
|
+
var PaymentsDialogProvider = ({
|
|
2975
|
+
children
|
|
2976
|
+
}) => {
|
|
2977
|
+
const [checkoutState, setCheckoutState] = useState(
|
|
2978
|
+
() => createDialogState()
|
|
2979
|
+
);
|
|
2980
|
+
const [walletState, setWalletState] = useState(
|
|
2981
|
+
() => createDialogState()
|
|
2982
|
+
);
|
|
2983
|
+
const contextValue = useMemo(() => {
|
|
2984
|
+
const openCheckout = (options) => setCheckoutState({
|
|
2985
|
+
isOpen: true,
|
|
2986
|
+
props: options
|
|
2987
|
+
});
|
|
2988
|
+
return {
|
|
2989
|
+
checkout: {
|
|
2990
|
+
isOpen: checkoutState.isOpen,
|
|
2991
|
+
open: openCheckout,
|
|
2992
|
+
close: () => setCheckoutState(createDialogState())
|
|
2993
|
+
},
|
|
2994
|
+
solana: {
|
|
2995
|
+
isOpen: checkoutState.isOpen && checkoutState.props?.initialMode === "solana",
|
|
2996
|
+
open: (options) => openCheckout({
|
|
2997
|
+
priceId: options.priceId,
|
|
2998
|
+
usdAmount: options.usdAmount,
|
|
2999
|
+
enableSolanaPay: true,
|
|
3000
|
+
initialMode: "solana",
|
|
3001
|
+
onSolanaSuccess: options.onSuccess,
|
|
3002
|
+
onSolanaError: options.onError
|
|
3003
|
+
}),
|
|
3004
|
+
close: () => setCheckoutState(createDialogState())
|
|
3005
|
+
},
|
|
3006
|
+
wallet: {
|
|
3007
|
+
isOpen: walletState.isOpen,
|
|
3008
|
+
open: (options) => setWalletState({
|
|
3009
|
+
isOpen: true,
|
|
3010
|
+
props: options ?? null
|
|
3011
|
+
}),
|
|
3012
|
+
close: () => setWalletState(createDialogState())
|
|
3013
|
+
}
|
|
3014
|
+
};
|
|
3015
|
+
}, [checkoutState, walletState.isOpen]);
|
|
3016
|
+
return /* @__PURE__ */ jsxs(PaymentsDialogContext.Provider, { value: contextValue, children: [
|
|
3017
|
+
children,
|
|
3018
|
+
checkoutState.props && /* @__PURE__ */ jsx(
|
|
3019
|
+
SubscriptionCheckoutModal,
|
|
3020
|
+
{
|
|
3021
|
+
open: checkoutState.isOpen,
|
|
3022
|
+
onOpenChange: (open) => open ? setCheckoutState((prev) => ({ ...prev, isOpen: true })) : setCheckoutState(createDialogState()),
|
|
3023
|
+
...checkoutState.props
|
|
3024
|
+
}
|
|
3025
|
+
),
|
|
3026
|
+
/* @__PURE__ */ jsx(
|
|
3027
|
+
WalletModal,
|
|
3028
|
+
{
|
|
3029
|
+
open: walletState.isOpen,
|
|
3030
|
+
onOpenChange: (open) => open ? setWalletState((prev) => ({ ...prev, isOpen: true })) : setWalletState(createDialogState()),
|
|
3031
|
+
...walletState.props ?? {}
|
|
2734
3032
|
}
|
|
2735
3033
|
)
|
|
2736
3034
|
] });
|
|
2737
3035
|
};
|
|
3036
|
+
var usePaymentDialogs = () => {
|
|
3037
|
+
const context = useContext(PaymentsDialogContext);
|
|
3038
|
+
if (!context) {
|
|
3039
|
+
throw new Error("usePaymentDialogs must be used within PaymentProvider");
|
|
3040
|
+
}
|
|
3041
|
+
return context;
|
|
3042
|
+
};
|
|
3043
|
+
var PaymentContext = createContext(void 0);
|
|
3044
|
+
var PaymentProvider = ({
|
|
3045
|
+
config,
|
|
3046
|
+
runtime: runtimeProp,
|
|
3047
|
+
children
|
|
3048
|
+
}) => {
|
|
3049
|
+
const runtime = useMemo(
|
|
3050
|
+
() => runtimeProp ?? createPaymentsRuntime(config),
|
|
3051
|
+
[runtimeProp, config]
|
|
3052
|
+
);
|
|
3053
|
+
const solanaEndpoint = useMemo(() => {
|
|
3054
|
+
if (config.solana?.endpoint) return config.solana.endpoint;
|
|
3055
|
+
const network = config.solana?.network ?? WalletAdapterNetwork.Mainnet;
|
|
3056
|
+
return clusterApiUrl(network);
|
|
3057
|
+
}, [config.solana?.endpoint, config.solana?.network]);
|
|
3058
|
+
const walletAdapters = useMemo(() => {
|
|
3059
|
+
if (config.solana?.wallets?.length) {
|
|
3060
|
+
return config.solana.wallets;
|
|
3061
|
+
}
|
|
3062
|
+
return [
|
|
3063
|
+
new PhantomWalletAdapter(),
|
|
3064
|
+
new SolflareWalletAdapter(),
|
|
3065
|
+
new TrustWalletAdapter(),
|
|
3066
|
+
new CoinbaseWalletAdapter()
|
|
3067
|
+
];
|
|
3068
|
+
}, [config.solana?.wallets]);
|
|
3069
|
+
const autoConnect = config.solana?.autoConnect ?? true;
|
|
3070
|
+
const value = useMemo(() => {
|
|
3071
|
+
return {
|
|
3072
|
+
config: runtime.config,
|
|
3073
|
+
fetcher: runtime.app.getFetcher(),
|
|
3074
|
+
resolveAuthToken: runtime.app.resolveAuthToken,
|
|
3075
|
+
app: runtime.app,
|
|
3076
|
+
services: runtime.services,
|
|
3077
|
+
queryClient: runtime.queryClient
|
|
3078
|
+
};
|
|
3079
|
+
}, [runtime]);
|
|
3080
|
+
useEffect(() => {
|
|
3081
|
+
if (!config.collectJsKey) return;
|
|
3082
|
+
loadCollectJs(config.collectJsKey);
|
|
3083
|
+
}, [config.collectJsKey]);
|
|
3084
|
+
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 }) }) }) }) }) });
|
|
3085
|
+
};
|
|
3086
|
+
var usePaymentContext = () => {
|
|
3087
|
+
const context = useContext(PaymentContext);
|
|
3088
|
+
if (!context) {
|
|
3089
|
+
throw new Error("usePaymentContext must be used within a PaymentProvider");
|
|
3090
|
+
}
|
|
3091
|
+
return context;
|
|
3092
|
+
};
|
|
3093
|
+
var SolanaPaymentSelector = ({
|
|
3094
|
+
isOpen,
|
|
3095
|
+
onClose,
|
|
3096
|
+
...props
|
|
3097
|
+
}) => {
|
|
3098
|
+
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 }) }) });
|
|
3099
|
+
};
|
|
2738
3100
|
var Table = React3.forwardRef(
|
|
2739
3101
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2740
3102
|
"table",
|
|
@@ -2919,7 +3281,7 @@ var CancelMembershipDialog = ({
|
|
|
2919
3281
|
/* @__PURE__ */ jsx(Ban, { className: "mr-2 h-4 w-4" }),
|
|
2920
3282
|
" Cancel Membership"
|
|
2921
3283
|
] }) }),
|
|
2922
|
-
/* @__PURE__ */ jsxs(AlertDialogContent, { className: "max-h-[90vh] overflow-y-auto rounded-
|
|
3284
|
+
/* @__PURE__ */ jsxs(AlertDialogContent, { className: "max-h-[90vh] overflow-y-auto rounded-md border border-border bg-background", children: [
|
|
2923
3285
|
/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
|
|
2924
3286
|
/* @__PURE__ */ jsxs(AlertDialogTitle, { className: "flex items-center gap-2 text-lg font-semibold", children: [
|
|
2925
3287
|
/* @__PURE__ */ jsx(TriangleAlert, { className: "h-5 w-5 text-destructive" }),
|
|
@@ -3880,45 +4242,6 @@ var SolanaWalletSection = ({
|
|
|
3880
4242
|
] });
|
|
3881
4243
|
};
|
|
3882
4244
|
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)) }) }) });
|
|
3921
|
-
};
|
|
3922
4245
|
var Checkbox = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
3923
4246
|
CheckboxPrimitive.Root,
|
|
3924
4247
|
{
|
|
@@ -3938,7 +4261,7 @@ var Checkbox = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
3938
4261
|
}
|
|
3939
4262
|
));
|
|
3940
4263
|
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
3941
|
-
var
|
|
4264
|
+
var initialState = {
|
|
3942
4265
|
nameOnCard: "",
|
|
3943
4266
|
cardNumber: "",
|
|
3944
4267
|
expiration: "",
|
|
@@ -3946,7 +4269,7 @@ var initialState2 = {
|
|
|
3946
4269
|
termsAccepted: false
|
|
3947
4270
|
};
|
|
3948
4271
|
var WalletDialog = ({ open, onOpenChange }) => {
|
|
3949
|
-
const [form, setForm] = useState(
|
|
4272
|
+
const [form, setForm] = useState(initialState);
|
|
3950
4273
|
const [errors, setErrors] = useState({});
|
|
3951
4274
|
const validators = useMemo(
|
|
3952
4275
|
() => ({
|
|
@@ -3979,7 +4302,7 @@ var WalletDialog = ({ open, onOpenChange }) => {
|
|
|
3979
4302
|
if (!validate()) return;
|
|
3980
4303
|
console.log("[payments-ui] wallet dialog submit", form);
|
|
3981
4304
|
onOpenChange(false);
|
|
3982
|
-
setForm(
|
|
4305
|
+
setForm(initialState);
|
|
3983
4306
|
};
|
|
3984
4307
|
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
4308
|
/* @__PURE__ */ jsxs(AlertDialogHeader, { className: "border-b border-border/60 pb-4", children: [
|
|
@@ -4026,7 +4349,7 @@ var WalletDialog = ({ open, onOpenChange }) => {
|
|
|
4026
4349
|
] })
|
|
4027
4350
|
] })
|
|
4028
4351
|
] }),
|
|
4029
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-
|
|
4352
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 rounded-md border border-border/70 bg-muted/10 p-4", children: [
|
|
4030
4353
|
/* @__PURE__ */ jsx(Checkbox, { id: "terms-agree", checked: form.termsAccepted, onCheckedChange: (checked) => updateField("termsAccepted", Boolean(checked)) }),
|
|
4031
4354
|
/* @__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
4355
|
] }),
|
|
@@ -4038,245 +4361,6 @@ var WalletDialog = ({ open, onOpenChange }) => {
|
|
|
4038
4361
|
] })
|
|
4039
4362
|
] }) });
|
|
4040
4363
|
};
|
|
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
4364
|
var useTokenBalance = (tokens) => {
|
|
4281
4365
|
const { publicKey } = useWallet();
|
|
4282
4366
|
const { connection } = useConnection();
|
|
@@ -4796,6 +4880,6 @@ var useAlternativePaymentProvider = () => {
|
|
|
4796
4880
|
return { openFlexForm, isLoading, error };
|
|
4797
4881
|
};
|
|
4798
4882
|
|
|
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,
|
|
4883
|
+
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
4884
|
//# sourceMappingURL=index.js.map
|
|
4801
4885
|
//# sourceMappingURL=index.js.map
|