@omnikit-js/ui 0.9.7 → 0.9.8

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.
@@ -1,9 +1,189 @@
1
1
  "use client";
2
- import { useState } from 'react';
3
- import { Card, Button, Tabs } from '@marcoschwartz/lite-ui';
2
+ import { useEffect, useState, useMemo } from 'react';
4
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+ import { loadStripe } from '@stripe/stripe-js';
5
+ import { Elements, useStripe, useElements, PaymentElement } from '@stripe/react-stripe-js';
6
+ import { Card, Button, Tabs } from '@marcoschwartz/lite-ui';
5
7
 
6
- // src/components/client/BillingContent/index.tsx
8
+ // src/components/client/Modal/index.tsx
9
+ function Modal({ isOpen, onClose, title, children, className = "" }) {
10
+ useEffect(() => {
11
+ const handleEscape = (e) => {
12
+ if (e.key === "Escape") onClose();
13
+ };
14
+ if (isOpen) {
15
+ document.addEventListener("keydown", handleEscape);
16
+ document.body.style.overflow = "hidden";
17
+ }
18
+ return () => {
19
+ document.removeEventListener("keydown", handleEscape);
20
+ document.body.style.overflow = "unset";
21
+ };
22
+ }, [isOpen, onClose]);
23
+ if (!isOpen) return null;
24
+ return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
25
+ /* @__PURE__ */ jsx(
26
+ "div",
27
+ {
28
+ className: "absolute inset-0 bg-black/50 backdrop-blur-sm",
29
+ onClick: onClose
30
+ }
31
+ ),
32
+ /* @__PURE__ */ jsxs(
33
+ "div",
34
+ {
35
+ className: `relative bg-white dark:bg-gray-900 rounded-lg shadow-xl max-w-md w-full max-h-[90vh] overflow-y-auto ${className}`,
36
+ children: [
37
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700", children: [
38
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold", children: title }),
39
+ /* @__PURE__ */ jsx(
40
+ "button",
41
+ {
42
+ onClick: onClose,
43
+ className: "text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors",
44
+ children: /* @__PURE__ */ jsx("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
45
+ }
46
+ )
47
+ ] }),
48
+ /* @__PURE__ */ jsx("div", { className: "p-6", children })
49
+ ]
50
+ }
51
+ )
52
+ ] });
53
+ }
54
+ function PaymentForm({ customerId, onSuccess, onCancel, onSubmit }) {
55
+ const stripe = useStripe();
56
+ const elements = useElements();
57
+ const [isProcessing, setIsProcessing] = useState(false);
58
+ const [errorMessage, setErrorMessage] = useState(null);
59
+ const [setAsDefault, setSetAsDefault] = useState(false);
60
+ const handleSubmit = async (e) => {
61
+ e.preventDefault();
62
+ if (!stripe || !elements) {
63
+ return;
64
+ }
65
+ setIsProcessing(true);
66
+ setErrorMessage(null);
67
+ try {
68
+ const { error: submitError } = await elements.submit();
69
+ if (submitError) {
70
+ setErrorMessage(submitError.message || "Failed to validate payment details");
71
+ setIsProcessing(false);
72
+ return;
73
+ }
74
+ const { error, paymentMethod } = await stripe.createPaymentMethod({
75
+ elements
76
+ });
77
+ if (error) {
78
+ setErrorMessage(error.message || "Failed to create payment method");
79
+ setIsProcessing(false);
80
+ return;
81
+ }
82
+ const result = await onSubmit(paymentMethod.id, setAsDefault);
83
+ if (!result.success) {
84
+ throw new Error(result.error || "Failed to add payment method");
85
+ }
86
+ onSuccess();
87
+ } catch (error) {
88
+ setErrorMessage(error instanceof Error ? error.message : String(error) || "An error occurred");
89
+ setIsProcessing(false);
90
+ }
91
+ };
92
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
93
+ /* @__PURE__ */ jsx(PaymentElement, {}),
94
+ errorMessage && /* @__PURE__ */ jsx("div", { className: "text-red-600 dark:text-red-400 text-sm", children: errorMessage }),
95
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-2", children: [
96
+ /* @__PURE__ */ jsx(
97
+ "input",
98
+ {
99
+ type: "checkbox",
100
+ id: "setDefault",
101
+ checked: setAsDefault,
102
+ onChange: (e) => setSetAsDefault(e.target.checked),
103
+ className: "w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
104
+ }
105
+ ),
106
+ /* @__PURE__ */ jsx(
107
+ "label",
108
+ {
109
+ htmlFor: "setDefault",
110
+ className: "text-sm text-gray-600 dark:text-gray-400",
111
+ children: "Set as default payment method"
112
+ }
113
+ )
114
+ ] }),
115
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
116
+ /* @__PURE__ */ jsx(
117
+ Button,
118
+ {
119
+ type: "button",
120
+ variant: "secondary",
121
+ onClick: onCancel,
122
+ disabled: isProcessing,
123
+ children: "Cancel"
124
+ }
125
+ ),
126
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: "primary", disabled: !stripe || isProcessing, children: isProcessing ? "Processing..." : "Add Payment Method" })
127
+ ] })
128
+ ] });
129
+ }
130
+ function AddPaymentMethodForm({
131
+ customerId,
132
+ stripePublishableKey,
133
+ onSuccess,
134
+ onCancel,
135
+ onSubmit
136
+ }) {
137
+ const [stripePromise, setStripePromise] = useState(null);
138
+ const [theme, setTheme] = useState("light");
139
+ useEffect(() => {
140
+ if (stripePublishableKey) {
141
+ setStripePromise(loadStripe(stripePublishableKey));
142
+ }
143
+ }, [stripePublishableKey]);
144
+ useEffect(() => {
145
+ const isDark = document.documentElement.classList.contains("dark") || window.matchMedia("(prefers-color-scheme: dark)").matches;
146
+ setTheme(isDark ? "dark" : "light");
147
+ const observer = new MutationObserver(() => {
148
+ const isDark2 = document.documentElement.classList.contains("dark");
149
+ setTheme(isDark2 ? "dark" : "light");
150
+ });
151
+ observer.observe(document.documentElement, {
152
+ attributes: true,
153
+ attributeFilter: ["class"]
154
+ });
155
+ return () => observer.disconnect();
156
+ }, []);
157
+ const stripeOptions = useMemo(() => ({
158
+ mode: "setup",
159
+ currency: "usd",
160
+ paymentMethodCreation: "manual",
161
+ appearance: {
162
+ theme: theme === "dark" ? "night" : "stripe",
163
+ variables: {
164
+ colorPrimary: "#3b82f6",
165
+ colorBackground: theme === "dark" ? "#1f2937" : "#ffffff",
166
+ colorText: theme === "dark" ? "#f9fafb" : "#1f2937",
167
+ colorDanger: "#ef4444",
168
+ fontFamily: "system-ui, -apple-system, sans-serif",
169
+ spacingUnit: "4px",
170
+ borderRadius: "6px"
171
+ }
172
+ }
173
+ }), [theme]);
174
+ if (!stripePromise) {
175
+ return /* @__PURE__ */ jsx("div", { className: "text-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: "Loading..." }) });
176
+ }
177
+ return /* @__PURE__ */ jsx(Elements, { stripe: stripePromise, options: stripeOptions, children: /* @__PURE__ */ jsx(
178
+ PaymentForm,
179
+ {
180
+ customerId,
181
+ onSuccess,
182
+ onCancel,
183
+ onSubmit
184
+ }
185
+ ) });
186
+ }
7
187
 
8
188
  // src/components/server/Billing/actions.ts
9
189
  function createHeaders(config) {
@@ -35,6 +215,26 @@ async function fetchAPI(config, url, options = {}) {
35
215
  };
36
216
  }
37
217
  }
218
+ async function addPaymentMethod(config, customerId, stripePaymentMethodId, setAsDefault = false) {
219
+ const { baseUrl, projectId } = config;
220
+ const result = await fetchAPI(
221
+ config,
222
+ `${baseUrl}/billing/customers/${customerId}/payment-methods`,
223
+ {
224
+ method: "POST",
225
+ body: JSON.stringify({
226
+ project_id: projectId,
227
+ type: "card",
228
+ stripe_payment_method_id: stripePaymentMethodId,
229
+ set_as_default: setAsDefault
230
+ })
231
+ }
232
+ );
233
+ if (!result.success) {
234
+ return { success: false, error: result.error || "Failed to add payment method" };
235
+ }
236
+ return { success: true, data: result.data };
237
+ }
38
238
  async function removePaymentMethod(config, customerId, paymentMethodId) {
39
239
  const { baseUrl, projectId } = config;
40
240
  const isStripeId = paymentMethodId.startsWith("pm_");
@@ -140,6 +340,17 @@ async function updateSubscription(config, subscriptionId, newPriceId) {
140
340
  }
141
341
  return { success: true, data: result.data };
142
342
  }
343
+ async function fetchPaymentConfig(config) {
344
+ const { baseUrl, projectId } = config;
345
+ const result = await fetchAPI(
346
+ config,
347
+ `${baseUrl}/billing/payment-config?project_id=${projectId}&test_mode=true`
348
+ );
349
+ if (!result.success) {
350
+ return { success: false, error: result.error || "Failed to fetch payment configuration" };
351
+ }
352
+ return { success: true, data: result.data };
353
+ }
143
354
  function UsageBar({ label, used, limit, unit = "" }) {
144
355
  const percentage = limit > 0 ? used / limit * 100 : 0;
145
356
  const isWarning = percentage > 80;
@@ -180,6 +391,28 @@ function BillingContent({
180
391
  const [isLoading, setIsLoading] = useState(false);
181
392
  const [error, setError] = useState(null);
182
393
  const [success, setSuccess] = useState(null);
394
+ const [isAddPaymentModalOpen, setIsAddPaymentModalOpen] = useState(false);
395
+ const [isRemovePaymentModalOpen, setIsRemovePaymentModalOpen] = useState(false);
396
+ const [isCancelModalOpen, setIsCancelModalOpen] = useState(false);
397
+ const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(null);
398
+ const [stripePublishableKey, setStripePublishableKey] = useState(null);
399
+ const [stripeLoading, setStripeLoading] = useState(false);
400
+ useEffect(() => {
401
+ async function loadStripeConfig() {
402
+ setStripeLoading(true);
403
+ try {
404
+ const result = await fetchPaymentConfig(actionConfig);
405
+ if (result.success && result.data?.publishable_key) {
406
+ setStripePublishableKey(result.data.publishable_key);
407
+ }
408
+ } catch (err) {
409
+ console.error("Failed to load Stripe config:", err);
410
+ } finally {
411
+ setStripeLoading(false);
412
+ }
413
+ }
414
+ loadStripeConfig();
415
+ }, [actionConfig]);
183
416
  const handleCancelSubscription = async () => {
184
417
  if (!subscription) return;
185
418
  setIsLoading(true);
@@ -189,6 +422,33 @@ function BillingContent({
189
422
  setError(result.error || "Failed to cancel subscription");
190
423
  } else {
191
424
  setSuccess("Subscription will be canceled at the end of the billing period");
425
+ setIsCancelModalOpen(false);
426
+ }
427
+ setIsLoading(false);
428
+ };
429
+ const handleAddPaymentMethod = async (stripePaymentMethodId, setAsDefault) => {
430
+ const result = await addPaymentMethod(actionConfig, customer.id, stripePaymentMethodId, setAsDefault);
431
+ return result;
432
+ };
433
+ const handleAddPaymentSuccess = () => {
434
+ setIsAddPaymentModalOpen(false);
435
+ setSuccess("Payment method added successfully");
436
+ };
437
+ const handleRemovePaymentClick = (pm) => {
438
+ setSelectedPaymentMethod(pm);
439
+ setIsRemovePaymentModalOpen(true);
440
+ };
441
+ const handleConfirmRemovePayment = async () => {
442
+ if (!selectedPaymentMethod) return;
443
+ setIsLoading(true);
444
+ setError(null);
445
+ const result = await removePaymentMethod(actionConfig, customer.id, String(selectedPaymentMethod.id));
446
+ if (!result.success) {
447
+ setError(result.error || "Failed to remove payment method");
448
+ } else {
449
+ setSuccess("Payment method removed");
450
+ setIsRemovePaymentModalOpen(false);
451
+ setSelectedPaymentMethod(null);
192
452
  }
193
453
  setIsLoading(false);
194
454
  };
@@ -213,17 +473,6 @@ function BillingContent({
213
473
  }
214
474
  setIsLoading(false);
215
475
  };
216
- const handleRemovePaymentMethod = async (pmId) => {
217
- setIsLoading(true);
218
- setError(null);
219
- const result = await removePaymentMethod(actionConfig, customer.id, String(pmId));
220
- if (!result.success) {
221
- setError(result.error || "Failed to remove payment method");
222
- } else {
223
- setSuccess("Payment method removed");
224
- }
225
- setIsLoading(false);
226
- };
227
476
  const handleSetDefaultPaymentMethod = async (pmId) => {
228
477
  setIsLoading(true);
229
478
  setError(null);
@@ -269,7 +518,7 @@ function BillingContent({
269
518
  Button,
270
519
  {
271
520
  variant: "secondary",
272
- onClick: handleCancelSubscription,
521
+ onClick: () => setIsCancelModalOpen(true),
273
522
  disabled: isLoading,
274
523
  children: "Cancel"
275
524
  }
@@ -413,7 +662,7 @@ function BillingContent({
413
662
  /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400 mb-6", children: "Manage your payment methods" }),
414
663
  paymentMethods.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8 border border-dashed border-gray-300 dark:border-neutral-700 rounded-lg", children: [
415
664
  /* @__PURE__ */ jsx("p", { className: "text-gray-500 dark:text-gray-400 mb-4", children: "No payment methods on file" }),
416
- /* @__PURE__ */ jsx(Button, { children: "Add Payment Method" })
665
+ /* @__PURE__ */ jsx(Button, { onClick: () => setIsAddPaymentModalOpen(true), disabled: stripeLoading, children: stripeLoading ? "Loading..." : "Add Payment Method" })
417
666
  ] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
418
667
  paymentMethods.map((pm) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 border border-gray-200 dark:border-neutral-700 rounded-lg", children: [
419
668
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
@@ -451,21 +700,145 @@ function BillingContent({
451
700
  {
452
701
  variant: "secondary",
453
702
  size: "sm",
454
- onClick: () => handleRemovePaymentMethod(pm.id),
703
+ onClick: () => handleRemovePaymentClick(pm),
455
704
  disabled: isLoading,
456
705
  children: "Remove"
457
706
  }
458
707
  )
459
708
  ] })
460
709
  ] }, pm.id)),
461
- /* @__PURE__ */ jsx(Button, { variant: "secondary", className: "w-full mt-4", children: "Add Payment Method" })
710
+ /* @__PURE__ */ jsx(
711
+ Button,
712
+ {
713
+ variant: "secondary",
714
+ className: "w-full mt-4",
715
+ onClick: () => setIsAddPaymentModalOpen(true),
716
+ disabled: stripeLoading,
717
+ children: stripeLoading ? "Loading..." : "Add Payment Method"
718
+ }
719
+ )
462
720
  ] })
463
721
  ] }) })
