@doujins/payments-ui 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,27 +1,30 @@
1
1
  'use strict';
2
2
 
3
3
  var React3 = require('react');
4
- var vanilla = require('zustand/vanilla');
5
- var jsxRuntime = require('react/jsx-runtime');
4
+ var reactQuery = require('@tanstack/react-query');
5
+ var walletAdapterReact = require('@solana/wallet-adapter-react');
6
+ var walletAdapterReactUi = require('@solana/wallet-adapter-react-ui');
7
+ require('@solana/wallet-adapter-react-ui/styles.css');
8
+ var web3_js = require('@solana/web3.js');
9
+ var walletAdapterPhantom = require('@solana/wallet-adapter-phantom');
10
+ var walletAdapterSolflare = require('@solana/wallet-adapter-solflare');
11
+ var walletAdapterTrust = require('@solana/wallet-adapter-trust');
12
+ var walletAdapterCoinbase = require('@solana/wallet-adapter-coinbase');
13
+ var DialogPrimitive = require('@radix-ui/react-dialog');
6
14
  var lucideReact = require('lucide-react');
7
- var countryList = require('country-list');
8
- var classVarianceAuthority = require('class-variance-authority');
9
15
  var clsx = require('clsx');
10
16
  var tailwindMerge = require('tailwind-merge');
17
+ var jsxRuntime = require('react/jsx-runtime');
18
+ var countryList = require('country-list');
19
+ var classVarianceAuthority = require('class-variance-authority');
11
20
  var LabelPrimitive = require('@radix-ui/react-label');
12
21
  var SelectPrimitive = require('@radix-ui/react-select');
13
- var reactQuery = require('@tanstack/react-query');
14
- var DialogPrimitive = require('@radix-ui/react-dialog');
15
22
  var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
16
- var walletAdapterReact = require('@solana/wallet-adapter-react');
23
+ var TabsPrimitive = require('@radix-ui/react-tabs');
17
24
  var buffer = require('buffer');
18
- var web3_js = require('@solana/web3.js');
19
25
  var splToken = require('@solana/spl-token');
20
26
  var QRCode = require('qrcode');
21
- var zustand = require('zustand');
22
- var TabsPrimitive = require('@radix-ui/react-tabs');
23
27
  var AlertDialogPrimitive = require('@radix-ui/react-alert-dialog');
24
- var walletAdapterReactUi = require('@solana/wallet-adapter-react-ui');
25
28
  var bs58 = require('bs58');
26
29
  var CheckboxPrimitive = require('@radix-ui/react-checkbox');
27
30
 
@@ -46,13 +49,13 @@ function _interopNamespace(e) {
46
49
  }
47
50
 
48
51
  var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
52
+ var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
49
53
  var countryList__default = /*#__PURE__*/_interopDefault(countryList);
50
54
  var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
51
55
  var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespace(SelectPrimitive);
52
- var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
53
56
  var ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespace(ScrollAreaPrimitive);
54
- var QRCode__default = /*#__PURE__*/_interopDefault(QRCode);
55
57
  var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
58
+ var QRCode__default = /*#__PURE__*/_interopDefault(QRCode);
56
59
  var AlertDialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(AlertDialogPrimitive);
57
60
  var bs58__default = /*#__PURE__*/_interopDefault(bs58);
58
61
  var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
@@ -524,141 +527,98 @@ var PaymentApp = class {
524
527
  };
525
528
  }
526
529
  };
527
- var initialState = {
528
- selectedMethodId: null,
529
- solanaModalOpen: false,
530
- savedPaymentStatus: "idle",
531
- savedPaymentError: null,
532
- newCardStatus: "idle",
533
- newCardError: null,
534
- solanaTab: "wallet",
535
- solanaStatus: "selecting",
536
- solanaError: null,
537
- solanaTransactionId: null,
538
- solanaSelectedToken: null,
539
- solanaTokenAmount: 0
540
- };
541
- var createPaymentStore = (options) => vanilla.createStore((set, get) => {
542
- const notifyStatus = (status, context) => {
543
- options?.callbacks?.onStatusChange?.({ status, context });
544
- };
545
- const notifySuccess = (payload) => {
546
- if (!options?.callbacks?.onSuccess) return;
547
- options.callbacks.onSuccess(payload ?? {});
548
- };
549
- const notifyError = (error) => {
550
- options?.callbacks?.onError?.(new Error(error));
551
- };
552
- return {
553
- ...initialState,
554
- setSelectedMethod: (methodId) => {
555
- if (get().selectedMethodId === methodId) return;
556
- set({ selectedMethodId: methodId });
557
- },
558
- setSolanaModalOpen: (open) => {
559
- if (get().solanaModalOpen === open) return;
560
- set({ solanaModalOpen: open });
561
- },
562
- setSolanaTab: (tab) => {
563
- if (get().solanaTab === tab) return;
564
- set({ solanaTab: tab });
565
- },
566
- setSolanaSelectedToken: (symbol) => {
567
- if (get().solanaSelectedToken === symbol) return;
568
- set({ solanaSelectedToken: symbol });
569
- },
570
- setSolanaTokenAmount: (amount) => {
571
- if (get().solanaTokenAmount === amount) return;
572
- set({ solanaTokenAmount: amount });
573
- },
574
- setSolanaTransactionId: (txId) => {
575
- if (get().solanaTransactionId === txId) return;
576
- set({ solanaTransactionId: txId });
577
- },
578
- startSavedPayment: () => {
579
- notifyStatus("processing", { source: "saved-payment" });
580
- set({ savedPaymentStatus: "processing", savedPaymentError: null });
581
- },
582
- completeSavedPayment: () => {
583
- notifyStatus("success", { source: "saved-payment" });
584
- set({ savedPaymentStatus: "success", savedPaymentError: null });
585
- },
586
- failSavedPayment: (error) => {
587
- notifyStatus("error", { source: "saved-payment" });
588
- notifyError(error);
589
- set({ savedPaymentStatus: "error", savedPaymentError: error });
590
- },
591
- resetSavedPayment: () => set({ savedPaymentStatus: "idle", savedPaymentError: null }),
592
- startNewCardPayment: () => {
593
- notifyStatus("processing", { source: "new-card" });
594
- set({ newCardStatus: "processing", newCardError: null });
595
- },
596
- completeNewCardPayment: () => {
597
- notifyStatus("success", { source: "new-card" });
598
- set({ newCardStatus: "success", newCardError: null });
599
- },
600
- failNewCardPayment: (error) => {
601
- notifyStatus("error", { source: "new-card" });
602
- notifyError(error);
603
- set({ newCardStatus: "error", newCardError: error });
604
- },
605
- resetNewCardPayment: () => set({ newCardStatus: "idle", newCardError: null }),
606
- startSolanaPayment: () => {
607
- notifyStatus("processing", { source: "solana" });
608
- set({ solanaStatus: "processing", solanaError: null });
609
- },
610
- confirmSolanaPayment: () => set({ solanaStatus: "confirming" }),
611
- completeSolanaPayment: (payload) => {
612
- notifyStatus("success", { source: "solana" });
613
- notifySuccess(payload);
614
- set({ solanaStatus: "success", solanaError: null });
615
- },
616
- failSolanaPayment: (error) => {
617
- notifyStatus("error", { source: "solana" });
618
- notifyError(error);
619
- set({ solanaStatus: "error", solanaError: error });
530
+
531
+ // src/runtime/PaymentsRuntime.ts
532
+ var createQueryClient = () => new reactQuery.QueryClient({
533
+ defaultOptions: {
534
+ queries: {
535
+ staleTime: 3e4,
536
+ gcTime: 5 * 6e4,
537
+ refetchOnWindowFocus: false,
538
+ retry: 1
620
539
  },
621
- resetSolanaPayment: () => set({
622
- solanaStatus: "selecting",
623
- solanaError: null,
624
- solanaTransactionId: null
625
- }),
626
- resetAll: () => set(initialState)
627
- };
540
+ mutations: {
541
+ retry: 1
542
+ }
543
+ }
628
544
  });
629
- var PaymentContext = React3.createContext(void 0);
630
- var PaymentProvider = ({
631
- config,
632
- children
633
- }) => {
634
- const app = React3.useMemo(() => new PaymentApp({ config }), [config]);
635
- const store = React3.useMemo(
636
- () => createPaymentStore({ callbacks: config.callbacks }),
637
- [config.callbacks]
638
- );
639
- const value = React3.useMemo(() => {
640
- return {
641
- config: app.getConfig(),
642
- fetcher: app.getFetcher(),
643
- resolveAuthToken: app.resolveAuthToken,
644
- app,
645
- services: app.getServices(),
646
- store
647
- };
648
- }, [app, store]);
649
- React3.useEffect(() => {
650
- if (!value.config.collectJsKey) return;
651
- loadCollectJs(value.config.collectJsKey);
652
- }, [value.config.collectJsKey]);
653
- return /* @__PURE__ */ jsxRuntime.jsx(PaymentContext.Provider, { value, children });
654
- };
655
- var usePaymentContext = () => {
656
- const context = React3.useContext(PaymentContext);
657
- if (!context) {
658
- throw new Error("usePaymentContext must be used within a PaymentProvider");
545
+ var PaymentsRuntime = class {
546
+ constructor(config) {
547
+ this.config = config;
548
+ this.app = new PaymentApp({ config });
549
+ this.services = this.app.getServices();
550
+ this.queryClient = createQueryClient();
659
551
  }
660
- return context;
661
552
  };
553
+ var createPaymentsRuntime = (config) => new PaymentsRuntime(config);
554
+
555
+ // node_modules/@solana/wallet-adapter-base/lib/esm/types.js
556
+ var WalletAdapterNetwork;
557
+ (function(WalletAdapterNetwork2) {
558
+ WalletAdapterNetwork2["Mainnet"] = "mainnet-beta";
559
+ WalletAdapterNetwork2["Testnet"] = "testnet";
560
+ WalletAdapterNetwork2["Devnet"] = "devnet";
561
+ })(WalletAdapterNetwork || (WalletAdapterNetwork = {}));
562
+ function cn(...inputs) {
563
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
564
+ }
565
+ var Dialog = DialogPrimitive__namespace.Root;
566
+ var DialogPortal = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Portal, { className: cn(className), ...props });
567
+ DialogPortal.displayName = DialogPrimitive__namespace.Portal.displayName;
568
+ var DialogOverlay = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
569
+ DialogPrimitive__namespace.Overlay,
570
+ {
571
+ ref,
572
+ className: cn(
573
+ "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",
574
+ className
575
+ ),
576
+ ...props
577
+ }
578
+ ));
579
+ DialogOverlay.displayName = DialogPrimitive__namespace.Overlay.displayName;
580
+ var DialogContent = React3__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
581
+ /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
582
+ /* @__PURE__ */ jsxRuntime.jsxs(
583
+ DialogPrimitive__namespace.Content,
584
+ {
585
+ ref,
586
+ className: cn(
587
+ "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%]",
588
+ className
589
+ ),
590
+ ...props,
591
+ children: [
592
+ children,
593
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.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: [
594
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }),
595
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
596
+ ] })
597
+ ]
598
+ }
599
+ )
600
+ ] }));
601
+ DialogContent.displayName = DialogPrimitive__namespace.Content.displayName;
602
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
603
+ DialogHeader.displayName = "DialogHeader";
604
+ var DialogTitle = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
605
+ DialogPrimitive__namespace.Title,
606
+ {
607
+ ref,
608
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
609
+ ...props
610
+ }
611
+ ));
612
+ DialogTitle.displayName = DialogPrimitive__namespace.Title.displayName;
613
+ var DialogDescription = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
614
+ DialogPrimitive__namespace.Description,
615
+ {
616
+ ref,
617
+ className: cn("text-sm text-muted-foreground", className),
618
+ ...props
619
+ }
620
+ ));
621
+ DialogDescription.displayName = DialogPrimitive__namespace.Description.displayName;
662
622
  var customCountries = [
663
623
  { code: "TW", name: "Taiwan, Province of China" },
664
624
  { code: "KR", name: "Korea" },
@@ -788,9 +748,6 @@ function getElementRef(element) {
788
748
  }
789
749
  return element.props.ref || element.ref;
790
750
  }
