@stripe-sdk/core 1.0.0
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/README.md +700 -0
- package/dist/client/index.d.mts +198 -0
- package/dist/client/index.d.ts +198 -0
- package/dist/client/index.js +517 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/index.mjs +506 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/index-D8rM_YD4.d.mts +375 -0
- package/dist/index-D8rM_YD4.d.ts +375 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1800 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1708 -0
- package/dist/index.mjs.map +1 -0
- package/dist/next/index.d.mts +65 -0
- package/dist/next/index.d.ts +65 -0
- package/dist/next/index.js +450 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/index.mjs +443 -0
- package/dist/next/index.mjs.map +1 -0
- package/dist/server/index.d.mts +115 -0
- package/dist/server/index.d.ts +115 -0
- package/dist/server/index.js +1290 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +1208 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/server/webhooks/index.d.mts +2 -0
- package/dist/server/webhooks/index.d.ts +2 -0
- package/dist/server/webhooks/index.js +156 -0
- package/dist/server/webhooks/index.js.map +1 -0
- package/dist/server/webhooks/index.mjs +152 -0
- package/dist/server/webhooks/index.mjs.map +1 -0
- package/package.json +109 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var stripeJs = require('@stripe/stripe-js');
|
|
5
|
+
var reactStripeJs = require('@stripe/react-stripe-js');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
|
|
8
|
+
// src/client/providers/StripeProvider.tsx
|
|
9
|
+
var StripeContext = react.createContext(null);
|
|
10
|
+
function useStripeConfig() {
|
|
11
|
+
const context = react.useContext(StripeContext);
|
|
12
|
+
if (!context) {
|
|
13
|
+
throw new Error("useStripeConfig must be used within a <StripeProvider>");
|
|
14
|
+
}
|
|
15
|
+
return context;
|
|
16
|
+
}
|
|
17
|
+
function StripeProvider({
|
|
18
|
+
publishableKey,
|
|
19
|
+
children,
|
|
20
|
+
options,
|
|
21
|
+
locale
|
|
22
|
+
}) {
|
|
23
|
+
const stripePromise = react.useMemo(
|
|
24
|
+
() => stripeJs.loadStripe(publishableKey, locale ? { locale } : void 0),
|
|
25
|
+
[publishableKey, locale]
|
|
26
|
+
);
|
|
27
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StripeContext.Provider, { value: { publishableKey }, children: /* @__PURE__ */ jsxRuntime.jsx(reactStripeJs.Elements, { stripe: stripePromise, options, children }) });
|
|
28
|
+
}
|
|
29
|
+
function StripeElementsProvider({
|
|
30
|
+
publishableKey,
|
|
31
|
+
clientSecret,
|
|
32
|
+
children,
|
|
33
|
+
appearance,
|
|
34
|
+
locale,
|
|
35
|
+
loader = "auto"
|
|
36
|
+
}) {
|
|
37
|
+
const stripePromise = react.useMemo(
|
|
38
|
+
() => stripeJs.loadStripe(publishableKey, locale ? { locale } : void 0),
|
|
39
|
+
[publishableKey, locale]
|
|
40
|
+
);
|
|
41
|
+
const options = react.useMemo(
|
|
42
|
+
() => ({
|
|
43
|
+
clientSecret,
|
|
44
|
+
appearance,
|
|
45
|
+
loader
|
|
46
|
+
}),
|
|
47
|
+
[clientSecret, appearance, loader]
|
|
48
|
+
);
|
|
49
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StripeContext.Provider, { value: { publishableKey }, children: /* @__PURE__ */ jsxRuntime.jsx(reactStripeJs.Elements, { stripe: stripePromise, options, children }) });
|
|
50
|
+
}
|
|
51
|
+
function usePayment(options) {
|
|
52
|
+
const stripe = reactStripeJs.useStripe();
|
|
53
|
+
const elements = reactStripeJs.useElements();
|
|
54
|
+
const [state, setState] = react.useState({
|
|
55
|
+
isProcessing: false,
|
|
56
|
+
isSuccess: false,
|
|
57
|
+
error: null,
|
|
58
|
+
paymentIntentId: null
|
|
59
|
+
});
|
|
60
|
+
const processPayment = react.useCallback(async (overrides) => {
|
|
61
|
+
if (!stripe || !elements) {
|
|
62
|
+
setState((s) => ({ ...s, error: "Stripe not loaded yet" }));
|
|
63
|
+
return { success: false, error: "Stripe not loaded yet" };
|
|
64
|
+
}
|
|
65
|
+
setState({ isProcessing: true, isSuccess: false, error: null, paymentIntentId: null });
|
|
66
|
+
const { error, paymentIntent } = await stripe.confirmPayment({
|
|
67
|
+
elements,
|
|
68
|
+
confirmParams: {
|
|
69
|
+
return_url: overrides?.returnUrl ?? options?.returnUrl ?? (typeof window !== "undefined" ? window.location.href : "")
|
|
70
|
+
},
|
|
71
|
+
redirect: "if_required"
|
|
72
|
+
});
|
|
73
|
+
if (error) {
|
|
74
|
+
const message = error.message ?? "Payment failed";
|
|
75
|
+
setState({ isProcessing: false, isSuccess: false, error: message, paymentIntentId: null });
|
|
76
|
+
options?.onError?.(message);
|
|
77
|
+
return { success: false, error: message };
|
|
78
|
+
}
|
|
79
|
+
if (paymentIntent?.status === "succeeded") {
|
|
80
|
+
setState({ isProcessing: false, isSuccess: true, error: null, paymentIntentId: paymentIntent.id });
|
|
81
|
+
options?.onSuccess?.(paymentIntent.id);
|
|
82
|
+
return { success: true, paymentIntentId: paymentIntent.id };
|
|
83
|
+
}
|
|
84
|
+
setState({ isProcessing: false, isSuccess: false, error: null, paymentIntentId: paymentIntent?.id ?? null });
|
|
85
|
+
return { success: false, status: paymentIntent?.status };
|
|
86
|
+
}, [stripe, elements, options]);
|
|
87
|
+
const reset = react.useCallback(() => {
|
|
88
|
+
setState({ isProcessing: false, isSuccess: false, error: null, paymentIntentId: null });
|
|
89
|
+
}, []);
|
|
90
|
+
return {
|
|
91
|
+
...state,
|
|
92
|
+
processPayment,
|
|
93
|
+
reset,
|
|
94
|
+
isReady: !!stripe && !!elements
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function useSetupIntent(options) {
|
|
98
|
+
const stripe = reactStripeJs.useStripe();
|
|
99
|
+
const elements = reactStripeJs.useElements();
|
|
100
|
+
const [state, setState] = react.useState({
|
|
101
|
+
isProcessing: false,
|
|
102
|
+
isSuccess: false,
|
|
103
|
+
error: null,
|
|
104
|
+
setupIntentId: null,
|
|
105
|
+
paymentMethodId: null
|
|
106
|
+
});
|
|
107
|
+
const confirmSetup = react.useCallback(async (overrides) => {
|
|
108
|
+
if (!stripe || !elements) {
|
|
109
|
+
setState((s) => ({ ...s, error: "Stripe not loaded yet" }));
|
|
110
|
+
return { success: false, error: "Stripe not loaded yet" };
|
|
111
|
+
}
|
|
112
|
+
setState({ isProcessing: true, isSuccess: false, error: null, setupIntentId: null, paymentMethodId: null });
|
|
113
|
+
const { error, setupIntent } = await stripe.confirmSetup({
|
|
114
|
+
elements,
|
|
115
|
+
confirmParams: {
|
|
116
|
+
return_url: overrides?.returnUrl ?? options?.returnUrl ?? (typeof window !== "undefined" ? window.location.href : "")
|
|
117
|
+
},
|
|
118
|
+
redirect: "if_required"
|
|
119
|
+
});
|
|
120
|
+
if (error) {
|
|
121
|
+
const message = error.message ?? "Setup failed";
|
|
122
|
+
setState({ isProcessing: false, isSuccess: false, error: message, setupIntentId: null, paymentMethodId: null });
|
|
123
|
+
options?.onError?.(message);
|
|
124
|
+
return { success: false, error: message };
|
|
125
|
+
}
|
|
126
|
+
if (setupIntent?.status === "succeeded") {
|
|
127
|
+
const pmId = typeof setupIntent.payment_method === "string" ? setupIntent.payment_method : setupIntent.payment_method?.id ?? null;
|
|
128
|
+
setState({ isProcessing: false, isSuccess: true, error: null, setupIntentId: setupIntent.id, paymentMethodId: pmId });
|
|
129
|
+
if (pmId) options?.onSuccess?.(setupIntent.id, pmId);
|
|
130
|
+
return { success: true, setupIntentId: setupIntent.id, paymentMethodId: pmId };
|
|
131
|
+
}
|
|
132
|
+
setState({ isProcessing: false, isSuccess: false, error: null, setupIntentId: setupIntent?.id ?? null, paymentMethodId: null });
|
|
133
|
+
return { success: false, status: setupIntent?.status };
|
|
134
|
+
}, [stripe, elements, options]);
|
|
135
|
+
const reset = react.useCallback(() => {
|
|
136
|
+
setState({ isProcessing: false, isSuccess: false, error: null, setupIntentId: null, paymentMethodId: null });
|
|
137
|
+
}, []);
|
|
138
|
+
return {
|
|
139
|
+
...state,
|
|
140
|
+
confirmSetup,
|
|
141
|
+
reset,
|
|
142
|
+
isReady: !!stripe && !!elements
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function useCheckout(options) {
|
|
146
|
+
const [state, setState] = react.useState({
|
|
147
|
+
isLoading: false,
|
|
148
|
+
error: null
|
|
149
|
+
});
|
|
150
|
+
const redirectToCheckout = react.useCallback(async (sessionId) => {
|
|
151
|
+
setState({ isLoading: true, error: null });
|
|
152
|
+
try {
|
|
153
|
+
const stripe = await stripeJs.loadStripe(options.publishableKey);
|
|
154
|
+
if (!stripe) {
|
|
155
|
+
throw new Error("Failed to load Stripe");
|
|
156
|
+
}
|
|
157
|
+
const { error } = await stripe.redirectToCheckout({ sessionId });
|
|
158
|
+
if (error) {
|
|
159
|
+
const message = error.message ?? "Redirect to checkout failed";
|
|
160
|
+
setState({ isLoading: false, error: message });
|
|
161
|
+
options.onError?.(message);
|
|
162
|
+
return { success: false, error: message };
|
|
163
|
+
}
|
|
164
|
+
return { success: true };
|
|
165
|
+
} catch (err) {
|
|
166
|
+
const message = err instanceof Error ? err.message : "Unknown error";
|
|
167
|
+
setState({ isLoading: false, error: message });
|
|
168
|
+
options.onError?.(message);
|
|
169
|
+
return { success: false, error: message };
|
|
170
|
+
}
|
|
171
|
+
}, [options]);
|
|
172
|
+
const redirectToPortal = react.useCallback((portalUrl) => {
|
|
173
|
+
window.location.href = portalUrl;
|
|
174
|
+
}, []);
|
|
175
|
+
return {
|
|
176
|
+
...state,
|
|
177
|
+
redirectToCheckout,
|
|
178
|
+
redirectToPortal
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function CheckoutForm({
|
|
182
|
+
onSuccess,
|
|
183
|
+
onError,
|
|
184
|
+
returnUrl,
|
|
185
|
+
submitLabel = "Pay now",
|
|
186
|
+
showEmail = false,
|
|
187
|
+
className,
|
|
188
|
+
buttonClassName,
|
|
189
|
+
errorClassName,
|
|
190
|
+
children,
|
|
191
|
+
layout = "tabs"
|
|
192
|
+
}) {
|
|
193
|
+
const { processPayment, isProcessing, isSuccess, error, isReady } = usePayment({
|
|
194
|
+
onSuccess,
|
|
195
|
+
onError,
|
|
196
|
+
returnUrl
|
|
197
|
+
});
|
|
198
|
+
const handleSubmit = async (e) => {
|
|
199
|
+
e.preventDefault();
|
|
200
|
+
await processPayment();
|
|
201
|
+
};
|
|
202
|
+
if (isSuccess) {
|
|
203
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: children ?? /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Payment successful!" }) });
|
|
204
|
+
}
|
|
205
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className, children: [
|
|
206
|
+
showEmail && /* @__PURE__ */ jsxRuntime.jsx(reactStripeJs.LinkAuthenticationElement, {}),
|
|
207
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactStripeJs.PaymentElement, { options: { layout } }),
|
|
208
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: errorClassName, role: "alert", children: error }),
|
|
209
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
210
|
+
"button",
|
|
211
|
+
{
|
|
212
|
+
type: "submit",
|
|
213
|
+
disabled: !isReady || isProcessing,
|
|
214
|
+
className: buttonClassName,
|
|
215
|
+
children: isProcessing ? "Processing..." : submitLabel
|
|
216
|
+
}
|
|
217
|
+
)
|
|
218
|
+
] });
|
|
219
|
+
}
|
|
220
|
+
function SetupForm({
|
|
221
|
+
onSuccess,
|
|
222
|
+
onError,
|
|
223
|
+
returnUrl,
|
|
224
|
+
submitLabel = "Save payment method",
|
|
225
|
+
className,
|
|
226
|
+
buttonClassName,
|
|
227
|
+
errorClassName,
|
|
228
|
+
successContent,
|
|
229
|
+
layout = "tabs"
|
|
230
|
+
}) {
|
|
231
|
+
const { confirmSetup, isProcessing, isSuccess, error, isReady } = useSetupIntent({
|
|
232
|
+
onSuccess,
|
|
233
|
+
onError,
|
|
234
|
+
returnUrl
|
|
235
|
+
});
|
|
236
|
+
const handleSubmit = async (e) => {
|
|
237
|
+
e.preventDefault();
|
|
238
|
+
await confirmSetup();
|
|
239
|
+
};
|
|
240
|
+
if (isSuccess) {
|
|
241
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: successContent ?? /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Payment method saved!" }) });
|
|
242
|
+
}
|
|
243
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className, children: [
|
|
244
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactStripeJs.PaymentElement, { options: { layout } }),
|
|
245
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: errorClassName, role: "alert", children: error }),
|
|
246
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
247
|
+
"button",
|
|
248
|
+
{
|
|
249
|
+
type: "submit",
|
|
250
|
+
disabled: !isReady || isProcessing,
|
|
251
|
+
className: buttonClassName,
|
|
252
|
+
children: isProcessing ? "Saving..." : submitLabel
|
|
253
|
+
}
|
|
254
|
+
)
|
|
255
|
+
] });
|
|
256
|
+
}
|
|
257
|
+
function defaultFormatPrice(amount, currency) {
|
|
258
|
+
return new Intl.NumberFormat(void 0, {
|
|
259
|
+
style: "currency",
|
|
260
|
+
currency,
|
|
261
|
+
minimumFractionDigits: 0
|
|
262
|
+
}).format(amount / 100);
|
|
263
|
+
}
|
|
264
|
+
function PricingTable({
|
|
265
|
+
plans,
|
|
266
|
+
onSelectPlan,
|
|
267
|
+
isLoading,
|
|
268
|
+
currentPlanId,
|
|
269
|
+
buttonLabel = "Get started",
|
|
270
|
+
currentPlanLabel = "Current plan",
|
|
271
|
+
className,
|
|
272
|
+
planClassName,
|
|
273
|
+
highlightedClassName,
|
|
274
|
+
buttonClassName,
|
|
275
|
+
formatPrice = defaultFormatPrice,
|
|
276
|
+
renderFeature
|
|
277
|
+
}) {
|
|
278
|
+
const defaultStyles = {
|
|
279
|
+
container: {
|
|
280
|
+
display: "grid",
|
|
281
|
+
gridTemplateColumns: `repeat(${Math.min(plans.length, 4)}, 1fr)`,
|
|
282
|
+
gap: "1.5rem",
|
|
283
|
+
maxWidth: "1200px",
|
|
284
|
+
margin: "0 auto"
|
|
285
|
+
},
|
|
286
|
+
plan: {
|
|
287
|
+
border: "1px solid #e5e7eb",
|
|
288
|
+
borderRadius: "0.75rem",
|
|
289
|
+
padding: "2rem",
|
|
290
|
+
display: "flex",
|
|
291
|
+
flexDirection: "column"
|
|
292
|
+
},
|
|
293
|
+
highlighted: {
|
|
294
|
+
border: "2px solid #6366f1",
|
|
295
|
+
boxShadow: "0 4px 14px rgba(99,102,241,0.15)"
|
|
296
|
+
},
|
|
297
|
+
badge: {
|
|
298
|
+
background: "#6366f1",
|
|
299
|
+
color: "#fff",
|
|
300
|
+
padding: "0.25rem 0.75rem",
|
|
301
|
+
borderRadius: "9999px",
|
|
302
|
+
fontSize: "0.75rem",
|
|
303
|
+
fontWeight: 600,
|
|
304
|
+
alignSelf: "flex-start",
|
|
305
|
+
marginBottom: "0.5rem"
|
|
306
|
+
},
|
|
307
|
+
name: { fontSize: "1.25rem", fontWeight: 700, margin: "0 0 0.25rem" },
|
|
308
|
+
description: { color: "#6b7280", fontSize: "0.875rem", margin: "0 0 1rem" },
|
|
309
|
+
price: { fontSize: "2.5rem", fontWeight: 800, margin: "0" },
|
|
310
|
+
interval: { color: "#6b7280", fontSize: "0.875rem", fontWeight: 400 },
|
|
311
|
+
features: { listStyle: "none", padding: 0, margin: "1.5rem 0", flex: 1 },
|
|
312
|
+
feature: { padding: "0.375rem 0", fontSize: "0.875rem" },
|
|
313
|
+
button: {
|
|
314
|
+
padding: "0.75rem 1.5rem",
|
|
315
|
+
borderRadius: "0.5rem",
|
|
316
|
+
border: "none",
|
|
317
|
+
fontWeight: 600,
|
|
318
|
+
cursor: "pointer",
|
|
319
|
+
fontSize: "0.875rem",
|
|
320
|
+
background: "#6366f1",
|
|
321
|
+
color: "#fff",
|
|
322
|
+
width: "100%"
|
|
323
|
+
},
|
|
324
|
+
currentButton: {
|
|
325
|
+
background: "#e5e7eb",
|
|
326
|
+
color: "#374151",
|
|
327
|
+
cursor: "default"
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: !className ? defaultStyles.container : void 0, children: plans.map((plan) => {
|
|
331
|
+
const isCurrent = plan.id === currentPlanId;
|
|
332
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
333
|
+
"div",
|
|
334
|
+
{
|
|
335
|
+
className: plan.highlighted ? highlightedClassName : planClassName,
|
|
336
|
+
style: !planClassName ? { ...defaultStyles.plan, ...plan.highlighted ? defaultStyles.highlighted : {} } : void 0,
|
|
337
|
+
children: [
|
|
338
|
+
plan.badge && /* @__PURE__ */ jsxRuntime.jsx("span", { style: !highlightedClassName ? defaultStyles.badge : void 0, children: plan.badge }),
|
|
339
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { style: defaultStyles.name, children: plan.name }),
|
|
340
|
+
plan.description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: defaultStyles.description, children: plan.description }),
|
|
341
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { style: defaultStyles.price, children: [
|
|
342
|
+
formatPrice(plan.amount, plan.currency),
|
|
343
|
+
plan.interval && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: defaultStyles.interval, children: [
|
|
344
|
+
" / ",
|
|
345
|
+
plan.interval
|
|
346
|
+
] })
|
|
347
|
+
] }),
|
|
348
|
+
plan.trialDays && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { ...defaultStyles.description, marginTop: "0.5rem" }, children: [
|
|
349
|
+
plan.trialDays,
|
|
350
|
+
"-day free trial"
|
|
351
|
+
] }),
|
|
352
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { style: defaultStyles.features, children: plan.features.map((feature, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { style: defaultStyles.feature, children: renderFeature ? renderFeature(feature) : `\u2713 ${feature}` }, i)) }),
|
|
353
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
354
|
+
"button",
|
|
355
|
+
{
|
|
356
|
+
onClick: () => !isCurrent && onSelectPlan(plan),
|
|
357
|
+
disabled: isLoading || isCurrent,
|
|
358
|
+
className: buttonClassName,
|
|
359
|
+
style: !buttonClassName ? { ...defaultStyles.button, ...isCurrent ? defaultStyles.currentButton : {} } : void 0,
|
|
360
|
+
children: isCurrent ? currentPlanLabel : buttonLabel
|
|
361
|
+
}
|
|
362
|
+
)
|
|
363
|
+
]
|
|
364
|
+
},
|
|
365
|
+
plan.id
|
|
366
|
+
);
|
|
367
|
+
}) });
|
|
368
|
+
}
|
|
369
|
+
function defaultFormatPrice2(amount, currency) {
|
|
370
|
+
return new Intl.NumberFormat(void 0, {
|
|
371
|
+
style: "currency",
|
|
372
|
+
currency,
|
|
373
|
+
minimumFractionDigits: 0
|
|
374
|
+
}).format(amount / 100);
|
|
375
|
+
}
|
|
376
|
+
var statusColors = {
|
|
377
|
+
active: "#10b981",
|
|
378
|
+
trialing: "#6366f1",
|
|
379
|
+
past_due: "#f59e0b",
|
|
380
|
+
canceled: "#ef4444",
|
|
381
|
+
incomplete: "#f59e0b",
|
|
382
|
+
unpaid: "#ef4444",
|
|
383
|
+
paused: "#6b7280"
|
|
384
|
+
};
|
|
385
|
+
function SubscriptionManager({
|
|
386
|
+
subscription,
|
|
387
|
+
onCancel,
|
|
388
|
+
onResume,
|
|
389
|
+
onChangePlan,
|
|
390
|
+
onManageBilling,
|
|
391
|
+
className,
|
|
392
|
+
formatPrice = defaultFormatPrice2,
|
|
393
|
+
cancelLabel = "Cancel subscription",
|
|
394
|
+
resumeLabel = "Resume subscription",
|
|
395
|
+
changePlanLabel = "Change plan",
|
|
396
|
+
manageBillingLabel = "Manage billing"
|
|
397
|
+
}) {
|
|
398
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
399
|
+
const [showConfirm, setShowConfirm] = react.useState(false);
|
|
400
|
+
const endDate = new Date(subscription.currentPeriodEnd).toLocaleDateString();
|
|
401
|
+
const trialEndDate = subscription.trialEnd ? new Date(subscription.trialEnd).toLocaleDateString() : null;
|
|
402
|
+
const handleCancel = async () => {
|
|
403
|
+
setIsLoading(true);
|
|
404
|
+
try {
|
|
405
|
+
await onCancel(subscription.id);
|
|
406
|
+
} finally {
|
|
407
|
+
setIsLoading(false);
|
|
408
|
+
setShowConfirm(false);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
const handleResume = async () => {
|
|
412
|
+
if (!onResume) return;
|
|
413
|
+
setIsLoading(true);
|
|
414
|
+
try {
|
|
415
|
+
await onResume(subscription.id);
|
|
416
|
+
} finally {
|
|
417
|
+
setIsLoading(false);
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
const styles = {
|
|
421
|
+
container: { border: "1px solid #e5e7eb", borderRadius: "0.75rem", padding: "1.5rem" },
|
|
422
|
+
header: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "1rem" },
|
|
423
|
+
planName: { fontSize: "1.25rem", fontWeight: 700, margin: 0 },
|
|
424
|
+
status: {
|
|
425
|
+
padding: "0.25rem 0.75rem",
|
|
426
|
+
borderRadius: "9999px",
|
|
427
|
+
fontSize: "0.75rem",
|
|
428
|
+
fontWeight: 600,
|
|
429
|
+
color: "#fff",
|
|
430
|
+
background: statusColors[subscription.status] ?? "#6b7280"
|
|
431
|
+
},
|
|
432
|
+
price: { fontSize: "1.5rem", fontWeight: 700, margin: "0 0 0.5rem" },
|
|
433
|
+
detail: { color: "#6b7280", fontSize: "0.875rem", margin: "0.25rem 0" },
|
|
434
|
+
actions: { display: "flex", gap: "0.75rem", marginTop: "1.5rem", flexWrap: "wrap" },
|
|
435
|
+
button: {
|
|
436
|
+
padding: "0.5rem 1rem",
|
|
437
|
+
borderRadius: "0.375rem",
|
|
438
|
+
border: "1px solid #d1d5db",
|
|
439
|
+
background: "#fff",
|
|
440
|
+
cursor: "pointer",
|
|
441
|
+
fontSize: "0.875rem",
|
|
442
|
+
fontWeight: 500
|
|
443
|
+
},
|
|
444
|
+
dangerButton: {
|
|
445
|
+
padding: "0.5rem 1rem",
|
|
446
|
+
borderRadius: "0.375rem",
|
|
447
|
+
border: "1px solid #fca5a5",
|
|
448
|
+
background: "#fef2f2",
|
|
449
|
+
color: "#dc2626",
|
|
450
|
+
cursor: "pointer",
|
|
451
|
+
fontSize: "0.875rem",
|
|
452
|
+
fontWeight: 500
|
|
453
|
+
},
|
|
454
|
+
confirm: {
|
|
455
|
+
background: "#fef2f2",
|
|
456
|
+
border: "1px solid #fca5a5",
|
|
457
|
+
borderRadius: "0.5rem",
|
|
458
|
+
padding: "1rem",
|
|
459
|
+
marginTop: "1rem"
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: !className ? styles.container : void 0, children: [
|
|
463
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.header, children: [
|
|
464
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { style: styles.planName, children: subscription.planName }),
|
|
465
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.status, children: subscription.status })
|
|
466
|
+
] }),
|
|
467
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { style: styles.price, children: [
|
|
468
|
+
formatPrice(subscription.amount, subscription.currency),
|
|
469
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "0.875rem", fontWeight: 400, color: "#6b7280" }, children: [
|
|
470
|
+
" ",
|
|
471
|
+
"/ ",
|
|
472
|
+
subscription.interval
|
|
473
|
+
] })
|
|
474
|
+
] }),
|
|
475
|
+
trialEndDate && subscription.status === "trialing" && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: styles.detail, children: [
|
|
476
|
+
"Trial ends on ",
|
|
477
|
+
trialEndDate
|
|
478
|
+
] }),
|
|
479
|
+
subscription.cancelAtPeriodEnd ? /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { ...styles.detail, color: "#dc2626" }, children: [
|
|
480
|
+
"Cancels on ",
|
|
481
|
+
endDate
|
|
482
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("p", { style: styles.detail, children: [
|
|
483
|
+
"Renews on ",
|
|
484
|
+
endDate
|
|
485
|
+
] }),
|
|
486
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.actions, children: [
|
|
487
|
+
onChangePlan && subscription.status === "active" && /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => onChangePlan(subscription.id), style: styles.button, children: changePlanLabel }),
|
|
488
|
+
onManageBilling && /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: onManageBilling, style: styles.button, children: manageBillingLabel }),
|
|
489
|
+
subscription.cancelAtPeriodEnd && onResume ? /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleResume, disabled: isLoading, style: styles.button, children: isLoading ? "Loading..." : resumeLabel }) : subscription.status === "active" && /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setShowConfirm(true), style: styles.dangerButton, children: cancelLabel })
|
|
490
|
+
] }),
|
|
491
|
+
showConfirm && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.confirm, children: [
|
|
492
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0 0 0.75rem", fontWeight: 500 }, children: "Are you sure you want to cancel?" }),
|
|
493
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { style: { ...styles.detail, marginBottom: "0.75rem" }, children: [
|
|
494
|
+
"You will still have access until ",
|
|
495
|
+
endDate,
|
|
496
|
+
"."
|
|
497
|
+
] }),
|
|
498
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "0.5rem" }, children: [
|
|
499
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleCancel, disabled: isLoading, style: styles.dangerButton, children: isLoading ? "Cancelling..." : "Confirm cancellation" }),
|
|
500
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setShowConfirm(false), style: styles.button, children: "Keep subscription" })
|
|
501
|
+
] })
|
|
502
|
+
] })
|
|
503
|
+
] });
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
exports.CheckoutForm = CheckoutForm;
|
|
507
|
+
exports.PricingTable = PricingTable;
|
|
508
|
+
exports.SetupForm = SetupForm;
|
|
509
|
+
exports.StripeElementsProvider = StripeElementsProvider;
|
|
510
|
+
exports.StripeProvider = StripeProvider;
|
|
511
|
+
exports.SubscriptionManager = SubscriptionManager;
|
|
512
|
+
exports.useCheckout = useCheckout;
|
|
513
|
+
exports.usePayment = usePayment;
|
|
514
|
+
exports.useSetupIntent = useSetupIntent;
|
|
515
|
+
exports.useStripeConfig = useStripeConfig;
|
|
516
|
+
//# sourceMappingURL=index.js.map
|
|
517
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/providers/StripeProvider.tsx","../../src/client/hooks/usePayment.ts","../../src/client/hooks/useSetupIntent.ts","../../src/client/hooks/useCheckout.ts","../../src/client/components/CheckoutForm.tsx","../../src/client/components/SetupForm.tsx","../../src/client/components/PricingTable.tsx","../../src/client/components/SubscriptionManager.tsx"],"names":["createContext","useContext","useMemo","loadStripe","jsx","Elements","useStripe","useElements","useState","useCallback","jsxs","LinkAuthenticationElement","PaymentElement","defaultFormatPrice"],"mappings":"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","file":"index.js","sourcesContent":["'use client';\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport { loadStripe } from '@stripe/stripe-js';\nimport { Elements } from '@stripe/react-stripe-js';\nimport type { Stripe, StripeElementsOptions } from '@stripe/stripe-js';\nimport type { ReactNode } from 'react';\n\ninterface StripeContextValue {\n publishableKey: string;\n}\n\nconst StripeContext = createContext<StripeContextValue | null>(null);\n\nexport function useStripeConfig(): StripeContextValue {\n const context = useContext(StripeContext);\n if (!context) {\n throw new Error('useStripeConfig must be used within a <StripeProvider>');\n }\n return context;\n}\n\nexport interface StripeProviderProps {\n publishableKey: string;\n children: ReactNode;\n options?: StripeElementsOptions;\n locale?: string;\n}\n\nexport function StripeProvider({\n publishableKey,\n children,\n options,\n locale,\n}: StripeProviderProps) {\n const stripePromise = useMemo(\n () => loadStripe(publishableKey, locale ? { locale: locale as 'auto' } : undefined),\n [publishableKey, locale]\n );\n\n return (\n <StripeContext.Provider value={{ publishableKey }}>\n <Elements stripe={stripePromise} options={options}>\n {children}\n </Elements>\n </StripeContext.Provider>\n );\n}\n\n/**\n * Provider for embedding Stripe Elements with a client secret.\n * Use this to wrap payment forms after creating a PaymentIntent or SetupIntent.\n */\nexport interface StripeElementsProviderProps {\n publishableKey: string;\n clientSecret: string;\n children: ReactNode;\n appearance?: StripeElementsOptions['appearance'];\n locale?: string;\n loader?: 'auto' | 'always' | 'never';\n}\n\nexport function StripeElementsProvider({\n publishableKey,\n clientSecret,\n children,\n appearance,\n locale,\n loader = 'auto',\n}: StripeElementsProviderProps) {\n const stripePromise = useMemo(\n () => loadStripe(publishableKey, locale ? { locale: locale as 'auto' } : undefined),\n [publishableKey, locale]\n );\n\n const options: StripeElementsOptions = useMemo(\n () => ({\n clientSecret,\n appearance,\n loader,\n }),\n [clientSecret, appearance, loader]\n );\n\n return (\n <StripeContext.Provider value={{ publishableKey }}>\n <Elements stripe={stripePromise} options={options}>\n {children}\n </Elements>\n </StripeContext.Provider>\n );\n}\n","'use client';\n\nimport { useState, useCallback } from 'react';\nimport { useStripe, useElements } from '@stripe/react-stripe-js';\n\ninterface PaymentState {\n isProcessing: boolean;\n isSuccess: boolean;\n error: string | null;\n paymentIntentId: string | null;\n}\n\ninterface UsePaymentOptions {\n onSuccess?: (paymentIntentId: string) => void;\n onError?: (error: string) => void;\n returnUrl?: string;\n}\n\nexport function usePayment(options?: UsePaymentOptions) {\n const stripe = useStripe();\n const elements = useElements();\n\n const [state, setState] = useState<PaymentState>({\n isProcessing: false,\n isSuccess: false,\n error: null,\n paymentIntentId: null,\n });\n\n const processPayment = useCallback(async (\n overrides?: { returnUrl?: string }\n ) => {\n if (!stripe || !elements) {\n setState((s) => ({ ...s, error: 'Stripe not loaded yet' }));\n return { success: false, error: 'Stripe not loaded yet' };\n }\n\n setState({ isProcessing: true, isSuccess: false, error: null, paymentIntentId: null });\n\n const { error, paymentIntent } = await stripe.confirmPayment({\n elements,\n confirmParams: {\n return_url: overrides?.returnUrl ?? options?.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : ''),\n },\n redirect: 'if_required',\n });\n\n if (error) {\n const message = error.message ?? 'Payment failed';\n setState({ isProcessing: false, isSuccess: false, error: message, paymentIntentId: null });\n options?.onError?.(message);\n return { success: false, error: message };\n }\n\n if (paymentIntent?.status === 'succeeded') {\n setState({ isProcessing: false, isSuccess: true, error: null, paymentIntentId: paymentIntent.id });\n options?.onSuccess?.(paymentIntent.id);\n return { success: true, paymentIntentId: paymentIntent.id };\n }\n\n setState({ isProcessing: false, isSuccess: false, error: null, paymentIntentId: paymentIntent?.id ?? null });\n return { success: false, status: paymentIntent?.status };\n }, [stripe, elements, options]);\n\n const reset = useCallback(() => {\n setState({ isProcessing: false, isSuccess: false, error: null, paymentIntentId: null });\n }, []);\n\n return {\n ...state,\n processPayment,\n reset,\n isReady: !!stripe && !!elements,\n };\n}\n","'use client';\n\nimport { useState, useCallback } from 'react';\nimport { useStripe, useElements } from '@stripe/react-stripe-js';\n\ninterface SetupState {\n isProcessing: boolean;\n isSuccess: boolean;\n error: string | null;\n setupIntentId: string | null;\n paymentMethodId: string | null;\n}\n\ninterface UseSetupIntentOptions {\n onSuccess?: (setupIntentId: string, paymentMethodId: string) => void;\n onError?: (error: string) => void;\n returnUrl?: string;\n}\n\nexport function useSetupIntent(options?: UseSetupIntentOptions) {\n const stripe = useStripe();\n const elements = useElements();\n\n const [state, setState] = useState<SetupState>({\n isProcessing: false,\n isSuccess: false,\n error: null,\n setupIntentId: null,\n paymentMethodId: null,\n });\n\n const confirmSetup = useCallback(async (\n overrides?: { returnUrl?: string }\n ) => {\n if (!stripe || !elements) {\n setState((s) => ({ ...s, error: 'Stripe not loaded yet' }));\n return { success: false, error: 'Stripe not loaded yet' };\n }\n\n setState({ isProcessing: true, isSuccess: false, error: null, setupIntentId: null, paymentMethodId: null });\n\n const { error, setupIntent } = await stripe.confirmSetup({\n elements,\n confirmParams: {\n return_url: overrides?.returnUrl ?? options?.returnUrl ?? (typeof window !== 'undefined' ? window.location.href : ''),\n },\n redirect: 'if_required',\n });\n\n if (error) {\n const message = error.message ?? 'Setup failed';\n setState({ isProcessing: false, isSuccess: false, error: message, setupIntentId: null, paymentMethodId: null });\n options?.onError?.(message);\n return { success: false, error: message };\n }\n\n if (setupIntent?.status === 'succeeded') {\n const pmId = typeof setupIntent.payment_method === 'string'\n ? setupIntent.payment_method\n : setupIntent.payment_method?.id ?? null;\n setState({ isProcessing: false, isSuccess: true, error: null, setupIntentId: setupIntent.id, paymentMethodId: pmId });\n if (pmId) options?.onSuccess?.(setupIntent.id, pmId);\n return { success: true, setupIntentId: setupIntent.id, paymentMethodId: pmId };\n }\n\n setState({ isProcessing: false, isSuccess: false, error: null, setupIntentId: setupIntent?.id ?? null, paymentMethodId: null });\n return { success: false, status: setupIntent?.status };\n }, [stripe, elements, options]);\n\n const reset = useCallback(() => {\n setState({ isProcessing: false, isSuccess: false, error: null, setupIntentId: null, paymentMethodId: null });\n }, []);\n\n return {\n ...state,\n confirmSetup,\n reset,\n isReady: !!stripe && !!elements,\n };\n}\n","'use client';\n\nimport { useState, useCallback } from 'react';\nimport { loadStripe } from '@stripe/stripe-js';\n\ninterface CheckoutState {\n isLoading: boolean;\n error: string | null;\n}\n\ninterface UseCheckoutOptions {\n publishableKey: string;\n onError?: (error: string) => void;\n}\n\nexport function useCheckout(options: UseCheckoutOptions) {\n const [state, setState] = useState<CheckoutState>({\n isLoading: false,\n error: null,\n });\n\n /**\n * Redirect to a Stripe Checkout session.\n * Pass the sessionId returned from your server (createCheckoutSession).\n */\n const redirectToCheckout = useCallback(async (sessionId: string) => {\n setState({ isLoading: true, error: null });\n\n try {\n const stripe = await loadStripe(options.publishableKey);\n if (!stripe) {\n throw new Error('Failed to load Stripe');\n }\n\n const { error } = await stripe.redirectToCheckout({ sessionId });\n\n if (error) {\n const message = error.message ?? 'Redirect to checkout failed';\n setState({ isLoading: false, error: message });\n options.onError?.(message);\n return { success: false, error: message };\n }\n\n return { success: true };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Unknown error';\n setState({ isLoading: false, error: message });\n options.onError?.(message);\n return { success: false, error: message };\n }\n }, [options]);\n\n /**\n * Open a Stripe Customer Portal session.\n * Pass the portal URL returned from your server (createPortalSession).\n */\n const redirectToPortal = useCallback((portalUrl: string) => {\n window.location.href = portalUrl;\n }, []);\n\n return {\n ...state,\n redirectToCheckout,\n redirectToPortal,\n };\n}\n","'use client';\n\nimport React from 'react';\nimport { PaymentElement, LinkAuthenticationElement } from '@stripe/react-stripe-js';\nimport { usePayment } from '../hooks/usePayment';\nimport type { ReactNode, FormEvent } from 'react';\n\nexport interface CheckoutFormProps {\n onSuccess?: (paymentIntentId: string) => void;\n onError?: (error: string) => void;\n returnUrl?: string;\n submitLabel?: string;\n showEmail?: boolean;\n className?: string;\n buttonClassName?: string;\n errorClassName?: string;\n children?: ReactNode;\n layout?: 'tabs' | 'accordion' | 'auto';\n}\n\nexport function CheckoutForm({\n onSuccess,\n onError,\n returnUrl,\n submitLabel = 'Pay now',\n showEmail = false,\n className,\n buttonClassName,\n errorClassName,\n children,\n layout = 'tabs',\n}: CheckoutFormProps) {\n const { processPayment, isProcessing, isSuccess, error, isReady } = usePayment({\n onSuccess,\n onError,\n returnUrl,\n });\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n await processPayment();\n };\n\n if (isSuccess) {\n return (\n <div className={className}>\n {children ?? <p>Payment successful!</p>}\n </div>\n );\n }\n\n return (\n <form onSubmit={handleSubmit} className={className}>\n {showEmail && <LinkAuthenticationElement />}\n <PaymentElement options={{ layout }} />\n {error && <p className={errorClassName} role=\"alert\">{error}</p>}\n <button\n type=\"submit\"\n disabled={!isReady || isProcessing}\n className={buttonClassName}\n >\n {isProcessing ? 'Processing...' : submitLabel}\n </button>\n </form>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport { PaymentElement } from '@stripe/react-stripe-js';\nimport { useSetupIntent } from '../hooks/useSetupIntent';\nimport type { ReactNode, FormEvent } from 'react';\n\nexport interface SetupFormProps {\n onSuccess?: (setupIntentId: string, paymentMethodId: string) => void;\n onError?: (error: string) => void;\n returnUrl?: string;\n submitLabel?: string;\n className?: string;\n buttonClassName?: string;\n errorClassName?: string;\n successContent?: ReactNode;\n layout?: 'tabs' | 'accordion' | 'auto';\n}\n\nexport function SetupForm({\n onSuccess,\n onError,\n returnUrl,\n submitLabel = 'Save payment method',\n className,\n buttonClassName,\n errorClassName,\n successContent,\n layout = 'tabs',\n}: SetupFormProps) {\n const { confirmSetup, isProcessing, isSuccess, error, isReady } = useSetupIntent({\n onSuccess,\n onError,\n returnUrl,\n });\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n await confirmSetup();\n };\n\n if (isSuccess) {\n return (\n <div className={className}>\n {successContent ?? <p>Payment method saved!</p>}\n </div>\n );\n }\n\n return (\n <form onSubmit={handleSubmit} className={className}>\n <PaymentElement options={{ layout }} />\n {error && <p className={errorClassName} role=\"alert\">{error}</p>}\n <button\n type=\"submit\"\n disabled={!isReady || isProcessing}\n className={buttonClassName}\n >\n {isProcessing ? 'Saving...' : submitLabel}\n </button>\n </form>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport type { ReactNode, CSSProperties } from 'react';\n\nexport interface PricingPlan {\n id: string;\n name: string;\n description?: string;\n priceId: string;\n amount: number;\n currency: string;\n interval?: 'month' | 'year' | 'week' | 'day';\n features: string[];\n highlighted?: boolean;\n badge?: string;\n trialDays?: number;\n}\n\nexport interface PricingTableProps {\n plans: PricingPlan[];\n onSelectPlan: (plan: PricingPlan) => void;\n isLoading?: boolean;\n currentPlanId?: string;\n buttonLabel?: string;\n currentPlanLabel?: string;\n className?: string;\n planClassName?: string;\n highlightedClassName?: string;\n buttonClassName?: string;\n formatPrice?: (amount: number, currency: string) => string;\n renderFeature?: (feature: string) => ReactNode;\n}\n\nfunction defaultFormatPrice(amount: number, currency: string): string {\n return new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n minimumFractionDigits: 0,\n }).format(amount / 100);\n}\n\nexport function PricingTable({\n plans,\n onSelectPlan,\n isLoading,\n currentPlanId,\n buttonLabel = 'Get started',\n currentPlanLabel = 'Current plan',\n className,\n planClassName,\n highlightedClassName,\n buttonClassName,\n formatPrice = defaultFormatPrice,\n renderFeature,\n}: PricingTableProps) {\n const defaultStyles: Record<string, CSSProperties> = {\n container: {\n display: 'grid',\n gridTemplateColumns: `repeat(${Math.min(plans.length, 4)}, 1fr)`,\n gap: '1.5rem',\n maxWidth: '1200px',\n margin: '0 auto',\n },\n plan: {\n border: '1px solid #e5e7eb',\n borderRadius: '0.75rem',\n padding: '2rem',\n display: 'flex',\n flexDirection: 'column',\n },\n highlighted: {\n border: '2px solid #6366f1',\n boxShadow: '0 4px 14px rgba(99,102,241,0.15)',\n },\n badge: {\n background: '#6366f1',\n color: '#fff',\n padding: '0.25rem 0.75rem',\n borderRadius: '9999px',\n fontSize: '0.75rem',\n fontWeight: 600,\n alignSelf: 'flex-start',\n marginBottom: '0.5rem',\n },\n name: { fontSize: '1.25rem', fontWeight: 700, margin: '0 0 0.25rem' },\n description: { color: '#6b7280', fontSize: '0.875rem', margin: '0 0 1rem' },\n price: { fontSize: '2.5rem', fontWeight: 800, margin: '0' },\n interval: { color: '#6b7280', fontSize: '0.875rem', fontWeight: 400 },\n features: { listStyle: 'none', padding: 0, margin: '1.5rem 0', flex: 1 },\n feature: { padding: '0.375rem 0', fontSize: '0.875rem' },\n button: {\n padding: '0.75rem 1.5rem',\n borderRadius: '0.5rem',\n border: 'none',\n fontWeight: 600,\n cursor: 'pointer',\n fontSize: '0.875rem',\n background: '#6366f1',\n color: '#fff',\n width: '100%',\n },\n currentButton: {\n background: '#e5e7eb',\n color: '#374151',\n cursor: 'default',\n },\n };\n\n return (\n <div className={className} style={!className ? defaultStyles.container : undefined}>\n {plans.map((plan) => {\n const isCurrent = plan.id === currentPlanId;\n return (\n <div\n key={plan.id}\n className={plan.highlighted ? highlightedClassName : planClassName}\n style={\n !planClassName\n ? { ...defaultStyles.plan, ...(plan.highlighted ? defaultStyles.highlighted : {}) }\n : undefined\n }\n >\n {plan.badge && (\n <span style={!highlightedClassName ? defaultStyles.badge : undefined}>\n {plan.badge}\n </span>\n )}\n <h3 style={defaultStyles.name}>{plan.name}</h3>\n {plan.description && <p style={defaultStyles.description}>{plan.description}</p>}\n <p style={defaultStyles.price}>\n {formatPrice(plan.amount, plan.currency)}\n {plan.interval && (\n <span style={defaultStyles.interval}> / {plan.interval}</span>\n )}\n </p>\n {plan.trialDays && (\n <p style={{ ...defaultStyles.description, marginTop: '0.5rem' }}>\n {plan.trialDays}-day free trial\n </p>\n )}\n <ul style={defaultStyles.features}>\n {plan.features.map((feature, i) => (\n <li key={i} style={defaultStyles.feature}>\n {renderFeature ? renderFeature(feature) : `✓ ${feature}`}\n </li>\n ))}\n </ul>\n <button\n onClick={() => !isCurrent && onSelectPlan(plan)}\n disabled={isLoading || isCurrent}\n className={buttonClassName}\n style={\n !buttonClassName\n ? { ...defaultStyles.button, ...(isCurrent ? defaultStyles.currentButton : {}) }\n : undefined\n }\n >\n {isCurrent ? currentPlanLabel : buttonLabel}\n </button>\n </div>\n );\n })}\n </div>\n );\n}\n","'use client';\n\nimport React, { useState } from 'react';\nimport type { ReactNode, CSSProperties } from 'react';\n\nexport interface SubscriptionInfo {\n id: string;\n status: string;\n planName: string;\n amount: number;\n currency: string;\n interval: string;\n currentPeriodEnd: string | Date;\n cancelAtPeriodEnd: boolean;\n trialEnd?: string | Date | null;\n}\n\nexport interface SubscriptionManagerProps {\n subscription: SubscriptionInfo;\n onCancel: (subscriptionId: string) => Promise<void>;\n onResume?: (subscriptionId: string) => Promise<void>;\n onChangePlan?: (subscriptionId: string) => void;\n onManageBilling?: () => void;\n className?: string;\n formatPrice?: (amount: number, currency: string) => string;\n cancelLabel?: string;\n resumeLabel?: string;\n changePlanLabel?: string;\n manageBillingLabel?: string;\n children?: ReactNode;\n}\n\nfunction defaultFormatPrice(amount: number, currency: string): string {\n return new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n minimumFractionDigits: 0,\n }).format(amount / 100);\n}\n\nconst statusColors: Record<string, string> = {\n active: '#10b981',\n trialing: '#6366f1',\n past_due: '#f59e0b',\n canceled: '#ef4444',\n incomplete: '#f59e0b',\n unpaid: '#ef4444',\n paused: '#6b7280',\n};\n\nexport function SubscriptionManager({\n subscription,\n onCancel,\n onResume,\n onChangePlan,\n onManageBilling,\n className,\n formatPrice = defaultFormatPrice,\n cancelLabel = 'Cancel subscription',\n resumeLabel = 'Resume subscription',\n changePlanLabel = 'Change plan',\n manageBillingLabel = 'Manage billing',\n}: SubscriptionManagerProps) {\n const [isLoading, setIsLoading] = useState(false);\n const [showConfirm, setShowConfirm] = useState(false);\n\n const endDate = new Date(subscription.currentPeriodEnd).toLocaleDateString();\n const trialEndDate = subscription.trialEnd\n ? new Date(subscription.trialEnd).toLocaleDateString()\n : null;\n\n const handleCancel = async () => {\n setIsLoading(true);\n try {\n await onCancel(subscription.id);\n } finally {\n setIsLoading(false);\n setShowConfirm(false);\n }\n };\n\n const handleResume = async () => {\n if (!onResume) return;\n setIsLoading(true);\n try {\n await onResume(subscription.id);\n } finally {\n setIsLoading(false);\n }\n };\n\n const styles: Record<string, CSSProperties> = {\n container: { border: '1px solid #e5e7eb', borderRadius: '0.75rem', padding: '1.5rem' },\n header: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem' },\n planName: { fontSize: '1.25rem', fontWeight: 700, margin: 0 },\n status: {\n padding: '0.25rem 0.75rem',\n borderRadius: '9999px',\n fontSize: '0.75rem',\n fontWeight: 600,\n color: '#fff',\n background: statusColors[subscription.status] ?? '#6b7280',\n },\n price: { fontSize: '1.5rem', fontWeight: 700, margin: '0 0 0.5rem' },\n detail: { color: '#6b7280', fontSize: '0.875rem', margin: '0.25rem 0' },\n actions: { display: 'flex', gap: '0.75rem', marginTop: '1.5rem', flexWrap: 'wrap' as const },\n button: {\n padding: '0.5rem 1rem',\n borderRadius: '0.375rem',\n border: '1px solid #d1d5db',\n background: '#fff',\n cursor: 'pointer',\n fontSize: '0.875rem',\n fontWeight: 500,\n },\n dangerButton: {\n padding: '0.5rem 1rem',\n borderRadius: '0.375rem',\n border: '1px solid #fca5a5',\n background: '#fef2f2',\n color: '#dc2626',\n cursor: 'pointer',\n fontSize: '0.875rem',\n fontWeight: 500,\n },\n confirm: {\n background: '#fef2f2',\n border: '1px solid #fca5a5',\n borderRadius: '0.5rem',\n padding: '1rem',\n marginTop: '1rem',\n },\n };\n\n return (\n <div className={className} style={!className ? styles.container : undefined}>\n <div style={styles.header}>\n <h3 style={styles.planName}>{subscription.planName}</h3>\n <span style={styles.status}>{subscription.status}</span>\n </div>\n\n <p style={styles.price}>\n {formatPrice(subscription.amount, subscription.currency)}\n <span style={{ fontSize: '0.875rem', fontWeight: 400, color: '#6b7280' }}>\n {' '}/ {subscription.interval}\n </span>\n </p>\n\n {trialEndDate && subscription.status === 'trialing' && (\n <p style={styles.detail}>Trial ends on {trialEndDate}</p>\n )}\n\n {subscription.cancelAtPeriodEnd ? (\n <p style={{ ...styles.detail, color: '#dc2626' }}>\n Cancels on {endDate}\n </p>\n ) : (\n <p style={styles.detail}>Renews on {endDate}</p>\n )}\n\n <div style={styles.actions}>\n {onChangePlan && subscription.status === 'active' && (\n <button onClick={() => onChangePlan(subscription.id)} style={styles.button}>\n {changePlanLabel}\n </button>\n )}\n\n {onManageBilling && (\n <button onClick={onManageBilling} style={styles.button}>\n {manageBillingLabel}\n </button>\n )}\n\n {subscription.cancelAtPeriodEnd && onResume ? (\n <button onClick={handleResume} disabled={isLoading} style={styles.button}>\n {isLoading ? 'Loading...' : resumeLabel}\n </button>\n ) : (\n subscription.status === 'active' && (\n <button onClick={() => setShowConfirm(true)} style={styles.dangerButton}>\n {cancelLabel}\n </button>\n )\n )}\n </div>\n\n {showConfirm && (\n <div style={styles.confirm}>\n <p style={{ margin: '0 0 0.75rem', fontWeight: 500 }}>\n Are you sure you want to cancel?\n </p>\n <p style={{ ...styles.detail, marginBottom: '0.75rem' }}>\n You will still have access until {endDate}.\n </p>\n <div style={{ display: 'flex', gap: '0.5rem' }}>\n <button onClick={handleCancel} disabled={isLoading} style={styles.dangerButton}>\n {isLoading ? 'Cancelling...' : 'Confirm cancellation'}\n </button>\n <button onClick={() => setShowConfirm(false)} style={styles.button}>\n Keep subscription\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
|