@doujins/payments-ui 0.1.15 → 0.1.17-alpha

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,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React15 = require('react');
3
+ var React4 = require('react');
4
4
  var reactQuery = require('@tanstack/react-query');
5
5
  var walletAdapterReact = require('@solana/wallet-adapter-react');
6
6
  var walletAdapterReactUi = require('@solana/wallet-adapter-react-ui');
@@ -48,7 +48,7 @@ function _interopNamespace(e) {
48
48
  return Object.freeze(n);
49
49
  }
50
50
 
51
- var React15__namespace = /*#__PURE__*/_interopNamespace(React15);
51
+ var React4__namespace = /*#__PURE__*/_interopNamespace(React4);
52
52
  var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
53
53
  var clsx2__default = /*#__PURE__*/_interopDefault(clsx2);
54
54
  var countryList__default = /*#__PURE__*/_interopDefault(countryList);
@@ -281,6 +281,7 @@ var createClient = (config) => {
281
281
  return normalizeList(result);
282
282
  },
283
283
  createPaymentMethod(payload) {
284
+ console.log("Creating payment method with payload:", payload);
284
285
  return request("POST", "/me/payment-methods", {
285
286
  body: payload
286
287
  });
@@ -298,10 +299,10 @@ var createClient = (config) => {
298
299
  },
299
300
  checkout(payload, idempotencyKey) {
300
301
  const key = idempotencyKey ?? crypto.randomUUID();
301
- return request("POST", "/me/checkout", {
302
+ return request("POST", "/checkout", {
302
303
  body: payload,
303
304
  headers: {
304
- "Idempotency-Key": key
305
+ "X-Idempotency-Key": key
305
306
  }
306
307
  });
307
308
  },
@@ -310,6 +311,36 @@ var createClient = (config) => {
310
311
  body: feedback ? { feedback } : void 0
311
312
  });
312
313
  },
314
+ async listSubscriptions(params) {
315
+ const result = await request(
316
+ "GET",
317
+ "/me/subscriptions",
318
+ {
319
+ query: {
320
+ status: params?.status,
321
+ limit: params?.limit,
322
+ offset: params?.offset
323
+ }
324
+ }
325
+ );
326
+ return normalizeList(result);
327
+ },
328
+ updateSubscriptionPaymentMethod(payload) {
329
+ return request("PUT", "/me/subscriptions/payment-method", {
330
+ body: {
331
+ subscription_id: payload.subscription_id,
332
+ payment_method_id: payload.payment_method_id
333
+ }
334
+ });
335
+ },
336
+ resumeSubscription() {
337
+ return request("POST", "/me/subscriptions/resume");
338
+ },
339
+ changeSubscription(payload) {
340
+ return request("POST", "/me/subscriptions/change", {
341
+ body: payload
342
+ });
343
+ },
313
344
  async getPaymentHistory(params) {
314
345
  const result = await request("GET", "/me/payments", {
315
346
  query: {
@@ -455,6 +486,19 @@ function DialogHeader({ className, ...props }) {
455
486
  }
456
487
  );
457
488
  }
489
+ function DialogFooter({ className, ...props }) {
490
+ return /* @__PURE__ */ jsxRuntime.jsx(
491
+ "div",
492
+ {
493
+ "data-slot": "dialog-footer",
494
+ className: cn(
495
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
496
+ className
497
+ ),
498
+ ...props
499
+ }
500
+ );
501
+ }
458
502
  function DialogTitle({
459
503
  className,
460
504
  ...props
@@ -521,7 +565,7 @@ var buttonVariants = classVarianceAuthority.cva(
521
565
  }
522
566
  }
523
567
  );
524
- var Button = React15__namespace.forwardRef(
568
+ var Button = React4__namespace.forwardRef(
525
569
  ({ className, variant, size, asChild = false, ...props }, ref) => {
526
570
  const Comp = asChild ? reactSlot.Slot : "button";
527
571
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -535,7 +579,7 @@ var Button = React15__namespace.forwardRef(
535
579
  }
536
580
  );
537
581
  Button.displayName = "Button";
538
- var Input = React15__namespace.forwardRef(
582
+ var Input = React4__namespace.forwardRef(
539
583
  ({ className, type, ...props }, ref) => {
540
584
  return /* @__PURE__ */ jsxRuntime.jsx(
541
585
  "input",
@@ -555,7 +599,7 @@ Input.displayName = "Input";
555
599
  var labelVariants = classVarianceAuthority.cva(
556
600
  "text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
557
601
  );
558
- var Label = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
602
+ var Label = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
559
603
  LabelPrimitive__namespace.Root,
560
604
  {
561
605
  ref,
@@ -564,9 +608,9 @@ var Label = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @
564
608
  }
565
609
  ));
566
610
  Label.displayName = LabelPrimitive__namespace.Root.displayName;
567
- var Select = ({ children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Root, { ...props, children }) });
611
+ var Select = SelectPrimitive__namespace.Root;
568
612
  var SelectValue = SelectPrimitive__namespace.Value;
569
- var SelectTrigger = React15__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
613
+ var SelectTrigger = React4__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
570
614
  SelectPrimitive__namespace.Trigger,
571
615
  {
572
616
  ref,
@@ -582,7 +626,7 @@ var SelectTrigger = React15__namespace.forwardRef(({ className, children, ...pro
582
626
  }
583
627
  ));
584
628
  SelectTrigger.displayName = SelectPrimitive__namespace.Trigger.displayName;
585
- var SelectScrollUpButton = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
629
+ var SelectScrollUpButton = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
586
630
  SelectPrimitive__namespace.ScrollUpButton,
587
631
  {
588
632
  ref,
@@ -595,7 +639,7 @@ var SelectScrollUpButton = React15__namespace.forwardRef(({ className, ...props
595
639
  }
596
640
  ));
597
641
  SelectScrollUpButton.displayName = SelectPrimitive__namespace.ScrollUpButton.displayName;
598
- var SelectScrollDownButton = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
642
+ var SelectScrollDownButton = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
599
643
  SelectPrimitive__namespace.ScrollDownButton,
600
644
  {
601
645
  ref,
@@ -608,39 +652,61 @@ var SelectScrollDownButton = React15__namespace.forwardRef(({ className, ...prop
608
652
  }
609
653
  ));
610
654
  SelectScrollDownButton.displayName = SelectPrimitive__namespace.ScrollDownButton.displayName;
611
- var SelectContent = React15__namespace.forwardRef(
612
- ({
613
- className,
614
- children,
615
- position = "popper",
616
- side = "bottom",
617
- sideOffset = 4,
618
- align = "start",
619
- ...props
620
- }, ref) => {
621
- const popperProps = position === "popper" ? { side, sideOffset, align } : {};
622
- return /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
623
- SelectPrimitive__namespace.Content,
624
- {
625
- ref,
626
- className: cn(
627
- "z-[200] max-h-64 w-[var(--radix-select-trigger-width)] overflow-y-auto overflow-x-hidden rounded-md border border-white/20 bg-background-regular text-foreground shadow-lg backdrop-blur-xl 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
628
- className
629
- ),
630
- position,
631
- ...popperProps,
632
- ...props,
633
- children: [
634
- /* @__PURE__ */ jsxRuntime.jsx(SelectScrollUpButton, {}),
635
- /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Viewport, { className: "p-1", children }),
636
- /* @__PURE__ */ jsxRuntime.jsx(SelectScrollDownButton, {})
637
- ]
655
+ var SelectContent = React4__namespace.forwardRef(({ className, children, position = "popper", ...props }, ref) => {
656
+ const viewportRef = React4__namespace.useRef(null);
657
+ const contentRef = React4__namespace.useCallback((node) => {
658
+ if (node) {
659
+ node.style.setProperty("max-height", "40vh", "important");
660
+ const anchorWidth = window.getComputedStyle(node).getPropertyValue("--radix-popper-anchor-width");
661
+ if (anchorWidth) {
662
+ node.style.setProperty("width", anchorWidth, "important");
638
663
  }
639
- ) });
640
- }
641
- );
664
+ }
665
+ }, []);
666
+ const combinedRef = React4__namespace.useCallback((node) => {
667
+ contentRef(node);
668
+ if (typeof ref === "function") {
669
+ ref(node);
670
+ } else if (ref) {
671
+ ref.current = node;
672
+ }
673
+ }, [contentRef, ref]);
674
+ React4__namespace.useEffect(() => {
675
+ if (viewportRef.current) {
676
+ viewportRef.current.style.setProperty("max-height", "40vh", "important");
677
+ }
678
+ });
679
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
680
+ SelectPrimitive__namespace.Content,
681
+ {
682
+ ref: combinedRef,
683
+ className: cn(
684
+ "relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-white/20 bg-background-regular text-foreground shadow-lg backdrop-blur-xl 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
685
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
686
+ className
687
+ ),
688
+ position,
689
+ ...props,
690
+ children: [
691
+ /* @__PURE__ */ jsxRuntime.jsx(SelectScrollUpButton, {}),
692
+ /* @__PURE__ */ jsxRuntime.jsx(
693
+ SelectPrimitive__namespace.Viewport,
694
+ {
695
+ ref: viewportRef,
696
+ className: cn(
697
+ "p-1 overflow-y-auto",
698
+ position === "popper" && "w-full min-w-[var(--radix-select-trigger-width)]"
699
+ ),
700
+ children
701
+ }
702
+ ),
703
+ /* @__PURE__ */ jsxRuntime.jsx(SelectScrollDownButton, {})
704
+ ]
705
+ }
706
+ ) });
707
+ });
642
708
  SelectContent.displayName = SelectPrimitive__namespace.Content.displayName;
643
- var SelectLabel = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
709
+ var SelectLabel = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
644
710
  SelectPrimitive__namespace.Label,
645
711
  {
646
712
  ref,
@@ -649,7 +715,7 @@ var SelectLabel = React15__namespace.forwardRef(({ className, ...props }, ref) =
649
715
  }
650
716
  ));
651
717
  SelectLabel.displayName = SelectPrimitive__namespace.Label.displayName;
652
- var SelectItem = React15__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
718
+ var SelectItem = React4__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
653
719
  SelectPrimitive__namespace.Item,
654
720
  {
655
721
  ref,
@@ -665,7 +731,7 @@ var SelectItem = React15__namespace.forwardRef(({ className, children, ...props
665
731
  }
666
732
  ));
667
733
  SelectItem.displayName = SelectPrimitive__namespace.Item.displayName;
668
- var SelectSeparator = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
734
+ var SelectSeparator = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
669
735
  SelectPrimitive__namespace.Separator,
670
736
  {
671
737
  ref,
@@ -687,6 +753,28 @@ var defaultBillingDetails = {
687
753
  email: "",
688
754
  provider: "mobius"
689
755
  };
756
+ var defaultCardDetailsFormTranslations = {
757
+ firstName: "First name",
758
+ lastName: "Last name",
759
+ email: "Email",
760
+ address: "Address",
761
+ city: "City",
762
+ state: "State / Region",
763
+ postalCode: "Postal code",
764
+ country: "Country",
765
+ cardNumber: "Card number",
766
+ expiry: "Expiry",
767
+ cvv: "CVV",
768
+ submit: "Submit",
769
+ processing: "Processing\u2026",
770
+ errorRequiredFields: "Please complete all required billing fields.",
771
+ errorTokenization: "Payment tokenization failed. Please try again.",
772
+ errorFormNotReady: "Payment form is not ready. Please try again later.",
773
+ infoSecure: "Your payment information is encrypted and processed securely.",
774
+ cancel: "Cancel",
775
+ editEmail: "Edit email",
776
+ selectCountry: "Select a country"
777
+ };
690
778
  var buildSelector = (prefix, field) => `#${prefix}-${field}`;
691
779
  var CardDetailsForm = ({
692
780
  visible,
@@ -698,11 +786,13 @@ var CardDetailsForm = ({
698
786
  collectPrefix = "card-form",
699
787
  className,
700
788
  onBillingChange,
701
- submitDisabled = false
789
+ submitDisabled = false,
790
+ translations
702
791
  }) => {
792
+ const t = { ...defaultCardDetailsFormTranslations, ...translations };
703
793
  const { config } = usePaymentContext();
704
- const defaultValuesKey = React15.useMemo(() => JSON.stringify(defaultValues ?? {}), [defaultValues]);
705
- const mergedDefaults = React15.useMemo(
794
+ const defaultValuesKey = React4.useMemo(() => JSON.stringify(defaultValues ?? {}), [defaultValues]);
795
+ const mergedDefaults = React4.useMemo(
706
796
  () => ({
707
797
  ...defaultBillingDetails,
708
798
  ...defaultValues,
@@ -710,20 +800,21 @@ var CardDetailsForm = ({
710
800
  }),
711
801
  [defaultValuesKey, config.defaultUser?.email]
712
802
  );
713
- const [firstName, setFirstName] = React15.useState(mergedDefaults.firstName);
714
- const [lastName, setLastName] = React15.useState(mergedDefaults.lastName);
715
- const [address1, setAddress1] = React15.useState(mergedDefaults.address1);
716
- const [city, setCity] = React15.useState(mergedDefaults.city);
717
- const [stateRegion, setStateRegion] = React15.useState(mergedDefaults.stateRegion ?? "");
718
- const [postalCode, setPostalCode] = React15.useState(mergedDefaults.postalCode);
719
- const [country, setCountry] = React15.useState(mergedDefaults.country);
720
- const [email, setEmail] = React15.useState(mergedDefaults.email ?? "");
721
- const [localError, setLocalError] = React15.useState(null);
722
- const [isTokenizing, setIsTokenizing] = React15.useState(false);
723
- const [collectReady, setCollectReady] = React15.useState(
803
+ const [firstName, setFirstName] = React4.useState(mergedDefaults.firstName);
804
+ const [lastName, setLastName] = React4.useState(mergedDefaults.lastName);
805
+ const [address1, setAddress1] = React4.useState(mergedDefaults.address1);
806
+ const [city, setCity] = React4.useState(mergedDefaults.city);
807
+ const [stateRegion, setStateRegion] = React4.useState(mergedDefaults.stateRegion ?? "");
808
+ const [postalCode, setPostalCode] = React4.useState(mergedDefaults.postalCode);
809
+ const [country, setCountry] = React4.useState(mergedDefaults.country);
810
+ const [email, setEmail] = React4.useState(mergedDefaults.email ?? "");
811
+ const [isEditingEmail, setIsEditingEmail] = React4.useState(false);
812
+ const [localError, setLocalError] = React4.useState(null);
813
+ const [isTokenizing, setIsTokenizing] = React4.useState(false);
814
+ const [collectReady, setCollectReady] = React4.useState(
724
815
  typeof window !== "undefined" && Boolean(window.CollectJS)
725
816
  );
726
- React15.useEffect(() => {
817
+ React4.useEffect(() => {
727
818
  if (collectReady) return;
728
819
  let active = true;
729
820
  waitForCollectJs().then((instance) => {
@@ -735,13 +826,16 @@ var CardDetailsForm = ({
735
826
  active = false;
736
827
  };
737
828
  }, [collectReady]);
738
- React15.useEffect(() => {
829
+ React4.useEffect(() => {
739
830
  if (!visible) {
740
831
  setLocalError(null);
741
832
  setIsTokenizing(false);
833
+ if (typeof window !== "undefined" && window.__doujinsCollectConfigured && collectPrefix) {
834
+ window.__doujinsCollectConfigured[collectPrefix] = false;
835
+ }
742
836
  }
743
- }, [visible]);
744
- React15.useEffect(() => {
837
+ }, [visible, collectPrefix]);
838
+ React4.useEffect(() => {
745
839
  if (!visible) return;
746
840
  setFirstName(mergedDefaults.firstName);
747
841
  setLastName(mergedDefaults.lastName);
@@ -752,7 +846,7 @@ var CardDetailsForm = ({
752
846
  setCountry(mergedDefaults.country);
753
847
  setEmail(mergedDefaults.email ?? "");
754
848
  }, [defaultValuesKey, mergedDefaults, visible]);
755
- React15.useEffect(() => {
849
+ React4.useEffect(() => {
756
850
  if (!onBillingChange) return;
757
851
  onBillingChange({
758
852
  firstName,
@@ -791,7 +885,7 @@ var CardDetailsForm = ({
791
885
  }
792
886
  return sanitized;
793
887
  };
794
- React15.useEffect(() => {
888
+ React4.useEffect(() => {
795
889
  if (!collectReady || typeof window === "undefined" || !window.CollectJS || !visible) {
796
890
  return;
797
891
  }
@@ -802,6 +896,8 @@ var CardDetailsForm = ({
802
896
  setLocalError("Payment tokenization failed. Please try again.");
803
897
  return;
804
898
  }
899
+ let rawExp = response.card?.exp;
900
+ let formattedExp = rawExp && rawExp.length === 4 ? `${rawExp.slice(0, 2)}/${rawExp.slice(2)}` : rawExp;
805
901
  const billing = {
806
902
  firstName,
807
903
  lastName,
@@ -811,7 +907,10 @@ var CardDetailsForm = ({
811
907
  postalCode,
812
908
  country,
813
909
  email,
814
- provider: mergedDefaults.provider ?? "mobius"
910
+ provider: mergedDefaults.provider ?? "mobius",
911
+ last_four: response.card?.number,
912
+ card_type: response.card?.type,
913
+ expiry_date: formattedExp
815
914
  };
816
915
  onTokenize(response.token, billing);
817
916
  };
@@ -851,9 +950,8 @@ var CardDetailsForm = ({
851
950
  visible
852
951
  ]);
853
952
  const validate = () => {
854
- const emailRequired = !defaultValues?.email && !config.defaultUser?.email;
855
- if (!firstName.trim() || !lastName.trim() || !address1.trim() || !city.trim() || !postalCode.trim() || !country.trim() || emailRequired && !email.trim()) {
856
- setLocalError("Please complete all required billing fields.");
953
+ if (!firstName.trim() || !lastName.trim() || !address1.trim() || !city.trim() || !postalCode.trim() || !country.trim() || !email.trim()) {
954
+ setLocalError(t.errorRequiredFields);
857
955
  return false;
858
956
  }
859
957
  setLocalError(null);
@@ -863,7 +961,7 @@ var CardDetailsForm = ({
863
961
  event.preventDefault();
864
962
  if (!validate()) return;
865
963
  if (!window.CollectJS) {
866
- setLocalError("Payment form is not ready. Please try again later.");
964
+ setLocalError(t.errorFormNotReady);
867
965
  return;
868
966
  }
869
967
  setIsTokenizing(true);
@@ -871,7 +969,8 @@ var CardDetailsForm = ({
871
969
  };
872
970
  const errorMessage = localError ?? externalError;
873
971
  const collectFieldClass = "relative flex h-9 w-full items-center overflow-hidden rounded-md border border-white/30 bg-transparent px-3 text-sm text-foreground";
874
- const showEmailField = !defaultValues?.email && !config.defaultUser?.email;
972
+ const hasDefaultEmail = Boolean(defaultValues?.email || config.defaultUser?.email);
973
+ const showEmailInput = !hasDefaultEmail || isEditingEmail;
875
974
  return /* @__PURE__ */ jsxRuntime.jsxs(
876
975
  "form",
877
976
  {
@@ -882,7 +981,7 @@ var CardDetailsForm = ({
882
981
  errorMessage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-red-500/40 bg-red-500/10 px-4 py-2 text-sm text-red-400", children: errorMessage }),
883
982
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 md:flex-row", children: [
884
983
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-2", children: [
885
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "firstName", children: "First name" }),
984
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "firstName", children: t.firstName }),
886
985
  /* @__PURE__ */ jsxRuntime.jsx(
887
986
  Input,
888
987
  {
@@ -894,7 +993,7 @@ var CardDetailsForm = ({
894
993
  )
895
994
  ] }),
896
995
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-2", children: [
897
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "lastName", children: "Last name" }),
996
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "lastName", children: t.lastName }),
898
997
  /* @__PURE__ */ jsxRuntime.jsx(
899
998
  Input,
900
999
  {
@@ -906,21 +1005,50 @@ var CardDetailsForm = ({
906
1005
  )
907
1006
  ] })
908
1007
  ] }),
909
- showEmailField && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
910
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "email", children: "Email" }),
911
- /* @__PURE__ */ jsxRuntime.jsx(
912
- Input,
913
- {
914
- id: "email",
915
- type: "email",
916
- value: email,
917
- onChange: (e) => setEmail(e.target.value),
918
- required: true
919
- }
920
- )
1008
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1009
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "email", children: t.email }),
1010
+ showEmailInput ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
1011
+ /* @__PURE__ */ jsxRuntime.jsx(
1012
+ Input,
1013
+ {
1014
+ id: "email",
1015
+ type: "email",
1016
+ value: email,
1017
+ onChange: (e) => setEmail(e.target.value),
1018
+ required: true,
1019
+ className: "flex-1"
1020
+ }
1021
+ ),
1022
+ hasDefaultEmail && /* @__PURE__ */ jsxRuntime.jsx(
1023
+ Button,
1024
+ {
1025
+ type: "button",
1026
+ variant: "ghost",
1027
+ size: "sm",
1028
+ onClick: () => {
1029
+ setIsEditingEmail(false);
1030
+ setEmail(mergedDefaults.email ?? "");
1031
+ },
1032
+ className: "px-3 text-xs text-muted-foreground hover:text-foreground",
1033
+ children: t.cancel
1034
+ }
1035
+ )
1036
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between h-9 w-full rounded-md border border-white/30 bg-transparent px-3 text-sm text-foreground", children: [
1037
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: email }),
1038
+ /* @__PURE__ */ jsxRuntime.jsx(
1039
+ "button",
1040
+ {
1041
+ type: "button",
1042
+ onClick: () => setIsEditingEmail(true),
1043
+ className: "text-muted-foreground hover:text-foreground transition-colors",
1044
+ "aria-label": t.editEmail,
1045
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-4 w-4" })
1046
+ }
1047
+ )
1048
+ ] })
921
1049
  ] }),
922
1050
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
923
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "address1", children: "Address" }),
1051
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "address1", children: t.address }),
924
1052
  /* @__PURE__ */ jsxRuntime.jsx(
925
1053
  Input,
926
1054
  {
@@ -933,7 +1061,7 @@ var CardDetailsForm = ({
933
1061
  ] }),
934
1062
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2 md:grid-cols-2", children: [
935
1063
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
936
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "city", children: "City" }),
1064
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "city", children: t.city }),
937
1065
  /* @__PURE__ */ jsxRuntime.jsx(
938
1066
  Input,
939
1067
  {
@@ -945,7 +1073,7 @@ var CardDetailsForm = ({
945
1073
  )
946
1074
  ] }),
947
1075
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
948
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "state", children: "State / Region" }),
1076
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "state", children: t.state }),
949
1077
  /* @__PURE__ */ jsxRuntime.jsx(
950
1078
  Input,
951
1079
  {
@@ -958,7 +1086,7 @@ var CardDetailsForm = ({
958
1086
  ] }),
959
1087
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2 md:grid-cols-2", children: [
960
1088
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
961
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "postal", children: "Postal code" }),
1089
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "postal", children: t.postalCode }),
962
1090
  /* @__PURE__ */ jsxRuntime.jsx(
963
1091
  Input,
964
1092
  {
@@ -970,24 +1098,24 @@ var CardDetailsForm = ({
970
1098
  )
971
1099
  ] }),
972
1100
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
973
- /* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Country" }),
1101
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { children: t.country }),
974
1102
  /* @__PURE__ */ jsxRuntime.jsxs(Select, { value: country, onValueChange: setCountry, children: [
975
- /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select a country" }) }),
976
- /* @__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)) })
1103
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: t.selectCountry }) }),
1104
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: countries.map((option) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: option.code, children: option.name }, option.code)) })
977
1105
  ] })
978
1106
  ] })
979
1107
  ] }),
980
1108
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
981
- /* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Card number" }),
1109
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { children: t.cardNumber }),
982
1110
  /* @__PURE__ */ jsxRuntime.jsx("div", { id: buildSelector(collectPrefix, "ccnumber").slice(1), className: collectFieldClass })
983
1111
  ] }),
984
1112
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2 md:grid-cols-2", children: [
985
1113
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
986
- /* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Expiry" }),
1114
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { children: t.expiry }),
987
1115
  /* @__PURE__ */ jsxRuntime.jsx("div", { id: buildSelector(collectPrefix, "ccexp").slice(1), className: collectFieldClass })
988
1116
  ] }),
989
1117
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
990
- /* @__PURE__ */ jsxRuntime.jsx(Label, { children: "CVV" }),
1118
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { children: t.cvv }),
991
1119
  /* @__PURE__ */ jsxRuntime.jsx("div", { id: buildSelector(collectPrefix, "cvv").slice(1), className: collectFieldClass })