464
722
  }
465
723
  ];
466
- return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(Tabs, { tabs, defaultIndex: 0 }) });
724
+ return /* @__PURE__ */ jsxs("div", { className, children: [
725
+ /* @__PURE__ */ jsx(Tabs, { tabs, defaultIndex: 0 }),
726
+ /* @__PURE__ */ jsx(
727
+ Modal,
728
+ {
729
+ isOpen: isAddPaymentModalOpen,
730
+ onClose: () => setIsAddPaymentModalOpen(false),
731
+ title: "Add Payment Method",
732
+ children: stripePublishableKey ? /* @__PURE__ */ jsx(
733
+ AddPaymentMethodForm,
734
+ {
735
+ customerId: customer.id,
736
+ stripePublishableKey,
737
+ onSuccess: handleAddPaymentSuccess,
738
+ onCancel: () => setIsAddPaymentModalOpen(false),
739
+ onSubmit: handleAddPaymentMethod
740
+ }
741
+ ) : /* @__PURE__ */ jsx("div", { className: "text-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: stripeLoading ? "Loading payment form..." : "Payment configuration not available" }) })
742
+ }
743
+ ),
744
+ /* @__PURE__ */ jsx(
745
+ Modal,
746
+ {
747
+ isOpen: isRemovePaymentModalOpen,
748
+ onClose: () => {
749
+ setIsRemovePaymentModalOpen(false);
750
+ setSelectedPaymentMethod(null);
751
+ },
752
+ title: "Remove Payment Method",
753
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
754
+ /* @__PURE__ */ jsx("p", { className: "text-gray-600 dark:text-gray-400", children: "Are you sure you want to remove this payment method?" }),
755
+ selectedPaymentMethod && /* @__PURE__ */ jsx("div", { className: "bg-gray-50 dark:bg-gray-800 rounded-lg p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
756
+ /* @__PURE__ */ jsx("div", { className: "w-12 h-8 bg-gradient-to-br from-indigo-500 to-purple-600 rounded-lg flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx("svg", { className: "w-6 h-6 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" }) }) }),
757
+ /* @__PURE__ */ jsxs("div", { children: [
758
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-gray-900 dark:text-white", children: selectedPaymentMethod.card_brand || "Card" }),
759
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: [
760
+ "\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 ",
761
+ selectedPaymentMethod.card_last4 || "****"
762
+ ] })
763
+ ] })
764
+ ] }) }),
765
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: "This action cannot be undone." }),
766
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
767
+ /* @__PURE__ */ jsx(
768
+ Button,
769
+ {
770
+ variant: "secondary",
771
+ onClick: () => {
772
+ setIsRemovePaymentModalOpen(false);
773
+ setSelectedPaymentMethod(null);
774
+ },
775
+ disabled: isLoading,
776
+ children: "Cancel"
777
+ }
778
+ ),
779
+ /* @__PURE__ */ jsx(
780
+ Button,
781
+ {
782
+ variant: "primary",
783
+ onClick: handleConfirmRemovePayment,
784
+ disabled: isLoading,
785
+ children: isLoading ? "Removing..." : "Remove Payment Method"
786
+ }
787
+ )
788
+ ] })
789
+ ] })
790
+ }
791
+ ),
792
+ /* @__PURE__ */ jsx(
793
+ Modal,
794
+ {
795
+ isOpen: isCancelModalOpen,
796
+ onClose: () => setIsCancelModalOpen(false),
797
+ title: "Cancel Subscription",
798
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
799
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4", children: [
800
+ /* @__PURE__ */ jsx("svg", { className: "w-6 h-6 text-yellow-600 dark:text-yellow-400 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }),
801
+ /* @__PURE__ */ jsxs("div", { children: [
802
+ /* @__PURE__ */ jsx("p", { className: "font-medium text-yellow-900 dark:text-yellow-100 mb-1", children: "Are you sure you want to cancel?" }),
803
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-yellow-800 dark:text-yellow-200", children: "You'll lose access to premium features when your current billing period ends." })
804
+ ] })
805
+ ] }),
806
+ subscription && /* @__PURE__ */ jsxs("div", { className: "bg-gray-50 dark:bg-gray-800 rounded-lg p-4", children: [
807
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm", children: [
808
+ /* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Current Plan:" }),
809
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: subscription.plan })
810
+ ] }),
811
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm mt-2", children: [
812
+ /* @__PURE__ */ jsx("span", { className: "text-gray-600 dark:text-gray-400", children: "Access Until:" }),
813
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: subscription.nextBilling })
814
+ ] })
815
+ ] }),
816
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-end mt-6 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
817
+ /* @__PURE__ */ jsx(
818
+ Button,
819
+ {
820
+ variant: "secondary",
821
+ onClick: () => setIsCancelModalOpen(false),
822
+ disabled: isLoading,
823
+ children: "Keep Subscription"
824
+ }
825
+ ),
826
+ /* @__PURE__ */ jsx(
827
+ Button,
828
+ {
829
+ variant: "primary",
830
+ onClick: handleCancelSubscription,
831
+ disabled: isLoading,
832
+ children: isLoading ? "Canceling..." : "Yes, Cancel Subscription"
833
+ }
834
+ )
835
+ ] })
836
+ ] })
837
+ }
838
+ )
839
+ ] });
467
840
  }
468
841
 
469
- export { BillingContent };
470
- //# sourceMappingURL=chunk-IKBW2JFX.js.map
471
- //# sourceMappingURL=chunk-IKBW2JFX.js.map
842
+ export { AddPaymentMethodForm, BillingContent, Modal };
843
+ //# sourceMappingURL=chunk-2KDIPVL3.js.map
844
+ //# sourceMappingURL=chunk-2KDIPVL3.js.map