791
- function cn(...inputs) {
792
- return tailwindMerge.twMerge(clsx.clsx(inputs));
793
- }
794
751
  var buttonVariants = classVarianceAuthority.cva(
795
752
  "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",
796
753
  {
@@ -933,7 +890,6 @@ var defaultBilling = {
933
890
  firstName: "",
934
891
  lastName: "",
935
892
  address1: "",
936
- address2: "",
937
893
  city: "",
938
894
  stateRegion: "",
939
895
  postalCode: "",
@@ -967,7 +923,6 @@ var CardDetailsForm = ({
967
923
  const [firstName, setFirstName] = React3.useState(mergedDefaults.firstName);
968
924
  const [lastName, setLastName] = React3.useState(mergedDefaults.lastName);
969
925
  const [address1, setAddress1] = React3.useState(mergedDefaults.address1);
970
- const [address2, setAddress2] = React3.useState(mergedDefaults.address2 ?? "");
971
926
  const [city, setCity] = React3.useState(mergedDefaults.city);
972
927
  const [stateRegion, setStateRegion] = React3.useState(mergedDefaults.stateRegion ?? "");
973
928
  const [postalCode, setPostalCode] = React3.useState(mergedDefaults.postalCode);
@@ -986,7 +941,6 @@ var CardDetailsForm = ({
986
941
  setFirstName(mergedDefaults.firstName);
987
942
  setLastName(mergedDefaults.lastName);
988
943
  setAddress1(mergedDefaults.address1);
989
- setAddress2(mergedDefaults.address2 ?? "");
990
944
  setCity(mergedDefaults.city);
991
945
  setStateRegion(mergedDefaults.stateRegion ?? "");
992
946
  setPostalCode(mergedDefaults.postalCode);
@@ -999,7 +953,6 @@ var CardDetailsForm = ({
999
953
  firstName,
1000
954
  lastName,
1001
955
  address1,
1002
- address2,
1003
956
  city,
1004
957
  stateRegion,
1005
958
  postalCode,
@@ -1011,7 +964,6 @@ var CardDetailsForm = ({
1011
964
  firstName,
1012
965
  lastName,
1013
966
  address1,
1014
- address2,
1015
967
  city,
1016
968
  stateRegion,
1017
969
  postalCode,
@@ -1035,7 +987,6 @@ var CardDetailsForm = ({
1035
987
  firstName,
1036
988
  lastName,
1037
989
  address1,
1038
- address2,
1039
990
  city,
1040
991
  stateRegion,
1041
992
  postalCode,
@@ -1066,7 +1017,6 @@ var CardDetailsForm = ({
1066
1017
  firstName,
1067
1018
  lastName,
1068
1019
  address1,
1069
- address2,
1070
1020
  city,
1071
1021
  stateRegion,
1072
1022
  postalCode,
@@ -1095,19 +1045,16 @@ var CardDetailsForm = ({
1095
1045
  window.CollectJS.startPaymentRequest();
1096
1046
  };
1097
1047
  const errorMessage = localError ?? externalError;
1098
- const collectFieldClass = "flex h-11 w-full items-center rounded-md border border-dashed border-muted-foreground/40 bg-muted/20 px-3 text-sm text-muted-foreground";
1048
+ const collectFieldClass = "flex h-11 w-full items-center rounded-md border border-border/60 bg-background px-3 text-sm text-muted-foreground";
1099
1049
  return /* @__PURE__ */ jsxRuntime.jsxs(
1100
1050
  "form",
1101
1051
  {
1102
- className: cn(
1103
- "space-y-6 rounded-2xl border border-border/60 bg-card/90 p-6 shadow-lg",
1104
- className
1105
- ),
1052
+ className: cn("space-y-5", className),
1106
1053
  onSubmit: handleSubmit,
1107
1054
  noValidate: true,
1108
1055
  children: [
1109
1056
  errorMessage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 px-4 py-2 text-sm text-destructive", children: errorMessage }),
1110
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
1057
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-5 md:grid-cols-2", children: [
1111
1058
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1112
1059
  /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: "payments-first", className: "flex items-center gap-2 text-muted-foreground", children: [
1113
1060
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.User, { className: "h-4 w-4" }),
@@ -1153,7 +1100,7 @@ var CardDetailsForm = ({
1153
1100
  )
1154
1101
  ] }),
1155
1102
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1156
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "payments-address1", children: "Address line 1" }),
1103
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "payments-address1", children: "Address" }),
1157
1104
  /* @__PURE__ */ jsxRuntime.jsx(
1158
1105
  Input,
1159
1106
  {
@@ -1164,18 +1111,7 @@ var CardDetailsForm = ({
1164
1111
  }
1165
1112
  )
1166
1113
  ] }),
1167
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1168
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "payments-address2", children: "Address line 2 (optional)" }),
1169
- /* @__PURE__ */ jsxRuntime.jsx(
1170
- Input,
1171
- {
1172
- id: "payments-address2",
1173
- value: address2,
1174
- onChange: (e) => setAddress2(e.target.value)
1175
- }
1176
- )
1177
- ] }),
1178
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
1114
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-5 md:grid-cols-2", children: [
1179
1115
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1180
1116
  /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "payments-city", children: "City" }),
1181
1117
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1200,7 +1136,7 @@ var CardDetailsForm = ({
1200
1136
  )
1201
1137
  ] })
1202
1138
  ] }),
1203
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
1139
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-5 md:grid-cols-2", children: [
1204
1140
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1205
1141
  /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: "payments-postal", className: "flex items-center gap-2 text-muted-foreground", children: [
1206
1142
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { className: "h-4 w-4" }),
@@ -1220,7 +1156,7 @@ var CardDetailsForm = ({
1220
1156
  /* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Country" }),
1221
1157
  /* @__PURE__ */ jsxRuntime.jsxs(Select, { value: country, onValueChange: setCountry, children: [
1222
1158
  /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select a country" }) }),
1223
- /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { className: "max-h-64", children: countries.map((option) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: option.code, children: option.name }, option.code)) })
1159
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { className: "max-h-64 w-full", children: countries.map((option) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: option.code, children: option.name }, option.code)) })
1224
1160
  ] })
1225
1161
  ] })
1226
1162
  ] }),
@@ -1309,63 +1245,6 @@ var usePaymentMethods = () => {
1309
1245
  deleteMutation
1310
1246
  };
1311
1247
  };
1312
- var Dialog = DialogPrimitive__namespace.Root;
1313
- var DialogPortal = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Portal, { className: cn(className), ...props });
1314
- DialogPortal.displayName = DialogPrimitive__namespace.Portal.displayName;
1315
- var DialogOverlay = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1316
- DialogPrimitive__namespace.Overlay,
1317
- {
1318
- ref,
1319
- className: cn(
1320
- "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",
1321
- className
1322
- ),
1323
- ...props
1324
- }
1325
- ));
1326
- DialogOverlay.displayName = DialogPrimitive__namespace.Overlay.displayName;
1327
- var DialogContent = React3__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
1328
- /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
1329
- /* @__PURE__ */ jsxRuntime.jsxs(
1330
- DialogPrimitive__namespace.Content,
1331
- {
1332
- ref,
1333
- className: cn(
1334
- "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%]",
1335
- className
1336
- ),
1337
- ...props,
1338
- children: [
1339
- children,
1340
- /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.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: [
1341
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }),
1342
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
1343
- ] })
1344
- ]
1345
- }
1346
- )
1347
- ] }));
1348
- DialogContent.displayName = DialogPrimitive__namespace.Content.displayName;
1349
- var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
1350
- DialogHeader.displayName = "DialogHeader";
1351
- var DialogTitle = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1352
- DialogPrimitive__namespace.Title,
1353
- {
1354
- ref,
1355
- className: cn("text-lg font-semibold leading-none tracking-tight", className),
1356
- ...props
1357
- }
1358
- ));
1359
- DialogTitle.displayName = DialogPrimitive__namespace.Title.displayName;
1360
- var DialogDescription = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1361
- DialogPrimitive__namespace.Description,
1362
- {
1363
- ref,
1364
- className: cn("text-sm text-muted-foreground", className),
1365
- ...props
1366
- }
1367
- ));
1368
- DialogDescription.displayName = DialogPrimitive__namespace.Description.displayName;
1369
1248
  var badgeVariants = classVarianceAuthority.cva(
1370
1249
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none",
1371
1250
  {
@@ -1415,43 +1294,6 @@ var ScrollBar = React3__namespace.forwardRef(({ className, orientation = "vertic
1415
1294
  }
1416
1295
  ));
1417
1296
  ScrollBar.displayName = ScrollAreaPrimitive__namespace.ScrollAreaScrollbar.displayName;
1418
- var Card = React3__namespace.forwardRef(
1419
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1420
- "div",
1421
- {
1422
- ref,
1423
- className: cn("rounded-xl border bg-card text-card-foreground shadow", className),
1424
- ...props
1425
- }
1426
- )
1427
- );
1428
- Card.displayName = "Card";
1429
- var CardHeader = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1430
- "div",
1431
- {
1432
- ref,
1433
- className: cn("flex flex-col space-y-1.5 p-6", className),
1434
- ...props
1435
- }
1436
- ));
1437
- CardHeader.displayName = "CardHeader";
1438
- var CardTitle = React3__namespace.forwardRef(
1439
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("text-2xl font-semibold leading-none tracking-tight", className), ...props })
1440
- );
1441
- CardTitle.displayName = "CardTitle";
1442
- var CardDescription = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
1443
- CardDescription.displayName = "CardDescription";
1444
- var CardContent = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
1445
- CardContent.displayName = "CardContent";
1446
- var CardFooter = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1447
- "div",
1448
- {
1449
- ref,
1450
- className: cn("flex items-center p-6 pt-0", className),
1451
- ...props
1452
- }
1453
- ));
1454
- CardFooter.displayName = "CardFooter";
1455
1297
  var formatCardLabel = (method) => {
1456
1298
  const brand = method.card_type ? method.card_type.toUpperCase() : "CARD";
1457
1299
  const lastFour = method.last_four ? `\u2022\u2022\u2022\u2022 ${method.last_four}` : "";
@@ -1480,22 +1322,22 @@ var StoredPaymentMethods = ({
1480
1322
  }
1481
1323
  );
1482
1324
  };
1483
- return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "border-border/60 bg-card/95", children: [
1484
- /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "flex flex-row items-start justify-between space-y-0", children: [
1485
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1486
- /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "text-base font-semibold text-foreground", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2 text-sm font-medium text-muted-foreground", children: [
1325
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
1326
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
1327
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1328
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 text-sm font-medium text-muted-foreground", children: [
1487
1329
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.WalletCards, { className: "h-4 w-4" }),
1488
1330
  " ",
1489
1331
  heading
1490
- ] }) }),
1491
- /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: description })
1332
+ ] }),
1333
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: description })
1492
1334
  ] }),
1493
- showAddButton && /* @__PURE__ */ jsxRuntime.jsxs(Button, { size: "sm", onClick: () => setIsModalOpen(true), children: [
1335
+ showAddButton && /* @__PURE__ */ jsxRuntime.jsxs(Button, { size: "sm", variant: "outline", onClick: () => setIsModalOpen(true), children: [
1494
1336
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "mr-2 h-4 w-4" }),
1495
1337
  " Add card"
1496
1338
  ] })
1497
1339
  ] }),
1498
- /* @__PURE__ */ jsxRuntime.jsx(CardContent, { children: listQuery.isLoading ? /* @__PURE__ */ jsxRuntime.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: [
1340
+ listQuery.isLoading ? /* @__PURE__ */ jsxRuntime.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: [
1499
1341
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
1500
1342
  " Loading cards\u2026"
1501
1343
  ] }) : payments.length === 0 ? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(ScrollArea, { className: "max-h-[320px] pr-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: payments.map((method) => {
@@ -1553,8 +1395,8 @@ var StoredPaymentMethods = ({
1553
1395
  },
1554
1396
  method.id
1555
1397
  );
1556
- }) }) }) }),
1557
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-h-[90vh] overflow-y-auto", children: [
1398
+ }) }) }),
1399
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-h-[85vh] overflow-y-auto", children: [
1558
1400
  /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
1559
1401
  /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Add a new card" }),
1560
1402
  /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Your card details are tokenized securely via our payment provider." })
@@ -1573,12 +1415,77 @@ var StoredPaymentMethods = ({
1573
1415
  ] }) })
1574
1416
  ] });
1575
1417
  };