992
1120
  ] })
993
1121
  ] }),
@@ -999,11 +1127,12 @@ var CardDetailsForm = ({
999
1127
  disabled: submitting || submitDisabled || isTokenizing,
1000
1128
  children: submitting || isTokenizing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1001
1129
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
1002
- " Processing\u2026"
1003
- ] }) : submitLabel
1130
+ " ",
1131
+ t.processing
1132
+ ] }) : submitLabel || t.submit
1004
1133
  }
1005
1134
  ),
1006
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-white/60", children: "Your payment information is encrypted and processed securely." })
1135
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-white/60", children: t.infoSecure })
1007
1136
  ]
1008
1137
  }
1009
1138
  );
@@ -1040,7 +1169,9 @@ var usePaymentMethods = () => {
1040
1169
  zip: billing.postalCode,
1041
1170
  country: billing.country,
1042
1171
  email: billing.email,
1043
- provider: billing.provider
1172
+ provider: billing.provider,
1173
+ last_four: billing.last_four,
1174
+ card_type: billing.card_type
1044
1175
  };
1045
1176
  return client.createPaymentMethod(payload);
1046
1177
  },
@@ -1079,7 +1210,7 @@ var badgeVariants = classVarianceAuthority.cva(
1079
1210
  function Badge({ className, variant, ...props }) {
1080
1211
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
1081
1212
  }
1082
- var ScrollArea = React15__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1213
+ var ScrollArea = React4__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1083
1214
  ScrollAreaPrimitive__namespace.Root,
1084
1215
  {
1085
1216
  ref,
@@ -1093,7 +1224,7 @@ var ScrollArea = React15__namespace.forwardRef(({ className, children, ...props
1093
1224
  }
1094
1225
  ));
1095
1226
  ScrollArea.displayName = ScrollAreaPrimitive__namespace.Root.displayName;
1096
- var ScrollBar = React15__namespace.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1227
+ var ScrollBar = React4__namespace.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1097
1228
  ScrollAreaPrimitive__namespace.ScrollAreaScrollbar,
1098
1229
  {
1099
1230
  ref,
@@ -1109,21 +1240,34 @@ var ScrollBar = React15__namespace.forwardRef(({ className, orientation = "verti
1109
1240
  }
1110
1241
  ));
1111
1242
  ScrollBar.displayName = ScrollAreaPrimitive__namespace.ScrollAreaScrollbar.displayName;
1243
+ var defaultTranslations = {
1244
+ loadingCards: "Loading cards...",
1245
+ noSavedMethods: "No saved payment methods yet.",
1246
+ selectedLabel: "Selected",
1247
+ useCardLabel: "Use card"
1248
+ };
1112
1249
  var formatCardLabel = (method) => {
1113
- const brand = method.card_type ? method.card_type.toUpperCase() : "CARD";
1114
- const lastFour = method.last_four ? `\u2022\u2022\u2022\u2022 ${method.last_four}` : "";
1115
- return `${brand} ${lastFour}`.trim();
1250
+ if (method.card) {
1251
+ const brand = method.card.brand ? method.card.brand.toUpperCase() : "CARD";
1252
+ const lastFour = method.card.last4 ? `\u2022\u2022\u2022\u2022 ${method.card.last4}` : "";
1253
+ const exp = method.card.exp_month && method.card.exp_year ? ` \u2022 ${String(method.card.exp_month).padStart(2, "0")}/${String(method.card.exp_year).slice(-2)}` : "";
1254
+ return `${brand} ${lastFour}${exp}`.trim();
1255
+ }
1256
+ return "CARD";
1116
1257
  };
1117
1258
  var StoredPaymentMethods = ({
1118
1259
  selectedMethodId,
1119
- onMethodSelect
1260
+ onMethodSelect,
1261
+ translations
1120
1262
  }) => {
1121
1263
  const { listQuery } = usePaymentMethods();
1122
- const payments = React15.useMemo(() => listQuery.data?.data ?? [], [listQuery.data]);
1264
+ const payments = React4.useMemo(() => listQuery.data?.data ?? [], [listQuery.data]);
1265
+ const t = { ...defaultTranslations, ...translations };
1123
1266
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: listQuery.isLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center py-4 text-sm text-muted-foreground", children: [
1124
1267
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
1125
- " Loading cards..."
1126
- ] }) : payments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center 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) => {
1268
+ " ",
1269
+ t.loadingCards
1270
+ ] }) : payments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: t.noSavedMethods }) : /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "max-h-[320px] pr-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: payments.map((method) => {
1127
1271
  const isSelected = selectedMethodId === method.id;
1128
1272
  return /* @__PURE__ */ jsxRuntime.jsxs(
1129
1273
  "div",
@@ -1146,7 +1290,7 @@ var StoredPaymentMethods = ({
1146
1290
  disabled: isSelected,
1147
1291
  onClick: () => onMethodSelect(method),
1148
1292
  className: clsx2__default.default("px-3", { "bg-muted/90": !isSelected, "bg-inherit": isSelected }),
1149
- children: isSelected ? "Selected" : "Use card"
1293
+ children: isSelected ? t.selectedLabel : t.useCardLabel
1150
1294
  }
1151
1295
  )
1152
1296
  ] })
@@ -1156,6 +1300,26 @@ var StoredPaymentMethods = ({
1156
1300
  );
1157
1301
  }) }) }) });
1158
1302
  };
