@solvapay/react 1.0.0-preview.1 → 1.0.0-preview.11
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 +294 -14
- package/dist/adapters/auth.cjs +49 -0
- package/dist/adapters/auth.d.cts +44 -0
- package/dist/adapters/auth.d.ts +44 -0
- package/dist/adapters/auth.js +6 -0
- package/dist/chunk-OUSEQRCT.js +25 -0
- package/dist/index.cjs +1151 -174
- package/dist/index.d.cts +672 -53
- package/dist/index.d.ts +672 -53
- package/dist/index.js +1116 -175
- package/package.json +21 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,84 +1,703 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Stripe } from '@stripe/stripe-js';
|
|
1
|
+
import React$1 from 'react';
|
|
2
|
+
import { PaymentIntent, Stripe } from '@stripe/stripe-js';
|
|
3
|
+
import { ProcessPaymentResult } from '@solvapay/server';
|
|
4
|
+
import { AuthAdapter } from './adapters/auth.cjs';
|
|
5
|
+
export { defaultAuthAdapter } from './adapters/auth.cjs';
|
|
3
6
|
|
|
7
|
+
/**
|
|
8
|
+
* TypeScript type definitions for @solvapay/react
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
interface SubscriptionInfo {
|
|
12
|
+
reference: string;
|
|
13
|
+
planName: string;
|
|
14
|
+
agentName: string;
|
|
15
|
+
status: string;
|
|
16
|
+
startDate: string;
|
|
17
|
+
endDate?: string;
|
|
18
|
+
cancelledAt?: string;
|
|
19
|
+
cancellationReason?: string;
|
|
20
|
+
amount?: number;
|
|
21
|
+
}
|
|
22
|
+
interface CustomerSubscriptionData {
|
|
23
|
+
customerRef?: string;
|
|
24
|
+
email?: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
subscriptions: SubscriptionInfo[];
|
|
27
|
+
}
|
|
28
|
+
interface PaymentIntentResult {
|
|
29
|
+
clientSecret: string;
|
|
30
|
+
publishableKey: string;
|
|
31
|
+
accountId?: string;
|
|
32
|
+
customerRef?: string;
|
|
33
|
+
}
|
|
34
|
+
interface SubscriptionStatus {
|
|
35
|
+
loading: boolean;
|
|
36
|
+
customerRef?: string;
|
|
37
|
+
email?: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
subscriptions: SubscriptionInfo[];
|
|
40
|
+
hasPlan: (planName: string) => boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Primary active subscription (paid or free) - most recent subscription with status === 'active'
|
|
43
|
+
* Backend keeps subscriptions as 'active' until expiration, even when cancelled.
|
|
44
|
+
* null if no active subscription exists
|
|
45
|
+
*/
|
|
46
|
+
activeSubscription: SubscriptionInfo | null;
|
|
47
|
+
/**
|
|
48
|
+
* Check if user has any active paid subscription (amount > 0)
|
|
49
|
+
* Checks subscriptions with status === 'active'.
|
|
50
|
+
* Backend keeps subscriptions as 'active' until expiration, even when cancelled.
|
|
51
|
+
*/
|
|
52
|
+
hasPaidSubscription: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Most recent active paid subscription (sorted by startDate)
|
|
55
|
+
* Returns subscription with status === 'active' and amount > 0.
|
|
56
|
+
* null if no active paid subscription exists
|
|
57
|
+
*/
|
|
58
|
+
activePaidSubscription: SubscriptionInfo | null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* SolvaPay Provider Configuration
|
|
62
|
+
* Sensible defaults for minimal code, but fully customizable
|
|
63
|
+
*/
|
|
64
|
+
interface SolvaPayConfig {
|
|
65
|
+
/**
|
|
66
|
+
* API route configuration
|
|
67
|
+
* Defaults to standard Next.js API routes
|
|
68
|
+
*/
|
|
69
|
+
api?: {
|
|
70
|
+
checkSubscription?: string;
|
|
71
|
+
createPayment?: string;
|
|
72
|
+
processPayment?: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Authentication configuration
|
|
76
|
+
* Uses adapter pattern for flexible auth provider support
|
|
77
|
+
*/
|
|
78
|
+
auth?: {
|
|
79
|
+
/**
|
|
80
|
+
* Auth adapter instance
|
|
81
|
+
* Default: checks localStorage for 'auth_token' key
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```tsx
|
|
85
|
+
* import { createSupabaseAuthAdapter } from '@solvapay/react-supabase';
|
|
86
|
+
*
|
|
87
|
+
* <SolvaPayProvider
|
|
88
|
+
* config={{
|
|
89
|
+
* auth: {
|
|
90
|
+
* adapter: createSupabaseAuthAdapter({
|
|
91
|
+
* supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
92
|
+
* supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
93
|
+
* })
|
|
94
|
+
* }
|
|
95
|
+
* }}
|
|
96
|
+
* >
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
adapter?: AuthAdapter;
|
|
100
|
+
/**
|
|
101
|
+
* @deprecated Use `adapter` instead. Will be removed in a future version.
|
|
102
|
+
* Function to get auth token
|
|
103
|
+
*/
|
|
104
|
+
getToken?: () => Promise<string | null>;
|
|
105
|
+
/**
|
|
106
|
+
* @deprecated Use `adapter` instead. Will be removed in a future version.
|
|
107
|
+
* Function to get user ID (for cache key)
|
|
108
|
+
*/
|
|
109
|
+
getUserId?: () => Promise<string | null>;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Custom fetch implementation
|
|
113
|
+
* Default: uses global fetch
|
|
114
|
+
*/
|
|
115
|
+
fetch?: typeof fetch;
|
|
116
|
+
/**
|
|
117
|
+
* Request headers to include in all API calls
|
|
118
|
+
* Default: empty
|
|
119
|
+
*/
|
|
120
|
+
headers?: HeadersInit | (() => Promise<HeadersInit>);
|
|
121
|
+
/**
|
|
122
|
+
* Custom error handler
|
|
123
|
+
* Default: logs to console
|
|
124
|
+
*/
|
|
125
|
+
onError?: (error: Error, context: string) => void;
|
|
126
|
+
}
|
|
127
|
+
interface SolvaPayContextValue {
|
|
128
|
+
subscription: SubscriptionStatus;
|
|
129
|
+
refetchSubscription: () => Promise<void>;
|
|
130
|
+
createPayment: (params: {
|
|
131
|
+
planRef: string;
|
|
132
|
+
agentRef?: string;
|
|
133
|
+
}) => Promise<PaymentIntentResult>;
|
|
134
|
+
processPayment?: (params: {
|
|
135
|
+
paymentIntentId: string;
|
|
136
|
+
agentRef: string;
|
|
137
|
+
planRef?: string;
|
|
138
|
+
}) => Promise<ProcessPaymentResult>;
|
|
139
|
+
customerRef?: string;
|
|
140
|
+
updateCustomerRef?: (newCustomerRef: string) => void;
|
|
141
|
+
}
|
|
4
142
|
interface SolvaPayProviderProps {
|
|
143
|
+
/**
|
|
144
|
+
* Configuration object with sensible defaults
|
|
145
|
+
* If not provided, uses standard Next.js API routes
|
|
146
|
+
*/
|
|
147
|
+
config?: SolvaPayConfig;
|
|
148
|
+
/**
|
|
149
|
+
* Custom API functions (override config defaults)
|
|
150
|
+
* Use only if you need custom logic beyond standard API routes
|
|
151
|
+
*/
|
|
152
|
+
createPayment?: (params: {
|
|
153
|
+
planRef: string;
|
|
154
|
+
agentRef?: string;
|
|
155
|
+
}) => Promise<PaymentIntentResult>;
|
|
156
|
+
checkSubscription?: () => Promise<CustomerSubscriptionData>;
|
|
157
|
+
processPayment?: (params: {
|
|
158
|
+
paymentIntentId: string;
|
|
159
|
+
agentRef: string;
|
|
160
|
+
planRef?: string;
|
|
161
|
+
}) => Promise<ProcessPaymentResult>;
|
|
5
162
|
children: React.ReactNode;
|
|
6
|
-
|
|
163
|
+
}
|
|
164
|
+
interface PlanBadgeProps {
|
|
165
|
+
children?: (props: {
|
|
166
|
+
subscriptions: SubscriptionInfo[];
|
|
167
|
+
loading: boolean;
|
|
168
|
+
displayPlan: string | null;
|
|
169
|
+
shouldShow: boolean;
|
|
170
|
+
}) => React.ReactNode;
|
|
171
|
+
as?: React.ElementType;
|
|
172
|
+
className?: string | ((props: {
|
|
173
|
+
subscriptions: SubscriptionInfo[];
|
|
174
|
+
}) => string);
|
|
175
|
+
}
|
|
176
|
+
interface SubscriptionGateProps {
|
|
177
|
+
requirePlan?: string;
|
|
178
|
+
children: (props: {
|
|
179
|
+
hasAccess: boolean;
|
|
180
|
+
subscriptions: SubscriptionInfo[];
|
|
181
|
+
loading: boolean;
|
|
182
|
+
}) => React.ReactNode;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Error type for payment operations
|
|
186
|
+
*/
|
|
187
|
+
interface PaymentError extends Error {
|
|
188
|
+
code?: string;
|
|
189
|
+
type?: string;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Plan interface for subscription plans
|
|
193
|
+
*/
|
|
194
|
+
interface Plan {
|
|
195
|
+
reference: string;
|
|
196
|
+
name: string;
|
|
197
|
+
description?: string;
|
|
198
|
+
price?: number;
|
|
7
199
|
currency?: string;
|
|
200
|
+
interval?: string;
|
|
201
|
+
features?: string[];
|
|
202
|
+
isFreeTier?: boolean;
|
|
203
|
+
metadata?: Record<string, any>;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Options for usePlans hook
|
|
207
|
+
*/
|
|
208
|
+
interface UsePlansOptions {
|
|
209
|
+
/**
|
|
210
|
+
* Fetcher function to retrieve plans
|
|
211
|
+
*/
|
|
212
|
+
fetcher: (agentRef: string) => Promise<Plan[]>;
|
|
213
|
+
/**
|
|
214
|
+
* Agent reference to fetch plans for
|
|
215
|
+
*/
|
|
216
|
+
agentRef?: string;
|
|
217
|
+
/**
|
|
218
|
+
* Optional filter function to filter plans
|
|
219
|
+
*/
|
|
220
|
+
filter?: (plan: Plan) => boolean;
|
|
221
|
+
/**
|
|
222
|
+
* Optional sort function to sort plans
|
|
223
|
+
*/
|
|
224
|
+
sortBy?: (a: Plan, b: Plan) => number;
|
|
225
|
+
/**
|
|
226
|
+
* Auto-select first paid plan on load
|
|
227
|
+
*/
|
|
228
|
+
autoSelectFirstPaid?: boolean;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Return type for usePlans hook
|
|
232
|
+
*/
|
|
233
|
+
interface UsePlansReturn {
|
|
234
|
+
plans: Plan[];
|
|
235
|
+
loading: boolean;
|
|
236
|
+
error: Error | null;
|
|
237
|
+
selectedPlanIndex: number;
|
|
238
|
+
selectedPlan: Plan | null;
|
|
239
|
+
setSelectedPlanIndex: (index: number) => void;
|
|
240
|
+
selectPlan: (planRef: string) => void;
|
|
241
|
+
refetch: () => Promise<void>;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Props for headless PlanSelector component
|
|
245
|
+
*/
|
|
246
|
+
interface PlanSelectorProps {
|
|
247
|
+
/**
|
|
248
|
+
* Agent reference to fetch plans for
|
|
249
|
+
*/
|
|
250
|
+
agentRef?: string;
|
|
251
|
+
/**
|
|
252
|
+
* Fetcher function to retrieve plans
|
|
253
|
+
*/
|
|
254
|
+
fetcher: (agentRef: string) => Promise<Plan[]>;
|
|
255
|
+
/**
|
|
256
|
+
* Optional filter function
|
|
257
|
+
*/
|
|
258
|
+
filter?: (plan: Plan) => boolean;
|
|
259
|
+
/**
|
|
260
|
+
* Optional sort function
|
|
261
|
+
*/
|
|
262
|
+
sortBy?: (a: Plan, b: Plan) => number;
|
|
263
|
+
/**
|
|
264
|
+
* Auto-select first paid plan on load
|
|
265
|
+
*/
|
|
266
|
+
autoSelectFirstPaid?: boolean;
|
|
267
|
+
/**
|
|
268
|
+
* Render prop function
|
|
269
|
+
*/
|
|
270
|
+
children: (props: UsePlansReturn & {
|
|
271
|
+
subscriptions: SubscriptionInfo[];
|
|
272
|
+
isPaidPlan: (planName: string) => boolean;
|
|
273
|
+
isCurrentPlan: (planName: string) => boolean;
|
|
274
|
+
}) => React.ReactNode;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Return type for useSubscriptionStatus hook
|
|
278
|
+
*
|
|
279
|
+
* Provides advanced subscription status helpers and utilities.
|
|
280
|
+
* Focuses on cancelled subscription logic and date formatting.
|
|
281
|
+
* For basic subscription data and paid status, use useSubscription() instead.
|
|
282
|
+
*/
|
|
283
|
+
interface SubscriptionStatusReturn {
|
|
284
|
+
/**
|
|
285
|
+
* Most recent cancelled paid subscription (sorted by startDate)
|
|
286
|
+
* null if no cancelled paid subscription exists
|
|
287
|
+
*/
|
|
288
|
+
cancelledSubscription: SubscriptionInfo | null;
|
|
289
|
+
/**
|
|
290
|
+
* Whether to show cancelled subscription notice
|
|
291
|
+
* true if cancelledSubscription exists
|
|
292
|
+
*/
|
|
293
|
+
shouldShowCancelledNotice: boolean;
|
|
294
|
+
/**
|
|
295
|
+
* Format a date string to locale format (e.g., "January 15, 2024")
|
|
296
|
+
* Returns null if dateString is not provided
|
|
297
|
+
*/
|
|
298
|
+
formatDate: (dateString?: string) => string | null;
|
|
299
|
+
/**
|
|
300
|
+
* Calculate days until expiration date
|
|
301
|
+
* Returns null if endDate is not provided, otherwise returns days (0 or positive)
|
|
302
|
+
*/
|
|
303
|
+
getDaysUntilExpiration: (endDate?: string) => number | null;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Payment form props - simplified and minimal
|
|
307
|
+
*/
|
|
308
|
+
interface PaymentFormProps {
|
|
309
|
+
/**
|
|
310
|
+
* Plan reference to checkout. PaymentForm handles the entire checkout flow internally
|
|
311
|
+
* including Stripe initialization and payment intent creation.
|
|
312
|
+
*/
|
|
8
313
|
planRef: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
314
|
+
/**
|
|
315
|
+
* Agent reference. Required for processing payment after confirmation.
|
|
316
|
+
*/
|
|
317
|
+
agentRef?: string;
|
|
318
|
+
/**
|
|
319
|
+
* Callback when payment succeeds
|
|
320
|
+
*/
|
|
321
|
+
onSuccess?: (paymentIntent: PaymentIntent) => void;
|
|
322
|
+
/**
|
|
323
|
+
* Callback when payment fails
|
|
324
|
+
*/
|
|
325
|
+
onError?: (error: Error) => void;
|
|
326
|
+
/**
|
|
327
|
+
* Return URL after payment completion. Defaults to current page URL if not provided.
|
|
328
|
+
*/
|
|
329
|
+
returnUrl?: string;
|
|
330
|
+
/**
|
|
331
|
+
* Text for the submit button. Defaults to "Pay Now"
|
|
332
|
+
*/
|
|
333
|
+
submitButtonText?: string;
|
|
334
|
+
/**
|
|
335
|
+
* Optional className for the form container
|
|
336
|
+
*/
|
|
337
|
+
className?: string;
|
|
338
|
+
/**
|
|
339
|
+
* Optional className for the submit button
|
|
340
|
+
*/
|
|
341
|
+
buttonClassName?: string;
|
|
12
342
|
}
|
|
343
|
+
|
|
13
344
|
/**
|
|
14
|
-
* SolvaPay
|
|
345
|
+
* SolvaPay Provider - Headless Context Provider
|
|
346
|
+
*
|
|
347
|
+
* Provides subscription state and payment methods to child components.
|
|
348
|
+
* Supports zero-config with sensible defaults, or full customization.
|
|
15
349
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```tsx
|
|
352
|
+
* // Zero config (uses defaults)
|
|
353
|
+
* <SolvaPayProvider>
|
|
354
|
+
* <App />
|
|
355
|
+
* </SolvaPayProvider>
|
|
18
356
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
357
|
+
* // Custom API routes
|
|
358
|
+
* <SolvaPayProvider
|
|
359
|
+
* config={{
|
|
360
|
+
* api: {
|
|
361
|
+
* checkSubscription: '/custom/api/subscription',
|
|
362
|
+
* createPayment: '/custom/api/payment'
|
|
363
|
+
* }
|
|
364
|
+
* }}
|
|
365
|
+
* >
|
|
366
|
+
* <App />
|
|
367
|
+
* </SolvaPayProvider>
|
|
368
|
+
*
|
|
369
|
+
* // Fully custom
|
|
370
|
+
* <SolvaPayProvider
|
|
371
|
+
* checkSubscription={async () => {
|
|
372
|
+
* return await myCustomAPI.checkSubscription();
|
|
373
|
+
* }}
|
|
374
|
+
* createPayment={async ({ planRef, agentRef }) => {
|
|
375
|
+
* return await myCustomAPI.createPayment(planRef, agentRef);
|
|
376
|
+
* }}
|
|
377
|
+
* >
|
|
378
|
+
* <App />
|
|
379
|
+
* </SolvaPayProvider>
|
|
380
|
+
* ```
|
|
381
|
+
*/
|
|
382
|
+
declare const SolvaPayProvider: React$1.FC<SolvaPayProviderProps>;
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* SolvaPay Payment Form Component
|
|
386
|
+
*
|
|
387
|
+
* A simplified, minimal payment form that handles the checkout flow.
|
|
388
|
+
* Automatically initializes Stripe and displays the payment form.
|
|
23
389
|
*
|
|
24
390
|
* @example
|
|
25
391
|
* ```tsx
|
|
26
|
-
*
|
|
27
|
-
* import { SolvaPayProvider, PaymentForm } from '@solvapay/react';
|
|
392
|
+
* import { PaymentForm } from '@solvapay/react';
|
|
28
393
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* >
|
|
40
|
-
* <PaymentForm />
|
|
41
|
-
* </SolvaPayProvider>
|
|
42
|
-
* );
|
|
43
|
-
* }
|
|
394
|
+
* <PaymentForm
|
|
395
|
+
* planRef="pro_plan"
|
|
396
|
+
* agentRef="agent_123"
|
|
397
|
+
* onSuccess={(paymentIntent) => {
|
|
398
|
+
* console.log('Payment successful!');
|
|
399
|
+
* }}
|
|
400
|
+
* onError={(error) => {
|
|
401
|
+
* console.error('Payment failed:', error);
|
|
402
|
+
* }}
|
|
403
|
+
* />
|
|
44
404
|
* ```
|
|
45
405
|
*/
|
|
46
|
-
declare const
|
|
406
|
+
declare const PaymentForm: React$1.FC<PaymentFormProps>;
|
|
47
407
|
|
|
48
|
-
|
|
49
|
-
|
|
408
|
+
/**
|
|
409
|
+
* Headless Plan Badge Component
|
|
410
|
+
*
|
|
411
|
+
* Displays subscription status with complete styling control.
|
|
412
|
+
* Supports render props, custom components, or className patterns.
|
|
413
|
+
*
|
|
414
|
+
* Prevents flickering by hiding the badge during initial load and when no subscription exists.
|
|
415
|
+
* Shows the badge once loading completes AND an active subscription exists (paid or free).
|
|
416
|
+
* Badge only updates when the plan name actually changes (prevents unnecessary re-renders).
|
|
417
|
+
*
|
|
418
|
+
* Displays the primary active subscription (paid or free) to show current plan status.
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* ```tsx
|
|
422
|
+
* // Render prop pattern
|
|
423
|
+
* <PlanBadge>
|
|
424
|
+
* {({ subscriptions, loading, displayPlan, shouldShow }) => (
|
|
425
|
+
* shouldShow ? (
|
|
426
|
+
* <div>{displayPlan}</div>
|
|
427
|
+
* ) : null
|
|
428
|
+
* )}
|
|
429
|
+
* </PlanBadge>
|
|
430
|
+
*
|
|
431
|
+
* //ClassName pattern
|
|
432
|
+
* <PlanBadge className="badge badge-primary" />
|
|
433
|
+
* ```
|
|
434
|
+
*/
|
|
435
|
+
declare const PlanBadge: React$1.FC<PlanBadgeProps>;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Headless Subscription Gate Component
|
|
439
|
+
*
|
|
440
|
+
* Controls access to content based on subscription status.
|
|
441
|
+
* Uses render props to give developers full control over locked/unlocked states.
|
|
442
|
+
*
|
|
443
|
+
* @example
|
|
444
|
+
* ```tsx
|
|
445
|
+
* <SubscriptionGate requirePlan="Pro Plan">
|
|
446
|
+
* {({ hasAccess, loading }) => {
|
|
447
|
+
* if (loading) return <Skeleton />;
|
|
448
|
+
* if (!hasAccess) return <Paywall />;
|
|
449
|
+
* return <PremiumContent />;
|
|
450
|
+
* }}
|
|
451
|
+
* </SubscriptionGate>
|
|
452
|
+
* ```
|
|
453
|
+
*/
|
|
454
|
+
declare const SubscriptionGate: React$1.FC<SubscriptionGateProps>;
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Headless Plan Selector Component
|
|
458
|
+
*
|
|
459
|
+
* Provides plan selection logic with complete styling control via render props.
|
|
460
|
+
* Integrates plan fetching, subscription status, and selection state management.
|
|
461
|
+
*
|
|
462
|
+
* Features:
|
|
463
|
+
* - Fetches and manages plans
|
|
464
|
+
* - Tracks selected plan
|
|
465
|
+
* - Provides helpers for checking if plan is current/paid
|
|
466
|
+
* - Integrates with subscription context
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* ```tsx
|
|
470
|
+
* <PlanSelector
|
|
471
|
+
* agentRef="agent_123"
|
|
472
|
+
* fetcher={async (agentRef) => {
|
|
473
|
+
* const res = await fetch(`/api/list-plans?agentRef=${agentRef}`);
|
|
474
|
+
* const data = await res.json();
|
|
475
|
+
* return data.plans;
|
|
476
|
+
* }}
|
|
477
|
+
* sortBy={(a, b) => (a.price || 0) - (b.price || 0)}
|
|
478
|
+
* autoSelectFirstPaid
|
|
479
|
+
* >
|
|
480
|
+
* {({ plans, selectedPlan, setSelectedPlanIndex, loading, isPaidPlan, isCurrentPlan }) => (
|
|
481
|
+
* <div>
|
|
482
|
+
* {loading ? (
|
|
483
|
+
* <div>Loading plans...</div>
|
|
484
|
+
* ) : (
|
|
485
|
+
* plans.map((plan, index) => (
|
|
486
|
+
* <button
|
|
487
|
+
* key={plan.reference}
|
|
488
|
+
* onClick={() => setSelectedPlanIndex(index)}
|
|
489
|
+
* disabled={!isPaidPlan(plan.name)}
|
|
490
|
+
* >
|
|
491
|
+
* {plan.name} - ${plan.price}
|
|
492
|
+
* {isCurrentPlan(plan.name) && ' (Current)'}
|
|
493
|
+
* </button>
|
|
494
|
+
* ))
|
|
495
|
+
* )}
|
|
496
|
+
* </div>
|
|
497
|
+
* )}
|
|
498
|
+
* </PlanSelector>
|
|
499
|
+
* ```
|
|
500
|
+
*/
|
|
501
|
+
declare const PlanSelector: React$1.FC<PlanSelectorProps>;
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* SVG-based spinner component using CSS animations
|
|
505
|
+
* Uses the same spinner design as the rest of the site
|
|
506
|
+
*/
|
|
507
|
+
declare const Spinner: React$1.FC<{
|
|
508
|
+
className?: string;
|
|
509
|
+
size?: 'sm' | 'md' | 'lg';
|
|
510
|
+
}>;
|
|
511
|
+
|
|
512
|
+
interface StripePaymentFormWrapperProps {
|
|
513
|
+
onSuccess?: (paymentIntent: any) => void | Promise<void>;
|
|
50
514
|
onError?: (error: Error) => void;
|
|
51
515
|
returnUrl?: string;
|
|
52
516
|
submitButtonText?: string;
|
|
53
|
-
|
|
517
|
+
buttonClassName?: string;
|
|
518
|
+
clientSecret: string;
|
|
54
519
|
}
|
|
55
520
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
|
|
521
|
+
* Stripe Payment Form Wrapper Component
|
|
522
|
+
* Renders inside Stripe Elements context and handles the payment flow
|
|
523
|
+
* All hooks are called unconditionally to comply with React Rules of Hooks
|
|
524
|
+
*/
|
|
525
|
+
declare const StripePaymentFormWrapper: React$1.FC<StripePaymentFormWrapperProps>;
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Hook to access subscription status
|
|
529
|
+
* Returns the current subscription state and a refetch function
|
|
530
|
+
*/
|
|
531
|
+
declare function useSubscription(): SubscriptionStatus & {
|
|
532
|
+
refetch: () => Promise<void>;
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Customer information interface
|
|
537
|
+
*/
|
|
538
|
+
interface CustomerInfo {
|
|
539
|
+
/**
|
|
540
|
+
* Customer reference ID
|
|
541
|
+
*/
|
|
542
|
+
customerRef?: string;
|
|
543
|
+
/**
|
|
544
|
+
* Customer email address
|
|
545
|
+
*/
|
|
546
|
+
email?: string;
|
|
547
|
+
/**
|
|
548
|
+
* Customer name
|
|
549
|
+
*/
|
|
550
|
+
name?: string;
|
|
551
|
+
/**
|
|
552
|
+
* Whether customer data is currently loading
|
|
553
|
+
*/
|
|
554
|
+
loading: boolean;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Hook to access customer information
|
|
558
|
+
* Returns customer data (email, name, customerRef) separate from subscription data
|
|
60
559
|
*
|
|
61
560
|
* @example
|
|
62
561
|
* ```tsx
|
|
63
|
-
* import {
|
|
562
|
+
* import { useCustomer } from '@solvapay/react';
|
|
563
|
+
*
|
|
564
|
+
* function MyComponent() {
|
|
565
|
+
* const { email, name, customerRef } = useCustomer();
|
|
64
566
|
*
|
|
65
|
-
* export default function CheckoutPage() {
|
|
66
567
|
* return (
|
|
67
|
-
* <
|
|
68
|
-
* <
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* console.log('Payment successful!', paymentIntent);
|
|
72
|
-
* }}
|
|
73
|
-
* onError={(error) => {
|
|
74
|
-
* console.error('Payment failed:', error);
|
|
75
|
-
* }}
|
|
76
|
-
* />
|
|
77
|
-
* </SolvaPayProvider>
|
|
568
|
+
* <div>
|
|
569
|
+
* <p>Email: {email || 'Not provided'}</p>
|
|
570
|
+
* <p>Name: {name || 'Not provided'}</p>
|
|
571
|
+
* </div>
|
|
78
572
|
* );
|
|
79
573
|
* }
|
|
80
574
|
* ```
|
|
81
575
|
*/
|
|
82
|
-
declare
|
|
576
|
+
declare function useCustomer(): CustomerInfo;
|
|
577
|
+
|
|
578
|
+
interface UseCheckoutReturn {
|
|
579
|
+
loading: boolean;
|
|
580
|
+
error: Error | null;
|
|
581
|
+
stripePromise: Promise<Stripe | null> | null;
|
|
582
|
+
clientSecret: string | null;
|
|
583
|
+
startCheckout: () => Promise<void>;
|
|
584
|
+
reset: () => void;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Hook to manage checkout flow
|
|
588
|
+
* Handles payment intent creation and Stripe initialization
|
|
589
|
+
*
|
|
590
|
+
* @param planRef - The plan reference to checkout
|
|
591
|
+
* @param agentRef - Optional agent reference
|
|
592
|
+
*/
|
|
593
|
+
declare function useCheckout(planRef: string, agentRef?: string): UseCheckoutReturn;
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Hook to access SolvaPay context
|
|
597
|
+
* Must be used within a SolvaPayProvider
|
|
598
|
+
*/
|
|
599
|
+
declare function useSolvaPay(): SolvaPayContextValue;
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Hook to manage plan fetching and selection
|
|
603
|
+
*
|
|
604
|
+
* Provides a reusable way to fetch, filter, sort and select subscription plans.
|
|
605
|
+
* Handles loading and error states automatically.
|
|
606
|
+
* Uses a global cache to prevent duplicate fetches when multiple components use the same agentRef.
|
|
607
|
+
*
|
|
608
|
+
* @example
|
|
609
|
+
* ```tsx
|
|
610
|
+
* const plans = usePlans({
|
|
611
|
+
* agentRef: 'agent_123',
|
|
612
|
+
* fetcher: async (agentRef) => {
|
|
613
|
+
* const res = await fetch(`/api/list-plans?agentRef=${agentRef}`);
|
|
614
|
+
* const data = await res.json();
|
|
615
|
+
* return data.plans;
|
|
616
|
+
* },
|
|
617
|
+
* sortBy: (a, b) => (a.price || 0) - (b.price || 0),
|
|
618
|
+
* autoSelectFirstPaid: true,
|
|
619
|
+
* });
|
|
620
|
+
*
|
|
621
|
+
* // Use in component
|
|
622
|
+
* if (plans.loading) return <div>Loading...</div>;
|
|
623
|
+
* if (plans.error) return <div>Error: {plans.error.message}</div>;
|
|
624
|
+
* ```
|
|
625
|
+
*/
|
|
626
|
+
declare function usePlans(options: UsePlansOptions): UsePlansReturn;
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Hook providing advanced status and helper functions for subscription management
|
|
630
|
+
*
|
|
631
|
+
* Focuses on cancelled subscription logic and date formatting utilities.
|
|
632
|
+
* For basic subscription data and paid status checks, use useSubscription() instead.
|
|
633
|
+
*
|
|
634
|
+
* @example
|
|
635
|
+
* ```tsx
|
|
636
|
+
* const { cancelledSubscription, shouldShowCancelledNotice, formatDate, getDaysUntilExpiration } = useSubscriptionStatus();
|
|
637
|
+
*
|
|
638
|
+
* if (shouldShowCancelledNotice && cancelledSubscription) {
|
|
639
|
+
* const formattedDate = formatDate(cancelledSubscription.endDate);
|
|
640
|
+
* const daysLeft = getDaysUntilExpiration(cancelledSubscription.endDate);
|
|
641
|
+
* }
|
|
642
|
+
* ```
|
|
643
|
+
*/
|
|
644
|
+
declare function useSubscriptionStatus(): SubscriptionStatusReturn;
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Subscription utility functions
|
|
648
|
+
*
|
|
649
|
+
* Provides shared logic for filtering and prioritizing subscriptions
|
|
650
|
+
*/
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Filter subscriptions to only include active ones
|
|
654
|
+
*
|
|
655
|
+
* Rules:
|
|
656
|
+
* - Keep subscriptions with status === 'active'
|
|
657
|
+
* - Filter out subscriptions with status === 'cancelled', 'expired', 'suspended', 'refunded', etc.
|
|
658
|
+
*
|
|
659
|
+
* Note: Backend now keeps subscriptions with status 'active' until expiration,
|
|
660
|
+
* even when cancelled. Cancellation is tracked via cancelledAt field.
|
|
661
|
+
*/
|
|
662
|
+
declare function filterSubscriptions(subscriptions: SubscriptionInfo[]): SubscriptionInfo[];
|
|
663
|
+
/**
|
|
664
|
+
* Get active subscriptions
|
|
665
|
+
*
|
|
666
|
+
* Returns subscriptions with status === 'active'.
|
|
667
|
+
* Note: Backend keeps subscriptions as 'active' until expiration, even when cancelled.
|
|
668
|
+
* Use cancelledAt field to check if a subscription is cancelled.
|
|
669
|
+
*/
|
|
670
|
+
declare function getActiveSubscriptions(subscriptions: SubscriptionInfo[]): SubscriptionInfo[];
|
|
671
|
+
/**
|
|
672
|
+
* Get cancelled subscriptions with valid endDate (not expired)
|
|
673
|
+
*
|
|
674
|
+
* Returns subscriptions with cancelledAt set and status === 'active' that have a future endDate.
|
|
675
|
+
* Backend keeps cancelled subscriptions as 'active' until expiration.
|
|
676
|
+
*/
|
|
677
|
+
declare function getCancelledSubscriptionsWithEndDate(subscriptions: SubscriptionInfo[]): SubscriptionInfo[];
|
|
678
|
+
/**
|
|
679
|
+
* Get the most recent subscription by startDate
|
|
680
|
+
*/
|
|
681
|
+
declare function getMostRecentSubscription(subscriptions: SubscriptionInfo[]): SubscriptionInfo | null;
|
|
682
|
+
/**
|
|
683
|
+
* Get the primary subscription to display
|
|
684
|
+
*
|
|
685
|
+
* Prioritization:
|
|
686
|
+
* 1. Active subscriptions (most recent by startDate)
|
|
687
|
+
* 2. null if no valid subscriptions
|
|
688
|
+
*
|
|
689
|
+
* Note: Backend keeps subscriptions as 'active' until expiration, so we only
|
|
690
|
+
* need to check for active subscriptions. Cancelled subscriptions are still
|
|
691
|
+
* active until their endDate.
|
|
692
|
+
*/
|
|
693
|
+
declare function getPrimarySubscription(subscriptions: SubscriptionInfo[]): SubscriptionInfo | null;
|
|
694
|
+
/**
|
|
695
|
+
* Check if a subscription is paid
|
|
696
|
+
* Uses subscription amount field: amount > 0 = paid, amount === 0 or undefined = free
|
|
697
|
+
*
|
|
698
|
+
* @param sub - Subscription to check
|
|
699
|
+
* @returns true if subscription is paid (amount > 0)
|
|
700
|
+
*/
|
|
701
|
+
declare function isPaidSubscription(sub: SubscriptionInfo): boolean;
|
|
83
702
|
|
|
84
|
-
export { PaymentForm, type PaymentFormProps, SolvaPayProvider, type SolvaPayProviderProps };
|
|
703
|
+
export { AuthAdapter, type CustomerInfo, type CustomerSubscriptionData, type PaymentError, PaymentForm, type PaymentFormProps, type PaymentIntentResult, type Plan, PlanBadge, type PlanBadgeProps, PlanSelector, type PlanSelectorProps, type SolvaPayConfig, type SolvaPayContextValue, SolvaPayProvider, type SolvaPayProviderProps, Spinner, StripePaymentFormWrapper, SubscriptionGate, type SubscriptionGateProps, type SubscriptionInfo, type SubscriptionStatus, type SubscriptionStatusReturn, type UsePlansOptions, type UsePlansReturn, filterSubscriptions, getActiveSubscriptions, getCancelledSubscriptionsWithEndDate, getMostRecentSubscription, getPrimarySubscription, isPaidSubscription, useCheckout, useCustomer, usePlans, useSolvaPay, useSubscription, useSubscriptionStatus };
|