1576
- var useSolanaService = () => {
1577
- const { services } = usePaymentContext();
1578
- return React3.useMemo(() => services.solanaPayments, [services]);
1579
- };
1580
- var getSolBalance = async (connection, publicKey) => {
1581
- try {
1418
+ var Tabs = TabsPrimitive__namespace.Root;
1419
+ var TabsList = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1420
+ TabsPrimitive__namespace.List,
1421
+ {
1422
+ ref,
1423
+ className: cn(
1424
+ "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
1425
+ className
1426
+ ),
1427
+ ...props
1428
+ }
1429
+ ));
1430
+ TabsList.displayName = TabsPrimitive__namespace.List.displayName;
1431
+ var TabsTrigger = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1432
+ TabsPrimitive__namespace.Trigger,
1433
+ {
1434
+ ref,
1435
+ className: cn(
1436
+ "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",
1437
+ className
1438
+ ),
1439
+ ...props
1440
+ }
1441
+ ));
1442
+ TabsTrigger.displayName = TabsPrimitive__namespace.Trigger.displayName;
1443
+ var TabsContent = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1444
+ TabsPrimitive__namespace.Content,
1445
+ {
1446
+ ref,
1447
+ className: cn(
1448
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
1449
+ className
1450
+ ),
1451
+ ...props
1452
+ }
1453
+ ));
1454
+ TabsContent.displayName = TabsPrimitive__namespace.Content.displayName;
1455
+ var usePaymentNotifications = () => {
1456
+ const { config } = usePaymentContext();
1457
+ const notifyStatus = React3.useCallback(
1458
+ (status, context) => {
1459
+ config.callbacks?.onStatusChange?.({ status, context });
1460
+ },
1461
+ [config.callbacks]
1462
+ );
1463
+ const notifySuccess = React3.useCallback(
1464
+ (payload) => {
1465
+ config.callbacks?.onSuccess?.(payload ?? {});
1466
+ },
1467
+ [config.callbacks]
1468
+ );
1469
+ const notifyError = React3.useCallback(
1470
+ (error) => {
1471
+ config.callbacks?.onError?.(
1472
+ typeof error === "string" ? new Error(error) : error
1473
+ );
1474
+ },
1475
+ [config.callbacks]
1476
+ );
1477
+ return {
1478
+ notifyStatus,
1479
+ notifySuccess,
1480
+ notifyError
1481
+ };
1482
+ };
1483
+ var useSolanaService = () => {
1484
+ const { services } = usePaymentContext();
1485
+ return React3.useMemo(() => services.solanaPayments, [services]);
1486
+ };
1487
+ var getSolBalance = async (connection, publicKey) => {
1488
+ try {
1582
1489
  const lamports = await connection.getBalance(publicKey);
1583
1490
  return lamports / web3_js.LAMPORTS_PER_SOL;
1584
1491
  } catch (error) {
@@ -1849,6 +1756,43 @@ var useSolanaDirectPayment = (options) => {
1849
1756
  pay
1850
1757
  };
1851
1758
  };
1759
+ var Card = React3__namespace.forwardRef(
1760
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1761
+ "div",
1762
+ {
1763
+ ref,
1764
+ className: cn("rounded-xl border bg-card text-card-foreground shadow", className),
1765
+ ...props
1766
+ }
1767
+ )
1768
+ );
1769
+ Card.displayName = "Card";
1770
+ var CardHeader = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1771
+ "div",
1772
+ {
1773
+ ref,
1774
+ className: cn("flex flex-col space-y-1.5 p-6", className),
1775
+ ...props
1776
+ }
1777
+ ));
1778
+ CardHeader.displayName = "CardHeader";
1779
+ var CardTitle = React3__namespace.forwardRef(
1780
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("text-2xl font-semibold leading-none tracking-tight", className), ...props })
1781
+ );
1782
+ CardTitle.displayName = "CardTitle";
1783
+ var CardDescription = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
1784
+ CardDescription.displayName = "CardDescription";
1785
+ var CardContent = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
1786
+ CardContent.displayName = "CardContent";
1787
+ var CardFooter = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1788
+ "div",
1789
+ {
1790
+ ref,
1791
+ className: cn("flex items-center p-6 pt-0", className),
1792
+ ...props
1793
+ }
1794
+ ));
1795
+ CardFooter.displayName = "CardFooter";
1852
1796
  var DirectPayment = ({
1853
1797
  priceId,
1854
1798
  tokenAmount,
@@ -1869,7 +1813,7 @@ var DirectPayment = ({
1869
1813
  onSuccess: onPaymentSuccess,
1870
1814
  onError: onPaymentError
1871
1815
  });
1872
- return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "space-y-4 border border-border/60 bg-background/80 p-6", children: [
1816
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "space-y-4 rounded-md border border-border/60 bg-background/80 shadow-none p-6", children: [
1873
1817
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1874
1818
  /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: [
1875
1819
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "h-4 w-4" }),
@@ -2101,9 +2045,9 @@ var QRCodePayment = ({
2101
2045
  onSuccess: onPaymentSuccess
2102
2046
  });
2103
2047
  if (!selectedToken) {
2104
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-dashed border-border/60 bg-muted/10 px-4 py-6 text-center text-sm text-muted-foreground", children: "Select a token to continue." });
2048
+ return /* @__PURE__ */ jsxRuntime.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." });
2105
2049
  }
2106
- return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "space-y-4 border border-border/60 bg-background/80 p-6", children: [
2050
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "space-y-4 border border-border/60 bg-background/80 p-6 shadow-none rounded-md", children: [
2107
2051
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
2108
2052
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2109
2053
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Scan with Solana Pay" }),
@@ -2332,109 +2276,21 @@ var useSupportedTokens = () => {
2332
2276
  tokenCount: tokens.length
2333
2277
  };
2334
2278
  };
2335
- var usePaymentStore = (selector) => {
2336
- const { store } = usePaymentContext();
2337
- return zustand.useStore(store, selector);
2338
- };
2339
-
2340
- // src/state/selectors.ts
2341
- var selectCheckoutFlow = (state) => ({
2342
- selectedMethodId: state.selectedMethodId,
2343
- savedStatus: state.savedPaymentStatus,
2344
- savedError: state.savedPaymentError,
2345
- newCardStatus: state.newCardStatus,
2346
- newCardError: state.newCardError,
2347
- solanaModalOpen: state.solanaModalOpen,
2348
- setSelectedMethod: state.setSelectedMethod,
2349
- setSolanaModalOpen: state.setSolanaModalOpen,
2350
- startSavedPayment: state.startSavedPayment,
2351
- completeSavedPayment: state.completeSavedPayment,
2352
- failSavedPayment: state.failSavedPayment,
2353
- startNewCardPayment: state.startNewCardPayment,
2354
- completeNewCardPayment: state.completeNewCardPayment,
2355
- failNewCardPayment: state.failNewCardPayment,
2356
- resetSavedPayment: state.resetSavedPayment
2357
- });
2358
- var selectSolanaFlow = (state) => ({
2359
- tab: state.solanaTab,
2360
- status: state.solanaStatus,
2361
- error: state.solanaError,
2362
- transactionId: state.solanaTransactionId,
2363
- tokenAmount: state.solanaTokenAmount,
2364
- selectedTokenSymbol: state.solanaSelectedToken,
2365
- setTab: state.setSolanaTab,
2366
- setTokenAmount: state.setSolanaTokenAmount,
2367
- setTransactionId: state.setSolanaTransactionId,
2368
- setSelectedTokenSymbol: state.setSolanaSelectedToken,
2369
- startSolanaPayment: state.startSolanaPayment,
2370
- confirmSolanaPayment: state.confirmSolanaPayment,
2371
- completeSolanaPayment: state.completeSolanaPayment,
2372
- failSolanaPayment: state.failSolanaPayment,
2373
- resetSolanaPayment: state.resetSolanaPayment
2374
- });
2375
- var Tabs = TabsPrimitive__namespace.Root;
2376
- var TabsList = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2377
- TabsPrimitive__namespace.List,
2378
- {
2379
- ref,
2380
- className: cn(
2381
- "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
2382
- className
2383
- ),
2384
- ...props
2385
- }
2386
- ));
2387
- TabsList.displayName = TabsPrimitive__namespace.List.displayName;
2388
- var TabsTrigger = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2389
- TabsPrimitive__namespace.Trigger,
2390
- {
2391
- ref,
2392
- className: cn(
2393
- "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",
2394
- className
2395
- ),
2396
- ...props
2397
- }
2398
- ));
2399
- TabsTrigger.displayName = TabsPrimitive__namespace.Trigger.displayName;
2400
- var TabsContent = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2401
- TabsPrimitive__namespace.Content,
2402
- {
2403
- ref,
2404
- className: cn(
2405
- "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
2406
- className
2407
- ),
2408
- ...props
2409
- }
2410
- ));
2411
- TabsContent.displayName = TabsPrimitive__namespace.Content.displayName;
2412
- var SolanaPaymentSelector = ({
2413
- isOpen,
2414
- onClose,
2279
+ var SolanaPaymentView = ({
2415
2280
  priceId,
2416
2281
  usdAmount,
2417
2282
  onSuccess,
2418
- onError
2283
+ onError,
2284
+ onClose
2419
2285
  }) => {
2420
2286
  const { connected } = walletAdapterReact.useWallet();
2421
- const {
2422
- tab: activeTab,
2423
- status: paymentState,
2424
- error: errorMessage,
2425
- transactionId,
2426
- tokenAmount,
2427
- selectedTokenSymbol,
2428
- setTab,
2429
- setTokenAmount,
2430
- setTransactionId,
2431
- setSelectedTokenSymbol,
2432
- startSolanaPayment,
2433
- confirmSolanaPayment,
2434
- completeSolanaPayment,
2435
- failSolanaPayment,
2436
- resetSolanaPayment
2437
- } = usePaymentStore(selectSolanaFlow);
2287
+ const { notifyStatus, notifyError, notifySuccess } = usePaymentNotifications();
2288
+ const [activeTab, setActiveTab] = React3.useState("wallet");
2289
+ const [paymentState, setPaymentState] = React3.useState("selecting");
2290
+ const [errorMessage, setErrorMessage] = React3.useState(null);
2291
+ const [transactionId, setTransactionId] = React3.useState(null);
2292
+ const [tokenAmount, setTokenAmount] = React3.useState(0);
2293
+ const [selectedTokenSymbol, setSelectedTokenSymbol] = React3.useState(null);
2438
2294
  const {
2439
2295
  tokens,
2440
2296
  isLoading: tokensLoading,
@@ -2450,60 +2306,70 @@ var SolanaPaymentSelector = ({
2450
2306
  const defaultToken = tokens.find((token) => token.symbol === "SOL") || tokens[0];
2451
2307
  setSelectedTokenSymbol(defaultToken.symbol);
2452
2308
  }
2453
- }, [tokens, selectedTokenSymbol, setSelectedTokenSymbol]);
2309
+ }, [tokens, selectedTokenSymbol]);
2454
2310
  const handlePaymentStart = React3.useCallback(() => {
2455
- startSolanaPayment();
2456
- }, [startSolanaPayment]);
2311
+ setPaymentState("processing");
2312
+ setErrorMessage(null);
2313
+ notifyStatus("processing", { source: "solana" });
2314
+ }, [notifyStatus]);
2457
2315
  const handlePaymentConfirming = React3.useCallback(() => {
2458
- confirmSolanaPayment();
2459
- }, [confirmSolanaPayment]);
2316
+ setPaymentState("confirming");
2317
+ }, []);
2460
2318
  const handlePaymentSuccess = React3.useCallback(
2461
2319
  (result, txId) => {
2462
2320
  const resolvedTx = txId || (typeof result === "string" ? result : result.transaction_id);
2463
2321
  setTransactionId(resolvedTx);
2464
- completeSolanaPayment(
2465
- typeof result === "string" ? {
2466
- transactionId: resolvedTx,
2467
- processor: "solana",
2468
- metadata: { source: "solana-pay" }
2469
- } : {
2470
- transactionId: result.transaction_id,
2471
- intentId: result.intent_id,
2472
- processor: "solana",
2473
- metadata: {
2474
- purchaseId: result.purchase_id,
2475
- amount: result.amount,
2476
- currency: result.currency
2477
- }
2322
+ setPaymentState("success");
2323
+ setErrorMessage(null);
2324
+ const payload = typeof result === "string" ? {
2325
+ transactionId: resolvedTx,
2326
+ processor: "solana",
2327
+ metadata: { source: "solana-pay" }
2328
+ } : {
2329
+ transactionId: result.transaction_id,
2330
+ intentId: result.intent_id,
2331
+ processor: "solana",
2332
+ metadata: {
2333
+ purchaseId: result.purchase_id,
2334
+ amount: result.amount,
2335
+ currency: result.currency
2478
2336
  }
2479
- );
2337
+ };
2338
+ notifyStatus("success", { source: "solana" });
2339
+ notifySuccess(payload);
2480
2340
  setTimeout(() => {
2481
2341
  onSuccess(result);
2482
2342
  }, 1500);
2483
2343
  },
2484
- [completeSolanaPayment, onSuccess, setTransactionId]
2344
+ [notifyStatus, notifySuccess, onSuccess]
2485
2345
  );
2486
2346
  const handlePaymentError = React3.useCallback(
2487
2347
  (error) => {
2488
- failSolanaPayment(error);
2348
+ setPaymentState("error");
2349
+ setErrorMessage(error);
2350
+ notifyStatus("error", { source: "solana" });
2351
+ notifyError(error);
2489
2352
  onError?.(error);
2490
2353
  },
2491
- [failSolanaPayment, onError]
2354
+ [notifyError, notifyStatus, onError]
2492
2355
  );
2493
- const handleRetry = React3.useCallback(() => {
2494
- resetSolanaPayment();
2356
+ const resetState = React3.useCallback(() => {
2357
+ setPaymentState("selecting");
2358
+ setErrorMessage(null);
2495
2359
  setTransactionId(null);
2496
- }, [resetSolanaPayment, setTransactionId]);
2360
+ }, []);
2361
+ const handleRetry = React3.useCallback(() => {
2362
+ resetState();
2363
+ }, [resetState]);
2497
2364
  const handleClose = React3.useCallback(() => {
2498
2365
  if (paymentState === "processing" || paymentState === "confirming") {
2499
2366
  return;
2500
2367
  }
2501
- resetSolanaPayment();
2502
- setTransactionId(null);
2503
- onClose();
2504
- }, [paymentState, resetSolanaPayment, setTransactionId, onClose]);
2368
+ resetState();
2369
+ onClose?.();
2370
+ }, [paymentState, onClose, resetState]);
2505
2371
  React3.useEffect(() => {
2506
- if (!isOpen || !selectedToken || usdAmount === 0) {
2372
+ if (!selectedToken || usdAmount === 0) {
2507
2373
  setTokenAmount(0);
2508
2374
  return;
2509
2375
  }
@@ -2513,23 +2379,20 @@ var SolanaPaymentSelector = ({
2513
2379
  return;
2514
2380
  }
2515
2381
  setTokenAmount(usdAmount / price);
2516
- }, [isOpen, usdAmount, selectedToken, setTokenAmount]);
2517
- const handleTokenChange = React3.useCallback(
2518
- (value) => {
2519
- setSelectedTokenSymbol(value);
2520
- },
2521
- [setSelectedTokenSymbol]
2522
- );
2382
+ }, [usdAmount, selectedToken]);
2383
+ const handleTokenChange = React3.useCallback((value) => {
2384
+ setSelectedTokenSymbol(value);
2385
+ }, []);
2523
2386
  const wasConnectedRef = React3.useRef(connected);
