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