@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/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
- amount?: number;
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
- agentRef: string;
10
- apiBaseUrl?: string;
11
- onPaymentReady?: (stripe: Stripe | null, clientSecret: string) => void;
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 Payment Provider Component
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
- * Wraps children with Stripe Elements context after initializing a payment intent
17
- * via the backend API. This component handles the secure payment flow:
350
+ * @example
351
+ * ```tsx
352
+ * // Zero config (uses defaults)
353
+ * <SolvaPayProvider>
354
+ * <App />
355
+ * </SolvaPayProvider>
18
356
  *
19
- * 1. Calls backend API route to create payment intent (backend uses secret key)
20
- * 2. Backend returns clientSecret and publishableKey from Stripe
21
- * 3. Initializes Stripe.js with publishableKey
22
- * 4. Wraps children in Stripe Elements provider
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
- * // In your Next.js page
27
- * import { SolvaPayProvider, PaymentForm } from '@solvapay/react';
392
+ * import { PaymentForm } from '@solvapay/react';
28
393
  *
29
- * export default function CheckoutPage() {
30
- * return (
31
- * <SolvaPayProvider
32
- * amount={999}
33
- * currency="USD"
34
- * planRef="pln_abc123"
35
- * agentRef="agt_xyz789"
36
- * onPaymentReady={(stripe, clientSecret) => {
37
- * console.log('Payment ready!');
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 SolvaPayProvider: React.FC<SolvaPayProviderProps>;
406
+ declare const PaymentForm: React$1.FC<PaymentFormProps>;
47
407
 
48
- interface PaymentFormProps {
49
- onSuccess?: (paymentIntent: any) => void;
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
- className?: string;
517
+ buttonClassName?: string;
518
+ clientSecret: string;
54
519
  }
55
520
  /**
56
- * SolvaPay Payment Form Component
57
- *
58
- * Renders a payment form using Stripe's PaymentElement for secure card input.
59
- * This component must be wrapped in a SolvaPayProvider to work properly.
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 { SolvaPayProvider, PaymentForm } from '@solvapay/react';
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
- * <SolvaPayProvider amount={999} planRef="pln_abc123">
68
- * <PaymentForm
69
- * returnUrl={`${window.location.origin}/checkout/success`}
70
- * onSuccess={(paymentIntent) => {
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 const PaymentForm: React.FC<PaymentFormProps>;
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 };