2524
2387
  React3.useEffect(() => {
2525
2388
  if (connected && !wasConnectedRef.current) {
2526
- setTab("wallet");
2389
+ setActiveTab("wallet");
2527
2390
  }
2528
2391
  if (!connected && wasConnectedRef.current) {
2529
- setTab("qr");
2392
+ setActiveTab("qr");
2530
2393
  }
2531
2394
  wasConnectedRef.current = connected;
2532
- }, [connected, setTab]);
2395
+ }, [connected]);
2533
2396
  const renderBody = () => {
2534
2397
  if (paymentState !== "selecting") {
2535
2398
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -2545,63 +2408,79 @@ var SolanaPaymentSelector = ({
2545
2408
  }
2546
2409
  );
2547
2410
  }
2548
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: tokensLoading ? /* @__PURE__ */ jsxRuntime.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: [
2549
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
2550
- " Loading supported tokens\u2026"
2551
- ] }) : tokensError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: tokensError }) : !tokens.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-border/60 bg-muted/10 px-4 py-6 text-sm text-muted-foreground", children: "No payment tokens available." }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2552
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-border/60 bg-muted/10 p-4 text-center", children: [
2553
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-2xl font-semibold text-foreground", children: [
2411
+ if (tokensLoading) {
2412
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center py-10 text-sm text-muted-foreground", children: [
2413
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
2414
+ " Loading supported tokens\u2026"
2415
+ ] });
2416
+ }
2417
+ if (tokensError) {
2418
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: tokensError });
2419
+ }
2420
+ if (!tokens.length) {
2421
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "No payment tokens available." });
2422
+ }
2423
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
2424
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 text-center", children: [
2425
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Amount due" }),
2426
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-3xl font-semibold text-foreground", children: [
2554
2427
  "$",
2555
2428
  usdAmount.toFixed(2),
2556
2429
  " USD"
2557
2430
  ] }),
2558
- selectedToken && tokenAmount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-muted-foreground", children: [
2431
+ selectedToken && tokenAmount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
2559
2432
  "\u2248 ",
2560
2433
  tokenAmount.toFixed(selectedToken.symbol === "SOL" ? 4 : 2),
2561
2434
  " ",
2562
2435
  selectedToken.symbol
2563
2436
  ] })
2564
2437
  ] }),
2565
- /* @__PURE__ */ jsxRuntime.jsxs(Select, { value: selectedToken?.symbol ?? "", onValueChange: handleTokenChange, children: [
2566
- /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select token" }) }),
2567
- /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { className: "max-h-64", children: tokens.map((token) => /* @__PURE__ */ jsxRuntime.jsxs(SelectItem, { value: token.symbol, children: [
2568
- token.name,
2569
- " (",
2570
- token.symbol,
2571
- ")"
2572
- ] }, token.symbol)) })
2438
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2439
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: "Select token" }),
2440
+ /* @__PURE__ */ jsxRuntime.jsxs(Select, { value: selectedToken?.symbol ?? "", onValueChange: handleTokenChange, children: [
2441
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select token" }) }),
2442
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { className: "max-h-64", children: tokens.map((token) => /* @__PURE__ */ jsxRuntime.jsxs(SelectItem, { value: token.symbol, children: [
2443
+ token.name,
2444
+ " (",
2445
+ token.symbol,
2446
+ ")"
2447
+ ] }, token.symbol)) })
2448
+ ] })
2573
2449
  ] }),
2574
- /* @__PURE__ */ jsxRuntime.jsxs(
2450
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
2575
2451
  Tabs,
2576
2452
  {
2577
2453
  value: activeTab,
2578
- onValueChange: (value) => setTab(value),
2579
- className: "w-full",
2454
+ onValueChange: (value) => setActiveTab(value),
2455
+ className: "w-full space-y-3",
2580
2456
  children: [
2581
- /* @__PURE__ */ jsxRuntime.jsxs(TabsList, { className: "grid w-full grid-cols-2 bg-muted/20", children: [
2457
+ /* @__PURE__ */ jsxRuntime.jsxs(TabsList, { className: "grid w-full grid-cols-2 bg-muted/10", children: [
2582
2458
  /* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "wallet", disabled: !connected, children: [
2583
2459
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "mr-2 h-4 w-4" }),
2584
- " Pay with Wallet"
2460
+ " Wallet"
2585
2461
  ] }),
2586
2462
  /* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "qr", children: [
2587
2463
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "mr-2 h-4 w-4" }),
2588
- " Scan QR Code"
2464
+ " QR Code"
2589
2465
  ] })
2590
2466
  ] }),
2591
- /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "wallet", className: "mt-4", children: activeTab === "wallet" && /* @__PURE__ */ jsxRuntime.jsx(
2592
- DirectPayment,
2593
- {
2594
- priceId,
2595
- tokenAmount,
2596
- selectedToken,
2597
- supportedTokens: tokens,
2598
- onPaymentStart: handlePaymentStart,
2599
- onPaymentConfirming: handlePaymentConfirming,
2600
- onPaymentSuccess: handlePaymentSuccess,
2601
- onPaymentError: handlePaymentError
2602
- }
2603
- ) }),
2604
- /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "qr", className: "mt-4", children: activeTab === "qr" && /* @__PURE__ */ jsxRuntime.jsx(
2467
+ /* @__PURE__ */ jsxRuntime.jsxs(TabsContent, { value: "wallet", className: "space-y-4", children: [
2468
+ activeTab === "wallet" && /* @__PURE__ */ jsxRuntime.jsx(
2469
+ DirectPayment,
2470
+ {
2471
+ priceId,
2472
+ tokenAmount,
2473
+ selectedToken,
2474
+ supportedTokens: tokens,
2475
+ onPaymentStart: handlePaymentStart,
2476
+ onPaymentConfirming: handlePaymentConfirming,
2477
+ onPaymentSuccess: handlePaymentSuccess,
2478
+ onPaymentError: handlePaymentError
2479
+ }
2480
+ ),
2481
+ !connected && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-amber-100", children: "Connect your Solana wallet to continue or switch to QR mode." })
2482
+ ] }),
2483
+ /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "qr", children: activeTab === "qr" && /* @__PURE__ */ jsxRuntime.jsx(
2605
2484
  QRCodePayment,
2606
2485
  {
2607
2486
  priceId,
@@ -2612,165 +2491,741 @@ var SolanaPaymentSelector = ({
2612
2491
  ) })
2613
2492
  ]
2614
2493
  }
2615
- ),
2616
- !connected && activeTab === "wallet" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-amber-500/40 bg-amber-500/10 p-4 text-sm text-amber-100", children: "Please connect your Solana wallet to complete this payment, or switch to QR mode." })
2617
- ] }) });
2494
+ ) })
2495
+ ] });
2618
2496
  };
2619
- return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-lg", children: [
2620
- /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { className: "space-y-1", children: [
2621
- /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Complete your payment" }),
2622
- /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Select a token and preferred method. We\u2019ll guide you through the rest." })
2497
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
2498
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
2499
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
2500
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs uppercase tracking-wide text-muted-foreground", children: "Solana Pay checkout" }),
2501
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-2xl font-semibold text-foreground", children: "Pay with Solana" }),
2502
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Choose a supported token and send the payment with your wallet or a QR code." })
2503
+ ] }),
2504
+ onClose && /* @__PURE__ */ jsxRuntime.jsxs(
2505
+ Button,
2506
+ {
2507
+ type: "button",
2508
+ size: "sm",
2509
+ variant: "ghost",
2510
+ onClick: handleClose,
2511
+ disabled: paymentState === "processing" || paymentState === "confirming",
2512
+ className: "h-8 px-2 text-sm",
2513
+ children: [
2514
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "mr-2 h-4 w-4" }),
2515
+ " Back"
2516
+ ]
2517
+ }
2518
+ )
2623
2519
  ] }),
2624
2520
  renderBody()
2625
- ] }) });
2521
+ ] });
2626
2522
  };