1303
+
1304
+ // src/utils/errorMessages.ts
1305
+ var resolveErrorMessageByCode = (error, translationErrors, fallbackMessage) => {
1306
+ const errors = translationErrors ?? {};
1307
+ const defaultMessage = fallbackMessage ?? (error instanceof Error ? error.message : typeof error === "string" ? error : "An unexpected error occurred");
1308
+ if (error instanceof ClientApiError) {
1309
+ const payload = error.body;
1310
+ const code = payload?.code ?? payload?.error?.code;
1311
+ if (code && errors[code]) return errors[code];
1312
+ if (typeof payload?.error?.message === "string") return payload.error.message;
1313
+ return error.message;
1314
+ }
1315
+ if (typeof error === "object" && error !== null && "code" in error) {
1316
+ const code = error.code;
1317
+ if (typeof code === "string" && errors[code]) return errors[code];
1318
+ }
1319
+ if (error instanceof Error) return error.message;
1320
+ if (typeof error === "string") return error;
1321
+ return defaultMessage;
1322
+ };
1159
1323
  function Tabs({
1160
1324
  className,
1161
1325
  ...props
@@ -1178,7 +1342,7 @@ function TabsList({
1178
1342
  {
1179
1343
  "data-slot": "tabs-list",
1180
1344
  className: cn(
1181
- "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
1345
+ "bg-transparent border border-white/30 text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-1",
1182
1346
  className
1183
1347
  ),
1184
1348
  ...props
@@ -1189,12 +1353,32 @@ function TabsTrigger({
1189
1353
  className,
1190
1354
  ...props
1191
1355
  }) {
1356
+ const triggerRef = React4__namespace.useRef(null);
1357
+ React4__namespace.useEffect(() => {
1358
+ const element = triggerRef.current;
1359
+ if (!element) return;
1360
+ const updateStyles = () => {
1361
+ const isActive = element.getAttribute("data-state") === "active";
1362
+ if (isActive) {
1363
+ element.style.setProperty("background-color", "rgba(255, 255, 255, 0.3)", "important");
1364
+ element.style.setProperty("border-color", "transparent", "important");
1365
+ } else {
1366
+ element.style.removeProperty("background-color");
1367
+ element.style.removeProperty("border-color");
1368
+ }
1369
+ };
1370
+ updateStyles();
1371
+ const observer = new MutationObserver(updateStyles);
1372
+ observer.observe(element, { attributes: true, attributeFilter: ["data-state"] });
1373
+ return () => observer.disconnect();
1374
+ }, []);
1192
1375
  return /* @__PURE__ */ jsxRuntime.jsx(
1193
1376
  TabsPrimitive__namespace.Trigger,
1194
1377
  {
1378
+ ref: triggerRef,
1195
1379
  "data-slot": "tabs-trigger",
1196
1380
  className: cn(
1197
- "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1381
+ "data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/70 inline-flex h-[calc(100%-0.5rem)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow,background-color,border-color] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1198
1382
  className
1199
1383
  ),
1200
1384
  ...props
@@ -1216,19 +1400,19 @@ function TabsContent({
1216
1400
  }
1217
1401
  var usePaymentNotifications = () => {
1218
1402
  const { config } = usePaymentContext();
1219
- const notifyStatus = React15.useCallback(
1403
+ const notifyStatus = React4.useCallback(
1220
1404
  (status, context) => {
1221
1405
  config.callbacks?.onStatusChange?.({ status, context });
1222
1406
  },
1223
1407
  [config.callbacks]
1224
1408
  );
1225
- const notifySuccess = React15.useCallback(
1409
+ const notifySuccess = React4.useCallback(
1226
1410
  (payload) => {
1227
1411
  config.callbacks?.onSuccess?.(payload ?? {});
1228
1412
  },
1229
1413
  [config.callbacks]
1230
1414
  );
1231
- const notifyError = React15.useCallback(
1415
+ const notifyError = React4.useCallback(
1232
1416
  (error) => {
1233
1417
  config.callbacks?.onError?.(
1234
1418
  typeof error === "string" ? new Error(error) : error
@@ -1246,17 +1430,17 @@ var useSolanaQrPayment = (options) => {
1246
1430
  const { priceId, selectedToken, onSuccess, onError } = options;
1247
1431
  const { client } = usePaymentContext();
1248
1432
  const tokenSymbol = selectedToken?.symbol ?? null;
1249
- const onSuccessRef = React15.useRef(onSuccess);
1250
- const onErrorRef = React15.useRef(onError);
1251
- const [intent, setIntent] = React15.useState(null);
1252
- const [qrDataUri, setQrDataUri] = React15.useState(null);
1253
- const [isLoading, setIsLoading] = React15.useState(false);
1254
- const [error, setError] = React15.useState(null);
1255
- const [timeRemaining, setTimeRemaining] = React15.useState(0);
1256
- const [refreshNonce, setRefreshNonce] = React15.useState(0);
1257
- const pollRef = React15.useRef(null);
1258
- const countdownRef = React15.useRef(null);
1259
- const clearTimers = React15.useCallback(() => {
1433
+ const onSuccessRef = React4.useRef(onSuccess);
1434
+ const onErrorRef = React4.useRef(onError);
1435
+ const [intent, setIntent] = React4.useState(null);
1436
+ const [qrDataUri, setQrDataUri] = React4.useState(null);
1437
+ const [isLoading, setIsLoading] = React4.useState(false);
1438
+ const [error, setError] = React4.useState(null);
1439
+ const [timeRemaining, setTimeRemaining] = React4.useState(0);
1440
+ const [refreshNonce, setRefreshNonce] = React4.useState(0);
1441
+ const pollRef = React4.useRef(null);
1442
+ const countdownRef = React4.useRef(null);
1443
+ const clearTimers = React4.useCallback(() => {
1260
1444
  if (pollRef.current) {
1261
1445
  clearInterval(pollRef.current);
1262
1446
  pollRef.current = null;
@@ -1266,12 +1450,12 @@ var useSolanaQrPayment = (options) => {
1266
1450
  countdownRef.current = null;
1267
1451
  }
1268
1452
  }, []);
1269
- React15.useEffect(() => {
1453
+ React4.useEffect(() => {
1270
1454
  return () => {
1271
1455
  clearTimers();
1272
1456
  };
1273
1457
  }, [clearTimers]);
1274
- const resetState = React15.useCallback(
1458
+ const resetState = React4.useCallback(
1275
1459
  (message) => {
1276
1460
  clearTimers();
1277
1461
  setIntent(null);
@@ -1281,13 +1465,13 @@ var useSolanaQrPayment = (options) => {
1281
1465
  },
1282
1466
  [clearTimers]
1283
1467
  );
1284
- React15.useEffect(() => {
1468
+ React4.useEffect(() => {
1285
1469
  onSuccessRef.current = onSuccess;
1286
1470
  }, [onSuccess]);
1287
- React15.useEffect(() => {
1471
+ React4.useEffect(() => {
1288
1472
  onErrorRef.current = onError;
1289
1473
  }, [onError]);
1290
- const handleError = React15.useCallback(
1474
+ const handleError = React4.useCallback(
1291
1475
  (message, notifyParent = false) => {
1292
1476
  console.error("[payments-ui] Solana Pay QR error:", message);
1293
1477
  clearTimers();
@@ -1298,7 +1482,7 @@ var useSolanaQrPayment = (options) => {
1298
1482
  },
1299
1483
  [clearTimers, resetState]
1300
1484
  );
1301
- const handleSuccess = React15.useCallback(
1485
+ const handleSuccess = React4.useCallback(
1302
1486
  (status) => {
1303
1487
  clearTimers();
1304
1488
  resetState(null);
@@ -1312,7 +1496,7 @@ var useSolanaQrPayment = (options) => {
1312
1496
  },
1313
1497
  [clearTimers, resetState]
1314
1498
  );
1315
- const pollStatus = React15.useCallback(
1499
+ const pollStatus = React4.useCallback(
1316
1500
  async (reference) => {
1317
1501
  try {
1318
1502
  const status = await client.getSolanaPayStatus(reference);
@@ -1331,7 +1515,7 @@ var useSolanaQrPayment = (options) => {
1331
1515
  },
1332
1516
  [handleError, handleSuccess, client]
1333
1517
  );
1334
- const startCountdown = React15.useCallback(
1518
+ const startCountdown = React4.useCallback(
1335
1519
  (expiresAt, reference) => {
1336
1520
  const updateTime = () => {
1337
1521
  const remaining = Math.max(0, Math.floor(expiresAt - Date.now() / 1e3));
@@ -1346,7 +1530,7 @@ var useSolanaQrPayment = (options) => {
1346
1530
  },
1347
1531
  [handleError, pollStatus]
1348
1532
  );
1349
- const renderQr = React15.useCallback(async (qrIntent) => {
1533
+ const renderQr = React4.useCallback(async (qrIntent) => {
1350
1534
  try {
1351
1535
  const dataUri = await QRCode__default.default.toDataURL(qrIntent.url, {
1352
1536
  width: 320,
@@ -1362,7 +1546,7 @@ var useSolanaQrPayment = (options) => {
1362
1546
  handleError("Unable to render QR code");
1363
1547
  }
1364
1548
  }, [handleError]);
1365
- React15.useEffect(() => {
1549
+ React4.useEffect(() => {
1366
1550
  let cancelled = false;
1367
1551
  const generateIntent = async () => {
1368
1552
  clearTimers();
@@ -1426,7 +1610,7 @@ var useSolanaQrPayment = (options) => {
1426
1610
  tokenSymbol,
1427
1611
  refreshNonce
1428
1612
  ]);
1429
- const refresh = React15.useCallback(() => {
1613
+ const refresh = React4.useCallback(() => {
1430
1614
  setRefreshNonce((value) => value + 1);
1431
1615
  }, []);
1432
1616
  return {
@@ -1438,7 +1622,7 @@ var useSolanaQrPayment = (options) => {
1438
1622
  refresh
1439
1623
  };
1440
1624
  };
1441
- var Card = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1625
+ var Card = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1442
1626
  "div",
1443
1627
  {
1444
1628
  ref,
@@ -1450,7 +1634,7 @@ var Card = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @_
1450
1634
  }
1451
1635
  ));
1452
1636
  Card.displayName = "Card";
1453
- var CardHeader = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1637
+ var CardHeader = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1454
1638
  "div",
1455
1639
  {
1456
1640
  ref,
@@ -1459,7 +1643,7 @@ var CardHeader = React15__namespace.forwardRef(({ className, ...props }, ref) =>
1459
1643
  }
1460
1644
  ));
1461
1645
  CardHeader.displayName = "CardHeader";
1462
- var CardTitle = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1646
+ var CardTitle = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1463
1647
  "div",
1464
1648
  {
1465
1649
  ref,
@@ -1471,7 +1655,7 @@ var CardTitle = React15__namespace.forwardRef(({ className, ...props }, ref) =>
1471
1655
  }
1472
1656
  ));
1473
1657
  CardTitle.displayName = "CardTitle";
1474
- var CardDescription = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1658
+ var CardDescription = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1475
1659
  "div",
1476
1660
  {
1477
1661
  ref,
@@ -1480,9 +1664,9 @@ var CardDescription = React15__namespace.forwardRef(({ className, ...props }, re
1480
1664
  }
1481
1665
  ));
1482
1666
  CardDescription.displayName = "CardDescription";
1483
- var CardContent = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
1667
+ var CardContent = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
1484
1668
  CardContent.displayName = "CardContent";
1485
- var CardFooter = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1669
+ var CardFooter = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1486
1670
  "div",
1487
1671
  {
1488
1672
  ref,
@@ -1497,7 +1681,7 @@ var QRCodePayment = ({
1497
1681
  onPaymentError,
1498
1682
  onPaymentSuccess
1499
1683
  }) => {
1500
- const handleQrSuccess = React15__namespace.default.useCallback(
1684
+ const handleQrSuccess = React4__namespace.default.useCallback(
1501
1685
  (paymentId, txId) => {
1502
1686
  if (!paymentId && !txId) {
1503
1687
  onPaymentError("Missing payment confirmation details");
@@ -1606,16 +1790,16 @@ var PaymentStatus = ({
1606
1790
  };
1607
1791
  var useSupportedTokens = () => {
1608
1792
  const { client } = usePaymentContext();
1609
- const [tokens, setTokens] = React15.useState([]);
1610
- const [isLoading, setIsLoading] = React15.useState(false);
1611
- const [error, setError] = React15.useState(null);
1612
- const [lastFetched, setLastFetched] = React15.useState(null);
1793
+ const [tokens, setTokens] = React4.useState([]);
1794
+ const [isLoading, setIsLoading] = React4.useState(false);
1795
+ const [error, setError] = React4.useState(null);
1796
+ const [lastFetched, setLastFetched] = React4.useState(null);
1613
1797
  const CACHE_DURATION = 5 * 60 * 1e3;
1614
- const tokensRef = React15.useRef(tokens);
1615
- const lastFetchedRef = React15.useRef(lastFetched);
1798
+ const tokensRef = React4.useRef(tokens);
1799
+ const lastFetchedRef = React4.useRef(lastFetched);
1616
1800
  tokensRef.current = tokens;
1617
1801
  lastFetchedRef.current = lastFetched;
1618
- const fetchSupportedTokens = React15.useCallback(async () => {
1802
+ const fetchSupportedTokens = React4.useCallback(async () => {
1619
1803
  if (tokensRef.current.length > 0 && lastFetchedRef.current && Date.now() - lastFetchedRef.current < CACHE_DURATION) {
1620
1804
  return tokensRef.current;
1621
1805
  }
@@ -1642,50 +1826,50 @@ var useSupportedTokens = () => {
1642
1826
  setIsLoading(false);
1643
1827
  }
1644
1828
  }, [client]);
1645
- React15.useEffect(() => {
1829
+ React4.useEffect(() => {
1646
1830
  if (tokens.length === 0) {
1647
1831
  fetchSupportedTokens();
1648
1832
  }
1649
1833
  }, [tokens.length, fetchSupportedTokens]);
1650
- const getTokenBySymbol = React15.useCallback(
1834
+ const getTokenBySymbol = React4.useCallback(
1651
1835
  (symbol) => {
1652
1836
  return tokens.find((token) => token.symbol === symbol);
1653
1837
  },
1654
1838
  [tokens]
1655
1839
  );
1656
- const getTokenByMint = React15.useCallback(
1840
+ const getTokenByMint = React4.useCallback(
1657
1841
  (mintAddress) => {
1658
1842
  return tokens.find((token) => token.mint === mintAddress);
1659
1843
  },
1660
1844
  [tokens]
1661
1845
  );
1662
- const isTokenSupported = React15.useCallback(
1846
+ const isTokenSupported = React4.useCallback(
1663
1847
  (symbol) => {
1664
1848
  return tokens.some((token) => token.symbol === symbol);
1665
1849
  },
1666
1850
  [tokens]
1667
1851
  );
1668
- const getUSDCToken = React15.useCallback(() => {
1852
+ const getUSDCToken = React4.useCallback(() => {
1669
1853
  return getTokenBySymbol("USDC");
1670
1854
  }, [getTokenBySymbol]);
1671
- const getPYUSDToken = React15.useCallback(() => {
1855
+ const getPYUSDToken = React4.useCallback(() => {
1672
1856
  return getTokenBySymbol("PYUSD");
1673
1857
  }, [getTokenBySymbol]);
1674
- const getSOLToken = React15.useCallback(() => {
1858
+ const getSOLToken = React4.useCallback(() => {
1675
1859
  return getTokenBySymbol("SOL");
1676
1860
  }, [getTokenBySymbol]);
1677
- const getStablecoins = React15.useCallback(() => {
1861
+ const getStablecoins = React4.useCallback(() => {
1678
1862
  return tokens.filter((token) => ["USDC", "PYUSD"].includes(token.symbol));
1679
1863
  }, [tokens]);
1680
- const refreshTokens = React15.useCallback(async () => {
1864
+ const refreshTokens = React4.useCallback(async () => {
1681
1865
  setLastFetched(null);
1682
1866
  return await fetchSupportedTokens();
1683
1867
  }, [fetchSupportedTokens]);
1684
- const isCacheStale = React15.useCallback(() => {
1868
+ const isCacheStale = React4.useCallback(() => {
1685
1869
  if (!lastFetched) return true;
1686
1870
  return Date.now() - lastFetched > CACHE_DURATION;
1687
1871
  }, [lastFetched]);
1688
- const getTokenDisplayInfo = React15.useCallback((token) => {
1872
+ const getTokenDisplayInfo = React4.useCallback((token) => {
1689
1873
  return {
1690
1874
  ...token,
1691
1875
  displayName: `${token.name} (${token.symbol})`,
@@ -1693,7 +1877,7 @@ var useSupportedTokens = () => {
1693
1877
  decimalPlaces: token.decimals
1694
1878
  };
1695
1879
  }, []);
1696
- const getTokenPrice = React15.useCallback(
1880
+ const getTokenPrice = React4.useCallback(
1697
1881
  (symbol) => {
1698
1882
  const token = getTokenBySymbol(symbol);
1699
1883
  if (!token) return 0;
@@ -1702,7 +1886,7 @@ var useSupportedTokens = () => {
1702
1886
  },
1703
1887
  [getTokenBySymbol]
1704
1888
  );
1705
- const calculateTokenAmount = React15.useCallback(
1889
+ const calculateTokenAmount = React4.useCallback(
1706
1890
  (usdAmount, tokenSymbol) => {
1707
1891
  const token = getTokenBySymbol(tokenSymbol);
1708
1892
  const price = getTokenPrice(tokenSymbol);
@@ -1713,7 +1897,7 @@ var useSupportedTokens = () => {
1713
1897
  },
1714
1898
  [getTokenBySymbol, getTokenPrice]
1715
1899
  );
1716
- const formatTokenAmount = React15.useCallback(
1900
+ const formatTokenAmount = React4.useCallback(
1717
1901
  (amount, tokenSymbol) => {
1718
1902
  const token = getTokenBySymbol(tokenSymbol);
1719
1903
  if (!token) return "0";
@@ -1754,28 +1938,28 @@ var SolanaPaymentView = ({
1754
1938
  onClose
1755
1939
  }) => {
1756
1940
  const { notifyStatus, notifyError, notifySuccess } = usePaymentNotifications();
1757
- const [paymentState, setPaymentState] = React15.useState("selecting");
1758
- const [errorMessage, setErrorMessage] = React15.useState(null);
1759
- const [transactionId, setTransactionId] = React15.useState(null);
1760
- const [tokenAmount, setTokenAmount] = React15.useState(0);
1761
- const [selectedTokenSymbol, setSelectedTokenSymbol] = React15.useState(null);
1941
+ const [paymentState, setPaymentState] = React4.useState("selecting");
1942
+ const [errorMessage, setErrorMessage] = React4.useState(null);
1943
+ const [transactionId, setTransactionId] = React4.useState(null);
1944
+ const [tokenAmount, setTokenAmount] = React4.useState(0);
1945
+ const [selectedTokenSymbol, setSelectedTokenSymbol] = React4.useState(null);
1762
1946
  const {
1763
1947
  tokens,
1764
1948
  isLoading: tokensLoading,
1765
1949
  error: tokensError
1766
1950
  } = useSupportedTokens();
1767
- const selectedToken = React15.useMemo(() => {
1951
+ const selectedToken = React4.useMemo(() => {
1768
1952
  if (!tokens.length) return null;
1769
1953
  const explicit = tokens.find((token) => token.symbol === selectedTokenSymbol);
1770
1954
  return explicit || tokens[0];
1771
1955
  }, [tokens, selectedTokenSymbol]);
1772
- React15.useEffect(() => {
1956
+ React4.useEffect(() => {
1773
1957
  if (!selectedTokenSymbol && tokens.length) {
1774
1958
  const defaultToken = tokens.find((token) => token.symbol === "SOL") || tokens[0];
1775
1959
  setSelectedTokenSymbol(defaultToken.symbol);
1776
1960
  }
1777
1961
  }, [tokens, selectedTokenSymbol]);
1778
- const handlePaymentSuccess = React15.useCallback(
1962
+ const handlePaymentSuccess = React4.useCallback(
1779
1963
  (result, txId) => {
1780
1964
  const resolvedTx = txId || (typeof result === "string" ? result : result.transaction_id);
1781
1965
  setTransactionId(resolvedTx);
@@ -1803,7 +1987,7 @@ var SolanaPaymentView = ({
1803
1987
  },
1804
1988
  [notifyStatus, notifySuccess, onSuccess]
1805
1989
  );
1806
- const handlePaymentError = React15.useCallback(
1990
+ const handlePaymentError = React4.useCallback(
1807
1991
  (error) => {
1808
1992
  setPaymentState("error");
1809
1993
  setErrorMessage(error);
@@ -1813,22 +1997,22 @@ var SolanaPaymentView = ({
1813
1997
  },
1814
1998
  [notifyError, notifyStatus, onError]
1815
1999
  );
1816
- const resetState = React15.useCallback(() => {
2000
+ const resetState = React4.useCallback(() => {
1817
2001
  setPaymentState("selecting");
1818
2002
  setErrorMessage(null);
1819
2003
  setTransactionId(null);
1820
2004
  }, []);
1821
- const handleRetry = React15.useCallback(() => {
2005
+ const handleRetry = React4.useCallback(() => {
1822
2006
  resetState();
1823
2007
  }, [resetState]);
1824
- const handleClose = React15.useCallback(() => {
2008
+ const handleClose = React4.useCallback(() => {
1825
2009
  if (paymentState === "processing" || paymentState === "confirming") {
1826
2010
  return;
1827
2011
  }
1828
2012
  resetState();
1829
2013
  onClose?.();
1830
2014
  }, [paymentState, onClose, resetState]);
1831
- React15.useEffect(() => {
2015
+ React4.useEffect(() => {
1832
2016
  if (!selectedToken || usdAmount === 0) {
1833
2017
  setTokenAmount(0);
1834
2018
  return;
@@ -1840,7 +2024,7 @@ var SolanaPaymentView = ({
1840
2024
  }
1841
2025
  setTokenAmount(usdAmount / price);
1842
2026
  }, [usdAmount, selectedToken]);
1843
- const handleTokenChange = React15.useCallback((value) => {
2027
+ const handleTokenChange = React4.useCallback((value) => {
1844
2028
  setSelectedTokenSymbol(value);
1845
2029
  }, []);
1846
2030
  const renderBody = () => {
@@ -1931,35 +2115,63 @@ var SolanaPaymentView = ({
1931
2115
  renderBody()
1932
2116
  ] });
1933
2117
  };
2118
+ var defaultPaymentExperienceTranslations = {
2119
+ ...defaultCardDetailsFormTranslations,
2120
+ useSavedCardTab: "Use saved card",
2121
+ addNewCardTab: "Add new card",
2122
+ savedUnavailable: "Saved payment methods are unavailable right now. Add a new card to get started.",
2123
+ payWithSavedCard: "Pay with selected card",
2124
+ processingSavedCard: "Processing...",
2125
+ savedErrorFallback: "Unable to complete payment with saved card",
2126
+ newCardUnavailable: "Select a subscription plan to add a new card.",
2127
+ payNow: "Pay now",
2128
+ storedLoadingCards: "Loading cards...",
2129
+ storedNoSavedMethods: "No saved payment methods yet.",
2130
+ storedSelectedLabel: "Selected",
2131
+ storedUseCardLabel: "Use card",
2132
+ payWithCcbill: "Pay with CCBill",
2133
+ processingCcbill: "Redirecting...",
2134
+ errors: {}
2135
+ };
1934
2136
  var PaymentExperience = ({
1935
2137
  priceId,
1936
2138
  usdAmount,
1937
2139
  onNewCardPayment,
1938
2140
  onSavedMethodPayment,
2141
+ onCcbillPayment,
1939
2142
  enableNewCard = true,
1940
2143
  enableStoredMethods = true,
1941
2144
  enableSolanaPay = true,
1942
2145
  onSolanaSuccess,
1943
2146
  onSolanaError,
1944
- initialMode = "cards"
2147
+ initialMode = "cards",
2148
+ translations
1945
2149
  }) => {
2150
+ const t = {
2151
+ ...defaultPaymentExperienceTranslations,
2152
+ ...translations
2153
+ };
1946
2154
  const showNewCard = enableNewCard && Boolean(onNewCardPayment);
1947
2155
  const showStored = enableStoredMethods && Boolean(onSavedMethodPayment);
2156
+ const showCcbill = showNewCard && Boolean(onCcbillPayment);
1948
2157
  const defaultTab = showStored ? "saved" : "new";
1949
- const [activeTab, setActiveTab] = React15.useState(defaultTab);
1950
- const [mode, setMode] = React15.useState(
2158
+ const [activeTab, setActiveTab] = React4.useState(defaultTab);
2159
+ const [mode, setMode] = React4.useState(
1951
2160
  () => initialMode === "solana" && enableSolanaPay ? "solana" : "cards"
1952
2161
  );
1953
- const [selectedMethodId, setSelectedMethodId] = React15.useState(null);
1954
- const [savedStatus, setSavedStatus] = React15.useState("idle");
1955
- const [savedError, setSavedError] = React15.useState(null);
1956
- const [newCardStatus, setNewCardStatus] = React15.useState("idle");
1957
- const [newCardError, setNewCardError] = React15.useState(null);
2162
+ const [selectedMethodId, setSelectedMethodId] = React4.useState(null);
2163
+ const [savedStatus, setSavedStatus] = React4.useState("idle");
2164
+ const [savedError, setSavedError] = React4.useState(null);
2165
+ const [newCardStatus, setNewCardStatus] = React4.useState("idle");
2166
+ const [newCardError, setNewCardError] = React4.useState(null);
2167
+ const [billingDetails, setBillingDetails] = React4.useState(null);
2168
+ const [ccbillStatus, setCcbillStatus] = React4.useState("idle");
2169
+ const [ccbillError, setCcbillError] = React4.useState(null);
1958
2170
  const { notifyStatus, notifyError } = usePaymentNotifications();
1959
- React15.useEffect(() => {
2171
+ React4.useEffect(() => {
1960
2172
  setActiveTab(showStored ? "saved" : "new");
1961
2173
  }, [showStored]);
1962
- React15.useEffect(() => {
2174
+ React4.useEffect(() => {
1963
2175
  if (!enableSolanaPay) {
1964
2176
  setMode("cards");
1965
2177
  return;
@@ -1970,12 +2182,30 @@ var PaymentExperience = ({
1970
2182
  setMode("cards");
1971
2183
  }
1972
2184
  }, [enableSolanaPay, initialMode]);
1973
- const handleMethodSelect = React15.useCallback((method) => {
2185
+ React4.useEffect(() => {
2186
+ if (!showNewCard) {
2187
+ setBillingDetails(null);
2188
+ setCcbillStatus("idle");
2189
+ setCcbillError(null);
2190
+ }
2191
+ }, [showNewCard]);
2192
+ const handleBillingChange = React4.useCallback((billing) => {
2193
+ setBillingDetails(billing);
2194
+ setCcbillError(null);
2195
+ setCcbillStatus("idle");
2196
+ }, []);
2197
+ const isBillingComplete = React4.useCallback((billing) => {
2198
+ if (!billing) return false;
2199
+ return Boolean(
2200
+ billing.firstName.trim() && billing.lastName.trim() && billing.address1.trim() && billing.city.trim() && billing.postalCode.trim() && billing.country.trim() && billing.email.trim()
2201
+ );
2202
+ }, []);
2203
+ const handleMethodSelect = React4.useCallback((method) => {
1974
2204
  setSelectedMethodId(method.id);
1975
2205
  setSavedStatus("idle");
1976
2206
  setSavedError(null);
1977
2207
  }, []);
1978
- const handleSavedPayment = React15.useCallback(async () => {
2208
+ const handleSavedPayment = React4.useCallback(async () => {
1979
2209
  if (!onSavedMethodPayment || !selectedMethodId) return;
1980
2210
  try {
1981
2211
  setSavedStatus("processing");
@@ -1988,14 +2218,18 @@ var PaymentExperience = ({
1988
2218
  setSavedStatus("success");
1989
2219
  notifyStatus("success", { source: "saved-payment" });
1990
2220
  } catch (error) {
1991
- const message = error instanceof Error ? error.message : "Unable to complete payment with saved card";
2221
+ const message = resolveErrorMessageByCode(
2222
+ error,
2223
+ t.errors,
2224
+ t.savedErrorFallback
2225
+ );
1992
2226
  setSavedStatus("error");
1993
2227
  setSavedError(message);
1994
2228
  notifyStatus("error", { source: "saved-payment" });
1995
2229
  notifyError(message);
1996
2230
  }
1997
- }, [notifyError, notifyStatus, onSavedMethodPayment, selectedMethodId, usdAmount]);
1998
- const handleNewCardTokenize = React15.useCallback(
2231
+ }, [notifyError, notifyStatus, onSavedMethodPayment, selectedMethodId, t, usdAmount]);
2232
+ const handleNewCardTokenize = React4.useCallback(
1999
2233
  async (token, billing) => {
2000
2234
  if (!onNewCardPayment) return;
2001
2235
  try {
@@ -2006,30 +2240,71 @@ var PaymentExperience = ({
2006
2240
  setNewCardStatus("success");
2007
2241
  notifyStatus("success", { source: "new-card" });
2008
2242
  } catch (error) {
2009
- const message = error instanceof Error ? error.message : "Unable to complete payment";
2243
+ const message = resolveErrorMessageByCode(
2244
+ error,
2245
+ t.errors,
2246
+ "Unable to complete payment"
2247
+ );
2010
2248
  setNewCardStatus("error");
2011
2249
  setNewCardError(message);
2012
2250
  notifyStatus("error", { source: "new-card" });
2013
2251
  notifyError(message);
2014
2252
  }
2015
2253
  },
2016
- [notifyError, notifyStatus, onNewCardPayment]
2254
+ [notifyError, notifyStatus, onNewCardPayment, t]
2017
2255
  );
2018
- React15.useCallback(() => {
2256
+ const handleCcbillPayment = React4.useCallback(async () => {
2257
+ if (!onCcbillPayment) return;
2258
+ if (!billingDetails || !isBillingComplete(billingDetails)) {
2259
+ const message = t.errorRequiredFields;
2260
+ setActiveTab("new");
2261
+ setCcbillStatus("error");
2262
+ setCcbillError(message);
2263
+ notifyStatus("error", { source: "ccbill" });
2264
+ notifyError(message);
2265
+ return;
2266
+ }
2267
+ try {
2268
+ setCcbillStatus("processing");
2269
+ setCcbillError(null);
2270
+ notifyStatus("processing", { source: "ccbill" });
2271
+ await onCcbillPayment({ billing: billingDetails });
2272
+ setCcbillStatus("success");
2273
+ notifyStatus("success", { source: "ccbill" });
2274
+ } catch (error) {
2275
+ const message = resolveErrorMessageByCode(
2276
+ error,
2277
+ t.errors,
2278
+ "Unable to start CCBill checkout"
2279
+ );
2280
+ setCcbillStatus("error");
2281
+ setCcbillError(message);
2282
+ notifyStatus("error", { source: "ccbill" });
2283
+ notifyError(message);
2284
+ }
2285
+ }, [
2286
+ billingDetails,
2287
+ isBillingComplete,
2288
+ notifyError,
2289
+ notifyStatus,
2290
+ onCcbillPayment,
2291
+ t
2292
+ ]);
2293
+ React4.useCallback(() => {
2019
2294
  if (!enableSolanaPay) return;
2020
2295
  setMode("solana");
2021
2296
  }, [enableSolanaPay]);
2022
- const exitSolanaView = React15.useCallback(() => {
2297
+ const exitSolanaView = React4.useCallback(() => {
2023
2298
  setMode("cards");
2024
2299
  }, []);
2025
- const handleSolanaSuccess = React15.useCallback(
2300
+ const handleSolanaSuccess = React4.useCallback(
2026
2301
  (result) => {
2027
2302
  onSolanaSuccess?.(result);
2028
2303
  exitSolanaView();
2029
2304
  },
2030
2305
  [exitSolanaView, onSolanaSuccess]
2031
2306
  );
2032
- const handleSolanaError = React15.useCallback(
2307
+ const handleSolanaError = React4.useCallback(
2033
2308
  (error) => {
2034
2309
  onSolanaError?.(error);
2035
2310
  },
@@ -2037,14 +2312,20 @@ var PaymentExperience = ({
2037
2312
  );
2038
2313
  const renderSavedTab = () => {
2039
2314
  if (!showStored) {
2040
- 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." });
2315
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: t.savedUnavailable });
2041
2316
  }
2042
2317
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
2043
2318
  /* @__PURE__ */ jsxRuntime.jsx(
2044
2319
  StoredPaymentMethods,
2045
2320
  {
2046
2321
  selectedMethodId,
2047
- onMethodSelect: handleMethodSelect
2322
+ onMethodSelect: handleMethodSelect,
2323
+ translations: {
2324
+ loadingCards: t.storedLoadingCards,
2325
+ noSavedMethods: t.storedNoSavedMethods,
2326
+ selectedLabel: t.storedSelectedLabel,
2327
+ useCardLabel: t.storedUseCardLabel
2328
+ }
2048
2329
  }
2049
2330
  ),
2050
2331
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2053,7 +2334,7 @@ var PaymentExperience = ({
2053
2334
  className: "w-full",
2054
2335
  disabled: !selectedMethodId || savedStatus === "processing",
2055
2336
  onClick: handleSavedPayment,
2056
- children: savedStatus === "processing" ? "Processing..." : "Pay with selected card"
2337
+ children: savedStatus === "processing" ? t.processingSavedCard : t.payWithSavedCard
2057
2338
  }
2058
2339
  ),
2059
2340
  savedError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: savedError })
@@ -2061,29 +2342,50 @@ var PaymentExperience = ({
2061
2342
  };
2062
2343
  const renderNewTab = () => {
2063
2344
  if (!showNewCard) {
2064
- return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Select a subscription plan to add a new card." });
2345
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: t.newCardUnavailable });
2065
2346
  }
2066
2347
  return /* @__PURE__ */ jsxRuntime.jsx(
2067
2348
  CardDetailsForm,
2068
2349
  {
2069
2350
  visible: true,
2070
- submitLabel: "Pay now",
2351
+ submitLabel: t.payNow,
2071
2352
  externalError: newCardError,
2072
2353
  onTokenize: handleNewCardTokenize,
2073
- submitting: newCardStatus === "processing"
2354
+ submitting: newCardStatus === "processing",
2355
+ onBillingChange: handleBillingChange,
2356
+ translations: t
2074
2357
  }
2075
2358
  );
2076
2359
  };
2077
2360
  const renderCardExperience = () => /* @__PURE__ */ jsxRuntime.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, children: [
2078
2361
  /* @__PURE__ */ jsxRuntime.jsxs(TabsList, { className: "w-full rounded-md mb-4", children: [
2079
- /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { className: clsx2.clsx("cursor-pointer", { "bg-background": activeTab == "saved" }), value: "saved", children: "Use saved card" }),
2080
- /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { className: clsx2.clsx("cursor-pointer", { "bg-background": activeTab == "new" }), value: "new", children: "Add new card" })
2362
+ /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { className: "cursor-pointer", value: "saved", children: t.useSavedCardTab }),
2363
+ /* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { className: "cursor-pointer", value: "new", children: t.addNewCardTab })
2081
2364
  ] }),
2082
2365
  /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "saved", children: renderSavedTab() }),
2083
2366
  /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "new", children: renderNewTab() })
2084
2367
  ] });
2368
+ const renderCcbillAction = () => {
2369
+ if (!showCcbill) return null;
2370
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 border-t border-white/10 pt-4", children: [
2371
+ /* @__PURE__ */ jsxRuntime.jsx(
2372
+ Button,
2373
+ {
2374
+ className: "w-full",
2375
+ variant: "outline",
2376
+ disabled: ccbillStatus === "processing",
2377
+ onClick: handleCcbillPayment,
2378
+ children: ccbillStatus === "processing" ? t.processingCcbill : t.payWithCcbill
2379
+ }
2380
+ ),
2381
+ ccbillError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: ccbillError })
2382
+ ] });
2383
+ };
2085
2384
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 pt-4", children: [
2086
- mode === "cards" && renderCardExperience(),
2385
+ mode === "cards" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2386
+ renderCardExperience(),
2387
+ renderCcbillAction()
2388
+ ] }),
2087
2389
  mode === "solana" && enableSolanaPay && /* @__PURE__ */ jsxRuntime.jsx(
2088
2390
  SolanaPaymentView,
2089
2391
  {
@@ -2132,20 +2434,20 @@ var useSubscriptionActions = () => {
2132
2434
  }
2133
2435
  return priceId;
2134
2436
  };
2135
- const subscribeWithCard = React15.useCallback(
2437
+ const subscribeWithCard = React4.useCallback(
2136
2438
  async ({
2137
2439
  priceId,
2138
- processor = "nmi",
2440
+ processor = "mobius",
2139
2441
  provider,
2140
2442
  paymentToken,
2141
2443
  billing,
2142
2444
  idempotencyKey
2143
2445
  }) => {
2144
- const payload = {
2145
- price_id: ensurePrice(priceId),
2446
+ if (processor !== "ccbill" && !paymentToken) {
2447
+ throw new Error("payments-ui: payment token is required for card checkout");
2448
+ }
2449
+ const payment = {
2146
2450
  processor,
2147
- provider,
2148
- payment_token: paymentToken,
2149
2451
  email: billing.email,
2150
2452
  first_name: billing.firstName,
2151
2453
  last_name: billing.lastName,
@@ -2155,14 +2457,25 @@ var useSubscriptionActions = () => {
2155
2457
  zip: billing.postalCode,
2156
2458
  country: billing.country
2157
2459
  };
2460
+ if (paymentToken) {
2461
+ payment.payment_token = paymentToken;
2462
+ payment.last_four = billing.last_four;
2463
+ payment.card_type = billing.card_type;
2464
+ payment.expiry_date = billing.expiry_date;
2465
+ }
2466
+ const payload = {
2467
+ price_id: ensurePrice(priceId),
2468
+ provider,
2469
+ payment
2470
+ };
2158
2471
  return client.checkout(payload, idempotencyKey);
2159
2472
  },
2160
2473
  [client]
2161
2474
  );
2162
- const subscribeWithSavedMethod = React15.useCallback(
2475
+ const subscribeWithSavedMethod = React4.useCallback(
2163
2476
  async ({
2164
2477
  priceId,
2165
- processor = "nmi",
2478
+ processor = "mobius",
2166
2479
  provider,
2167
2480
  paymentMethodId,
2168
2481
  email,
@@ -2170,16 +2483,18 @@ var useSubscriptionActions = () => {
2170
2483
  }) => {
2171
2484
  const payload = {
2172
2485
  price_id: ensurePrice(priceId),
2173
- processor,
2174
2486
  provider,
2175
- payment_method_id: paymentMethodId,
2176
- email
2487
+ payment: {
2488
+ processor,
2489
+ payment_method_id: paymentMethodId,
2490
+ email
2491
+ }
2177
2492
  };
2178
2493
  return client.checkout(payload, idempotencyKey);
2179
2494
  },
2180
2495
  [client]
2181
2496
  );
2182
- const subscribeWithCCBill = React15.useCallback(
2497
+ const subscribeWithCCBill = React4.useCallback(
2183
2498
  async ({
2184
2499
  priceId,
2185
2500
  email,
@@ -2192,12 +2507,14 @@ var useSubscriptionActions = () => {
2192
2507
  }) => {
2193
2508
  const payload = {
2194
2509
  price_id: ensurePrice(priceId),
2195
- processor,
2196
- email,
2197
- first_name: firstName,
2198
- last_name: lastName,
2199
- zip: zipCode,
2200
- country
2510
+ payment: {
2511
+ processor,
2512
+ email,
2513
+ first_name: firstName,
2514
+ last_name: lastName,
2515
+ zip: zipCode,
2516
+ country
2517
+ }
2201
2518
  };
2202
2519
  return client.checkout(payload, idempotencyKey);
2203
2520
  },
@@ -2209,6 +2526,11 @@ var useSubscriptionActions = () => {
2209
2526
  subscribeWithCCBill
2210
2527
  };
2211
2528
  };
2529
+ var defaultTranslations2 = {
2530
+ ...defaultPaymentExperienceTranslations,
2531
+ title: "Checkout",
2532
+ selectPlanMessage: "Select a subscription plan to continue."
2533
+ };
2212
2534
  var SubscriptionCheckoutModal = ({
2213
2535
  open,
2214
2536
  onOpenChange,
@@ -2223,17 +2545,22 @@ var SubscriptionCheckoutModal = ({
2223
2545
  enableSolanaPay = true,
2224
2546
  onSolanaSuccess,
2225
2547
  onSolanaError,
2226
- initialMode = "cards"
2548
+ initialMode = "cards",
2549
+ translations
2227
2550
  }) => {
2228
- const [showSuccess, setShowSuccess] = React15.useState(false);
2229
- const [idempotencyKey, setIdempotencyKey] = React15.useState(() => crypto.randomUUID());
2551
+ const [showSuccess, setShowSuccess] = React4.useState(false);
2552
+ const [idempotencyKey, setIdempotencyKey] = React4.useState(() => crypto.randomUUID());
2230
2553
  const { subscribeWithCard, subscribeWithSavedMethod } = useSubscriptionActions();
2231
- React15.useEffect(() => {
2554
+ const t = {
2555
+ ...defaultTranslations2,
2556
+ ...translations
2557
+ };
2558
+ React4.useEffect(() => {
2232
2559
  if (open) {
2233
2560
  setIdempotencyKey(crypto.randomUUID());
2234
2561
  }
2235
2562
  }, [open, priceId]);
2236
- const handleClose = React15.useCallback(
2563
+ const handleClose = React4.useCallback(
2237
2564
  (nextOpen) => {
2238
2565
  onOpenChange(nextOpen);
2239
2566
  if (!nextOpen) setShowSuccess(false);
@@ -2251,13 +2578,31 @@ var SubscriptionCheckoutModal = ({
2251
2578
  console.debug("[payments-ui] subscription success", result);
2252
2579
  }
2253
2580
  };
2254
- const assertCheckoutSuccess = (status, message) => {
2255
- if (status === "blocked") {
2256
- throw new Error(message || "This subscription cannot be completed right now.");
2581
+ const handleCheckoutResponse = (response) => {
2582
+ if (response.status === "blocked") {
2583
+ throw new Error(response.message || "This subscription cannot be completed right now.");
2257
2584
  }
2258
- if (status === "redirect_required") {
2259
- throw new Error(message || "Additional action required in an alternate flow.");
2585
+ const nextAction = response.next_action;
2586
+ if (nextAction?.type === "redirect_to_url") {
2587
+ const redirectUrl = nextAction.redirect_to_url?.url || response.payment?.redirect_url;
2588
+ if (!redirectUrl) {
2589
+ throw new Error(response.message || "Checkout requires a redirect URL.");
2590
+ }
2591
+ if (typeof window !== "undefined") {
2592
+ window.location.assign(redirectUrl);
2593
+ }
2594
+ return;
2260
2595
  }
2596
+ if (response.payment?.redirect_url) {
2597
+ if (typeof window !== "undefined") {
2598
+ window.location.assign(response.payment.redirect_url);
2599
+ }
2600
+ return;
2601
+ }
2602
+ if (nextAction && nextAction.type !== "none") {
2603
+ throw new Error(response.message || "Unsupported checkout action.");
2604
+ }
2605
+ notifySuccess();
2261
2606
  };
2262
2607
  const handleNewCardPayment = async ({ token, billing }) => {
2263
2608
  const response = await subscribeWithCard({
@@ -2267,8 +2612,7 @@ var SubscriptionCheckoutModal = ({
2267
2612
  paymentToken: token,
2268
2613
  priceId: ensurePrice()
2269
2614
  });
2270
- assertCheckoutSuccess(response.status, response.message);
2271
- notifySuccess();
2615
+ handleCheckoutResponse(response);
2272
2616
  };
2273
2617
  const handleSavedMethodPayment = async ({ paymentMethodId }) => {
2274
2618
  const response = await subscribeWithSavedMethod({
@@ -2278,8 +2622,16 @@ var SubscriptionCheckoutModal = ({
2278
2622
  email: userEmail ?? "",
2279
2623
  idempotencyKey
2280
2624
  });
2281
- assertCheckoutSuccess(response.status, response.message);
2282
- notifySuccess();
2625
+ handleCheckoutResponse(response);
2626
+ };
2627
+ const handleCcbillPayment = async ({ billing }) => {
2628
+ const response = await subscribeWithCard({
2629
+ billing,
2630
+ idempotencyKey,
2631
+ processor: "ccbill",
2632
+ priceId: ensurePrice()
2633
+ });
2634
+ handleCheckoutResponse(response);
2283
2635
  };
2284
2636
  const solanaSuccess = (result) => {
2285
2637
  notifySuccess(result);
@@ -2295,11 +2647,11 @@ var SubscriptionCheckoutModal = ({
2295
2647
  {
2296
2648
  className: "z-[100] max-w-xl max-h-[90vh] overflow-y-auto border border-white/20 p-6 backdrop-blur-xl bg-background-regular rounded-md [&::-webkit-scrollbar]:hidden",
2297
2649
  children: [
2298
- /* @__PURE__ */ jsxRuntime.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "flex items-center gap-2 text-foreground", children: "Checkout" }) }),
2650
+ /* @__PURE__ */ jsxRuntime.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "flex items-center gap-2 text-foreground", children: t.title }) }),
2299
2651
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: !priceId ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-center px-3 py-2 text-sm text-destructive", children: [
2300
2652
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-4 w-4" }),
2301
2653
  " ",
2302
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Select a subscription plan to continue." })
2654
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t.selectPlanMessage })
2303
2655
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(
2304
2656
  PaymentExperience,
2305
2657
  {
@@ -2312,7 +2664,9 @@ var SubscriptionCheckoutModal = ({
2312
2664
  enableStoredMethods: Boolean(priceId),
2313
2665
  enableSolanaPay: enableSolanaPay && Boolean(priceId),
2314
2666
  onNewCardPayment: priceId ? handleNewCardPayment : void 0,
2315
- onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0
2667
+ onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
2668
+ onCcbillPayment: priceId ? handleCcbillPayment : void 0,
2669
+ translations: t
2316
2670
  }
2317
2671
  ) })
2318
2672
  ]
@@ -2322,7 +2676,9 @@ var SubscriptionCheckoutModal = ({
2322
2676
  SubscriptionSuccessDialog,
2323
2677
  {
2324
2678
  open: showSuccess,
2325
- onClose: () => setShowSuccess(false),
2679
+ onClose: () => {
2680
+ setShowSuccess(false);
2681
+ },
2326
2682
  planName,
2327
2683
  amountLabel: amountLabel ?? `$${usdAmount.toFixed(2)}`,
2328
2684
  billingPeriodLabel
@@ -2343,7 +2699,7 @@ var wallets = [
2343
2699
  }
2344
2700
  ];
2345
2701
  var WalletModal = ({ open, onOpenChange }) => {
2346
- const [expandedWallet, setExpandedWallet] = React15.useState(null);
2702
+ const [expandedWallet, setExpandedWallet] = React4.useState(null);
2347
2703
  return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "z-[100] w-full max-w-lg max-h-[90vh] overflow-y-auto rounded-md border border-white/20 p-0 backdrop-blur-xl bg-background-regular shadow-2xl [&::-webkit-scrollbar]:hidden", children: [
2348
2704
  /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { className: "border-b border-white/10 bg-gradient-to-r from-primary/10 via-transparent to-transparent px-6 py-5 text-left", children: [
2349
2705
  /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex items-center gap-2 text-foreground", children: [
@@ -2399,17 +2755,17 @@ var createDialogState = () => ({
2399
2755
  isOpen: false,
2400
2756
  props: null
2401
2757
  });
2402
- var PaymentsDialogContext = React15.createContext(void 0);
2758
+ var PaymentsDialogContext = React4.createContext(void 0);
2403
2759
  var PaymentsDialogProvider = ({
2404
2760
  children
2405
2761
  }) => {
2406
- const [checkoutState, setCheckoutState] = React15.useState(
2762
+ const [checkoutState, setCheckoutState] = React4.useState(
2407
2763
  () => createDialogState()
2408
2764
  );
2409
- const [walletState, setWalletState] = React15.useState(
2765
+ const [walletState, setWalletState] = React4.useState(
2410
2766
  () => createDialogState()
2411
2767
  );
2412
- const contextValue = React15.useMemo(() => {
2768
+ const contextValue = React4.useMemo(() => {
2413
2769
  const openCheckout = (options) => setCheckoutState({
2414
2770
  isOpen: true,
2415
2771
  props: options
@@ -2463,18 +2819,18 @@ var PaymentsDialogProvider = ({
2463
2819
  ] });
2464
2820
  };
2465
2821
  var usePaymentDialogs = () => {
2466
- const context = React15.useContext(PaymentsDialogContext);
2822
+ const context = React4.useContext(PaymentsDialogContext);
2467
2823
  if (!context) {
2468
2824
  throw new Error("usePaymentDialogs must be used within PaymentProvider");
2469
2825
  }
2470
2826
  return context;
2471
2827
  };
2472
- var PaymentContext = React15.createContext(void 0);
2828
+ var PaymentContext = React4.createContext(void 0);
2473
2829
  var PaymentProvider = ({
2474
2830
  config,
2475
2831
  children
2476
2832
  }) => {
2477
- const queryClient = React15.useMemo(() => {
2833
+ const queryClient = React4.useMemo(() => {
2478
2834
  return new reactQuery.QueryClient({
2479
2835
  defaultOptions: {
2480
2836
  queries: {
@@ -2489,7 +2845,7 @@ var PaymentProvider = ({
2489
2845
  }
2490
2846
  });
2491
2847
  }, []);
2492
- const client = React15.useMemo(() => {
2848
+ const client = React4.useMemo(() => {
2493
2849
  const authProvider = config.getAuthToken ? async () => {
2494
2850
  try {
2495
2851
  const result = config.getAuthToken?.();
@@ -2513,12 +2869,12 @@ var PaymentProvider = ({
2513
2869
  defaultHeaders: config.defaultHeaders
2514
2870
  });
2515
2871
  }, [config]);
2516
- const solanaEndpoint = React15.useMemo(() => {
2872
+ const solanaEndpoint = React4.useMemo(() => {
2517
2873
  if (config.solana?.endpoint) return config.solana.endpoint;
2518
2874
  const network = config.solana?.network ?? walletAdapterBase.WalletAdapterNetwork.Mainnet;
2519
2875
  return web3_js.clusterApiUrl(network);
2520
2876
  }, [config.solana?.endpoint, config.solana?.network]);
2521
- const walletAdapters = React15.useMemo(() => {
2877
+ const walletAdapters = React4.useMemo(() => {
2522
2878
  if (config.solana?.wallets?.length) {
2523
2879
  return config.solana.wallets;
2524
2880
  }
@@ -2530,21 +2886,21 @@ var PaymentProvider = ({
2530
2886
  ];
2531
2887
  }, [config.solana?.wallets]);
2532
2888
  const autoConnect = config.solana?.autoConnect ?? true;
2533
- const value = React15.useMemo(() => {
2889
+ const value = React4.useMemo(() => {
2534
2890
  return {
2535
2891
  config,
2536
2892
  client,
2537
2893
  queryClient
2538
2894
  };
2539
2895
  }, [client, config, queryClient]);
2540
- React15.useEffect(() => {
2896
+ React4.useEffect(() => {
2541
2897
  if (!config.collectJsKey) return;
2542
2898
  loadCollectJs(config.collectJsKey);
2543
2899
  }, [config.collectJsKey]);
2544
2900
  return /* @__PURE__ */ jsxRuntime.jsx(PaymentContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: 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 }) }) }) }) }) });
2545
2901
  };
2546
2902
  var usePaymentContext = () => {
2547
- const context = React15.useContext(PaymentContext);
2903
+ const context = React4.useContext(PaymentContext);
2548
2904
  if (!context) {
2549
2905
  throw new Error("usePaymentContext must be used within a PaymentProvider");
2550
2906
  }
@@ -2557,7 +2913,7 @@ var SolanaPaymentSelector = ({
2557
2913
  }) => {
2558
2914
  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 bg-background/95 p-0 shadow-2xl [&::-webkit-scrollbar]:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(SolanaPaymentView, { ...props, onClose }) }) });
2559
2915
  };
2560
- var Table = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
2916
+ var Table = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
2561
2917
  "table",
2562
2918
  {
2563
2919
  ref,
@@ -2566,9 +2922,9 @@ var Table = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @
2566
2922
  }
2567
2923
  ) }));
2568
2924
  Table.displayName = "Table";
2569
- var TableHeader = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
2925
+ var TableHeader = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
2570
2926
  TableHeader.displayName = "TableHeader";
2571
- var TableBody = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2927
+ var TableBody = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2572
2928
  "tbody",
2573
2929
  {
2574
2930
  ref,
@@ -2577,7 +2933,7 @@ var TableBody = React15__namespace.forwardRef(({ className, ...props }, ref) =>
2577
2933
  }
2578
2934
  ));
2579
2935
  TableBody.displayName = "TableBody";
2580
- var TableFooter = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2936
+ var TableFooter = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2581
2937
  "tfoot",
2582
2938
  {
2583
2939
  ref,
@@ -2589,7 +2945,7 @@ var TableFooter = React15__namespace.forwardRef(({ className, ...props }, ref) =
2589
2945
  }
2590
2946
  ));
2591
2947
  TableFooter.displayName = "TableFooter";
2592
- var TableRow = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2948
+ var TableRow = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2593
2949
  "tr",
2594
2950
  {
2595
2951
  ref,
@@ -2601,7 +2957,7 @@ var TableRow = React15__namespace.forwardRef(({ className, ...props }, ref) => /
2601
2957
  }
2602
2958
  ));
2603
2959
  TableRow.displayName = "TableRow";
2604
- var TableHead = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2960
+ var TableHead = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2605
2961
  "th",
2606
2962
  {
2607
2963
  ref,
@@ -2613,7 +2969,7 @@ var TableHead = React15__namespace.forwardRef(({ className, ...props }, ref) =>
2613
2969
  }
2614
2970
  ));
2615
2971
  TableHead.displayName = "TableHead";
2616
- var TableCell = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2972
+ var TableCell = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2617
2973
  "td",
2618
2974
  {
2619
2975
  ref,
@@ -2622,7 +2978,7 @@ var TableCell = React15__namespace.forwardRef(({ className, ...props }, ref) =>
2622
2978
  }
2623
2979
  ));
2624
2980
  TableCell.displayName = "TableCell";
2625
- var TableCaption = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2981
+ var TableCaption = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2626
2982
  "caption",
2627
2983
  {
2628
2984
  ref,
@@ -2634,7 +2990,7 @@ TableCaption.displayName = "TableCaption";
2634
2990
  var AlertDialog = AlertDialogPrimitive__namespace.Root;
2635
2991
  var AlertDialogTrigger = AlertDialogPrimitive__namespace.Trigger;
2636
2992
  var AlertDialogPortal = AlertDialogPrimitive__namespace.Portal;
2637
- var AlertDialogOverlay = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2993
+ var AlertDialogOverlay = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2638
2994
  AlertDialogPrimitive__namespace.Overlay,
2639
2995
  {
2640
2996
  className: cn(
@@ -2646,7 +3002,7 @@ var AlertDialogOverlay = React15__namespace.forwardRef(({ className, ...props },
2646
3002
  }
2647
3003
  ));
2648
3004
  AlertDialogOverlay.displayName = AlertDialogPrimitive__namespace.Overlay.displayName;
2649
- var AlertDialogContent = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogPortal, { children: [
3005
+ var AlertDialogContent = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogPortal, { children: [
2650
3006
  /* @__PURE__ */ jsxRuntime.jsx(AlertDialogOverlay, {}),
2651
3007
  /* @__PURE__ */ jsxRuntime.jsx(
2652
3008
  AlertDialogPrimitive__namespace.Content,
@@ -2689,7 +3045,7 @@ var AlertDialogFooter = ({
2689
3045
  }
2690
3046
  );
2691
3047
  AlertDialogFooter.displayName = "AlertDialogFooter";
2692
- var AlertDialogTitle = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3048
+ var AlertDialogTitle = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2693
3049
  AlertDialogPrimitive__namespace.Title,
2694
3050
  {
2695
3051
  ref,
@@ -2698,7 +3054,7 @@ var AlertDialogTitle = React15__namespace.forwardRef(({ className, ...props }, r
2698
3054
  }
2699
3055
  ));
2700
3056
  AlertDialogTitle.displayName = AlertDialogPrimitive__namespace.Title.displayName;
2701
- var AlertDialogDescription = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3057
+ var AlertDialogDescription = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2702
3058
  AlertDialogPrimitive__namespace.Description,
2703
3059
  {
2704
3060
  ref,
@@ -2707,7 +3063,7 @@ var AlertDialogDescription = React15__namespace.forwardRef(({ className, ...prop
2707
3063
  }
2708
3064
  ));
2709
3065
  AlertDialogDescription.displayName = AlertDialogPrimitive__namespace.Description.displayName;
2710
- var AlertDialogAction = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3066
+ var AlertDialogAction = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2711
3067
  AlertDialogPrimitive__namespace.Action,
2712
3068
  {
2713
3069
  ref,
@@ -2716,7 +3072,7 @@ var AlertDialogAction = React15__namespace.forwardRef(({ className, ...props },
2716
3072
  }
2717
3073
  ));
2718
3074
  AlertDialogAction.displayName = AlertDialogPrimitive__namespace.Action.displayName;
2719
- var AlertDialogCancel = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3075
+ var AlertDialogCancel = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2720
3076
  AlertDialogPrimitive__namespace.Cancel,
2721
3077
  {
2722
3078
  ref,
@@ -2729,7 +3085,7 @@ var AlertDialogCancel = React15__namespace.forwardRef(({ className, ...props },
2729
3085
  }
2730
3086
  ));
2731
3087
  AlertDialogCancel.displayName = AlertDialogPrimitive__namespace.Cancel.displayName;
2732
- var Textarea = React15__namespace.forwardRef(({ className, ...props }, ref) => {
3088
+ var Textarea = React4__namespace.forwardRef(({ className, ...props }, ref) => {
2733
3089
  return /* @__PURE__ */ jsxRuntime.jsx(
2734
3090
  "textarea",
2735
3091
  {
@@ -2747,7 +3103,7 @@ var notifyDefault = (payload) => {
2747
3103
  const level = payload.status === "destructive" ? "error" : "info";
2748
3104
  console[level === "error" ? "error" : "log"]("[payments-ui] cancellation", payload);
2749
3105
  };
2750
- var defaultTranslations = {
3106
+ var defaultTranslations3 = {
2751
3107
  buttonLabel: "Cancel Membership",
2752
3108
  title: "Confirm Membership Cancellation",
2753
3109
  description: "You are about to cancel your membership. Please review the consequences:",
@@ -2769,23 +3125,33 @@ var CancelMembershipDialog = ({
2769
3125
  minReasonLength = 15,
2770
3126
  onCancelled,
2771
3127
  onNotify,
2772
- translations: customTranslations
3128
+ translations: customTranslations,
3129
+ open,
3130
+ onOpenChange
2773
3131
  }) => {
2774
3132
  const { client } = usePaymentContext();
2775
3133
  const notify = onNotify ?? notifyDefault;
2776
- const t = { ...defaultTranslations, ...customTranslations };
2777
- const [cancelReason, setCancelReason] = React15.useState("");
2778
- const [isOpen, setIsOpen] = React15.useState(false);
2779
- const [isReasonValid, setIsReasonValid] = React15.useState(false);
2780
- const [hasInteracted, setHasInteracted] = React15.useState(false);
2781
- const [isSubmitting, setIsSubmitting] = React15.useState(false);
2782
- React15.useEffect(() => {
3134
+ const t = { ...defaultTranslations3, ...customTranslations };
3135
+ const [cancelReason, setCancelReason] = React4.useState("");
3136
+ const [internalOpen, setInternalOpen] = React4.useState(false);
3137
+ const [isReasonValid, setIsReasonValid] = React4.useState(false);
3138
+ const [hasInteracted, setHasInteracted] = React4.useState(false);
3139
+ const [isSubmitting, setIsSubmitting] = React4.useState(false);
3140
+ const isControlled = typeof open === "boolean";
3141
+ const isOpen = isControlled ? open : internalOpen;
3142
+ const setOpen = (next) => {
3143
+ if (!isControlled) {
3144
+ setInternalOpen(next);
3145
+ }
3146
+ onOpenChange?.(next);
3147
+ };
3148
+ React4.useEffect(() => {
2783
3149
  const trimmed = cancelReason.trim();
2784
3150
  setIsReasonValid(trimmed.length >= minReasonLength);
2785
3151
  }, [cancelReason, minReasonLength]);
2786
- const handleOpenChange = (open) => {
2787
- setIsOpen(open);
2788
- if (!open) {
3152
+ const handleOpenChange = (open2) => {
3153
+ setOpen(open2);
3154
+ if (!open2) {
2789
3155
  setCancelReason("");
2790
3156
  setIsReasonValid(false);
2791
3157
  setHasInteracted(false);
@@ -2822,7 +3188,7 @@ var CancelMembershipDialog = ({
2822
3188
  };
2823
3189
  const showError = hasInteracted && !isReasonValid;
2824
3190
  return /* @__PURE__ */ jsxRuntime.jsxs(AlertDialog, { open: isOpen, onOpenChange: handleOpenChange, children: [
2825
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", className: "border-destructive/50 text-destructive", children: [
3191
+ /* @__PURE__ */ jsxRuntime.jsx(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { className: "bg-destructive text-destructive-foreground border-destructive/50 hover:bg-destructive/90", children: [
2826
3192
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ban, { className: "mr-2 h-4 w-4" }),
2827
3193
  " ",
2828
3194
  t.buttonLabel
@@ -2889,7 +3255,7 @@ var notifyDefault2 = (payload) => {
2889
3255
  const level = payload.status === "destructive" ? "error" : "info";
2890
3256
  console[level === "error" ? "error" : "log"]("[payments-ui] billing", payload);
2891
3257
  };
2892
- var defaultTranslations2 = {
3258
+ var defaultTranslations4 = {
2893
3259
  title: "Transaction History",
2894
3260
  description: "Record of billing history",
2895
3261
  reviewActivity: "Review your account activity below",
@@ -2911,10 +3277,10 @@ var BillingHistory = ({
2911
3277
  }) => {
2912
3278
  const { client } = usePaymentContext();
2913
3279
  const notify = onNotify ?? notifyDefault2;
2914
- const t = { ...defaultTranslations2, ...customTranslations };
2915
- const [isExpanded, setIsExpanded] = React15.useState(false);
2916
- const observerRef = React15.useRef(null);
2917
- const loadMoreRef = React15.useRef(null);
3280
+ const t = { ...defaultTranslations4, ...customTranslations };
3281
+ const [isExpanded, setIsExpanded] = React4.useState(false);
3282
+ const observerRef = React4.useRef(null);
3283
+ const loadMoreRef = React4.useRef(null);
2918
3284
  const historyQuery = reactQuery.useInfiniteQuery({
2919
3285
  queryKey: ["payments-ui", "billing-history", pageSize],
2920
3286
  queryFn: async ({ pageParam = initialPage }) => {
@@ -2941,7 +3307,7 @@ var BillingHistory = ({
2941
3307
  },
2942
3308
  staleTime: 5 * 60 * 1e3
2943
3309
  });
2944
- React15.useEffect(() => {
3310
+ React4.useEffect(() => {
2945
3311
  if (!loadMoreRef.current || !isExpanded) return;
2946
3312
  observerRef.current = new IntersectionObserver((entries) => {
2947
3313
  const [entry] = entries;
@@ -2956,7 +3322,7 @@ var BillingHistory = ({
2956
3322
  observerRef.current?.disconnect();
2957
3323
  };
2958
3324
  }, [historyQuery, isExpanded, notify]);
2959
- const payments = React15.useMemo(() => {
3325
+ const payments = React4.useMemo(() => {
2960
3326
  const data = historyQuery.data;
2961
3327
  return data?.pages ?? [];
2962
3328
  }, [historyQuery.data]);
@@ -3020,15 +3386,21 @@ var BillingHistory = ({
3020
3386
  ] }) });
3021
3387
  };
3022
3388
  var formatCardLabel2 = (method) => {
3023
- const brand = method.card_type ? method.card_type.toUpperCase() : "CARD";
3024
- const lastFour = method.last_four ? `\u2022\u2022\u2022\u2022 ${method.last_four}` : "";
3389
+ if (method.card) {
3390
+ const brand2 = method.card.brand ? method.card.brand.toUpperCase() : "CARD";
3391
+ const lastFour2 = method.card.last4 ? `\u2022\u2022\u2022\u2022 ${method.card.last4}` : "";
3392
+ const exp = method.card.exp_month && method.card.exp_year ? ` \u2022 ${String(method.card.exp_month).padStart(2, "0")}/${String(method.card.exp_year).slice(-2)}` : "";
3393
+ return `${brand2} ${lastFour2}${exp}`.trim();
3394
+ }
3395
+ const brand = "CARD";
3396
+ const lastFour = "";
3025
3397
  return `${brand} ${lastFour}`.trim();
3026
3398
  };
3027
3399
  var notifyDefault3 = (payload) => {
3028
3400
  const level = payload.status === "destructive" ? "error" : "info";
3029
3401
  console[level === "error" ? "error" : "log"]("[payments-ui] notification", payload);
3030
3402
  };
3031
- var defaultTranslations3 = {
3403
+ var defaultTranslations5 = {
3032
3404
  title: "Payment Methods",
3033
3405
  description: "Manage your saved billing cards",
3034
3406
  addCard: "Add card",
@@ -3049,7 +3421,11 @@ var defaultTranslations3 = {
3049
3421
  cardUpdated: "Card updated",
3050
3422
  unableToRemoveCard: "Unable to remove card",
3051
3423
  defaultPaymentMethodUpdated: "Default payment method updated",
3052
- unableToSetDefault: "Unable to set default payment method"
3424
+ unableToSetDefault: "Unable to set default payment method",
3425
+ errors: {},
3426
+ activeSubscriptions: "Active subscriptions",
3427
+ showSubscriptions: "Show",
3428
+ hideSubscriptions: "Hide"
3053
3429
  };
3054
3430
  var PaymentMethodsSection = ({
3055
3431
  isAuthenticated = true,
@@ -3060,8 +3436,7 @@ var PaymentMethodsSection = ({
3060
3436
  onNotify,
3061
3437
  translations: customTranslations
3062
3438
  }) => {
3063
- const { client } = usePaymentContext();
3064
- const queryClient = reactQuery.useQueryClient();
3439
+ const { client, queryClient } = usePaymentContext();
3065
3440
  const paymentMethods = {
3066
3441
  list: (params) => client.listPaymentMethods({ limit: params.pageSize }),
3067
3442
  create: (payload) => client.createPaymentMethod(payload),
@@ -3069,15 +3444,17 @@ var PaymentMethodsSection = ({
3069
3444
  remove: (id) => client.deletePaymentMethod(id),
3070
3445
  activate: (id) => client.activatePaymentMethod(id)
3071
3446
  };
3072
- const [isModalOpen, setIsModalOpen] = React15.useState(false);
3073
- const [deletingId, setDeletingId] = React15.useState(null);
3447
+ const [isModalOpen, setIsModalOpen] = React4.useState(false);
3448
+ const [deletingId, setDeletingId] = React4.useState(null);
3449
+ const [createErrorMessage, setCreateErrorMessage] = React4.useState(null);
3450
+ const [expandedSubscriptions, setExpandedSubscriptions] = React4.useState({});
3074
3451
  const notify = onNotify ?? notifyDefault3;
3075
- const t = { ...defaultTranslations3, ...customTranslations };
3452
+ const t = { ...defaultTranslations5, ...customTranslations };
3076
3453
  const queryKey = ["payments-ui", "payment-methods"];
3077
3454
  const paymentQuery = reactQuery.useQuery({
3078
3455
  queryKey,
3079
3456
  queryFn: () => paymentMethods.list({ pageSize: 50 }),
3080
- enabled: isAuthenticated,
3457
+ enabled: isAuthenticated && !!client,
3081
3458
  staleTime: 3e4
3082
3459
  });
3083
3460
  const createMutation = reactQuery.useMutation({
@@ -3086,11 +3463,14 @@ var PaymentMethodsSection = ({
3086
3463
  notify({ title: t.cardAddedSuccess, status: "success" });
3087
3464
  setIsModalOpen(false);
3088
3465
  void queryClient.invalidateQueries({ queryKey });
3466
+ setCreateErrorMessage(null);
3089
3467
  },
3090
3468
  onError: (error) => {
3469
+ const message = resolveErrorMessageByCode(error, t.errors, error.message);
3470
+ setCreateErrorMessage(message);
3091
3471
  notify({
3092
3472
  title: t.unableToAddCard,
3093
- description: error.message,
3473
+ description: message,
3094
3474
  status: "destructive"
3095
3475
  });
3096
3476
  }
@@ -3101,6 +3481,9 @@ var PaymentMethodsSection = ({
3101
3481
  onSuccess: () => {
3102
3482
  notify({ title: t.cardRemoved, status: "success" });
3103
3483
  void queryClient.invalidateQueries({ queryKey });
3484
+ if (paymentQuery.refetch) {
3485
+ paymentQuery.refetch();
3486
+ }
3104
3487
  },
3105
3488
  onError: (error) => {
3106
3489
  notify({
@@ -3111,7 +3494,7 @@ var PaymentMethodsSection = ({
3111
3494
  },
3112
3495
  onSettled: () => setDeletingId(null)
3113
3496
  });
3114
- const activateMutation = reactQuery.useMutation({
3497
+ reactQuery.useMutation({
3115
3498
  mutationFn: (id) => paymentMethods.activate(id),
3116
3499
  onSuccess: () => {
3117
3500
  notify({ title: t.defaultPaymentMethodUpdated, status: "success" });
@@ -3125,12 +3508,18 @@ var PaymentMethodsSection = ({
3125
3508
  });
3126
3509
  }
3127
3510
  });
3128
- React15.useEffect(() => {
3511
+ React4.useEffect(() => {
3129
3512
  if (!isModalOpen) {
3130
3513
  createMutation.reset();
3514
+ setCreateErrorMessage(null);
3515
+ }
3516
+ }, [isModalOpen]);
3517
+ React4.useEffect(() => {
3518
+ if (!isModalOpen && paymentQuery.refetch) {
3519
+ paymentQuery.refetch();
3131
3520
  }
3132
- }, [createMutation, isModalOpen]);
3133
- const payments = React15.useMemo(() => paymentQuery.data?.data ?? [], [paymentQuery.data]);
3521
+ }, [isModalOpen]);
3522
+ const payments = React4.useMemo(() => paymentQuery.data?.data ?? [], [paymentQuery.data]);
3134
3523
  const loading = paymentQuery.isLoading || paymentQuery.isFetching;
3135
3524
  const buildPayload = (token, billing) => ({
3136
3525
  payment_token: token,
@@ -3143,9 +3532,13 @@ var PaymentMethodsSection = ({
3143
3532
  zip: billing.postalCode,
3144
3533
  country: billing.country,
3145
3534
  email: billing.email,
3146
- provider: billing.provider
3535
+ provider: billing.provider,
3536
+ last_four: billing.last_four,
3537
+ card_type: billing.card_type,
3538
+ expiry_date: billing.expiry_date
3147
3539
  });
3148
3540
  const handleCardTokenize = (token, billing) => {
3541
+ setCreateErrorMessage(null);
3149
3542
  createMutation.mutate(buildPayload(token, billing));
3150
3543
  };
3151
3544
  return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "border-0 bg-black/30 shadow-2xl backdrop-blur-xl", children: [
@@ -3164,32 +3557,19 @@ var PaymentMethodsSection = ({
3164
3557
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-5 w-5 animate-spin" }),
3165
3558
  " ",
3166
3559
  t.loadingCards
3167
- ] }) : payments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 text-sm text-center", children: t.noPaymentMethods }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: payments.map((method) => /* @__PURE__ */ jsxRuntime.jsxs(
3168
- "div",
3169
- {
3170
- className: "rounded-lg border bg-white/5 p-4 shadow-sm",
3171
- children: [
3172
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
3173
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
3174
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-medium text-white", children: formatCardLabel2(method) }),
3175
- /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: method.is_active ? "default" : "secondary", children: method.is_active ? t.active : t.inactive })
3560
+ ] }) : payments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 text-sm text-center", children: t.noPaymentMethods }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: payments.map((method) => {
3561
+ (method.subscriptions?.length ?? 0) > 0;
3562
+ expandedSubscriptions[method.id] ?? false;
3563
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3564
+ "div",
3565
+ {
3566
+ className: "rounded-lg border bg-white/5 p-4 shadow-sm",
3567
+ children: [
3568
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
3569
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-between", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-medium text-white", children: formatCardLabel2(method) }) }),
3570
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: method.failure_reason && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "destructive", children: method.failure_reason }) })
3176
3571
  ] }),
3177
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: method.failure_reason && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "destructive", children: method.failure_reason }) })
3178
- ] }),
3179
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex flex-wrap gap-2", children: [
3180
- /* @__PURE__ */ jsxRuntime.jsxs(
3181
- Button,
3182
- {
3183
- variant: "outline",
3184
- disabled: method.is_active || activateMutation.isPending,
3185
- onClick: () => activateMutation.mutate(method.id),
3186
- children: [
3187
- activateMutation.isPending ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
3188
- method.is_active ? t.defaultMethod : t.makeDefault
3189
- ]
3190
- }
3191
- ),
3192
- /* @__PURE__ */ jsxRuntime.jsxs(
3572
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
3193
3573
  Button,
3194
3574
  {
3195
3575
  variant: "ghost",
@@ -3201,12 +3581,12 @@ var PaymentMethodsSection = ({
3201
3581
  t.remove
3202
3582
  ]
3203
3583
  }
3204
- )
3205
- ] })
3206
- ]
3207
- },
3208
- method.id
3209
- )) }) }),
3584
+ ) })
3585
+ ]
3586
+ },
3587
+ method.id
3588
+ );
3589
+ }) }) }),
3210
3590
  /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(
3211
3591
  DialogContent,
3212
3592
  {
@@ -3224,12 +3604,13 @@ var PaymentMethodsSection = ({
3224
3604
  collectPrefix,
3225
3605
  onTokenize: handleCardTokenize,
3226
3606
  submitting: createMutation.isPending,
3607
+ translations: t,
3227
3608
  defaultValues: {
3228
3609
  provider,
3229
3610
  email: userEmail ?? "",
3230
3611
  country: defaultCountry
3231
3612
  },
3232
- externalError: createMutation.error?.message ?? null
3613
+ externalError: createErrorMessage
3233
3614
  }
3234
3615
  )
3235
3616
  ]
@@ -3237,7 +3618,388 @@ var PaymentMethodsSection = ({
3237
3618
  ) })
3238
3619
  ] });
3239
3620
  };
3240
- var Checkbox = React15__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3621
+ var notifyDefault4 = (payload) => {
3622
+ const level = payload.status === "destructive" ? "error" : "info";
3623
+ console[level === "error" ? "error" : "log"]("[payments-ui] notification", payload);
3624
+ };
3625
+ var defaultTranslations6 = {
3626
+ title: "Subscriptions",
3627
+ description: "Manage your active and recent subscriptions.",
3628
+ loading: "Loading subscriptions...",
3629
+ noSubscriptions: "No subscriptions found.",
3630
+ status: "Status",
3631
+ active: "Active",
3632
+ cancelled: "Cancelled",
3633
+ pastDue: "Past due",
3634
+ pending: "Pending",
3635
+ paymentMethodLabel: "Payment method",
3636
+ changePaymentMethod: "Change payment method",
3637
+ paymentMethodUpdated: "Payment method updated",
3638
+ paymentMethodUpdateFailed: "Unable to update payment method",
3639
+ resume: "Resume subscription",
3640
+ changePlan: "Change plan",
3641
+ changePlanPlaceholder: "Enter a new price ID",
3642
+ planChanged: "Subscription updated",
3643
+ planChangeFailed: "Unable to update subscription",
3644
+ planChangeUnavailable: "Plan changes are unavailable for this subscription.",
3645
+ resumeSuccess: "Resume requested",
3646
+ resumeFailed: "Unable to resume subscription",
3647
+ update: "Update",
3648
+ product: "Product",
3649
+ price: "Price",
3650
+ currentPeriod: "Current period",
3651
+ refresh: "Refresh",
3652
+ manage: "Manage",
3653
+ close: "Close",
3654
+ paymentMethodTab: "Payment method",
3655
+ changePlanTab: "Change plan",
3656
+ statusTab: "Details",
3657
+ cancelTab: "Cancel/Resume"
3658
+ };
3659
+ var formatCardLabel3 = (method) => {
3660
+ if (method.card) {
3661
+ const brand2 = method.card.brand ? method.card.brand.toUpperCase() : "CARD";
3662
+ const lastFour2 = method.card.last4 ? `\u2022\u2022\u2022\u2022 ${method.card.last4}` : "";
3663
+ const exp = method.card.exp_month && method.card.exp_year ? ` \u2022 ${String(method.card.exp_month).padStart(2, "0")}/${String(method.card.exp_year).slice(-2)}` : "";
3664
+ return `${brand2} ${lastFour2}${exp}`.trim();
3665
+ }
3666
+ const brand = "CARD";
3667
+ const lastFour = "";
3668
+ return `${brand} ${lastFour}`.trim();
3669
+ };
3670
+ var SubscriptionsSection = ({
3671
+ isAuthenticated = true,
3672
+ translations: customTranslations,
3673
+ onNotify,
3674
+ statusFilter,
3675
+ cancelDialogTranslations,
3676
+ onCancelled
3677
+ }) => {
3678
+ const { client, queryClient } = usePaymentContext();
3679
+ const notify = onNotify ?? notifyDefault4;
3680
+ const t = { ...defaultTranslations6, ...customTranslations };
3681
+ const cancelTranslations = cancelDialogTranslations ?? defaultTranslations3;
3682
+ const [paymentSelections, setPaymentSelections] = React4.useState({});
3683
+ const [priceInputs, setPriceInputs] = React4.useState({});
3684
+ const [activeSubId, setActiveSubId] = React4.useState(null);
3685
+ const [cancelDialogOpen, setCancelDialogOpen] = React4.useState(false);
3686
+ const [sectionsOpen, setSectionsOpen] = React4.useState({
3687
+ status: true,
3688
+ payment: false,
3689
+ plan: false,
3690
+ cancel: false
3691
+ });
3692
+ const normalizedStatusFilter = statusFilter ?? "all";
3693
+ const subscriptionsQueryKey = ["payments-ui", "subscriptions", normalizedStatusFilter];
3694
+ const paymentMethodsQueryKey = ["payments-ui", "payment-methods"];
3695
+ const subscriptionsQuery = reactQuery.useQuery({
3696
+ queryKey: subscriptionsQueryKey,
3697
+ queryFn: () => client.listSubscriptions({
3698
+ status: normalizedStatusFilter,
3699
+ limit: 50
3700
+ }),
3701
+ enabled: isAuthenticated && !!client,
3702
+ staleTime: 3e4
3703
+ });
3704
+ const paymentMethodsQuery = reactQuery.useQuery({
3705
+ queryKey: paymentMethodsQueryKey,
3706
+ queryFn: () => client.listPaymentMethods({ limit: 50 }),
3707
+ enabled: isAuthenticated && !!client,
3708
+ staleTime: 3e4
3709
+ });
3710
+ const subscriptions = React4.useMemo(() => subscriptionsQuery.data?.data ?? [], [subscriptionsQuery.data]);
3711
+ const paymentMethods = React4.useMemo(() => paymentMethodsQuery.data?.data ?? [], [paymentMethodsQuery.data]);
3712
+ const activeSubscription = React4.useMemo(
3713
+ () => subscriptions.find((sub) => sub.id === activeSubId),
3714
+ [subscriptions, activeSubId]
3715
+ );
3716
+ React4.useEffect(() => {
3717
+ setPaymentSelections((prev) => {
3718
+ const next = {};
3719
+ subscriptions.forEach((sub) => {
3720
+ next[sub.id] = prev[sub.id] ?? "";
3721
+ });
3722
+ return next;
3723
+ });
3724
+ }, [subscriptions]);
3725
+ React4.useEffect(() => {
3726
+ setCancelDialogOpen(false);
3727
+ }, [activeSubId]);
3728
+ const updatePaymentMethodMutation = reactQuery.useMutation({
3729
+ mutationFn: (payload) => client.updateSubscriptionPaymentMethod({
3730
+ subscription_id: payload.subscriptionId,
3731
+ payment_method_id: payload.paymentMethodId
3732
+ }),
3733
+ onSuccess: () => {
3734
+ notify({ title: t.paymentMethodUpdated, status: "success" });
3735
+ void queryClient.invalidateQueries({ queryKey: subscriptionsQueryKey });
3736
+ },
3737
+ onError: (error) => {
3738
+ notify({
3739
+ title: t.paymentMethodUpdateFailed,
3740
+ description: resolveErrorMessageByCode(error, {}, error.message),
3741
+ status: "destructive"
3742
+ });
3743
+ }
3744
+ });
3745
+ const resumeSubscriptionMutation = reactQuery.useMutation({
3746
+ mutationFn: () => client.resumeSubscription(),
3747
+ onSuccess: () => {
3748
+ notify({ title: t.resumeSuccess, status: "success" });
3749
+ void queryClient.invalidateQueries({ queryKey: subscriptionsQueryKey });
3750
+ },
3751
+ onError: (error) => {
3752
+ notify({
3753
+ title: t.resumeFailed,
3754
+ description: resolveErrorMessageByCode(error, {}, error.message),
3755
+ status: "destructive"
3756
+ });
3757
+ }
3758
+ });
3759
+ reactQuery.useMutation({
3760
+ mutationFn: (payload) => client.changeSubscription({ price_id: payload.priceId }),
3761
+ onSuccess: () => {
3762
+ notify({ title: t.planChanged, status: "success" });
3763
+ void queryClient.invalidateQueries({ queryKey: subscriptionsQueryKey });
3764
+ },
3765
+ onError: (error) => {
3766
+ notify({
3767
+ title: t.planChangeFailed,
3768
+ description: resolveErrorMessageByCode(error, {}, error.message),
3769
+ status: "destructive"
3770
+ });
3771
+ }
3772
+ });
3773
+ const isLoading = subscriptionsQuery.isLoading || subscriptionsQuery.isFetching;
3774
+ const isError = subscriptionsQuery.isError;
3775
+ const errorMessage = subscriptionsQuery.error instanceof Error ? subscriptionsQuery.error.message : void 0;
3776
+ React4.useEffect(() => {
3777
+ if (subscriptionsQuery.refetch) {
3778
+ void subscriptionsQuery.refetch();
3779
+ }
3780
+ }, []);
3781
+ const formatPrice = (sub) => {
3782
+ const price = sub.price;
3783
+ if (!price) return t.price;
3784
+ const amount = (price.amount / 100).toFixed(2);
3785
+ const currency = price.currency ? price.currency?.toUpperCase() : "";
3786
+ return `${price.display_name ?? t.price} \u2014 ${currency} ${amount}`;
3787
+ };
3788
+ const renderStatusBadge = (status) => {
3789
+ const normalized = status.toLowerCase();
3790
+ const label = normalized === "active" ? t.active : normalized === "past_due" ? t.pastDue : normalized === "pending" ? t.pending : t.cancelled;
3791
+ const variant = normalized === "active" ? "default" : normalized === "past_due" ? "destructive" : normalized === "pending" ? "outline" : "secondary";
3792
+ return /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant, children: label });
3793
+ };
3794
+ const handleUpdatePaymentMethod = (subscriptionId) => {
3795
+ const paymentMethodId = paymentSelections[subscriptionId];
3796
+ const currentPaymentMethodId = "pm_" + subscriptions.find((s) => s.id === subscriptionId)?.payment_method_id;
3797
+ if (!paymentMethodId) return;
3798
+ if (currentPaymentMethodId && paymentMethodId === currentPaymentMethodId) {
3799
+ notify({
3800
+ title: t.paymentMethodUpdateFailed,
3801
+ description: t.paymentMethodUpdateFailed,
3802
+ status: "destructive"
3803
+ });
3804
+ return;
3805
+ }
3806
+ updatePaymentMethodMutation.mutate({ subscriptionId, paymentMethodId });
3807
+ };
3808
+ const toggleSection = (key) => {
3809
+ setSectionsOpen((prev) => ({
3810
+ ...prev,
3811
+ [key]: !prev[key]
3812
+ }));
3813
+ };
3814
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3815
+ /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "border-0 bg-black/30 shadow-2xl backdrop-blur-xl", children: [
3816
+ /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "flex flex-col gap-4 md:flex-row md:items-center md:justify-between", children: [
3817
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3818
+ /* @__PURE__ */ jsxRuntime.jsxs(CardTitle, { className: "flex items-center gap-2", children: [
3819
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.WalletCards, { className: "h-5 w-5" }),
3820
+ t.title
3821
+ ] }),
3822
+ /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: t.description })
3823
+ ] }),
3824
+ /* @__PURE__ */ jsxRuntime.jsxs(
3825
+ Button,
3826
+ {
3827
+ variant: "ghost",
3828
+ size: "sm",
3829
+ onClick: () => subscriptionsQuery.refetch?.(),
3830
+ disabled: subscriptionsQuery.isFetching,
3831
+ children: [
3832
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "mr-2 h-4 w-4" }),
3833
+ " ",
3834
+ subscriptionsQuery.isFetching ? t.loading : t.refresh
3835
+ ]
3836
+ }
3837
+ )
3838
+ ] }),
3839
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "space-y-4", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center py-10 text-white/60", children: [
3840
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-5 w-5 animate-spin" }),
3841
+ " ",
3842
+ t.loading
3843
+ ] }) : isError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-red-500/30 bg-red-500/10 p-4 text-sm text-red-100", children: errorMessage ?? "Unable to load subscriptions." }) : subscriptions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 text-sm text-center", children: t.noSubscriptions }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: subscriptions.map((subscription) => {
3844
+ return /* @__PURE__ */ jsxRuntime.jsx(
3845
+ "div",
3846
+ {
3847
+ className: "rounded-lg border bg-white/5 p-4 shadow-sm",
3848
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
3849
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3850
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-semibold text-white", children: subscription.product?.display_name ?? t.product }),
3851
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-white/80", children: formatPrice(subscription) })
3852
+ ] }),
3853
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3854
+ renderStatusBadge(subscription.status),
3855
+ /* @__PURE__ */ jsxRuntime.jsx(
3856
+ Button,
3857
+ {
3858
+ variant: "default",
3859
+ size: "sm",
3860
+ className: "rounded-full bg-foreground/10 text-muted-foreground hover:bg-foreground/20 hover:text-foreground",
3861
+ onClick: () => setActiveSubId(subscription.id),
3862
+ children: t.update
3863
+ }
3864
+ )
3865
+ ] })
3866
+ ] })
3867
+ },
3868
+ subscription.id
3869
+ );
3870
+ }) }) })
3871
+ ] }),
3872
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: !!activeSubscription, onOpenChange: (open) => setActiveSubId(open ? activeSubId : null), children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-w-2xl min-h-[300px] border border-white/20 bg-background-regular p-6 text-foreground", children: [
3873
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
3874
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "flex items-center gap-2", children: activeSubscription?.product?.display_name ?? t.product }),
3875
+ /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { className: "text-white/70", children: activeSubscription ? formatPrice(activeSubscription) : null })
3876
+ ] }),
3877
+ activeSubscription && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 space-y-3", children: [
3878
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-lg border border-white/15 bg-white/5", children: [
3879
+ /* @__PURE__ */ jsxRuntime.jsxs(
3880
+ "button",
3881
+ {
3882
+ type: "button",
3883
+ className: "flex w-full items-center justify-between px-4 py-3 text-left text-white hover:bg-white/10",
3884
+ onClick: () => toggleSection("status"),
3885
+ children: [
3886
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: t.statusTab }),
3887
+ /* @__PURE__ */ jsxRuntime.jsx(
3888
+ lucideReact.ChevronDown,
3889
+ {
3890
+ className: `h-4 w-4 transition-transform ${sectionsOpen.status ? "rotate-180" : ""}`
3891
+ }
3892
+ )
3893
+ ]
3894
+ }
3895
+ ),
3896
+ sectionsOpen.status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 border-t border-white/10 px-4 py-3", children: [
3897
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between rounded-lg border border-white/10 bg-white/5 p-3", children: [
3898
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-white/80", children: t.status }),
3899
+ renderStatusBadge(activeSubscription.status)
3900
+ ] }),
3901
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-white/60", children: [
3902
+ t.currentPeriod,
3903
+ ": ",
3904
+ activeSubscription.started_at ? new Date(activeSubscription.started_at).toLocaleDateString() : "\u2014",
3905
+ " \u2192",
3906
+ " ",
3907
+ activeSubscription.current_period_ends_at ?? "\u2014"
3908
+ ] }),
3909
+ activeSubscription.status.toLowerCase() === "cancelled" ? /* @__PURE__ */ jsxRuntime.jsxs(
3910
+ Button,
3911
+ {
3912
+ variant: "secondary",
3913
+ onClick: () => resumeSubscriptionMutation.mutate(),
3914
+ disabled: resumeSubscriptionMutation.isPending,
3915
+ className: "rounded-full px-4",
3916
+ children: [
3917
+ resumeSubscriptionMutation.isPending ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
3918
+ t.resume
3919
+ ]
3920
+ }
3921
+ ) : null
3922
+ ] }) : null
3923
+ ] }),
3924
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-lg border border-white/15 bg-white/5", children: [
3925
+ /* @__PURE__ */ jsxRuntime.jsxs(
3926
+ "button",
3927
+ {
3928
+ type: "button",
3929
+ className: "flex w-full items-center justify-between px-4 py-3 text-left text-white hover:bg-white/10",
3930
+ onClick: () => toggleSection("payment"),
3931
+ children: [
3932
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: t.paymentMethodTab }),
3933
+ /* @__PURE__ */ jsxRuntime.jsx(
3934
+ lucideReact.ChevronDown,
3935
+ {
3936
+ className: `h-4 w-4 transition-transform ${sectionsOpen.payment ? "rotate-180" : ""}`
3937
+ }
3938
+ )
3939
+ ]
3940
+ }
3941
+ ),
3942
+ sectionsOpen.payment ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 border-t border-white/10 px-4 py-3", children: [
3943
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs uppercase tracking-wide text-white/60", children: t.paymentMethodLabel }),
3944
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:gap-2", children: [
3945
+ /* @__PURE__ */ jsxRuntime.jsxs(
3946
+ Select,
3947
+ {
3948
+ value: paymentSelections[activeSubscription.id] || "pm_" + activeSubscription.payment_method_id || "",
3949
+ onValueChange: (value) => setPaymentSelections((prev) => ({ ...prev, [activeSubscription.id]: value })),
3950
+ disabled: paymentMethodsQuery.isLoading || paymentMethods.length === 0,
3951
+ children: [
3952
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "w-full md:w-64 text-white", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: paymentMethodsQuery.isLoading ? t.loading : "" }) }),
3953
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: paymentMethods.filter((method) => method.id !== activeSubscription.payment_method_id).map((method) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: method.id, children: formatCardLabel3(method) }, method.id)) })
3954
+ ]
3955
+ }
3956
+ ),
3957
+ /* @__PURE__ */ jsxRuntime.jsxs(
3958
+ Button,
3959
+ {
3960
+ size: "sm",
3961
+ onClick: () => handleUpdatePaymentMethod(activeSubscription.id),
3962
+ disabled: updatePaymentMethodMutation.isPending || !paymentSelections[activeSubscription.id] || paymentSelections[activeSubscription.id] === activeSubscription.payment_method_id,
3963
+ className: "border-0 bg-green-bg text-white hover:bg-green-bg/80 disabled:opacity-50",
3964
+ children: [
3965
+ updatePaymentMethodMutation.isPending ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
3966
+ t.update
3967
+ ]
3968
+ }
3969
+ )
3970
+ ] })
3971
+ ] }) : null
3972
+ ] })
3973
+ ] }),
3974
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { className: "flex flex-wrap gap-2", children: [
3975
+ /* @__PURE__ */ jsxRuntime.jsx(
3976
+ CancelMembershipDialog,
3977
+ {
3978
+ translations: cancelTranslations,
3979
+ onNotify,
3980
+ open: cancelDialogOpen,
3981
+ onOpenChange: (openState) => setCancelDialogOpen(openState),
3982
+ onCancelled: () => {
3983
+ void queryClient.invalidateQueries({ queryKey: subscriptionsQueryKey });
3984
+ onCancelled?.();
3985
+ setActiveSubId(null);
3986
+ }
3987
+ }
3988
+ ),
3989
+ /* @__PURE__ */ jsxRuntime.jsx(
3990
+ Button,
3991
+ {
3992
+ variant: "secondary",
3993
+ onClick: () => setActiveSubId(null),
3994
+ className: "border-white/20 bg-transparent text-foreground hover:bg-foreground/10 hover:text-foreground",
3995
+ children: t.close
3996
+ }
3997
+ )
3998
+ ] })
3999
+ ] }) })
4000
+ ] });
4001
+ };
4002
+ var Checkbox = React4__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3241
4003
  CheckboxPrimitive__namespace.Root,
3242
4004
  {
3243
4005
  ref,
@@ -3264,9 +4026,9 @@ var initialState = {
3264
4026
  termsAccepted: false
3265
4027
  };
3266
4028
  var WalletDialog = ({ open, onOpenChange }) => {
3267
- const [form, setForm] = React15.useState(initialState);
3268
- const [errors, setErrors] = React15.useState({});
3269
- const validators = React15.useMemo(
4029
+ const [form, setForm] = React4.useState(initialState);
4030
+ const [errors, setErrors] = React4.useState({});
4031
+ const validators = React4.useMemo(
3270
4032
  () => ({
3271
4033
  nameOnCard: (value) => !value ? "Name is required" : void 0,
3272
4034
  cardNumber: (value) => /^\d{16}$/.test(value) ? void 0 : "Card number must be 16 digits",
@@ -3359,10 +4121,10 @@ var WalletDialog = ({ open, onOpenChange }) => {
3359
4121
  var useTokenBalance = (tokens) => {
3360
4122
  const { publicKey } = walletAdapterReact.useWallet();
3361
4123
  const { connection } = walletAdapterReact.useConnection();
3362
- const [balances, setBalances] = React15.useState([]);
3363
- const [isLoading, setIsLoading] = React15.useState(false);
3364
- const [error, setError] = React15.useState(null);
3365
- const fetchTokenBalance = React15.useCallback(
4124
+ const [balances, setBalances] = React4.useState([]);
4125
+ const [isLoading, setIsLoading] = React4.useState(false);
4126
+ const [error, setError] = React4.useState(null);
4127
+ const fetchTokenBalance = React4.useCallback(
3366
4128
  async (token, walletAddress) => {
3367
4129
  try {
3368
4130
  const mintPublicKey = new web3_js.PublicKey(token.mint);
@@ -3403,8 +4165,8 @@ var useTokenBalance = (tokens) => {
3403
4165
  },
3404
4166
  [connection]
3405
4167
  );
3406
- const tokensKey = React15.useMemo(() => tokens.map((t) => t.mint).join(","), [tokens]);
3407
- React15.useEffect(() => {
4168
+ const tokensKey = React4.useMemo(() => tokens.map((t) => t.mint).join(","), [tokens]);
4169
+ React4.useEffect(() => {
3408
4170
  if (!publicKey || tokens.length === 0) {
3409
4171
  setBalances([]);
3410
4172
  return;
@@ -3428,20 +4190,20 @@ var useTokenBalance = (tokens) => {
3428
4190
  };
3429
4191
  fetchAllBalances();
3430
4192
  }, [publicKey, tokensKey, fetchTokenBalance]);
3431
- const getTokenBalance = React15.useCallback(
4193
+ const getTokenBalance = React4.useCallback(
3432
4194
  (tokenSymbol) => {
3433
4195
  return balances.find((balance) => balance.token.symbol === tokenSymbol);
3434
4196
  },
3435
4197
  [balances]
3436
4198
  );
3437
- const hasSufficientBalance = React15.useCallback(
4199
+ const hasSufficientBalance = React4.useCallback(
3438
4200
  (tokenSymbol, requiredAmount) => {
3439
4201
  const balance = getTokenBalance(tokenSymbol);
3440
4202
  return balance ? balance.uiAmount >= requiredAmount : false;
3441
4203
  },
3442
4204
  [getTokenBalance]
3443
4205
  );
3444
- const getFormattedBalance = React15.useCallback(
4206
+ const getFormattedBalance = React4.useCallback(
3445
4207
  (tokenSymbol) => {
3446
4208
  const balance = getTokenBalance(tokenSymbol);
3447
4209
  if (!balance) return "0.00";
@@ -3455,7 +4217,7 @@ var useTokenBalance = (tokens) => {
3455
4217
  },
3456
4218
  [getTokenBalance]
3457
4219
  );
3458
- const refreshBalances = React15.useCallback(async () => {
4220
+ const refreshBalances = React4.useCallback(async () => {
3459
4221
  if (!publicKey || tokens.length === 0) {
3460
4222
  setBalances([]);
3461
4223
  return;
@@ -3476,7 +4238,7 @@ var useTokenBalance = (tokens) => {
3476
4238
  setIsLoading(false);
3477
4239
  }
3478
4240
  }, [publicKey, tokens, fetchTokenBalance]);
3479
- const getTotalValue = React15.useCallback(
4241
+ const getTotalValue = React4.useCallback(
3480
4242
  (priceData) => {
3481
4243
  if (!priceData) return 0;
3482
4244
  return balances.reduce((total, balance) => {
@@ -3515,21 +4277,21 @@ var usePaymentStatus = (options = {}) => {
3515
4277
  retryInterval = 1e4
3516
4278
  // 10 seconds
3517
4279
  } = options;
3518
- const [status, setStatus] = React15.useState(null);
3519
- const [paymentStatus, setPaymentStatus] = React15.useState(null);
3520
- const [isLoading, setIsLoading] = React15.useState(false);
3521
- const [error, setError] = React15.useState(null);
3522
- const [retryCount, setRetryCount] = React15.useState(0);
3523
- const intervalRef = React15.useRef(null);
3524
- const isMonitoringRef = React15.useRef(false);
3525
- React15.useEffect(() => {
4280
+ const [status, setStatus] = React4.useState(null);
4281
+ const [paymentStatus, setPaymentStatus] = React4.useState(null);
4282
+ const [isLoading, setIsLoading] = React4.useState(false);
4283
+ const [error, setError] = React4.useState(null);
4284
+ const [retryCount, setRetryCount] = React4.useState(0);
4285
+ const intervalRef = React4.useRef(null);
4286
+ const isMonitoringRef = React4.useRef(false);
4287
+ React4.useEffect(() => {
3526
4288
  return () => {
3527
4289
  if (intervalRef.current) {
3528
4290
  clearInterval(intervalRef.current);
3529
4291
  }
3530
4292
  };
3531
4293
  }, []);
3532
- const checkTransactionStatus = React15.useCallback(
4294
+ const checkTransactionStatus = React4.useCallback(
3533
4295
  async (signature) => {
3534
4296
  try {
3535
4297
  const statusResponse = await connection.getSignatureStatus(signature, {
@@ -3574,7 +4336,7 @@ var usePaymentStatus = (options = {}) => {
3574
4336
  },
3575
4337
  [connection]
3576
4338
  );
3577
- const checkPaymentStatus = React15.useCallback(
4339
+ const checkPaymentStatus = React4.useCallback(
3578
4340
  async (id) => {
3579
4341
  try {
3580
4342
  return await client.getPaymentStatus(id);
@@ -3588,7 +4350,7 @@ var usePaymentStatus = (options = {}) => {
3588
4350
  },
3589
4351
  [client]
3590
4352
  );
3591
- const startMonitoring = React15.useCallback(async () => {
4353
+ const startMonitoring = React4.useCallback(async () => {
3592
4354
  if (isMonitoringRef.current || !transactionId && !purchaseId) {
3593
4355
  return;
3594
4356
  }
@@ -3676,14 +4438,14 @@ var usePaymentStatus = (options = {}) => {
3676
4438
  retryInterval,
3677
4439
  retryCount
3678
4440
  ]);
3679
- const stopMonitoring = React15.useCallback(() => {
4441
+ const stopMonitoring = React4.useCallback(() => {
3680
4442
  if (intervalRef.current) {
3681
4443
  clearInterval(intervalRef.current);
3682
4444
  }
3683
4445
  isMonitoringRef.current = false;
3684
4446
  setIsLoading(false);
3685
4447
  }, []);
3686
- const checkStatus = React15.useCallback(async () => {
4448
+ const checkStatus = React4.useCallback(async () => {
3687
4449
  if (!transactionId && !purchaseId) return;
3688
4450
  setIsLoading(true);
3689
4451
  setError(null);
@@ -3708,7 +4470,7 @@ var usePaymentStatus = (options = {}) => {
3708
4470
  setIsLoading(false);
3709
4471
  }
3710
4472
  }, [transactionId, purchaseId, checkTransactionStatus, checkPaymentStatus]);
3711
- React15.useEffect(() => {
4473
+ React4.useEffect(() => {
3712
4474
  if ((transactionId || purchaseId) && !isMonitoringRef.current) {
3713
4475
  startMonitoring();
3714
4476
  }
@@ -3716,7 +4478,7 @@ var usePaymentStatus = (options = {}) => {
3716
4478
  stopMonitoring();
3717
4479
  };
3718
4480
  }, [transactionId, purchaseId, startMonitoring, stopMonitoring]);
3719
- const getConfirmationStatus = React15.useCallback(() => {
4481
+ const getConfirmationStatus = React4.useCallback(() => {
3720
4482
  if (paymentStatus?.status === "confirmed") return "confirmed";
3721
4483
  if (paymentStatus?.status === "failed") return "failed";
3722
4484
  if (status?.confirmationStatus === "finalized") return "confirmed";
@@ -3725,7 +4487,7 @@ var usePaymentStatus = (options = {}) => {
3725
4487
  return "failed";
3726
4488
  return "pending";
3727
4489
  }, [status, paymentStatus]);
3728
- const getSolscanUrl = React15.useCallback(
4490
+ const getSolscanUrl = React4.useCallback(
3729
4491
  (signature) => {
3730
4492
  const txId = signature || transactionId;
3731
4493
  if (!txId) return null;
@@ -3766,9 +4528,13 @@ exports.SolanaPaymentView = SolanaPaymentView;
3766
4528
  exports.StoredPaymentMethods = StoredPaymentMethods;
3767
4529
  exports.SubscriptionCheckoutModal = SubscriptionCheckoutModal;
3768
4530
  exports.SubscriptionSuccessDialog = SubscriptionSuccessDialog;
4531
+ exports.SubscriptionsSection = SubscriptionsSection;
3769
4532
  exports.WalletDialog = WalletDialog;
3770
4533
  exports.WalletModal = WalletModal;
3771
4534
  exports.createClient = createClient;
4535
+ exports.defaultCardDetailsFormTranslations = defaultCardDetailsFormTranslations;
4536
+ exports.defaultPaymentExperienceTranslations = defaultPaymentExperienceTranslations;
4537
+ exports.defaultTranslations = defaultTranslations3;
3772
4538
  exports.usePaymentContext = usePaymentContext;
3773
4539
  exports.usePaymentDialogs = usePaymentDialogs;
3774
4540
  exports.usePaymentMethods = usePaymentMethods;