@solvapay/react 1.0.0-preview.8 → 1.0.1-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,26 +1,52 @@
1
1
  import React$1 from 'react';
2
2
  import { PaymentIntent, Stripe } from '@stripe/stripe-js';
3
3
  import { ProcessPaymentResult } from '@solvapay/server';
4
+ import { AuthAdapter } from './adapters/auth.cjs';
5
+ export { defaultAuthAdapter } from './adapters/auth.cjs';
4
6
 
5
7
  /**
6
8
  * TypeScript type definitions for @solvapay/react
7
9
  */
8
10
 
9
- interface SubscriptionInfo {
11
+ interface PurchaseInfo {
10
12
  reference: string;
11
- planName: string;
12
- agentName: string;
13
+ productName: string;
14
+ productReference?: string;
13
15
  status: string;
14
16
  startDate: string;
15
17
  endDate?: string;
16
18
  cancelledAt?: string;
17
19
  cancellationReason?: string;
20
+ amount?: number;
21
+ currency?: string;
22
+ planType?: string;
23
+ isRecurring?: boolean;
24
+ nextBillingDate?: string;
25
+ billingCycle?: string;
26
+ transactionId?: string;
27
+ planSnapshot?: {
28
+ reference?: string;
29
+ meterId?: string;
30
+ limit?: number;
31
+ freeUnits?: number;
32
+ pricePerUnit?: number;
33
+ planType?: string;
34
+ billingCycle?: string | null;
35
+ features?: Record<string, unknown> | null;
36
+ };
37
+ usage?: {
38
+ used: number;
39
+ overageUnits?: number;
40
+ overageCost?: number;
41
+ periodStart?: string;
42
+ periodEnd?: string;
43
+ };
18
44
  }
19
- interface CustomerSubscriptionData {
45
+ interface CustomerPurchaseData {
20
46
  customerRef?: string;
21
47
  email?: string;
22
48
  name?: string;
23
- subscriptions: SubscriptionInfo[];
49
+ purchases: PurchaseInfo[];
24
50
  }
25
51
  interface PaymentIntentResult {
26
52
  clientSecret: string;
@@ -28,64 +54,159 @@ interface PaymentIntentResult {
28
54
  accountId?: string;
29
55
  customerRef?: string;
30
56
  }
31
- interface SubscriptionStatus {
57
+ interface PurchaseStatus {
32
58
  loading: boolean;
33
59
  customerRef?: string;
34
60
  email?: string;
35
61
  name?: string;
36
- subscriptions: SubscriptionInfo[];
37
- hasActiveSubscription: boolean;
38
- hasPlan: (planName: string) => boolean;
62
+ purchases: PurchaseInfo[];
63
+ hasProduct: (productName: string) => boolean;
64
+ /** @deprecated Use hasProduct instead */
65
+ hasPlan: (productName: string) => boolean;
66
+ /**
67
+ * Primary active purchase (paid or free) - most recent purchase with status === 'active'
68
+ * Backend keeps purchases as 'active' until expiration, even when cancelled.
69
+ * null if no active purchase exists
70
+ */
71
+ activePurchase: PurchaseInfo | null;
72
+ /**
73
+ * Check if user has any active paid purchase (amount > 0)
74
+ * Checks purchases with status === 'active'.
75
+ * Backend keeps purchases as 'active' until expiration, even when cancelled.
76
+ */
77
+ hasPaidPurchase: boolean;
78
+ /**
79
+ * Most recent active paid purchase (sorted by startDate)
80
+ * Returns purchase with status === 'active' and amount > 0.
81
+ * null if no active paid purchase exists
82
+ */
83
+ activePaidPurchase: PurchaseInfo | null;
84
+ }
85
+ /**
86
+ * SolvaPay Provider Configuration
87
+ * Sensible defaults for minimal code, but fully customizable
88
+ */
89
+ interface SolvaPayConfig {
90
+ /**
91
+ * API route configuration
92
+ * Defaults to standard Next.js API routes
93
+ */
94
+ api?: {
95
+ checkPurchase?: string;
96
+ createPayment?: string;
97
+ processPayment?: string;
98
+ };
99
+ /**
100
+ * Authentication configuration
101
+ * Uses adapter pattern for flexible auth provider support
102
+ */
103
+ auth?: {
104
+ /**
105
+ * Auth adapter instance
106
+ * Default: checks localStorage for 'auth_token' key
107
+ *
108
+ * @example
109
+ * ```tsx
110
+ * import { createSupabaseAuthAdapter } from '@solvapay/react-supabase';
111
+ *
112
+ * <SolvaPayProvider
113
+ * config={{
114
+ * auth: {
115
+ * adapter: createSupabaseAuthAdapter({
116
+ * supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
117
+ * supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
118
+ * })
119
+ * }
120
+ * }}
121
+ * >
122
+ * ```
123
+ */
124
+ adapter?: AuthAdapter;
125
+ /**
126
+ * @deprecated Use `adapter` instead. Will be removed in a future version.
127
+ * Function to get auth token
128
+ */
129
+ getToken?: () => Promise<string | null>;
130
+ /**
131
+ * @deprecated Use `adapter` instead. Will be removed in a future version.
132
+ * Function to get user ID (for cache key)
133
+ */
134
+ getUserId?: () => Promise<string | null>;
135
+ };
136
+ /**
137
+ * Custom fetch implementation
138
+ * Default: uses global fetch
139
+ */
140
+ fetch?: typeof fetch;
141
+ /**
142
+ * Request headers to include in all API calls
143
+ * Default: empty
144
+ */
145
+ headers?: HeadersInit | (() => Promise<HeadersInit>);
146
+ /**
147
+ * Custom error handler
148
+ * Default: logs to console
149
+ */
150
+ onError?: (error: Error, context: string) => void;
39
151
  }
40
152
  interface SolvaPayContextValue {
41
- subscription: SubscriptionStatus;
42
- refetchSubscription: () => Promise<void>;
153
+ purchase: PurchaseStatus;
154
+ refetchPurchase: () => Promise<void>;
43
155
  createPayment: (params: {
44
156
  planRef: string;
45
- customerRef: string;
157
+ productRef?: string;
46
158
  }) => Promise<PaymentIntentResult>;
47
159
  processPayment?: (params: {
48
160
  paymentIntentId: string;
49
- agentRef: string;
50
- customerRef: string;
161
+ productRef: string;
51
162
  planRef?: string;
52
163
  }) => Promise<ProcessPaymentResult>;
53
164
  customerRef?: string;
54
165
  updateCustomerRef?: (newCustomerRef: string) => void;
55
166
  }
56
167
  interface SolvaPayProviderProps {
57
- createPayment: (params: {
168
+ /**
169
+ * Configuration object with sensible defaults
170
+ * If not provided, uses standard Next.js API routes
171
+ */
172
+ config?: SolvaPayConfig;
173
+ /**
174
+ * Custom API functions (override config defaults)
175
+ * Use only if you need custom logic beyond standard API routes
176
+ */
177
+ createPayment?: (params: {
58
178
  planRef: string;
59
- customerRef: string;
179
+ productRef?: string;
60
180
  }) => Promise<PaymentIntentResult>;
61
- checkSubscription: (customerRef: string) => Promise<CustomerSubscriptionData>;
181
+ checkPurchase?: () => Promise<CustomerPurchaseData>;
62
182
  processPayment?: (params: {
63
183
  paymentIntentId: string;
64
- agentRef: string;
65
- customerRef: string;
184
+ productRef: string;
66
185
  planRef?: string;
67
186
  }) => Promise<ProcessPaymentResult>;
68
- customerRef?: string;
69
- onCustomerRefUpdate?: (newCustomerRef: string) => void;
70
187
  children: React.ReactNode;
71
188
  }
72
- interface PlanBadgeProps {
189
+ interface ProductBadgeProps {
73
190
  children?: (props: {
74
- subscriptions: SubscriptionInfo[];
191
+ purchases: PurchaseInfo[];
75
192
  loading: boolean;
76
193
  displayPlan: string | null;
77
194
  shouldShow: boolean;
78
195
  }) => React.ReactNode;
79
196
  as?: React.ElementType;
80
197
  className?: string | ((props: {
81
- subscriptions: SubscriptionInfo[];
198
+ purchases: PurchaseInfo[];
82
199
  }) => string);
83
200
  }
84
- interface SubscriptionGateProps {
201
+ /** @deprecated Use ProductBadgeProps instead */
202
+ type PlanBadgeProps = ProductBadgeProps;
203
+ interface PurchaseGateProps {
204
+ /** @deprecated Use requireProduct instead */
85
205
  requirePlan?: string;
206
+ requireProduct?: string;
86
207
  children: (props: {
87
208
  hasAccess: boolean;
88
- subscriptions: SubscriptionInfo[];
209
+ purchases: PurchaseInfo[];
89
210
  loading: boolean;
90
211
  }) => React.ReactNode;
91
212
  }
@@ -97,18 +218,16 @@ interface PaymentError extends Error {
97
218
  type?: string;
98
219
  }
99
220
  /**
100
- * Plan interface for subscription plans
221
+ * Plan interface for plans
101
222
  */
102
223
  interface Plan {
103
224
  reference: string;
104
- name: string;
105
- description?: string;
106
225
  price?: number;
107
226
  currency?: string;
108
227
  interval?: string;
109
228
  features?: string[];
110
229
  isFreeTier?: boolean;
111
- metadata?: Record<string, any>;
230
+ metadata?: Record<string, unknown>;
112
231
  }
113
232
  /**
114
233
  * Options for usePlans hook
@@ -117,11 +236,11 @@ interface UsePlansOptions {
117
236
  /**
118
237
  * Fetcher function to retrieve plans
119
238
  */
120
- fetcher: (agentRef: string) => Promise<Plan[]>;
239
+ fetcher: (productRef: string) => Promise<Plan[]>;
121
240
  /**
122
- * Agent reference to fetch plans for
241
+ * Product reference to fetch plans for
123
242
  */
124
- agentRef?: string;
243
+ productRef?: string;
125
244
  /**
126
245
  * Optional filter function to filter plans
127
246
  */
@@ -149,17 +268,17 @@ interface UsePlansReturn {
149
268
  refetch: () => Promise<void>;
150
269
  }
151
270
  /**
152
- * Props for headless PlanSelector component
271
+ * Props for headless PricingSelector component
153
272
  */
154
- interface PlanSelectorProps {
273
+ interface PricingSelectorProps {
155
274
  /**
156
- * Agent reference to fetch plans for
275
+ * Product reference to fetch plans for
157
276
  */
158
- agentRef?: string;
277
+ productRef?: string;
159
278
  /**
160
279
  * Fetcher function to retrieve plans
161
280
  */
162
- fetcher: (agentRef: string) => Promise<Plan[]>;
281
+ fetcher: (productRef: string) => Promise<Plan[]>;
163
282
  /**
164
283
  * Optional filter function
165
284
  */
@@ -176,45 +295,39 @@ interface PlanSelectorProps {
176
295
  * Render prop function
177
296
  */
178
297
  children: (props: UsePlansReturn & {
179
- subscriptions: SubscriptionInfo[];
180
- isPaidPlan: (planName: string) => boolean;
181
- isCurrentPlan: (planName: string) => boolean;
298
+ purchases: PurchaseInfo[];
299
+ isPaidPlan: (planRef: string) => boolean;
300
+ isCurrentPlan: (planRef: string) => boolean;
182
301
  }) => React.ReactNode;
183
302
  }
303
+ /** @deprecated Use PricingSelectorProps instead */
304
+ type PlanSelectorProps = PricingSelectorProps;
184
305
  /**
185
- * Return type for useSubscriptionHelpers hook
306
+ * Return type for usePurchaseStatus hook
307
+ *
308
+ * Provides advanced purchase status helpers and utilities.
309
+ * Focuses on cancelled purchase logic and date formatting.
310
+ * For basic purchase data and paid status, use usePurchase() instead.
186
311
  */
187
- interface SubscriptionHelpersReturn {
188
- /**
189
- * Check if a plan name is a paid plan
190
- */
191
- isPaidPlan: (planName: string) => boolean;
192
- /**
193
- * Get active paid subscription
194
- */
195
- activePaidSubscription: SubscriptionInfo | null;
196
- /**
197
- * Get cancelled subscription
198
- */
199
- cancelledSubscription: SubscriptionInfo | null;
312
+ interface PurchaseStatusReturn {
200
313
  /**
201
- * Check if user has any paid subscription
314
+ * Most recent cancelled paid purchase (sorted by startDate)
315
+ * null if no cancelled paid purchase exists
202
316
  */
203
- hasPaidSubscription: boolean;
317
+ cancelledPurchase: PurchaseInfo | null;
204
318
  /**
205
- * Check if should show cancelled notice
319
+ * Whether to show cancelled purchase notice
320
+ * true if cancelledPurchase exists
206
321
  */
207
322
  shouldShowCancelledNotice: boolean;
208
323
  /**
209
- * Get active plan name
210
- */
211
- activePlanName: string | null;
212
- /**
213
- * Format a date string
324
+ * Format a date string to locale format (e.g., "January 15, 2024")
325
+ * Returns null if dateString is not provided
214
326
  */
215
327
  formatDate: (dateString?: string) => string | null;
216
328
  /**
217
- * Get days until a date
329
+ * Calculate days until expiration date
330
+ * Returns null if endDate is not provided, otherwise returns days (0 or positive)
218
331
  */
219
332
  getDaysUntilExpiration: (endDate?: string) => number | null;
220
333
  }
@@ -228,9 +341,9 @@ interface PaymentFormProps {
228
341
  */
229
342
  planRef: string;
230
343
  /**
231
- * Agent reference. Required for processing payment after confirmation.
344
+ * Product reference. Required for processing payment after confirmation.
232
345
  */
233
- agentRef?: string;
346
+ productRef?: string;
234
347
  /**
235
348
  * Callback when payment succeeds
236
349
  */
@@ -256,123 +369,207 @@ interface PaymentFormProps {
256
369
  */
257
370
  buttonClassName?: string;
258
371
  }
372
+ type PurchaseStatusValue = 'pending' | 'active' | 'trialing' | 'past_due' | 'cancelled' | 'expired' | 'suspended' | 'refunded';
259
373
 
260
374
  /**
261
- * SolvaPay Provider - Headless Context Provider
375
+ * SolvaPay Provider - Headless Context Provider for React.
376
+ *
377
+ * Provides purchase state, payment methods, and customer data to child components
378
+ * via React Context. This is the root component that must wrap your app to use
379
+ * SolvaPay React hooks and components.
380
+ *
381
+ * Features:
382
+ * - Automatic purchase status checking
383
+ * - Customer reference caching in localStorage
384
+ * - Payment intent creation and processing
385
+ * - Authentication adapter support (Supabase, custom, etc.)
386
+ * - Zero-config with sensible defaults, or full customization
262
387
  *
263
- * Provides subscription state and payment methods to child components.
264
- * This is a headless provider that manages state without rendering UI.
388
+ * @param props - Provider configuration
389
+ * @param props.config - Configuration object for API routes and authentication
390
+ * @param props.config.api - API route configuration (optional, uses defaults if not provided)
391
+ * @param props.config.api.checkPurchase - Endpoint for checking purchase status (default: '/api/check-purchase')
392
+ * @param props.config.api.createPayment - Endpoint for creating payment intents (default: '/api/create-payment-intent')
393
+ * @param props.config.api.processPayment - Endpoint for processing payments (default: '/api/process-payment')
394
+ * @param props.config.auth - Authentication configuration (optional)
395
+ * @param props.config.auth.adapter - Auth adapter for extracting user ID and token
396
+ * @param props.children - React children components
265
397
  *
266
398
  * @example
267
399
  * ```tsx
268
- * <SolvaPayProvider
269
- * customerRef={user?.id}
270
- * createPayment={async ({ planRef, customerRef }) => {
271
- * const res = await fetch('/api/payments/create', {
272
- * method: 'POST',
273
- * body: JSON.stringify({ planRef, customerRef })
274
- * });
275
- * return res.json();
276
- * }}
277
- * checkSubscription={async (customerRef) => {
278
- * const res = await fetch(`/api/subscriptions/${customerRef}`);
279
- * return res.json();
280
- * }}
281
- * >
282
- * <App />
283
- * </SolvaPayProvider>
400
+ * import { SolvaPayProvider } from '@solvapay/react';
401
+ *
402
+ * // Zero config (uses defaults)
403
+ * function App() {
404
+ * return (
405
+ * <SolvaPayProvider>
406
+ * <YourApp />
407
+ * </SolvaPayProvider>
408
+ * );
409
+ * }
410
+ *
411
+ * // Custom API routes
412
+ * function App() {
413
+ * return (
414
+ * <SolvaPayProvider
415
+ * config={{
416
+ * api: {
417
+ * checkPurchase: '/custom/api/purchase',
418
+ * createPayment: '/custom/api/payment'
419
+ * }
420
+ * }}
421
+ * >
422
+ * <YourApp />
423
+ * </SolvaPayProvider>
424
+ * );
425
+ * }
426
+ *
427
+ * // With Supabase auth adapter
428
+ * import { createSupabaseAuthAdapter } from '@solvapay/react-supabase';
429
+ *
430
+ * function App() {
431
+ * const adapter = createSupabaseAuthAdapter({
432
+ * supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
433
+ * supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
434
+ * });
435
+ *
436
+ * return (
437
+ * <SolvaPayProvider
438
+ * config={{
439
+ * auth: { adapter }
440
+ * }}
441
+ * >
442
+ * <YourApp />
443
+ * </SolvaPayProvider>
444
+ * );
445
+ * }
284
446
  * ```
447
+ *
448
+ * @see {@link usePurchase} for accessing purchase data
449
+ * @see {@link useCheckout} for payment checkout flow
450
+ * @see {@link useSolvaPay} for accessing provider methods
451
+ * @since 1.0.0
285
452
  */
286
453
  declare const SolvaPayProvider: React$1.FC<SolvaPayProviderProps>;
287
454
 
288
455
  /**
289
- * SolvaPay Payment Form Component
456
+ * Payment form component for handling Stripe checkout.
457
+ *
458
+ * This component provides a complete payment form with Stripe integration,
459
+ * including card input, plan selection, and payment processing. It handles
460
+ * the entire checkout flow including payment intent creation and confirmation.
461
+ *
462
+ * Features:
463
+ * - Automatic Stripe Elements initialization
464
+ * - Payment intent creation on mount
465
+ * - Card input and validation
466
+ * - Payment processing with error handling
467
+ * - Automatic purchase refresh after payment
290
468
  *
291
- * A simplified, minimal payment form that handles the checkout flow.
292
- * Automatically initializes Stripe and displays the payment form.
469
+ * @param props - Payment form configuration
470
+ * @param props.planRef - Plan reference to purchase (required)
471
+ * @param props.productRef - Product reference for usage tracking
472
+ * @param props.onSuccess - Callback when payment succeeds
473
+ * @param props.onError - Callback when payment fails
474
+ * @param props.returnUrl - Optional return URL after payment (for redirects)
475
+ * @param props.submitButtonText - Custom text for submit button (default: 'Pay Now')
476
+ * @param props.className - Custom CSS class for the form container
477
+ * @param props.buttonClassName - Custom CSS class for the submit button
293
478
  *
294
479
  * @example
295
480
  * ```tsx
296
481
  * import { PaymentForm } from '@solvapay/react';
482
+ * import { useRouter } from 'next/navigation';
297
483
  *
298
- * <PaymentForm
299
- * planRef="pro_plan"
300
- * agentRef="agent_123"
301
- * onSuccess={(paymentIntent) => {
302
- * console.log('Payment successful!');
303
- * }}
304
- * onError={(error) => {
305
- * console.error('Payment failed:', error);
306
- * }}
307
- * />
484
+ * function CheckoutPage() {
485
+ * const router = useRouter();
486
+ *
487
+ * return (
488
+ * <PaymentForm
489
+ * planRef="pln_premium"
490
+ * productRef="prd_myapi"
491
+ * onSuccess={() => {
492
+ * console.log('Payment successful!');
493
+ * router.push('/dashboard');
494
+ * }}
495
+ * onError={(error) => {
496
+ * console.error('Payment failed:', error);
497
+ * }}
498
+ * />
499
+ * );
500
+ * }
308
501
  * ```
502
+ *
503
+ * @see {@link useCheckout} for programmatic checkout handling
504
+ * @see {@link SolvaPayProvider} for required context provider
505
+ * @since 1.0.0
309
506
  */
310
507
  declare const PaymentForm: React$1.FC<PaymentFormProps>;
311
508
 
312
509
  /**
313
- * Headless Plan Badge Component
510
+ * Headless Product Badge Component
314
511
  *
315
- * Displays subscription status with complete styling control.
512
+ * Displays purchase status with complete styling control.
316
513
  * Supports render props, custom components, or className patterns.
317
514
  *
318
- * Prevents flickering by hiding the badge during initial load and when no subscription exists.
319
- * Only shows the badge once loading completes AND a subscription value is available.
320
- * Badge only updates when the plan name actually changes (prevents unnecessary re-renders).
515
+ * Hidden while loading or when no active purchase exists to prevent flickering.
321
516
  *
322
517
  * @example
323
518
  * ```tsx
324
519
  * // Render prop pattern
325
- * <PlanBadge>
326
- * {({ subscriptions, loading, displayPlan, shouldShow }) => (
520
+ * <ProductBadge>
521
+ * {({ purchases, loading, displayPlan, shouldShow }) => (
327
522
  * shouldShow ? (
328
523
  * <div>{displayPlan}</div>
329
524
  * ) : null
330
525
  * )}
331
- * </PlanBadge>
526
+ * </ProductBadge>
332
527
  *
333
- * //ClassName pattern
334
- * <PlanBadge className="badge badge-primary" />
528
+ * // ClassName pattern
529
+ * <ProductBadge className="badge badge-primary" />
335
530
  * ```
336
531
  */
337
- declare const PlanBadge: React$1.FC<PlanBadgeProps>;
532
+ declare const ProductBadge: React$1.FC<ProductBadgeProps>;
533
+ /** @deprecated Use ProductBadge instead */
534
+ declare const PlanBadge: React$1.FC<ProductBadgeProps>;
338
535
 
339
536
  /**
340
- * Headless Subscription Gate Component
537
+ * Headless Purchase Gate Component
341
538
  *
342
- * Controls access to content based on subscription status.
539
+ * Controls access to content based on purchase status.
343
540
  * Uses render props to give developers full control over locked/unlocked states.
344
541
  *
345
542
  * @example
346
543
  * ```tsx
347
- * <SubscriptionGate requirePlan="Pro Plan">
544
+ * <PurchaseGate requireProduct="Pro Plan">
348
545
  * {({ hasAccess, loading }) => {
349
546
  * if (loading) return <Skeleton />;
350
547
  * if (!hasAccess) return <Paywall />;
351
548
  * return <PremiumContent />;
352
549
  * }}
353
- * </SubscriptionGate>
550
+ * </PurchaseGate>
354
551
  * ```
355
552
  */
356
- declare const SubscriptionGate: React$1.FC<SubscriptionGateProps>;
553
+ declare const PurchaseGate: React$1.FC<PurchaseGateProps>;
357
554
 
358
555
  /**
359
- * Headless Plan Selector Component
556
+ * Headless Pricing Selector Component
360
557
  *
361
- * Provides plan selection logic with complete styling control via render props.
362
- * Integrates plan fetching, subscription status, and selection state management.
558
+ * Provides pricing selection logic with complete styling control via render props.
559
+ * Integrates plan fetching, purchase status, and selection state management.
363
560
  *
364
561
  * Features:
365
- * - Fetches and manages plans
366
- * - Tracks selected plan
367
- * - Provides helpers for checking if plan is current/paid
368
- * - Integrates with subscription context
562
+ * - Fetches and manages pricing options
563
+ * - Tracks selected option
564
+ * - Provides helpers for checking if option is current/paid
565
+ * - Integrates with purchase context
369
566
  *
370
567
  * @example
371
568
  * ```tsx
372
- * <PlanSelector
373
- * agentRef="agent_123"
374
- * fetcher={async (agentRef) => {
375
- * const res = await fetch(`/api/list-plans?agentRef=${agentRef}`);
569
+ * <PricingSelector
570
+ * productRef="prd_123"
571
+ * fetcher={async (productRef) => {
572
+ * const res = await fetch(`/api/list-plans?productRef=${productRef}`);
376
573
  * const data = await res.json();
377
574
  * return data.plans;
378
575
  * }}
@@ -382,28 +579,31 @@ declare const SubscriptionGate: React$1.FC<SubscriptionGateProps>;
382
579
  * {({ plans, selectedPlan, setSelectedPlanIndex, loading, isPaidPlan, isCurrentPlan }) => (
383
580
  * <div>
384
581
  * {loading ? (
385
- * <div>Loading plans...</div>
582
+ * <div>Loading...</div>
386
583
  * ) : (
387
584
  * plans.map((plan, index) => (
388
585
  * <button
389
586
  * key={plan.reference}
390
587
  * onClick={() => setSelectedPlanIndex(index)}
391
- * disabled={!isPaidPlan(plan.name)}
588
+ * disabled={!isPaidPlan(plan.reference)}
392
589
  * >
393
- * {plan.name} - ${plan.price}
394
- * {isCurrentPlan(plan.name) && ' (Current)'}
590
+ * ${plan.price}/{plan.interval}
591
+ * {isCurrentPlan(plan.reference) && ' (Current)'}
395
592
  * </button>
396
593
  * ))
397
594
  * )}
398
595
  * </div>
399
596
  * )}
400
- * </PlanSelector>
597
+ * </PricingSelector>
401
598
  * ```
402
599
  */
403
- declare const PlanSelector: React$1.FC<PlanSelectorProps>;
600
+ declare const PricingSelector: React$1.FC<PricingSelectorProps>;
601
+ /** @deprecated Use PricingSelector instead */
602
+ declare const PlanSelector: React$1.FC<PricingSelectorProps>;
404
603
 
405
604
  /**
406
- * Simple spinner component using CSS animations
605
+ * SVG-based spinner component using CSS animations
606
+ * Uses the same spinner design as the rest of the site
407
607
  */
408
608
  declare const Spinner: React$1.FC<{
409
609
  className?: string;
@@ -411,11 +611,12 @@ declare const Spinner: React$1.FC<{
411
611
  }>;
412
612
 
413
613
  interface StripePaymentFormWrapperProps {
414
- onSuccess?: (paymentIntent: any) => void;
614
+ onSuccess?: (paymentIntent: unknown) => void | Promise<void>;
415
615
  onError?: (error: Error) => void;
416
616
  returnUrl?: string;
417
617
  submitButtonText?: string;
418
618
  buttonClassName?: string;
619
+ clientSecret: string;
419
620
  }
420
621
  /**
421
622
  * Stripe Payment Form Wrapper Component
@@ -425,13 +626,93 @@ interface StripePaymentFormWrapperProps {
425
626
  declare const StripePaymentFormWrapper: React$1.FC<StripePaymentFormWrapperProps>;
426
627
 
427
628
  /**
428
- * Hook to access subscription status
429
- * Returns the current subscription state and a refetch function
629
+ * Hook to get current purchase status and information.
630
+ *
631
+ * Returns the current user's purchase status, including active
632
+ * purchases, plan details, and payment information. Automatically
633
+ * syncs with the SolvaPay backend and handles loading and error states.
634
+ *
635
+ * @returns Purchase data and status
636
+ * @returns purchases - Array of active purchases
637
+ * @returns hasPaidPurchase - Whether user has any paid purchase
638
+ * @returns isLoading - Loading state
639
+ * @returns error - Error state if purchase check fails
640
+ * @returns refetch - Function to manually refetch purchase data
641
+ *
642
+ * @example
643
+ * ```tsx
644
+ * import { usePurchase } from '@solvapay/react';
645
+ *
646
+ * function Dashboard() {
647
+ * const { purchases, hasPaidPurchase, isLoading, refetch } = usePurchase();
648
+ *
649
+ * if (isLoading) return <Spinner />;
650
+ *
651
+ * if (!hasPaidPurchase) {
652
+ * return <UpgradePrompt />;
653
+ * }
654
+ *
655
+ * return (
656
+ * <div>
657
+ * <h2>Welcome, Premium User!</h2>
658
+ * <p>Active purchases: {purchases.length}</p>
659
+ * <button onClick={() => refetch()}>Refresh</button>
660
+ * </div>
661
+ * );
662
+ * }
663
+ * ```
664
+ *
665
+ * @see {@link SolvaPayProvider} for required context provider
666
+ * @see {@link usePurchaseStatus} for detailed status information
667
+ * @since 1.0.0
430
668
  */
431
- declare function useSubscription(): SubscriptionStatus & {
669
+ declare function usePurchase(): PurchaseStatus & {
432
670
  refetch: () => Promise<void>;
433
671
  };
434
672
 
673
+ /**
674
+ * Customer information interface
675
+ */
676
+ interface CustomerInfo {
677
+ /**
678
+ * Customer reference ID
679
+ */
680
+ customerRef?: string;
681
+ /**
682
+ * Customer email address
683
+ */
684
+ email?: string;
685
+ /**
686
+ * Customer name
687
+ */
688
+ name?: string;
689
+ /**
690
+ * Whether customer data is currently loading
691
+ */
692
+ loading: boolean;
693
+ }
694
+ /**
695
+ * Hook to access customer information
696
+ * Returns customer data (email, name, customerRef) separate from purchase data
697
+ *
698
+ * @example
699
+ * ```tsx
700
+ * import { useCustomer } from '@solvapay/react';
701
+ *
702
+ * function MyComponent() {
703
+ * const { email, name, customerRef } = useCustomer();
704
+ *
705
+ * return (
706
+ * <div>
707
+ * <p>Email: {email || 'Not provided'}</p>
708
+ * <p>Name: {name || 'Not provided'}</p>
709
+ * </div>
710
+ * );
711
+ * }
712
+ * ```
713
+ */
714
+ declare function useCustomer(): CustomerInfo;
715
+
435
716
  interface UseCheckoutReturn {
436
717
  loading: boolean;
437
718
  error: Error | null;
@@ -441,31 +722,115 @@ interface UseCheckoutReturn {
441
722
  reset: () => void;
442
723
  }
443
724
  /**
444
- * Hook to manage checkout flow
445
- * Handles payment intent creation and Stripe initialization
725
+ * Hook to manage checkout flow for payment processing.
726
+ *
727
+ * Handles payment intent creation and Stripe initialization. This hook
728
+ * manages the checkout state including loading, errors, Stripe instance,
729
+ * and client secret. Use this for programmatic checkout flows.
730
+ *
731
+ * @param options - Checkout options
732
+ * @param options.planRef - Plan reference to purchase (required)
733
+ * @param options.productRef - Optional product reference for usage tracking
734
+ * @returns Checkout state and methods
735
+ * @returns loading - Whether checkout is in progress
736
+ * @returns error - Error state if checkout fails
737
+ * @returns stripePromise - Promise resolving to Stripe instance
738
+ * @returns clientSecret - Stripe payment intent client secret
739
+ * @returns startCheckout - Function to start the checkout process
740
+ * @returns reset - Function to reset checkout state
741
+ *
742
+ * @example
743
+ * ```tsx
744
+ * import { useCheckout } from '@solvapay/react';
745
+ * import { PaymentElement } from '@stripe/react-stripe-js';
746
+ *
747
+ * function CustomCheckout() {
748
+ * const { loading, error, stripePromise, clientSecret, startCheckout } = useCheckout({
749
+ * planRef: 'pln_premium',
750
+ * productRef: 'prd_myapi',
751
+ * });
752
+ *
753
+ * useEffect(() => {
754
+ * startCheckout();
755
+ * }, []);
446
756
  *
447
- * @param planRef - The plan reference to checkout
757
+ * if (loading) return <Spinner />;
758
+ * if (error) return <div>Error: {error.message}</div>;
759
+ * if (!clientSecret || !stripePromise) return null;
760
+ *
761
+ * return (
762
+ * <Elements stripe={await stripePromise} options={{ clientSecret }}>
763
+ * <PaymentElement />
764
+ * </Elements>
765
+ * );
766
+ * }
767
+ * ```
768
+ *
769
+ * @see {@link PaymentForm} for a complete payment form component
770
+ * @see {@link SolvaPayProvider} for required context provider
771
+ * @since 1.0.0
448
772
  */
449
- declare function useCheckout(planRef: string): UseCheckoutReturn;
773
+ declare function useCheckout(options: {
774
+ planRef: string;
775
+ productRef?: string;
776
+ }): UseCheckoutReturn;
450
777
 
451
778
  /**
452
- * Hook to access SolvaPay context
453
- * Must be used within a SolvaPayProvider
779
+ * Hook to access SolvaPay context and provider methods.
780
+ *
781
+ * This is the base hook that provides access to all SolvaPay functionality
782
+ * including purchase data, payment methods, and customer information.
783
+ * Other hooks like `usePurchase` and `useCheckout` use this internally.
784
+ *
785
+ * Must be used within a `SolvaPayProvider` component.
786
+ *
787
+ * @returns SolvaPay context value with all provider methods and state
788
+ * @returns purchase - Purchase status and data
789
+ * @returns createPayment - Function to create payment intents
790
+ * @returns processPayment - Function to process payments
791
+ * @returns customerRef - Current customer reference
792
+ * @returns refetchPurchase - Function to refetch purchase data
793
+ *
794
+ * @example
795
+ * ```tsx
796
+ * import { useSolvaPay } from '@solvapay/react';
797
+ *
798
+ * function CustomComponent() {
799
+ * const { purchase, createPayment, processPayment } = useSolvaPay();
800
+ *
801
+ * const handlePayment = async () => {
802
+ * const intent = await createPayment({
803
+ * planRef: 'pln_premium',
804
+ * productRef: 'prd_myapi'
805
+ * });
806
+ * // Process payment...
807
+ * };
808
+ *
809
+ * return <div>Purchase status: {purchase.hasPaidPurchase ? 'Active' : 'None'}</div>;
810
+ * }
811
+ * ```
812
+ *
813
+ * @throws {Error} If used outside of SolvaPayProvider
814
+ * @see {@link SolvaPayProvider} for required context provider
815
+ * @see {@link usePurchase} for purchase-specific hook
816
+ * @see {@link useCheckout} for checkout-specific hook
817
+ * @since 1.0.0
454
818
  */
455
819
  declare function useSolvaPay(): SolvaPayContextValue;
456
820
 
457
821
  /**
458
822
  * Hook to manage plan fetching and selection
459
823
  *
460
- * Provides a reusable way to fetch, filter, sort and select subscription plans.
824
+ * Provides a reusable way to fetch, filter, sort and select plans.
461
825
  * Handles loading and error states automatically.
826
+ * Uses a global cache to prevent duplicate fetches when multiple components use the same productRef.
462
827
  *
463
828
  * @example
464
829
  * ```tsx
465
830
  * const plans = usePlans({
466
- * agentRef: 'agent_123',
467
- * fetcher: async (agentRef) => {
468
- * const res = await fetch(`/api/list-plans?agentRef=${agentRef}`);
831
+ * productRef: 'prd_123',
832
+ * fetcher: async (productRef) => {
833
+ * const res = await fetch(`/api/list-plans?productRef=${productRef}`);
469
834
  * const data = await res.json();
470
835
  * return data.plans;
471
836
  * },
@@ -481,74 +846,78 @@ declare function useSolvaPay(): SolvaPayContextValue;
481
846
  declare function usePlans(options: UsePlansOptions): UsePlansReturn;
482
847
 
483
848
  /**
484
- * Hook providing helper functions for subscription management
849
+ * Hook providing advanced status and helper functions for purchase management
485
850
  *
486
- * Provides utilities for checking subscription status, formatting dates,
487
- * and working with paid vs free plans.
488
- *
489
- * @param plans - Array of available plans to determine if a subscription is paid
851
+ * Focuses on cancelled purchase logic and date formatting utilities.
852
+ * For basic purchase data and paid status checks, use usePurchase() instead.
490
853
  *
491
854
  * @example
492
855
  * ```tsx
493
- * const helpers = useSubscriptionHelpers(plans);
856
+ * const { cancelledPurchase, shouldShowCancelledNotice, formatDate, getDaysUntilExpiration } = usePurchaseStatus();
494
857
  *
495
- * if (helpers.isPaidPlan('Pro Plan')) {
496
- * // Handle paid plan
858
+ * if (shouldShowCancelledNotice && cancelledPurchase) {
859
+ * const formattedDate = formatDate(cancelledPurchase.endDate);
860
+ * const daysLeft = getDaysUntilExpiration(cancelledPurchase.endDate);
497
861
  * }
498
- *
499
- * const daysLeft = helpers.getDaysUntilExpiration(subscription.endDate);
500
862
  * ```
501
863
  */
502
- declare function useSubscriptionHelpers(plans: Plan[]): SubscriptionHelpersReturn;
864
+ declare function usePurchaseStatus(): PurchaseStatusReturn;
503
865
 
504
866
  /**
505
- * Subscription utility functions
867
+ * Purchase utility functions
506
868
  *
507
- * Provides shared logic for filtering and prioritizing subscriptions
869
+ * Provides shared logic for filtering and prioritizing purchases
508
870
  */
509
871
 
510
872
  /**
511
- * Filter subscriptions based on cancellation status and endDate
873
+ * Filter purchases to only include active ones
512
874
  *
513
875
  * Rules:
514
- * - Keep all non-cancelled subscriptions
515
- * - A subscription is considered cancelled if:
516
- * 1. status === 'cancelled', OR
517
- * 2. cancelledAt is set (even if status is still 'active' - this is expected behavior)
518
- * - Keep cancelled subscriptions only if they have an endDate in the future
519
- * (meaning the subscription is cancelled but still active until the endDate)
520
- * - Filter out cancelled subscriptions without endDate or with past endDate
876
+ * - Keep purchases with status === 'active'
877
+ * - Filter out purchases with status === 'cancelled', 'expired', 'suspended', 'refunded', etc.
878
+ *
879
+ * Note: Backend now keeps purchases with status 'active' until expiration,
880
+ * even when cancelled. Cancellation is tracked via cancelledAt field.
521
881
  */
522
- declare function filterSubscriptions(subscriptions: SubscriptionInfo[]): SubscriptionInfo[];
882
+ declare function filterPurchases(purchases: PurchaseInfo[]): PurchaseInfo[];
523
883
  /**
524
- * Get active subscriptions (excluding cancelled ones)
525
- * Also excludes subscriptions with cancelledAt set, even if status is still 'active'
884
+ * Get active purchases
885
+ *
886
+ * Returns purchases with status === 'active'.
887
+ * Note: Backend keeps purchases as 'active' until expiration, even when cancelled.
888
+ * Use cancelledAt field to check if a purchase is cancelled.
526
889
  */
527
- declare function getActiveSubscriptions(subscriptions: SubscriptionInfo[]): SubscriptionInfo[];
890
+ declare function getActivePurchases(purchases: PurchaseInfo[]): PurchaseInfo[];
528
891
  /**
529
- * Get cancelled subscriptions with valid endDate (not expired)
530
- * Includes subscriptions with cancelledAt set, even if status is still 'active'
892
+ * Get cancelled purchases with valid endDate (not expired)
893
+ *
894
+ * Returns purchases with cancelledAt set and status === 'active' that have a future endDate.
895
+ * Backend keeps cancelled purchases as 'active' until expiration.
531
896
  */
532
- declare function getCancelledSubscriptionsWithEndDate(subscriptions: SubscriptionInfo[]): SubscriptionInfo[];
897
+ declare function getCancelledPurchasesWithEndDate(purchases: PurchaseInfo[]): PurchaseInfo[];
533
898
  /**
534
- * Get the most recent subscription by startDate
899
+ * Get the most recent purchase by startDate
535
900
  */
536
- declare function getMostRecentSubscription(subscriptions: SubscriptionInfo[]): SubscriptionInfo | null;
901
+ declare function getMostRecentPurchase(purchases: PurchaseInfo[]): PurchaseInfo | null;
537
902
  /**
538
- * Get the primary subscription to display
903
+ * Get the primary purchase to display
539
904
  *
540
905
  * Prioritization:
541
- * 1. Active subscriptions (most recent by startDate)
542
- * 2. Cancelled subscriptions with endDate in the future (most recent by startDate)
543
- * 3. null if no valid subscriptions
906
+ * 1. Active purchases (most recent by startDate)
907
+ * 2. null if no valid purchases
908
+ *
909
+ * Note: Backend keeps purchases as 'active' until expiration, so we only
910
+ * need to check for active purchases. Cancelled purchases are still
911
+ * active until their endDate.
544
912
  */
545
- declare function getPrimarySubscription(subscriptions: SubscriptionInfo[]): SubscriptionInfo | null;
913
+ declare function getPrimaryPurchase(purchases: PurchaseInfo[]): PurchaseInfo | null;
546
914
  /**
547
- * Check if user has an active paid subscription
915
+ * Check if a purchase is paid
916
+ * Uses purchase amount field: amount > 0 = paid, amount === 0 or undefined = free
548
917
  *
549
- * @param subscriptions - Array of subscriptions
550
- * @param isPaidPlan - Function to check if a plan name represents a paid plan
918
+ * @param purchase - Purchase to check
919
+ * @returns true if purchase is paid (amount > 0)
551
920
  */
552
- declare function hasActivePaidSubscription(subscriptions: SubscriptionInfo[], isPaidPlan: (planName: string) => boolean): boolean;
921
+ declare function isPaidPurchase(purchase: PurchaseInfo): boolean;
553
922
 
554
- export { type CustomerSubscriptionData, type PaymentError, PaymentForm, type PaymentFormProps, type PaymentIntentResult, type Plan, PlanBadge, type PlanBadgeProps, PlanSelector, type PlanSelectorProps, type SolvaPayContextValue, SolvaPayProvider, type SolvaPayProviderProps, Spinner, StripePaymentFormWrapper, SubscriptionGate, type SubscriptionGateProps, type SubscriptionHelpersReturn, type SubscriptionInfo, type SubscriptionStatus, type UsePlansOptions, type UsePlansReturn, filterSubscriptions, getActiveSubscriptions, getCancelledSubscriptionsWithEndDate, getMostRecentSubscription, getPrimarySubscription, hasActivePaidSubscription, useCheckout, usePlans, useSolvaPay, useSubscription, useSubscriptionHelpers };
923
+ export { AuthAdapter, type CustomerInfo, type CustomerPurchaseData, type PaymentError, PaymentForm, type PaymentFormProps, type PaymentIntentResult, type Plan, PlanBadge, type PlanBadgeProps, PlanSelector, type PlanSelectorProps, PricingSelector, type PricingSelectorProps, ProductBadge, type ProductBadgeProps, PurchaseGate, type PurchaseGateProps, type PurchaseInfo, type PurchaseStatus, type PurchaseStatusReturn, type PurchaseStatusValue, type SolvaPayConfig, type SolvaPayContextValue, SolvaPayProvider, type SolvaPayProviderProps, Spinner, StripePaymentFormWrapper, type UsePlansOptions, type UsePlansReturn, filterPurchases, getActivePurchases, getCancelledPurchasesWithEndDate, getMostRecentPurchase, getPrimaryPurchase, isPaidPurchase, useCheckout, useCustomer, usePlans, usePurchase, usePurchaseStatus, useSolvaPay };