2627
- var PaymentExperience = ({
2628
- priceId,
2629
- usdAmount,
2630
- onNewCardPayment,
2631
- onSavedMethodPayment,
2632
- enableNewCard = true,
2633
- enableStoredMethods = true,
2634
- enableSolanaPay = true,
2635
- checkoutSummary,
2636
- onSolanaSuccess,
2637
- onSolanaError
2638
- }) => {
2639
- const showNewCard = enableNewCard && Boolean(onNewCardPayment);
2640
- const showStored = enableStoredMethods;
2641
- const {
2642
- selectedMethodId,
2643
- savedStatus,
2644
- savedError,
2645
- newCardStatus,
2646
- newCardError,
2647
- solanaModalOpen,
2648
- setSelectedMethod,
2649
- setSolanaModalOpen,
2650
- startSavedPayment,
2651
- completeSavedPayment,
2652
- failSavedPayment,
2653
- startNewCardPayment,
2654
- completeNewCardPayment,
2655
- failNewCardPayment,
2656
- resetSavedPayment
2657
- } = usePaymentStore(selectCheckoutFlow);
2658
- const handleMethodSelect = (method) => {
2659
- setSelectedMethod(method.id);
2660
- resetSavedPayment();
2661
- };
2662
- const handleNewCardTokenize = async (token, billing) => {
2663
- if (!onNewCardPayment) return;
2664
- try {
2665
- startNewCardPayment();
2666
- await onNewCardPayment({ token, billing });
2667
- completeNewCardPayment();
2668
- } catch (error) {
2669
- const message = error instanceof Error ? error.message : "Unable to complete payment";
2670
- failNewCardPayment(message);
2671
- }
2672
- };
2673
- const handleSavedPayment = async () => {
2674
- if (!onSavedMethodPayment || !selectedMethodId) return;
2675
- try {
2676
- startSavedPayment();
2677
- await onSavedMethodPayment({
2678
- paymentMethodId: selectedMethodId,
2679
- amount: usdAmount
2680
- });
2681
- completeSavedPayment();
2682
- } catch (error) {
2683
- const message = error instanceof Error ? error.message : "Unable to complete payment with saved card";
2684
- failSavedPayment(message);
2523
+ var useSubscriptionActions = () => {
2524
+ const { services } = usePaymentContext();
2525
+ const ensurePrice = (priceId) => {
2526
+ if (!priceId) {
2527
+ throw new Error("payments-ui: priceId is required for subscription actions");
2685
2528
  }
2529
+ return priceId;
2686
2530
  };
2687
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-8", children: [
2688
- /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "border-border/60 bg-card/95", children: [
2689
- /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
2690
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2691
- /* @__PURE__ */ jsxRuntime.jsxs(CardTitle, { className: "flex items-center gap-2 text-lg text-foreground", children: [
2692
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "h-5 w-5 text-primary" }),
2693
- " Secure checkout"
2694
- ] }),
2695
- /* @__PURE__ */ jsxRuntime.jsxs(CardDescription, { children: [
2696
- "Amount due: $",
2697
- usdAmount.toFixed(2)
2698
- ] })
2699
- ] }),
2700
- checkoutSummary && /* @__PURE__ */ jsxRuntime.jsx("div", { children: checkoutSummary })
2701
- ] }),
2702
- /* @__PURE__ */ jsxRuntime.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 lg:grid-cols-2", children: [
2703
- showStored && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
2704
- /* @__PURE__ */ jsxRuntime.jsx(
2705
- StoredPaymentMethods,
2706
- {
2707
- selectedMethodId,
2708
- onMethodSelect: handleMethodSelect,
2709
- heading: "Saved cards",
2710
- description: "Use or manage your saved payment methods."
2711
- }
2712
- ),
2713
- onSavedMethodPayment && /* @__PURE__ */ jsxRuntime.jsx(
2714
- Button,
2715
- {
2716
- className: "w-full",
2717
- disabled: !selectedMethodId || savedStatus === "processing",
2718
- onClick: handleSavedPayment,
2719
- children: savedStatus === "processing" ? "Processing\u2026" : "Pay with selected card"
2720
- }
2721
- ),
2722
- savedError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: savedError })
2723
- ] }),
2724
- showNewCard && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl border border-border/60 bg-background/80 p-6", children: [
2725
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 space-y-1", children: [
2726
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: [
2727
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "h-4 w-4" }),
2728
- " Pay with a new card"
2729
- ] }),
2730
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Card details are tokenized via Collect.js and never hit your server." })
2731
- ] }),
2732
- /* @__PURE__ */ jsxRuntime.jsx(
2733
- CardDetailsForm,
2734
- {
2735
- visible: true,
2736
- submitLabel: "Pay now",
2737
- submitting: newCardStatus === "processing",
2738
- externalError: newCardError,
2739
- onTokenize: handleNewCardTokenize
2740
- }
2741
- )
2742
- ] }) })
2743
- ] }) })
2744
- ] }),
2745
- enableSolanaPay && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "border border-primary/40 bg-primary/5", children: /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "flex flex-col gap-4 text-sm text-primary md:flex-row md:items-center md:justify-between", children: [
2746
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2747
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 text-base font-semibold text-primary", children: [
2748
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-4 w-4" }),
2749
- " Prefer Solana Pay?"
2750
- ] }),
2751
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-primary/80", children: "Use a Solana wallet or QR code for instant settlement." })
2752
- ] }),
2753
- /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setSolanaModalOpen(true), children: "Open Solana Pay" })
2754
- ] }) }),
2755
- enableSolanaPay && /* @__PURE__ */ jsxRuntime.jsx(
2756
- SolanaPaymentSelector,
2757
- {
2758
- isOpen: solanaModalOpen,
2759
- onClose: () => setSolanaModalOpen(false),
2760
- priceId,
2761
- usdAmount,
2762
- onSuccess: (result) => {
2763
- setSolanaModalOpen(false);
2764
- onSolanaSuccess?.(result);
2765
- },
2766
- onError: onSolanaError
2767
- }
2768
- )
2769
- ] });
2770
- };
2771
- var Table = React3__namespace.forwardRef(
2772
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2773
- "table",
2531
+ const subscribeWithCard = React3.useCallback(
2532
+ async ({
2533
+ priceId,
2534
+ processor = "nmi",
2535
+ provider,
2536
+ paymentToken,
2537
+ billing
2538
+ }) => {
2539
+ const payload = {
2540
+ priceId: ensurePrice(priceId),
2541
+ paymentToken,
2542
+ processor,
2543
+ provider,
2544
+ email: billing.email,
2545
+ firstName: billing.firstName,
2546
+ lastName: billing.lastName,
2547
+ address1: billing.address1,
2548
+ city: billing.city,
2549
+ state: billing.stateRegion,
2550
+ zipCode: billing.postalCode,
2551
+ country: billing.country
2552
+ };
2553
+ return services.subscriptions.subscribe("nmi", payload);
2554
+ },
2555
+ [services]
2556
+ );
2557
+ const subscribeWithSavedMethod = React3.useCallback(
2558
+ async ({
2559
+ priceId,
2560
+ processor = "nmi",
2561
+ provider,
2562
+ paymentMethodId,
2563
+ email
2564
+ }) => {
2565
+ const payload = {
2566
+ priceId: ensurePrice(priceId),
2567
+ paymentMethodId,
2568
+ processor,
2569
+ provider,
2570
+ email
2571
+ };
2572
+ return services.subscriptions.subscribe("nmi", payload);
2573
+ },
2574
+ [services]
2575
+ );
2576
+ const subscribeWithCCBill = React3.useCallback(
2577
+ async ({
2578
+ priceId,
2579
+ email,
2580
+ firstName,
2581
+ lastName,
2582
+ zipCode,
2583
+ country,
2584
+ processor = "ccbill"
2585
+ }) => {
2586
+ const payload = {
2587
+ priceId: ensurePrice(priceId),
2588
+ email,
2589
+ firstName,
2590
+ lastName,
2591
+ zipCode,
2592
+ country,
2593
+ processor
2594
+ };
2595
+ return services.subscriptions.subscribe("ccbill", payload);
2596
+ },
2597
+ [services]
2598
+ );
2599
+ const generateFlexFormUrl = React3.useCallback(
2600
+ async ({
2601
+ priceId,
2602
+ firstName,
2603
+ lastName,
2604
+ address1,
2605
+ city,
2606
+ state,
2607
+ zipCode,
2608
+ country
2609
+ }) => {
2610
+ const payload = {
2611
+ price_id: ensurePrice(priceId),
2612
+ first_name: firstName,
2613
+ last_name: lastName,
2614
+ address1,
2615
+ city,
2616
+ state,
2617
+ zip_code: zipCode,
2618
+ country
2619
+ };
2620
+ return services.subscriptions.generateFlexFormUrl(payload);
2621
+ },
2622
+ [services]
2623
+ );
2624
+ return {
2625
+ subscribeWithCard,
2626
+ subscribeWithSavedMethod,
2627
+ subscribeWithCCBill,
2628
+ generateFlexFormUrl
2629
+ };
2630
+ };
2631
+
2632
+ // src/hooks/useAlternativePaymentProvider.ts
2633
+ var useAlternativePaymentProvider = () => {
2634
+ const [isLoading, setIsLoading] = React3.useState(false);
2635
+ const [error, setError] = React3.useState(null);
2636
+ const { generateFlexFormUrl } = useSubscriptionActions();
2637
+ const openFlexForm = React3.useCallback(
2638
+ async (payload) => {
2639
+ setIsLoading(true);
2640
+ setError(null);
2641
+ try {
2642
+ const response = await generateFlexFormUrl(payload);
2643
+ if (response?.iframe_url) {
2644
+ window.location.href = response.iframe_url;
2645
+ } else {
2646
+ throw new Error("Unable to launch payment provider.");
2647
+ }
2648
+ } catch (err) {
2649
+ const message = err instanceof Error ? err.message : "Failed to open payment provider.";
2650
+ setError(message);
2651
+ console.error("[payments-ui] failed to open alternative payment provider", err);
2652
+ } finally {
2653
+ setIsLoading(false);
2654
+ }
2655
+ },
2656
+ [generateFlexFormUrl]
2657
+ );
2658
+ return { openFlexForm, isLoading, error };
2659
+ };
2660
+ var PaymentExperience = ({
2661
+ priceId,
2662
+ usdAmount,
2663
+ onNewCardPayment,
2664
+ onSavedMethodPayment,
2665
+ enableNewCard = true,
2666
+ enableStoredMethods = true,
2667
+ enableSolanaPay = true,
2668
+ enableAlternativePayments = true,
2669
+ onSolanaSuccess,
2670
+ onSolanaError,
2671
+ initialMode = "cards"
2672
+ }) => {
2673
+ const showNewCard = enableNewCard && Boolean(onNewCardPayment);
2674
+ const showStored = enableStoredMethods && Boolean(onSavedMethodPayment);
2675
+ const defaultTab = showStored ? "saved" : "new";
2676
+ const [activeTab, setActiveTab] = React3.useState(defaultTab);
2677
+ const [mode, setMode] = React3.useState(
2678
+ () => initialMode === "solana" && enableSolanaPay ? "solana" : "cards"
2679
+ );
2680
+ const [selectedMethodId, setSelectedMethodId] = React3.useState(null);
2681
+ const [savedStatus, setSavedStatus] = React3.useState("idle");
2682
+ const [savedError, setSavedError] = React3.useState(null);
2683
+ const [newCardStatus, setNewCardStatus] = React3.useState("idle");
2684
+ const [newCardError, setNewCardError] = React3.useState(null);
2685
+ const [billingDetails, setBillingDetails] = React3.useState(null);
2686
+ const [alternativePaymentError, setAlternativePaymentError] = React3.useState(null);
2687
+ const { notifyStatus, notifySuccess, notifyError } = usePaymentNotifications();
2688
+ const {
2689
+ openFlexForm,
2690
+ isLoading: flexFormLoading,
2691
+ error: flexFormError
2692
+ } = useAlternativePaymentProvider();
2693
+ React3.useEffect(() => {
2694
+ setActiveTab(showStored ? "saved" : "new");
2695
+ }, [showStored]);
2696
+ React3.useEffect(() => {
2697
+ if (!enableSolanaPay) {
2698
+ setMode("cards");
2699
+ return;
2700
+ }
2701
+ if (initialMode === "solana") {
2702
+ setMode("solana");
2703
+ } else {
2704
+ setMode("cards");
2705
+ }
2706
+ }, [enableSolanaPay, initialMode]);
2707
+ const handleMethodSelect = React3.useCallback((method) => {
2708
+ setSelectedMethodId(method.id);
2709
+ setSavedStatus("idle");
2710
+ setSavedError(null);
2711
+ }, []);
2712
+ const handleSavedPayment = React3.useCallback(async () => {
2713
+ if (!onSavedMethodPayment || !selectedMethodId) return;
2714
+ try {
2715
+ setSavedStatus("processing");
2716
+ setSavedError(null);
2717
+ notifyStatus("processing", { source: "saved-payment" });
2718
+ await onSavedMethodPayment({
2719
+ paymentMethodId: selectedMethodId,
2720
+ amount: usdAmount
2721
+ });
2722
+ setSavedStatus("success");
2723
+ notifyStatus("success", { source: "saved-payment" });
2724
+ } catch (error) {
2725
+ const message = error instanceof Error ? error.message : "Unable to complete payment with saved card";
2726
+ setSavedStatus("error");
2727
+ setSavedError(message);
2728
+ notifyStatus("error", { source: "saved-payment" });
2729
+ notifyError(message);
2730
+ }
2731
+ }, [notifyError, notifyStatus, onSavedMethodPayment, selectedMethodId, usdAmount]);
2732
+ const handleNewCardTokenize = React3.useCallback(
2733
+ async (token, billing) => {
2734
+ if (!onNewCardPayment) return;
2735
+ try {
2736
+ setNewCardStatus("processing");
2737
+ setNewCardError(null);
2738
+ notifyStatus("processing", { source: "new-card" });
2739
+ await onNewCardPayment({ token, billing });
2740
+ setNewCardStatus("success");
2741
+ notifyStatus("success", { source: "new-card" });
2742
+ } catch (error) {
2743
+ const message = error instanceof Error ? error.message : "Unable to complete payment";
2744
+ setNewCardStatus("error");
2745
+ setNewCardError(message);
2746
+ notifyStatus("error", { source: "new-card" });
2747
+ notifyError(message);
2748
+ }
2749
+ },
2750
+ [notifyError, notifyStatus, onNewCardPayment]
2751
+ );
2752
+ const showSolanaView = React3.useCallback(() => {
2753
+ if (!enableSolanaPay) return;
2754
+ setMode("solana");
2755
+ }, [enableSolanaPay]);
2756
+ const exitSolanaView = React3.useCallback(() => {
2757
+ setMode("cards");
2758
+ }, []);
2759
+ const handleSolanaSuccess = React3.useCallback(
2760
+ (result) => {
2761
+ onSolanaSuccess?.(result);
2762
+ exitSolanaView();
2763
+ },
2764
+ [exitSolanaView, onSolanaSuccess]
2765
+ );
2766
+ const handleSolanaError = React3.useCallback(
2767
+ (error) => {
2768
+ onSolanaError?.(error);
2769
+ },
2770
+ [onSolanaError]
2771
+ );
2772
+ const handleAlternativePayment = React3.useCallback(() => {
2773
+ if (!enableAlternativePayments || !priceId) {
2774
+ return;
2775
+ }
2776
+ if (!billingDetails) {
2777
+ setAlternativePaymentError("Enter your billing details first.");
2778
+ return;
2779
+ }
2780
+ const requiredFields = [
2781
+ "firstName",
2782
+ "lastName",
2783
+ "address1",
2784
+ "city",
2785
+ "stateRegion",
2786
+ "postalCode",
2787
+ "country"
2788
+ ];
2789
+ const missingField = requiredFields.find((field) => {
2790
+ const value = billingDetails[field];
2791
+ return typeof value !== "string" || value.trim().length === 0;
2792
+ });
2793
+ if (missingField) {
2794
+ setAlternativePaymentError("Please complete your billing address before continuing.");
2795
+ return;
2796
+ }
2797
+ setAlternativePaymentError(null);
2798
+ openFlexForm({
2799
+ priceId,
2800
+ firstName: billingDetails.firstName,
2801
+ lastName: billingDetails.lastName,
2802
+ address1: billingDetails.address1,
2803
+ city: billingDetails.city,
2804
+ state: billingDetails.stateRegion ?? "",
2805
+ zipCode: billingDetails.postalCode,
2806
+ country: billingDetails.country
2807
+ });
2808
+ }, [
2809
+ billingDetails,
2810
+ enableAlternativePayments,
2811
+ openFlexForm,
2812
+ priceId
2813
+ ]);
2814
+ const renderSavedTab = () => {
2815
+ if (!showStored) {
2816
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Saved payment methods are unavailable right now. Add a new card to get started." });
2817
+ }
2818
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
2819
+ /* @__PURE__ */ jsxRuntime.jsx(
2820
+ StoredPaymentMethods,
2821
+ {
2822
+ heading: "Saved cards",
2823
+ selectedMethodId,
2824
+ onMethodSelect: handleMethodSelect,
2825
+ description: "Select one of your stored payment methods.",
2826
+ showAddButton: false
2827
+ }
2828
+ ),
2829
+ /* @__PURE__ */ jsxRuntime.jsx(
2830
+ Button,
2831
+ {
2832
+ className: "w-full",
2833
+ disabled: !selectedMethodId || savedStatus === "processing",
2834
+ onClick: handleSavedPayment,
2835
+ children: savedStatus === "processing" ? "Processing\u2026" : "Pay with selected card"
2836
+ }
2837
+ ),
2838
+ savedError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: savedError })
2839
+ ] });
2840
+ };
2841
+ const renderNewTab = () => {
2842
+ if (!showNewCard) {
2843
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Select a subscription plan to add a new card." });
2844
+ }
2845
+ return /* @__PURE__ */ jsxRuntime.jsx(
2846
+ CardDetailsForm,
2847
+ {
2848
+ visible: true,
2849
+ submitLabel: "Pay now",
2850
+ externalError: newCardError,
2851
+ onTokenize: handleNewCardTokenize,
2852
+ submitting: newCardStatus === "processing",
2853
+ onBillingChange: setBillingDetails
2854
+ }
2855
+ );
2856
+ };
2857
+ const renderCardExperience = () => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2858
+ /* @__PURE__ */ jsxRuntime.jsxs(
2859
+ Tabs,
2860
+ {
2861
+ value: activeTab,
2862
+ onValueChange: (value) => setActiveTab(value),
2863
+ className: "space-y-3",
2864
+ children: [
2865
+ /* @__PURE__ */ jsxRuntime.jsxs(TabsList, { className: "grid w-full grid-cols-2 border border-border/60", children: [
2866
+ /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { value: "saved", disabled: !showStored, children: "Use saved card" }),
2867
+ /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { value: "new", disabled: !showNewCard, children: "Add new card" })
2868
+ ] }),
2869
+ /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "saved", className: "space-y-4", children: renderSavedTab() }),
2870
+ /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "new", className: "space-y-4", children: renderNewTab() })
2871
+ ]
2872
+ }
2873
+ ),
2874
+ enableSolanaPay && /* @__PURE__ */ jsxRuntime.jsxs(Button, { className: "w-full", variant: "secondary", onClick: showSolanaView, children: [
2875
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "mr-2 h-4 w-4" }),
2876
+ " Pay with Solana"
2877
+ ] })
2878
+ ] });
2879
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 pt-4", children: [
2880
+ mode === "cards" && renderCardExperience(),
2881
+ mode === "cards" && enableAlternativePayments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 text-center text-sm text-muted-foreground", children: [
2882
+ /* @__PURE__ */ jsxRuntime.jsx(
2883
+ "button",
2884
+ {
2885
+ type: "button",
2886
+ className: "text-primary underline-offset-4 hover:underline disabled:opacity-60",
2887
+ onClick: handleAlternativePayment,
2888
+ disabled: flexFormLoading || !priceId,
2889
+ children: flexFormLoading ? "Preparing alternative checkout\u2026" : "Prefer a different processor? Pay with CCBill"
2890
+ }
2891
+ ),
2892
+ (alternativePaymentError || flexFormError) && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: alternativePaymentError || flexFormError })
2893
+ ] }),
2894
+ mode === "solana" && enableSolanaPay && /* @__PURE__ */ jsxRuntime.jsx(
2895
+ SolanaPaymentView,
2896
+ {
2897
+ priceId,
2898
+ usdAmount,
2899
+ onSuccess: handleSolanaSuccess,
2900
+ onError: handleSolanaError,
2901
+ onClose: exitSolanaView
2902
+ }
2903
+ )
2904
+ ] });
2905
+ };
2906
+ var SubscriptionSuccessDialog = ({
2907
+ open,
2908
+ planName = "Premium Plan",
2909
+ amountLabel = "$0.00",
2910
+ billingPeriodLabel = "billing period",
2911
+ onClose
2912
+ }) => {
2913
+ return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: (value) => {
2914
+ if (!value) onClose();
2915
+ }, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "w-full max-w-md overflow-hidden border border-border/70 bg-background/95 p-0 shadow-2xl", children: [
2916
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-gradient-to-b from-primary/25 via-primary/10 to-background px-6 py-8 text-center", children: [
2917
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-background/60", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "h-10 w-10 text-primary" }) }),
2918
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
2919
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "text-2xl font-semibold text-foreground", children: "Subscription activated" }),
2920
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogDescription, { className: "text-base text-muted-foreground", children: [
2921
+ "You now have access to ",
2922
+ planName,
2923
+ ". Billing: ",
2924
+ amountLabel,
2925
+ " / ",
2926
+ billingPeriodLabel,
2927
+ "."
2928
+ ] })
2929
+ ] })
2930
+ ] }),
2931
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-6", children: /* @__PURE__ */ jsxRuntime.jsx(Button, { className: "w-full", onClick: onClose, children: "Continue exploring" }) })
2932
+ ] }) });
2933
+ };
2934
+ var SubscriptionCheckoutModal = ({
2935
+ open,
2936
+ onOpenChange,
2937
+ priceId,
2938
+ usdAmount = 0,
2939
+ planName,
2940
+ amountLabel,
2941
+ billingPeriodLabel,
2942
+ userEmail,
2943
+ provider = "mobius",
2944
+ onSuccess,
2945
+ enableSolanaPay = true,
2946
+ onSolanaSuccess,
2947
+ onSolanaError,
2948
+ initialMode = "cards"
2949
+ }) => {
2950
+ const [showSuccess, setShowSuccess] = React3.useState(false);
2951
+ const { subscribeWithCard, subscribeWithSavedMethod } = useSubscriptionActions();
2952
+ const handleClose = React3.useCallback(
2953
+ (nextOpen) => {
2954
+ onOpenChange(nextOpen);
2955
+ if (!nextOpen) setShowSuccess(false);
2956
+ },
2957
+ [onOpenChange]
2958
+ );
2959
+ const ensurePrice = () => {
2960
+ if (!priceId) throw new Error("Select a plan before subscribing.");
2961
+ return priceId;
2962
+ };
2963
+ const notifySuccess = (result) => {
2964
+ setShowSuccess(true);
2965
+ onSuccess?.();
2966
+ if (result && typeof window !== "undefined") {
2967
+ console.debug("[payments-ui] subscription success", result);
2968
+ }
2969
+ };
2970
+ const handleNewCardPayment = async ({ token, billing }) => {
2971
+ await subscribeWithCard({
2972
+ priceId: ensurePrice(),
2973
+ provider,
2974
+ paymentToken: token,
2975
+ billing
2976
+ });
2977
+ notifySuccess();
2978
+ };
2979
+ const handleSavedMethodPayment = async ({ paymentMethodId }) => {
2980
+ await subscribeWithSavedMethod({
2981
+ priceId: ensurePrice(),
2982
+ provider,
2983
+ paymentMethodId,
2984
+ email: userEmail ?? ""
2985
+ });
2986
+ notifySuccess();
2987
+ };
2988
+ const solanaSuccess = (result) => {
2989
+ notifySuccess(result);
2990
+ onSolanaSuccess?.(result);
2991
+ onOpenChange(false);
2992
+ };
2993
+ const solanaError = (error) => {
2994
+ onSolanaError?.(error);
2995
+ };
2996
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2997
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("div", { className: "p-6 space-y-6", children: [
2998
+ !priceId && /* @__PURE__ */ jsxRuntime.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: [
2999
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-4 w-4" }),
3000
+ " Select a subscription plan to continue."
3001
+ ] }),
3002
+ /* @__PURE__ */ jsxRuntime.jsx(
3003
+ PaymentExperience,
3004
+ {
3005
+ usdAmount,
3006
+ priceId: priceId ?? "",
3007
+ onSolanaSuccess: solanaSuccess,
3008
+ onSolanaError: solanaError,
3009
+ enableNewCard: Boolean(priceId),
3010
+ enableStoredMethods: Boolean(priceId),
3011
+ enableSolanaPay: enableSolanaPay && Boolean(priceId),
3012
+ onNewCardPayment: priceId ? handleNewCardPayment : void 0,
3013
+ onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
3014
+ initialMode
3015
+ }
3016
+ )
3017
+ ] }) }) }),
3018
+ /* @__PURE__ */ jsxRuntime.jsx(
3019
+ SubscriptionSuccessDialog,
3020
+ {
3021
+ open: showSuccess,
3022
+ onClose: () => setShowSuccess(false),
3023
+ planName,
3024
+ amountLabel: amountLabel ?? `$${usdAmount.toFixed(2)}`,
3025
+ billingPeriodLabel
3026
+ }
3027
+ )
3028
+ ] });
3029
+ };
3030
+ var wallets = [
3031
+ {
3032
+ id: "phantom",
3033
+ name: "Phantom",
3034
+ icon: "https://phantom.app/img/logo.png"
3035
+ },
3036
+ {
3037
+ id: "solflare",
3038
+ name: "Solflare",
3039
+ icon: "https://solflare.com/favicon.ico"
3040
+ }
3041
+ ];
3042
+ var WalletModal = ({ open, onOpenChange }) => {
3043
+ const [expandedWallet, setExpandedWallet] = React3.useState(null);
3044
+ return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.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: [
3045
+ /* @__PURE__ */ jsxRuntime.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: [
3046
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex items-center gap-2 text-foreground", children: [
3047
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "h-5 w-5 text-primary" }),
3048
+ " Connect a Solana wallet"
3049
+ ] }),
3050
+ /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { className: "text-sm text-muted-foreground", children: "Pick a supported wallet to link with Doujins. Verified wallets unlock Solana payments and withdrawals." })
3051
+ ] }),
3052
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 space-y-4", children: [
3053
+ wallets.map((wallet) => /* @__PURE__ */ jsxRuntime.jsxs(
3054
+ "div",
3055
+ {
3056
+ className: "rounded-2xl border border-border/60 bg-background/80 p-4 shadow-sm",
3057
+ children: [
3058
+ /* @__PURE__ */ jsxRuntime.jsxs(
3059
+ "button",
3060
+ {
3061
+ className: "flex w-full items-center justify-between",
3062
+ onClick: () => setExpandedWallet((prev) => prev === wallet.id ? null : wallet.id),
3063
+ children: [
3064
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-left", children: [
3065
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src: wallet.icon, alt: wallet.name, className: "h-10 w-10 rounded-full" }),
3066
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3067
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold text-foreground", children: wallet.name }),
3068
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Browser extension or mobile app" })
3069
+ ] })
3070
+ ] }),
3071
+ expandedWallet === wallet.id ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "h-4 w-4 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4 text-muted-foreground" })
3072
+ ]
3073
+ }
3074
+ ),
3075
+ expandedWallet === wallet.id && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 space-y-3 text-sm text-muted-foreground", children: [
3076
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
3077
+ "Open the ",
3078
+ wallet.name,
3079
+ " wallet, approve the connection request, and confirm the signature prompt to finish linking."
3080
+ ] }),
3081
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { className: "w-full", variant: "outline", disabled: true, children: [
3082
+ "Connect with ",
3083
+ wallet.name,
3084
+ " (coming soon)"
3085
+ ] })
3086
+ ] })
3087
+ ]
3088
+ },
3089
+ wallet.id
3090
+ )),
3091
+ /* @__PURE__ */ jsxRuntime.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." })
3092
+ ] })
3093
+ ] }) });
3094
+ };
3095
+ var createDialogState = () => ({
3096
+ isOpen: false,
3097
+ props: null
3098
+ });
3099
+ var PaymentsDialogContext = React3.createContext(void 0);
3100
+ var PaymentsDialogProvider = ({
3101
+ children
3102
+ }) => {
3103
+ const [checkoutState, setCheckoutState] = React3.useState(
3104
+ () => createDialogState()
3105
+ );
3106
+ const [walletState, setWalletState] = React3.useState(
3107
+ () => createDialogState()
3108
+ );
3109
+ const contextValue = React3.useMemo(() => {
3110
+ const openCheckout = (options) => setCheckoutState({
3111
+ isOpen: true,
3112
+ props: options
3113
+ });
3114
+ return {
3115
+ checkout: {
3116
+ isOpen: checkoutState.isOpen,
3117
+ open: openCheckout,
3118
+ close: () => setCheckoutState(createDialogState())
3119
+ },
3120
+ solana: {
3121
+ isOpen: checkoutState.isOpen && checkoutState.props?.initialMode === "solana",
3122
+ open: (options) => openCheckout({
3123
+ priceId: options.priceId,
3124
+ usdAmount: options.usdAmount,
3125
+ enableSolanaPay: true,
3126
+ initialMode: "solana",
3127
+ onSolanaSuccess: options.onSuccess,
3128
+ onSolanaError: options.onError
3129
+ }),
3130
+ close: () => setCheckoutState(createDialogState())
3131
+ },
3132
+ wallet: {
3133
+ isOpen: walletState.isOpen,
3134
+ open: (options) => setWalletState({
3135
+ isOpen: true,
3136
+ props: options ?? null
3137
+ }),
3138
+ close: () => setWalletState(createDialogState())
3139
+ }
3140
+ };
3141
+ }, [checkoutState, walletState.isOpen]);
3142
+ return /* @__PURE__ */ jsxRuntime.jsxs(PaymentsDialogContext.Provider, { value: contextValue, children: [
3143
+ children,
3144
+ checkoutState.props && /* @__PURE__ */ jsxRuntime.jsx(
3145
+ SubscriptionCheckoutModal,
3146
+ {
3147
+ open: checkoutState.isOpen,
3148
+ onOpenChange: (open) => open ? setCheckoutState((prev) => ({ ...prev, isOpen: true })) : setCheckoutState(createDialogState()),
3149
+ ...checkoutState.props
3150
+ }
3151
+ ),
3152
+ /* @__PURE__ */ jsxRuntime.jsx(
3153
+ WalletModal,
3154
+ {
3155
+ open: walletState.isOpen,
3156
+ onOpenChange: (open) => open ? setWalletState((prev) => ({ ...prev, isOpen: true })) : setWalletState(createDialogState()),
3157
+ ...walletState.props ?? {}
3158
+ }
3159
+ )
3160
+ ] });
3161
+ };
3162
+ var usePaymentDialogs = () => {
3163
+ const context = React3.useContext(PaymentsDialogContext);
3164
+ if (!context) {
3165
+ throw new Error("usePaymentDialogs must be used within PaymentProvider");
3166
+ }
3167
+ return context;
3168
+ };
3169
+ var PaymentContext = React3.createContext(void 0);
3170
+ var PaymentProvider = ({
3171
+ config,
3172
+ runtime: runtimeProp,
3173
+ children
3174
+ }) => {
3175
+ const runtime = React3.useMemo(
3176
+ () => runtimeProp ?? createPaymentsRuntime(config),
3177
+ [runtimeProp, config]
3178
+ );
3179
+ const solanaEndpoint = React3.useMemo(() => {
3180
+ if (config.solana?.endpoint) return config.solana.endpoint;
3181
+ const network = config.solana?.network ?? WalletAdapterNetwork.Mainnet;
3182
+ return web3_js.clusterApiUrl(network);
3183
+ }, [config.solana?.endpoint, config.solana?.network]);
3184
+ const walletAdapters = React3.useMemo(() => {
3185
+ if (config.solana?.wallets?.length) {
3186
+ return config.solana.wallets;
3187
+ }
3188
+ return [
3189
+ new walletAdapterPhantom.PhantomWalletAdapter(),
3190
+ new walletAdapterSolflare.SolflareWalletAdapter(),
3191
+ new walletAdapterTrust.TrustWalletAdapter(),
3192
+ new walletAdapterCoinbase.CoinbaseWalletAdapter()
3193
+ ];
3194
+ }, [config.solana?.wallets]);
3195
+ const autoConnect = config.solana?.autoConnect ?? true;
3196
+ const value = React3.useMemo(() => {
3197
+ return {
3198
+ config: runtime.config,
3199
+ fetcher: runtime.app.getFetcher(),
3200
+ resolveAuthToken: runtime.app.resolveAuthToken,
3201
+ app: runtime.app,
3202
+ services: runtime.services,
3203
+ queryClient: runtime.queryClient
3204
+ };
3205
+ }, [runtime]);
3206
+ React3.useEffect(() => {
3207
+ if (!config.collectJsKey) return;
3208
+ loadCollectJs(config.collectJsKey);
3209
+ }, [config.collectJsKey]);
3210
+ return /* @__PURE__ */ jsxRuntime.jsx(PaymentContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: runtime.queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReact.ConnectionProvider, { endpoint: solanaEndpoint, config: { commitment: "confirmed" }, children: /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReact.WalletProvider, { wallets: walletAdapters, autoConnect, children: /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReactUi.WalletModalProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(PaymentsDialogProvider, { children }) }) }) }) }) });
3211
+ };
3212
+ var usePaymentContext = () => {
3213
+ const context = React3.useContext(PaymentContext);
3214
+ if (!context) {
3215
+ throw new Error("usePaymentContext must be used within a PaymentProvider");
3216
+ }
3217
+ return context;
3218
+ };
3219
+ var SolanaPaymentSelector = ({
3220
+ isOpen,
3221
+ onClose,
3222
+ ...props
3223
+ }) => {
3224
+ return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isOpen, onOpenChange: (value) => value ? void 0 : onClose(), children: /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(SolanaPaymentView, { ...props, onClose }) }) });
3225
+ };
3226
+ var Table = React3__namespace.forwardRef(
3227
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3228
+ "table",
2774
3229
  {
2775
3230
  ref,
2776
3231
  className: cn("w-full caption-bottom text-sm", className),
@@ -2952,7 +3407,7 @@ var CancelMembershipDialog = ({
2952
3407
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ban, { className: "mr-2 h-4 w-4" }),
2953
3408
  " Cancel Membership"
2954
3409
  ] }) }),
2955
- /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { className: "max-h-[90vh] overflow-y-auto rounded-xl border border-border bg-background", children: [
3410
+ /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { className: "max-h-[90vh] overflow-y-auto rounded-md border border-border bg-background", children: [
2956
3411
  /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogHeader, { children: [
2957
3412
  /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogTitle, { className: "flex items-center gap-2 text-lg font-semibold", children: [
2958
3413
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TriangleAlert, { className: "h-5 w-5 text-destructive" }),
@@ -3893,65 +4348,26 @@ var SolanaWalletSection = ({
3893
4348
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
3894
4349
  /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: registerWallet, disabled: isRegistering || walletConnection.isConnecting, className: "flex-1 bg-primary text-primary-foreground", children: isRegistering ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3895
4350
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
3896
- " Registering..."
3897
- ] }) : "Register This Wallet" }),
3898
- /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => disconnect(), variant: "outline", className: "border-border", children: "Disconnect" })
3899
- ] })
3900
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReactUi.WalletMultiButton, { className: "w-full !bg-primary text-primary-foreground" }) })
3901
- ] }) })
3902
- ] }),
3903
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialog, { open: !!walletToDelete, onOpenChange: () => setWalletToDelete(null), children: /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { children: [
3904
- /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogHeader, { children: [
3905
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogTitle, { children: "Remove Wallet" }),
3906
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogDescription, { children: "Are you sure you want to remove this wallet from your account? This action cannot be undone." })
3907
- ] }),
3908
- /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogFooter, { children: [
3909
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogCancel, { children: "Cancel" }),
3910
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogAction, { onClick: () => walletToDelete && handleDeleteWallet(walletToDelete.id), className: "bg-destructive text-destructive-foreground", children: "Remove" })
3911
- ] })
3912
- ] }) })
3913
- ] });
3914
- };
3915
- var WalletManagement = (props) => /* @__PURE__ */ jsxRuntime.jsx(SolanaWalletSection, { ...props });
3916
- var wallets = [
3917
- {
3918
- id: "phantom",
3919
- name: "Phantom",
3920
- icon: "https://phantom.app/img/logo.png"
3921
- },
3922
- {
3923
- id: "solflare",
3924
- name: "Solflare",
3925
- icon: "https://solflare.com/favicon.ico"
3926
- }
3927
- ];
3928
- var WalletModal = ({ open, onOpenChange }) => {
3929
- const [expandedWallet, setExpandedWallet] = React3.useState(null);
3930
- return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsx(DialogContent, { className: "max-w-md border border-border bg-background", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: wallets.map((wallet) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-border/80", children: [
3931
- /* @__PURE__ */ jsxRuntime.jsxs(
3932
- "button",
3933
- {
3934
- className: "flex w-full items-center justify-between px-4 py-3",
3935
- onClick: () => setExpandedWallet((prev) => prev === wallet.id ? null : wallet.id),
3936
- children: [
3937
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-left", children: [
3938
- /* @__PURE__ */ jsxRuntime.jsx("img", { src: wallet.icon, alt: wallet.name, className: "h-8 w-8 rounded-full" }),
3939
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3940
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold", children: wallet.name }),
3941
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Connect via browser extension" })
3942
- ] })
3943
- ] }),
3944
- expandedWallet === wallet.id ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "h-4 w-4 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4 text-muted-foreground" })
3945
- ]
3946
- }
3947
- ),
3948
- expandedWallet === wallet.id && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border/60 px-4 py-3 text-sm text-muted-foreground", children: [
3949
- "Follow the prompts in your ",
3950
- wallet.name,
3951
- " wallet to approve access."
3952
- ] })
3953
- ] }, wallet.id)) }) }) });
4351
+ " Registering..."
4352
+ ] }) : "Register This Wallet" }),
4353
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => disconnect(), variant: "outline", className: "border-border", children: "Disconnect" })
4354
+ ] })
4355
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReactUi.WalletMultiButton, { className: "w-full !bg-primary text-primary-foreground" }) })
4356
+ ] }) })
4357
+ ] }),
4358
+ /* @__PURE__ */ jsxRuntime.jsx(AlertDialog, { open: !!walletToDelete, onOpenChange: () => setWalletToDelete(null), children: /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { children: [
4359
+ /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogHeader, { children: [
4360
+ /* @__PURE__ */ jsxRuntime.jsx(AlertDialogTitle, { children: "Remove Wallet" }),
4361
+ /* @__PURE__ */ jsxRuntime.jsx(AlertDialogDescription, { children: "Are you sure you want to remove this wallet from your account? This action cannot be undone." })
4362
+ ] }),
4363
+ /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogFooter, { children: [
4364
+ /* @__PURE__ */ jsxRuntime.jsx(AlertDialogCancel, { children: "Cancel" }),
4365
+ /* @__PURE__ */ jsxRuntime.jsx(AlertDialogAction, { onClick: () => walletToDelete && handleDeleteWallet(walletToDelete.id), className: "bg-destructive text-destructive-foreground", children: "Remove" })
4366
+ ] })
4367
+ ] }) })
4368
+ ] });
3954
4369
  };
4370
+ var WalletManagement = (props) => /* @__PURE__ */ jsxRuntime.jsx(SolanaWalletSection, { ...props });
3955
4371
  var Checkbox = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3956
4372
  CheckboxPrimitive__namespace.Root,
3957
4373
  {
@@ -3971,7 +4387,7 @@ var Checkbox = React3__namespace.forwardRef(({ className, ...props }, ref) => /*
3971
4387
  }
3972
4388
  ));
3973
4389
  Checkbox.displayName = CheckboxPrimitive__namespace.Root.displayName;
3974
- var initialState2 = {
4390
+ var initialState = {
3975
4391
  nameOnCard: "",
3976
4392
  cardNumber: "",
3977
4393
  expiration: "",
@@ -3979,7 +4395,7 @@ var initialState2 = {
3979
4395
  termsAccepted: false
3980
4396
  };
3981
4397
  var WalletDialog = ({ open, onOpenChange }) => {
3982
- const [form, setForm] = React3.useState(initialState2);
4398
+ const [form, setForm] = React3.useState(initialState);
3983
4399
  const [errors, setErrors] = React3.useState({});
3984
4400
  const validators = React3.useMemo(
3985
4401
  () => ({
@@ -4012,7 +4428,7 @@ var WalletDialog = ({ open, onOpenChange }) => {
4012
4428
  if (!validate()) return;
4013
4429
  console.log("[payments-ui] wallet dialog submit", form);
4014
4430
  onOpenChange(false);
4015
- setForm(initialState2);
4431
+ setForm(initialState);
4016
4432
  };
4017
4433
  return /* @__PURE__ */ jsxRuntime.jsx(AlertDialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { className: "max-h-[95vh] max-w-lg overflow-y-auto rounded-2xl border border-border bg-background", children: [
4018
4434
  /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogHeader, { className: "border-b border-border/60 pb-4", children: [
@@ -4059,7 +4475,7 @@ var WalletDialog = ({ open, onOpenChange }) => {
4059
4475
  ] })
4060
4476
  ] })
4061
4477
  ] }),
4062
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 rounded-xl border border-border/70 bg-muted/10 p-4", children: [
4478
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 rounded-md border border-border/70 bg-muted/10 p-4", children: [
4063
4479
  /* @__PURE__ */ jsxRuntime.jsx(Checkbox, { id: "terms-agree", checked: form.termsAccepted, onCheckedChange: (checked) => updateField("termsAccepted", Boolean(checked)) }),
4064
4480
  /* @__PURE__ */ jsxRuntime.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." })
4065
4481
  ] }),
@@ -4071,245 +4487,6 @@ var WalletDialog = ({ open, onOpenChange }) => {
4071
4487
  ] })
4072
4488
  ] }) });
4073
4489
  };
4074
- var SubscriptionSuccessDialog = ({
4075
- open,
4076
- planName = "Premium Plan",
4077
- amountLabel = "$0.00",
4078
- billingPeriodLabel = "billing period",
4079
- onClose
4080
- }) => {
4081
- return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: (value) => {
4082
- if (!value) onClose();
4083
- }, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-w-sm text-center", children: [
4084
- /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
4085
- /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex flex-col items-center gap-3 text-foreground", children: [
4086
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "h-10 w-10 text-primary" }),
4087
- "Subscription activated"
4088
- ] }),
4089
- /* @__PURE__ */ jsxRuntime.jsxs(DialogDescription, { className: "text-base text-muted-foreground", children: [
4090
- "You now have access to ",
4091
- planName,
4092
- ". Billing: ",
4093
- amountLabel,
4094
- " / ",
4095
- billingPeriodLabel,
4096
- "."
4097
- ] })
4098
- ] }),
4099
- /* @__PURE__ */ jsxRuntime.jsx(Button, { className: "mt-6 w-full", onClick: onClose, children: "Continue" })
4100
- ] }) });
4101
- };
4102
- var useSubscriptionActions = () => {
4103
- const { services } = usePaymentContext();
4104
- const ensurePrice = (priceId) => {
4105
- if (!priceId) {
4106
- throw new Error("payments-ui: priceId is required for subscription actions");
4107
- }
4108
- return priceId;
4109
- };
4110
- const subscribeWithCard = React3.useCallback(
4111
- async ({
4112
- priceId,
4113
- processor = "nmi",
4114
- provider,
4115
- paymentToken,
4116
- billing
4117
- }) => {
4118
- const payload = {
4119
- priceId: ensurePrice(priceId),
4120
- paymentToken,
4121
- processor,
4122
- provider,
4123
- email: billing.email,
4124
- firstName: billing.firstName,
4125
- lastName: billing.lastName,
4126
- address1: billing.address1,
4127
- city: billing.city,
4128
- state: billing.stateRegion,
4129
- zipCode: billing.postalCode,
4130
- country: billing.country
4131
- };
4132
- return services.subscriptions.subscribe("nmi", payload);
4133
- },
4134
- [services]
4135
- );
4136
- const subscribeWithSavedMethod = React3.useCallback(
4137
- async ({
4138
- priceId,
4139
- processor = "nmi",
4140
- provider,
4141
- paymentMethodId,
4142
- email
4143
- }) => {
4144
- const payload = {
4145
- priceId: ensurePrice(priceId),
4146
- paymentMethodId,
4147
- processor,
4148
- provider,
4149
- email
4150
- };
4151
- return services.subscriptions.subscribe("nmi", payload);
4152
- },
4153
- [services]
4154
- );
4155
- const subscribeWithCCBill = React3.useCallback(
4156
- async ({
4157
- priceId,
4158
- email,
4159
- firstName,
4160
- lastName,
4161
- zipCode,
4162
- country,
4163
- processor = "ccbill"
4164
- }) => {
4165
- const payload = {
4166
- priceId: ensurePrice(priceId),
4167
- email,
4168
- firstName,
4169
- lastName,
4170
- zipCode,
4171
- country,
4172
- processor
4173
- };
4174
- return services.subscriptions.subscribe("ccbill", payload);
4175
- },
4176
- [services]
4177
- );
4178
- const generateFlexFormUrl = React3.useCallback(
4179
- async ({
4180
- priceId,
4181
- firstName,
4182
- lastName,
4183
- address1,
4184
- city,
4185
- state,
4186
- zipCode,
4187
- country
4188
- }) => {
4189
- const payload = {
4190
- price_id: ensurePrice(priceId),
4191
- first_name: firstName,
4192
- last_name: lastName,
4193
- address1,
4194
- city,
4195
- state,
4196
- zip_code: zipCode,
4197
- country
4198
- };
4199
- return services.subscriptions.generateFlexFormUrl(payload);
4200
- },
4201
- [services]
4202
- );
4203
- return {
4204
- subscribeWithCard,
4205
- subscribeWithSavedMethod,
4206
- subscribeWithCCBill,
4207
- generateFlexFormUrl
4208
- };
4209
- };
4210
- var SubscriptionCheckoutModal = ({
4211
- open,
4212
- onOpenChange,
4213
- priceId,
4214
- usdAmount = 0,
4215
- planName,
4216
- amountLabel,
4217
- billingPeriodLabel,
4218
- userEmail,
4219
- provider = "mobius",
4220
- onSuccess,
4221
- enableSolanaPay = true
4222
- }) => {
4223
- const [showSuccess, setShowSuccess] = React3.useState(false);
4224
- const { subscribeWithCard, subscribeWithSavedMethod } = useSubscriptionActions();
4225
- const handleClose = React3.useCallback(
4226
- (nextOpen) => {
4227
- onOpenChange(nextOpen);
4228
- if (!nextOpen) {
4229
- setShowSuccess(false);
4230
- }
4231
- },
4232
- [onOpenChange]
4233
- );
4234
- const ensurePrice = () => {
4235
- if (!priceId) {
4236
- throw new Error("Select a plan before subscribing.");
4237
- }
4238
- return priceId;
4239
- };
4240
- const notifySuccess = (result) => {
4241
- setShowSuccess(true);
4242
- onSuccess?.();
4243
- if (result && typeof window !== "undefined") {
4244
- console.debug("[payments-ui] subscription success", result);
4245
- }
4246
- };
4247
- const handleNewCardPayment = async ({ token, billing }) => {
4248
- await subscribeWithCard({
4249
- priceId: ensurePrice(),
4250
- provider,
4251
- paymentToken: token,
4252
- billing
4253
- });
4254
- notifySuccess();
4255
- };
4256
- const handleSavedMethodPayment = async ({ paymentMethodId }) => {
4257
- await subscribeWithSavedMethod({
4258
- priceId: ensurePrice(),
4259
- provider,
4260
- paymentMethodId,
4261
- email: userEmail ?? ""
4262
- });
4263
- notifySuccess();
4264
- };
4265
- const solanaSuccess = (result) => {
4266
- notifySuccess(result);
4267
- onOpenChange(false);
4268
- };
4269
- const summary = React3.useMemo(() => {
4270
- if (!planName && !amountLabel) return null;
4271
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-border/60 bg-muted/10 p-3 text-sm text-muted-foreground", children: [
4272
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-foreground", children: planName ?? "Selected plan" }),
4273
- /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
4274
- amountLabel ?? `$${usdAmount.toFixed(2)}`,
4275
- " ",
4276
- billingPeriodLabel ? `/ ${billingPeriodLabel}` : ""
4277
- ] })
4278
- ] });
4279
- }, [planName, amountLabel, billingPeriodLabel, usdAmount]);
4280
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4281
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "sm:max-w-3xl", children: [
4282
- !priceId && /* @__PURE__ */ jsxRuntime.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: [
4283
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-4 w-4" }),
4284
- " Select a subscription plan to continue."
4285
- ] }),
4286
- /* @__PURE__ */ jsxRuntime.jsx(
4287
- PaymentExperience,
4288
- {
4289
- priceId: priceId ?? "",
4290
- usdAmount,
4291
- checkoutSummary: summary,
4292
- onNewCardPayment: priceId ? handleNewCardPayment : void 0,
4293
- onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
4294
- enableNewCard: Boolean(priceId),
4295
- enableStoredMethods: Boolean(priceId),
4296
- enableSolanaPay: enableSolanaPay && Boolean(priceId),
4297
- onSolanaSuccess: solanaSuccess
4298
- }
4299
- )
4300
- ] }) }),
4301
- /* @__PURE__ */ jsxRuntime.jsx(
4302
- SubscriptionSuccessDialog,
4303
- {
4304
- open: showSuccess,
4305
- onClose: () => setShowSuccess(false),
4306
- planName,
4307
- amountLabel: amountLabel ?? `$${usdAmount.toFixed(2)}`,
4308
- billingPeriodLabel
4309
- }
4310
- )
4311
- ] });
4312
- };
4313
4490
  var useTokenBalance = (tokens) => {
4314
4491
  const { publicKey } = walletAdapterReact.useWallet();
4315
4492
  const { connection } = walletAdapterReact.useConnection();
@@ -4801,33 +4978,6 @@ var usePaymentStatus = (options = {}) => {
4801
4978
  isPending: getConfirmationStatus() === "pending"
4802
4979
  };
4803
4980
  };
4804
- var useAlternativePaymentProvider = () => {
4805
- const [isLoading, setIsLoading] = React3.useState(false);
4806
- const [error, setError] = React3.useState(null);
4807
- const { generateFlexFormUrl } = useSubscriptionActions();
4808
- const openFlexForm = React3.useCallback(
4809
- async (payload) => {
4810
- setIsLoading(true);
4811
- setError(null);
4812
- try {
4813
- const response = await generateFlexFormUrl(payload);
4814
- if (response?.iframe_url) {
4815
- window.location.href = response.iframe_url;
4816
- } else {
4817
- throw new Error("Unable to launch payment provider.");
4818
- }
4819
- } catch (err) {
4820
- const message = err instanceof Error ? err.message : "Failed to open payment provider.";
4821
- setError(message);
4822
- console.error("[payments-ui] failed to open alternative payment provider", err);
4823
- } finally {
4824
- setIsLoading(false);
4825
- }
4826
- },
4827
- [generateFlexFormUrl]
4828
- );
4829
- return { openFlexForm, isLoading, error };
4830
- };
4831
4981
 
4832
4982
  exports.BillingHistory = BillingHistory;
4833
4983
  exports.CancelMembershipDialog = CancelMembershipDialog;
@@ -4839,8 +4989,11 @@ exports.PaymentExperience = PaymentExperience;
4839
4989
  exports.PaymentMethodService = PaymentMethodService;
4840
4990
  exports.PaymentMethodsSection = PaymentMethodsSection;
4841
4991
  exports.PaymentProvider = PaymentProvider;
4992
+ exports.PaymentsDialogProvider = PaymentsDialogProvider;
4993
+ exports.PaymentsRuntime = PaymentsRuntime;
4842
4994
  exports.SolanaPaymentSelector = SolanaPaymentSelector;
4843
4995
  exports.SolanaPaymentService = SolanaPaymentService;
4996
+ exports.SolanaPaymentView = SolanaPaymentView;
4844
4997
  exports.SolanaWalletSection = SolanaWalletSection;
4845
4998
  exports.SolanaWalletService = SolanaWalletService;
4846
4999
  exports.StoredPaymentMethods = StoredPaymentMethods;
@@ -4853,14 +5006,15 @@ exports.WalletDialog = WalletDialog;
4853
5006
  exports.WalletGateway = WalletGateway;
4854
5007
  exports.WalletManagement = WalletManagement;
4855
5008
  exports.WalletModal = WalletModal;
4856
- exports.createPaymentStore = createPaymentStore;
5009
+ exports.createPaymentsRuntime = createPaymentsRuntime;
4857
5010
  exports.useAlternativePaymentProvider = useAlternativePaymentProvider;
4858
5011
  exports.useDirectWalletPayment = useDirectWalletPayment;
4859
5012
  exports.usePaymentContext = usePaymentContext;
5013
+ exports.usePaymentDialogs = usePaymentDialogs;
4860
5014
  exports.usePaymentMethodService = usePaymentMethodService;
4861
5015
  exports.usePaymentMethods = usePaymentMethods;
5016
+ exports.usePaymentNotifications = usePaymentNotifications;
4862
5017
  exports.usePaymentStatus = usePaymentStatus;
4863
- exports.usePaymentStore = usePaymentStore;
4864
5018
  exports.useSolanaDirectPayment = useSolanaDirectPayment;
4865
5019
  exports.useSolanaQrPayment = useSolanaQrPayment;
4866
5020
  exports.useSolanaService = useSolanaService;