@billingos/sdk 0.1.2 → 0.1.5
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 +3118 -0
- package/dist/index.d.ts +3118 -3346
- package/dist/index.js +7477 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4876 -3875
- package/dist/index.mjs.map +1 -1
- package/package.json +17 -15
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/client/errors.ts","../src/client/index.ts","../src/hooks/useSessionToken.ts","../src/providers/BillingOSProvider.tsx","../src/hooks/useSubscription.ts","../src/utils/cn.ts","../src/components/ui/dialog.tsx","../src/components/CheckoutModal/CheckoutIframe.tsx","../src/components/CheckoutModal/hooks/useCheckoutSession.ts","../src/components/CheckoutModal/utils/security.ts","../src/components/CheckoutModal/hooks/useIframeMessaging.ts","../src/components/CheckoutModal/CheckoutModal.tsx","../src/checkout.ts","../src/hooks/useCheckout.ts","../src/hooks/useEntitlements.ts","../src/hooks/useFeature.ts","../src/hooks/useProducts.ts","../src/components/ui/alert.tsx","../src/components/ui/badge.tsx","../src/components/ui/button.tsx","../src/components/ui/card.tsx","../src/components/ui/checkbox.tsx","../src/components/ui/drawer.tsx","../src/components/ui/input.tsx","../src/components/ui/label.tsx","../src/components/ui/progress.tsx","../src/components/ui/radio-group.tsx","../src/components/ui/scroll-area.tsx","../src/components/ui/select.tsx","../src/components/ui/separator.tsx","../src/components/ui/sheet.tsx","../src/components/ui/skeleton.tsx","../src/components/ui/tabs.tsx","../src/components/ui/textarea.tsx","../src/components/CustomerPortal/PortalIframe.tsx","../src/components/CustomerPortal/hooks/usePortalSession.ts","../src/components/CustomerPortal/hooks/usePortalMessaging.ts","../src/components/ui/table.tsx","../src/components/PricingTable/hooks/useProducts.ts","../src/components/ErrorBoundary.tsx","../src/components/PaymentBottomSheet/hooks/useCheckout.ts","../src/components/PaymentBottomSheet/PaymentForm.tsx","../src/components/PaymentBottomSheet/DemoPaymentForm.tsx","../src/config/stripe.ts","../src/components/PaymentBottomSheet/PaymentBottomSheet.tsx","../src/components/PricingTable/PricingTable.tsx","../src/components/PricingTable/PricingCard.tsx","../src/components/CustomerPortal/CustomerPortal.tsx","../src/components/CustomerPortal/hooks/usePortalData.ts","../src/components/CustomerPortal/components/UsageBar.tsx","../src/components/CustomerPortal/components/FeatureList.tsx","../src/components/CustomerPortal/components/WarningBanner.tsx","../src/utils/money.ts","../src/components/CustomerPortal/tabs/SubscriptionTab.tsx","../src/components/CustomerPortal/components/InvoiceCard.tsx","../src/components/CustomerPortal/tabs/InvoicesTab.tsx","../src/components/CustomerPortal/components/PaymentMethodCard.tsx","../src/components/CustomerPortal/tabs/PaymentMethodsTab.tsx","../src/components/CustomerPortal/tabs/SettingsTab.tsx","../src/components/CustomerPortal/components/ProrationPreview.tsx","../src/components/CustomerPortal/modals/ChangePlanModal.tsx","../src/components/CustomerPortal/modals/CancelSubscriptionModal.tsx","../src/components/CustomerPortal/modals/AddPaymentMethodModal.tsx","../src/components/UpgradeNudge/BannerNudge.tsx","../src/components/UpgradeNudge/ToastNudge.tsx","../src/components/UpgradeNudge/ModalNudge.tsx","../src/components/UpgradeNudge/UpgradeNudge.tsx","../src/components/UpgradeNudge/hooks/useUsageCheck.ts","../src/components/FeatureGate/FeatureGate.tsx","../src/components/UsageDisplay/UsageDisplay.tsx","../src/components/UpgradePrompt/UpgradePrompt.tsx","../src/utils/date.ts","../src/index.ts"],"sourcesContent":["/**\n * Base error class for all BillingOS SDK errors\n */\nexport class BillingOSError extends Error {\n constructor(\n message: string,\n public status?: number,\n public data?: unknown\n ) {\n super(message)\n this.name = 'BillingOSError'\n Object.setPrototypeOf(this, BillingOSError.prototype)\n }\n}\n\n/**\n * Thrown when the API request fails due to authentication issues (401)\n */\nexport class UnauthorizedError extends BillingOSError {\n constructor(message = 'Unauthorized: Invalid or missing API key', data?: unknown) {\n super(message, 401, data)\n this.name = 'UnauthorizedError'\n Object.setPrototypeOf(this, UnauthorizedError.prototype)\n }\n}\n\n/**\n * Thrown when the requested resource is not found (404)\n */\nexport class NotFoundError extends BillingOSError {\n constructor(message = 'Resource not found', data?: unknown) {\n super(message, 404, data)\n this.name = 'NotFoundError'\n Object.setPrototypeOf(this, NotFoundError.prototype)\n }\n}\n\n/**\n * Thrown when the request fails validation (400)\n */\nexport class ValidationError extends BillingOSError {\n constructor(message = 'Validation failed', data?: unknown) {\n super(message, 400, data)\n this.name = 'ValidationError'\n Object.setPrototypeOf(this, ValidationError.prototype)\n }\n}\n\n/**\n * Thrown when rate limit is exceeded (429)\n */\nexport class RateLimitError extends BillingOSError {\n constructor(message = 'Too many requests', data?: unknown) {\n super(message, 429, data)\n this.name = 'RateLimitError'\n Object.setPrototypeOf(this, RateLimitError.prototype)\n }\n}\n\n/**\n * Thrown when the server returns a 500 error\n */\nexport class ServerError extends BillingOSError {\n constructor(message = 'Internal server error', data?: unknown) {\n super(message, 500, data)\n this.name = 'ServerError'\n Object.setPrototypeOf(this, ServerError.prototype)\n }\n}\n\n/**\n * Thrown when the network request fails\n */\nexport class NetworkError extends BillingOSError {\n constructor(message = 'Network request failed', originalError?: unknown) {\n super(message, undefined, originalError)\n this.name = 'NetworkError'\n Object.setPrototypeOf(this, NetworkError.prototype)\n }\n}\n\n/**\n * Type guard to check if an error is a validation error\n */\nexport function isValidationError(error: unknown): error is ValidationError {\n return error instanceof ValidationError\n}\n\n/**\n * Type guard to check if an error is an unauthorized error\n */\nexport function isUnauthorizedError(error: unknown): error is UnauthorizedError {\n return error instanceof UnauthorizedError\n}\n\n/**\n * Type guard to check if an error is a not found error\n */\nexport function isNotFoundError(error: unknown): error is NotFoundError {\n return error instanceof NotFoundError\n}\n\n/**\n * Type guard to check if an error is a rate limit error\n */\nexport function isRateLimitError(error: unknown): error is RateLimitError {\n return error instanceof RateLimitError\n}\n","import {\n BillingOSError,\n UnauthorizedError,\n NotFoundError,\n ValidationError,\n RateLimitError,\n ServerError,\n NetworkError,\n} from './errors'\nimport type {\n Customer,\n CreateCustomerInput,\n UpdateCustomerInput,\n Subscription,\n CreateSubscriptionInput,\n UpdateSubscriptionInput,\n SubscriptionPreview,\n Entitlement,\n CheckEntitlementInput,\n UsageEvent,\n UsageMetrics,\n Invoice,\n PaymentMethod,\n PaginatedResponse,\n APIErrorResponse,\n // Portal types\n CustomerPortalData,\n PortalUpdateSubscriptionInput,\n PortalUpdateSubscriptionResponse,\n PortalCancelSubscriptionInput,\n PortalCancelSubscriptionResponse,\n AddPaymentMethodInput,\n AddPaymentMethodResponse,\n SetupIntentResponse,\n RetryInvoiceResponse,\n UpdateCustomerBillingInput,\n CustomerBillingInfo,\n AvailablePlansResponse,\n PreviewChangeInput,\n PreviewChangeResponse,\n ChangePlanInput,\n ChangePlanResponse,\n // Checkout types\n CreateCheckoutInput,\n CreateCheckoutResponse,\n ConfirmCheckoutResponse,\n // Checkout Modal types\n CreateCheckoutSessionInput,\n CreateCheckoutSessionResponse,\n CheckoutSessionDetails,\n // Pricing table types\n GetProductsResponse,\n // Upgrade nudge types\n UsageCheckResponse,\n} from './types'\n\nexport * from './types'\nexport * from './errors'\n\n/**\n * Configuration options for the BillingOS client\n */\nexport interface BillingOSClientOptions {\n /**\n * Base URL for the API (defaults to production)\n */\n baseUrl?: string\n\n /**\n * Environment (production or sandbox)\n */\n environment?: 'production' | 'sandbox'\n\n /**\n * API version to use\n */\n version?: string\n\n /**\n * Custom headers to include in all requests\n */\n headers?: Record<string, string>\n\n /**\n * Timeout for requests in milliseconds\n */\n timeout?: number\n}\n\n/**\n * Main BillingOS API client\n */\nexport class BillingOSClient {\n private sessionToken: string\n private baseUrl: string\n private headers: Record<string, string>\n private timeout: number\n\n constructor(sessionToken: string, options: BillingOSClientOptions = {}) {\n if (!sessionToken) {\n throw new Error('Session token is required')\n }\n\n this.sessionToken = sessionToken\n this.timeout = options.timeout || 30000\n\n // Set base URL based on environment\n if (options.baseUrl) {\n this.baseUrl = options.baseUrl\n } else if (options.environment === 'sandbox') {\n this.baseUrl = 'https://sandbox.billingos.com/api'\n } else {\n this.baseUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001'\n }\n\n // Setup default headers\n this.headers = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.sessionToken}`,\n 'X-BillingOS-Version': options.version || '2026-01-01',\n ...options.headers,\n }\n }\n\n /**\n * Internal method to make HTTP requests\n */\n private async request<T>(\n path: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n ...this.headers,\n ...options.headers,\n },\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n // Handle 204 No Content\n if (response.status === 204) {\n return undefined as T\n }\n\n // Parse response\n const contentType = response.headers.get('content-type')\n const isJson = contentType?.includes('application/json')\n const data = isJson ? await response.json() : await response.text()\n\n // Handle errors\n if (!response.ok) {\n const errorData = isJson ? (data as APIErrorResponse) : { error: { message: data } }\n const errorMessage = errorData.error?.message || `Request failed with status ${response.status}`\n\n switch (response.status) {\n case 400:\n throw new ValidationError(errorMessage, errorData)\n case 401:\n throw new UnauthorizedError(errorMessage, errorData)\n case 404:\n throw new NotFoundError(errorMessage, errorData)\n case 429:\n throw new RateLimitError(errorMessage, errorData)\n case 500:\n case 502:\n case 503:\n case 504:\n throw new ServerError(errorMessage, errorData)\n default:\n throw new BillingOSError(errorMessage, response.status, errorData)\n }\n }\n\n return data as T\n } catch (error) {\n clearTimeout(timeoutId)\n\n if (error instanceof BillingOSError) {\n throw error\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new NetworkError('Request timeout')\n }\n\n throw new NetworkError('Network request failed', error)\n }\n }\n\n /**\n * GET request helper\n */\n get<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'GET' })\n }\n\n /**\n * POST request helper\n */\n post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, {\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n })\n }\n\n /**\n * PATCH request helper\n */\n patch<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, {\n method: 'PATCH',\n body: body ? JSON.stringify(body) : undefined,\n })\n }\n\n /**\n * DELETE request helper\n */\n delete<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'DELETE' })\n }\n\n // =============================================================================\n // CUSTOMERS API\n // =============================================================================\n\n /**\n * Create a new customer\n */\n async createCustomer(input: CreateCustomerInput): Promise<Customer> {\n return this.post<Customer>('/customers', input)\n }\n\n /**\n * Get a customer by ID\n */\n async getCustomer(id: string): Promise<Customer> {\n return this.get<Customer>(`/customers/${id}`)\n }\n\n /**\n * List customers (paginated)\n */\n async listCustomers(params?: {\n page?: number\n page_size?: number\n }): Promise<PaginatedResponse<Customer>> {\n const query = new URLSearchParams()\n if (params?.page) query.set('page', params.page.toString())\n if (params?.page_size) query.set('page_size', params.page_size.toString())\n\n const queryString = query.toString()\n return this.get<PaginatedResponse<Customer>>(\n `/customers${queryString ? `?${queryString}` : ''}`\n )\n }\n\n /**\n * Update a customer\n */\n async updateCustomer(id: string, input: UpdateCustomerInput): Promise<Customer> {\n return this.patch<Customer>(`/customers/${id}`, input)\n }\n\n /**\n * Delete a customer\n */\n async deleteCustomer(id: string): Promise<void> {\n return this.delete<void>(`/customers/${id}`)\n }\n\n // =============================================================================\n // SUBSCRIPTIONS API\n // =============================================================================\n\n /**\n * Create a new subscription\n */\n async createSubscription(input: CreateSubscriptionInput): Promise<Subscription> {\n return this.post<Subscription>('/subscriptions', input)\n }\n\n /**\n * Get a subscription by ID\n */\n async getSubscription(id: string): Promise<Subscription> {\n return this.get<Subscription>(`/subscriptions/${id}`)\n }\n\n /**\n * List subscriptions (paginated)\n */\n async listSubscriptions(params?: {\n customer_id?: string\n page?: number\n page_size?: number\n }): Promise<PaginatedResponse<Subscription>> {\n const query = new URLSearchParams()\n if (params?.customer_id) query.set('customer_id', params.customer_id)\n if (params?.page) query.set('page', params.page.toString())\n if (params?.page_size) query.set('page_size', params.page_size.toString())\n\n const queryString = query.toString()\n return this.get<PaginatedResponse<Subscription>>(\n `/subscriptions${queryString ? `?${queryString}` : ''}`\n )\n }\n\n /**\n * Update a subscription\n */\n async updateSubscription(\n id: string,\n input: UpdateSubscriptionInput\n ): Promise<Subscription> {\n return this.patch<Subscription>(`/subscriptions/${id}`, input)\n }\n\n /**\n * Cancel a subscription\n */\n async cancelSubscription(id: string, immediately = false): Promise<Subscription> {\n return this.post<Subscription>(`/subscriptions/${id}/cancel`, { immediately })\n }\n\n /**\n * Reactivate a canceled subscription\n */\n async reactivateSubscription(id: string): Promise<Subscription> {\n return this.post<Subscription>(`/subscriptions/${id}/reactivate`)\n }\n\n /**\n * Preview subscription changes\n */\n async previewSubscription(\n id: string,\n input: UpdateSubscriptionInput\n ): Promise<SubscriptionPreview> {\n return this.post<SubscriptionPreview>(`/subscriptions/${id}/preview`, input)\n }\n\n /**\n * Get available plans for upgrade/downgrade\n */\n async getAvailablePlans(subscriptionId: string): Promise<AvailablePlansResponse> {\n return this.get<AvailablePlansResponse>(`/subscriptions/${subscriptionId}/available-plans`)\n }\n\n /**\n * Preview a plan change (upgrade/downgrade) with proration details\n */\n async previewPlanChange(\n subscriptionId: string,\n input: PreviewChangeInput\n ): Promise<PreviewChangeResponse> {\n return this.post<PreviewChangeResponse>(`/subscriptions/${subscriptionId}/preview-change`, input)\n }\n\n /**\n * Execute a plan change (upgrade/downgrade)\n */\n async changePlan(\n subscriptionId: string,\n input: ChangePlanInput\n ): Promise<ChangePlanResponse> {\n return this.post<ChangePlanResponse>(`/subscriptions/${subscriptionId}/change-plan`, input)\n }\n\n // =============================================================================\n // ENTITLEMENTS API\n // =============================================================================\n\n /**\n * Check if a customer has access to a feature\n * Customer ID is resolved server-side from session token\n */\n async checkEntitlement(input: CheckEntitlementInput): Promise<Entitlement> {\n return this.get<Entitlement>(`/v1/features/check?feature_key=${encodeURIComponent(input.feature_key)}`)\n }\n\n /**\n * List all entitlements for a customer\n * Customer ID is resolved server-side from session token\n */\n async listEntitlements(_customerId?: string): Promise<Entitlement[]> {\n const response = await this.get<{ entitlements: Entitlement[] }>('/v1/features/entitlements')\n return response.entitlements\n }\n\n // =============================================================================\n // USAGE TRACKING API\n // =============================================================================\n\n /**\n * Track a usage event\n * Customer ID is resolved server-side from session token\n */\n async trackUsage(event: UsageEvent): Promise<void> {\n return this.post<void>('/v1/features/track-usage', {\n feature_key: event.feature_key,\n quantity: event.quantity,\n timestamp: event.timestamp,\n idempotency_key: event.idempotency_key,\n metadata: event.metadata,\n })\n }\n\n /**\n * Get usage metrics for a customer and feature\n * Customer ID is resolved server-side from session token\n */\n async getUsageMetrics(_customerId?: string, featureKey?: string): Promise<UsageMetrics> {\n const query = featureKey ? `?feature_key=${encodeURIComponent(featureKey)}` : ''\n const response = await this.get<{ metrics: UsageMetrics[] }>(`/v1/features/usage-metrics${query}`)\n return response.metrics?.[0] ?? { feature_key: featureKey || '', current_usage: 0, period_start: '', period_end: '' }\n }\n\n // =============================================================================\n // INVOICES API\n // =============================================================================\n\n /**\n * Get an invoice by ID\n */\n async getInvoice(id: string): Promise<Invoice> {\n return this.get<Invoice>(`/invoices/${id}`)\n }\n\n /**\n * List invoices for a customer\n */\n async listInvoices(params?: {\n customer_id?: string\n page?: number\n page_size?: number\n }): Promise<PaginatedResponse<Invoice>> {\n const query = new URLSearchParams()\n if (params?.customer_id) query.set('customer_id', params.customer_id)\n if (params?.page) query.set('page', params.page.toString())\n if (params?.page_size) query.set('page_size', params.page_size.toString())\n\n const queryString = query.toString()\n return this.get<PaginatedResponse<Invoice>>(\n `/invoices${queryString ? `?${queryString}` : ''}`\n )\n }\n\n // =============================================================================\n // PAYMENT METHODS API\n // =============================================================================\n\n /**\n * List payment methods for a customer\n */\n async listPaymentMethods(customerId: string): Promise<PaymentMethod[]> {\n return this.get<PaymentMethod[]>(`/payment-methods?customer_id=${customerId}`)\n }\n\n /**\n * Remove a payment method\n */\n async removePaymentMethod(id: string): Promise<void> {\n return this.delete<void>(`/payment-methods/${id}`)\n }\n\n /**\n * Set default payment method\n */\n async setDefaultPaymentMethod(id: string): Promise<void> {\n return this.post<void>(`/payment-methods/${id}/set-default`)\n }\n\n // =============================================================================\n // CUSTOMER PORTAL API\n // =============================================================================\n\n /**\n * Get all portal data for the current customer\n */\n async getCustomerPortal(): Promise<CustomerPortalData> {\n return this.get<CustomerPortalData>('/sdk/customer/portal')\n }\n\n /**\n * Update subscription (upgrade/downgrade)\n */\n async updatePortalSubscription(\n subscriptionId: string,\n input: PortalUpdateSubscriptionInput\n ): Promise<PortalUpdateSubscriptionResponse> {\n return this.post<PortalUpdateSubscriptionResponse>(\n `/sdk/subscriptions/${subscriptionId}/update`,\n input\n )\n }\n\n /**\n * Cancel subscription with feedback\n */\n async cancelPortalSubscription(\n subscriptionId: string,\n input: PortalCancelSubscriptionInput\n ): Promise<PortalCancelSubscriptionResponse> {\n return this.post<PortalCancelSubscriptionResponse>(\n `/sdk/subscriptions/${subscriptionId}/cancel`,\n input\n )\n }\n\n /**\n * Reactivate a canceled subscription\n */\n async reactivatePortalSubscription(subscriptionId: string): Promise<void> {\n return this.post<void>(`/sdk/subscriptions/${subscriptionId}/reactivate`)\n }\n\n /**\n * Add a payment method\n */\n async addPaymentMethod(input: AddPaymentMethodInput): Promise<AddPaymentMethodResponse> {\n return this.post<AddPaymentMethodResponse>('/sdk/payment-methods', input)\n }\n\n /**\n * Get setup intent for adding a new card\n */\n async getSetupIntent(): Promise<SetupIntentResponse> {\n return this.post<SetupIntentResponse>('/sdk/payment-methods/setup-intent')\n }\n\n /**\n * Retry a failed invoice\n */\n async retryInvoice(\n invoiceId: string,\n paymentMethodId?: string\n ): Promise<RetryInvoiceResponse> {\n return this.post<RetryInvoiceResponse>(`/sdk/invoices/${invoiceId}/retry`, {\n paymentMethodId,\n })\n }\n\n /**\n * Update customer billing information\n */\n async updateCustomerBilling(input: UpdateCustomerBillingInput): Promise<CustomerBillingInfo> {\n return this.patch<CustomerBillingInfo>('/sdk/customer/billing', input)\n }\n\n // =============================================================================\n // CHECKOUT API (Payment Bottom Sheet)\n // =============================================================================\n\n /**\n * Create a checkout session for purchasing a subscription\n */\n async createCheckout(input: CreateCheckoutInput): Promise<CreateCheckoutResponse> {\n return this.post<CreateCheckoutResponse>('/v1/checkout/create', input)\n }\n\n /**\n * Confirm a checkout after payment is processed\n */\n async confirmCheckout(\n clientSecret: string,\n paymentMethodId: string\n ): Promise<ConfirmCheckoutResponse> {\n return this.post<ConfirmCheckoutResponse>(\n `/v1/checkout/${clientSecret}/confirm`,\n { paymentMethodId }\n )\n }\n\n // =============================================================================\n // CHECKOUT MODAL API (Iframe-based checkout)\n // =============================================================================\n\n /**\n * Checkout API methods for iframe-based checkout modal\n */\n public checkout = {\n /**\n * Create a checkout session for iframe-based checkout\n */\n createSession: async (input: CreateCheckoutSessionInput): Promise<CreateCheckoutSessionResponse> => {\n // Log what we're sending\n console.log('[SDK Client] Creating checkout session with:', {\n priceId: input.priceId,\n customer: input.customer,\n hasEmail: !!input.customer?.email,\n hasName: !!input.customer?.name,\n })\n\n const response = await this.post<CreateCheckoutSessionResponse>('/v1/checkout/create', input)\n\n console.log('[SDK Client] Checkout session created:', {\n sessionId: response.id,\n status: response.status,\n })\n\n return response\n },\n\n /**\n * Get checkout session details\n */\n getSession: async (sessionId: string): Promise<CheckoutSessionDetails> => {\n return this.get<CheckoutSessionDetails>(`/v1/checkout/${sessionId}/status`)\n },\n\n /**\n * Cancel a checkout session (not implemented in backend yet)\n */\n cancelSession: async (_sessionId: string): Promise<void> => {\n // TODO: Backend doesn't have this endpoint yet\n throw new Error('Cancel session not implemented yet')\n },\n\n /**\n * Confirm payment for a checkout session\n */\n confirmPayment: async (clientSecret: string, paymentMethodId: string): Promise<ConfirmCheckoutResponse> => {\n return this.post<ConfirmCheckoutResponse>(\n `/v1/checkout/${clientSecret}/confirm`,\n { paymentMethodId }\n )\n },\n\n /**\n * Apply coupon to a checkout session (not implemented in backend yet)\n */\n applyCoupon: async (_sessionId: string, _couponCode: string): Promise<CheckoutSessionDetails> => {\n // TODO: Backend doesn't have this endpoint yet\n throw new Error('Apply coupon not implemented yet')\n }\n }\n\n // =============================================================================\n // PORTAL API (Iframe-based customer portal)\n // =============================================================================\n\n /**\n * Portal API methods for iframe-based customer portal\n */\n public portal = {\n /**\n * Create a portal session for customer self-service\n */\n createSession: async (input?: { customerId?: string; metadata?: Record<string, any> }): Promise<{ id: string; expiresAt: string }> => {\n console.log('[SDK Client] Creating portal session')\n\n const response = await this.post<{ id: string; customerId: string; organizationId: string; expiresAt: string }>(\n '/v1/portal/create',\n input || {}\n )\n\n console.log('[SDK Client] Portal session created:', {\n sessionId: response.id,\n customerId: response.customerId,\n expiresAt: response.expiresAt,\n })\n\n return {\n id: response.id,\n expiresAt: response.expiresAt,\n }\n },\n\n /**\n * Get portal session status\n */\n getSessionStatus: async (sessionId: string): Promise<{ isValid: boolean; expiresAt?: string }> => {\n return this.get<{ sessionId: string; isValid: boolean; expiresAt?: string; customerId?: string }>(\n `/v1/portal/${sessionId}/status`\n )\n },\n\n /**\n * Get portal data for a session\n */\n getPortalData: async (sessionId: string): Promise<any> => {\n return this.get(`/v1/portal/${sessionId}/data`)\n },\n }\n\n // =============================================================================\n // PRICING TABLE API\n // =============================================================================\n\n /**\n * Get all products for the pricing table\n * @param planIds - Optional array of plan IDs to filter\n */\n async getProducts(planIds?: string[]): Promise<GetProductsResponse> {\n const query = new URLSearchParams()\n if (planIds && planIds.length > 0) {\n query.set('planIds', planIds.join(','))\n }\n const queryString = query.toString()\n return this.get<GetProductsResponse>(\n `/v1/products${queryString ? `?${queryString}` : ''}`\n )\n }\n\n // =============================================================================\n // UPGRADE NUDGE API\n // =============================================================================\n\n /**\n * Check usage and get nudge trigger if applicable\n * Uses usage-metrics endpoint and computes nudge client-side\n */\n async checkUsage(): Promise<UsageCheckResponse> {\n const response = await this.get<{ metrics: any[] }>('/v1/features/usage-metrics')\n const metrics = response.metrics || []\n\n // Check if any feature is near its limit (80% threshold)\n const atRisk = metrics.find((m: any) => {\n if (!m.limit || m.limit === 0) return false\n return (m.consumed / m.limit) * 100 >= 80\n })\n\n if (!atRisk) {\n return { shouldShowNudge: false }\n }\n\n return {\n shouldShowNudge: true,\n trigger: {\n type: 'usage_threshold',\n feature: atRisk.feature_key,\n threshold: 80,\n actual: Math.round((atRisk.consumed / atRisk.limit) * 100 * 10) / 10,\n message: {\n title: 'Approaching usage limit',\n body: `You've used ${Math.round((atRisk.consumed / atRisk.limit) * 100)}% of your ${atRisk.feature_title || atRisk.feature_key} limit.`,\n cta: 'Upgrade plan',\n },\n suggestedPlan: { id: '', priceId: '', name: '', price: { amount: 0, currency: 'usd', interval: 'month' }, highlights: [] },\n },\n }\n }\n}\n\n/**\n * Factory function to create a BillingOS client instance\n */\nexport function createBillingOSClient(\n sessionToken: string,\n options?: BillingOSClientOptions\n): BillingOSClient {\n return new BillingOSClient(sessionToken, options)\n}\n","/**\n * Hook for managing session tokens with auto-fetch and auto-refresh\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\n\nexport interface SessionTokenData {\n sessionToken: string;\n expiresAt: string; // ISO date string\n}\n\nexport interface UseSessionTokenOptions {\n /** URL to fetch session token from (e.g., /api/billingos-session) */\n tokenUrl?: string;\n\n /** Manually provided session token */\n token?: string;\n\n /** How many seconds before expiry to refresh (default: 300 = 5 minutes) */\n refreshBeforeExpiry?: number;\n\n /** Enable auto-refresh (default: true) */\n autoRefresh?: boolean;\n\n /** Callback when token is refreshed */\n onTokenRefresh?: (token: string) => void;\n\n /** Callback when token fetch fails */\n onError?: (error: Error) => void;\n}\n\nexport interface UseSessionTokenReturn {\n /** Current session token */\n token: string | null;\n\n /** When the token expires */\n expiresAt: Date | null;\n\n /** Whether the token is currently being fetched */\n isLoading: boolean;\n\n /** Any error that occurred */\n error: Error | null;\n\n /** Manually refresh the token */\n refresh: () => Promise<void>;\n\n /** Whether the token is valid (not expired) */\n isValid: boolean;\n}\n\n/**\n * Hook to manage session tokens with automatic fetching and refreshing\n *\n * @example\n * // Auto-fetch from endpoint\n * const { token, isLoading } = useSessionToken({\n * tokenUrl: '/api/billingos-session',\n * });\n *\n * @example\n * // Manual token\n * const { token } = useSessionToken({\n * token: 'bos_session_abc123...',\n * });\n */\nexport function useSessionToken(options: UseSessionTokenOptions = {}): UseSessionTokenReturn {\n const {\n tokenUrl,\n token: manualToken,\n refreshBeforeExpiry = 300, // 5 minutes\n autoRefresh = true,\n onTokenRefresh,\n onError,\n } = options;\n\n const [token, setToken] = useState<string | null>(manualToken || null);\n const [expiresAt, setExpiresAt] = useState<Date | null>(null);\n // Start as loading if we need to fetch from tokenUrl\n const [isLoading, setIsLoading] = useState<boolean>(Boolean(tokenUrl && !manualToken));\n const [error, setError] = useState<Error | null>(null);\n\n const refreshTimerRef = useRef<NodeJS.Timeout | null>(null);\n const isMountedRef = useRef<boolean>(true);\n\n /**\n * Fetch token from endpoint\n */\n const fetchToken = useCallback(async () => {\n if (!tokenUrl) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const response = await fetch(tokenUrl, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n credentials: 'include', // Include cookies for auth\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new Error(errorData.error || `Failed to fetch session token: ${response.statusText}`);\n }\n\n const data: SessionTokenData = await response.json();\n\n if (!isMountedRef.current) return;\n\n setToken(data.sessionToken);\n setExpiresAt(new Date(data.expiresAt));\n setError(null);\n\n onTokenRefresh?.(data.sessionToken);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch session token');\n\n if (!isMountedRef.current) return;\n\n setError(error);\n onError?.(error);\n } finally {\n if (isMountedRef.current) {\n setIsLoading(false);\n }\n }\n }, [tokenUrl, onTokenRefresh, onError]);\n\n /**\n * Setup auto-refresh timer\n */\n useEffect(() => {\n if (!autoRefresh || !expiresAt || !tokenUrl) return;\n\n // Clear existing timer\n if (refreshTimerRef.current) {\n clearTimeout(refreshTimerRef.current);\n }\n\n const now = Date.now();\n const expiryTime = expiresAt.getTime();\n const msUntilExpiry = expiryTime - now;\n\n // Refresh X seconds before expiry\n const refreshAt = msUntilExpiry - (refreshBeforeExpiry * 1000);\n\n if (refreshAt > 0) {\n refreshTimerRef.current = setTimeout(() => {\n fetchToken();\n }, refreshAt);\n } else if (msUntilExpiry > 0) {\n // Token expires soon, refresh immediately\n fetchToken();\n }\n\n return () => {\n if (refreshTimerRef.current) {\n clearTimeout(refreshTimerRef.current);\n }\n };\n }, [expiresAt, autoRefresh, refreshBeforeExpiry, tokenUrl, fetchToken]);\n\n /**\n * Initial fetch when tokenUrl is provided\n */\n useEffect(() => {\n if (tokenUrl && !manualToken) {\n fetchToken();\n }\n }, [tokenUrl, manualToken, fetchToken]);\n\n /**\n * Update token when manual token changes\n */\n useEffect(() => {\n if (manualToken) {\n setToken(manualToken);\n // Can't determine expiry from manual token, so disable auto-refresh\n setExpiresAt(null);\n }\n }, [manualToken]);\n\n /**\n * Cleanup on unmount\n */\n useEffect(() => {\n return () => {\n isMountedRef.current = false;\n if (refreshTimerRef.current) {\n clearTimeout(refreshTimerRef.current);\n }\n };\n }, []);\n\n /**\n * Check if token is valid (not expired)\n */\n const isValid = Boolean(\n token && (!expiresAt || expiresAt.getTime() > Date.now())\n );\n\n return {\n token,\n expiresAt,\n isLoading,\n error,\n refresh: fetchToken,\n isValid,\n };\n}\n","import React, { createContext, useContext, useMemo } from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { BillingOSClient, BillingOSClientOptions } from '../client'\nimport { useSessionToken, UseSessionTokenOptions } from '../hooks/useSessionToken'\n\n/**\n * Context value provided by BillingOSProvider\n */\nexport interface BillingOSContextValue {\n /**\n * The BillingOS API client instance\n */\n client: BillingOSClient\n\n /**\n * Optional customer ID for the current user\n */\n customerId?: string\n\n /**\n * Optional customer email\n */\n customerEmail?: string\n\n /**\n * Optional customer name\n */\n customerName?: string\n\n /**\n * Optional organization ID\n */\n organizationId?: string\n}\n\n/**\n * React Context for BillingOS SDK\n */\nconst BillingOSContext = createContext<BillingOSContextValue | undefined>(undefined)\n\n/**\n * Props for BillingOSProvider\n */\nexport interface BillingOSProviderProps {\n /**\n * Session token - can be provided directly OR fetched automatically from tokenUrl\n * Use this when you already have a session token\n */\n sessionToken?: string\n\n /**\n * URL to fetch session token from (e.g., /api/billingos-session)\n * The SDK will automatically fetch and refresh the token\n */\n sessionTokenUrl?: string\n\n /**\n * Session token options (auto-refresh settings, error handlers, etc.)\n */\n sessionTokenOptions?: Omit<UseSessionTokenOptions, 'token' | 'tokenUrl'>\n\n /**\n * Optional customer ID for the current user\n */\n customerId?: string\n\n /**\n * Optional customer email\n */\n customerEmail?: string\n\n /**\n * Optional customer name\n */\n customerName?: string\n\n /**\n * Optional organization ID\n */\n organizationId?: string\n\n /**\n * Client configuration options\n */\n options?: BillingOSClientOptions\n\n /**\n * Optional custom QueryClient instance\n * If not provided, a default one will be created\n */\n queryClient?: QueryClient\n\n /**\n * Child components\n */\n children: React.ReactNode\n}\n\n/**\n * Default QueryClient configuration\n */\nconst createDefaultQueryClient = () =>\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 1000 * 60 * 5, // 5 minutes\n gcTime: 1000 * 60 * 10, // 10 minutes (formerly cacheTime)\n retry: 1,\n refetchOnWindowFocus: false,\n },\n mutations: {\n retry: false,\n },\n },\n })\n\n/**\n * Provider component for BillingOS SDK\n *\n * Wraps your app and provides the BillingOS client to all hooks and components.\n *\n * @example\n * Auto-fetch session token from endpoint:\n * ```tsx\n * import { BillingOSProvider } from '@billingos/sdk'\n *\n * function App() {\n * return (\n * <BillingOSProvider\n * sessionTokenUrl=\"/api/billingos-session\"\n * customerId=\"customer_123\"\n * >\n * <YourApp />\n * </BillingOSProvider>\n * )\n * }\n * ```\n *\n * @example\n * Manually provide session token:\n * ```tsx\n * function App() {\n * const [sessionToken, setSessionToken] = useState('bos_session_...')\n *\n * return (\n * <BillingOSProvider sessionToken={sessionToken}>\n * <YourApp />\n * </BillingOSProvider>\n * )\n * }\n * ```\n */\nexport function BillingOSProvider({\n sessionToken: manualSessionToken,\n sessionTokenUrl,\n sessionTokenOptions,\n customerId,\n customerEmail,\n customerName,\n organizationId,\n options,\n queryClient,\n children,\n}: BillingOSProviderProps) {\n // Log SDK version on mount\n React.useEffect(() => {\n console.log('%c🚀 BillingOS SDK v1.2.0 Initialized', 'color: #10b981; font-weight: bold; font-size: 16px;')\n console.log('✨ Features: Real-time subscription updates, Customer data prefill, Iframe checkout')\n }, [])\n\n // Fetch and manage session token\n const { token, isLoading, error } = useSessionToken({\n token: manualSessionToken,\n tokenUrl: sessionTokenUrl,\n ...sessionTokenOptions,\n })\n\n // Use provided QueryClient or create default\n const qc = useMemo(\n () => queryClient || createDefaultQueryClient(),\n [queryClient]\n )\n\n // Create BillingOS client instance (conditionally, but hook always called)\n const client = useMemo(\n () => token ? new BillingOSClient(token, options) : null,\n [token, options]\n )\n\n // Context value (conditionally, but hook always called)\n const contextValue = useMemo<BillingOSContextValue | null>(\n () => client ? {\n client,\n customerId,\n customerEmail,\n customerName,\n organizationId,\n } : null,\n [client, customerId, customerEmail, customerName, organizationId]\n )\n\n // Show loading state while fetching token\n if (sessionTokenUrl && isLoading) {\n return null // or a loading spinner\n }\n\n // Show error if token fetch failed\n if (sessionTokenUrl && error) {\n console.error('Failed to fetch BillingOS session token:', error)\n return null // or an error component\n }\n\n // Don't render if no token available\n if (!token || !client || !contextValue) {\n console.error('BillingOS: No session token provided. Use sessionToken or sessionTokenUrl prop.')\n return null\n }\n\n return (\n <BillingOSContext.Provider value={contextValue}>\n <QueryClientProvider client={qc}>{children}</QueryClientProvider>\n </BillingOSContext.Provider>\n )\n}\n\n/**\n * Hook to access the BillingOS context\n *\n * Must be used within a BillingOSProvider.\n *\n * @throws Error if used outside of BillingOSProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { client, customerId } = useBillingOS()\n *\n * // Use client to make API calls\n * const subscription = await client.getSubscription(id)\n *\n * return <div>Customer: {customerId}</div>\n * }\n * ```\n */\nexport function useBillingOS(): BillingOSContextValue {\n const context = useContext(BillingOSContext)\n\n if (!context) {\n throw new Error(\n 'useBillingOS must be used within a BillingOSProvider. ' +\n 'Wrap your app with <BillingOSProvider> to use BillingOS hooks and components.'\n )\n }\n\n return context\n}\n\n/**\n * Hook to access the React Query client used by BillingOS SDK\n *\n * Useful for manual query invalidation or cache management.\n *\n * Must be used within a BillingOSProvider.\n *\n * @example\n * ```tsx\n * import { useBillingOSQueryClient } from '@billingos/sdk'\n * import { useQueryClient } from '@tanstack/react-query'\n *\n * function MyComponent() {\n * const queryClient = useBillingOSQueryClient()\n *\n * const handleRefresh = () => {\n * // Invalidate products query to refresh pricing table\n * queryClient.invalidateQueries({ queryKey: ['billingos', 'products'] })\n * }\n *\n * return <button onClick={handleRefresh}>Refresh</button>\n * }\n * ```\n */\nexport { useQueryClient as useBillingOSQueryClient } from '@tanstack/react-query'\n","import { useQuery, useMutation, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'\nimport { useBillingOS } from '../providers'\nimport type {\n Subscription,\n CreateSubscriptionInput,\n UpdateSubscriptionInput,\n SubscriptionPreview,\n PaginatedResponse,\n AvailablePlansResponse,\n PreviewChangeInput,\n PreviewChangeResponse,\n ChangePlanInput,\n ChangePlanResponse,\n} from '../client'\n\n/**\n * Query keys for subscription-related queries\n */\nexport const subscriptionKeys = {\n all: ['subscriptions'] as const,\n lists: () => [...subscriptionKeys.all, 'list'] as const,\n list: (filters?: Record<string, unknown>) => [...subscriptionKeys.lists(), filters] as const,\n details: () => [...subscriptionKeys.all, 'detail'] as const,\n detail: (id: string) => [...subscriptionKeys.details(), id] as const,\n preview: (id: string, input: UpdateSubscriptionInput) => [...subscriptionKeys.all, 'preview', id, input] as const,\n}\n\n/**\n * Fetch a single subscription by ID\n *\n * @param id - Subscription ID\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function SubscriptionDetails({ id }: { id: string }) {\n * const { data: subscription, isLoading, error } = useSubscription(id)\n *\n * if (isLoading) return <div>Loading...</div>\n * if (error) return <div>Error: {error.message}</div>\n *\n * return (\n * <div>\n * <h1>Subscription Status: {subscription.status}</h1>\n * <p>Next billing: {subscription.current_period_end}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useSubscription(\n id: string,\n options?: Omit<UseQueryOptions<Subscription>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: subscriptionKeys.detail(id),\n queryFn: () => client.getSubscription(id),\n enabled: !!id,\n ...options,\n })\n}\n\n/**\n * Fetch a list of subscriptions (paginated)\n *\n * @param params - Query parameters (customer_id, pagination)\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function SubscriptionsList() {\n * const { data, isLoading } = useSubscriptions({\n * customer_id: 'cus_123',\n * page: 1,\n * page_size: 10\n * })\n *\n * if (isLoading) return <div>Loading...</div>\n *\n * return (\n * <div>\n * {data?.data.map(subscription => (\n * <SubscriptionCard key={subscription.id} subscription={subscription} />\n * ))}\n * <p>Total: {data?.meta.total}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useSubscriptions(\n params?: {\n customer_id?: string\n page?: number\n page_size?: number\n },\n options?: Omit<UseQueryOptions<PaginatedResponse<Subscription>>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: subscriptionKeys.list(params),\n queryFn: () => client.listSubscriptions(params),\n ...options,\n })\n}\n\n/**\n * Create a new subscription\n *\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function CreateSubscriptionButton() {\n * const createSubscription = useCreateSubscription({\n * onSuccess: (subscription) => {\n * console.log('Subscription created:', subscription.id)\n * // Redirect to success page\n * },\n * onError: (error) => {\n * console.error('Failed to create subscription:', error)\n * }\n * })\n *\n * const handleClick = () => {\n * createSubscription.mutate({\n * customer_id: 'cus_123',\n * price_id: 'price_456',\n * trial_days: 14\n * })\n * }\n *\n * return (\n * <button\n * onClick={handleClick}\n * disabled={createSubscription.isPending}\n * >\n * {createSubscription.isPending ? 'Creating...' : 'Subscribe'}\n * </button>\n * )\n * }\n * ```\n */\nexport function useCreateSubscription(\n options?: Omit<UseMutationOptions<Subscription, Error, CreateSubscriptionInput>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: CreateSubscriptionInput) => client.createSubscription(input),\n onSuccess: (_data, _variables, _context) => {\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n },\n })\n}\n\n/**\n * Update an existing subscription\n *\n * @param subscriptionId - Subscription ID to update\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function UpgradeButton({ subscriptionId }: { subscriptionId: string }) {\n * const updateSubscription = useUpdateSubscription(subscriptionId, {\n * onSuccess: () => {\n * console.log('Subscription updated!')\n * }\n * })\n *\n * const handleUpgrade = () => {\n * updateSubscription.mutate({\n * price_id: 'price_pro_plan'\n * })\n * }\n *\n * return (\n * <button onClick={handleUpgrade} disabled={updateSubscription.isPending}>\n * Upgrade to Pro\n * </button>\n * )\n * }\n * ```\n */\nexport function useUpdateSubscription(\n subscriptionId: string,\n options?: Omit<UseMutationOptions<Subscription, Error, UpdateSubscriptionInput>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: UpdateSubscriptionInput) =>\n client.updateSubscription(subscriptionId, input),\n onSuccess: (_data, _variables, _context) => {\n // Invalidate this subscription's cache\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.detail(subscriptionId) })\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n },\n })\n}\n\n/**\n * Cancel a subscription\n *\n * @param subscriptionId - Subscription ID to cancel\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function CancelButton({ subscriptionId }: { subscriptionId: string }) {\n * const cancelSubscription = useCancelSubscription(subscriptionId, {\n * onSuccess: () => {\n * alert('Subscription cancelled')\n * }\n * })\n *\n * const handleCancel = (immediately: boolean) => {\n * if (confirm('Are you sure you want to cancel?')) {\n * cancelSubscription.mutate({ immediately })\n * }\n * }\n *\n * return (\n * <div>\n * <button onClick={() => handleCancel(false)}>\n * Cancel at period end\n * </button>\n * <button onClick={() => handleCancel(true)}>\n * Cancel immediately\n * </button>\n * </div>\n * )\n * }\n * ```\n */\nexport function useCancelSubscription(\n subscriptionId: string,\n options?: Omit<UseMutationOptions<Subscription, Error, { immediately?: boolean }>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: ({ immediately = false }: { immediately?: boolean }) =>\n client.cancelSubscription(subscriptionId, immediately),\n onSuccess: (_data, _variables, _context) => {\n // Invalidate this subscription's cache\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.detail(subscriptionId) })\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n },\n })\n}\n\n/**\n * Reactivate a canceled subscription\n *\n * @param subscriptionId - Subscription ID to reactivate\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function ReactivateButton({ subscriptionId }: { subscriptionId: string }) {\n * const reactivateSubscription = useReactivateSubscription(subscriptionId)\n *\n * return (\n * <button\n * onClick={() => reactivateSubscription.mutate()}\n * disabled={reactivateSubscription.isPending}\n * >\n * Reactivate Subscription\n * </button>\n * )\n * }\n * ```\n */\nexport function useReactivateSubscription(\n subscriptionId: string,\n options?: Omit<UseMutationOptions<Subscription, Error, void>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: () => client.reactivateSubscription(subscriptionId),\n onSuccess: (_data, _variables, _context) => {\n // Invalidate this subscription's cache\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.detail(subscriptionId) })\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n },\n })\n}\n\n/**\n * Preview subscription changes before applying them\n *\n * @param subscriptionId - Subscription ID\n * @param input - Proposed changes\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function UpgradePreview({ subscriptionId }: { subscriptionId: string }) {\n * const { data: preview, isLoading } = useSubscriptionPreview(\n * subscriptionId,\n * { price_id: 'price_pro_plan' }\n * )\n *\n * if (isLoading) return <div>Calculating...</div>\n *\n * return (\n * <div>\n * <p>Proration: ${preview?.proration_amount / 100}</p>\n * <p>Next invoice: ${preview?.next_invoice_amount / 100}</p>\n * <p>Billing date: {preview?.next_invoice_date}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useSubscriptionPreview(\n subscriptionId: string,\n input: UpdateSubscriptionInput,\n options?: Omit<UseQueryOptions<SubscriptionPreview>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: subscriptionKeys.preview(subscriptionId, input),\n queryFn: () => client.previewSubscription(subscriptionId, input),\n enabled: !!subscriptionId && !!input,\n ...options,\n })\n}\n\n/**\n * Fetch available plans for upgrade/downgrade\n *\n * @param subscriptionId - Subscription ID\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function AvailablePlans({ subscriptionId }: { subscriptionId: string }) {\n * const { data, isLoading } = useAvailablePlans(subscriptionId)\n *\n * if (isLoading) return <div>Loading plans...</div>\n *\n * return (\n * <div>\n * <h3>Upgrades:</h3>\n * {data?.available_upgrades.map(plan => (\n * <div key={plan.price_id}>{plan.product_name}</div>\n * ))}\n * </div>\n * )\n * }\n * ```\n */\nexport function useAvailablePlans(\n subscriptionId: string,\n options?: Omit<UseQueryOptions<AvailablePlansResponse>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: [...subscriptionKeys.detail(subscriptionId), 'available-plans'] as const,\n queryFn: () => client.getAvailablePlans(subscriptionId),\n enabled: !!subscriptionId,\n ...options,\n })\n}\n\n/**\n * Preview a plan change with proration details\n *\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function PlanChangePreview({ subscriptionId }: { subscriptionId: string }) {\n * const previewChange = usePreviewPlanChange()\n *\n * const handlePreview = async (newPriceId: string) => {\n * const preview = await previewChange.mutateAsync({\n * subscriptionId,\n * input: { new_price_id: newPriceId }\n * })\n * console.log('Proration:', preview.proration.immediate_payment)\n * }\n *\n * return <button onClick={() => handlePreview('price_123')}>Preview</button>\n * }\n * ```\n */\nexport function usePreviewPlanChange(\n options?: Omit<\n UseMutationOptions<\n PreviewChangeResponse,\n Error,\n { subscriptionId: string; input: PreviewChangeInput }\n >,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n\n return useMutation({\n ...options,\n mutationFn: ({ subscriptionId, input }) =>\n client.previewPlanChange(subscriptionId, input),\n })\n}\n\n/**\n * Execute a plan change (upgrade/downgrade)\n *\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function ChangePlanButton({ subscriptionId }: { subscriptionId: string }) {\n * const changePlan = useChangePlan({\n * onSuccess: (response) => {\n * console.log('Plan changed:', response.subscription.id)\n * }\n * })\n *\n * const handleChange = () => {\n * changePlan.mutate({\n * subscriptionId,\n * input: {\n * new_price_id: 'price_456',\n * confirm_amount: 1999\n * }\n * })\n * }\n *\n * return (\n * <button onClick={handleChange} disabled={changePlan.isPending}>\n * {changePlan.isPending ? 'Changing...' : 'Change Plan'}\n * </button>\n * )\n * }\n * ```\n */\nexport function useChangePlan(\n options?: Omit<\n UseMutationOptions<\n ChangePlanResponse,\n Error,\n { subscriptionId: string; input: ChangePlanInput }\n >,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: ({ subscriptionId, input }) =>\n client.changePlan(subscriptionId, input),\n onSuccess: (_data, variables, _context) => {\n // Invalidate subscription cache\n queryClient.invalidateQueries({\n queryKey: subscriptionKeys.detail(variables.subscriptionId),\n })\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n // Invalidate available plans\n queryClient.invalidateQueries({\n queryKey: [...subscriptionKeys.detail(variables.subscriptionId), 'available-plans'],\n })\n },\n })\n}\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\n/**\n * Utility function to merge Tailwind CSS classes\n * Combines clsx for conditional classes with tailwind-merge for deduplication\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface DialogContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n}\n\nconst DialogContext = React.createContext<DialogContextValue | null>(null)\n\nfunction useDialogContext() {\n const context = React.useContext(DialogContext)\n if (!context) {\n throw new Error('Dialog components must be used within a Dialog provider')\n }\n return context\n}\n\ninterface DialogProps {\n open?: boolean\n onOpenChange?: (open: boolean) => void\n children: React.ReactNode\n}\n\nfunction Dialog({ open = false, onOpenChange, children }: DialogProps) {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const isOpen = open ?? internalOpen\n const handleOpenChange = onOpenChange ?? setInternalOpen\n\n return (\n <DialogContext.Provider value={{ open: isOpen, onOpenChange: handleOpenChange }}>\n {children}\n </DialogContext.Provider>\n )\n}\n\ninterface DialogTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean\n}\n\nconst DialogTrigger = React.forwardRef<HTMLButtonElement, DialogTriggerProps>(\n ({ onClick, ...props }, ref) => {\n const { onOpenChange } = useDialogContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(true)\n onClick?.(e)\n }}\n {...props}\n />\n )\n }\n)\nDialogTrigger.displayName = 'DialogTrigger'\n\ninterface DialogPortalProps {\n children: React.ReactNode\n}\n\nfunction DialogPortal({ children }: DialogPortalProps) {\n const { open } = useDialogContext()\n if (!open) return null\n return <>{children}</>\n}\n\nconst DialogOverlay = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const { onOpenChange } = useDialogContext()\n\n return (\n <div\n ref={ref}\n onClick={() => onOpenChange(false)}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n className\n )}\n {...props}\n />\n )\n})\nDialogOverlay.displayName = 'DialogOverlay'\n\nconst DialogContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, children, ...props }, ref) => {\n const { open, onOpenChange } = useDialogContext()\n\n // Handle escape key\n React.useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onOpenChange(false)\n }\n }\n if (open) {\n document.addEventListener('keydown', handleEscape)\n document.body.style.overflow = 'hidden'\n }\n return () => {\n document.removeEventListener('keydown', handleEscape)\n document.body.style.overflow = ''\n }\n }, [open, onOpenChange])\n\n if (!open) return null\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <DialogOverlay />\n <div\n ref={ref}\n onClick={(e) => e.stopPropagation()}\n className={cn(\n 'relative z-50 w-full max-w-lg gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg',\n className\n )}\n {...props}\n >\n {children}\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"h-4 w-4\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n <span className=\"sr-only\">Close</span>\n </button>\n </div>\n </div>\n )\n})\nDialogContent.displayName = 'DialogContent'\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col space-y-1.5 text-center sm:text-left',\n className\n )}\n {...props}\n />\n)\nDialogHeader.displayName = 'DialogHeader'\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n className\n )}\n {...props}\n />\n)\nDialogFooter.displayName = 'DialogFooter'\n\nconst DialogTitle = React.forwardRef<\n HTMLHeadingElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn(\n 'text-lg font-semibold leading-none tracking-tight',\n className\n )}\n {...props}\n />\n))\nDialogTitle.displayName = 'DialogTitle'\n\nconst DialogDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nDialogDescription.displayName = 'DialogDescription'\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n}\n","import React, { forwardRef } from 'react'\nimport { cn } from '../../utils/cn'\n\ninterface CheckoutIframeProps {\n /**\n * The iframe source URL\n */\n src: string\n\n /**\n * Height of the iframe\n */\n height?: number | string\n\n /**\n * Additional CSS classes\n */\n className?: string\n\n /**\n * Load event handler\n */\n onLoad?: () => void\n\n /**\n * Error event handler\n */\n onError?: (error: React.SyntheticEvent<HTMLIFrameElement>) => void\n}\n\nexport const CheckoutIframe = forwardRef<HTMLIFrameElement, CheckoutIframeProps>(\n ({ src, height = 600, className, onLoad, onError }, ref) => {\n return (\n <iframe\n ref={ref}\n src={src}\n className={cn(\"w-full border-none\", className)}\n style={{\n height: typeof height === 'number' ? `${height}px` : height,\n minHeight: '400px',\n maxHeight: '80vh'\n }}\n onLoad={onLoad}\n onError={onError}\n // Security attributes\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\"\n allow=\"payment\"\n // Accessibility\n title=\"Secure Checkout\"\n // Performance\n loading=\"lazy\"\n />\n )\n }\n)\n\nCheckoutIframe.displayName = 'CheckoutIframe'","import { useState, useEffect } from 'react'\nimport { useBillingOS } from '../../../providers/BillingOSProvider'\n\ninterface UseCheckoutSessionOptions {\n enabled: boolean\n priceId: string\n customer?: {\n email?: string\n name?: string\n taxId?: string\n }\n couponCode?: string\n metadata?: Record<string, string>\n existingSubscriptionId?: string\n}\n\ninterface UseCheckoutSessionReturn {\n sessionId: string | null\n sessionUrl: string | null\n loading: boolean\n error: Error | null\n refresh: () => Promise<void>\n}\n\nexport function useCheckoutSession({\n enabled,\n priceId,\n customer,\n couponCode,\n metadata,\n existingSubscriptionId\n}: UseCheckoutSessionOptions): UseCheckoutSessionReturn {\n const { client } = useBillingOS()\n const [sessionId, setSessionId] = useState<string | null>(null)\n const [sessionUrl, setSessionUrl] = useState<string | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const createSession = async () => {\n if (!enabled || !priceId) return\n\n console.log(\n '%c🔄 Creating checkout session...',\n 'color: #3b82f6; font-weight: 600;',\n { priceId, customer }\n )\n\n setLoading(true)\n setError(null)\n\n try {\n // Create checkout session via API\n const session = await client.checkout.createSession({\n priceId,\n customer,\n couponCode,\n metadata,\n existingSubscriptionId,\n // Return URLs will be handled by postMessage instead\n mode: 'embedded'\n })\n\n setSessionId(session.id)\n console.log(\n '%c✨ Session created!',\n 'color: #10b981; font-weight: 600;',\n `ID: ${session.id}`\n )\n\n // Generate iframe URL\n // The iframe should always load from the BillingOS web app, not the merchant's app\n // In production, this would be your BillingOS domain (e.g., https://app.billingos.com)\n const billingOSAppUrl = process.env.NEXT_PUBLIC_BILLINGOS_APP_URL || 'http://localhost:3000'\n const iframeUrl = `${billingOSAppUrl}/embed/checkout/${session.id}`\n setSessionUrl(iframeUrl)\n\n console.log(\n '%c📍 Iframe URL ready',\n 'color: #8b5cf6; font-weight: 600;',\n iframeUrl\n )\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to create checkout session')\n setError(error)\n console.error('[useCheckoutSession] Error creating session:', error)\n } finally {\n setLoading(false)\n }\n }\n\n // Create session when enabled\n useEffect(() => {\n if (enabled && !sessionId) {\n createSession()\n }\n }, [enabled, priceId])\n\n // Cleanup session when component unmounts\n useEffect(() => {\n return () => {\n if (sessionId) {\n // Optionally cancel the session if not completed\n // client.checkout.cancelSession(sessionId).catch(() => {})\n }\n }\n }, [sessionId])\n\n const refresh = async () => {\n setSessionId(null)\n setSessionUrl(null)\n await createSession()\n }\n\n return {\n sessionId,\n sessionUrl,\n loading,\n error,\n refresh\n }\n}","/**\n * Security utilities for iframe communication\n */\n\n/**\n * Get allowed origins for iframe communication\n */\nexport function getAllowedOrigins(): string[] {\n const origins: string[] = []\n\n // Add configured app URL\n if (process.env.NEXT_PUBLIC_APP_URL) {\n origins.push(process.env.NEXT_PUBLIC_APP_URL)\n }\n\n // Add BillingOS domains\n origins.push('https://app.billingos.com')\n origins.push('https://embed.billingos.com')\n\n // Add localhost for development\n if (process.env.NODE_ENV === 'development') {\n origins.push('http://localhost:3000')\n origins.push('http://localhost:3001')\n origins.push('http://127.0.0.1:3000')\n origins.push('http://127.0.0.1:3001')\n }\n\n return origins\n}\n\n/**\n * Validate message origin\n */\nexport function validateOrigin(origin: string): boolean {\n const allowedOrigins = getAllowedOrigins()\n if (allowedOrigins.includes(origin)) return true\n\n // Allow BillingOS Vercel deployments\n if (origin.endsWith('.vercel.app') && origin.includes('billingos')) return true\n\n // Allow Stripe origins\n if (origin.endsWith('.stripe.com')) return true\n\n return false\n}\n\n/**\n * Generate a random nonce for message verification\n */\nexport function generateNonce(): string {\n return Math.random().toString(36).substring(2, 15) +\n Math.random().toString(36).substring(2, 15)\n}\n\n/**\n * Sanitize URL to prevent XSS\n */\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url)\n // Only allow http and https protocols\n if (!['http:', 'https:'].includes(parsed.protocol)) {\n throw new Error('Invalid protocol')\n }\n return parsed.toString()\n } catch {\n throw new Error('Invalid URL')\n }\n}\n\n/**\n * Create Content Security Policy for iframe\n */\nexport function getIframeCSP(): string {\n return [\n \"default-src 'self'\",\n \"script-src 'self' 'unsafe-inline' https://js.stripe.com\",\n \"connect-src 'self' https://api.stripe.com\",\n \"frame-src https://js.stripe.com https://hooks.stripe.com\",\n \"img-src 'self' data: https:\",\n \"style-src 'self' 'unsafe-inline'\"\n ].join('; ')\n}\n\n/**\n * Verify session token hasn't expired\n */\nexport function isSessionExpired(expiresAt: string | Date): boolean {\n const expiryTime = new Date(expiresAt).getTime()\n return Date.now() > expiryTime\n}","import { useEffect, useCallback, RefObject } from 'react'\nimport { validateOrigin } from '../utils/security'\nimport type { IframeMessage, ParentMessage } from '../utils/messaging'\n\ninterface UseIframeMessagingOptions {\n iframeRef: RefObject<HTMLIFrameElement | null>\n onMessage: (message: IframeMessage) => void\n targetOrigin?: string\n debug?: boolean\n}\n\ninterface UseIframeMessagingReturn {\n sendMessage: (message: ParentMessage) => void\n isConnected: boolean\n}\n\nexport function useIframeMessaging({\n iframeRef,\n onMessage,\n targetOrigin = process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000',\n debug = false\n}: UseIframeMessagingOptions): UseIframeMessagingReturn {\n const isConnected = Boolean(iframeRef.current?.contentWindow)\n\n /**\n * Send message to iframe\n */\n const sendMessage = useCallback((message: ParentMessage) => {\n if (iframeRef.current?.contentWindow) {\n if (debug) {\n console.log('[useIframeMessaging] Sending message:', message)\n }\n iframeRef.current.contentWindow.postMessage(message, targetOrigin)\n } else {\n console.warn('[useIframeMessaging] Cannot send message - iframe not ready')\n }\n }, [iframeRef, targetOrigin, debug])\n\n /**\n * Handle incoming messages from iframe\n */\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n // Validate origin\n if (!validateOrigin(event.origin)) {\n if (debug) {\n console.warn(`[useIframeMessaging] Invalid origin: ${event.origin}`)\n }\n return\n }\n\n // Validate message structure\n if (!event.data || typeof event.data !== 'object' || !event.data.type) {\n return\n }\n\n // Check if this is a checkout message\n if (!event.data.type.startsWith('CHECKOUT_') && event.data.type !== 'HEIGHT_CHANGED' && event.data.type !== 'PROCESSING') {\n return\n }\n\n if (debug) {\n console.log('[useIframeMessaging] Received message:', event.data)\n }\n\n // Pass message to handler\n onMessage(event.data as IframeMessage)\n }\n\n window.addEventListener('message', handleMessage)\n\n return () => {\n window.removeEventListener('message', handleMessage)\n }\n }, [onMessage, debug])\n\n return {\n sendMessage,\n isConnected\n }\n}","import { useState, useEffect, useRef, useCallback } from 'react'\nimport { Dialog, DialogContent } from '../ui/dialog'\nimport { CheckoutIframe } from './CheckoutIframe'\nimport { useCheckoutSession } from './hooks/useCheckoutSession'\nimport { useIframeMessaging } from './hooks/useIframeMessaging'\nimport type { IframeMessage } from './utils/messaging'\nimport { cn } from '../../utils/cn'\n\nexport interface CheckoutModalProps {\n /**\n * Whether the modal is open\n */\n open: boolean\n\n /**\n * Callback when the modal open state changes\n */\n onOpenChange: (open: boolean) => void\n\n /**\n * The price ID to checkout\n */\n priceId: string\n\n /**\n * Customer information to pre-populate\n */\n customer?: {\n email?: string\n name?: string\n taxId?: string\n }\n\n /**\n * Coupon code to apply\n */\n couponCode?: string\n\n /**\n * Whether to collect billing address\n */\n collectBillingAddress?: boolean\n\n /**\n * Currency for the checkout (defaults to price currency)\n */\n currency?: string\n\n /**\n * Existing subscription ID for upgrades/downgrades\n */\n existingSubscriptionId?: string\n\n /**\n * Custom metadata to attach to the subscription\n */\n metadata?: Record<string, string>\n\n /**\n * Theme for the checkout modal\n */\n theme?: 'light' | 'dark' | 'auto'\n\n /**\n * Locale for the checkout (e.g., 'en', 'es', 'fr')\n */\n locale?: string\n\n /**\n * Success callback with the created subscription\n */\n onSuccess: (subscription: any) => void\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n\n /**\n * Cancel callback when user closes without completing\n */\n onCancel?: () => void\n\n /**\n * Debug mode for development\n */\n debug?: boolean\n}\n\ntype CheckoutState = 'loading' | 'ready' | 'processing' | 'success' | 'error'\n\nexport function CheckoutModal({\n open,\n onOpenChange,\n priceId,\n customer,\n couponCode,\n collectBillingAddress,\n existingSubscriptionId,\n metadata,\n theme = 'light',\n locale = 'en',\n onSuccess,\n onError,\n onCancel,\n debug = false\n}: CheckoutModalProps) {\n const [state, setState] = useState<CheckoutState>('loading')\n const [error, setError] = useState<Error | null>(null)\n const [iframeHeight, setIframeHeight] = useState(600)\n const iframeRef = useRef<HTMLIFrameElement>(null)\n\n // Log version on mount\n useEffect(() => {\n console.log(\n '%c🚀 BillingOS SDK v1.2.0 loaded with Iframe Checkout',\n 'background: linear-gradient(to right, #667eea, #764ba2); color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;'\n )\n console.log('%c📦 Using iframe for PCI compliance and security', 'color: #10b981; font-weight: 600;')\n console.log('%c✨ Customer prefill support enabled', 'color: #8b5cf6; font-weight: 600;')\n if (debug) {\n console.log('[CheckoutModal] Debug mode enabled')\n }\n }, [])\n\n // Create checkout session when modal opens\n const { sessionId, sessionUrl, loading, error: sessionError } = useCheckoutSession({\n enabled: open,\n priceId,\n customer,\n couponCode,\n metadata,\n existingSubscriptionId\n })\n\n // Handle iframe messaging\n const handleIframeMessage = useCallback((message: IframeMessage) => {\n console.log('[CheckoutModal] Received message from iframe:', message.type, message)\n\n switch (message.type) {\n case 'CHECKOUT_READY':\n console.log('[CheckoutModal] Checkout is ready')\n setState('ready')\n break\n\n case 'CHECKOUT_SUCCESS':\n console.log('[CheckoutModal] Payment SUCCESS! Subscription:', message.payload?.subscription)\n setState('success')\n if (message.payload?.subscription) {\n console.log('[CheckoutModal] Calling onSuccess with subscription data')\n onSuccess(message.payload.subscription)\n } else {\n console.log('[CheckoutModal] No subscription data, calling onSuccess with undefined')\n onSuccess(undefined)\n }\n onOpenChange(false)\n break\n\n case 'CHECKOUT_ERROR':\n setState('error')\n const errorMessage = message.payload?.error || 'An error occurred'\n const error = new Error(errorMessage)\n setError(error)\n onError?.(error)\n break\n\n case 'CHECKOUT_CLOSE':\n onCancel?.()\n onOpenChange(false)\n break\n\n case 'HEIGHT_CHANGED':\n if (message.payload?.height) {\n setIframeHeight(message.payload.height)\n }\n break\n\n case 'PROCESSING':\n setState('processing')\n break\n\n default:\n break\n }\n }, [debug, onSuccess, onError, onCancel, onOpenChange])\n\n const { sendMessage } = useIframeMessaging({\n iframeRef,\n onMessage: handleIframeMessage,\n debug\n })\n\n // Send initialization message when iframe is ready\n useEffect(() => {\n if (sessionId && state === 'ready') {\n sendMessage({\n type: 'INIT_CHECKOUT',\n sessionId,\n config: {\n theme,\n locale,\n collectBillingAddress\n }\n })\n }\n }, [sessionId, state, theme, locale, collectBillingAddress, sendMessage])\n\n // Reset state when modal closes\n useEffect(() => {\n if (!open) {\n setState('loading')\n setError(null)\n setIframeHeight(600)\n }\n }, [open])\n\n // Handle session creation error\n useEffect(() => {\n if (sessionError) {\n setState('error')\n setError(sessionError)\n onError?.(sessionError)\n }\n }, [sessionError, onError])\n\n const showSpinner = loading || state === 'loading'\n const showError = state === 'error' && error\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n className={cn(\n \"sm:max-w-[500px] p-0 overflow-hidden\",\n \"max-h-[90vh] relative\"\n )}\n >\n {/* Iframe Badge */}\n <div className=\"absolute top-2 right-2 z-20 flex items-center gap-1 bg-gradient-to-r from-blue-600 to-purple-600 text-white text-xs font-medium px-2 py-1 rounded-full shadow-lg\">\n <svg className=\"w-3 h-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clipRule=\"evenodd\" />\n </svg>\n <span>Secure Iframe</span>\n </div>\n {showError ? (\n <div className=\"p-8 text-center\">\n <div className=\"text-red-600 mb-2\">\n <svg\n className=\"w-12 h-12 mx-auto\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">Payment Error</h3>\n <p className=\"text-gray-600\">{error.message}</p>\n <button\n onClick={() => onOpenChange(false)}\n className=\"mt-4 px-4 py-2 bg-gray-200 rounded-md hover:bg-gray-300\"\n >\n Close\n </button>\n </div>\n ) : (\n <>\n {showSpinner && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white z-10\">\n <div className=\"flex flex-col items-center\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600\"></div>\n <p className=\"mt-4 text-gray-600 font-medium\">Loading secure checkout...</p>\n <p className=\"mt-2 text-xs text-gray-500\">Iframe-based • PCI Compliant</p>\n </div>\n </div>\n )}\n\n {sessionUrl && (\n <CheckoutIframe\n ref={iframeRef}\n src={sessionUrl}\n height={iframeHeight}\n className={cn(\n \"transition-opacity duration-300\",\n showSpinner ? \"opacity-0\" : \"opacity-100\"\n )}\n onLoad={() => {\n console.log(\n '%c✅ Iframe loaded successfully',\n 'color: #10b981; font-weight: 600;',\n `\\nURL: ${sessionUrl}`\n )\n if (debug) {\n console.log('[CheckoutModal] Full iframe details:', {\n sessionUrl,\n sessionId,\n state,\n height: iframeHeight\n })\n }\n }}\n />\n )}\n\n {state === 'processing' && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/80 z-10\">\n <div className=\"flex flex-col items-center\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-green-600\"></div>\n <p className=\"mt-4 text-gray-600\">Processing payment...</p>\n </div>\n </div>\n )}\n </>\n )}\n\n {debug && (\n <div className=\"absolute bottom-0 left-0 right-0 bg-black/80 text-white p-2 text-xs\">\n <div>State: {state}</div>\n <div>Session: {sessionId || 'Creating...'}</div>\n {error && <div>Error: {error.message}</div>}\n </div>\n )}\n </DialogContent>\n </Dialog>\n )\n}","import React from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { CheckoutModal, CheckoutModalProps } from './components/CheckoutModal'\nimport { BillingOSProvider } from './providers/BillingOSProvider'\nimport { BillingOSClient } from './client'\nimport type { Subscription } from './client/types'\n\n/**\n * Options for opening the checkout modal programmatically\n */\nexport interface CheckoutOpenOptions {\n /**\n * The price ID to checkout\n */\n priceId: string\n\n /**\n * Customer information to pre-populate\n */\n customer?: {\n email?: string\n name?: string\n taxId?: string\n }\n\n /**\n * Coupon code to apply\n */\n couponCode?: string\n\n /**\n * Whether to collect billing address\n */\n collectBillingAddress?: boolean\n\n /**\n * Currency for the checkout (defaults to price currency)\n */\n currency?: string\n\n /**\n * Existing subscription ID for upgrades/downgrades\n */\n existingSubscriptionId?: string\n\n /**\n * Custom metadata to attach to the subscription\n */\n metadata?: Record<string, string>\n\n /**\n * Theme for the checkout modal\n */\n theme?: 'light' | 'dark' | 'auto'\n\n /**\n * Locale for the checkout (e.g., 'en', 'es', 'fr')\n */\n locale?: string\n\n /**\n * Success callback with the created subscription\n */\n onSuccess?: (subscription: Subscription) => void\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n\n /**\n * Cancel callback when user closes without completing\n */\n onCancel?: () => void\n\n /**\n * Debug mode for development\n */\n debug?: boolean\n\n /**\n * Session token for authentication (if not using provider)\n */\n sessionToken?: string\n\n /**\n * API base URL (if not using provider)\n */\n apiUrl?: string\n}\n\n/**\n * Programmatic checkout API\n */\nexport class CheckoutAPI {\n private client?: BillingOSClient\n private container?: HTMLElement\n private root?: ReturnType<typeof createRoot>\n\n constructor(client?: BillingOSClient) {\n this.client = client\n }\n\n /**\n * Open the checkout modal programmatically\n */\n async open(options: CheckoutOpenOptions): Promise<{ success: boolean; subscription?: Subscription; error?: Error }> {\n return new Promise((resolve) => {\n // Create container if it doesn't exist\n if (!this.container) {\n this.container = document.createElement('div')\n this.container.id = 'billingos-checkout-container'\n this.container.style.position = 'fixed'\n this.container.style.zIndex = '999999'\n document.body.appendChild(this.container)\n }\n\n // Create the modal component\n const modalProps: CheckoutModalProps = {\n open: true,\n onOpenChange: (open: boolean) => {\n if (!open) {\n this.close()\n if (options.onCancel) {\n options.onCancel()\n }\n resolve({ success: false })\n }\n },\n priceId: options.priceId,\n customer: options.customer,\n couponCode: options.couponCode,\n collectBillingAddress: options.collectBillingAddress,\n currency: options.currency,\n existingSubscriptionId: options.existingSubscriptionId,\n metadata: options.metadata,\n theme: options.theme,\n locale: options.locale,\n onSuccess: (subscription: Subscription) => {\n if (options.onSuccess) {\n options.onSuccess(subscription)\n }\n resolve({ success: true, subscription })\n this.close()\n },\n onError: (error: Error) => {\n if (options.onError) {\n options.onError(error)\n }\n resolve({ success: false, error })\n },\n onCancel: options.onCancel,\n debug: options.debug\n }\n\n // Render the modal\n if (!this.root) {\n this.root = createRoot(this.container)\n }\n\n // If we have a client, use it directly\n // Otherwise, create a new one with the provided session token\n if (this.client) {\n // Already have a provider context\n this.root.render(\n React.createElement(CheckoutModal, modalProps)\n )\n } else if (options.sessionToken) {\n // Need to create a provider\n this.root.render(\n React.createElement(\n BillingOSProvider,\n {\n sessionToken: options.sessionToken,\n options: {\n baseUrl: options.apiUrl\n },\n children: React.createElement(CheckoutModal, modalProps)\n }\n )\n )\n } else {\n // No authentication provided\n const error = new Error('No session token or BillingOS client provided')\n if (options.onError) {\n options.onError(error)\n }\n resolve({ success: false, error })\n this.close()\n }\n })\n }\n\n /**\n * Close the checkout modal\n */\n close() {\n if (this.root) {\n this.root.unmount()\n this.root = undefined\n }\n if (this.container) {\n this.container.remove()\n this.container = undefined\n }\n }\n}\n\n/**\n * Global checkout API instance\n */\nlet globalCheckoutAPI: CheckoutAPI | null = null\n\n/**\n * Get or create the global checkout API instance\n */\nexport function getCheckoutAPI(client?: BillingOSClient): CheckoutAPI {\n if (!globalCheckoutAPI) {\n globalCheckoutAPI = new CheckoutAPI(client)\n }\n return globalCheckoutAPI\n}\n\n/**\n * Convenience function to open checkout modal\n */\nexport async function openCheckout(options: CheckoutOpenOptions) {\n const api = getCheckoutAPI()\n return api.open(options)\n}","import { useState, useCallback } from 'react'\nimport { useBillingOS } from '../providers/BillingOSProvider'\nimport { getCheckoutAPI, type CheckoutOpenOptions } from '../checkout'\nimport type { Subscription } from '../client/types'\n\n/**\n * Result from opening checkout\n */\nexport interface CheckoutResult {\n success: boolean\n subscription?: Subscription\n error?: Error\n}\n\n/**\n * Hook for programmatically opening checkout\n */\nexport function useCheckout() {\n const { client } = useBillingOS()\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const openCheckout = useCallback(async (options: Omit<CheckoutOpenOptions, 'sessionToken' | 'apiUrl'>): Promise<CheckoutResult> => {\n setIsLoading(true)\n setError(null)\n\n try {\n const api = getCheckoutAPI(client)\n const result = await api.open(options)\n\n if (!result.success && result.error) {\n setError(result.error)\n }\n\n return result\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to open checkout')\n setError(error)\n return { success: false, error }\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n const closeCheckout = useCallback(() => {\n const api = getCheckoutAPI(client)\n api.close()\n }, [client])\n\n return {\n openCheckout,\n closeCheckout,\n isLoading,\n error\n }\n}","import { useQuery, useMutation, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'\nimport { useBillingOS } from '../providers'\nimport type { Entitlement, UsageEvent, UsageMetrics } from '../client'\n\n/**\n * Query keys for entitlement-related queries\n */\nexport const entitlementKeys = {\n all: ['entitlements'] as const,\n lists: () => [...entitlementKeys.all, 'list'] as const,\n list: (customerId: string) => [...entitlementKeys.lists(), customerId] as const,\n checks: () => [...entitlementKeys.all, 'check'] as const,\n check: (customerId: string, featureKey: string) =>\n [...entitlementKeys.checks(), customerId, featureKey] as const,\n usage: (customerId: string, featureKey: string) =>\n [...entitlementKeys.all, 'usage', customerId, featureKey] as const,\n}\n\n/**\n * Check if a customer has access to a specific feature\n *\n * @param customerId - Customer ID to check\n * @param featureKey - Feature key to check access for\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function FeatureGate({ children }: { children: React.ReactNode }) {\n * const { data: entitlement, isLoading } = useCheckEntitlement(\n * 'cus_123',\n * 'advanced_analytics'\n * )\n *\n * if (isLoading) return <div>Checking access...</div>\n * if (!entitlement?.has_access) {\n * return <UpgradePrompt feature=\"advanced_analytics\" />\n * }\n *\n * return <>{children}</>\n * }\n * ```\n */\nexport function useCheckEntitlement(\n customerId: string,\n featureKey: string,\n options?: Omit<UseQueryOptions<Entitlement>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: entitlementKeys.check(customerId, featureKey),\n queryFn: () => client.checkEntitlement({ customer_id: customerId, feature_key: featureKey }),\n enabled: !!customerId && !!featureKey,\n staleTime: 1000 * 60, // 1 minute (entitlements are cached server-side)\n ...options,\n })\n}\n\n/**\n * Simplified hook to check if a customer has access to a feature\n * Returns a boolean directly instead of the full Entitlement object\n *\n * @param customerId - Customer ID to check\n * @param featureKey - Feature key to check access for\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function PremiumFeature() {\n * const hasAccess = useHasFeature('cus_123', 'premium_features')\n *\n * if (!hasAccess) {\n * return <div>Upgrade to access this feature</div>\n * }\n *\n * return <div>Premium feature content here</div>\n * }\n * ```\n */\nexport function useHasFeature(\n customerId: string,\n featureKey: string,\n options?: Omit<UseQueryOptions<Entitlement>, 'queryKey' | 'queryFn'>\n): boolean {\n const { data } = useCheckEntitlement(customerId, featureKey, options)\n return data?.has_access || false\n}\n\n/**\n * Get all entitlements for a customer\n *\n * @param customerId - Customer ID\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function EntitlementsList({ customerId }: { customerId: string }) {\n * const { data: entitlements, isLoading } = useEntitlements(customerId)\n *\n * if (isLoading) return <div>Loading...</div>\n *\n * return (\n * <ul>\n * {entitlements?.map(entitlement => (\n * <li key={entitlement.feature_key}>\n * {entitlement.feature_key}: {entitlement.has_access ? '✓' : '✗'}\n * {entitlement.limit && ` (${entitlement.usage}/${entitlement.limit})`}\n * </li>\n * ))}\n * </ul>\n * )\n * }\n * ```\n */\nexport function useEntitlements(\n customerId: string,\n options?: Omit<UseQueryOptions<Entitlement[]>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: entitlementKeys.list(customerId),\n queryFn: () => client.listEntitlements(customerId),\n enabled: !!customerId,\n ...options,\n })\n}\n\n/**\n * Track a usage event for a customer\n *\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function APICallButton() {\n * const trackUsage = useTrackUsage({\n * onSuccess: () => {\n * console.log('Usage tracked')\n * }\n * })\n *\n * const handleAPICall = async () => {\n * // Make API call\n * await makeAPICall()\n *\n * // Track usage\n * trackUsage.mutate({\n * customer_id: 'cus_123',\n * feature_key: 'api_calls',\n * quantity: 1\n * })\n * }\n *\n * return <button onClick={handleAPICall}>Make API Call</button>\n * }\n * ```\n */\nexport function useTrackUsage(\n options?: Omit<UseMutationOptions<void, Error, UsageEvent>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (event: UsageEvent) => client.trackUsage(event),\n onSuccess: (_data, variables, _context) => {\n // Invalidate usage metrics for this feature\n queryClient.invalidateQueries({\n queryKey: entitlementKeys.usage(variables.customer_id || '', variables.feature_key),\n })\n // Invalidate entitlement check (usage affects has_access)\n queryClient.invalidateQueries({\n queryKey: entitlementKeys.check(variables.customer_id || '', variables.feature_key),\n })\n },\n })\n}\n\n/**\n * Get usage metrics for a customer and feature\n *\n * @param customerId - Customer ID\n * @param featureKey - Feature key\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function UsageDisplay({ customerId }: { customerId: string }) {\n * const { data: metrics, isLoading } = useUsageMetrics(\n * customerId,\n * 'api_calls'\n * )\n *\n * if (isLoading) return <div>Loading...</div>\n *\n * const percentage = metrics?.limit\n * ? (metrics.current_usage / metrics.limit) * 100\n * : 0\n *\n * return (\n * <div>\n * <h3>API Usage</h3>\n * <p>{metrics?.current_usage} / {metrics?.limit || '∞'} calls</p>\n * <progress value={percentage} max={100} />\n * <p>Period: {metrics?.period_start} - {metrics?.period_end}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useUsageMetrics(\n customerId: string,\n featureKey: string,\n options?: Omit<UseQueryOptions<UsageMetrics>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: entitlementKeys.usage(customerId, featureKey),\n queryFn: () => client.getUsageMetrics(customerId, featureKey),\n enabled: !!customerId && !!featureKey,\n ...options,\n })\n}\n\n/**\n * Check if a customer is approaching their usage limit\n *\n * @param customerId - Customer ID\n * @param featureKey - Feature key\n * @param threshold - Threshold percentage (0-100) to warn at (default: 80)\n * @param options - React Query options\n * @returns Boolean indicating if customer is approaching limit\n *\n * @example\n * ```tsx\n * function UsageWarning({ customerId }: { customerId: string }) {\n * const isApproachingLimit = useIsApproachingLimit(\n * customerId,\n * 'api_calls',\n * 80 // Warn at 80%\n * )\n *\n * if (!isApproachingLimit) return null\n *\n * return (\n * <Alert variant=\"warning\">\n * You're approaching your API call limit. Upgrade to increase your quota.\n * </Alert>\n * )\n * }\n * ```\n */\nexport function useIsApproachingLimit(\n customerId: string,\n featureKey: string,\n threshold = 80,\n options?: Omit<UseQueryOptions<UsageMetrics>, 'queryKey' | 'queryFn'>\n): boolean {\n const { data: metrics } = useUsageMetrics(customerId, featureKey, options)\n\n if (!metrics || !metrics.limit) return false\n\n const percentage = (metrics.current_usage / metrics.limit) * 100\n return percentage >= threshold\n}\n","import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useBillingOS } from '../providers/BillingOSProvider'\n\n/**\n * Feature access response\n */\nexport interface FeatureAccess {\n feature_key: string\n has_access: boolean\n limit?: number\n usage?: number\n metadata?: Record<string, any>\n}\n\n/**\n * Feature entitlement\n */\nexport interface FeatureEntitlement {\n feature_key: string\n feature_title: string\n feature_type: 'boolean_flag' | 'usage_quota' | 'numeric_limit'\n granted_at: string\n product_name: string\n subscription_status: string\n properties?: Record<string, any>\n}\n\n/**\n * Usage metric\n */\nexport interface UsageMetric {\n feature_key: string\n feature_title: string\n product_name: string\n consumed: number\n limit: number\n remaining: number\n percentage_used: number\n period_start: string\n period_end: string\n resets_in_days: number\n}\n\n/**\n * Hook to check if user has access to a feature\n */\nexport function useFeature(featureKey: string, options?: {\n refetchInterval?: number\n enabled?: boolean\n}) {\n const { client } = useBillingOS()\n\n return useQuery<FeatureAccess>({\n queryKey: ['billingos', 'features', featureKey],\n queryFn: async () => {\n return await client.get<FeatureAccess>(\n `/v1/features/check?feature_key=${featureKey}`\n )\n },\n refetchInterval: options?.refetchInterval,\n enabled: options?.enabled !== false,\n })\n}\n\n/**\n * Hook to track usage for a feature\n */\nexport function useTrackUsage() {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async ({\n featureKey,\n quantity,\n metadata\n }: {\n featureKey: string\n quantity: number\n metadata?: Record<string, any>\n }) => {\n return await client.post('/v1/features/track-usage', {\n feature_key: featureKey,\n quantity,\n metadata,\n })\n },\n onSuccess: (_, variables) => {\n // Invalidate the feature check query to refresh usage\n queryClient.invalidateQueries({\n queryKey: ['billingos', 'features', variables.featureKey]\n })\n // Also invalidate usage metrics\n queryClient.invalidateQueries({\n queryKey: ['billingos', 'usage-metrics']\n })\n },\n })\n}\n\n/**\n * Hook to get all feature entitlements for the current user\n */\nexport function useFeatureEntitlements() {\n const { client } = useBillingOS()\n\n return useQuery<{ entitlements: FeatureEntitlement[] }>({\n queryKey: ['billingos', 'entitlements'],\n queryFn: async () => {\n return await client.get<{ entitlements: FeatureEntitlement[] }>(\n '/v1/features/entitlements'\n )\n },\n })\n}\n\n/**\n * Hook to get usage metrics for features\n */\nexport function useUsageMetrics(featureKey?: string) {\n const { client } = useBillingOS()\n\n return useQuery<{ metrics: UsageMetric[] }>({\n queryKey: ['billingos', 'usage-metrics', featureKey],\n queryFn: async () => {\n const url = featureKey\n ? `/v1/features/usage-metrics?feature_key=${featureKey}`\n : '/v1/features/usage-metrics'\n return await client.get<{ metrics: UsageMetric[] }>(url)\n },\n // Refresh every 30 seconds to keep usage data fresh\n refetchInterval: 30000,\n })\n}\n\n/**\n * Hook that combines feature access check and tracks when access is denied\n */\nexport function useFeatureGate(featureKey: string, options?: {\n onAccessDenied?: () => void\n onQuotaExceeded?: (usage: number, limit: number) => void\n}) {\n const feature = useFeature(featureKey)\n\n // Call callbacks when access is denied\n if (feature.data && !feature.data.has_access) {\n if (feature.data.usage && feature.data.limit && feature.data.usage >= feature.data.limit) {\n options?.onQuotaExceeded?.(feature.data.usage, feature.data.limit)\n } else {\n options?.onAccessDenied?.()\n }\n }\n\n return {\n ...feature,\n hasAccess: feature.data?.has_access || false,\n isQuotaExceeded: feature.data?.usage && feature.data.limit\n ? feature.data.usage >= feature.data.limit\n : false,\n usage: feature.data?.usage || 0,\n limit: feature.data?.limit || 0,\n remaining: feature.data?.limit && feature.data?.usage\n ? Math.max(0, feature.data.limit - feature.data.usage)\n : 0,\n }\n}","import { useQuery } from '@tanstack/react-query'\nimport { useBillingOS } from '../providers/BillingOSProvider'\n\nexport interface Product {\n id: string\n name: string\n description?: string\n features?: string[]\n prices?: Price[]\n}\n\nexport interface Price {\n id: string\n amount: number\n currency: string\n interval?: string\n interval_count?: number\n}\n\n/**\n * Hook to fetch products for pricing table\n */\nexport function useProducts() {\n const { client } = useBillingOS()\n\n return useQuery<{ products: Product[] }>({\n queryKey: ['billingos', 'products'],\n queryFn: async () => {\n return await client.get<{ products: Product[] }>('/v1/products')\n },\n })\n}","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\nconst alertVariants = cva(\n 'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',\n {\n variants: {\n variant: {\n default: 'bg-background text-foreground',\n destructive:\n 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',\n warning:\n 'border-yellow-500/50 bg-yellow-50 text-yellow-900 dark:bg-yellow-900/10 dark:text-yellow-500 [&>svg]:text-yellow-500',\n success:\n 'border-green-500/50 bg-green-50 text-green-900 dark:bg-green-900/10 dark:text-green-500 [&>svg]:text-green-500',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n)\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n))\nAlert.displayName = 'Alert'\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn('mb-1 font-medium leading-none tracking-tight', className)}\n {...props}\n />\n))\nAlertTitle.displayName = 'AlertTitle'\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-sm [&_p]:leading-relaxed', className)}\n {...props}\n />\n))\nAlertDescription.displayName = 'AlertDescription'\n\nexport { Alert, AlertTitle, AlertDescription }\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\nconst badgeVariants = cva(\n 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',\n {\n variants: {\n variant: {\n default:\n 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',\n secondary:\n 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',\n destructive:\n 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',\n outline: 'text-foreground',\n success:\n 'border-transparent bg-green-500 text-white hover:bg-green-500/80',\n warning:\n 'border-transparent bg-yellow-500 text-white hover:bg-yellow-500/80',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\n )\n}\n\nexport { Badge, badgeVariants }\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive:\n 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline:\n 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n return (\n <button\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n )\n }\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\nconst Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'rounded-lg border bg-card text-card-foreground shadow-sm',\n className\n )}\n {...props}\n />\n))\nCard.displayName = 'Card'\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex flex-col space-y-1.5 p-6', className)}\n {...props}\n />\n))\nCardHeader.displayName = 'CardHeader'\n\nconst CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'text-2xl font-semibold leading-none tracking-tight',\n className\n )}\n {...props}\n />\n))\nCardTitle.displayName = 'CardTitle'\n\nconst CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nCardDescription.displayName = 'CardDescription'\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />\n))\nCardContent.displayName = 'CardContent'\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center p-6 pt-0', className)}\n {...props}\n />\n))\nCardFooter.displayName = 'CardFooter'\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {\n onCheckedChange?: (checked: boolean) => void\n}\n\nconst Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n ({ className, onCheckedChange, onChange, ...props }, ref) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange?.(e)\n onCheckedChange?.(e.target.checked)\n }\n\n return (\n <input\n type=\"checkbox\"\n ref={ref}\n onChange={handleChange}\n className={cn(\n 'peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 checked:bg-primary checked:text-primary-foreground',\n className\n )}\n {...props}\n />\n )\n }\n)\nCheckbox.displayName = 'Checkbox'\n\nexport { Checkbox }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface DrawerContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n}\n\nconst DrawerContext = React.createContext<DrawerContextValue | null>(null)\n\nfunction useDrawerContext() {\n const context = React.useContext(DrawerContext)\n if (!context) {\n throw new Error('Drawer components must be used within a Drawer provider')\n }\n return context\n}\n\ninterface DrawerProps {\n open?: boolean\n onOpenChange?: (open: boolean) => void\n children: React.ReactNode\n}\n\nfunction Drawer({ open = false, onOpenChange, children }: DrawerProps) {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const isOpen = open ?? internalOpen\n const handleOpenChange = onOpenChange ?? setInternalOpen\n\n // Debug logging\n React.useEffect(() => {\n console.log('[Drawer] State:', { open, internalOpen, isOpen })\n }, [open, internalOpen, isOpen])\n\n return (\n <DrawerContext.Provider value={{ open: isOpen, onOpenChange: handleOpenChange }}>\n {children}\n </DrawerContext.Provider>\n )\n}\n\ninterface DrawerTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean\n}\n\nconst DrawerTrigger = React.forwardRef<HTMLButtonElement, DrawerTriggerProps>(\n ({ onClick, ...props }, ref) => {\n const { onOpenChange } = useDrawerContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(true)\n onClick?.(e)\n }}\n {...props}\n />\n )\n }\n)\nDrawerTrigger.displayName = 'DrawerTrigger'\n\nconst DrawerClose = React.forwardRef<\n HTMLButtonElement,\n React.ButtonHTMLAttributes<HTMLButtonElement>\n>(({ onClick, ...props }, ref) => {\n const { onOpenChange } = useDrawerContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(false)\n onClick?.(e)\n }}\n {...props}\n />\n )\n})\nDrawerClose.displayName = 'DrawerClose'\n\nconst DrawerOverlay = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const { onOpenChange } = useDrawerContext()\n\n return (\n <div\n ref={ref}\n onClick={() => onOpenChange(false)}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 transition-opacity duration-300',\n className\n )}\n {...props}\n />\n )\n})\nDrawerOverlay.displayName = 'DrawerOverlay'\n\ninterface DrawerContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Whether to prevent closing when clicking outside or pressing ESC\n */\n preventClose?: boolean\n /**\n * Callback when user attempts to close but it's prevented\n */\n onCloseAttempt?: () => void\n}\n\nconst DrawerContent = React.forwardRef<HTMLDivElement, DrawerContentProps>(\n ({ className, children, preventClose = false, onCloseAttempt, ...props }, ref) => {\n const { open, onOpenChange } = useDrawerContext()\n const [isDragging, setIsDragging] = React.useState(false)\n const [dragY, setDragY] = React.useState(0)\n const contentRef = React.useRef<HTMLDivElement>(null)\n const startYRef = React.useRef(0)\n\n // Handle escape key\n React.useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n if (preventClose) {\n onCloseAttempt?.()\n } else {\n onOpenChange(false)\n }\n }\n }\n if (open) {\n document.addEventListener('keydown', handleEscape)\n document.body.style.overflow = 'hidden'\n }\n return () => {\n document.removeEventListener('keydown', handleEscape)\n document.body.style.overflow = ''\n }\n }, [open, onOpenChange, preventClose, onCloseAttempt])\n\n // Handle drag to close (mobile)\n const handleDragStart = (e: React.TouchEvent | React.MouseEvent) => {\n if (preventClose) return\n setIsDragging(true)\n const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY\n startYRef.current = clientY\n }\n\n const handleDragMove = (e: React.TouchEvent | React.MouseEvent) => {\n if (!isDragging || preventClose) return\n const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY\n const delta = clientY - startYRef.current\n if (delta > 0) {\n setDragY(delta)\n }\n }\n\n const handleDragEnd = () => {\n if (!isDragging) return\n setIsDragging(false)\n // Close if dragged more than 80px\n if (dragY > 80 && !preventClose) {\n onOpenChange(false)\n }\n setDragY(0)\n }\n\n const handleOverlayClick = () => {\n if (preventClose) {\n onCloseAttempt?.()\n } else {\n onOpenChange(false)\n }\n }\n\n // Debug logging\n console.log('[DrawerContent] Rendering, open:', open, 'preventClose:', preventClose)\n\n if (!open) {\n console.log('[DrawerContent] Not rendering because open is false')\n return null\n }\n\n return (\n <div className=\"fixed inset-0 z-50\">\n <div\n className=\"fixed inset-0 bg-black/80 transition-opacity duration-300\"\n onClick={handleOverlayClick}\n />\n <div\n ref={ref}\n className={cn(\n // Base styles\n 'fixed z-50 bg-background shadow-lg transition-transform duration-300 ease-out',\n // Mobile: bottom sheet\n 'inset-x-0 bottom-0 rounded-t-[10px] border-t',\n // Desktop: centered modal\n 'md:inset-auto md:left-1/2 md:top-1/2 md:-translate-x-1/2 md:-translate-y-1/2',\n 'md:rounded-lg md:border md:max-w-[500px] md:w-full md:max-h-[90vh]',\n className\n )}\n style={{\n transform: isDragging ? `translateY(${dragY}px)` : undefined,\n }}\n onClick={(e) => e.stopPropagation()}\n onTouchStart={handleDragStart}\n onTouchMove={handleDragMove}\n onTouchEnd={handleDragEnd}\n onMouseDown={handleDragStart}\n onMouseMove={handleDragMove}\n onMouseUp={handleDragEnd}\n onMouseLeave={handleDragEnd}\n {...props}\n >\n {/* Drag handle (mobile only) */}\n <div className=\"md:hidden flex justify-center pt-4 pb-2\">\n <div className=\"w-12 h-1.5 rounded-full bg-muted-foreground/30\" />\n </div>\n {/* Close button */}\n <button\n type=\"button\"\n onClick={() => {\n if (preventClose) {\n onCloseAttempt?.()\n } else {\n onOpenChange(false)\n }\n }}\n className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"h-4 w-4\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n <span className=\"sr-only\">Close</span>\n </button>\n <div ref={contentRef} className=\"px-6 pb-6 pt-2 md:pt-6 overflow-y-auto max-h-[80vh] md:max-h-[calc(90vh-2rem)]\">\n {children}\n </div>\n </div>\n </div>\n )\n }\n)\nDrawerContent.displayName = 'DrawerContent'\n\nconst DrawerHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)}\n {...props}\n />\n)\nDrawerHeader.displayName = 'DrawerHeader'\n\nconst DrawerFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}\n {...props}\n />\n)\nDrawerFooter.displayName = 'DrawerFooter'\n\nconst DrawerTitle = React.forwardRef<\n HTMLHeadingElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn('text-lg font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n))\nDrawerTitle.displayName = 'DrawerTitle'\n\nconst DrawerDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nDrawerDescription.displayName = 'DrawerDescription'\n\nexport {\n Drawer,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n}\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = 'Input'\n\nexport { Input }\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\nconst labelVariants = cva(\n 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'\n)\n\nexport interface LabelProps\n extends React.LabelHTMLAttributes<HTMLLabelElement>,\n VariantProps<typeof labelVariants> {}\n\nconst Label = React.forwardRef<HTMLLabelElement, LabelProps>(\n ({ className, ...props }, ref) => (\n <label ref={ref} className={cn(labelVariants(), className)} {...props} />\n )\n)\nLabel.displayName = 'Label'\n\nexport { Label }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface ProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: number\n max?: number\n indicatorClassName?: string\n}\n\nconst Progress = React.forwardRef<HTMLDivElement, ProgressProps>(\n ({ className, value = 0, max = 100, indicatorClassName, ...props }, ref) => {\n const percentage = Math.min(Math.max((value / max) * 100, 0), 100)\n\n return (\n <div\n ref={ref}\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={value}\n className={cn(\n 'relative h-4 w-full overflow-hidden rounded-full bg-secondary',\n className\n )}\n {...props}\n >\n <div\n className={cn(\n 'h-full bg-primary transition-all',\n indicatorClassName\n )}\n style={{ width: `${percentage}%` }}\n />\n </div>\n )\n }\n)\nProgress.displayName = 'Progress'\n\nexport { Progress }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface RadioGroupContextValue {\n value: string\n onValueChange: (value: string) => void\n name: string\n}\n\nconst RadioGroupContext = React.createContext<RadioGroupContextValue | null>(null)\n\nfunction useRadioGroupContext() {\n const context = React.useContext(RadioGroupContext)\n if (!context) {\n throw new Error('RadioGroup components must be used within a RadioGroup provider')\n }\n return context\n}\n\ninterface RadioGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n name?: string\n}\n\nconst RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>(\n ({ className, value, defaultValue, onValueChange, name = 'radio-group', children, ...props }, ref) => {\n const [internalValue, setInternalValue] = React.useState(defaultValue ?? '')\n const currentValue = value ?? internalValue\n const handleValueChange = onValueChange ?? setInternalValue\n\n return (\n <RadioGroupContext.Provider value={{ value: currentValue, onValueChange: handleValueChange, name }}>\n <div\n ref={ref}\n role=\"radiogroup\"\n className={cn('grid gap-2', className)}\n {...props}\n >\n {children}\n </div>\n </RadioGroupContext.Provider>\n )\n }\n)\nRadioGroup.displayName = 'RadioGroup'\n\ninterface RadioGroupItemProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {\n value: string\n}\n\nconst RadioGroupItem = React.forwardRef<HTMLInputElement, RadioGroupItemProps>(\n ({ className, value, ...props }, ref) => {\n const { value: groupValue, onValueChange, name } = useRadioGroupContext()\n const isChecked = groupValue === value\n\n return (\n <input\n ref={ref}\n type=\"radio\"\n name={name}\n value={value}\n checked={isChecked}\n onChange={() => onValueChange(value)}\n className={cn(\n 'aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n {...props}\n />\n )\n }\n)\nRadioGroupItem.displayName = 'RadioGroupItem'\n\nexport { RadioGroup, RadioGroupItem }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface ScrollAreaProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * The orientation of the scrollable area\n */\n orientation?: 'vertical' | 'horizontal' | 'both'\n \n /**\n * Always show the custom scrollbar (instead of only on hover)\n */\n alwaysShowScrollbar?: boolean\n}\n\nconst ScrollArea = React.forwardRef<HTMLDivElement, ScrollAreaProps>(\n ({ className, children, orientation = 'vertical', alwaysShowScrollbar = false, ...props }, ref) => {\n const [showScrollbar, setShowScrollbar] = React.useState(false)\n const [scrollbarHeight, setScrollbarHeight] = React.useState(0)\n const [scrollbarTop, setScrollbarTop] = React.useState(0)\n const viewportRef = React.useRef<HTMLDivElement>(null)\n\n const handleScroll = React.useCallback(() => {\n const viewport = viewportRef.current\n if (!viewport) return\n\n const { scrollTop, scrollHeight, clientHeight } = viewport\n\n // Only show scrollbar if there's actually scrollable content\n const hasScrollableContent = scrollHeight > clientHeight\n \n if (!hasScrollableContent && !alwaysShowScrollbar) {\n setScrollbarHeight(0)\n setScrollbarTop(0)\n return\n }\n\n // Calculate scrollbar dimensions\n const scrollRatio = clientHeight / scrollHeight\n const thumbHeight = Math.max(scrollRatio * clientHeight, 30) // Min 30px\n const maxScrollTop = scrollHeight - clientHeight\n const scrollProgress = maxScrollTop > 0 ? scrollTop / maxScrollTop : 0\n const maxThumbTop = clientHeight - thumbHeight\n const thumbTop = scrollProgress * maxThumbTop\n\n setScrollbarHeight(hasScrollableContent ? thumbHeight : 0)\n setScrollbarTop(thumbTop)\n }, [alwaysShowScrollbar])\n\n React.useEffect(() => {\n const viewport = viewportRef.current\n if (!viewport) return\n\n // Initial calculation\n handleScroll()\n\n // Create resize observer\n const resizeObserver = new ResizeObserver(handleScroll)\n resizeObserver.observe(viewport)\n\n // Listen for scroll events\n viewport.addEventListener('scroll', handleScroll)\n\n return () => {\n resizeObserver.disconnect()\n viewport.removeEventListener('scroll', handleScroll)\n }\n }, [handleScroll])\n\n const handleScrollbarDrag = React.useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n e.preventDefault()\n const viewport = viewportRef.current\n if (!viewport) return\n\n const { scrollHeight, clientHeight } = viewport\n const maxScrollTop = scrollHeight - clientHeight\n \n if (maxScrollTop <= 0) return // No scrollable content\n\n const scrollbarContainer = e.currentTarget.parentElement?.parentElement\n if (!scrollbarContainer) return\n\n const containerRect = scrollbarContainer.getBoundingClientRect()\n const startY = e.clientY\n const startScrollTop = viewport.scrollTop\n\n const onMouseMove = (moveEvent: MouseEvent) => {\n const deltaY = moveEvent.clientY - startY\n const containerHeight = containerRect.height\n const scrollRatio = deltaY / containerHeight\n const scrollDelta = scrollRatio * maxScrollTop\n \n const newScrollTop = Math.max(0, Math.min(maxScrollTop, startScrollTop + scrollDelta))\n viewport.scrollTop = newScrollTop\n }\n\n const onMouseUp = () => {\n document.removeEventListener('mousemove', onMouseMove)\n document.removeEventListener('mouseup', onMouseUp)\n document.body.style.userSelect = ''\n document.body.style.cursor = ''\n }\n\n document.body.style.userSelect = 'none'\n document.body.style.cursor = 'grabbing'\n document.addEventListener('mousemove', onMouseMove)\n document.addEventListener('mouseup', onMouseUp)\n },\n []\n )\n\n return (\n <div\n ref={ref}\n className={cn('relative overflow-hidden', className)}\n onMouseEnter={() => setShowScrollbar(true)}\n onMouseLeave={() => setShowScrollbar(false)}\n {...props}\n >\n <div\n ref={viewportRef}\n className={cn(\n 'h-full w-full rounded-[inherit]',\n orientation === 'vertical' && 'overflow-y-auto overflow-x-hidden',\n orientation === 'horizontal' && 'overflow-x-auto overflow-y-hidden',\n orientation === 'both' && 'overflow-auto',\n // Hide native scrollbar\n '[&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]'\n )}\n >\n {children}\n </div>\n\n {/* Custom Scrollbar */}\n {(orientation === 'vertical' || orientation === 'both') && (\n <div\n className={cn(\n 'absolute top-0 right-0 w-2.5 h-full transition-opacity duration-150',\n alwaysShowScrollbar || showScrollbar ? 'opacity-100' : 'opacity-0'\n )}\n >\n <div className=\"relative h-full w-full\">\n {/* Track - Make it visible */}\n <div className=\"absolute inset-0 rounded-full bg-gray-100 hover:bg-gray-200\" />\n {/* Thumb */}\n {scrollbarHeight > 0 && (\n <div\n className=\"absolute right-0.5 w-1.5 rounded-full bg-gray-400 hover:bg-gray-600 transition-colors cursor-pointer\"\n style={{\n height: `${scrollbarHeight}px`,\n top: `${scrollbarTop}px`,\n }}\n onMouseDown={handleScrollbarDrag}\n />\n )}\n </div>\n </div>\n )}\n </div>\n )\n }\n)\nScrollArea.displayName = 'ScrollArea'\n\nconst ScrollBar = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & {\n orientation?: 'vertical' | 'horizontal'\n }\n>(({ className, orientation = 'vertical', ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex touch-none select-none transition-colors',\n orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-[1px]',\n orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-[1px]',\n className\n )}\n {...props}\n />\n))\nScrollBar.displayName = 'ScrollBar'\n\nexport { ScrollArea, ScrollBar }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {\n onValueChange?: (value: string) => void\n}\n\nconst Select = React.forwardRef<HTMLSelectElement, SelectProps>(\n ({ className, children, onValueChange, onChange, ...props }, ref) => {\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n onChange?.(e)\n onValueChange?.(e.target.value)\n }\n\n return (\n <select\n ref={ref}\n onChange={handleChange}\n className={cn(\n 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n {...props}\n >\n {children}\n </select>\n )\n }\n)\nSelect.displayName = 'Select'\n\nconst SelectOption = React.forwardRef<\n HTMLOptionElement,\n React.OptionHTMLAttributes<HTMLOptionElement>\n>(({ className, ...props }, ref) => (\n <option ref={ref} className={cn('', className)} {...props} />\n))\nSelectOption.displayName = 'SelectOption'\n\nexport { Select, SelectOption }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface SeparatorProps extends React.HTMLAttributes<HTMLDivElement> {\n orientation?: 'horizontal' | 'vertical'\n decorative?: boolean\n}\n\nconst Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(\n (\n { className, orientation = 'horizontal', decorative = true, ...props },\n ref\n ) => (\n <div\n ref={ref}\n role={decorative ? 'none' : 'separator'}\n aria-orientation={decorative ? undefined : orientation}\n className={cn(\n 'shrink-0 bg-border',\n orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',\n className\n )}\n {...props}\n />\n )\n)\nSeparator.displayName = 'Separator'\n\nexport { Separator }\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\ninterface SheetContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n}\n\nconst SheetContext = React.createContext<SheetContextValue | null>(null)\n\nfunction useSheetContext() {\n const context = React.useContext(SheetContext)\n if (!context) {\n throw new Error('Sheet components must be used within a Sheet provider')\n }\n return context\n}\n\ninterface SheetProps {\n open?: boolean\n onOpenChange?: (open: boolean) => void\n children: React.ReactNode\n}\n\nfunction Sheet({ open = false, onOpenChange, children }: SheetProps) {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const isOpen = open ?? internalOpen\n const handleOpenChange = onOpenChange ?? setInternalOpen\n\n return (\n <SheetContext.Provider value={{ open: isOpen, onOpenChange: handleOpenChange }}>\n {children}\n </SheetContext.Provider>\n )\n}\n\ninterface SheetTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean\n}\n\nconst SheetTrigger = React.forwardRef<HTMLButtonElement, SheetTriggerProps>(\n ({ onClick, ...props }, ref) => {\n const { onOpenChange } = useSheetContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(true)\n onClick?.(e)\n }}\n {...props}\n />\n )\n }\n)\nSheetTrigger.displayName = 'SheetTrigger'\n\nconst SheetClose = React.forwardRef<\n HTMLButtonElement,\n React.ButtonHTMLAttributes<HTMLButtonElement>\n>(({ onClick, ...props }, ref) => {\n const { onOpenChange } = useSheetContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(false)\n onClick?.(e)\n }}\n {...props}\n />\n )\n})\nSheetClose.displayName = 'SheetClose'\n\nconst SheetOverlay = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const { onOpenChange } = useSheetContext()\n\n return (\n <div\n ref={ref}\n onClick={() => onOpenChange(false)}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 transition-opacity',\n className\n )}\n {...props}\n />\n )\n})\nSheetOverlay.displayName = 'SheetOverlay'\n\nconst sheetVariants = cva(\n 'fixed z-50 gap-4 bg-background p-6 shadow-lg transition-transform duration-300 ease-in-out',\n {\n variants: {\n side: {\n top: 'inset-x-0 top-0 border-b',\n bottom: 'inset-x-0 bottom-0 border-t',\n left: 'inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',\n right: 'inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',\n },\n },\n defaultVariants: {\n side: 'right',\n },\n }\n)\n\ninterface SheetContentProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof sheetVariants> {}\n\nconst SheetContent = React.forwardRef<HTMLDivElement, SheetContentProps>(\n ({ side = 'right', className, children, ...props }, ref) => {\n const { open, onOpenChange } = useSheetContext()\n\n // Handle escape key\n React.useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onOpenChange(false)\n }\n }\n if (open) {\n document.addEventListener('keydown', handleEscape)\n document.body.style.overflow = 'hidden'\n }\n return () => {\n document.removeEventListener('keydown', handleEscape)\n document.body.style.overflow = ''\n }\n }, [open, onOpenChange])\n\n if (!open) return null\n\n const getTransform = () => {\n switch (side) {\n case 'top':\n return open ? 'translateY(0)' : 'translateY(-100%)'\n case 'bottom':\n return open ? 'translateY(0)' : 'translateY(100%)'\n case 'left':\n return open ? 'translateX(0)' : 'translateX(-100%)'\n case 'right':\n return open ? 'translateX(0)' : 'translateX(100%)'\n default:\n return 'translateX(0)'\n }\n }\n\n return (\n <div className=\"fixed inset-0 z-50\">\n <SheetOverlay />\n <div\n ref={ref}\n style={{ transform: getTransform() }}\n className={cn(sheetVariants({ side }), className)}\n onClick={(e) => e.stopPropagation()}\n {...props}\n >\n {children}\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"h-4 w-4\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n <span className=\"sr-only\">Close</span>\n </button>\n </div>\n </div>\n )\n }\n)\nSheetContent.displayName = 'SheetContent'\n\nconst SheetHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col space-y-2 text-center sm:text-left',\n className\n )}\n {...props}\n />\n)\nSheetHeader.displayName = 'SheetHeader'\n\nconst SheetFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n className\n )}\n {...props}\n />\n)\nSheetFooter.displayName = 'SheetFooter'\n\nconst SheetTitle = React.forwardRef<\n HTMLHeadingElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn('text-lg font-semibold text-foreground', className)}\n {...props}\n />\n))\nSheetTitle.displayName = 'SheetTitle'\n\nconst SheetDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nSheetDescription.displayName = 'SheetDescription'\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n","import { cn } from '@/utils/cn'\n\nfunction Skeleton({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn('animate-pulse rounded-md bg-muted', className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface TabsContextValue {\n value: string\n onValueChange: (value: string) => void\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null)\n\nfunction useTabsContext() {\n const context = React.useContext(TabsContext)\n if (!context) {\n throw new Error('Tabs components must be used within a Tabs provider')\n }\n return context\n}\n\ninterface TabsProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n}\n\nconst Tabs = React.forwardRef<HTMLDivElement, TabsProps>(\n ({ className, value, defaultValue, onValueChange, children, ...props }, ref) => {\n const [internalValue, setInternalValue] = React.useState(defaultValue ?? '')\n const currentValue = value ?? internalValue\n const handleValueChange = onValueChange ?? setInternalValue\n\n return (\n <TabsContext.Provider value={{ value: currentValue, onValueChange: handleValueChange }}>\n <div ref={ref} className={cn('', className)} {...props}>\n {children}\n </div>\n </TabsContext.Provider>\n )\n }\n)\nTabs.displayName = 'Tabs'\n\nconst TabsList = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"tablist\"\n className={cn(\n 'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',\n className\n )}\n {...props}\n />\n))\nTabsList.displayName = 'TabsList'\n\ninterface TabsTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n value: string\n}\n\nconst TabsTrigger = React.forwardRef<HTMLButtonElement, TabsTriggerProps>(\n ({ className, value, ...props }, ref) => {\n const { value: currentValue, onValueChange } = useTabsContext()\n const isSelected = currentValue === value\n\n return (\n <button\n ref={ref}\n role=\"tab\"\n type=\"button\"\n aria-selected={isSelected}\n data-state={isSelected ? 'active' : 'inactive'}\n onClick={() => onValueChange(value)}\n className={cn(\n 'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n isSelected\n ? 'bg-background text-foreground shadow-sm'\n : 'hover:bg-background/50 hover:text-foreground',\n className\n )}\n {...props}\n />\n )\n }\n)\nTabsTrigger.displayName = 'TabsTrigger'\n\ninterface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string\n}\n\nconst TabsContent = React.forwardRef<HTMLDivElement, TabsContentProps>(\n ({ className, value, children, ...props }, ref) => {\n const { value: currentValue } = useTabsContext()\n const isSelected = currentValue === value\n\n if (!isSelected) return null\n\n return (\n <div\n ref={ref}\n role=\"tabpanel\"\n data-state={isSelected ? 'active' : 'inactive'}\n className={cn(\n 'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n }\n)\nTabsContent.displayName = 'TabsContent'\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n","import * as React from 'react'\nimport { cn } from '@/utils/cn'\n\nconst Textarea = React.forwardRef<\n HTMLTextAreaElement,\n React.ComponentProps<'textarea'>\n>(({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n 'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n className\n )}\n ref={ref}\n {...props}\n />\n )\n})\nTextarea.displayName = 'Textarea'\n\nexport { Textarea }\n","import { forwardRef } from 'react'\nimport { cn } from '../../utils/cn'\n\ninterface PortalIframeProps {\n src: string\n height?: number\n className?: string\n onLoad?: () => void\n}\n\nexport const PortalIframe = forwardRef<HTMLIFrameElement, PortalIframeProps>(\n ({ src, height = 600, className, onLoad }, ref) => {\n return (\n <iframe\n ref={ref}\n src={src}\n className={cn('w-full border-0', className)}\n style={{ height: `${height}px` }}\n allow=\"payment\"\n sandbox=\"allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox\"\n onLoad={onLoad}\n title=\"Customer Portal\"\n />\n )\n }\n)\n\nPortalIframe.displayName = 'PortalIframe'\n","import { useState, useEffect } from 'react'\nimport { useBillingOS } from '../../../providers/BillingOSProvider'\n\ninterface UsePortalSessionOptions {\n enabled: boolean\n customerId?: string\n metadata?: Record<string, any>\n}\n\ninterface UsePortalSessionReturn {\n sessionId: string | null\n sessionUrl: string | null\n loading: boolean\n error: Error | null\n refresh: () => Promise<void>\n}\n\nexport function usePortalSession({\n enabled,\n customerId,\n metadata\n}: UsePortalSessionOptions): UsePortalSessionReturn {\n const { client } = useBillingOS()\n const [sessionId, setSessionId] = useState<string | null>(null)\n const [sessionUrl, setSessionUrl] = useState<string | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const createSession = async () => {\n if (!enabled) return\n\n console.log(\n '%c🔄 Creating portal session...',\n 'color: #3b82f6; font-weight: 600;'\n )\n\n setLoading(true)\n setError(null)\n\n try {\n // Create portal session via API\n const session = await client.portal.createSession({\n customerId,\n metadata\n })\n\n setSessionId(session.id)\n console.log(\n '%c✨ Portal session created!',\n 'color: #10b981; font-weight: 600;',\n `ID: ${session.id}`\n )\n\n // Generate iframe URL\n const billingOSAppUrl = process.env.NEXT_PUBLIC_BILLINGOS_APP_URL || 'http://localhost:3000'\n const iframeUrl = `${billingOSAppUrl}/embed/portal/${session.id}`\n setSessionUrl(iframeUrl)\n\n console.log(\n '%c📍 Iframe URL ready',\n 'color: #8b5cf6; font-weight: 600;',\n iframeUrl\n )\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to create portal session')\n setError(error)\n console.error('[usePortalSession] Error creating session:', error)\n } finally {\n setLoading(false)\n }\n }\n\n // Create session when enabled\n useEffect(() => {\n if (enabled && !sessionId) {\n createSession()\n }\n }, [enabled])\n\n // Cleanup session when component unmounts\n useEffect(() => {\n return () => {\n // Optionally invalidate session\n // if (sessionId) {\n // client.portal.invalidateSession(sessionId).catch(() => {})\n // }\n }\n }, [sessionId])\n\n const refresh = async () => {\n setSessionId(null)\n setSessionUrl(null)\n await createSession()\n }\n\n return {\n sessionId,\n sessionUrl,\n loading,\n error,\n refresh\n }\n}\n","import { useEffect, useCallback, RefObject } from 'react'\n\nexport interface IframeMessage {\n type:\n | 'PORTAL_READY'\n | 'PORTAL_CLOSE'\n | 'SUBSCRIPTION_UPDATED'\n | 'SUBSCRIPTION_CANCELLED'\n | 'PAYMENT_METHOD_ADDED'\n | 'PAYMENT_METHOD_UPDATED'\n | 'HEIGHT_CHANGED'\n | 'OPEN_PRICING_TABLE'\n | 'CLOSE_PRICING_TABLE'\n | 'ERROR'\n payload?: any\n}\n\nexport interface ParentMessage {\n type: 'INIT_PORTAL' | 'UPDATE_CONFIG' | 'CLOSE_PORTAL'\n sessionId?: string\n config?: {\n theme?: 'light' | 'dark' | 'auto'\n locale?: string\n defaultTab?: string\n }\n payload?: any\n}\n\ninterface UsePortalMessagingOptions {\n iframeRef: RefObject<HTMLIFrameElement | null>\n onMessage: (message: IframeMessage) => void\n debug?: boolean\n}\n\ninterface UsePortalMessagingReturn {\n sendMessage: (message: ParentMessage) => void\n}\n\nexport function usePortalMessaging({\n iframeRef,\n onMessage,\n debug = false\n}: UsePortalMessagingOptions): UsePortalMessagingReturn {\n\n /**\n * Send message to iframe\n */\n const sendMessage = useCallback((message: ParentMessage) => {\n const iframe = iframeRef.current\n if (!iframe || !iframe.contentWindow) {\n console.warn('[usePortalMessaging] Iframe not ready')\n return\n }\n\n if (debug) {\n console.log('[usePortalMessaging] 📤 Sending to iframe:', message)\n }\n\n // Get target origin from iframe src\n const iframeSrc = iframe.src\n const targetOrigin = new URL(iframeSrc).origin\n\n iframe.contentWindow.postMessage(message, targetOrigin)\n }, [iframeRef, debug])\n\n /**\n * Listen for messages from iframe\n */\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n // Validate message structure\n if (!event.data || typeof event.data !== 'object' || !event.data.type) {\n return\n }\n\n // Validate origin (should be from BillingOS app)\n const iframe = iframeRef.current\n if (!iframe) return\n\n const iframeSrc = iframe.src\n if (!iframeSrc) return\n\n const expectedOrigin = new URL(iframeSrc).origin\n if (event.origin !== expectedOrigin && process.env.NODE_ENV !== 'development') {\n console.warn(`[usePortalMessaging] Message from unexpected origin: ${event.origin}`)\n return\n }\n\n const message = event.data as IframeMessage\n\n if (debug) {\n console.log('[usePortalMessaging] 📥 Received from iframe:', message)\n }\n\n onMessage(message)\n }\n\n window.addEventListener('message', handleMessage)\n\n return () => {\n window.removeEventListener('message', handleMessage)\n }\n }, [iframeRef, onMessage, debug])\n\n return {\n sendMessage\n }\n}\n","import * as React from \"react\"\n\nimport { cn } from \"../../utils/cn\"\n\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement>\n>(({ className, ...props }, ref) => (\n <div className=\"relative w-full overflow-auto\">\n <table\n ref={ref}\n className={cn(\"w-full caption-bottom text-sm\", className)}\n {...props}\n />\n </div>\n))\nTable.displayName = \"Table\"\n\nconst TableHeader = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <thead ref={ref} className={cn(\"[&_tr]:border-b\", className)} {...props} />\n))\nTableHeader.displayName = \"TableHeader\"\n\nconst TableBody = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tbody\n ref={ref}\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n))\nTableBody.displayName = \"TableBody\"\n\nconst TableFooter = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className\n )}\n {...props}\n />\n))\nTableFooter.displayName = \"TableFooter\"\n\nconst TableRow = React.forwardRef<\n HTMLTableRowElement,\n React.HTMLAttributes<HTMLTableRowElement>\n>(({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n \"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted\",\n className\n )}\n {...props}\n />\n))\nTableRow.displayName = \"TableRow\"\n\nconst TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n \"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0\",\n className\n )}\n {...props}\n />\n))\nTableHead.displayName = \"TableHead\"\n\nconst TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn(\"p-4 align-middle [&:has([role=checkbox])]:pr-0\", className)}\n {...props}\n />\n))\nTableCell.displayName = \"TableCell\"\n\nconst TableCaption = React.forwardRef<\n HTMLTableCaptionElement,\n React.HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n <caption\n ref={ref}\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\n {...props}\n />\n))\nTableCaption.displayName = \"TableCaption\"\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { useBillingOS } from '../../../providers/BillingOSProvider'\nimport type { GetProductsResponse } from '../../../client/types'\n\nexport interface UseProductsOptions {\n /**\n * Optional array of plan IDs to filter\n */\n planIds?: string[]\n /**\n * Whether to enable the query\n */\n enabled?: boolean\n}\n\n/**\n * Hook to fetch products for pricing table\n */\nexport function useProducts(options: UseProductsOptions = {}) {\n const { client } = useBillingOS()\n const { planIds, enabled = true } = options\n\n return useQuery<GetProductsResponse, Error>({\n queryKey: ['products', planIds],\n queryFn: async () => {\n return client.getProducts(planIds)\n },\n enabled,\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 10 * 60 * 1000, // 10 minutes\n })\n}\n","import * as React from 'react'\n\ninterface ErrorBoundaryState {\n hasError: boolean\n error: Error | null\n}\n\ninterface ErrorBoundaryProps {\n children: React.ReactNode\n fallback?: (error: Error | null, reset: () => void) => React.ReactNode\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void\n}\n\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props)\n this.state = { hasError: false, error: null }\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n // Update state so the next render will show the fallback UI\n return { hasError: true, error }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n // Log the error to console in development\n console.error('[ErrorBoundary] Caught error:', error)\n console.error('[ErrorBoundary] Error info:', errorInfo)\n\n // Call the optional error handler\n this.props.onError?.(error, errorInfo)\n }\n\n reset = () => {\n this.setState({ hasError: false, error: null })\n }\n\n render() {\n if (this.state.hasError) {\n // If a custom fallback is provided, use it\n if (this.props.fallback) {\n return this.props.fallback(this.state.error, this.reset)\n }\n\n // Default fallback UI\n return (\n <div style={{\n padding: '20px',\n border: '1px solid #ef4444',\n borderRadius: '8px',\n backgroundColor: '#fee2e2',\n color: '#991b1b',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n }}>\n <h3 style={{ margin: '0 0 10px 0', fontSize: '16px', fontWeight: 'bold' }}>\n Payment Error\n </h3>\n <p style={{ margin: '0 0 10px 0', fontSize: '14px' }}>\n {this.state.error?.message || 'An unexpected error occurred while loading the payment form.'}\n </p>\n <button\n onClick={this.reset}\n style={{\n padding: '8px 16px',\n border: 'none',\n borderRadius: '6px',\n backgroundColor: '#ef4444',\n color: 'white',\n fontSize: '14px',\n cursor: 'pointer',\n fontWeight: '500',\n }}\n >\n Try Again\n </button>\n </div>\n )\n }\n\n return this.props.children\n }\n}\n\n// Hook for using error boundary programmatically\nexport function useErrorHandler() {\n const [error, setError] = React.useState<Error | null>(null)\n\n React.useEffect(() => {\n if (error) {\n throw error\n }\n }, [error])\n\n return setError\n}","import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useBillingOS } from '../../../providers/BillingOSProvider'\nimport type {\n CreateCheckoutInput,\n CreateCheckoutResponse,\n ConfirmCheckoutResponse,\n} from '../../../client/types'\n\n/**\n * Hook to create a checkout session\n */\nexport function useCreateCheckout(\n input: CreateCheckoutInput | null,\n options?: {\n enabled?: boolean\n onSuccess?: (data: CreateCheckoutResponse) => void\n onError?: (error: Error) => void\n }\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: ['checkout', input?.priceId, input?.existingSubscriptionId],\n queryFn: async () => {\n if (!input) throw new Error('Checkout input is required')\n return client.createCheckout(input)\n },\n enabled: options?.enabled !== false && !!input,\n staleTime: 0, // Always fetch fresh checkout session\n gcTime: 0, // Don't cache checkout sessions\n })\n}\n\n/**\n * Hook to confirm a checkout after payment\n */\nexport function useConfirmCheckout(options?: {\n onSuccess?: (data: ConfirmCheckoutResponse) => void\n onError?: (error: Error) => void\n}) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async ({\n clientSecret,\n paymentMethodId,\n }: {\n clientSecret: string\n paymentMethodId: string\n }) => {\n return client.confirmCheckout(clientSecret, paymentMethodId)\n },\n onSuccess: (data) => {\n // Invalidate subscription queries after successful checkout\n queryClient.invalidateQueries({ queryKey: ['portal'] })\n queryClient.invalidateQueries({ queryKey: ['subscriptions'] })\n options?.onSuccess?.(data)\n },\n onError: (error) => {\n options?.onError?.(error as Error)\n },\n })\n}\n","import * as React from 'react'\nimport {\n PaymentElement,\n ExpressCheckoutElement,\n useStripe,\n useElements,\n} from '@stripe/react-stripe-js'\nimport type { StripeExpressCheckoutElementConfirmEvent } from '@stripe/stripe-js'\nimport { Button } from '../ui/button'\nimport { Alert, AlertDescription } from '../ui/alert'\nimport { Separator } from '../ui/separator'\nimport { cn } from '@/utils/cn'\nimport type { CheckoutSession } from '../../client/types'\nimport { useBillingOS } from '../../providers/BillingOSProvider'\n\ninterface PaymentFormProps {\n checkoutSession: CheckoutSession\n onSuccess: (subscriptionId: string) => void\n onError?: (error: string) => void\n isProcessing: boolean\n setIsProcessing: (processing: boolean) => void\n}\n\nexport function PaymentForm({\n checkoutSession,\n onSuccess,\n onError,\n isProcessing,\n setIsProcessing,\n}: PaymentFormProps) {\n const { client } = useBillingOS()\n const stripe = useStripe()\n const elements = useElements()\n const [error, setError] = React.useState<string | null>(null)\n const [isExpressCheckoutReady, setIsExpressCheckoutReady] = React.useState(false)\n\n const formatAmount = (cents: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(cents / 100)\n }\n\n const totalAmount = checkoutSession.proration?.total ?? checkoutSession.amount\n const formattedAmount = formatAmount(totalAmount, checkoutSession.currency)\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!stripe || !elements) {\n return\n }\n\n setIsProcessing(true)\n setError(null)\n\n try {\n // Confirm payment with Stripe\n const { error: submitError, paymentIntent } = await stripe.confirmPayment({\n elements,\n confirmParams: {\n return_url: `${window.location.origin}/billing/success`,\n },\n redirect: 'if_required',\n })\n\n if (submitError) {\n setError(submitError.message || 'Payment failed')\n onError?.(submitError.message || 'Payment failed')\n setIsProcessing(false)\n return\n }\n\n // Payment successful - confirm with backend to create subscription\n if (paymentIntent?.status === 'succeeded' && paymentIntent.payment_method) {\n try {\n const result = await client.confirmCheckout(\n checkoutSession.clientSecret,\n paymentIntent.payment_method as string\n )\n\n if (result.success) {\n onSuccess(result.subscriptionId)\n } else {\n throw new Error(result.message || 'Failed to create subscription')\n }\n } catch (confirmError) {\n const message = confirmError instanceof Error ? confirmError.message : 'Failed to complete checkout'\n setError(message)\n onError?.(message)\n setIsProcessing(false)\n return\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Payment failed'\n setError(message)\n onError?.(message)\n } finally {\n setIsProcessing(false)\n }\n }\n\n const handleExpressCheckout = async (_event: StripeExpressCheckoutElementConfirmEvent) => {\n if (!stripe || !elements) {\n return\n }\n\n setIsProcessing(true)\n setError(null)\n\n try {\n const { error: submitError } = await stripe.confirmPayment({\n elements,\n clientSecret: checkoutSession.clientSecret,\n confirmParams: {\n return_url: `${window.location.origin}/billing/success`,\n },\n redirect: 'if_required',\n })\n\n if (submitError) {\n setError(submitError.message || 'Payment failed')\n onError?.(submitError.message || 'Payment failed')\n setIsProcessing(false)\n return\n }\n\n // Express checkout successful\n onSuccess(checkoutSession.id)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Payment failed'\n setError(message)\n onError?.(message)\n } finally {\n setIsProcessing(false)\n }\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {/* Express Checkout (Apple Pay, Google Pay, Link) */}\n <div className={cn(!isExpressCheckoutReady && 'hidden')}>\n <ExpressCheckoutElement\n options={{\n wallets: {\n applePay: 'auto',\n googlePay: 'auto',\n },\n }}\n onConfirm={handleExpressCheckout}\n onReady={() => setIsExpressCheckoutReady(true)}\n />\n </div>\n\n {/* Separator */}\n {isExpressCheckoutReady && (\n <div className=\"relative\">\n <div className=\"absolute inset-0 flex items-center\">\n <Separator className=\"w-full\" />\n </div>\n <div className=\"relative flex justify-center text-xs uppercase\">\n <span className=\"bg-background px-2 text-muted-foreground\">\n or pay with card\n </span>\n </div>\n </div>\n )}\n\n {/* Card Payment Form */}\n <div className=\"space-y-4\">\n <PaymentElement\n options={{\n layout: 'tabs',\n }}\n />\n </div>\n\n {/* Error Message */}\n {error && (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n {/* Submit Button */}\n <Button\n type=\"submit\"\n className=\"w-full\"\n size=\"lg\"\n disabled={!stripe || isProcessing}\n >\n {isProcessing ? (\n <span className=\"flex items-center gap-2\">\n <svg\n className=\"animate-spin h-4 w-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n Processing...\n </span>\n ) : checkoutSession.proration ? (\n `Upgrade Now - ${formattedAmount}`\n ) : (\n `Subscribe - ${formattedAmount}`\n )}\n </Button>\n\n {/* Security Badge */}\n <div className=\"flex items-center justify-center gap-2 text-xs text-muted-foreground\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n <span>Secured by Stripe • Cancel anytime</span>\n </div>\n </form>\n )\n}\n","import * as React from 'react'\nimport { Button } from '../ui/button'\nimport { Input } from '../ui/input'\nimport { Label } from '../ui/label'\nimport type { CheckoutSession } from '../../client/types'\n\ninterface DemoPaymentFormProps {\n checkoutSession: CheckoutSession\n onSuccess: (subscriptionId: string) => void\n isProcessing: boolean\n setIsProcessing: (processing: boolean) => void\n}\n\nexport function DemoPaymentForm({\n checkoutSession,\n onSuccess,\n isProcessing,\n setIsProcessing,\n}: DemoPaymentFormProps) {\n const [cardNumber, setCardNumber] = React.useState('')\n const [expiry, setExpiry] = React.useState('')\n const [cvc, setCvc] = React.useState('')\n\n const formatAmount = (cents: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(cents / 100)\n }\n\n const totalAmount = checkoutSession.proration?.total ?? checkoutSession.amount\n const formattedAmount = formatAmount(totalAmount, checkoutSession.currency)\n\n const formatCardNumber = (value: string) => {\n const digits = value.replace(/\\D/g, '')\n const groups = digits.match(/.{1,4}/g)\n return groups ? groups.join(' ').substring(0, 19) : ''\n }\n\n const formatExpiry = (value: string) => {\n const digits = value.replace(/\\D/g, '')\n if (digits.length >= 2) {\n return `${digits.slice(0, 2)}/${digits.slice(2, 4)}`\n }\n return digits\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n setIsProcessing(true)\n\n // Simulate payment processing\n await new Promise((resolve) => setTimeout(resolve, 2000))\n\n // Simulate success\n onSuccess(`sub_demo_${Date.now()}`)\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {/* Mock Express Checkout Buttons */}\n <div className=\"grid grid-cols-2 gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"h-12\"\n disabled={isProcessing}\n onClick={() => {\n setIsProcessing(true)\n setTimeout(() => onSuccess(`sub_demo_apple_${Date.now()}`), 2000)\n }}\n >\n <svg viewBox=\"0 0 24 24\" className=\"w-5 h-5 mr-2\" fill=\"currentColor\">\n <path d=\"M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z\" />\n </svg>\n Apple Pay\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"h-12\"\n disabled={isProcessing}\n onClick={() => {\n setIsProcessing(true)\n setTimeout(() => onSuccess(`sub_demo_google_${Date.now()}`), 2000)\n }}\n >\n <svg viewBox=\"0 0 24 24\" className=\"w-5 h-5 mr-2\">\n <path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\" />\n <path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" />\n <path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </svg>\n Google Pay\n </Button>\n </div>\n\n {/* Separator */}\n <div className=\"relative\">\n <div className=\"absolute inset-0 flex items-center\">\n <span className=\"w-full border-t\" />\n </div>\n <div className=\"relative flex justify-center text-xs uppercase\">\n <span className=\"bg-background px-2 text-muted-foreground\">\n or pay with card\n </span>\n </div>\n </div>\n\n {/* Card Form */}\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"card-number\">Card number</Label>\n <Input\n id=\"card-number\"\n placeholder=\"1234 5678 9012 3456\"\n value={cardNumber}\n onChange={(e) => setCardNumber(formatCardNumber(e.target.value))}\n disabled={isProcessing}\n maxLength={19}\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"expiry\">Expiry date</Label>\n <Input\n id=\"expiry\"\n placeholder=\"MM/YY\"\n value={expiry}\n onChange={(e) => setExpiry(formatExpiry(e.target.value))}\n disabled={isProcessing}\n maxLength={5}\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"cvc\">CVC</Label>\n <Input\n id=\"cvc\"\n placeholder=\"123\"\n value={cvc}\n onChange={(e) => setCvc(e.target.value.replace(/\\D/g, '').substring(0, 4))}\n disabled={isProcessing}\n maxLength={4}\n />\n </div>\n </div>\n </div>\n\n {/* Submit Button */}\n <Button\n type=\"submit\"\n className=\"w-full\"\n size=\"lg\"\n disabled={isProcessing}\n >\n {isProcessing ? (\n <span className=\"flex items-center gap-2\">\n <svg\n className=\"animate-spin h-4 w-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n Processing...\n </span>\n ) : checkoutSession.proration ? (\n `Upgrade Now - ${formattedAmount}`\n ) : (\n `Subscribe - ${formattedAmount}`\n )}\n </Button>\n\n {/* Security Badge */}\n <div className=\"flex items-center justify-center gap-2 text-xs text-muted-foreground\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n <span>Secured by Stripe - Cancel anytime</span>\n </div>\n </form>\n )\n}\n","/**\n * Stripe Configuration for BillingOS SDK\n *\n * This file contains the BillingOS platform's Stripe publishable key.\n * This key is bundled with the SDK and is safe to expose publicly.\n *\n * Merchants never see or configure this - it's completely internal to BillingOS.\n * Payments are routed to merchant's Stripe Connect accounts via the stripeAccount parameter.\n */\n\n/**\n * BillingOS Platform Stripe Publishable Key\n *\n * This is the platform's key (not the merchant's).\n * It's paired with the merchant's Stripe Connect account ID to route payments correctly.\n */\nexport const BILLINGOS_STRIPE_PUBLISHABLE_KEY =\n 'pk_test_51SihBODiEfx9xR94hb9APIlKq2CEr3uJqjQ1j98VdO5i30EGWi4HieGFjy1O3lEF3OWangT10RYr2Kae4CxfAvYd00xEVl0Raw'\n\n/**\n * Check if a Stripe key is valid format\n */\nexport function isValidStripeKey(key: string): boolean {\n return Boolean(key && (key.startsWith('pk_live_') || key.startsWith('pk_test_')) && key.length > 20)\n}\n\n/**\n * Check if a client secret is valid format\n */\nexport function isValidClientSecret(secret: string): boolean {\n // Valid client secrets look like: pi_xxx_secret_xxx or seti_xxx_secret_xxx\n return Boolean(secret && /^(pi|seti)_[a-zA-Z0-9]+_secret_[a-zA-Z0-9]+$/.test(secret))\n}\n","import * as React from 'react'\nimport { loadStripe } from '@stripe/stripe-js'\nimport { Elements } from '@stripe/react-stripe-js'\nimport { useQueryClient } from '@tanstack/react-query'\nimport type { Stripe, Appearance } from '@stripe/stripe-js'\nimport {\n Drawer,\n DrawerContent,\n DrawerHeader,\n DrawerTitle,\n DrawerDescription,\n} from '../ui/drawer'\nimport { ErrorBoundary } from '../ErrorBoundary'\nimport { Card, CardContent } from '../ui/card'\nimport { Badge } from '../ui/badge'\nimport { Skeleton } from '../ui/skeleton'\nimport { Alert, AlertDescription } from '../ui/alert'\nimport { Button } from '../ui/button'\nimport { Separator } from '../ui/separator'\nimport { useBillingOS } from '../../providers/BillingOSProvider'\nimport { useCreateCheckout } from './hooks/useCheckout'\nimport { PaymentForm } from './PaymentForm'\nimport { DemoPaymentForm } from './DemoPaymentForm'\nimport { BILLINGOS_STRIPE_PUBLISHABLE_KEY, isValidStripeKey, isValidClientSecret } from '../../config/stripe'\n\nexport interface PaymentBottomSheetProps {\n /**\n * Price ID to purchase\n */\n priceId: string\n\n /**\n * Open/close state\n */\n isOpen: boolean\n\n /**\n * Callback when user closes sheet\n */\n onClose: () => void\n\n /**\n * Callback when payment succeeds\n */\n onSuccess: (subscriptionId: string) => void\n\n /**\n * Optional: Subscription ID if upgrading\n */\n existingSubscriptionId?: string\n\n /**\n * Optional: Custom theme\n */\n theme?: 'light' | 'dark'\n}\n\ntype SheetState = 'loading' | 'ready' | 'processing' | 'success' | 'error'\n\nexport function PaymentBottomSheet({\n priceId,\n isOpen,\n onClose,\n onSuccess,\n existingSubscriptionId,\n theme,\n}: PaymentBottomSheetProps) {\n // Debug logging\n console.log('[PaymentBottomSheet v0.1.3] Rendering with checkout fix:', {\n priceId,\n isOpen,\n existingSubscriptionId,\n theme\n })\n\n const { customerEmail, customerName } = useBillingOS()\n const queryClient = useQueryClient()\n const [stripePromise, setStripePromise] = React.useState<Promise<Stripe | null> | null>(null)\n const [sheetState, setSheetState] = React.useState<SheetState>('loading')\n const [error, setError] = React.useState<string | null>(null)\n const [isProcessing, setIsProcessing] = React.useState(false)\n const [isDemoMode, setIsDemoMode] = React.useState(false)\n\n // Log state changes\n React.useEffect(() => {\n console.log('[PaymentBottomSheet] State changed:', {\n sheetState,\n error,\n isProcessing,\n isDemoMode,\n hasStripePromise: !!stripePromise\n })\n }, [sheetState, error, isProcessing, isDemoMode, stripePromise])\n\n // Create checkout session\n const {\n data: checkoutData,\n error: checkoutError,\n refetch: refetchCheckout,\n } = useCreateCheckout(\n isOpen\n ? {\n priceId,\n customerEmail,\n customerName,\n existingSubscriptionId,\n }\n : null,\n {\n enabled: isOpen,\n }\n )\n\n // The API returns the checkout session directly\n const checkoutSession = checkoutData\n\n // Log checkout session data\n React.useEffect(() => {\n console.log('[PaymentBottomSheet] Checkout session data:', {\n hasCheckoutData: !!checkoutData,\n checkoutSession: checkoutSession,\n checkoutError: checkoutError?.message,\n isOpen\n })\n }, [checkoutData, checkoutSession, checkoutError, isOpen])\n\n // Initialize Stripe when checkout session is ready\n React.useEffect(() => {\n console.log('[PaymentBottomSheet] Stripe initialization effect triggered')\n if (checkoutSession) {\n const validKey = isValidStripeKey(BILLINGOS_STRIPE_PUBLISHABLE_KEY)\n const validSecret = isValidClientSecret(checkoutSession.clientSecret)\n\n console.log('[PaymentBottomSheet] Stripe validation:', {\n publishableKey: BILLINGOS_STRIPE_PUBLISHABLE_KEY,\n validKey,\n clientSecret: checkoutSession.clientSecret?.substring(0, 20) + '...',\n validSecret,\n stripeAccountId: checkoutSession.stripeAccountId\n })\n\n if (validKey && validSecret) {\n // Use BillingOS platform Stripe key with merchant's Connect account ID\n console.log('[PaymentBottomSheet] Loading Stripe with valid credentials')\n const stripe = loadStripe(BILLINGOS_STRIPE_PUBLISHABLE_KEY, {\n stripeAccount: checkoutSession.stripeAccountId,\n })\n setStripePromise(stripe)\n setIsDemoMode(false)\n } else {\n // Demo mode - invalid credentials\n console.log('[PaymentBottomSheet] Invalid Stripe credentials, entering demo mode')\n setIsDemoMode(true)\n }\n setSheetState('ready')\n }\n }, [checkoutSession])\n\n // Handle checkout error\n React.useEffect(() => {\n if (checkoutError) {\n setError(checkoutError.message || 'Failed to create checkout session')\n setSheetState('error')\n }\n }, [checkoutError])\n\n // Reset state when closed\n React.useEffect(() => {\n if (!isOpen) {\n setSheetState('loading')\n setError(null)\n setStripePromise(null)\n setIsDemoMode(false)\n }\n }, [isOpen])\n\n const handlePaymentSuccess = (subscriptionId: string) => {\n setSheetState('success')\n\n // Invalidate products query to refresh pricing table with new subscription status\n queryClient.invalidateQueries({ queryKey: ['billingos', 'products'] })\n console.log('💫 Invalidated products query - PricingTable will auto-refresh')\n\n setTimeout(() => {\n onSuccess(subscriptionId)\n }, 1500)\n }\n\n const handlePaymentError = (errorMessage: string) => {\n setError(errorMessage)\n }\n\n const handleClose = () => {\n console.log('[PaymentBottomSheet] handleClose called, isProcessing:', isProcessing)\n if (isProcessing) {\n // Show confirmation if payment is processing\n const confirmed = window.confirm(\n 'Your payment is being processed. Are you sure you want to close?'\n )\n if (!confirmed) return\n }\n onClose()\n }\n\n const handleRetry = () => {\n setError(null)\n setSheetState('loading')\n refetchCheckout()\n }\n\n // Stripe appearance based on theme\n const appearance: Appearance = {\n theme: theme === 'dark' ? 'night' : 'stripe',\n variables: {\n colorPrimary: '#3B82F6',\n borderRadius: '8px',\n },\n }\n\n const formatAmount = (cents: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(cents / 100)\n }\n\n const formatInterval = (interval: string) => {\n switch (interval) {\n case 'day':\n return 'day'\n case 'week':\n return 'week'\n case 'month':\n return 'month'\n case 'year':\n return 'year'\n default:\n return interval\n }\n }\n\n // Log render\n console.log('[PaymentBottomSheet] Rendering drawer with isOpen:', isOpen, 'sheetState:', sheetState)\n\n return (\n <ErrorBoundary\n fallback={(error, reset) => (\n <div style={{ padding: '20px', maxWidth: '400px', margin: '0 auto' }}>\n <Alert variant=\"destructive\">\n <AlertDescription>\n Failed to load payment form: {error?.message || 'Unknown error'}\n </AlertDescription>\n </Alert>\n <div className=\"mt-4 flex gap-2\">\n <Button variant=\"outline\" onClick={onClose}>Cancel</Button>\n <Button onClick={reset}>Try Again</Button>\n </div>\n </div>\n )}\n onError={(error, errorInfo) => {\n console.error('[PaymentBottomSheet] Error caught by boundary:', error)\n console.error('[PaymentBottomSheet] Error info:', errorInfo)\n }}\n >\n <Drawer open={isOpen} onOpenChange={(open) => {\n console.log('[PaymentBottomSheet] Drawer.onOpenChange called with open:', open)\n if (!open) {\n handleClose()\n }\n }}>\n <DrawerContent\n preventClose={isProcessing}\n onCloseAttempt={() => {\n window.alert('Please wait while your payment is being processed.')\n }}\n >\n <DrawerHeader className=\"text-center sm:text-left\">\n <DrawerTitle>\n {sheetState === 'success'\n ? 'Payment Successful!'\n : existingSubscriptionId\n ? 'Complete Your Upgrade'\n : 'Complete Payment'}\n </DrawerTitle>\n {sheetState !== 'success' && checkoutSession && (\n <DrawerDescription>\n {existingSubscriptionId ? 'Upgrading to' : 'Subscribing to'}:{' '}\n <span className=\"font-medium\">{checkoutSession.product.name}</span>\n </DrawerDescription>\n )}\n </DrawerHeader>\n\n {/* Loading State */}\n {sheetState === 'loading' && (\n <div className=\"space-y-6 py-4\">\n <Skeleton className=\"h-20 w-full\" />\n <Skeleton className=\"h-40 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n </div>\n )}\n\n {/* Error State */}\n {sheetState === 'error' && (\n <div className=\"space-y-4 py-4\">\n <Alert variant=\"destructive\">\n <AlertDescription>\n {error || 'Something went wrong. Please try again.'}\n </AlertDescription>\n </Alert>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" onClick={onClose} className=\"flex-1\">\n Cancel\n </Button>\n <Button onClick={handleRetry} className=\"flex-1\">\n Try Again\n </Button>\n </div>\n </div>\n )}\n\n {/* Success State */}\n {sheetState === 'success' && checkoutSession && (\n <div className=\"flex flex-col items-center justify-center py-8 space-y-4\">\n <div className=\"w-16 h-16 rounded-full bg-green-100 flex items-center justify-center\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-green-600\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </div>\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold\">Payment Successful!</p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Your subscription to {checkoutSession.product.name} is now active.\n </p>\n </div>\n </div>\n )}\n\n {/* Processing State */}\n {sheetState === 'processing' && (\n <div className=\"flex flex-col items-center justify-center py-8 space-y-4\">\n <div className=\"w-16 h-16 rounded-full bg-primary/10 flex items-center justify-center\">\n <svg\n className=\"animate-spin h-8 w-8 text-primary\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n </div>\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold\">Processing Payment...</p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Please don't close this window.\n </p>\n </div>\n </div>\n )}\n\n {/* Ready State - Show Payment Form */}\n {sheetState === 'ready' && checkoutSession && (\n <div className=\"space-y-6\">\n {/* Demo Mode Banner */}\n {isDemoMode && (\n <Alert>\n <AlertDescription className=\"text-sm\">\n <strong>Demo Mode:</strong> This is a preview with mock data. In production,\n a real Stripe payment form will appear here.\n </AlertDescription>\n </Alert>\n )}\n\n {/* Plan Summary */}\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-start justify-between\">\n <div>\n <h3 className=\"font-semibold\">{checkoutSession.product.name}</h3>\n <p className=\"text-2xl font-bold mt-1\">\n {formatAmount(checkoutSession.amount, checkoutSession.currency)}\n <span className=\"text-sm font-normal text-muted-foreground\">\n /{formatInterval(checkoutSession.product.interval)}\n </span>\n </p>\n </div>\n <Badge variant=\"secondary\">\n {existingSubscriptionId ? 'Upgrade' : 'New'}\n </Badge>\n </div>\n\n {/* Features */}\n {checkoutSession.product.features.length > 0 && (\n <div className=\"mt-4 space-y-2\">\n <p className=\"text-sm font-medium text-muted-foreground\">\n Features Included:\n </p>\n <ul className=\"space-y-1\">\n {checkoutSession.product.features.map((feature, index) => (\n <li key={index} className=\"flex items-center gap-2 text-sm\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-green-500\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n {feature}\n </li>\n ))}\n </ul>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Proration Details (for upgrades) */}\n {checkoutSession.proration && (\n <Card>\n <CardContent className=\"pt-4\">\n <h4 className=\"font-medium mb-3\">Amount Due Today:</h4>\n <div className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span>{checkoutSession.product.name}</span>\n <span>\n {formatAmount(\n checkoutSession.proration.charged,\n checkoutSession.currency\n )}\n </span>\n </div>\n <div className=\"flex justify-between text-green-600\">\n <span>Credit (unused time)</span>\n <span>\n -\n {formatAmount(\n checkoutSession.proration.credited,\n checkoutSession.currency\n )}\n </span>\n </div>\n <Separator />\n <div className=\"flex justify-between font-semibold\">\n <span>Total Due Now</span>\n <span>\n {formatAmount(\n checkoutSession.proration.total,\n checkoutSession.currency\n )}\n </span>\n </div>\n </div>\n <p className=\"text-xs text-muted-foreground mt-3 flex items-start gap-1\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"mt-0.5 flex-shrink-0\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4\" />\n <path d=\"M12 8h.01\" />\n </svg>\n {checkoutSession.proration.explanation}\n </p>\n </CardContent>\n </Card>\n )}\n\n {/* Amount Due (no proration) */}\n {!checkoutSession.proration && (\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex justify-between items-center\">\n <span className=\"font-medium\">Amount Due Today:</span>\n <span className=\"text-xl font-bold\">\n {formatAmount(checkoutSession.amount, checkoutSession.currency)}\n </span>\n </div>\n </CardContent>\n </Card>\n )}\n\n <Separator />\n\n {/* Payment Form - Demo or Real Stripe */}\n {isDemoMode ? (\n <DemoPaymentForm\n checkoutSession={checkoutSession}\n onSuccess={handlePaymentSuccess}\n isProcessing={isProcessing}\n setIsProcessing={setIsProcessing}\n />\n ) : stripePromise ? (\n <Elements\n stripe={stripePromise}\n options={{\n clientSecret: checkoutSession.clientSecret,\n appearance,\n }}\n >\n <PaymentForm\n checkoutSession={checkoutSession}\n onSuccess={handlePaymentSuccess}\n onError={handlePaymentError}\n isProcessing={isProcessing}\n setIsProcessing={setIsProcessing}\n />\n </Elements>\n ) : null}\n </div>\n )}\n </DrawerContent>\n </Drawer>\n </ErrorBoundary>\n )\n}\n","import * as React from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { Skeleton } from '../ui/skeleton'\nimport { Alert, AlertDescription } from '../ui/alert'\nimport { Button } from '../ui/button'\nimport { Badge } from '../ui/badge'\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '../ui/table'\nimport { cn } from '../../utils/cn'\nimport { useProducts } from './hooks/useProducts'\nimport { PaymentBottomSheet } from '../PaymentBottomSheet'\nimport { CheckoutModal } from '../CheckoutModal'\nimport { useBillingOS } from '../../providers/BillingOSProvider'\nimport type { PricingProduct, PricingPrice } from '../../client/types'\n\nexport interface PricingTableProps {\n planIds?: string[]\n showIntervalToggle?: boolean\n defaultInterval?: 'month' | 'year'\n onSelectPlan?: (priceId: string) => void\n theme?: 'light' | 'dark'\n title?: string\n description?: string\n /** Use the new iframe-based checkout modal instead of bottom sheet */\n useCheckoutModal?: boolean\n /** Callback when plan is changed (for upgrade/downgrade flows) */\n onPlanChanged?: (subscription: any) => void\n /** Customer information to prefill in checkout (overrides context) */\n customer?: {\n email?: string\n name?: string\n }\n}\n\ninterface FeatureRow {\n name: string\n values: (string | boolean | number | null)[]\n}\n\nexport function PricingTable({\n planIds,\n showIntervalToggle = true,\n defaultInterval = 'month',\n onSelectPlan,\n theme,\n title = 'Choose Your Plan',\n description,\n useCheckoutModal = false,\n onPlanChanged,\n customer: customerProp,\n}: PricingTableProps) {\n const [selectedInterval, setSelectedInterval] = React.useState<'month' | 'year'>(defaultInterval)\n const [selectedPriceId, setSelectedPriceId] = React.useState<string | null>(null)\n const [isPaymentOpen, setIsPaymentOpen] = React.useState(false)\n\n // Get customer data from context to prefill checkout form\n const { customerEmail, customerName } = useBillingOS()\n\n // Use prop customer data if provided, otherwise fall back to context\n const finalCustomerEmail = customerProp?.email || customerEmail\n const finalCustomerName = customerProp?.name || customerName\n\n // Get query client for cache invalidation\n const queryClient = useQueryClient()\n\n // State for success notification\n const [showSuccessMessage, setShowSuccessMessage] = React.useState(false)\n\n // Debug logging\n React.useEffect(() => {\n console.log('[PricingTable] Customer data:', {\n fromProp: customerProp,\n fromContext: { customerEmail, customerName },\n final: { email: finalCustomerEmail, name: finalCustomerName },\n hasEmail: !!finalCustomerEmail,\n hasName: !!finalCustomerName,\n })\n }, [customerProp, customerEmail, customerName, finalCustomerEmail, finalCustomerName])\n\n React.useEffect(() => {\n console.log('📊 BillingOS SDK v1.2.0 - PricingTable rendered - CSS injected')\n console.log('%c🚀 BillingOS SDK Version: 1.1.0', 'color: #10b981; font-weight: bold; font-size: 14px;')\n if (useCheckoutModal) {\n console.log(\n '%c🎉 Using NEW Iframe-based CheckoutModal with Real-time Updates!',\n 'background: linear-gradient(to right, #10b981, #3b82f6); color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;'\n )\n } else {\n console.log('📦 Using PaymentBottomSheet (legacy)')\n }\n }, [useCheckoutModal])\n\n const { data, isLoading, error, refetch } = useProducts({ planIds })\n\n const products = data?.products || []\n const currentSubscription = data?.currentSubscription || null\n\n // Check if any product has yearly pricing\n const hasYearlyPricing = products.some((p) =>\n p.prices.some((price) => price.interval === 'year')\n )\n\n // Extract all unique features across all products\n const getAllFeatures = React.useMemo((): FeatureRow[] => {\n const featureMap = new Map<string, FeatureRow>()\n\n // First, collect all unique features using feature.id as key\n products.forEach((product) => {\n product.features.forEach((feature) => {\n if (!featureMap.has(feature.id)) {\n featureMap.set(feature.id, {\n name: feature.title,\n values: Array(products.length).fill(null),\n })\n }\n })\n })\n\n // Populate feature values for each product\n const featureRows = Array.from(featureMap.entries())\n featureRows.forEach(([featureId, featureRow]) => {\n products.forEach((product, productIndex) => {\n const feature = product.features.find((f) => f.id === featureId)\n if (feature) {\n // Determine feature value based on type\n if (feature.type === 'boolean_flag') {\n featureRow.values[productIndex] = true\n } else if (feature.type === 'usage_quota' || feature.type === 'numeric_limit') {\n const limit = feature.properties?.limit\n if (limit === -1) {\n featureRow.values[productIndex] = 'Unlimited'\n } else if (typeof limit === 'number') {\n featureRow.values[productIndex] = limit\n } else {\n featureRow.values[productIndex] = true\n }\n }\n }\n })\n })\n\n return featureRows.map(([, row]) => row)\n }, [products])\n\n // Format price for display\n const formatPrice = (price: PricingPrice) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: price.currency.toUpperCase(),\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n }).format(price.amount / 100)\n }\n\n // Get price for selected interval\n const getPriceForInterval = (product: PricingProduct): PricingPrice | null => {\n return product.prices.find((p) => p.interval === selectedInterval) || product.prices[0] || null\n }\n\n // Handle plan selection\n const handleSelectPlan = (priceId: string) => {\n if (onSelectPlan) {\n onSelectPlan(priceId)\n } else {\n setSelectedPriceId(priceId)\n setIsPaymentOpen(true)\n }\n }\n\n // Handle payment success with real-time update\n const handlePaymentSuccess = React.useCallback(async (subscription?: any) => {\n console.log('%c🎉 [PricingTable] handlePaymentSuccess CALLED!', 'color: #10b981; font-size: 14px; font-weight: bold;', subscription)\n console.log('[PricingTable] Subscription data:', subscription)\n\n // Close the payment modal\n setIsPaymentOpen(false)\n setSelectedPriceId(null)\n\n // Show success message\n console.log('[PricingTable] Showing success notification...')\n setShowSuccessMessage(true)\n setTimeout(() => setShowSuccessMessage(false), 5000) // Hide after 5 seconds\n\n // Call onPlanChanged callback if provided (for portal integration)\n if (onPlanChanged) {\n console.log('[PricingTable] Calling onPlanChanged callback...')\n onPlanChanged(subscription)\n }\n\n // Force invalidate the products query to bypass stale time\n // This ensures immediate refetch of subscription status\n console.log('%c🔄 Invalidating products cache...', 'color: #8b5cf6; font-weight: 600;')\n await queryClient.invalidateQueries({\n queryKey: ['products'],\n refetchType: 'all' // Force refetch even if not stale\n })\n\n // If subscription data is provided, we can also optimistically update the cache\n if (subscription) {\n console.log('[PricingTable] Optimistically updating cache with subscription:', subscription)\n\n queryClient.setQueryData(['products', planIds], (oldData: any) => {\n if (!oldData) return oldData\n\n console.log('[PricingTable] Updating cache - old data:', oldData)\n\n const updatedData = {\n ...oldData,\n currentSubscription: subscription,\n products: oldData.products?.map((product: any) => ({\n ...product,\n // Update isCurrentPlan based on the new subscription\n isCurrentPlan: product.prices?.some((price: any) =>\n price.id === subscription.priceId\n ) || false\n }))\n }\n\n console.log('[PricingTable] Updated cache data:', updatedData)\n return updatedData\n })\n }\n\n // Also trigger a background refetch to ensure data consistency\n console.log('[PricingTable] Triggering background refetch...')\n await refetch()\n\n console.log('%c✅ Products cache invalidated and refetched', 'color: #10b981; font-weight: 600;')\n }, [queryClient, refetch, planIds, onPlanChanged])\n\n // Loading state\n if (isLoading) {\n return (\n <div className={cn('w-full', theme === 'dark' && 'dark')}>\n {title && (\n <div className=\"text-center mb-8\">\n <Skeleton className=\"h-10 w-64 mx-auto mb-2\" />\n {description && <Skeleton className=\"h-5 w-96 mx-auto\" />}\n </div>\n )}\n <Skeleton className=\"h-[600px] w-full\" />\n </div>\n )\n }\n\n // Error state\n if (error) {\n return (\n <div className={cn('w-full max-w-md mx-auto', theme === 'dark' && 'dark')}>\n <Alert variant=\"destructive\">\n <AlertDescription>\n {error.message || 'Failed to load pricing plans'}\n </AlertDescription>\n </Alert>\n <div className=\"mt-4 flex justify-center\">\n <Button onClick={() => refetch()}>Try Again</Button>\n </div>\n </div>\n )\n }\n\n // Empty state\n if (products.length === 0) {\n return (\n <div className={cn('w-full text-center py-12', theme === 'dark' && 'dark')}>\n <p className=\"text-muted-foreground\">No pricing plans available</p>\n </div>\n )\n }\n\n return (\n <div className={cn('w-full', theme === 'dark' && 'dark')}>\n {/* Success Notification */}\n {showSuccessMessage && (\n <div className=\"mb-6 p-4 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg animate-in slide-in-from-top-2 duration-300\">\n <div className=\"flex items-center space-x-2\">\n <svg\n className=\"w-5 h-5 text-green-600 dark:text-green-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n <p className=\"text-green-800 dark:text-green-200 font-medium\">\n Payment successful! Your subscription has been updated.\n </p>\n </div>\n </div>\n )}\n\n {/* Header */}\n {(title || description) && (\n <div className=\"text-center mb-8\">\n {title && (\n <h2 className=\"text-3xl font-bold tracking-tight text-foreground\">{title}</h2>\n )}\n {description && (\n <p className=\"text-muted-foreground mt-2 max-w-2xl mx-auto\">\n {description}\n </p>\n )}\n {useCheckoutModal && (\n <div className=\"inline-flex items-center gap-2 mt-4 px-3 py-1 bg-gradient-to-r from-blue-100 to-purple-100 text-blue-800 rounded-full text-sm font-medium\">\n <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clipRule=\"evenodd\" />\n </svg>\n <span>Using Secure Iframe Checkout</span>\n </div>\n )}\n </div>\n )}\n\n {/* Interval Toggle */}\n {showIntervalToggle && hasYearlyPricing && (\n <div className=\"flex justify-center mb-8\">\n <div className=\"inline-flex items-center rounded-lg bg-muted p-1\">\n <button\n onClick={() => setSelectedInterval('month')}\n className={cn(\n 'px-4 py-2 rounded-md text-sm font-medium transition-colors',\n selectedInterval === 'month'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n )}\n >\n Monthly\n </button>\n <button\n onClick={() => setSelectedInterval('year')}\n className={cn(\n 'px-4 py-2 rounded-md text-sm font-medium transition-colors flex items-center gap-2',\n selectedInterval === 'year'\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground'\n )}\n >\n Yearly\n <Badge variant=\"secondary\" className=\"text-xs\">\n Save\n </Badge>\n </button>\n </div>\n </div>\n )}\n\n {/* Pricing Table */}\n <div className=\"rounded-lg border bg-card overflow-hidden\">\n <Table>\n {/* Header Row: Plan Names & Prices */}\n <TableHeader>\n <TableRow className=\"hover:bg-transparent border-b\">\n <TableHead className=\"w-[200px]\" />\n {products.map((product) => {\n const price = getPriceForInterval(product)\n const isHighlighted = product.highlighted\n const isCurrentPlan = product.isCurrentPlan\n\n return (\n <TableHead\n key={product.id}\n className={cn(\n 'text-center relative',\n isHighlighted && 'bg-foreground text-background'\n )}\n >\n <div className=\"py-8\">\n {/* Badges */}\n {(isHighlighted || isCurrentPlan) && (\n <div className=\"flex justify-center gap-2 mb-3\">\n {isCurrentPlan && (\n <Badge className=\"bg-primary text-primary-foreground text-xs\">\n Current Plan\n </Badge>\n )}\n {isHighlighted && !isCurrentPlan && (\n <Badge\n variant=\"secondary\"\n className={cn(\n \"text-xs\",\n isHighlighted && \"bg-background text-foreground\"\n )}\n >\n Popular\n </Badge>\n )}\n </div>\n )}\n\n {/* Plan Name */}\n <div className={cn(\n \"font-bold text-xl mb-3\",\n isHighlighted ? \"text-background\" : \"text-foreground\"\n )}>\n {product.name}\n </div>\n\n {/* Price */}\n {price && (\n <>\n <div className={cn(\n \"text-5xl font-bold mb-2\",\n isHighlighted ? \"text-background\" : \"text-foreground\"\n )}>\n {formatPrice(price)}\n </div>\n <div className={cn(\n \"text-sm mt-1\",\n isHighlighted ? \"text-background/70\" : \"text-muted-foreground\"\n )}>\n Per {selectedInterval === 'year' ? 'year' : 'month'}\n </div>\n </>\n )}\n </div>\n </TableHead>\n )\n })}\n </TableRow>\n </TableHeader>\n\n {/* Feature Rows */}\n <TableBody>\n {getAllFeatures.map((featureRow, index) => (\n <TableRow key={index}>\n <TableCell className=\"font-medium text-foreground py-4\">\n {featureRow.name}\n </TableCell>\n {featureRow.values.map((value, productIndex) => {\n const isHighlighted = products[productIndex]?.highlighted\n\n return (\n <TableCell\n key={productIndex}\n className={cn(\n 'text-center py-4',\n isHighlighted && 'bg-foreground/5'\n )}\n >\n {value === null || value === false ? (\n <span className=\"text-muted-foreground\">-</span>\n ) : value === true ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"inline-block text-foreground\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"9 12 11 14 15 10\" />\n </svg>\n ) : (\n <span className=\"text-foreground font-medium\">{value}</span>\n )}\n </TableCell>\n )\n })}\n </TableRow>\n ))}\n\n {/* CTA Buttons Row */}\n <TableRow className=\"hover:bg-transparent border-t\">\n <TableCell className=\"font-medium text-foreground py-6\">\n Server speed\n </TableCell>\n {products.map((product) => {\n const price = getPriceForInterval(product)\n const isHighlighted = product.highlighted\n const isCurrentPlan = product.isCurrentPlan\n\n // Smart button text based on subscription state\n const hasSubscription = currentSubscription !== null\n let buttonText = 'Get Started'\n\n if (isCurrentPlan) {\n buttonText = 'Current Plan'\n } else if (hasSubscription && price && currentSubscription) {\n // Get current price for comparison\n const currentPrice = products.find(p => p.isCurrentPlan)\n const currentPriceAmount = currentPrice\n ? getPriceForInterval(currentPrice)?.amount || 0\n : 0\n\n // Compare prices to determine upgrade/downgrade\n if (price.amount > currentPriceAmount) {\n buttonText = 'Upgrade'\n } else if (price.amount < currentPriceAmount) {\n buttonText = 'Downgrade'\n } else {\n buttonText = 'Switch Plan'\n }\n }\n\n return (\n <TableCell\n key={product.id}\n className={cn(\n 'text-center py-6',\n isHighlighted && 'bg-foreground/5'\n )}\n >\n <Button\n onClick={() => price && handleSelectPlan(price.id)}\n disabled={isCurrentPlan || !price}\n variant={isHighlighted && !isCurrentPlan ? 'default' : 'outline'}\n className={cn(\n \"w-full max-w-[200px]\",\n isHighlighted && !isCurrentPlan && \"bg-foreground text-background hover:bg-foreground/90\"\n )}\n >\n {buttonText}\n </Button>\n </TableCell>\n )\n })}\n </TableRow>\n </TableBody>\n </Table>\n </div>\n\n {/* Payment Component - Either Modal or Bottom Sheet */}\n {!onSelectPlan && selectedPriceId && (\n <>\n {useCheckoutModal ? (\n <CheckoutModal\n open={isPaymentOpen}\n onOpenChange={(open) => {\n if (!open) {\n setIsPaymentOpen(false)\n setSelectedPriceId(null)\n }\n }}\n priceId={selectedPriceId}\n customer={{\n email: finalCustomerEmail,\n name: finalCustomerName,\n }}\n onSuccess={(subscription) => {\n handlePaymentSuccess(subscription)\n }}\n existingSubscriptionId={currentSubscription?.id}\n theme={theme}\n />\n ) : (\n <PaymentBottomSheet\n priceId={selectedPriceId}\n isOpen={isPaymentOpen}\n onClose={() => {\n setIsPaymentOpen(false)\n setSelectedPriceId(null)\n }}\n onSuccess={handlePaymentSuccess}\n existingSubscriptionId={currentSubscription?.id}\n theme={theme}\n />\n )}\n </>\n )}\n </div>\n )\n}\n","import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '../ui/card'\nimport { Badge } from '../ui/badge'\nimport { Button } from '../ui/button'\nimport { cn } from '../../utils/cn'\nimport type { PricingProduct, PricingPrice, PricingCurrentSubscription } from '../../client/types'\n\nexport interface PricingCardProps {\n product: PricingProduct\n selectedInterval: 'month' | 'year'\n currentSubscription: PricingCurrentSubscription | null\n onSelectPlan: (priceId: string) => void\n theme?: 'light' | 'dark'\n}\n\nexport function PricingCard({\n product,\n selectedInterval,\n currentSubscription,\n onSelectPlan,\n}: PricingCardProps) {\n // Find the price for the selected interval\n const selectedPrice = product.prices.find(\n (p) => p.interval === selectedInterval\n ) || product.prices[0]\n\n // Determine button state based on current subscription\n const isCurrentPlan = product.isCurrentPlan\n\n // Helper to determine if this is an upgrade or downgrade\n const getButtonState = (): 'current' | 'upgrade' | 'downgrade' | 'buy' => {\n if (!currentSubscription) return 'buy'\n if (isCurrentPlan) return 'current'\n\n // If current plan is this product, it's current\n if (currentSubscription.productId === product.id) return 'current'\n\n // Otherwise, we need to compare - for simplicity, assume products are sorted by price\n // In real implementation, you'd compare actual amounts\n return 'upgrade' // Default to upgrade for non-current plans\n }\n\n const buttonState = getButtonState()\n\n // Format price for display\n const formatPrice = (price: PricingPrice) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: price.currency.toUpperCase(),\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n }).format(price.amount / 100)\n }\n\n // Calculate yearly savings\n const calculateYearlySavings = () => {\n const monthlyPrice = product.prices.find((p) => p.interval === 'month')\n const yearlyPrice = product.prices.find((p) => p.interval === 'year')\n\n if (!monthlyPrice || !yearlyPrice) return null\n\n const monthlyTotal = monthlyPrice.amount * 12\n const yearlyCost = yearlyPrice.amount\n const savings = ((monthlyTotal - yearlyCost) / monthlyTotal) * 100\n\n return Math.round(savings)\n }\n\n const yearlySavings = selectedInterval === 'year' ? calculateYearlySavings() : null\n\n // Format feature display\n const formatFeature = (feature: typeof product.features[0]) => {\n if (feature.properties?.limit === -1) {\n return `Unlimited ${feature.properties?.unit || feature.title.toLowerCase()}`\n }\n return feature.title\n }\n\n const handleClick = () => {\n if (buttonState !== 'current' && selectedPrice) {\n onSelectPlan(selectedPrice.id)\n }\n }\n\n return (\n <Card\n className={cn(\n 'relative flex flex-col h-full transition-all duration-200',\n isCurrentPlan && 'border-primary border-2 shadow-lg',\n product.highlighted && !isCurrentPlan && 'border-primary/50',\n 'hover:shadow-lg'\n )}\n >\n {/* Badges */}\n <div className=\"absolute -top-3 left-1/2 -translate-x-1/2 flex gap-2\">\n {isCurrentPlan && (\n <Badge className=\"bg-primary text-primary-foreground\">\n Current Plan\n </Badge>\n )}\n {product.highlighted && !isCurrentPlan && (\n <Badge variant=\"secondary\">\n Most Popular\n </Badge>\n )}\n </div>\n\n <CardHeader className=\"text-center pb-2 pt-8\">\n <CardTitle className=\"text-2xl font-bold\">{product.name}</CardTitle>\n <CardDescription className=\"text-sm mt-1\">\n {product.description}\n </CardDescription>\n </CardHeader>\n\n <CardContent className=\"flex-1 pt-4\">\n {/* Price */}\n <div className=\"text-center mb-6\">\n <div className=\"flex items-baseline justify-center gap-1\">\n <span className=\"text-4xl font-bold tracking-tight\">\n {selectedPrice ? formatPrice(selectedPrice) : 'N/A'}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n /{selectedInterval === 'year' ? 'year' : 'mo'}\n </span>\n </div>\n {yearlySavings && yearlySavings > 0 && (\n <Badge variant=\"secondary\" className=\"mt-2 bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300\">\n Save {yearlySavings}%\n </Badge>\n )}\n {product.trialDays > 0 && buttonState === 'buy' && (\n <p className=\"text-sm text-muted-foreground mt-2\">\n {product.trialDays}-day free trial\n </p>\n )}\n </div>\n\n {/* Features */}\n <ul className=\"space-y-3\">\n {product.features.map((feature) => (\n <li key={feature.id} className=\"flex items-start gap-3\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-green-500 flex-shrink-0 mt-0.5\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n <span className=\"text-sm\">{formatFeature(feature)}</span>\n </li>\n ))}\n </ul>\n </CardContent>\n\n <CardFooter className=\"pt-4\">\n <Button\n className=\"w-full\"\n size=\"lg\"\n variant={buttonState === 'current' ? 'outline' : 'default'}\n disabled={buttonState === 'current'}\n onClick={handleClick}\n >\n {buttonState === 'current' && (\n <span className=\"flex items-center gap-2\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n Current Plan\n </span>\n )}\n {buttonState === 'buy' && (\n product.trialDays > 0 ? 'Start Free Trial' : 'Get Started'\n )}\n {buttonState === 'upgrade' && 'Upgrade'}\n {buttonState === 'downgrade' && 'Downgrade'}\n </Button>\n </CardFooter>\n </Card>\n )\n}\n","import { useState, useEffect, useRef, useCallback } from 'react'\nimport { Sheet, SheetContent, SheetHeader, SheetTitle } from '../ui/sheet'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog'\nimport { PortalIframe } from './PortalIframe'\nimport { usePortalSession } from './hooks/usePortalSession'\nimport { usePortalMessaging, IframeMessage } from './hooks/usePortalMessaging'\nimport { PricingTable } from '../PricingTable'\nimport { cn } from '../../utils/cn'\nimport { Alert, AlertDescription } from '../ui/alert'\n\ntype PortalState = 'loading' | 'ready' | 'error'\ntype PortalTab = 'subscription' | 'invoices' | 'payment' | 'settings'\n\nexport interface CustomerPortalProps {\n /**\n * Open/close state (for drawer/modal mode)\n */\n isOpen?: boolean\n\n /**\n * Callback when user closes portal\n */\n onClose?: () => void\n\n /**\n * Display mode\n * - 'drawer': Slide-in from right (default)\n * - 'modal': Centered modal\n * - 'page': Full-page view\n */\n mode?: 'drawer' | 'modal' | 'page'\n\n /**\n * Default tab to show\n */\n defaultTab?: PortalTab\n\n /**\n * Optional: Custom theme\n */\n theme?: 'light' | 'dark'\n\n /**\n * Optional: Custom class name\n */\n className?: string\n\n /**\n * Optional: Customer ID to load specific customer\n */\n customerId?: string\n\n /**\n * Optional: Custom metadata\n */\n metadata?: Record<string, any>\n\n /**\n * Callback when subscription is updated\n */\n onSubscriptionUpdate?: (subscription: any) => void\n\n /**\n * Callback when subscription is cancelled\n */\n onSubscriptionCancel?: () => void\n\n /**\n * Callback when payment method is added\n */\n onPaymentMethodAdd?: () => void\n\n /**\n * Callback when payment method is updated\n */\n onPaymentMethodUpdate?: () => void\n\n /**\n * Debug mode for development\n */\n debug?: boolean\n}\n\nexport function CustomerPortal({\n isOpen = false,\n onClose,\n mode = 'drawer',\n defaultTab = 'subscription',\n theme = 'light',\n className,\n customerId,\n metadata,\n onSubscriptionUpdate,\n onSubscriptionCancel,\n onPaymentMethodAdd,\n onPaymentMethodUpdate,\n debug = false\n}: CustomerPortalProps) {\n const [state, setState] = useState<PortalState>('loading')\n const [error, setError] = useState<Error | null>(null)\n const [iframeHeight, setIframeHeight] = useState(600)\n const [showPricingTable, setShowPricingTable] = useState(false)\n const [portalCustomer, setPortalCustomer] = useState<{ email?: string; name?: string } | null>(null)\n const iframeRef = useRef<HTMLIFrameElement>(null)\n\n // Log version on mount (only once)\n useEffect(() => {\n console.log(\n '%c🚀 BillingOS SDK v1.2.0 - Iframe Customer Portal with Smart Pricing Table',\n 'background: linear-gradient(to right, #667eea, #764ba2); color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;'\n )\n console.log('%c📦 Using iframe for instant updates and security', 'color: #10b981; font-weight: 600;')\n console.log('%c🎨 Supports drawer, modal, and page modes', 'color: #8b5cf6; font-weight: 600;')\n if (debug) {\n console.log('[CustomerPortal] Debug mode enabled')\n }\n }, [])\n\n // Create portal session when opened\n const isOpenOrPage = mode === 'page' || isOpen\n const { sessionId, sessionUrl, loading, error: sessionError } = usePortalSession({\n enabled: isOpenOrPage,\n customerId,\n metadata\n })\n\n // Handle iframe messaging\n const handleIframeMessage = useCallback((message: IframeMessage) => {\n if (debug) {\n console.log('[CustomerPortal] Received message from iframe:', message.type, message)\n }\n\n switch (message.type) {\n case 'PORTAL_READY':\n console.log('[CustomerPortal] Portal is ready')\n setState('ready')\n break\n\n case 'PORTAL_CLOSE':\n console.log('[CustomerPortal] User requested close')\n onClose?.()\n break\n\n case 'SUBSCRIPTION_UPDATED':\n console.log('[CustomerPortal] Subscription updated')\n onSubscriptionUpdate?.(message.payload)\n break\n\n case 'SUBSCRIPTION_CANCELLED':\n console.log('[CustomerPortal] Subscription cancelled')\n onSubscriptionCancel?.()\n break\n\n case 'PAYMENT_METHOD_ADDED':\n console.log('[CustomerPortal] Payment method added')\n onPaymentMethodAdd?.()\n break\n\n case 'PAYMENT_METHOD_UPDATED':\n console.log('[CustomerPortal] Payment method updated')\n onPaymentMethodUpdate?.()\n break\n\n case 'HEIGHT_CHANGED':\n if (message.payload?.height) {\n setIframeHeight(message.payload.height)\n if (debug) {\n console.log('[CustomerPortal] Height changed to:', message.payload.height)\n }\n }\n break\n\n case 'OPEN_PRICING_TABLE':\n console.log('[CustomerPortal] Opening pricing table for plan change')\n if (message.payload?.customer) {\n console.log('[CustomerPortal] Received customer data for prefill:', message.payload.customer)\n setPortalCustomer(message.payload.customer)\n }\n setShowPricingTable(true)\n break\n\n case 'CLOSE_PRICING_TABLE':\n console.log('[CustomerPortal] Closing pricing table')\n setShowPricingTable(false)\n break\n\n case 'ERROR':\n setState('error')\n const errorMessage = message.payload?.error || 'An error occurred'\n const err = new Error(errorMessage)\n setError(err)\n break\n\n default:\n break\n }\n }, [debug, onClose, onSubscriptionUpdate, onSubscriptionCancel, onPaymentMethodAdd, onPaymentMethodUpdate])\n\n const { sendMessage } = usePortalMessaging({\n iframeRef,\n onMessage: handleIframeMessage,\n debug\n })\n\n // Send initialization message when iframe is ready\n useEffect(() => {\n if (sessionId && state === 'ready') {\n sendMessage({\n type: 'INIT_PORTAL',\n sessionId,\n config: {\n theme,\n defaultTab\n }\n })\n }\n }, [sessionId, state, theme, defaultTab, sendMessage])\n\n // Reset state when closed\n useEffect(() => {\n if (!isOpenOrPage) {\n setState('loading')\n setError(null)\n setIframeHeight(600)\n }\n }, [isOpenOrPage])\n\n // Handle session creation error\n useEffect(() => {\n if (sessionError) {\n setState('error')\n setError(sessionError)\n }\n }, [sessionError])\n\n const showSpinner = loading || state === 'loading'\n const showError = state === 'error' && error\n\n // Portal content\n const portalContent = (\n <>\n {/* Iframe Badge */}\n <div className=\"absolute top-2 right-2 z-20 flex items-center gap-1 bg-gradient-to-r from-blue-600 to-purple-600 text-white text-xs font-medium px-2 py-1 rounded-full shadow-lg\">\n <svg className=\"w-3 h-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clipRule=\"evenodd\" />\n </svg>\n <span>Secure Iframe</span>\n </div>\n\n {showError ? (\n <div className=\"p-8\">\n <Alert variant=\"destructive\">\n <AlertDescription>{error.message}</AlertDescription>\n </Alert>\n </div>\n ) : (\n <>\n {showSpinner && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white z-10\">\n <div className=\"flex flex-col items-center\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600\"></div>\n <p className=\"mt-4 text-gray-600 font-medium\">Loading portal...</p>\n <p className=\"mt-2 text-xs text-gray-500\">Iframe-based • Always up-to-date</p>\n </div>\n </div>\n )}\n\n {sessionUrl && (\n <PortalIframe\n ref={iframeRef}\n src={sessionUrl}\n height={iframeHeight}\n className={cn(\n \"transition-opacity duration-300\",\n showSpinner ? \"opacity-0\" : \"opacity-100\"\n )}\n onLoad={() => {\n console.log(\n '%c✅ Portal iframe loaded successfully',\n 'color: #10b981; font-weight: 600;',\n `\\nURL: ${sessionUrl}`\n )\n if (debug) {\n console.log('[CustomerPortal] Full iframe details:', {\n sessionUrl,\n sessionId,\n state,\n height: iframeHeight\n })\n }\n }}\n />\n )}\n </>\n )}\n\n {debug && (\n <div className=\"absolute bottom-0 left-0 right-0 bg-black/80 text-white p-2 text-xs\">\n <div>State: {state}</div>\n <div>Session: {sessionId || 'Creating...'}</div>\n {error && <div>Error: {error.message}</div>}\n </div>\n )}\n </>\n )\n\n // Render based on mode\n const mainPortal = mode === 'page' ? (\n <div className={cn('relative w-full', className)}>\n {portalContent}\n </div>\n ) : mode === 'modal' ? (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onClose?.()}>\n <DialogContent className={cn('sm:max-w-[800px] p-0 overflow-hidden max-h-[90vh] relative', className)}>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>Customer Portal</DialogTitle>\n </DialogHeader>\n {portalContent}\n </DialogContent>\n </Dialog>\n ) : (\n // Default: drawer mode\n <Sheet open={isOpen} onOpenChange={(open) => !open && onClose?.()}>\n <SheetContent\n side=\"right\"\n className={cn('w-full sm:max-w-[600px] p-0 overflow-hidden', className)}\n >\n <SheetHeader className=\"sr-only\">\n <SheetTitle>Customer Portal</SheetTitle>\n </SheetHeader>\n {portalContent}\n </SheetContent>\n </Sheet>\n )\n\n return (\n <>\n {mainPortal}\n\n {/* PricingTable Modal for Plan Changes */}\n <Dialog open={showPricingTable} onOpenChange={setShowPricingTable}>\n <DialogContent className=\"sm:max-w-6xl max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle>Change Your Plan</DialogTitle>\n </DialogHeader>\n <PricingTable\n useCheckoutModal={true}\n theme={theme}\n customer={portalCustomer || undefined}\n onPlanChanged={(subscription) => {\n console.log('[CustomerPortal] Plan changed successfully:', subscription)\n // Close the pricing table\n setShowPricingTable(false)\n // Clear customer data\n setPortalCustomer(null)\n // Send message back to portal iframe to refresh\n sendMessage({\n type: 'UPDATE_CONFIG',\n payload: { refresh: true }\n })\n // Notify parent app\n onSubscriptionUpdate?.(subscription)\n }}\n />\n </DialogContent>\n </Dialog>\n </>\n )\n}\n","import { useQuery, useMutation, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'\nimport { useBillingOS } from '../../../providers'\nimport type {\n CustomerPortalData,\n PortalUpdateSubscriptionInput,\n PortalUpdateSubscriptionResponse,\n PortalCancelSubscriptionInput,\n PortalCancelSubscriptionResponse,\n AddPaymentMethodInput,\n AddPaymentMethodResponse,\n SetupIntentResponse,\n RetryInvoiceResponse,\n UpdateCustomerBillingInput,\n CustomerBillingInfo,\n} from '../../../client/types'\n\n/**\n * Query keys for portal-related queries\n */\nexport const portalKeys = {\n all: ['portal'] as const,\n data: () => [...portalKeys.all, 'data'] as const,\n setupIntent: () => [...portalKeys.all, 'setupIntent'] as const,\n}\n\n/**\n * Fetch all portal data for the current customer\n * Returns subscription, invoices, payment methods, customer info, and available plans\n */\nexport function usePortalData(\n options?: Omit<UseQueryOptions<CustomerPortalData>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: portalKeys.data(),\n queryFn: () => client.getCustomerPortal(),\n staleTime: 1000 * 60 * 5, // 5 minutes\n ...options,\n })\n}\n\n/**\n * Update subscription (upgrade/downgrade)\n */\nexport function useUpdatePortalSubscription(\n subscriptionId: string,\n options?: Omit<\n UseMutationOptions<PortalUpdateSubscriptionResponse, Error, PortalUpdateSubscriptionInput>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: PortalUpdateSubscriptionInput) =>\n client.updatePortalSubscription(subscriptionId, input),\n onSuccess: (...args) => {\n // Invalidate portal data to refresh subscription info\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Cancel subscription with feedback\n */\nexport function useCancelPortalSubscription(\n subscriptionId: string,\n options?: Omit<\n UseMutationOptions<PortalCancelSubscriptionResponse, Error, PortalCancelSubscriptionInput>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: PortalCancelSubscriptionInput) =>\n client.cancelPortalSubscription(subscriptionId, input),\n onSuccess: (...args) => {\n // Invalidate portal data to refresh subscription status\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Reactivate a canceled subscription\n */\nexport function useReactivatePortalSubscription(\n subscriptionId: string,\n options?: Omit<UseMutationOptions<void, Error, void>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: () => client.reactivatePortalSubscription(subscriptionId),\n onSuccess: (...args) => {\n // Invalidate portal data to refresh subscription status\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Get setup intent for adding a new payment method\n */\nexport function useSetupIntent(\n options?: Omit<UseQueryOptions<SetupIntentResponse>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: portalKeys.setupIntent(),\n queryFn: () => client.getSetupIntent(),\n enabled: false, // Only fetch when explicitly requested\n ...options,\n })\n}\n\n/**\n * Add a payment method\n */\nexport function useAddPaymentMethod(\n options?: Omit<\n UseMutationOptions<AddPaymentMethodResponse, Error, AddPaymentMethodInput>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: AddPaymentMethodInput) => client.addPaymentMethod(input),\n onSuccess: (...args) => {\n // Invalidate portal data to refresh payment methods\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Remove a payment method\n */\nexport function useRemovePaymentMethod(\n options?: Omit<UseMutationOptions<void, Error, string>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (paymentMethodId: string) => client.removePaymentMethod(paymentMethodId),\n onSuccess: (...args) => {\n // Invalidate portal data to refresh payment methods\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Set default payment method\n */\nexport function useSetDefaultPaymentMethod(\n options?: Omit<UseMutationOptions<void, Error, string>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (paymentMethodId: string) => client.setDefaultPaymentMethod(paymentMethodId),\n onSuccess: (...args) => {\n // Invalidate portal data to refresh payment methods\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Retry a failed invoice\n */\nexport function useRetryInvoice(\n options?: Omit<\n UseMutationOptions<RetryInvoiceResponse, Error, { invoiceId: string; paymentMethodId?: string }>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: ({ invoiceId, paymentMethodId }) =>\n client.retryInvoice(invoiceId, paymentMethodId),\n onSuccess: (...args) => {\n // Invalidate portal data to refresh invoice status\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Update customer billing information\n */\nexport function useUpdateCustomerBilling(\n options?: Omit<\n UseMutationOptions<CustomerBillingInfo, Error, UpdateCustomerBillingInput>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: UpdateCustomerBillingInput) => client.updateCustomerBilling(input),\n onSuccess: (...args) => {\n // Invalidate portal data to refresh customer info\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n","import { Progress } from '../../ui/progress'\nimport { cn } from '@/utils/cn'\nimport type { PortalUsageInfo } from '../../../client/types'\n\ninterface UsageBarProps {\n title: string\n usage: PortalUsageInfo\n unit?: string\n className?: string\n}\n\nfunction formatNumber(num: number): string {\n if (num >= 1000000) {\n return `${(num / 1000000).toFixed(1)}M`\n }\n if (num >= 1000) {\n return `${(num / 1000).toFixed(1)}K`\n }\n return num.toLocaleString()\n}\n\nfunction getProgressColor(percentage: number): string {\n if (percentage >= 90) return 'bg-destructive'\n if (percentage >= 75) return 'bg-yellow-500'\n return 'bg-primary'\n}\n\nexport function UsageBar({ title, usage, unit, className }: UsageBarProps) {\n const { consumed, limit, percentage, resetDate } = usage\n\n const formattedConsumed = formatNumber(consumed)\n const formattedLimit = formatNumber(limit)\n const progressColor = getProgressColor(percentage)\n\n return (\n <div className={cn('space-y-2', className)}>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-medium\">{title}</span>\n <span className=\"text-muted-foreground\">\n {formattedConsumed} / {formattedLimit} {unit && `(${unit})`}\n </span>\n </div>\n <Progress\n value={percentage}\n max={100}\n className=\"h-2\"\n indicatorClassName={progressColor}\n />\n <div className=\"flex items-center justify-between text-xs text-muted-foreground\">\n <span>{Math.round(percentage)}% used</span>\n {resetDate && (\n <span>\n Resets: {new Date(resetDate).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}\n </span>\n )}\n </div>\n </div>\n )\n}\n","import { cn } from '@/utils/cn'\nimport type { PortalFeatureWithUsage } from '../../../client/types'\n\ninterface FeatureListProps {\n features: PortalFeatureWithUsage[]\n className?: string\n}\n\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n )\n}\n\nexport function FeatureList({ features, className }: FeatureListProps) {\n // Filter to only show boolean features that are enabled\n const booleanFeatures = features.filter(\n (f) => f.type === 'boolean_flag' && f.enabled\n )\n\n if (booleanFeatures.length === 0) {\n return null\n }\n\n return (\n <div className={cn('space-y-2', className)}>\n <h4 className=\"text-sm font-medium text-muted-foreground\">Included Features</h4>\n <ul className=\"space-y-1.5\">\n {booleanFeatures.map((feature) => (\n <li key={feature.id} className=\"flex items-center gap-2 text-sm\">\n <CheckIcon className=\"text-green-500\" />\n <span>{feature.title}</span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n","import { Alert, AlertTitle, AlertDescription } from '../../ui/alert'\nimport { Button } from '../../ui/button'\nimport { cn } from '@/utils/cn'\n\ninterface WarningBannerProps {\n type: 'trial_ending' | 'payment_failed' | 'subscription_canceled' | 'past_due'\n message: string\n actionLabel?: string\n onAction?: () => void\n className?: string\n}\n\nfunction AlertTriangleIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n )\n}\n\nfunction getTitle(type: WarningBannerProps['type']): string {\n switch (type) {\n case 'trial_ending':\n return 'Trial Ending Soon'\n case 'payment_failed':\n return 'Payment Failed'\n case 'subscription_canceled':\n return 'Subscription Canceled'\n case 'past_due':\n return 'Payment Past Due'\n default:\n return 'Warning'\n }\n}\n\nfunction getVariant(type: WarningBannerProps['type']): 'warning' | 'destructive' {\n switch (type) {\n case 'payment_failed':\n case 'past_due':\n return 'destructive'\n default:\n return 'warning'\n }\n}\n\nexport function WarningBanner({\n type,\n message,\n actionLabel,\n onAction,\n className,\n}: WarningBannerProps) {\n const title = getTitle(type)\n const variant = getVariant(type)\n\n return (\n <Alert variant={variant} className={cn('', className)}>\n <AlertTriangleIcon />\n <AlertTitle>{title}</AlertTitle>\n <AlertDescription className=\"flex items-center justify-between\">\n <span>{message}</span>\n {actionLabel && onAction && (\n <Button\n size=\"sm\"\n variant={variant === 'destructive' ? 'outline' : 'default'}\n onClick={onAction}\n className=\"ml-4\"\n >\n {actionLabel}\n </Button>\n )}\n </AlertDescription>\n </Alert>\n )\n}\n","/**\n * Currency utilities for formatting and converting money values\n */\n\n/**\n * Convert cents to dollar string\n * @param cents - Amount in cents\n * @param showCents - Force showing cents even if amount is whole dollars\n * @param pretty - Use locale formatting with thousand separators\n * @returns Formatted dollar string\n *\n * @example\n * getCentsInDollarString(1000) // \"10\"\n * getCentsInDollarString(1050, true) // \"10.50\"\n * getCentsInDollarString(1000000, false, true) // \"10,000\"\n */\nexport const getCentsInDollarString = (\n cents: number,\n showCents = false,\n pretty = false,\n): string => {\n const dollars = cents / 100\n\n const precision = cents % 100 === 0 && !showCents ? 0 : 2\n\n if (pretty) {\n return dollars.toLocaleString('en-US', {\n maximumFractionDigits: precision,\n minimumFractionDigits: precision,\n })\n }\n\n return dollars.toFixed(precision)\n}\n\n/**\n * Format cents as currency with symbol\n * @param cents - Amount in cents\n * @param currency - Currency code (e.g., 'USD', 'EUR')\n * @param minimumFractionDigits - Minimum decimal places\n * @param notation - Number notation style\n * @param maximumFractionDigits - Maximum decimal places\n * @returns Formatted currency string with symbol\n *\n * @example\n * formatCurrencyAndAmount(1050, 'USD') // \"$10.50\"\n * formatCurrencyAndAmount(1000000, 'USD', 0, 'compact') // \"$10K\"\n * formatCurrencyAndAmount(5000, 'EUR') // \"€50.00\"\n */\nexport const formatCurrencyAndAmount = (\n cents: number,\n currency: string,\n minimumFractionDigits?: number,\n notation?: 'standard' | 'scientific' | 'engineering' | 'compact',\n maximumFractionDigits?: number,\n): string => {\n const currencyNumberFormat = new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency,\n minimumFractionDigits,\n maximumFractionDigits,\n notation,\n })\n return currencyNumberFormat.format(cents / 100)\n}\n\n/**\n * Convert cents to float (dollars)\n * @param cents - Amount in cents\n * @returns Amount in dollars as a float\n *\n * @example\n * convertCentsToFloat(1050) // 10.5\n */\nexport const convertCentsToFloat = (cents: number): number => {\n return cents / 100\n}\n\n/**\n * Convert float (dollars) to cents\n * @param amount - Amount in dollars\n * @returns Amount in cents as an integer\n *\n * @example\n * convertFloatToCents(10.5) // 1050\n */\nexport const convertFloatToCents = (amount: number): number => {\n return Math.round(amount * 100)\n}\n\n/**\n * Format currency in compact notation (e.g., $1.2K, $3.5M)\n * @param cents - Amount in cents\n * @param currency - Currency code\n * @returns Compact formatted currency string\n *\n * @example\n * formatCurrencyCompact(1200000, 'USD') // \"$12K\"\n * formatCurrencyCompact(3500000000, 'USD') // \"$35M\"\n */\nexport const formatCurrencyCompact = (cents: number, currency: string): string => {\n return formatCurrencyAndAmount(cents, currency, 0, 'compact', 1)\n}\n\n/**\n * Format currency without cents (whole dollars only)\n * @param cents - Amount in cents\n * @param currency - Currency code\n * @returns Formatted currency string without cents\n *\n * @example\n * formatCurrencyWhole(1050, 'USD') // \"$10\"\n * formatCurrencyWhole(1099, 'USD') // \"$11\" (rounds)\n */\nexport const formatCurrencyWhole = (cents: number, currency: string): string => {\n return formatCurrencyAndAmount(cents, currency, 0, 'standard', 0)\n}\n\n/**\n * Get currency symbol for a currency code\n * @param currency - Currency code (e.g., 'USD', 'EUR')\n * @returns Currency symbol (e.g., '$', '€')\n *\n * @example\n * getCurrencySymbol('USD') // \"$\"\n * getCurrencySymbol('EUR') // \"€\"\n * getCurrencySymbol('GBP') // \"£\"\n */\nexport const getCurrencySymbol = (currency: string): string => {\n const formatter = new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency,\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n })\n\n // Format zero to extract symbol\n const parts = formatter.formatToParts(0)\n const symbolPart = parts.find((part) => part.type === 'currency')\n return symbolPart?.value || currency\n}\n\n/**\n * Format a price range (e.g., \"$10 - $50\")\n * @param minCents - Minimum amount in cents\n * @param maxCents - Maximum amount in cents\n * @param currency - Currency code\n * @returns Formatted price range string\n *\n * @example\n * formatPriceRange(1000, 5000, 'USD') // \"$10 - $50\"\n */\nexport const formatPriceRange = (\n minCents: number,\n maxCents: number,\n currency: string,\n): string => {\n const min = formatCurrencyAndAmount(minCents, currency)\n const max = formatCurrencyAndAmount(maxCents, currency)\n return `${min} - ${max}`\n}\n\n/**\n * Check if an amount is zero\n * @param cents - Amount in cents\n * @returns True if amount is zero\n */\nexport const isZeroAmount = (cents: number): boolean => {\n return cents === 0\n}\n\n/**\n * Check if an amount is negative\n * @param cents - Amount in cents\n * @returns True if amount is negative\n */\nexport const isNegativeAmount = (cents: number): boolean => {\n return cents < 0\n}\n\n/**\n * Calculate percentage of an amount\n * @param cents - Amount in cents\n * @param percentage - Percentage (0-100)\n * @returns Calculated amount in cents\n *\n * @example\n * calculatePercentage(10000, 20) // 2000 (20% of $100)\n */\nexport const calculatePercentage = (cents: number, percentage: number): number => {\n return Math.round((cents * percentage) / 100)\n}\n\n/**\n * Add amounts together\n * @param amounts - Array of amounts in cents\n * @returns Sum in cents\n *\n * @example\n * addAmounts([1000, 2000, 3000]) // 6000\n */\nexport const addAmounts = (...amounts: number[]): number => {\n return amounts.reduce((sum, amount) => sum + amount, 0)\n}\n\n/**\n * Money utilities namespace for convenience\n */\nexport const Money = {\n format: formatCurrencyAndAmount,\n formatCompact: formatCurrencyCompact,\n formatWhole: formatCurrencyWhole,\n formatRange: formatPriceRange,\n fromCents: convertCentsToFloat,\n toCents: convertFloatToCents,\n getSymbol: getCurrencySymbol,\n isZero: isZeroAmount,\n isNegative: isNegativeAmount,\n calculatePercentage,\n add: addAmounts,\n}\n","import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '../../ui/card'\nimport { Badge } from '../../ui/badge'\nimport { Button } from '../../ui/button'\nimport { Skeleton } from '../../ui/skeleton'\nimport { UsageBar } from '../components/UsageBar'\nimport { FeatureList } from '../components/FeatureList'\nimport { WarningBanner } from '../components/WarningBanner'\nimport { Money } from '../../../utils/money'\nimport { cn } from '@/utils/cn'\nimport type { PortalSubscription, PortalAvailablePlan } from '../../../client/types'\n\ninterface SubscriptionTabProps {\n subscription: PortalSubscription | null\n availablePlans: PortalAvailablePlan[]\n onChangePlan: () => void\n onCancelSubscription: () => void\n onReactivate: () => void\n onAddPaymentMethod: () => void\n isLoading?: boolean\n className?: string\n}\n\nfunction formatInterval(interval: string, intervalCount: number): string {\n if (intervalCount === 1) {\n return interval\n }\n return `${intervalCount} ${interval}s`\n}\n\nfunction getStatusBadge(status: PortalSubscription['status'], cancelAtPeriodEnd: boolean) {\n if (cancelAtPeriodEnd) {\n return <Badge variant=\"warning\">Cancels at period end</Badge>\n }\n\n switch (status) {\n case 'active':\n return <Badge variant=\"success\">Active</Badge>\n case 'trialing':\n return <Badge variant=\"secondary\">Trial</Badge>\n case 'past_due':\n return <Badge variant=\"destructive\">Past Due</Badge>\n case 'canceled':\n return <Badge variant=\"outline\">Canceled</Badge>\n case 'unpaid':\n return <Badge variant=\"destructive\">Unpaid</Badge>\n default:\n return <Badge variant=\"outline\">{status}</Badge>\n }\n}\n\nfunction NoSubscription({ onBrowsePlans }: { onBrowsePlans: () => void }) {\n return (\n <Card>\n <CardContent className=\"flex flex-col items-center justify-center py-12 text-center\">\n <p className=\"text-muted-foreground mb-4\">You don't have an active subscription.</p>\n <Button onClick={onBrowsePlans}>Browse Plans</Button>\n </CardContent>\n </Card>\n )\n}\n\nfunction SubscriptionTabSkeleton() {\n return (\n <div className=\"space-y-6\">\n <Card>\n <CardHeader>\n <Skeleton className=\"h-6 w-32\" />\n <Skeleton className=\"h-4 w-48\" />\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-4 w-36\" />\n <div className=\"flex gap-2\">\n <Skeleton className=\"h-9 w-32\" />\n <Skeleton className=\"h-9 w-40\" />\n </div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <Skeleton className=\"h-5 w-20\" />\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <Skeleton className=\"h-12 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n </CardContent>\n </Card>\n </div>\n )\n}\n\nexport function SubscriptionTab({\n subscription,\n onChangePlan,\n onCancelSubscription,\n onReactivate,\n onAddPaymentMethod,\n isLoading,\n className,\n}: SubscriptionTabProps) {\n if (isLoading) {\n return <SubscriptionTabSkeleton />\n }\n\n if (!subscription) {\n return <NoSubscription onBrowsePlans={onChangePlan} />\n }\n\n const {\n product,\n price,\n status,\n currentPeriodEnd,\n cancelAtPeriodEnd,\n trialEnd,\n features,\n } = subscription\n\n const formattedPrice = Money.format(price.amount, price.currency)\n const interval = formatInterval(price.interval, price.intervalCount)\n const nextBillingDate = new Date(currentPeriodEnd).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n })\n\n // Filter usage-based features\n const usageFeatures = features.filter(\n (f) => (f.type === 'usage_quota' || f.type === 'numeric_limit') && f.usage\n )\n\n // Check for trial ending soon (within 3 days)\n const isTrialEndingSoon =\n status === 'trialing' &&\n trialEnd &&\n new Date(trialEnd).getTime() - Date.now() < 3 * 24 * 60 * 60 * 1000\n\n return (\n <div className={cn('space-y-6', className)}>\n {/* Warning Banners */}\n {status === 'past_due' && (\n <WarningBanner\n type=\"past_due\"\n message=\"Your last payment was declined. Update your payment method to avoid service interruption.\"\n actionLabel=\"Update Payment\"\n onAction={onAddPaymentMethod}\n />\n )}\n\n {isTrialEndingSoon && trialEnd && (\n <WarningBanner\n type=\"trial_ending\"\n message={`Your trial ends on ${new Date(trialEnd).toLocaleDateString()}. Add a payment method to continue.`}\n actionLabel=\"Add Payment Method\"\n onAction={onAddPaymentMethod}\n />\n )}\n\n {cancelAtPeriodEnd && (\n <WarningBanner\n type=\"subscription_canceled\"\n message={`Your subscription will end on ${nextBillingDate}. You'll have access until then.`}\n actionLabel=\"Reactivate\"\n onAction={onReactivate}\n />\n )}\n\n {/* Current Plan Card */}\n <Card>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <div>\n <CardTitle>{product.name}</CardTitle>\n <CardDescription>\n {formattedPrice} / {interval}\n </CardDescription>\n </div>\n {getStatusBadge(status, cancelAtPeriodEnd)}\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"text-sm text-muted-foreground\">\n <p>\n {cancelAtPeriodEnd ? 'Access until' : 'Next billing'}:{' '}\n <span className=\"font-medium text-foreground\">{nextBillingDate}</span>\n </p>\n </div>\n\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"outline\" onClick={onChangePlan}>\n View Other Plans\n </Button>\n {!cancelAtPeriodEnd && status !== 'canceled' && (\n <Button\n variant=\"ghost\"\n className=\"text-destructive hover:text-destructive\"\n onClick={onCancelSubscription}\n >\n Cancel Subscription\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n\n {/* Usage Section */}\n {usageFeatures.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Usage This Billing Period</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n {usageFeatures.map((feature) => (\n <UsageBar\n key={feature.id}\n title={feature.title}\n usage={feature.usage!}\n unit={feature.properties.unit as string | undefined}\n />\n ))}\n </CardContent>\n </Card>\n )}\n\n {/* Features Section */}\n {features.some((f) => f.type === 'boolean_flag' && f.enabled) && (\n <Card>\n <CardContent className=\"pt-6\">\n <FeatureList features={features} />\n </CardContent>\n </Card>\n )}\n </div>\n )\n}\n","import { Card, CardContent } from '../../ui/card'\nimport { Badge } from '../../ui/badge'\nimport { Button } from '../../ui/button'\nimport { cn } from '@/utils/cn'\nimport { Money } from '../../../utils/money'\nimport type { PortalInvoice } from '../../../client/types'\n\ninterface InvoiceCardProps {\n invoice: PortalInvoice\n onRetry?: (invoiceId: string) => void\n onDownload?: (pdfUrl: string) => void\n isRetrying?: boolean\n className?: string\n}\n\nfunction DownloadIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"7 10 12 15 17 10\" />\n <line x1=\"12\" x2=\"12\" y1=\"15\" y2=\"3\" />\n </svg>\n )\n}\n\nfunction getStatusBadge(status: PortalInvoice['status']) {\n switch (status) {\n case 'paid':\n return <Badge variant=\"success\">Paid</Badge>\n case 'open':\n return <Badge variant=\"secondary\">Open</Badge>\n case 'failed':\n return <Badge variant=\"destructive\">Failed</Badge>\n case 'void':\n return <Badge variant=\"outline\">Void</Badge>\n default:\n return <Badge variant=\"outline\">{status}</Badge>\n }\n}\n\nexport function InvoiceCard({\n invoice,\n onRetry,\n onDownload,\n isRetrying,\n className,\n}: InvoiceCardProps) {\n const formattedDate = new Date(invoice.date).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n })\n\n const formattedAmount = Money.format(invoice.amount, invoice.currency)\n\n return (\n <Card className={cn('', className)}>\n <CardContent className=\"p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{invoice.number}</span>\n {getStatusBadge(invoice.status)}\n </div>\n <p className=\"text-sm text-muted-foreground\">{formattedDate}</p>\n {invoice.lineItems.length > 0 && (\n <p className=\"text-sm text-muted-foreground\">\n {invoice.lineItems[0].description}\n </p>\n )}\n </div>\n <div className=\"text-right\">\n <p className=\"font-semibold\">{formattedAmount}</p>\n </div>\n </div>\n\n {invoice.status === 'failed' && invoice.failureReason && (\n <div className=\"mt-3 rounded-md bg-destructive/10 p-2 text-sm text-destructive\">\n {invoice.failureReason}\n </div>\n )}\n\n <div className=\"mt-4 flex items-center gap-2\">\n {invoice.status === 'failed' && onRetry && (\n <Button\n size=\"sm\"\n variant=\"default\"\n onClick={() => onRetry(invoice.id)}\n disabled={isRetrying}\n >\n {isRetrying ? 'Retrying...' : 'Retry Payment'}\n </Button>\n )}\n {invoice.pdfUrl && onDownload && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => onDownload(invoice.pdfUrl!)}\n >\n <DownloadIcon className=\"mr-1\" />\n Download PDF\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n )\n}\n","import { Card, CardContent } from '../../ui/card'\nimport { Skeleton } from '../../ui/skeleton'\nimport { InvoiceCard } from '../components/InvoiceCard'\nimport { cn } from '@/utils/cn'\nimport type { PortalInvoice } from '../../../client/types'\n\ninterface InvoicesTabProps {\n invoices: PortalInvoice[]\n onRetryInvoice: (invoiceId: string) => void\n onDownloadInvoice: (pdfUrl: string) => void\n retryingInvoiceId?: string\n isLoading?: boolean\n className?: string\n}\n\nfunction NoInvoices() {\n return (\n <Card>\n <CardContent className=\"flex flex-col items-center justify-center py-12 text-center\">\n <p className=\"text-muted-foreground\">No invoices yet.</p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Your first invoice will appear here after your first billing cycle.\n </p>\n </CardContent>\n </Card>\n )\n}\n\nfunction InvoicesTabSkeleton() {\n return (\n <div className=\"space-y-4\">\n {[1, 2, 3].map((i) => (\n <Card key={i}>\n <CardContent className=\"p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-5 w-32\" />\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-4 w-48\" />\n </div>\n <Skeleton className=\"h-5 w-16\" />\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Skeleton className=\"h-8 w-24\" />\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )\n}\n\nexport function InvoicesTab({\n invoices,\n onRetryInvoice,\n onDownloadInvoice,\n retryingInvoiceId,\n isLoading,\n className,\n}: InvoicesTabProps) {\n if (isLoading) {\n return <InvoicesTabSkeleton />\n }\n\n if (invoices.length === 0) {\n return <NoInvoices />\n }\n\n return (\n <div className={cn('space-y-4', className)}>\n <h3 className=\"font-medium\">Invoice History</h3>\n {invoices.map((invoice) => (\n <InvoiceCard\n key={invoice.id}\n invoice={invoice}\n onRetry={onRetryInvoice}\n onDownload={onDownloadInvoice}\n isRetrying={retryingInvoiceId === invoice.id}\n />\n ))}\n </div>\n )\n}\n","import { Card, CardContent } from '../../ui/card'\nimport { Badge } from '../../ui/badge'\nimport { Button } from '../../ui/button'\nimport { cn } from '@/utils/cn'\nimport type { PortalPaymentMethod, PortalCardDetails } from '../../../client/types'\n\ninterface PaymentMethodCardProps {\n paymentMethod: PortalPaymentMethod\n onSetDefault?: (id: string) => void\n onRemove?: (id: string) => void\n isSettingDefault?: boolean\n isRemoving?: boolean\n className?: string\n}\n\nfunction getCardIcon(brand: PortalCardDetails['brand']) {\n // Simple card brand icons using unicode/emoji\n const icons: Record<string, string> = {\n visa: '💳',\n mastercard: '💳',\n amex: '💳',\n discover: '💳',\n diners: '💳',\n jcb: '💳',\n unionpay: '💳',\n }\n return icons[brand] || '💳'\n}\n\nfunction formatCardBrand(brand: string): string {\n const brandNames: Record<string, string> = {\n visa: 'Visa',\n mastercard: 'Mastercard',\n amex: 'American Express',\n discover: 'Discover',\n diners: 'Diners Club',\n jcb: 'JCB',\n unionpay: 'UnionPay',\n }\n return brandNames[brand] || brand.charAt(0).toUpperCase() + brand.slice(1)\n}\n\nexport function PaymentMethodCard({\n paymentMethod,\n onSetDefault,\n onRemove,\n isSettingDefault,\n isRemoving,\n className,\n}: PaymentMethodCardProps) {\n const { id, card, isDefault } = paymentMethod\n\n if (!card) {\n return null\n }\n\n const expiryDate = `${card.expMonth.toString().padStart(2, '0')}/${card.expYear}`\n\n return (\n <Card className={cn('', className)}>\n <CardContent className=\"p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-3\">\n <span className=\"text-2xl\">{getCardIcon(card.brand)}</span>\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">\n {formatCardBrand(card.brand)} •••• {card.last4}\n </span>\n {isDefault && <Badge variant=\"secondary\">Default</Badge>}\n </div>\n <p className=\"text-sm text-muted-foreground\">Expires {expiryDate}</p>\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 flex items-center gap-2\">\n {!isDefault && onSetDefault && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => onSetDefault(id)}\n disabled={isSettingDefault}\n >\n {isSettingDefault ? 'Setting...' : 'Set as Default'}\n </Button>\n )}\n {onRemove && !isDefault && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => onRemove(id)}\n disabled={isRemoving}\n className=\"text-destructive hover:text-destructive\"\n >\n {isRemoving ? 'Removing...' : 'Remove'}\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n )\n}\n","import { Card, CardContent } from '../../ui/card'\nimport { Button } from '../../ui/button'\nimport { Skeleton } from '../../ui/skeleton'\nimport { PaymentMethodCard } from '../components/PaymentMethodCard'\nimport { cn } from '@/utils/cn'\nimport type { PortalPaymentMethod } from '../../../client/types'\n\ninterface PaymentMethodsTabProps {\n paymentMethods: PortalPaymentMethod[]\n onAddPaymentMethod: () => void\n onSetDefault: (id: string) => void\n onRemove: (id: string) => void\n settingDefaultId?: string\n removingId?: string\n isLoading?: boolean\n className?: string\n}\n\nfunction PlusIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <path d=\"M5 12h14\" />\n <path d=\"M12 5v14\" />\n </svg>\n )\n}\n\nfunction NoPaymentMethods({ onAdd }: { onAdd: () => void }) {\n return (\n <Card>\n <CardContent className=\"flex flex-col items-center justify-center py-12 text-center\">\n <p className=\"text-muted-foreground mb-4\">No payment methods on file.</p>\n <Button onClick={onAdd}>\n <PlusIcon className=\"mr-2\" />\n Add Payment Method\n </Button>\n </CardContent>\n </Card>\n )\n}\n\nfunction PaymentMethodsTabSkeleton() {\n return (\n <div className=\"space-y-4\">\n {[1, 2].map((i) => (\n <Card key={i}>\n <CardContent className=\"p-4\">\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"h-8 w-8 rounded\" />\n <div className=\"space-y-2\">\n <Skeleton className=\"h-5 w-40\" />\n <Skeleton className=\"h-4 w-24\" />\n </div>\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Skeleton className=\"h-8 w-28\" />\n <Skeleton className=\"h-8 w-20\" />\n </div>\n </CardContent>\n </Card>\n ))}\n <Skeleton className=\"h-10 w-44\" />\n </div>\n )\n}\n\nexport function PaymentMethodsTab({\n paymentMethods,\n onAddPaymentMethod,\n onSetDefault,\n onRemove,\n settingDefaultId,\n removingId,\n isLoading,\n className,\n}: PaymentMethodsTabProps) {\n if (isLoading) {\n return <PaymentMethodsTabSkeleton />\n }\n\n if (paymentMethods.length === 0) {\n return <NoPaymentMethods onAdd={onAddPaymentMethod} />\n }\n\n // Sort to show default first\n const sortedMethods = [...paymentMethods].sort((a, b) => {\n if (a.isDefault && !b.isDefault) return -1\n if (!a.isDefault && b.isDefault) return 1\n return 0\n })\n\n return (\n <div className={cn('space-y-4', className)}>\n <h3 className=\"font-medium\">Payment Methods</h3>\n {sortedMethods.map((method) => (\n <PaymentMethodCard\n key={method.id}\n paymentMethod={method}\n onSetDefault={onSetDefault}\n onRemove={onRemove}\n isSettingDefault={settingDefaultId === method.id}\n isRemoving={removingId === method.id}\n />\n ))}\n <Button variant=\"outline\" onClick={onAddPaymentMethod}>\n <PlusIcon className=\"mr-2\" />\n Add New Payment Method\n </Button>\n </div>\n )\n}\n","import { useForm } from 'react-hook-form'\nimport { z } from 'zod'\nimport { Card, CardContent, CardHeader, CardTitle } from '../../ui/card'\nimport { Button } from '../../ui/button'\nimport { Input } from '../../ui/input'\nimport { Label } from '../../ui/label'\nimport { Select, SelectOption } from '../../ui/select'\nimport { Skeleton } from '../../ui/skeleton'\nimport { cn } from '@/utils/cn'\nimport type { PortalCustomer, PortalAddress } from '../../../client/types'\n\n// Country list (simplified)\nconst COUNTRIES = [\n { code: 'US', name: 'United States' },\n { code: 'CA', name: 'Canada' },\n { code: 'GB', name: 'United Kingdom' },\n { code: 'AU', name: 'Australia' },\n { code: 'DE', name: 'Germany' },\n { code: 'FR', name: 'France' },\n { code: 'JP', name: 'Japan' },\n { code: 'IN', name: 'India' },\n { code: 'BR', name: 'Brazil' },\n { code: 'MX', name: 'Mexico' },\n]\n\nconst settingsSchema = z.object({\n name: z.string().min(1, 'Name is required'),\n email: z.string().email('Invalid email address'),\n line1: z.string().optional(),\n line2: z.string().optional(),\n city: z.string().optional(),\n state: z.string().optional(),\n postalCode: z.string().optional(),\n country: z.string().optional(),\n})\n\ntype SettingsFormData = z.infer<typeof settingsSchema>\n\ninterface SettingsTabProps {\n customer: PortalCustomer\n onSave: (data: { name?: string; email?: string; billingAddress?: PortalAddress }) => void\n isSaving?: boolean\n isLoading?: boolean\n className?: string\n}\n\nfunction SettingsTabSkeleton() {\n return (\n <div className=\"space-y-6\">\n <Card>\n <CardHeader>\n <Skeleton className=\"h-5 w-40\" />\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-12\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-12\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <Skeleton className=\"h-5 w-32\" />\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n <div className=\"grid grid-cols-2 gap-4\">\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n </CardContent>\n </Card>\n <Skeleton className=\"h-10 w-28\" />\n </div>\n )\n}\n\nexport function SettingsTab({\n customer,\n onSave,\n isSaving,\n isLoading,\n className,\n}: SettingsTabProps) {\n const {\n register,\n handleSubmit,\n formState: { errors, isDirty },\n } = useForm<SettingsFormData>({\n defaultValues: {\n name: customer.name || '',\n email: customer.email || '',\n line1: customer.billingAddress?.line1 || '',\n line2: customer.billingAddress?.line2 || '',\n city: customer.billingAddress?.city || '',\n state: customer.billingAddress?.state || '',\n postalCode: customer.billingAddress?.postalCode || '',\n country: customer.billingAddress?.country || 'US',\n },\n })\n\n if (isLoading) {\n return <SettingsTabSkeleton />\n }\n\n const onSubmit = (data: SettingsFormData) => {\n const billingAddress: PortalAddress | undefined =\n data.line1 || data.city || data.state || data.postalCode\n ? {\n line1: data.line1 || '',\n line2: data.line2,\n city: data.city || '',\n state: data.state || '',\n postalCode: data.postalCode || '',\n country: data.country || 'US',\n }\n : undefined\n\n onSave({\n name: data.name,\n email: data.email,\n billingAddress,\n })\n }\n\n return (\n <form onSubmit={handleSubmit(onSubmit)} className={cn('space-y-6', className)}>\n {/* Personal Information */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Personal Information</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"name\">Name</Label>\n <Input\n id=\"name\"\n {...register('name')}\n placeholder=\"Your name\"\n />\n {errors.name && (\n <p className=\"text-sm text-destructive\">{errors.name.message}</p>\n )}\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n {...register('email')}\n placeholder=\"your@email.com\"\n />\n {errors.email && (\n <p className=\"text-sm text-destructive\">{errors.email.message}</p>\n )}\n </div>\n </CardContent>\n </Card>\n\n {/* Billing Address */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Billing Address</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"line1\">Address Line 1</Label>\n <Input\n id=\"line1\"\n {...register('line1')}\n placeholder=\"123 Main St\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"line2\">Address Line 2</Label>\n <Input\n id=\"line2\"\n {...register('line2')}\n placeholder=\"Apt 4B (optional)\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"city\">City</Label>\n <Input\n id=\"city\"\n {...register('city')}\n placeholder=\"San Francisco\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"state\">State/Province</Label>\n <Input\n id=\"state\"\n {...register('state')}\n placeholder=\"CA\"\n />\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"postalCode\">ZIP/Postal Code</Label>\n <Input\n id=\"postalCode\"\n {...register('postalCode')}\n placeholder=\"94102\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"country\">Country</Label>\n <Select id=\"country\" {...register('country')}>\n {COUNTRIES.map((country) => (\n <SelectOption key={country.code} value={country.code}>\n {country.name}\n </SelectOption>\n ))}\n </Select>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <Button type=\"submit\" disabled={isSaving || !isDirty}>\n {isSaving ? 'Saving...' : 'Save Changes'}\n </Button>\n </form>\n )\n}\n","import { Card, CardContent, CardHeader, CardTitle } from '../../ui/card'\nimport { Alert, AlertDescription } from '../../ui/alert'\nimport { Badge } from '../../ui/badge'\nimport { Money } from '../../../utils/money'\nimport type { PreviewChangeResponse } from '../../../client/types'\n\ninterface ProrationPreviewProps {\n preview: PreviewChangeResponse\n}\n\nexport function ProrationPreview({ preview }: ProrationPreviewProps) {\n const { current_plan, new_plan, proration, change_type, next_billing_date, notes } = preview\n\n const isUpgrade = change_type === 'upgrade'\n\n return (\n <div className=\"space-y-4\">\n {/* Plan Comparison */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">Plan Change Summary</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {/* Current Plan */}\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">Current Plan:</span>\n <div className=\"text-right\">\n <div className=\"font-medium\">{current_plan.product_name}</div>\n <div className=\"text-muted-foreground text-xs\">\n {Money.format(current_plan.amount, current_plan.currency)} / {current_plan.interval}\n </div>\n </div>\n </div>\n\n {/* Arrow */}\n <div className=\"flex justify-center\">\n <svg\n className=\"w-4 h-4 text-muted-foreground\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 14l-7 7m0 0l-7-7m7 7V3\" />\n </svg>\n </div>\n\n {/* New Plan */}\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">New Plan:</span>\n <div className=\"text-right\">\n <div className=\"font-medium flex items-center gap-2 justify-end\">\n {new_plan.product_name}\n <Badge variant={isUpgrade ? 'default' : 'secondary'} className=\"text-xs\">\n {isUpgrade ? 'Upgrade' : 'Downgrade'}\n </Badge>\n </div>\n <div className=\"text-muted-foreground text-xs\">\n {Money.format(new_plan.amount, new_plan.currency)} / {new_plan.interval}\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n\n {/* Proration Breakdown */}\n {isUpgrade && proration.immediate_payment > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">Billing Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {/* Credit for unused time */}\n {proration.unused_time_credit > 0 && (\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-muted-foreground\">Credit for unused time:</span>\n <span className=\"text-green-600 font-medium\">\n -{Money.format(proration.unused_time_credit, current_plan.currency)}\n </span>\n </div>\n )}\n\n {/* New plan charge */}\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-muted-foreground\">Prorated charge for new plan:</span>\n <span className=\"font-medium\">\n {Money.format(proration.new_plan_charge, new_plan.currency)}\n </span>\n </div>\n\n {/* Divider */}\n <div className=\"border-t my-2\" />\n\n {/* Total */}\n <div className=\"flex justify-between text-base font-semibold\">\n <span>Due Today:</span>\n <span>{Money.format(proration.immediate_payment, new_plan.currency)}</span>\n </div>\n\n {/* Next billing date */}\n <div className=\"text-xs text-muted-foreground mt-3\">\n Next billing: {new Date(next_billing_date).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n })}\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Downgrade Notice */}\n {!isUpgrade && (\n <Alert>\n <AlertDescription className=\"text-sm\">\n Your plan will change to <strong>{new_plan.product_name}</strong> on{' '}\n <strong>\n {new Date(next_billing_date).toLocaleDateString(undefined, {\n month: 'long',\n day: 'numeric',\n year: 'numeric',\n })}\n </strong>\n . You'll keep access to your current plan features until then.\n </AlertDescription>\n </Alert>\n )}\n\n {/* Additional Notes */}\n {notes && notes.length > 0 && (\n <Alert>\n <AlertDescription>\n <ul className=\"list-disc list-inside space-y-1 text-sm\">\n {notes.map((note, idx) => (\n <li key={idx}>{note}</li>\n ))}\n </ul>\n </AlertDescription>\n </Alert>\n )}\n </div>\n )\n}\n","import * as React from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '../../ui/dialog'\nimport { Card, CardContent } from '../../ui/card'\nimport { Button } from '../../ui/button'\nimport { Badge } from '../../ui/badge'\nimport { Alert, AlertDescription } from '../../ui/alert'\nimport { Skeleton } from '../../ui/skeleton'\nimport { Money } from '../../../utils/money'\nimport { cn } from '@/utils/cn'\nimport { ProrationPreview } from '../components/ProrationPreview'\nimport { useAvailablePlans, usePreviewPlanChange, useChangePlan } from '../../../hooks/useSubscription'\nimport type { AvailablePlan, PreviewChangeResponse } from '../../../client/types'\n\ninterface ChangePlanModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n subscriptionId: string\n onSuccess?: () => void\n}\n\nfunction PlanCard({\n plan,\n isSelected,\n isCurrent,\n onSelect,\n disabled,\n}: {\n plan: AvailablePlan\n isSelected: boolean\n isCurrent: boolean\n onSelect: () => void\n disabled?: boolean\n}) {\n const formattedPrice = Money.format(plan.amount, plan.currency)\n const isUpgrade = !isCurrent && plan.amount > 0\n const isDowngrade = !isCurrent && !isUpgrade\n\n return (\n <Card\n className={cn(\n 'cursor-pointer transition-all hover:border-primary',\n isSelected && 'ring-2 ring-primary',\n isCurrent && 'opacity-60',\n disabled && 'pointer-events-none opacity-50'\n )}\n onClick={() => !isCurrent && !disabled && onSelect()}\n >\n <CardContent className=\"p-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-semibold\">{plan.product_name}</span>\n {isCurrent && <Badge variant=\"secondary\">Current</Badge>}\n {isUpgrade && <Badge variant=\"default\">Upgrade</Badge>}\n {isDowngrade && <Badge variant=\"outline\">Downgrade</Badge>}\n </div>\n {plan.description && (\n <p className=\"text-xs text-muted-foreground mt-1\">{plan.description}</p>\n )}\n <p className=\"text-sm font-medium mt-2\">\n {plan.is_free ? 'Free' : `${formattedPrice} / ${plan.interval}`}\n </p>\n </div>\n {!isCurrent && (\n <div className=\"h-5 w-5 rounded-full border-2 border-primary flex items-center justify-center flex-shrink-0 ml-3\">\n {isSelected && (\n <div className=\"h-2.5 w-2.5 rounded-full bg-primary\" />\n )}\n </div>\n )}\n </div>\n </CardContent>\n </Card>\n )\n}\n\nexport function ChangePlanModal({\n open,\n onOpenChange,\n subscriptionId,\n onSuccess,\n}: ChangePlanModalProps) {\n const [selectedPlan, setSelectedPlan] = React.useState<AvailablePlan | null>(null)\n const [preview, setPreview] = React.useState<PreviewChangeResponse | null>(null)\n const [showConfirmation, setShowConfirmation] = React.useState(false)\n\n // Fetch available plans\n const { data: availablePlans, isLoading: isLoadingPlans, error: plansError } = useAvailablePlans(\n subscriptionId,\n { enabled: open }\n )\n\n // Preview mutation\n const previewMutation = usePreviewPlanChange()\n\n // Change plan mutation\n const changePlanMutation = useChangePlan({\n onSuccess: () => {\n onSuccess?.()\n onOpenChange(false)\n },\n })\n\n // Reset state when modal opens/closes\n React.useEffect(() => {\n if (!open) {\n setSelectedPlan(null)\n setPreview(null)\n setShowConfirmation(false)\n }\n }, [open])\n\n // Handle plan selection and fetch preview\n const handleSelectPlan = async (plan: AvailablePlan) => {\n setSelectedPlan(plan)\n setShowConfirmation(false)\n setPreview(null)\n\n // Fetch preview\n try {\n const previewData = await previewMutation.mutateAsync({\n subscriptionId,\n input: {\n new_price_id: plan.price_id,\n effective_date: 'immediate', // Can be made configurable in Phase 2\n },\n })\n\n setPreview(previewData)\n setShowConfirmation(true)\n } catch (error) {\n console.error('Failed to preview plan change:', error)\n setSelectedPlan(null)\n }\n }\n\n // Handle plan change confirmation\n const handleConfirm = async () => {\n if (!selectedPlan || !preview) return\n\n try {\n await changePlanMutation.mutateAsync({\n subscriptionId,\n input: {\n new_price_id: selectedPlan.price_id,\n confirm_amount: preview.proration.immediate_payment,\n effective_date: 'immediate',\n },\n })\n } catch (error) {\n console.error('Failed to change plan:', error)\n }\n }\n\n const allPlans = [\n ...(availablePlans?.available_upgrades || []),\n ...(availablePlans?.available_downgrades || []),\n ]\n\n const currentPlanId = availablePlans?.current_plan?.price_id\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-2xl max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle>\n {showConfirmation ? 'Confirm Plan Change' : 'Change Your Plan'}\n </DialogTitle>\n {!showConfirmation && availablePlans?.current_plan && (\n <DialogDescription>\n You're currently on:{' '}\n <strong>\n {availablePlans.current_plan.product_name} (\n {Money.format(\n availablePlans.current_plan.amount,\n availablePlans.current_plan.currency\n )}\n /{availablePlans.current_plan.interval})\n </strong>\n </DialogDescription>\n )}\n </DialogHeader>\n\n <div className=\"py-4\">\n {/* Loading State */}\n {isLoadingPlans && (\n <div className=\"space-y-3\">\n <Skeleton className=\"h-20 w-full\" />\n <Skeleton className=\"h-20 w-full\" />\n <Skeleton className=\"h-20 w-full\" />\n </div>\n )}\n\n {/* Error State */}\n {plansError && (\n <Alert variant=\"destructive\">\n <AlertDescription>\n Failed to load available plans. Please try again.\n </AlertDescription>\n </Alert>\n )}\n\n {/* Plan Selection View */}\n {!isLoadingPlans && !plansError && !showConfirmation && (\n <div className=\"space-y-3\">\n {allPlans.length === 0 ? (\n <Alert>\n <AlertDescription>\n No other plans are currently available. Contact support if you need assistance.\n </AlertDescription>\n </Alert>\n ) : (\n <>\n {allPlans.map((plan) => (\n <PlanCard\n key={plan.price_id}\n plan={plan}\n isSelected={selectedPlan?.price_id === plan.price_id}\n isCurrent={plan.price_id === currentPlanId}\n onSelect={() => handleSelectPlan(plan)}\n disabled={previewMutation.isPending}\n />\n ))}\n\n {/* Restrictions */}\n {availablePlans?.restrictions && availablePlans.restrictions.length > 0 && (\n <Alert className=\"mt-4\">\n <AlertDescription>\n <p className=\"font-semibold mb-2\">Plan Change Restrictions:</p>\n <ul className=\"list-disc list-inside space-y-1 text-sm\">\n {availablePlans.restrictions.map((restriction, idx) => (\n <li key={idx}>{restriction}</li>\n ))}\n </ul>\n </AlertDescription>\n </Alert>\n )}\n </>\n )}\n </div>\n )}\n\n {/* Preview Loading State */}\n {previewMutation.isPending && selectedPlan && (\n <div className=\"flex items-center justify-center py-8\">\n <div className=\"flex items-center gap-2\">\n <svg className=\"animate-spin h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n <span>Calculating proration...</span>\n </div>\n </div>\n )}\n\n {/* Preview Error State */}\n {previewMutation.isError && (\n <Alert variant=\"destructive\">\n <AlertDescription>\n Failed to calculate proration. Please try again.\n </AlertDescription>\n </Alert>\n )}\n\n {/* Confirmation View with Proration */}\n {showConfirmation && preview && (\n <div>\n <Alert className=\"mb-4\">\n <AlertDescription className=\"text-sm\">\n Please review the details below before confirming your plan change.\n </AlertDescription>\n </Alert>\n\n <ProrationPreview preview={preview} />\n </div>\n )}\n </div>\n\n <DialogFooter>\n {!showConfirmation ? (\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n ) : (\n <>\n <Button\n variant=\"outline\"\n onClick={() => {\n setShowConfirmation(false)\n setPreview(null)\n setSelectedPlan(null)\n }}\n disabled={changePlanMutation.isPending}\n >\n Back\n </Button>\n <Button\n onClick={handleConfirm}\n disabled={changePlanMutation.isPending}\n >\n {changePlanMutation.isPending ? (\n <span className=\"flex items-center gap-2\">\n <svg className=\"animate-spin h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n Processing...\n </span>\n ) : (\n `Confirm ${preview?.change_type === 'upgrade' ? 'Upgrade' : 'Downgrade'}`\n )}\n </Button>\n </>\n )}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","import * as React from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '../../ui/dialog'\nimport { Button } from '../../ui/button'\nimport { Checkbox } from '../../ui/checkbox'\nimport { RadioGroup, RadioGroupItem } from '../../ui/radio-group'\nimport { Textarea } from '../../ui/textarea'\nimport { Label } from '../../ui/label'\nimport type { PortalCancelSubscriptionInput } from '../../../client/types'\n\ntype CancellationReason = PortalCancelSubscriptionInput['cancellationReason']\n\ninterface CancelSubscriptionModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n periodEndDate: string\n onConfirm: (input: PortalCancelSubscriptionInput) => void\n isCanceling?: boolean\n}\n\nconst CANCELLATION_REASONS: { value: CancellationReason; label: string }[] = [\n { value: 'too_expensive', label: 'Too expensive' },\n { value: 'missing_features', label: 'Missing features I need' },\n { value: 'found_alternative', label: 'Found a better alternative' },\n { value: 'no_longer_needed', label: 'No longer need the service' },\n { value: 'other', label: 'Other' },\n]\n\nexport function CancelSubscriptionModal({\n open,\n onOpenChange,\n periodEndDate,\n onConfirm,\n isCanceling,\n}: CancelSubscriptionModalProps) {\n const [selectedReasons, setSelectedReasons] = React.useState<CancellationReason[]>([])\n const [feedback, setFeedback] = React.useState('')\n const [cancelTiming, setCancelTiming] = React.useState<'period_end' | 'immediately'>('period_end')\n\n // Reset form when modal opens\n React.useEffect(() => {\n if (open) {\n setSelectedReasons([])\n setFeedback('')\n setCancelTiming('period_end')\n }\n }, [open])\n\n const formattedEndDate = new Date(periodEndDate).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n })\n\n const toggleReason = (reason: CancellationReason) => {\n setSelectedReasons((prev) =>\n prev.includes(reason)\n ? prev.filter((r) => r !== reason)\n : [...prev, reason]\n )\n }\n\n const handleConfirm = () => {\n onConfirm({\n cancelAtPeriodEnd: cancelTiming === 'period_end',\n cancellationReason: selectedReasons[0], // API accepts single reason\n feedback: feedback || undefined,\n })\n }\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>Cancel Subscription</DialogTitle>\n <DialogDescription>\n We're sorry to see you go! Help us improve by telling us why you're canceling.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-6 py-4\">\n {/* Reasons */}\n <div className=\"space-y-3\">\n <Label className=\"text-sm font-medium\">Reason for canceling</Label>\n {CANCELLATION_REASONS.map((reason) => (\n <label\n key={reason.value}\n className=\"flex items-center gap-2 cursor-pointer\"\n >\n <Checkbox\n checked={selectedReasons.includes(reason.value)}\n onCheckedChange={() => toggleReason(reason.value)}\n />\n <span className=\"text-sm\">{reason.label}</span>\n </label>\n ))}\n </div>\n\n {/* Feedback */}\n <div className=\"space-y-2\">\n <Label htmlFor=\"feedback\" className=\"text-sm font-medium\">\n Additional feedback (optional)\n </Label>\n <Textarea\n id=\"feedback\"\n value={feedback}\n onChange={(e) => setFeedback(e.target.value)}\n placeholder=\"What could we have done better?\"\n className=\"resize-none\"\n rows={3}\n />\n </div>\n\n {/* Timing */}\n <div className=\"space-y-3\">\n <Label className=\"text-sm font-medium\">When would you like to cancel?</Label>\n <RadioGroup\n value={cancelTiming}\n onValueChange={(v) => setCancelTiming(v as 'period_end' | 'immediately')}\n >\n <label className=\"flex items-start gap-2 cursor-pointer\">\n <RadioGroupItem value=\"period_end\" className=\"mt-1\" />\n <div>\n <span className=\"text-sm font-medium\">Cancel at period end ({formattedEndDate})</span>\n <p className=\"text-xs text-muted-foreground\">\n You'll keep access until then.\n </p>\n </div>\n </label>\n <label className=\"flex items-start gap-2 cursor-pointer\">\n <RadioGroupItem value=\"immediately\" className=\"mt-1\" />\n <div>\n <span className=\"text-sm font-medium\">Cancel immediately</span>\n <p className=\"text-xs text-muted-foreground\">\n You'll lose access now. No refunds.\n </p>\n </div>\n </label>\n </RadioGroup>\n </div>\n </div>\n\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={isCanceling}\n >\n Keep Subscription\n </Button>\n <Button\n variant=\"destructive\"\n onClick={handleConfirm}\n disabled={isCanceling}\n >\n {isCanceling ? 'Canceling...' : 'Confirm Cancellation'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","import * as React from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '../../ui/dialog'\nimport { Button } from '../../ui/button'\nimport { Checkbox } from '../../ui/checkbox'\nimport { Label } from '../../ui/label'\nimport { Skeleton } from '../../ui/skeleton'\nimport { cn } from '@/utils/cn'\n\n// Stripe imports\nimport {\n Elements,\n CardElement,\n useStripe,\n useElements,\n} from '@stripe/react-stripe-js'\nimport { loadStripe, type Stripe } from '@stripe/stripe-js'\n\ninterface AddPaymentMethodModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n onSuccess: (paymentMethodId: string, setAsDefault: boolean) => void\n clientSecret?: string\n stripePublishableKey?: string\n isLoading?: boolean\n}\n\n// Card element styling\nconst cardElementOptions = {\n style: {\n base: {\n fontSize: '16px',\n color: 'hsl(var(--foreground))',\n '::placeholder': {\n color: 'hsl(var(--muted-foreground))',\n },\n },\n invalid: {\n color: 'hsl(var(--destructive))',\n },\n },\n}\n\ninterface PaymentFormProps {\n clientSecret: string\n onSuccess: (paymentMethodId: string, setAsDefault: boolean) => void\n onCancel: () => void\n}\n\nfunction PaymentForm({ clientSecret, onSuccess, onCancel }: PaymentFormProps) {\n const stripe = useStripe()\n const elements = useElements()\n const [isSubmitting, setIsSubmitting] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [setAsDefault, setSetAsDefault] = React.useState(true)\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!stripe || !elements) {\n return\n }\n\n setIsSubmitting(true)\n setError(null)\n\n const cardElement = elements.getElement(CardElement)\n if (!cardElement) {\n setError('Card element not found')\n setIsSubmitting(false)\n return\n }\n\n try {\n const { setupIntent, error: setupError } = await stripe.confirmCardSetup(\n clientSecret,\n {\n payment_method: {\n card: cardElement,\n },\n }\n )\n\n if (setupError) {\n setError(setupError.message || 'Failed to set up payment method')\n setIsSubmitting(false)\n return\n }\n\n if (setupIntent?.payment_method) {\n onSuccess(setupIntent.payment_method as string, setAsDefault)\n }\n } catch (err) {\n setError('An unexpected error occurred')\n setIsSubmitting(false)\n }\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label>Card Details</Label>\n <div className=\"rounded-md border border-input bg-background p-3\">\n <CardElement options={cardElementOptions} />\n </div>\n </div>\n\n {error && (\n <p className=\"text-sm text-destructive\">{error}</p>\n )}\n\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <Checkbox\n checked={setAsDefault}\n onCheckedChange={(checked) => setSetAsDefault(checked as boolean)}\n />\n <span className=\"text-sm\">Set as default payment method</span>\n </label>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={isSubmitting}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={!stripe || isSubmitting}>\n {isSubmitting ? 'Adding...' : 'Add Card'}\n </Button>\n </DialogFooter>\n\n <p className=\"text-xs text-muted-foreground text-center flex items-center justify-center gap-1\">\n <LockIcon className=\"h-3 w-3\" />\n Secured by Stripe\n </p>\n </form>\n )\n}\n\nfunction LockIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n )\n}\n\nfunction LoadingSkeleton() {\n return (\n <div className=\"space-y-6\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-12 w-full\" />\n </div>\n <div className=\"flex items-center gap-2\">\n <Skeleton className=\"h-4 w-4\" />\n <Skeleton className=\"h-4 w-48\" />\n </div>\n <div className=\"flex justify-end gap-2\">\n <Skeleton className=\"h-10 w-20\" />\n <Skeleton className=\"h-10 w-24\" />\n </div>\n </div>\n )\n}\n\n// Stripe promise cache\nlet stripePromise: Promise<Stripe | null> | null = null\n\nfunction getStripePromise(publishableKey: string) {\n if (!stripePromise) {\n stripePromise = loadStripe(publishableKey)\n }\n return stripePromise\n}\n\nexport function AddPaymentMethodModal({\n open,\n onOpenChange,\n onSuccess,\n clientSecret,\n stripePublishableKey,\n isLoading,\n}: AddPaymentMethodModalProps) {\n const handleCancel = () => {\n onOpenChange(false)\n }\n\n const handleSuccess = (paymentMethodId: string, setAsDefault: boolean) => {\n onSuccess(paymentMethodId, setAsDefault)\n onOpenChange(false)\n }\n\n const showForm = !isLoading && clientSecret && stripePublishableKey\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>Add Payment Method</DialogTitle>\n <DialogDescription>\n Enter your card details below. Your card will be saved for future payments.\n </DialogDescription>\n </DialogHeader>\n\n {isLoading && <LoadingSkeleton />}\n\n {showForm && (\n <Elements stripe={getStripePromise(stripePublishableKey)}>\n <PaymentForm\n clientSecret={clientSecret}\n onSuccess={handleSuccess}\n onCancel={handleCancel}\n />\n </Elements>\n )}\n\n {!isLoading && !showForm && (\n <div className=\"py-8 text-center text-muted-foreground\">\n <p>Unable to load payment form. Please try again.</p>\n <Button variant=\"outline\" className=\"mt-4\" onClick={handleCancel}>\n Close\n </Button>\n </div>\n )}\n </DialogContent>\n </Dialog>\n )\n}\n","import { Alert, AlertDescription, AlertTitle } from '../ui/alert'\nimport { Button } from '../ui/button'\nimport { cn } from '../../utils/cn'\nimport type { NudgeTrigger } from '../../client/types'\n\nexport interface BannerNudgeProps {\n trigger: NudgeTrigger\n onUpgrade: () => void\n onDismiss: () => void\n theme?: 'light' | 'dark'\n}\n\nexport function BannerNudge({\n trigger,\n onUpgrade,\n onDismiss,\n}: BannerNudgeProps) {\n const isUrgent = trigger.actual && trigger.actual >= 95\n\n return (\n <div\n className={cn(\n 'fixed top-0 left-0 right-0 z-50 animate-in slide-in-from-top duration-300',\n 'px-4 py-2'\n )}\n role={isUrgent ? 'alert' : 'status'}\n >\n <Alert\n variant={isUrgent ? 'destructive' : 'default'}\n className=\"max-w-4xl mx-auto flex items-center justify-between\"\n >\n <div className=\"flex items-start gap-3 flex-1\">\n {/* Icon */}\n <div className=\"flex-shrink-0 mt-0.5\">\n {isUrgent ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-destructive\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-amber-500\"\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z\" />\n <line x1=\"12\" x2=\"12\" y1=\"9\" y2=\"13\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"17\" y2=\"17\" />\n </svg>\n )}\n </div>\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n <AlertTitle className=\"mb-1 font-semibold\">\n {trigger.message.title}\n </AlertTitle>\n <AlertDescription className=\"text-sm\">\n {trigger.message.body}\n </AlertDescription>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-2 ml-4 flex-shrink-0\">\n <Button\n size=\"sm\"\n onClick={onUpgrade}\n >\n {trigger.message.cta}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onDismiss}\n >\n Maybe Later\n </Button>\n </div>\n </Alert>\n </div>\n )\n}\n","import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'\nimport { Button } from '../ui/button'\nimport { cn } from '../../utils/cn'\nimport type { NudgeTrigger } from '../../client/types'\n\nexport interface ToastNudgeProps {\n trigger: NudgeTrigger\n onUpgrade: () => void\n onDismiss: () => void\n theme?: 'light' | 'dark'\n}\n\nexport function ToastNudge({\n trigger,\n onUpgrade,\n onDismiss,\n}: ToastNudgeProps) {\n const isUrgent = trigger.actual && trigger.actual >= 95\n\n return (\n <div\n className={cn(\n 'fixed bottom-4 right-4 z-50 animate-in slide-in-from-bottom-4 duration-400',\n 'w-80 max-w-[calc(100vw-2rem)]'\n )}\n role=\"status\"\n aria-live=\"polite\"\n >\n <Card className=\"shadow-lg border-2\">\n <CardHeader className=\"pb-2 pr-8 relative\">\n {/* Close button */}\n <button\n onClick={onDismiss}\n className=\"absolute top-3 right-3 p-1 rounded-md hover:bg-muted transition-colors\"\n aria-label=\"Dismiss\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n\n {/* Icon and Title */}\n <div className=\"flex items-start gap-2\">\n {isUrgent ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-destructive flex-shrink-0 mt-0.5\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-amber-500 flex-shrink-0 mt-0.5\"\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z\" />\n <line x1=\"12\" x2=\"12\" y1=\"9\" y2=\"13\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"17\" y2=\"17\" />\n </svg>\n )}\n <CardTitle className=\"text-base font-semibold leading-tight\">\n {trigger.message.title}\n </CardTitle>\n </div>\n </CardHeader>\n\n <CardContent className=\"pt-0 pb-4\">\n <p className=\"text-sm text-muted-foreground mb-4\">\n {trigger.message.body}\n </p>\n\n <Button\n className=\"w-full\"\n size=\"sm\"\n onClick={onUpgrade}\n >\n {trigger.message.cta}\n </Button>\n </CardContent>\n </Card>\n </div>\n )\n}\n","import {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '../ui/dialog'\nimport { Card, CardContent } from '../ui/card'\nimport { Button } from '../ui/button'\nimport { Badge } from '../ui/badge'\nimport type { NudgeTrigger } from '../../client/types'\n\nexport interface ModalNudgeProps {\n trigger: NudgeTrigger\n onUpgrade: () => void\n onDismiss: () => void\n theme?: 'light' | 'dark'\n}\n\nexport function ModalNudge({\n trigger,\n onUpgrade,\n onDismiss,\n}: ModalNudgeProps) {\n const isUrgent = trigger.actual && trigger.actual >= 100\n\n // Format price for display\n const formatPrice = (amount: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n }).format(amount / 100)\n }\n\n return (\n <Dialog open onOpenChange={(open) => !open && onDismiss()}>\n <DialogContent\n className=\"sm:max-w-md\"\n role={isUrgent ? 'alertdialog' : 'dialog'}\n >\n <DialogHeader>\n <div className=\"flex items-center gap-2\">\n {isUrgent ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-destructive\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-amber-500\"\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z\" />\n <line x1=\"12\" x2=\"12\" y1=\"9\" y2=\"13\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"17\" y2=\"17\" />\n </svg>\n )}\n <DialogTitle>{trigger.message.title}</DialogTitle>\n </div>\n <DialogDescription className=\"pt-2\">\n {trigger.message.body}\n </DialogDescription>\n </DialogHeader>\n\n {/* Suggested Plan Card */}\n <Card className=\"border-2 border-primary/20\">\n <CardContent className=\"pt-4\">\n <div className=\"flex items-start justify-between mb-4\">\n <div>\n <h3 className=\"font-semibold text-lg\">\n {trigger.suggestedPlan.name}\n </h3>\n <div className=\"flex items-baseline gap-1 mt-1\">\n <span className=\"text-2xl font-bold\">\n {formatPrice(\n trigger.suggestedPlan.price.amount,\n trigger.suggestedPlan.price.currency\n )}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n / {trigger.suggestedPlan.price.interval}\n </span>\n </div>\n </div>\n <Badge variant=\"secondary\">Recommended</Badge>\n </div>\n\n {/* Highlights */}\n <div className=\"space-y-2\">\n <p className=\"text-sm font-medium text-muted-foreground\">\n What you'll get:\n </p>\n <ul className=\"space-y-2\">\n {trigger.suggestedPlan.highlights.map((highlight, index) => (\n <li key={index} className=\"flex items-start gap-2 text-sm\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-green-500 flex-shrink-0 mt-0.5\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n {highlight}\n </li>\n ))}\n </ul>\n </div>\n </CardContent>\n </Card>\n\n <DialogFooter className=\"flex-col sm:flex-row gap-2\">\n <Button\n variant=\"outline\"\n onClick={onDismiss}\n className=\"sm:flex-1\"\n >\n Maybe Later\n </Button>\n <Button\n onClick={onUpgrade}\n className=\"sm:flex-1\"\n >\n {trigger.message.cta} - {formatPrice(\n trigger.suggestedPlan.price.amount,\n trigger.suggestedPlan.price.currency\n )}/{trigger.suggestedPlan.price.interval}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","import * as React from 'react'\nimport { BannerNudge } from './BannerNudge'\nimport { ToastNudge } from './ToastNudge'\nimport { ModalNudge } from './ModalNudge'\nimport type { NudgeTrigger } from '../../client/types'\n\nexport interface UpgradeNudgeProps {\n /**\n * Nudge trigger data (from API or usage check)\n */\n trigger: NudgeTrigger\n\n /**\n * Display style\n * - 'banner': Top banner (non-intrusive)\n * - 'toast': Toast notification (bottom-right)\n * - 'modal': Modal dialog (more prominent)\n */\n style?: 'banner' | 'toast' | 'modal'\n\n /**\n * Auto-dismiss after N milliseconds (0 = no auto-dismiss)\n */\n autoDismiss?: number\n\n /**\n * Callback when user clicks upgrade\n */\n onUpgrade?: (priceId: string) => void\n\n /**\n * Callback when user dismisses nudge\n */\n onDismiss?: () => void\n\n /**\n * Optional: Custom theme\n */\n theme?: 'light' | 'dark'\n}\n\n// Store dismissal timestamp\nfunction storeDismissal(trigger: NudgeTrigger): void {\n if (typeof window === 'undefined') return\n\n const dismissalKey = `nudge_dismissed_${trigger.type}_${trigger.feature || 'general'}`\n localStorage.setItem(dismissalKey, Date.now().toString())\n}\n\nexport function UpgradeNudge({\n trigger,\n style = 'banner',\n autoDismiss = 0,\n onUpgrade,\n onDismiss,\n theme,\n}: UpgradeNudgeProps) {\n const [isVisible, setIsVisible] = React.useState(true)\n\n // Reset visibility when trigger changes (for demo purposes)\n React.useEffect(() => {\n setIsVisible(true)\n }, [trigger, style])\n\n // Auto-dismiss timer (autoDismiss is in milliseconds)\n React.useEffect(() => {\n if (autoDismiss > 0 && isVisible) {\n const timer = setTimeout(() => {\n handleDismiss()\n }, autoDismiss)\n\n return () => clearTimeout(timer)\n }\n }, [autoDismiss, isVisible])\n\n // Handle keyboard escape\n React.useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && isVisible) {\n handleDismiss()\n }\n }\n\n window.addEventListener('keydown', handleKeyDown)\n return () => window.removeEventListener('keydown', handleKeyDown)\n }, [isVisible])\n\n const handleDismiss = () => {\n setIsVisible(false)\n storeDismissal(trigger)\n onDismiss?.()\n }\n\n const handleUpgrade = () => {\n onUpgrade?.(trigger.suggestedPlan.priceId)\n }\n\n if (!isVisible) return null\n\n switch (style) {\n case 'banner':\n return (\n <BannerNudge\n trigger={trigger}\n onUpgrade={handleUpgrade}\n onDismiss={handleDismiss}\n theme={theme}\n />\n )\n case 'toast':\n return (\n <ToastNudge\n trigger={trigger}\n onUpgrade={handleUpgrade}\n onDismiss={handleDismiss}\n theme={theme}\n />\n )\n case 'modal':\n return (\n <ModalNudge\n trigger={trigger}\n onUpgrade={handleUpgrade}\n onDismiss={handleDismiss}\n theme={theme}\n />\n )\n default:\n return null\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { useBillingOS } from '../../../providers/BillingOSProvider'\nimport type { UsageCheckResponse } from '../../../client/types'\n\nexport interface UseUsageCheckOptions {\n /**\n * Whether to enable the query\n */\n enabled?: boolean\n /**\n * Refetch interval in milliseconds (0 = no auto refetch)\n */\n refetchInterval?: number\n}\n\n/**\n * Hook to check usage and get nudge trigger\n */\nexport function useUsageCheck(options: UseUsageCheckOptions = {}) {\n const { client } = useBillingOS()\n const { enabled = true, refetchInterval = 0 } = options\n\n return useQuery<UsageCheckResponse, Error>({\n queryKey: ['usageCheck'],\n queryFn: async () => {\n return client.checkUsage()\n },\n enabled,\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 10 * 60 * 1000, // 10 minutes\n refetchInterval: refetchInterval > 0 ? refetchInterval : undefined,\n })\n}\n","import React from 'react'\nimport { useFeatureGate } from '../../hooks/useFeature'\n\nexport interface FeatureGateProps {\n /**\n * The feature key to check access for\n */\n feature: string\n\n /**\n * Content to render when user has access\n */\n children: React.ReactNode\n\n /**\n * Content to render when access is denied (optional)\n */\n fallback?: React.ReactNode\n\n /**\n * Content to render while loading (optional)\n */\n loading?: React.ReactNode\n\n /**\n * Callback when access is denied\n */\n onAccessDenied?: () => void\n\n /**\n * Callback when quota is exceeded\n */\n onQuotaExceeded?: (usage: number, limit: number) => void\n\n /**\n * Whether to show remaining usage in a badge\n */\n showUsageBadge?: boolean\n}\n\n/**\n * FeatureGate component for conditional rendering based on feature access\n *\n * @example\n * ```tsx\n * <FeatureGate\n * feature=\"advanced_analytics\"\n * fallback={<UpgradePrompt feature=\"Advanced Analytics\" />}\n * >\n * <AdvancedAnalyticsDashboard />\n * </FeatureGate>\n * ```\n */\nexport function FeatureGate({\n feature,\n children,\n fallback,\n loading,\n onAccessDenied,\n onQuotaExceeded,\n showUsageBadge = false,\n}: FeatureGateProps) {\n const {\n hasAccess,\n isLoading,\n isError,\n usage,\n limit,\n remaining,\n } = useFeatureGate(feature, {\n onAccessDenied,\n onQuotaExceeded,\n })\n\n if (isLoading) {\n return <>{loading || <FeatureGateLoading />}</>\n }\n\n if (isError || !hasAccess) {\n return <>{fallback || <FeatureGateDenied feature={feature} />}</>\n }\n\n // If user has access and usage badge is requested, wrap with usage indicator\n if (showUsageBadge && limit > 0) {\n return (\n <div className=\"relative\">\n {children}\n <UsageBadge usage={usage} limit={limit} remaining={remaining} />\n </div>\n )\n }\n\n return <>{children}</>\n}\n\n/**\n * Default loading component\n */\nfunction FeatureGateLoading() {\n return (\n <div className=\"flex items-center justify-center p-4\">\n <div className=\"animate-pulse text-gray-400\">\n Checking access...\n </div>\n </div>\n )\n}\n\n/**\n * Default access denied component\n */\nfunction FeatureGateDenied({ feature }: { feature: string }) {\n return (\n <div className=\"p-4 border border-gray-200 bg-gray-50 rounded-lg\">\n <div className=\"text-center\">\n <svg\n className=\"mx-auto h-12 w-12 text-gray-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n <h3 className=\"mt-2 text-sm font-medium text-gray-900\">\n Feature Locked\n </h3>\n <p className=\"mt-1 text-sm text-gray-500\">\n Upgrade your plan to access {feature.replace(/_/g, ' ')}\n </p>\n </div>\n </div>\n )\n}\n\n/**\n * Usage badge component\n */\nfunction UsageBadge({\n usage,\n limit,\n remaining,\n}: {\n usage: number\n limit: number\n remaining: number\n}) {\n const percentage = Math.min(100, Math.round((usage / limit) * 100))\n\n // Determine color based on usage\n let colorClass = 'bg-green-100 text-green-800'\n if (percentage >= 90) {\n colorClass = 'bg-red-100 text-red-800'\n } else if (percentage >= 75) {\n colorClass = 'bg-yellow-100 text-yellow-800'\n }\n\n return (\n <div className={`absolute top-2 right-2 px-2 py-1 rounded-full text-xs font-medium ${colorClass}`}>\n {remaining.toLocaleString()} / {limit.toLocaleString()} remaining\n </div>\n )\n}","import { useUsageMetrics } from '../../hooks/useFeature'\n\nexport interface UsageDisplayProps {\n /**\n * Optional feature key to show usage for specific feature\n */\n featureKey?: string\n\n /**\n * Custom title\n */\n title?: string\n\n /**\n * Whether to show a progress bar\n */\n showProgress?: boolean\n\n /**\n * Whether to show reset timer\n */\n showResetTimer?: boolean\n\n /**\n * Custom className for styling\n */\n className?: string\n}\n\n/**\n * Component to display usage metrics for features\n *\n * @example\n * ```tsx\n * // Show all usage metrics\n * <UsageDisplay />\n *\n * // Show specific feature usage\n * <UsageDisplay featureKey=\"api_calls\" />\n * ```\n */\nexport function UsageDisplay({\n featureKey,\n title = 'Usage Metrics',\n showProgress = true,\n showResetTimer = true,\n className = '',\n}: UsageDisplayProps) {\n const { data, isLoading, isError } = useUsageMetrics(featureKey)\n\n if (isLoading) {\n return (\n <div className={`p-4 animate-pulse ${className}`}>\n <div className=\"h-4 bg-gray-200 rounded w-1/4 mb-4\"></div>\n <div className=\"space-y-3\">\n <div className=\"h-8 bg-gray-200 rounded\"></div>\n <div className=\"h-8 bg-gray-200 rounded\"></div>\n </div>\n </div>\n )\n }\n\n if (isError || !data?.metrics || data.metrics.length === 0) {\n return (\n <div className={`p-4 text-center text-gray-500 ${className}`}>\n No usage data available\n </div>\n )\n }\n\n return (\n <div className={`p-4 ${className}`}>\n <h3 className=\"text-lg font-semibold mb-4\">{title}</h3>\n <div className=\"space-y-4\">\n {data.metrics.map((metric) => (\n <UsageMetricCard\n key={metric.feature_key}\n metric={metric}\n showProgress={showProgress}\n showResetTimer={showResetTimer}\n />\n ))}\n </div>\n </div>\n )\n}\n\n/**\n * Individual usage metric card\n */\nfunction UsageMetricCard({\n metric,\n showProgress,\n showResetTimer,\n}: {\n metric: any\n showProgress: boolean\n showResetTimer: boolean\n}) {\n const getProgressColor = (percentage: number) => {\n if (percentage >= 90) return 'bg-red-500'\n if (percentage >= 75) return 'bg-yellow-500'\n return 'bg-green-500'\n }\n\n return (\n <div className=\"border border-gray-200 rounded-lg p-4 bg-white\">\n <div className=\"flex justify-between items-start mb-2\">\n <div>\n <h4 className=\"font-medium text-gray-900\">{metric.feature_title}</h4>\n <p className=\"text-sm text-gray-500\">{metric.product_name}</p>\n </div>\n <div className=\"text-right\">\n <div className=\"text-2xl font-semibold\">\n {metric.consumed.toLocaleString()}\n </div>\n <div className=\"text-sm text-gray-500\">\n of {metric.limit.toLocaleString()}\n </div>\n </div>\n </div>\n\n {showProgress && (\n <div className=\"mt-3\">\n <div className=\"w-full bg-gray-200 rounded-full h-2\">\n <div\n className={`h-2 rounded-full transition-all ${getProgressColor(\n metric.percentage_used\n )}`}\n style={{ width: `${Math.min(100, metric.percentage_used)}%` }}\n ></div>\n </div>\n <div className=\"flex justify-between mt-1\">\n <span className=\"text-xs text-gray-500\">\n {metric.percentage_used}% used\n </span>\n <span className=\"text-xs text-gray-500\">\n {metric.remaining.toLocaleString()} remaining\n </span>\n </div>\n </div>\n )}\n\n {showResetTimer && metric.resets_in_days > 0 && (\n <div className=\"mt-2 text-xs text-gray-500\">\n <svg\n className=\"inline-block w-3 h-3 mr-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n Resets in {metric.resets_in_days} day{metric.resets_in_days !== 1 ? 's' : ''}\n </div>\n )}\n </div>\n )\n}\n\n/**\n * Compact usage display for inline use\n */\nexport function CompactUsageDisplay({\n featureKey,\n className = '',\n}: {\n featureKey: string\n className?: string\n}) {\n const { data, isLoading } = useUsageMetrics(featureKey)\n\n if (isLoading || !data?.metrics?.[0]) {\n return null\n }\n\n const metric = data.metrics[0]\n const getColor = (percentage: number) => {\n if (percentage >= 90) return 'text-red-600'\n if (percentage >= 75) return 'text-yellow-600'\n return 'text-green-600'\n }\n\n return (\n <div className={`inline-flex items-center gap-2 ${className}`}>\n <span className=\"text-sm text-gray-500\">Usage:</span>\n <span className={`text-sm font-medium ${getColor(metric.percentage_used)}`}>\n {metric.consumed.toLocaleString()} / {metric.limit.toLocaleString()}\n </span>\n {metric.percentage_used >= 90 && (\n <svg\n className=\"w-4 h-4 text-red-500\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z\"\n clipRule=\"evenodd\"\n />\n </svg>\n )}\n </div>\n )\n}","import { useProducts } from '../../hooks/useProducts'\n\nexport interface UpgradePromptProps {\n /**\n * Feature that requires upgrade\n */\n feature?: string\n\n /**\n * Title text\n */\n title?: string\n\n /**\n * Description text\n */\n description?: string\n\n /**\n * Whether it's a quota exceeded prompt\n */\n isQuotaExceeded?: boolean\n\n /**\n * Current usage (for quota exceeded)\n */\n usage?: number\n\n /**\n * Usage limit (for quota exceeded)\n */\n limit?: number\n\n /**\n * Custom className for styling\n */\n className?: string\n\n /**\n * Click handler for upgrade button\n */\n onUpgradeClick?: () => void\n}\n\n/**\n * Component that prompts users to upgrade when they hit limits or access denied features\n *\n * @example\n * ```tsx\n * <UpgradePrompt\n * feature=\"Advanced Analytics\"\n * description=\"Upgrade to Pro to access advanced analytics and reporting\"\n * />\n * ```\n */\nexport function UpgradePrompt({\n feature,\n title = 'Upgrade Required',\n description,\n isQuotaExceeded = false,\n usage,\n limit,\n className = '',\n onUpgradeClick,\n}: UpgradePromptProps) {\n const { data: productsData } = useProducts()\n\n const defaultDescription = isQuotaExceeded\n ? `You've reached your usage limit${feature ? ` for ${feature}` : ''}. Upgrade your plan to continue.`\n : `Upgrade your plan to access${feature ? ` ${feature}` : ' this feature'}.`\n\n const handleUpgradeClick = () => {\n if (onUpgradeClick) {\n onUpgradeClick()\n } else {\n // Scroll to pricing table if it exists\n const pricingTable = document.querySelector('[data-pricing-table]')\n if (pricingTable) {\n pricingTable.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n }\n }\n\n return (\n <div className={`rounded-lg border-2 border-dashed border-gray-300 p-8 ${className}`}>\n <div className=\"text-center\">\n {/* Icon */}\n <div className=\"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-gradient-to-br from-blue-500 to-purple-600\">\n <svg\n className=\"h-6 w-6 text-white\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 10V3L4 14h7v7l9-11h-7z\"\n />\n </svg>\n </div>\n\n {/* Title */}\n <h3 className=\"mt-4 text-lg font-semibold text-gray-900\">\n {title}\n </h3>\n\n {/* Description */}\n <p className=\"mt-2 text-sm text-gray-600\">\n {description || defaultDescription}\n </p>\n\n {/* Usage Info (if quota exceeded) */}\n {isQuotaExceeded && usage !== undefined && limit !== undefined && (\n <div className=\"mt-4 inline-flex items-center gap-2 rounded-full bg-red-50 px-3 py-1\">\n <svg\n className=\"h-4 w-4 text-red-500\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"text-sm font-medium text-red-800\">\n {usage.toLocaleString()} / {limit.toLocaleString()} used\n </span>\n </div>\n )}\n\n {/* Upgrade Button */}\n <div className=\"mt-6\">\n <button\n onClick={handleUpgradeClick}\n className=\"inline-flex items-center rounded-md bg-gradient-to-r from-blue-600 to-purple-600 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:from-blue-700 hover:to-purple-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n <svg\n className=\"mr-2 h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 10l7-7m0 0l7 7m-7-7v18\"\n />\n </svg>\n Upgrade Plan\n </button>\n </div>\n\n {/* Available Plans Preview */}\n {productsData?.products && productsData.products.length > 0 && (\n <div className=\"mt-6 text-xs text-gray-500\">\n Available plans:\n <div className=\"mt-1 flex justify-center gap-2\">\n {productsData.products.slice(0, 3).map((product) => (\n <span\n key={product.id}\n className=\"inline-block rounded-full bg-gray-100 px-2 py-1\"\n >\n {product.name}\n </span>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n}\n\n/**\n * Compact upgrade prompt for inline use\n */\nexport function CompactUpgradePrompt({\n feature,\n onUpgradeClick,\n className = '',\n}: {\n feature?: string\n onUpgradeClick?: () => void\n className?: string\n}) {\n return (\n <div className={`inline-flex items-center gap-2 rounded-md bg-yellow-50 px-3 py-2 ${className}`}>\n <svg\n className=\"h-4 w-4 text-yellow-600\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M10 1.944A11.954 11.954 0 012.166 5C2.056 5.649 2 6.319 2 7c0 5.225 3.34 9.67 8 11.317C14.66 16.67 18 12.225 18 7c0-.682-.057-1.35-.166-2.001A11.954 11.954 0 0110 1.944zM11 14a1 1 0 11-2 0 1 1 0 012 0zm0-7a1 1 0 10-2 0v3a1 1 0 102 0V7z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"text-sm text-yellow-800\">\n Upgrade to access{feature ? ` ${feature}` : ' this feature'}\n </span>\n <button\n onClick={onUpgradeClick}\n className=\"ml-1 text-sm font-medium text-yellow-800 hover:text-yellow-900 underline\"\n >\n Upgrade\n </button>\n </div>\n )\n}","import { format, formatDistance, formatRelative, isAfter, isBefore, parseISO } from 'date-fns'\n\n/**\n * Format a date string or Date object\n * @param date - Date string (ISO) or Date object\n * @param formatStr - Format string (date-fns format)\n * @returns Formatted date string\n *\n * @example\n * formatDate('2024-01-15T10:30:00Z', 'PPP') // \"January 15th, 2024\"\n * formatDate(new Date(), 'yyyy-MM-dd') // \"2024-01-15\"\n */\nexport const formatDate = (date: string | Date, formatStr = 'PPP'): string => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return format(dateObj, formatStr)\n}\n\n/**\n * Format a date as relative time (e.g., \"2 hours ago\")\n * @param date - Date string (ISO) or Date object\n * @param baseDate - Base date to compare against (defaults to now)\n * @returns Relative time string\n *\n * @example\n * formatRelativeTime('2024-01-15T08:30:00Z') // \"2 hours ago\"\n */\nexport const formatRelativeTime = (\n date: string | Date,\n baseDate: Date = new Date(),\n): string => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return formatDistance(dateObj, baseDate, { addSuffix: true })\n}\n\n/**\n * Format a date relative to now (e.g., \"today at 10:30 AM\")\n * @param date - Date string (ISO) or Date object\n * @param baseDate - Base date to compare against (defaults to now)\n * @returns Relative date string\n *\n * @example\n * formatRelativeDate('2024-01-15T10:30:00Z') // \"today at 10:30 AM\"\n */\nexport const formatRelativeDate = (\n date: string | Date,\n baseDate: Date = new Date(),\n): string => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return formatRelative(dateObj, baseDate)\n}\n\n/**\n * Check if a date is in the past\n * @param date - Date string (ISO) or Date object\n * @returns True if date is in the past\n */\nexport const isPast = (date: string | Date): boolean => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return isBefore(dateObj, new Date())\n}\n\n/**\n * Check if a date is in the future\n * @param date - Date string (ISO) or Date object\n * @returns True if date is in the future\n */\nexport const isFuture = (date: string | Date): boolean => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return isAfter(dateObj, new Date())\n}\n\n/**\n * Parse ISO date string to Date object\n * @param date - ISO date string\n * @returns Date object\n */\nexport const parseDate = (date: string): Date => {\n return parseISO(date)\n}\n\n/**\n * Date utilities namespace\n */\nexport const DateUtils = {\n format: formatDate,\n formatRelative: formatRelativeTime,\n formatRelativeDate,\n isPast,\n isFuture,\n parse: parseDate,\n}\n","// BillingOS SDK - Main Entry Point\n\n// Log SDK version on load\nconsole.log(\n '%c🎯 BillingOS SDK v1.2.0 loaded with Iframe Checkout',\n 'background: #3b82f6; color: white; padding: 6px 12px; border-radius: 6px; font-weight: bold; font-size: 14px;'\n)\n\n// Import global styles (will be bundled)\nimport './styles/globals.css'\n\n// Client\nexport * from './client'\n\n// Hooks\nexport * from './hooks'\n\n// Components\nexport * from './components'\n\n// Providers\nexport * from './providers'\n\n// Utils\nexport * from './utils'\n\n// Checkout API\nexport { openCheckout, getCheckoutAPI, CheckoutAPI } from './checkout'\nexport type { CheckoutOpenOptions } from './checkout'\n\n// Create a global billingOS object for imperative API\nimport { BillingOSClient } from './client'\nimport { getCheckoutAPI } from './checkout'\n\ndeclare global {\n interface Window {\n billingOS?: {\n checkout: {\n open: (options: import('./checkout').CheckoutOpenOptions) => Promise<{\n success: boolean\n subscription?: import('./client/types').Subscription\n error?: Error\n }>\n }\n client?: BillingOSClient\n }\n }\n}\n\n// Initialize global billingOS object if in browser\nif (typeof window !== 'undefined') {\n window.billingOS = {\n checkout: {\n open: async (options) => {\n const api = getCheckoutAPI()\n return api.open(options)\n }\n }\n }\n}\n"],"names":["BillingOSError","message","status","data","UnauthorizedError","NotFoundError","ValidationError","RateLimitError","ServerError","NetworkError","originalError","isValidationError","error","isUnauthorizedError","isNotFoundError","isRateLimitError","BillingOSClient","sessionToken","options","__publicField","input","_a","_b","response","sessionId","_sessionId","clientSecret","paymentMethodId","_couponCode","path","url","controller","timeoutId","contentType","isJson","errorData","errorMessage","body","id","params","query","queryString","immediately","subscriptionId","_customerId","event","featureKey","customerId","invoiceId","planIds","atRisk","m","createBillingOSClient","useSessionToken","tokenUrl","manualToken","refreshBeforeExpiry","autoRefresh","onTokenRefresh","onError","token","setToken","useState","expiresAt","setExpiresAt","isLoading","setIsLoading","setError","refreshTimerRef","useRef","isMountedRef","fetchToken","useCallback","err","useEffect","now","msUntilExpiry","refreshAt","isValid","BillingOSContext","createContext","createDefaultQueryClient","QueryClient","BillingOSProvider","manualSessionToken","sessionTokenUrl","sessionTokenOptions","customerEmail","customerName","organizationId","queryClient","children","React","qc","useMemo","client","contextValue","jsx","QueryClientProvider","useBillingOS","context","useContext","subscriptionKeys","filters","useSubscription","useQuery","useSubscriptions","useCreateSubscription","useQueryClient","useMutation","_data","_variables","_context","useUpdateSubscription","useCancelSubscription","useReactivateSubscription","useSubscriptionPreview","useAvailablePlans","usePreviewPlanChange","useChangePlan","variables","cn","inputs","twMerge","clsx","DialogContext","useDialogContext","Dialog","open","onOpenChange","internalOpen","setInternalOpen","isOpen","handleOpenChange","DialogTrigger","onClick","props","ref","e","DialogPortal","DialogOverlay","className","DialogContent","handleEscape","jsxs","DialogHeader","DialogFooter","DialogTitle","DialogDescription","CheckoutIframe","forwardRef","src","height","onLoad","useCheckoutSession","enabled","priceId","customer","couponCode","metadata","existingSubscriptionId","setSessionId","sessionUrl","setSessionUrl","loading","setLoading","createSession","session","iframeUrl","getAllowedOrigins","origins","validateOrigin","origin","useIframeMessaging","iframeRef","onMessage","targetOrigin","debug","isConnected","sendMessage","handleMessage","CheckoutModal","collectBillingAddress","theme","locale","onSuccess","onCancel","state","setState","iframeHeight","setIframeHeight","sessionError","handleIframeMessage","_c","_d","showSpinner","showError","Fragment","CheckoutAPI","resolve","modalProps","subscription","createRoot","globalCheckoutAPI","getCheckoutAPI","openCheckout","useCheckout","result","closeCheckout","entitlementKeys","useCheckEntitlement","useHasFeature","useEntitlements","useUsageMetrics","useIsApproachingLimit","threshold","metrics","useFeature","useTrackUsage","quantity","_","useFeatureEntitlements","useFeatureGate","feature","_e","_f","_g","_h","useProducts","alertVariants","cva","Alert","variant","AlertTitle","AlertDescription","badgeVariants","Badge","buttonVariants","Button","size","asChild","Card","CardHeader","CardTitle","CardDescription","CardContent","CardFooter","Checkbox","onCheckedChange","onChange","handleChange","DrawerContext","useDrawerContext","Drawer","DrawerTrigger","DrawerClose","DrawerOverlay","DrawerContent","preventClose","onCloseAttempt","isDragging","setIsDragging","dragY","setDragY","contentRef","startYRef","handleDragStart","clientY","handleDragMove","delta","handleDragEnd","handleOverlayClick","DrawerHeader","DrawerFooter","DrawerTitle","DrawerDescription","Input","type","labelVariants","Label","Progress","value","max","indicatorClassName","percentage","RadioGroupContext","useRadioGroupContext","RadioGroup","defaultValue","onValueChange","name","internalValue","setInternalValue","currentValue","handleValueChange","RadioGroupItem","groupValue","isChecked","ScrollArea","orientation","alwaysShowScrollbar","showScrollbar","setShowScrollbar","scrollbarHeight","setScrollbarHeight","scrollbarTop","setScrollbarTop","viewportRef","handleScroll","viewport","scrollTop","scrollHeight","clientHeight","hasScrollableContent","scrollRatio","thumbHeight","maxScrollTop","scrollProgress","maxThumbTop","thumbTop","resizeObserver","handleScrollbarDrag","scrollbarContainer","containerRect","startY","startScrollTop","onMouseMove","moveEvent","deltaY","containerHeight","scrollDelta","newScrollTop","onMouseUp","ScrollBar","Select","SelectOption","Separator","decorative","SheetContext","useSheetContext","Sheet","SheetTrigger","SheetClose","SheetOverlay","sheetVariants","SheetContent","side","getTransform","SheetHeader","SheetFooter","SheetTitle","SheetDescription","Skeleton","TabsContext","useTabsContext","Tabs","TabsList","TabsTrigger","isSelected","TabsContent","Textarea","PortalIframe","usePortalSession","usePortalMessaging","iframe","iframeSrc","expectedOrigin","Table","TableHeader","TableBody","TableFooter","TableRow","TableHead","TableCell","TableCaption","ErrorBoundary","errorInfo","useCreateCheckout","useConfirmCheckout","PaymentForm","checkoutSession","isProcessing","setIsProcessing","stripe","useStripe","elements","useElements","isExpressCheckoutReady","setIsExpressCheckoutReady","formatAmount","cents","currency","totalAmount","formattedAmount","handleSubmit","submitError","paymentIntent","confirmError","handleExpressCheckout","_event","ExpressCheckoutElement","PaymentElement","DemoPaymentForm","cardNumber","setCardNumber","expiry","setExpiry","cvc","setCvc","formatCardNumber","groups","formatExpiry","digits","BILLINGOS_STRIPE_PUBLISHABLE_KEY","isValidStripeKey","key","isValidClientSecret","secret","PaymentBottomSheet","onClose","stripePromise","setStripePromise","sheetState","setSheetState","isDemoMode","setIsDemoMode","checkoutData","checkoutError","refetchCheckout","validKey","validSecret","loadStripe","handlePaymentSuccess","handlePaymentError","handleClose","handleRetry","appearance","formatInterval","interval","reset","index","Elements","PricingTable","showIntervalToggle","defaultInterval","onSelectPlan","title","description","useCheckoutModal","onPlanChanged","customerProp","selectedInterval","setSelectedInterval","selectedPriceId","setSelectedPriceId","isPaymentOpen","setIsPaymentOpen","finalCustomerEmail","finalCustomerName","showSuccessMessage","setShowSuccessMessage","refetch","products","currentSubscription","hasYearlyPricing","p","price","getAllFeatures","featureMap","product","featureRows","featureId","featureRow","productIndex","f","limit","row","formatPrice","getPriceForInterval","handleSelectPlan","oldData","updatedData","isHighlighted","isCurrentPlan","hasSubscription","buttonText","currentPrice","currentPriceAmount","PricingCard","selectedPrice","buttonState","yearlySavings","monthlyPrice","yearlyPrice","monthlyTotal","yearlyCost","savings","formatFeature","handleClick","CustomerPortal","mode","defaultTab","onSubscriptionUpdate","onSubscriptionCancel","onPaymentMethodAdd","onPaymentMethodUpdate","showPricingTable","setShowPricingTable","portalCustomer","setPortalCustomer","isOpenOrPage","portalContent","mainPortal","portalKeys","usePortalData","useUpdatePortalSubscription","args","useCancelPortalSubscription","useReactivatePortalSubscription","useSetupIntent","useAddPaymentMethod","useRemovePaymentMethod","useSetDefaultPaymentMethod","useRetryInvoice","useUpdateCustomerBilling","formatNumber","num","getProgressColor","UsageBar","usage","unit","consumed","resetDate","formattedConsumed","formattedLimit","progressColor","CheckIcon","FeatureList","features","booleanFeatures","AlertTriangleIcon","getTitle","getVariant","WarningBanner","actionLabel","onAction","getCentsInDollarString","showCents","pretty","dollars","precision","formatCurrencyAndAmount","minimumFractionDigits","notation","maximumFractionDigits","convertCentsToFloat","convertFloatToCents","amount","formatCurrencyCompact","formatCurrencyWhole","getCurrencySymbol","symbolPart","part","formatPriceRange","minCents","maxCents","min","isZeroAmount","isNegativeAmount","calculatePercentage","addAmounts","amounts","sum","Money","intervalCount","getStatusBadge","cancelAtPeriodEnd","NoSubscription","onBrowsePlans","SubscriptionTabSkeleton","SubscriptionTab","onChangePlan","onCancelSubscription","onReactivate","onAddPaymentMethod","currentPeriodEnd","trialEnd","formattedPrice","nextBillingDate","usageFeatures","isTrialEndingSoon","DownloadIcon","InvoiceCard","invoice","onRetry","onDownload","isRetrying","formattedDate","NoInvoices","InvoicesTabSkeleton","i","InvoicesTab","invoices","onRetryInvoice","onDownloadInvoice","retryingInvoiceId","getCardIcon","brand","formatCardBrand","PaymentMethodCard","paymentMethod","onSetDefault","onRemove","isSettingDefault","isRemoving","card","isDefault","expiryDate","PlusIcon","NoPaymentMethods","onAdd","PaymentMethodsTabSkeleton","PaymentMethodsTab","paymentMethods","settingDefaultId","removingId","sortedMethods","a","b","method","COUNTRIES","z","SettingsTabSkeleton","SettingsTab","onSave","isSaving","register","errors","isDirty","useForm","onSubmit","billingAddress","country","ProrationPreview","preview","current_plan","new_plan","proration","change_type","next_billing_date","notes","isUpgrade","note","idx","PlanCard","plan","isCurrent","onSelect","disabled","isDowngrade","ChangePlanModal","selectedPlan","setSelectedPlan","setPreview","showConfirmation","setShowConfirmation","availablePlans","isLoadingPlans","plansError","previewMutation","changePlanMutation","previewData","handleConfirm","allPlans","currentPlanId","restriction","CANCELLATION_REASONS","CancelSubscriptionModal","periodEndDate","onConfirm","isCanceling","selectedReasons","setSelectedReasons","feedback","setFeedback","cancelTiming","setCancelTiming","formattedEndDate","toggleReason","reason","prev","r","v","cardElementOptions","isSubmitting","setIsSubmitting","setAsDefault","setSetAsDefault","cardElement","CardElement","setupIntent","setupError","checked","LockIcon","LoadingSkeleton","getStripePromise","publishableKey","AddPaymentMethodModal","stripePublishableKey","handleCancel","handleSuccess","showForm","BannerNudge","trigger","onUpgrade","onDismiss","isUrgent","ToastNudge","ModalNudge","highlight","storeDismissal","dismissalKey","UpgradeNudge","style","autoDismiss","isVisible","setIsVisible","timer","handleDismiss","handleKeyDown","handleUpgrade","useUsageCheck","refetchInterval","FeatureGate","fallback","onAccessDenied","onQuotaExceeded","showUsageBadge","hasAccess","isError","remaining","FeatureGateLoading","FeatureGateDenied","UsageBadge","colorClass","UsageDisplay","showProgress","showResetTimer","metric","UsageMetricCard","CompactUsageDisplay","getColor","UpgradePrompt","isQuotaExceeded","onUpgradeClick","productsData","defaultDescription","handleUpgradeClick","pricingTable","CompactUpgradePrompt","formatDate","date","formatStr","dateObj","parseISO","format","formatRelativeTime","baseDate","formatDistance","formatRelativeDate","formatRelative","isPast","isBefore","isFuture","isAfter","parseDate","DateUtils"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/styles/inject.ts","../src/client/errors.ts","../src/utils/urls.ts","../src/client/index.ts","../src/hooks/useSessionToken.ts","../src/hooks/useSubscription.ts","../src/providers/BillingOSProvider.tsx","../src/hooks/useCheckout.ts","../src/checkout.ts","../src/components/CheckoutModal/CheckoutModal.tsx","../src/components/ui/dialog.tsx","../src/utils/cn.ts","../src/components/CheckoutModal/CheckoutIframe.tsx","../src/components/CheckoutModal/hooks/useCheckoutSession.ts","../src/components/CheckoutModal/hooks/useIframeMessaging.ts","../src/components/CheckoutModal/utils/security.ts","../src/hooks/useEntitlements.ts","../src/hooks/useFeature.ts","../src/hooks/useProducts.ts","../src/components/ui/alert.tsx","../src/components/ui/badge.tsx","../src/components/ui/button.tsx","../src/components/ui/card.tsx","../src/components/ui/checkbox.tsx","../src/components/ui/drawer.tsx","../src/components/ui/input.tsx","../src/components/ui/label.tsx","../src/components/ui/progress.tsx","../src/components/ui/radio-group.tsx","../src/components/ui/scroll-area.tsx","../src/components/ui/select.tsx","../src/components/ui/separator.tsx","../src/components/ui/sheet.tsx","../src/components/ui/skeleton.tsx","../src/components/ui/switch.tsx","../src/components/ui/tabs.tsx","../src/components/ui/textarea.tsx","../src/components/CustomerPortal/CustomerPortal.tsx","../src/components/CustomerPortal/PortalIframe.tsx","../src/components/CustomerPortal/hooks/usePortalSession.ts","../src/components/CustomerPortal/hooks/usePortalMessaging.ts","../src/components/PricingTable/PricingTable.tsx","../src/components/PricingTable/hooks/useProducts.ts","../src/components/PricingTable/PricingCard.tsx","../src/components/PaymentBottomSheet/PaymentBottomSheet.tsx","../src/components/ErrorBoundary.tsx","../src/components/PaymentBottomSheet/hooks/useCheckout.ts","../src/components/PaymentBottomSheet/PaymentForm.tsx","../src/components/PaymentBottomSheet/DemoPaymentForm.tsx","../src/config/stripe.ts","../src/components/CustomerPortal/hooks/usePortalData.ts","../src/components/CustomerPortal/components/UsageBar.tsx","../src/components/CustomerPortal/components/FeatureList.tsx","../src/components/CustomerPortal/components/WarningBanner.tsx","../src/utils/money.ts","../src/components/CustomerPortal/tabs/SubscriptionTab.tsx","../src/components/CustomerPortal/components/InvoiceCard.tsx","../src/components/CustomerPortal/tabs/InvoicesTab.tsx","../src/components/CustomerPortal/components/PaymentMethodCard.tsx","../src/components/CustomerPortal/tabs/PaymentMethodsTab.tsx","../src/components/CustomerPortal/tabs/SettingsTab.tsx","../src/components/CustomerPortal/modals/ChangePlanModal.tsx","../src/components/CustomerPortal/components/ProrationPreview.tsx","../src/components/CustomerPortal/modals/CancelSubscriptionModal.tsx","../src/components/CustomerPortal/modals/AddPaymentMethodModal.tsx","../src/components/UpgradeNudge/UpgradeNudge.tsx","../src/components/UpgradeNudge/BannerNudge.tsx","../src/components/UpgradeNudge/ToastNudge.tsx","../src/components/UpgradeNudge/ModalNudge.tsx","../src/components/UpgradeNudge/hooks/useUsageCheck.ts","../src/components/FeatureGate/FeatureGate.tsx","../src/components/UsageDisplay/UsageDisplay.tsx","../src/components/UpgradePrompt/UpgradePrompt.tsx","../src/utils/date.ts"],"sourcesContent":["// BillingOS SDK - Main Entry Point\n\n// Import global styles (injected at runtime; CSS string is substituted at build time)\nimport './styles/inject'\n\n// Client\nexport * from './client'\n\n// Hooks\nexport * from './hooks'\n\n// Components\nexport * from './components'\n\n// Providers\nexport * from './providers'\n\n// Utils\nexport * from './utils'\n\n// Checkout API\nexport { openCheckout, getCheckoutAPI, CheckoutAPI } from './checkout'\nexport type { CheckoutOpenOptions } from './checkout'\n\n// Create a global billingOS object for imperative API\nimport { BillingOSClient } from './client'\nimport { getCheckoutAPI } from './checkout'\n\ndeclare global {\n interface Window {\n billingOS?: {\n checkout: {\n open: (options: import('./checkout').CheckoutOpenOptions) => Promise<{\n success: boolean\n subscription?: import('./client/types').Subscription\n error?: Error\n }>\n }\n client?: BillingOSClient\n }\n }\n}\n\n// Initialize global billingOS object if in browser\nif (typeof window !== 'undefined') {\n window.billingOS = {\n checkout: {\n open: async (options) => {\n const api = getCheckoutAPI()\n return api.open(options)\n }\n }\n }\n}\n","\"use client\";\n// Auto-injected by tsup.config.ts — do not import __BILLINGOS_CSS__ directly.\n// This constant is replaced at build time with the processed Tailwind CSS string.\ndeclare const __BILLINGOS_CSS__: string\n;(function () {\n if (typeof document === 'undefined') return\n var id = 'billingos-styles'\n if (document.getElementById(id)) return\n var s = document.createElement('style')\n s.id = id\n s.textContent = __BILLINGOS_CSS__\n document.head.appendChild(s)\n})()\n","/**\n * Base error class for all BillingOS SDK errors\n */\nexport class BillingOSError extends Error {\n constructor(\n message: string,\n public status?: number,\n public data?: unknown\n ) {\n super(message)\n this.name = 'BillingOSError'\n Object.setPrototypeOf(this, BillingOSError.prototype)\n }\n}\n\n/**\n * Thrown when the API request fails due to authentication issues (401)\n */\nexport class UnauthorizedError extends BillingOSError {\n constructor(message = 'Unauthorized: Invalid or missing API key', data?: unknown) {\n super(message, 401, data)\n this.name = 'UnauthorizedError'\n Object.setPrototypeOf(this, UnauthorizedError.prototype)\n }\n}\n\n/**\n * Thrown when the requested resource is not found (404)\n */\nexport class NotFoundError extends BillingOSError {\n constructor(message = 'Resource not found', data?: unknown) {\n super(message, 404, data)\n this.name = 'NotFoundError'\n Object.setPrototypeOf(this, NotFoundError.prototype)\n }\n}\n\n/**\n * Thrown when the request fails validation (400)\n */\nexport class ValidationError extends BillingOSError {\n constructor(message = 'Validation failed', data?: unknown) {\n super(message, 400, data)\n this.name = 'ValidationError'\n Object.setPrototypeOf(this, ValidationError.prototype)\n }\n}\n\n/**\n * Thrown when rate limit is exceeded (429)\n */\nexport class RateLimitError extends BillingOSError {\n constructor(message = 'Too many requests', data?: unknown) {\n super(message, 429, data)\n this.name = 'RateLimitError'\n Object.setPrototypeOf(this, RateLimitError.prototype)\n }\n}\n\n/**\n * Thrown when the server returns a 500 error\n */\nexport class ServerError extends BillingOSError {\n constructor(message = 'Internal server error', data?: unknown) {\n super(message, 500, data)\n this.name = 'ServerError'\n Object.setPrototypeOf(this, ServerError.prototype)\n }\n}\n\n/**\n * Thrown when the network request fails\n */\nexport class NetworkError extends BillingOSError {\n constructor(message = 'Network request failed', originalError?: unknown) {\n super(message, undefined, originalError)\n this.name = 'NetworkError'\n Object.setPrototypeOf(this, NetworkError.prototype)\n }\n}\n\n/**\n * Type guard to check if an error is a validation error\n */\nexport function isValidationError(error: unknown): error is ValidationError {\n return error instanceof ValidationError\n}\n\n/**\n * Type guard to check if an error is an unauthorized error\n */\nexport function isUnauthorizedError(error: unknown): error is UnauthorizedError {\n return error instanceof UnauthorizedError\n}\n\n/**\n * Type guard to check if an error is a not found error\n */\nexport function isNotFoundError(error: unknown): error is NotFoundError {\n return error instanceof NotFoundError\n}\n\n/**\n * Type guard to check if an error is a rate limit error\n */\nexport function isRateLimitError(error: unknown): error is RateLimitError {\n return error instanceof RateLimitError\n}\n","/**\n * BillingOS production URLs.\n * These are the defaults — SDK users don't need to configure anything.\n * The SDK auto-detects the correct API URL from the session token prefix.\n */\nexport const BILLINGOS_API_URL = 'https://api.billingos.dev'\nexport const BILLINGOS_SANDBOX_API_URL = 'https://sandbox-api.billingos.dev'\nexport const BILLINGOS_APP_URL = 'https://app.billingos.dev'\n\n/**\n * Detect environment from session token prefix.\n */\nexport function detectEnvironmentFromToken(token: string): 'test' | 'live' {\n if (token.startsWith('bos_session_test_')) return 'test'\n return 'live' // bos_session_live_ or legacy bos_session_ → production\n}\n\n/**\n * Resolve the BillingOS API URL from a session token prefix.\n * This is the primary resolution method — no configuration needed.\n */\nexport function resolveApiUrlFromToken(token: string): string {\n return detectEnvironmentFromToken(token) === 'test'\n ? BILLINGOS_SANDBOX_API_URL\n : BILLINGOS_API_URL\n}\n\n/**\n * Resolve the BillingOS app URL.\n * The app URL is the same for both test and live environments.\n */\nexport function resolveAppUrlFromToken(_token: string): string {\n return BILLINGOS_APP_URL\n}\n\n/**\n * @deprecated Use resolveApiUrlFromToken() instead. The SDK now auto-detects\n * the API URL from the session token prefix (bos_session_test_ / bos_session_live_).\n */\nexport function resolveApiUrl(propUrl?: string): string {\n const url =\n propUrl ||\n (typeof process !== 'undefined'\n ? process.env?.NEXT_PUBLIC_BILLINGOS_API_URL\n : undefined) ||\n BILLINGOS_API_URL\n\n if (propUrl) {\n console.warn(\n '[BillingOS] The apiUrl prop is deprecated. ' +\n 'The SDK now auto-detects the environment from the session token prefix.'\n )\n }\n\n return url.replace(/\\/$/, '')\n}\n\n/**\n * @deprecated Use resolveAppUrlFromToken() instead. The app URL is now\n * always https://app.billingos.dev for both test and live environments.\n */\nexport function resolveAppUrl(propUrl?: string): string {\n const url =\n propUrl ||\n (typeof process !== 'undefined'\n ? process.env?.NEXT_PUBLIC_BILLINGOS_APP_URL\n : undefined) ||\n BILLINGOS_APP_URL\n\n if (propUrl) {\n console.warn(\n '[BillingOS] The appUrl prop is deprecated. ' +\n 'The app URL is now always https://app.billingos.dev.'\n )\n }\n\n return url.replace(/\\/$/, '')\n}\n","import {\n BillingOSError,\n UnauthorizedError,\n NotFoundError,\n ValidationError,\n RateLimitError,\n ServerError,\n NetworkError,\n} from './errors'\nimport { resolveApiUrlFromToken } from '../utils/urls'\nimport type {\n Customer,\n CreateCustomerInput,\n UpdateCustomerInput,\n Subscription,\n CreateSubscriptionInput,\n UpdateSubscriptionInput,\n SubscriptionPreview,\n Entitlement,\n CheckEntitlementInput,\n UsageEvent,\n UsageMetrics,\n Invoice,\n PaymentMethod,\n PaginatedResponse,\n APIErrorResponse,\n // Portal types\n CustomerPortalData,\n PortalUpdateSubscriptionInput,\n PortalUpdateSubscriptionResponse,\n PortalCancelSubscriptionInput,\n PortalCancelSubscriptionResponse,\n AddPaymentMethodInput,\n AddPaymentMethodResponse,\n SetupIntentResponse,\n RetryInvoiceResponse,\n UpdateCustomerBillingInput,\n CustomerBillingInfo,\n AvailablePlansResponse,\n PreviewChangeInput,\n PreviewChangeResponse,\n ChangePlanInput,\n ChangePlanResponse,\n // Checkout types\n CreateCheckoutInput,\n CreateCheckoutResponse,\n ConfirmCheckoutResponse,\n // Checkout Modal types\n CreateCheckoutSessionInput,\n CreateCheckoutSessionResponse,\n CheckoutSessionDetails,\n // Pricing table types\n GetProductsResponse,\n // Upgrade nudge types\n UsageCheckResponse,\n} from './types'\n\nexport * from './types'\nexport * from './errors'\n\n/**\n * Configuration options for the BillingOS client\n */\nexport interface BillingOSClientOptions {\n /**\n * Base URL for the API (defaults to production)\n */\n baseUrl?: string\n\n /**\n * Environment (production or sandbox)\n */\n environment?: 'production' | 'sandbox'\n\n /**\n * API version to use\n */\n version?: string\n\n /**\n * Custom headers to include in all requests\n */\n headers?: Record<string, string>\n\n /**\n * Timeout for requests in milliseconds\n */\n timeout?: number\n}\n\n/**\n * Main BillingOS API client\n */\nexport class BillingOSClient {\n private sessionToken: string\n private baseUrl: string\n private headers: Record<string, string>\n private timeout: number\n\n constructor(sessionToken: string, options: BillingOSClientOptions = {}) {\n if (!sessionToken) {\n throw new Error('Session token is required')\n }\n\n this.sessionToken = sessionToken\n this.timeout = options.timeout || 30000\n\n // Resolve the API base URL.\n // Priority: explicit baseUrl > env var override > auto-detect from token prefix\n if (options.baseUrl) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n } else {\n const envUrl = typeof process !== 'undefined'\n ? process.env?.NEXT_PUBLIC_BILLINGOS_API_URL\n : undefined\n this.baseUrl = envUrl\n ? envUrl.replace(/\\/$/, '')\n : resolveApiUrlFromToken(sessionToken)\n }\n\n // Setup default headers\n this.headers = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.sessionToken}`,\n 'X-BillingOS-Version': options.version || '2026-01-01',\n ...options.headers,\n }\n }\n\n /**\n * Internal method to make HTTP requests\n */\n private async request<T>(\n path: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n ...this.headers,\n ...options.headers,\n },\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n // Handle 204 No Content\n if (response.status === 204) {\n return undefined as T\n }\n\n // Parse response\n const contentType = response.headers.get('content-type')\n const isJson = contentType?.includes('application/json')\n const data = isJson ? await response.json() : await response.text()\n\n // Handle errors\n if (!response.ok) {\n const errorData = isJson ? (data as APIErrorResponse) : { error: { message: data } }\n const errorMessage = errorData.error?.message || `Request failed with status ${response.status}`\n\n switch (response.status) {\n case 400:\n throw new ValidationError(errorMessage, errorData)\n case 401:\n throw new UnauthorizedError(errorMessage, errorData)\n case 404:\n throw new NotFoundError(errorMessage, errorData)\n case 429:\n throw new RateLimitError(errorMessage, errorData)\n case 500:\n case 502:\n case 503:\n case 504:\n throw new ServerError(errorMessage, errorData)\n default:\n throw new BillingOSError(errorMessage, response.status, errorData)\n }\n }\n\n return data as T\n } catch (error) {\n clearTimeout(timeoutId)\n\n if (error instanceof BillingOSError) {\n throw error\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new NetworkError('Request timeout')\n }\n\n throw new NetworkError('Network request failed', error)\n }\n }\n\n /**\n * GET request helper\n */\n get<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'GET' })\n }\n\n /**\n * POST request helper\n */\n post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, {\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n })\n }\n\n /**\n * PATCH request helper\n */\n patch<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, {\n method: 'PATCH',\n body: body ? JSON.stringify(body) : undefined,\n })\n }\n\n /**\n * DELETE request helper\n */\n delete<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'DELETE' })\n }\n\n // =============================================================================\n // CUSTOMERS API\n // =============================================================================\n\n /**\n * Create a new customer\n */\n async createCustomer(input: CreateCustomerInput): Promise<Customer> {\n return this.post<Customer>('/customers', input)\n }\n\n /**\n * Get a customer by ID\n */\n async getCustomer(id: string): Promise<Customer> {\n return this.get<Customer>(`/customers/${id}`)\n }\n\n /**\n * List customers (paginated)\n */\n async listCustomers(params?: {\n page?: number\n page_size?: number\n }): Promise<PaginatedResponse<Customer>> {\n const query = new URLSearchParams()\n if (params?.page) query.set('page', params.page.toString())\n if (params?.page_size) query.set('page_size', params.page_size.toString())\n\n const queryString = query.toString()\n return this.get<PaginatedResponse<Customer>>(\n `/customers${queryString ? `?${queryString}` : ''}`\n )\n }\n\n /**\n * Update a customer\n */\n async updateCustomer(id: string, input: UpdateCustomerInput): Promise<Customer> {\n return this.patch<Customer>(`/customers/${id}`, input)\n }\n\n /**\n * Delete a customer\n */\n async deleteCustomer(id: string): Promise<void> {\n return this.delete<void>(`/customers/${id}`)\n }\n\n // =============================================================================\n // SUBSCRIPTIONS API\n // =============================================================================\n\n /**\n * Create a new subscription\n */\n async createSubscription(input: CreateSubscriptionInput): Promise<Subscription> {\n return this.post<Subscription>('/subscriptions', input)\n }\n\n /**\n * Get a subscription by ID\n */\n async getSubscription(id: string): Promise<Subscription> {\n return this.get<Subscription>(`/subscriptions/${id}`)\n }\n\n /**\n * List subscriptions (paginated)\n */\n async listSubscriptions(params?: {\n customer_id?: string\n page?: number\n page_size?: number\n }): Promise<PaginatedResponse<Subscription>> {\n const query = new URLSearchParams()\n if (params?.customer_id) query.set('customer_id', params.customer_id)\n if (params?.page) query.set('page', params.page.toString())\n if (params?.page_size) query.set('page_size', params.page_size.toString())\n\n const queryString = query.toString()\n return this.get<PaginatedResponse<Subscription>>(\n `/subscriptions${queryString ? `?${queryString}` : ''}`\n )\n }\n\n /**\n * Update a subscription\n */\n async updateSubscription(\n id: string,\n input: UpdateSubscriptionInput\n ): Promise<Subscription> {\n return this.patch<Subscription>(`/subscriptions/${id}`, input)\n }\n\n /**\n * Cancel a subscription\n */\n async cancelSubscription(id: string, immediately = false): Promise<Subscription> {\n return this.post<Subscription>(`/subscriptions/${id}/cancel`, { immediately })\n }\n\n /**\n * Reactivate a canceled subscription\n */\n async reactivateSubscription(id: string): Promise<Subscription> {\n return this.post<Subscription>(`/subscriptions/${id}/reactivate`)\n }\n\n /**\n * Preview subscription changes\n */\n async previewSubscription(\n id: string,\n input: UpdateSubscriptionInput\n ): Promise<SubscriptionPreview> {\n return this.post<SubscriptionPreview>(`/subscriptions/${id}/preview`, input)\n }\n\n /**\n * Get available plans for upgrade/downgrade\n */\n async getAvailablePlans(subscriptionId: string): Promise<AvailablePlansResponse> {\n return this.get<AvailablePlansResponse>(`/subscriptions/${subscriptionId}/available-plans`)\n }\n\n /**\n * Preview a plan change (upgrade/downgrade) with proration details\n */\n async previewPlanChange(\n subscriptionId: string,\n input: PreviewChangeInput\n ): Promise<PreviewChangeResponse> {\n return this.post<PreviewChangeResponse>(`/subscriptions/${subscriptionId}/preview-change`, input)\n }\n\n /**\n * Execute a plan change (upgrade/downgrade)\n */\n async changePlan(\n subscriptionId: string,\n input: ChangePlanInput\n ): Promise<ChangePlanResponse> {\n return this.post<ChangePlanResponse>(`/subscriptions/${subscriptionId}/change-plan`, input)\n }\n\n // =============================================================================\n // ENTITLEMENTS API\n // =============================================================================\n\n /**\n * Check if a customer has access to a feature\n * Customer ID is resolved server-side from session token\n */\n async checkEntitlement(input: CheckEntitlementInput): Promise<Entitlement> {\n return this.get<Entitlement>(`/v1/features/check?feature_key=${encodeURIComponent(input.feature_key)}`)\n }\n\n /**\n * List all entitlements for a customer\n * Customer ID is resolved server-side from session token\n */\n async listEntitlements(_customerId?: string): Promise<Entitlement[]> {\n const response = await this.get<{ entitlements: Entitlement[] }>('/v1/features/entitlements')\n return response.entitlements\n }\n\n // =============================================================================\n // USAGE TRACKING API\n // =============================================================================\n\n /**\n * Track a usage event\n * Customer ID is resolved server-side from session token\n */\n async trackUsage(event: UsageEvent): Promise<void> {\n return this.post<void>('/v1/features/track-usage', {\n feature_key: event.feature_key,\n quantity: event.quantity,\n timestamp: event.timestamp,\n idempotency_key: event.idempotency_key,\n metadata: event.metadata,\n })\n }\n\n /**\n * Get usage metrics for a customer and feature\n * Customer ID is resolved server-side from session token\n */\n async getUsageMetrics(_customerId?: string, featureKey?: string): Promise<UsageMetrics> {\n const query = featureKey ? `?feature_key=${encodeURIComponent(featureKey)}` : ''\n const response = await this.get<{ metrics: UsageMetrics[] }>(`/v1/features/usage-metrics${query}`)\n return response.metrics?.[0] ?? { feature_key: featureKey || '', current_usage: 0, period_start: '', period_end: '' }\n }\n\n // =============================================================================\n // INVOICES API\n // =============================================================================\n\n /**\n * Get an invoice by ID\n */\n async getInvoice(id: string): Promise<Invoice> {\n return this.get<Invoice>(`/invoices/${id}`)\n }\n\n /**\n * List invoices for a customer\n */\n async listInvoices(params?: {\n customer_id?: string\n page?: number\n page_size?: number\n }): Promise<PaginatedResponse<Invoice>> {\n const query = new URLSearchParams()\n if (params?.customer_id) query.set('customer_id', params.customer_id)\n if (params?.page) query.set('page', params.page.toString())\n if (params?.page_size) query.set('page_size', params.page_size.toString())\n\n const queryString = query.toString()\n return this.get<PaginatedResponse<Invoice>>(\n `/invoices${queryString ? `?${queryString}` : ''}`\n )\n }\n\n // =============================================================================\n // PAYMENT METHODS API\n // =============================================================================\n\n /**\n * List payment methods for a customer\n */\n async listPaymentMethods(customerId: string): Promise<PaymentMethod[]> {\n return this.get<PaymentMethod[]>(`/payment-methods?customer_id=${customerId}`)\n }\n\n /**\n * Remove a payment method\n */\n async removePaymentMethod(id: string): Promise<void> {\n return this.delete<void>(`/payment-methods/${id}`)\n }\n\n /**\n * Set default payment method\n */\n async setDefaultPaymentMethod(id: string): Promise<void> {\n return this.post<void>(`/payment-methods/${id}/set-default`)\n }\n\n // =============================================================================\n // CUSTOMER PORTAL API\n // =============================================================================\n\n /**\n * Get all portal data for the current customer\n */\n async getCustomerPortal(): Promise<CustomerPortalData> {\n return this.get<CustomerPortalData>('/sdk/customer/portal')\n }\n\n /**\n * Update subscription (upgrade/downgrade)\n */\n async updatePortalSubscription(\n subscriptionId: string,\n input: PortalUpdateSubscriptionInput\n ): Promise<PortalUpdateSubscriptionResponse> {\n return this.post<PortalUpdateSubscriptionResponse>(\n `/sdk/subscriptions/${subscriptionId}/update`,\n input\n )\n }\n\n /**\n * Cancel subscription with feedback\n */\n async cancelPortalSubscription(\n subscriptionId: string,\n input: PortalCancelSubscriptionInput\n ): Promise<PortalCancelSubscriptionResponse> {\n return this.post<PortalCancelSubscriptionResponse>(\n `/sdk/subscriptions/${subscriptionId}/cancel`,\n input\n )\n }\n\n /**\n * Reactivate a canceled subscription\n */\n async reactivatePortalSubscription(subscriptionId: string): Promise<void> {\n return this.post<void>(`/sdk/subscriptions/${subscriptionId}/reactivate`)\n }\n\n /**\n * Add a payment method\n */\n async addPaymentMethod(input: AddPaymentMethodInput): Promise<AddPaymentMethodResponse> {\n return this.post<AddPaymentMethodResponse>('/sdk/payment-methods', input)\n }\n\n /**\n * Get setup intent for adding a new card\n */\n async getSetupIntent(): Promise<SetupIntentResponse> {\n return this.post<SetupIntentResponse>('/sdk/payment-methods/setup-intent')\n }\n\n /**\n * Retry a failed invoice\n */\n async retryInvoice(\n invoiceId: string,\n paymentMethodId?: string\n ): Promise<RetryInvoiceResponse> {\n return this.post<RetryInvoiceResponse>(`/sdk/invoices/${invoiceId}/retry`, {\n paymentMethodId,\n })\n }\n\n /**\n * Update customer billing information\n */\n async updateCustomerBilling(input: UpdateCustomerBillingInput): Promise<CustomerBillingInfo> {\n return this.patch<CustomerBillingInfo>('/sdk/customer/billing', input)\n }\n\n // =============================================================================\n // CHECKOUT API (Payment Bottom Sheet)\n // =============================================================================\n\n /**\n * Create a checkout session for purchasing a subscription\n */\n async createCheckout(input: CreateCheckoutInput): Promise<CreateCheckoutResponse> {\n return this.post<CreateCheckoutResponse>('/v1/checkout/create', input)\n }\n\n /**\n * Confirm a checkout after payment is processed\n */\n async confirmCheckout(\n clientSecret: string,\n paymentMethodId: string\n ): Promise<ConfirmCheckoutResponse> {\n return this.post<ConfirmCheckoutResponse>(\n `/v1/checkout/${clientSecret}/confirm`,\n { paymentMethodId }\n )\n }\n\n // =============================================================================\n // CHECKOUT MODAL API (Iframe-based checkout)\n // =============================================================================\n\n /**\n * Checkout API methods for iframe-based checkout modal\n */\n public checkout = {\n /**\n * Create a checkout session for iframe-based checkout\n */\n createSession: async (input: CreateCheckoutSessionInput): Promise<CreateCheckoutSessionResponse> => {\n // Log what we're sending\n console.log('[SDK Client] Creating checkout session with:', {\n priceId: input.priceId,\n customer: input.customer,\n hasEmail: !!input.customer?.email,\n hasName: !!input.customer?.name,\n })\n\n const response = await this.post<CreateCheckoutSessionResponse>('/v1/checkout/create', input)\n\n console.log('[SDK Client] Checkout session created:', {\n sessionId: response.id,\n status: response.status,\n })\n\n return response\n },\n\n /**\n * Get checkout session details\n */\n getSession: async (sessionId: string): Promise<CheckoutSessionDetails> => {\n return this.get<CheckoutSessionDetails>(`/v1/checkout/${sessionId}/status`)\n },\n\n /**\n * Cancel a checkout session (not implemented in backend yet)\n */\n cancelSession: async (_sessionId: string): Promise<void> => {\n // TODO: Backend doesn't have this endpoint yet\n throw new Error('Cancel session not implemented yet')\n },\n\n /**\n * Confirm payment for a checkout session\n */\n confirmPayment: async (clientSecret: string, paymentMethodId: string): Promise<ConfirmCheckoutResponse> => {\n return this.post<ConfirmCheckoutResponse>(\n `/v1/checkout/${clientSecret}/confirm`,\n { paymentMethodId }\n )\n },\n\n /**\n * Apply coupon to a checkout session (not implemented in backend yet)\n */\n applyCoupon: async (_sessionId: string, _couponCode: string): Promise<CheckoutSessionDetails> => {\n // TODO: Backend doesn't have this endpoint yet\n throw new Error('Apply coupon not implemented yet')\n }\n }\n\n // =============================================================================\n // PORTAL API (Iframe-based customer portal)\n // =============================================================================\n\n /**\n * Portal API methods for iframe-based customer portal\n */\n public portal = {\n /**\n * Create a portal session for customer self-service\n */\n createSession: async (input?: { customerId?: string; metadata?: Record<string, any> }): Promise<{ id: string; expiresAt: string }> => {\n console.log('[SDK Client] Creating portal session')\n\n const response = await this.post<{ id: string; customerId: string; organizationId: string; expiresAt: string }>(\n '/v1/portal/create',\n input || {}\n )\n\n console.log('[SDK Client] Portal session created:', {\n sessionId: response.id,\n customerId: response.customerId,\n expiresAt: response.expiresAt,\n })\n\n return {\n id: response.id,\n expiresAt: response.expiresAt,\n }\n },\n\n /**\n * Get portal session status\n */\n getSessionStatus: async (sessionId: string): Promise<{ isValid: boolean; expiresAt?: string }> => {\n return this.get<{ sessionId: string; isValid: boolean; expiresAt?: string; customerId?: string }>(\n `/v1/portal/${sessionId}/status`\n )\n },\n\n /**\n * Get portal data for a session\n */\n getPortalData: async (sessionId: string): Promise<any> => {\n return this.get(`/v1/portal/${sessionId}/data`)\n },\n }\n\n // =============================================================================\n // PRICING TABLE API\n // =============================================================================\n\n /**\n * Get all products for the pricing table\n * @param planIds - Optional array of plan IDs to filter\n */\n async getProducts(planIds?: string[]): Promise<GetProductsResponse> {\n const query = new URLSearchParams()\n if (planIds && planIds.length > 0) {\n query.set('planIds', planIds.join(','))\n }\n const queryString = query.toString()\n return this.get<GetProductsResponse>(\n `/v1/products${queryString ? `?${queryString}` : ''}`\n )\n }\n\n // =============================================================================\n // UPGRADE NUDGE API\n // =============================================================================\n\n /**\n * Check usage and get nudge trigger if applicable\n * Uses usage-metrics endpoint and computes nudge client-side\n */\n async checkUsage(): Promise<UsageCheckResponse> {\n const response = await this.get<{ metrics: any[] }>('/v1/features/usage-metrics')\n const metrics = response.metrics || []\n\n // Check if any feature is near its limit (80% threshold)\n const atRisk = metrics.find((m: any) => {\n if (!m.limit || m.limit === 0) return false\n return (m.consumed / m.limit) * 100 >= 80\n })\n\n if (!atRisk) {\n return { shouldShowNudge: false }\n }\n\n return {\n shouldShowNudge: true,\n trigger: {\n type: 'usage_threshold',\n feature: atRisk.feature_key,\n threshold: 80,\n actual: Math.round((atRisk.consumed / atRisk.limit) * 100 * 10) / 10,\n message: {\n title: 'Approaching usage limit',\n body: `You've used ${Math.round((atRisk.consumed / atRisk.limit) * 100)}% of your ${atRisk.feature_title || atRisk.feature_key} limit.`,\n cta: 'Upgrade plan',\n },\n suggestedPlan: { id: '', priceId: '', name: '', price: { amount: 0, currency: 'usd', interval: 'month' }, highlights: [] },\n },\n }\n }\n}\n\n/**\n * Factory function to create a BillingOS client instance\n */\nexport function createBillingOSClient(\n sessionToken: string,\n options?: BillingOSClientOptions\n): BillingOSClient {\n return new BillingOSClient(sessionToken, options)\n}\n","\"use client\";\n/**\n * Hook for managing session tokens with auto-fetch and auto-refresh\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\n\nexport interface SessionTokenData {\n sessionToken: string;\n expiresAt: string; // ISO date string\n}\n\nexport interface UseSessionTokenOptions {\n /** URL to fetch session token from (e.g., /api/billingos-session) */\n tokenUrl?: string;\n\n /** Manually provided session token */\n token?: string;\n\n /** How many seconds before expiry to refresh (default: 300 = 5 minutes) */\n refreshBeforeExpiry?: number;\n\n /** Enable auto-refresh (default: true) */\n autoRefresh?: boolean;\n\n /** Callback when token is refreshed */\n onTokenRefresh?: (token: string) => void;\n\n /** Callback when token fetch fails */\n onError?: (error: Error) => void;\n}\n\nexport interface UseSessionTokenReturn {\n /** Current session token */\n token: string | null;\n\n /** When the token expires */\n expiresAt: Date | null;\n\n /** Whether the token is currently being fetched */\n isLoading: boolean;\n\n /** Any error that occurred */\n error: Error | null;\n\n /** Manually refresh the token */\n refresh: () => Promise<void>;\n\n /** Whether the token is valid (not expired) */\n isValid: boolean;\n}\n\n/**\n * Hook to manage session tokens with automatic fetching and refreshing\n *\n * @example\n * // Auto-fetch from endpoint\n * const { token, isLoading } = useSessionToken({\n * tokenUrl: '/api/billingos-session',\n * });\n *\n * @example\n * // Manual token\n * const { token } = useSessionToken({\n * token: 'bos_session_abc123...',\n * });\n */\nexport function useSessionToken(options: UseSessionTokenOptions = {}): UseSessionTokenReturn {\n const {\n tokenUrl,\n token: manualToken,\n refreshBeforeExpiry = 300, // 5 minutes\n autoRefresh = true,\n onTokenRefresh,\n onError,\n } = options;\n\n const [token, setToken] = useState<string | null>(manualToken || null);\n const [expiresAt, setExpiresAt] = useState<Date | null>(null);\n // Start as loading if we need to fetch from tokenUrl\n const [isLoading, setIsLoading] = useState<boolean>(Boolean(tokenUrl && !manualToken));\n const [error, setError] = useState<Error | null>(null);\n\n const refreshTimerRef = useRef<NodeJS.Timeout | null>(null);\n const isMountedRef = useRef<boolean>(true);\n\n /**\n * Fetch token from endpoint\n */\n const fetchToken = useCallback(async () => {\n if (!tokenUrl) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const response = await fetch(tokenUrl, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n credentials: 'include', // Include cookies for auth\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new Error(errorData.error || `Failed to fetch session token: ${response.statusText}`);\n }\n\n const data: SessionTokenData = await response.json();\n\n if (!isMountedRef.current) return;\n\n setToken(data.sessionToken);\n setExpiresAt(new Date(data.expiresAt));\n setError(null);\n\n onTokenRefresh?.(data.sessionToken);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch session token');\n\n if (!isMountedRef.current) return;\n\n setError(error);\n onError?.(error);\n } finally {\n if (isMountedRef.current) {\n setIsLoading(false);\n }\n }\n }, [tokenUrl, onTokenRefresh, onError]);\n\n /**\n * Setup auto-refresh timer\n */\n useEffect(() => {\n if (!autoRefresh || !expiresAt || !tokenUrl) return;\n\n // Clear existing timer\n if (refreshTimerRef.current) {\n clearTimeout(refreshTimerRef.current);\n }\n\n const now = Date.now();\n const expiryTime = expiresAt.getTime();\n const msUntilExpiry = expiryTime - now;\n\n // Refresh X seconds before expiry\n const refreshAt = msUntilExpiry - (refreshBeforeExpiry * 1000);\n\n if (refreshAt > 0) {\n refreshTimerRef.current = setTimeout(() => {\n fetchToken();\n }, refreshAt);\n } else if (msUntilExpiry > 0) {\n // Token expires soon, refresh immediately\n fetchToken();\n }\n\n return () => {\n if (refreshTimerRef.current) {\n clearTimeout(refreshTimerRef.current);\n }\n };\n }, [expiresAt, autoRefresh, refreshBeforeExpiry, tokenUrl, fetchToken]);\n\n /**\n * Initial fetch when tokenUrl is provided\n */\n useEffect(() => {\n if (tokenUrl && !manualToken) {\n fetchToken();\n }\n }, [tokenUrl, manualToken, fetchToken]);\n\n /**\n * Update token when manual token changes\n */\n useEffect(() => {\n if (manualToken) {\n setToken(manualToken);\n // Can't determine expiry from manual token, so disable auto-refresh\n setExpiresAt(null);\n }\n }, [manualToken]);\n\n /**\n * Cleanup on unmount\n */\n useEffect(() => {\n return () => {\n isMountedRef.current = false;\n if (refreshTimerRef.current) {\n clearTimeout(refreshTimerRef.current);\n }\n };\n }, []);\n\n /**\n * Check if token is valid (not expired)\n */\n const isValid = Boolean(\n token && (!expiresAt || expiresAt.getTime() > Date.now())\n );\n\n return {\n token,\n expiresAt,\n isLoading,\n error,\n refresh: fetchToken,\n isValid,\n };\n}\n","\"use client\";\nimport { useQuery, useMutation, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'\nimport { useBillingOS } from '../providers'\nimport type {\n Subscription,\n CreateSubscriptionInput,\n UpdateSubscriptionInput,\n SubscriptionPreview,\n PaginatedResponse,\n AvailablePlansResponse,\n PreviewChangeInput,\n PreviewChangeResponse,\n ChangePlanInput,\n ChangePlanResponse,\n} from '../client'\n\n/**\n * Query keys for subscription-related queries\n */\nexport const subscriptionKeys = {\n all: ['subscriptions'] as const,\n lists: () => [...subscriptionKeys.all, 'list'] as const,\n list: (filters?: Record<string, unknown>) => [...subscriptionKeys.lists(), filters] as const,\n details: () => [...subscriptionKeys.all, 'detail'] as const,\n detail: (id: string) => [...subscriptionKeys.details(), id] as const,\n preview: (id: string, input: UpdateSubscriptionInput) => [...subscriptionKeys.all, 'preview', id, input] as const,\n}\n\n/**\n * Fetch a single subscription by ID\n *\n * @param id - Subscription ID\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function SubscriptionDetails({ id }: { id: string }) {\n * const { data: subscription, isLoading, error } = useSubscription(id)\n *\n * if (isLoading) return <div>Loading...</div>\n * if (error) return <div>Error: {error.message}</div>\n *\n * return (\n * <div>\n * <h1>Subscription Status: {subscription.status}</h1>\n * <p>Next billing: {subscription.current_period_end}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useSubscription(\n id: string,\n options?: Omit<UseQueryOptions<Subscription>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: subscriptionKeys.detail(id),\n queryFn: () => client!.getSubscription(id),\n enabled: !!client && !!id,\n ...options,\n })\n}\n\n/**\n * Fetch a list of subscriptions (paginated)\n *\n * @param params - Query parameters (customer_id, pagination)\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function SubscriptionsList() {\n * const { data, isLoading } = useSubscriptions({\n * customer_id: 'cus_123',\n * page: 1,\n * page_size: 10\n * })\n *\n * if (isLoading) return <div>Loading...</div>\n *\n * return (\n * <div>\n * {data?.data.map(subscription => (\n * <SubscriptionCard key={subscription.id} subscription={subscription} />\n * ))}\n * <p>Total: {data?.meta.total}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useSubscriptions(\n params?: {\n customer_id?: string\n page?: number\n page_size?: number\n },\n options?: Omit<UseQueryOptions<PaginatedResponse<Subscription>>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: subscriptionKeys.list(params),\n queryFn: () => client!.listSubscriptions(params),\n enabled: !!client,\n ...options,\n })\n}\n\n/**\n * Create a new subscription\n *\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function CreateSubscriptionButton() {\n * const createSubscription = useCreateSubscription({\n * onSuccess: (subscription) => {\n * console.log('Subscription created:', subscription.id)\n * // Redirect to success page\n * },\n * onError: (error) => {\n * console.error('Failed to create subscription:', error)\n * }\n * })\n *\n * const handleClick = () => {\n * createSubscription.mutate({\n * customer_id: 'cus_123',\n * price_id: 'price_456',\n * trial_days: 14\n * })\n * }\n *\n * return (\n * <button\n * onClick={handleClick}\n * disabled={createSubscription.isPending}\n * >\n * {createSubscription.isPending ? 'Creating...' : 'Subscribe'}\n * </button>\n * )\n * }\n * ```\n */\nexport function useCreateSubscription(\n options?: Omit<UseMutationOptions<Subscription, Error, CreateSubscriptionInput>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: CreateSubscriptionInput) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.createSubscription(input)\n },\n onSuccess: (_data, _variables, _context) => {\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n },\n })\n}\n\n/**\n * Update an existing subscription\n *\n * @param subscriptionId - Subscription ID to update\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function UpgradeButton({ subscriptionId }: { subscriptionId: string }) {\n * const updateSubscription = useUpdateSubscription(subscriptionId, {\n * onSuccess: () => {\n * console.log('Subscription updated!')\n * }\n * })\n *\n * const handleUpgrade = () => {\n * updateSubscription.mutate({\n * price_id: 'price_pro_plan'\n * })\n * }\n *\n * return (\n * <button onClick={handleUpgrade} disabled={updateSubscription.isPending}>\n * Upgrade to Pro\n * </button>\n * )\n * }\n * ```\n */\nexport function useUpdateSubscription(\n subscriptionId: string,\n options?: Omit<UseMutationOptions<Subscription, Error, UpdateSubscriptionInput>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: UpdateSubscriptionInput) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.updateSubscription(subscriptionId, input)\n },\n onSuccess: (_data, _variables, _context) => {\n // Invalidate this subscription's cache\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.detail(subscriptionId) })\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n },\n })\n}\n\n/**\n * Cancel a subscription\n *\n * @param subscriptionId - Subscription ID to cancel\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function CancelButton({ subscriptionId }: { subscriptionId: string }) {\n * const cancelSubscription = useCancelSubscription(subscriptionId, {\n * onSuccess: () => {\n * alert('Subscription cancelled')\n * }\n * })\n *\n * const handleCancel = (immediately: boolean) => {\n * if (confirm('Are you sure you want to cancel?')) {\n * cancelSubscription.mutate({ immediately })\n * }\n * }\n *\n * return (\n * <div>\n * <button onClick={() => handleCancel(false)}>\n * Cancel at period end\n * </button>\n * <button onClick={() => handleCancel(true)}>\n * Cancel immediately\n * </button>\n * </div>\n * )\n * }\n * ```\n */\nexport function useCancelSubscription(\n subscriptionId: string,\n options?: Omit<UseMutationOptions<Subscription, Error, { immediately?: boolean }>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: ({ immediately = false }: { immediately?: boolean }) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.cancelSubscription(subscriptionId, immediately)\n },\n onSuccess: (_data, _variables, _context) => {\n // Invalidate this subscription's cache\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.detail(subscriptionId) })\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n },\n })\n}\n\n/**\n * Reactivate a canceled subscription\n *\n * @param subscriptionId - Subscription ID to reactivate\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function ReactivateButton({ subscriptionId }: { subscriptionId: string }) {\n * const reactivateSubscription = useReactivateSubscription(subscriptionId)\n *\n * return (\n * <button\n * onClick={() => reactivateSubscription.mutate()}\n * disabled={reactivateSubscription.isPending}\n * >\n * Reactivate Subscription\n * </button>\n * )\n * }\n * ```\n */\nexport function useReactivateSubscription(\n subscriptionId: string,\n options?: Omit<UseMutationOptions<Subscription, Error, void>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: () => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.reactivateSubscription(subscriptionId)\n },\n onSuccess: (_data, _variables, _context) => {\n // Invalidate this subscription's cache\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.detail(subscriptionId) })\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n },\n })\n}\n\n/**\n * Preview subscription changes before applying them\n *\n * @param subscriptionId - Subscription ID\n * @param input - Proposed changes\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function UpgradePreview({ subscriptionId }: { subscriptionId: string }) {\n * const { data: preview, isLoading } = useSubscriptionPreview(\n * subscriptionId,\n * { price_id: 'price_pro_plan' }\n * )\n *\n * if (isLoading) return <div>Calculating...</div>\n *\n * return (\n * <div>\n * <p>Proration: ${preview?.proration_amount / 100}</p>\n * <p>Next invoice: ${preview?.next_invoice_amount / 100}</p>\n * <p>Billing date: {preview?.next_invoice_date}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useSubscriptionPreview(\n subscriptionId: string,\n input: UpdateSubscriptionInput,\n options?: Omit<UseQueryOptions<SubscriptionPreview>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: subscriptionKeys.preview(subscriptionId, input),\n queryFn: () => client!.previewSubscription(subscriptionId, input),\n enabled: !!client && !!subscriptionId && !!input,\n ...options,\n })\n}\n\n/**\n * Fetch available plans for upgrade/downgrade\n *\n * @param subscriptionId - Subscription ID\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function AvailablePlans({ subscriptionId }: { subscriptionId: string }) {\n * const { data, isLoading } = useAvailablePlans(subscriptionId)\n *\n * if (isLoading) return <div>Loading plans...</div>\n *\n * return (\n * <div>\n * <h3>Upgrades:</h3>\n * {data?.available_upgrades.map(plan => (\n * <div key={plan.price_id}>{plan.product_name}</div>\n * ))}\n * </div>\n * )\n * }\n * ```\n */\nexport function useAvailablePlans(\n subscriptionId: string,\n options?: Omit<UseQueryOptions<AvailablePlansResponse>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: [...subscriptionKeys.detail(subscriptionId), 'available-plans'] as const,\n queryFn: () => client!.getAvailablePlans(subscriptionId),\n enabled: !!client && !!subscriptionId,\n ...options,\n })\n}\n\n/**\n * Preview a plan change with proration details\n *\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function PlanChangePreview({ subscriptionId }: { subscriptionId: string }) {\n * const previewChange = usePreviewPlanChange()\n *\n * const handlePreview = async (newPriceId: string) => {\n * const preview = await previewChange.mutateAsync({\n * subscriptionId,\n * input: { new_price_id: newPriceId }\n * })\n * console.log('Proration:', preview.proration.immediate_payment)\n * }\n *\n * return <button onClick={() => handlePreview('price_123')}>Preview</button>\n * }\n * ```\n */\nexport function usePreviewPlanChange(\n options?: Omit<\n UseMutationOptions<\n PreviewChangeResponse,\n Error,\n { subscriptionId: string; input: PreviewChangeInput }\n >,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n\n return useMutation({\n ...options,\n mutationFn: ({ subscriptionId, input }) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.previewPlanChange(subscriptionId, input)\n },\n })\n}\n\n/**\n * Execute a plan change (upgrade/downgrade)\n *\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function ChangePlanButton({ subscriptionId }: { subscriptionId: string }) {\n * const changePlan = useChangePlan({\n * onSuccess: (response) => {\n * console.log('Plan changed:', response.subscription.id)\n * }\n * })\n *\n * const handleChange = () => {\n * changePlan.mutate({\n * subscriptionId,\n * input: {\n * new_price_id: 'price_456',\n * confirm_amount: 1999\n * }\n * })\n * }\n *\n * return (\n * <button onClick={handleChange} disabled={changePlan.isPending}>\n * {changePlan.isPending ? 'Changing...' : 'Change Plan'}\n * </button>\n * )\n * }\n * ```\n */\nexport function useChangePlan(\n options?: Omit<\n UseMutationOptions<\n ChangePlanResponse,\n Error,\n { subscriptionId: string; input: ChangePlanInput }\n >,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: ({ subscriptionId, input }) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.changePlan(subscriptionId, input)\n },\n onSuccess: (_data, variables, _context) => {\n // Invalidate subscription cache\n queryClient.invalidateQueries({\n queryKey: subscriptionKeys.detail(variables.subscriptionId),\n })\n // Invalidate subscription lists\n queryClient.invalidateQueries({ queryKey: subscriptionKeys.lists() })\n // Invalidate available plans\n queryClient.invalidateQueries({\n queryKey: [...subscriptionKeys.detail(variables.subscriptionId), 'available-plans'],\n })\n },\n })\n}\n","\"use client\";\nimport React, { createContext, useContext, useMemo } from 'react'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { BillingOSClient, BillingOSClientOptions } from '../client'\nimport { useSessionToken, UseSessionTokenOptions } from '../hooks/useSessionToken'\nimport { resolveApiUrl, resolveAppUrl, resolveApiUrlFromToken, BILLINGOS_APP_URL } from '../utils/urls'\n\n/**\n * Context value provided by BillingOSProvider\n */\nexport interface BillingOSContextValue {\n client: BillingOSClient | null\n apiUrl: string\n appUrl: string\n customerId?: string\n customerEmail?: string\n customerName?: string\n organizationId?: string\n debug: boolean\n}\n\nconst BillingOSContext = createContext<BillingOSContextValue | undefined>(undefined)\n\nexport interface BillingOSProviderProps {\n /**\n * @deprecated The SDK now auto-detects the API URL from the session token prefix.\n * Only use this for internal development to override the auto-detected URL.\n */\n apiUrl?: string\n\n /**\n * @deprecated The app URL is now always https://app.billingos.dev.\n * Only use this for internal development to override the default.\n */\n appUrl?: string\n\n /**\n * URL to fetch session token from (e.g., /api/billingos-session).\n * The SDK will automatically fetch and refresh the token.\n */\n sessionTokenUrl?: string\n\n /**\n * Provide a session token directly instead of auto-fetching.\n */\n sessionToken?: string\n\n /**\n * Session token auto-refresh configuration.\n */\n sessionTokenOptions?: Omit<UseSessionTokenOptions, 'token' | 'tokenUrl'>\n\n /**\n * Rendered while the session token is being fetched.\n * Defaults to rendering children (app is visible immediately, billing components show their own loading state).\n */\n loadingFallback?: React.ReactNode\n\n /**\n * Optional customer context passed to all hooks and components.\n */\n customerId?: string\n customerEmail?: string\n customerName?: string\n organizationId?: string\n\n /**\n * Additional client configuration (headers, timeout, etc.).\n */\n options?: BillingOSClientOptions\n\n /**\n * Inject a custom TanStack QueryClient.\n */\n queryClient?: QueryClient\n\n /**\n * Enable debug logging. Off by default.\n */\n debug?: boolean\n\n children: React.ReactNode\n}\n\nconst createDefaultQueryClient = () =>\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 1000 * 60 * 5,\n gcTime: 1000 * 60 * 10,\n retry: 1,\n refetchOnWindowFocus: false,\n },\n mutations: {\n retry: false,\n },\n },\n })\n\nexport function BillingOSProvider({\n apiUrl: apiUrlProp,\n appUrl: appUrlProp,\n sessionToken: manualSessionToken,\n sessionTokenUrl,\n sessionTokenOptions,\n loadingFallback,\n customerId,\n customerEmail,\n customerName,\n organizationId,\n options,\n queryClient,\n debug = false,\n children,\n}: BillingOSProviderProps) {\n // Resolve URLs: prop/env var overrides take priority, otherwise auto-detect from token prefix\n const hasApiUrlOverride = !!(apiUrlProp || (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_BILLINGOS_API_URL))\n const hasAppUrlOverride = !!(appUrlProp || (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_BILLINGOS_APP_URL))\n\n const { token, isLoading, error } = useSessionToken({\n token: manualSessionToken,\n tokenUrl: sessionTokenUrl,\n ...sessionTokenOptions,\n })\n\n // API URL: use override if provided, otherwise auto-detect from token prefix\n const apiUrl = useMemo(() => {\n if (hasApiUrlOverride) return resolveApiUrl(apiUrlProp)\n if (token) return resolveApiUrlFromToken(token)\n return resolveApiUrl(apiUrlProp) // fallback to default while token is loading\n }, [apiUrlProp, hasApiUrlOverride, token])\n\n // App URL: use override if provided, otherwise always app.billingos.dev\n const appUrl = useMemo(() => {\n if (hasAppUrlOverride) return resolveAppUrl(appUrlProp)\n return BILLINGOS_APP_URL\n }, [appUrlProp, hasAppUrlOverride])\n\n const qc = useMemo(\n () => queryClient || createDefaultQueryClient(),\n [queryClient]\n )\n\n const client = useMemo(\n () =>\n token\n ? new BillingOSClient(token, { ...(hasApiUrlOverride ? { baseUrl: apiUrl } : {}), ...options })\n : null,\n [token, apiUrl, hasApiUrlOverride, options]\n )\n\n const contextValue = useMemo<BillingOSContextValue>(\n () => ({\n client,\n apiUrl,\n appUrl,\n customerId,\n customerEmail,\n customerName,\n organizationId,\n debug,\n }),\n [client, apiUrl, appUrl, customerId, customerEmail, customerName, organizationId, debug]\n )\n\n if (sessionTokenUrl && isLoading) {\n if (debug) console.log('[BillingOS] Fetching session token...')\n return (\n <BillingOSContext.Provider value={contextValue}>\n <QueryClientProvider client={qc}>\n {loadingFallback !== undefined ? loadingFallback : children}\n </QueryClientProvider>\n </BillingOSContext.Provider>\n )\n }\n\n if (sessionTokenUrl && error) {\n console.error('[BillingOS] Failed to fetch session token:', error)\n return (\n <BillingOSContext.Provider value={contextValue}>\n <QueryClientProvider client={qc}>{children}</QueryClientProvider>\n </BillingOSContext.Provider>\n )\n }\n\n if (!token) {\n if (debug) {\n console.warn('[BillingOS] No session token available. Pass sessionToken or sessionTokenUrl.')\n }\n return (\n <BillingOSContext.Provider value={contextValue}>\n <QueryClientProvider client={qc}>{children}</QueryClientProvider>\n </BillingOSContext.Provider>\n )\n }\n\n return (\n <BillingOSContext.Provider value={contextValue}>\n <QueryClientProvider client={qc}>{children}</QueryClientProvider>\n </BillingOSContext.Provider>\n )\n}\n\nexport function useBillingOS(): BillingOSContextValue {\n const context = useContext(BillingOSContext)\n\n if (!context) {\n throw new Error(\n 'useBillingOS must be used within a BillingOSProvider. ' +\n 'Wrap your app with <BillingOSProvider> to use BillingOS hooks and components.'\n )\n }\n\n return context\n}\n\nexport { useQueryClient as useBillingOSQueryClient } from '@tanstack/react-query'\n","\"use client\";\nimport { useState, useCallback } from 'react'\nimport { useBillingOS } from '../providers/BillingOSProvider'\nimport { getCheckoutAPI, type CheckoutOpenOptions } from '../checkout'\nimport type { Subscription } from '../client/types'\n\n/**\n * Result from opening checkout\n */\nexport interface CheckoutResult {\n success: boolean\n subscription?: Subscription\n error?: Error\n}\n\n/**\n * Hook for programmatically opening checkout\n */\nexport function useCheckout() {\n const { client } = useBillingOS()\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const openCheckout = useCallback(async (options: Omit<CheckoutOpenOptions, 'sessionToken' | 'apiUrl'>): Promise<CheckoutResult> => {\n if (!client) return { success: false, error: new Error('[BillingOS] No active session') }\n setIsLoading(true)\n setError(null)\n\n try {\n const api = getCheckoutAPI(client)\n const result = await api.open(options)\n\n if (!result.success && result.error) {\n setError(result.error)\n }\n\n return result\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to open checkout')\n setError(error)\n return { success: false, error }\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n const closeCheckout = useCallback(() => {\n if (!client) return\n const api = getCheckoutAPI(client)\n api.close()\n }, [client])\n\n return {\n openCheckout,\n closeCheckout,\n isLoading,\n error\n }\n}","\"use client\";\nimport React from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { CheckoutModal, CheckoutModalProps } from './components/CheckoutModal'\nimport { BillingOSProvider } from './providers/BillingOSProvider'\nimport { BillingOSClient } from './client'\nimport type { Subscription } from './client/types'\n\n/**\n * Options for opening the checkout modal programmatically\n */\nexport interface CheckoutOpenOptions {\n /**\n * The price ID to checkout\n */\n priceId: string\n\n /**\n * Customer information to pre-populate\n */\n customer?: {\n email?: string\n name?: string\n taxId?: string\n }\n\n /**\n * Coupon code to apply\n */\n couponCode?: string\n\n /**\n * Whether to collect billing address\n */\n collectBillingAddress?: boolean\n\n /**\n * Currency for the checkout (defaults to price currency)\n */\n currency?: string\n\n /**\n * Existing subscription ID for upgrades/downgrades\n */\n existingSubscriptionId?: string\n\n /**\n * Custom metadata to attach to the subscription\n */\n metadata?: Record<string, string>\n\n /**\n * Theme for the checkout modal\n */\n theme?: 'light' | 'dark' | 'auto'\n\n /**\n * Locale for the checkout (e.g., 'en', 'es', 'fr')\n */\n locale?: string\n\n /**\n * Success callback with the created subscription\n */\n onSuccess?: (subscription: Subscription) => void\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n\n /**\n * Cancel callback when user closes without completing\n */\n onCancel?: () => void\n\n /**\n * Debug mode for development\n */\n debug?: boolean\n\n /**\n * Session token for authentication (if not using provider)\n */\n sessionToken?: string\n\n /**\n * API base URL (if not using provider)\n */\n apiUrl?: string\n\n /**\n * Enable Stripe Adaptive Pricing — lets customers pay in their local currency (~150 countries).\n * Defaults to true.\n */\n adaptivePricing?: boolean\n}\n\n/**\n * Programmatic checkout API\n */\nexport class CheckoutAPI {\n private client?: BillingOSClient\n private container?: HTMLElement\n private root?: ReturnType<typeof createRoot>\n\n constructor(client?: BillingOSClient) {\n this.client = client\n }\n\n /**\n * Open the checkout modal programmatically\n */\n async open(options: CheckoutOpenOptions): Promise<{ success: boolean; subscription?: Subscription; error?: Error }> {\n return new Promise((resolve) => {\n // Create container if it doesn't exist\n if (!this.container) {\n this.container = document.createElement('div')\n this.container.id = 'billingos-checkout-container'\n this.container.style.position = 'fixed'\n this.container.style.zIndex = '999999'\n document.body.appendChild(this.container)\n }\n\n // Create the modal component\n const modalProps: CheckoutModalProps = {\n open: true,\n onOpenChange: (open: boolean) => {\n if (!open) {\n this.close()\n if (options.onCancel) {\n options.onCancel()\n }\n resolve({ success: false })\n }\n },\n priceId: options.priceId,\n customer: options.customer,\n couponCode: options.couponCode,\n collectBillingAddress: options.collectBillingAddress,\n currency: options.currency,\n existingSubscriptionId: options.existingSubscriptionId,\n metadata: options.metadata,\n theme: options.theme,\n locale: options.locale,\n adaptivePricing: options.adaptivePricing ?? true,\n onSuccess: (subscription: Subscription) => {\n if (options.onSuccess) {\n options.onSuccess(subscription)\n }\n resolve({ success: true, subscription })\n this.close()\n },\n onError: (error: Error) => {\n if (options.onError) {\n options.onError(error)\n }\n resolve({ success: false, error })\n },\n onCancel: options.onCancel,\n debug: options.debug\n }\n\n // Render the modal\n if (!this.root) {\n this.root = createRoot(this.container)\n }\n\n // If we have a client, use it directly\n // Otherwise, create a new one with the provided session token\n if (this.client) {\n // Already have a provider context\n this.root.render(\n React.createElement(CheckoutModal, modalProps)\n )\n } else if (options.sessionToken) {\n // Need to create a provider\n this.root.render(\n React.createElement(\n BillingOSProvider,\n {\n sessionToken: options.sessionToken,\n options: {\n baseUrl: options.apiUrl\n },\n children: React.createElement(CheckoutModal, modalProps)\n }\n )\n )\n } else {\n // No authentication provided\n const error = new Error('No session token or BillingOS client provided')\n if (options.onError) {\n options.onError(error)\n }\n resolve({ success: false, error })\n this.close()\n }\n })\n }\n\n /**\n * Close the checkout modal\n */\n close() {\n if (this.root) {\n this.root.unmount()\n this.root = undefined\n }\n if (this.container) {\n this.container.remove()\n this.container = undefined\n }\n }\n}\n\n/**\n * Global checkout API instance\n */\nlet globalCheckoutAPI: CheckoutAPI | null = null\n\n/**\n * Get or create the global checkout API instance\n */\nexport function getCheckoutAPI(client?: BillingOSClient): CheckoutAPI {\n if (!globalCheckoutAPI) {\n globalCheckoutAPI = new CheckoutAPI(client)\n }\n return globalCheckoutAPI\n}\n\n/**\n * Convenience function to open checkout modal\n */\nexport async function openCheckout(options: CheckoutOpenOptions) {\n const api = getCheckoutAPI()\n return api.open(options)\n}","\"use client\";\nimport { useState, useEffect, useRef, useCallback } from 'react'\nimport { Dialog, DialogContent } from '../ui/dialog'\nimport { CheckoutIframe } from './CheckoutIframe'\nimport { useCheckoutSession } from './hooks/useCheckoutSession'\nimport { useIframeMessaging } from './hooks/useIframeMessaging'\nimport { useBillingOS } from '../../providers/BillingOSProvider'\nimport type { IframeMessage } from './utils/messaging'\nimport { cn } from '../../utils/cn'\n\nexport interface CheckoutModalProps {\n /**\n * Whether the modal is open\n */\n open: boolean\n\n /**\n * Callback when the modal open state changes\n */\n onOpenChange: (open: boolean) => void\n\n /**\n * The price ID to checkout\n */\n priceId: string\n\n /**\n * Customer information to pre-populate\n */\n customer?: {\n email?: string\n name?: string\n taxId?: string\n }\n\n /**\n * Coupon code to apply\n */\n couponCode?: string\n\n /**\n * Whether to collect billing address\n */\n collectBillingAddress?: boolean\n\n /**\n * Currency for the checkout (defaults to price currency)\n */\n currency?: string\n\n /**\n * Existing subscription ID for upgrades/downgrades\n */\n existingSubscriptionId?: string\n\n /**\n * Custom metadata to attach to the subscription\n */\n metadata?: Record<string, string>\n\n /**\n * Theme for the checkout modal\n */\n theme?: 'light' | 'dark' | 'auto'\n\n /**\n * Locale for the checkout (e.g., 'en', 'es', 'fr')\n */\n locale?: string\n\n /**\n * Success callback with the created subscription\n */\n onSuccess: (subscription: any) => void\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n\n /**\n * Cancel callback when user closes without completing\n */\n onCancel?: () => void\n\n /**\n * Debug mode for development\n */\n debug?: boolean\n\n /**\n * Enable Stripe Adaptive Pricing — lets customers pay in their local currency (~150 countries).\n * Defaults to true.\n */\n adaptivePricing?: boolean\n}\n\ntype CheckoutState = 'loading' | 'ready' | 'processing' | 'success' | 'error'\n\nexport function CheckoutModal({\n open,\n onOpenChange,\n priceId,\n customer,\n couponCode,\n collectBillingAddress,\n existingSubscriptionId,\n metadata,\n theme = 'light',\n locale = 'en',\n onSuccess,\n onError,\n onCancel,\n debug = false,\n adaptivePricing = true,\n}: CheckoutModalProps) {\n const { appUrl, debug: contextDebug } = useBillingOS()\n const isDebug = debug || contextDebug\n\n const [state, setState] = useState<CheckoutState>('loading')\n const [error, setError] = useState<Error | null>(null)\n const [iframeHeight, setIframeHeight] = useState(600)\n const iframeRef = useRef<HTMLIFrameElement>(null)\n\n\n // Create checkout session when modal opens\n const { sessionId, sessionUrl, loading, error: sessionError } = useCheckoutSession({\n enabled: open,\n priceId,\n customer,\n couponCode,\n metadata,\n existingSubscriptionId,\n adaptivePricing,\n })\n\n // Handle iframe messaging\n const handleIframeMessage = useCallback((message: IframeMessage) => {\n switch (message.type) {\n case 'CHECKOUT_READY':\n setState('ready')\n break\n\n case 'CHECKOUT_SUCCESS':\n setState('success')\n onSuccess(message.payload?.subscription)\n onOpenChange(false)\n break\n\n case 'CHECKOUT_ERROR':\n setState('error')\n const errorMessage = message.payload?.error || 'An error occurred'\n const error = new Error(errorMessage)\n setError(error)\n onError?.(error)\n break\n\n case 'CHECKOUT_CLOSE':\n onCancel?.()\n onOpenChange(false)\n break\n\n case 'HEIGHT_CHANGED':\n if (message.payload?.height) {\n setIframeHeight(message.payload.height)\n }\n break\n\n case 'PROCESSING':\n setState('processing')\n break\n\n default:\n break\n }\n }, [isDebug, onSuccess, onError, onCancel, onOpenChange])\n\n const { sendMessage } = useIframeMessaging({\n iframeRef,\n onMessage: handleIframeMessage,\n targetOrigin: appUrl || '*',\n debug: isDebug\n })\n\n // Send initialization message when iframe is ready\n useEffect(() => {\n if (sessionId && state === 'ready') {\n sendMessage({\n type: 'INIT_CHECKOUT',\n sessionId,\n config: {\n theme,\n locale,\n collectBillingAddress\n }\n })\n }\n }, [sessionId, state, theme, locale, collectBillingAddress, sendMessage])\n\n // Reset state when modal closes\n useEffect(() => {\n if (!open) {\n setState('loading')\n setError(null)\n setIframeHeight(600)\n }\n }, [open])\n\n // Handle session creation error\n useEffect(() => {\n if (sessionError) {\n setState('error')\n setError(sessionError)\n onError?.(sessionError)\n }\n }, [sessionError, onError])\n\n const showSpinner = loading || state === 'loading'\n const showError = state === 'error' && error\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n className={cn(\n \"max-w-[800px] w-full p-0 overflow-hidden\",\n \"max-h-[90vh] relative\"\n )}\n >\n {showError ? (\n <div className=\"p-8 text-center\">\n <div className=\"text-red-600 mb-2\">\n <svg\n className=\"w-12 h-12 mx-auto\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">Payment Error</h3>\n <p className=\"text-gray-600\">{error.message}</p>\n <button\n onClick={() => onOpenChange(false)}\n className=\"mt-4 px-4 py-2 bg-gray-200 rounded-md hover:bg-gray-300\"\n >\n Close\n </button>\n </div>\n ) : (\n <>\n {showSpinner && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white z-10\">\n <div className=\"animate-spin rounded-full h-10 w-10 border-b-2 border-blue-600\"></div>\n </div>\n )}\n\n {sessionUrl && (\n <CheckoutIframe\n ref={iframeRef}\n src={sessionUrl}\n height={iframeHeight}\n className={cn(\n \"transition-opacity duration-300\",\n showSpinner ? \"opacity-0\" : \"opacity-100\"\n )}\n onLoad={() => {}}\n />\n )}\n\n {state === 'processing' && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/80 z-10\">\n <div className=\"flex flex-col items-center\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-green-600\"></div>\n <p className=\"mt-4 text-gray-600\">Processing payment...</p>\n </div>\n </div>\n )}\n </>\n )}\n\n {debug && (\n <div className=\"absolute bottom-0 left-0 right-0 bg-black/80 text-white p-2 text-xs\">\n <div>State: {state}</div>\n <div>Session: {sessionId || 'Creating...'}</div>\n {error && <div>Error: {error.message}</div>}\n </div>\n )}\n </DialogContent>\n </Dialog>\n )\n}","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface DialogContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n}\n\nconst DialogContext = React.createContext<DialogContextValue | null>(null)\n\nfunction useDialogContext() {\n const context = React.useContext(DialogContext)\n if (!context) {\n throw new Error('Dialog components must be used within a Dialog provider')\n }\n return context\n}\n\ninterface DialogProps {\n open?: boolean\n onOpenChange?: (open: boolean) => void\n children: React.ReactNode\n}\n\nfunction Dialog({ open = false, onOpenChange, children }: DialogProps) {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const isOpen = open ?? internalOpen\n const handleOpenChange = onOpenChange ?? setInternalOpen\n\n return (\n <DialogContext.Provider value={{ open: isOpen, onOpenChange: handleOpenChange }}>\n {children}\n </DialogContext.Provider>\n )\n}\n\ninterface DialogTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean\n}\n\nconst DialogTrigger = React.forwardRef<HTMLButtonElement, DialogTriggerProps>(\n ({ onClick, ...props }, ref) => {\n const { onOpenChange } = useDialogContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(true)\n onClick?.(e)\n }}\n {...props}\n />\n )\n }\n)\nDialogTrigger.displayName = 'DialogTrigger'\n\ninterface DialogPortalProps {\n children: React.ReactNode\n}\n\nfunction DialogPortal({ children }: DialogPortalProps) {\n const { open } = useDialogContext()\n if (!open) return null\n return <>{children}</>\n}\n\nconst DialogOverlay = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const { onOpenChange } = useDialogContext()\n\n return (\n <div\n ref={ref}\n onClick={() => onOpenChange(false)}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n className\n )}\n {...props}\n />\n )\n})\nDialogOverlay.displayName = 'DialogOverlay'\n\nconst DialogContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, children, ...props }, ref) => {\n const { open, onOpenChange } = useDialogContext()\n\n // Handle escape key\n React.useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onOpenChange(false)\n }\n }\n if (open) {\n document.addEventListener('keydown', handleEscape)\n document.body.style.overflow = 'hidden'\n }\n return () => {\n document.removeEventListener('keydown', handleEscape)\n document.body.style.overflow = ''\n }\n }, [open, onOpenChange])\n\n if (!open) return null\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <DialogOverlay />\n <div\n ref={ref}\n onClick={(e) => e.stopPropagation()}\n className={cn(\n 'relative z-50 w-full max-w-lg gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg',\n className\n )}\n {...props}\n >\n {children}\n </div>\n </div>\n )\n})\nDialogContent.displayName = 'DialogContent'\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col space-y-1.5 text-center sm:text-left',\n className\n )}\n {...props}\n />\n)\nDialogHeader.displayName = 'DialogHeader'\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n className\n )}\n {...props}\n />\n)\nDialogFooter.displayName = 'DialogFooter'\n\nconst DialogTitle = React.forwardRef<\n HTMLHeadingElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn(\n 'text-lg font-semibold leading-none tracking-tight',\n className\n )}\n {...props}\n />\n))\nDialogTitle.displayName = 'DialogTitle'\n\nconst DialogDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nDialogDescription.displayName = 'DialogDescription'\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n}\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\n/**\n * Utility function to merge Tailwind CSS classes\n * Combines clsx for conditional classes with tailwind-merge for deduplication\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\";\nimport React, { forwardRef } from 'react'\nimport { cn } from '../../utils/cn'\n\ninterface CheckoutIframeProps {\n /**\n * The iframe source URL\n */\n src: string\n\n /**\n * Height of the iframe\n */\n height?: number | string\n\n /**\n * Additional CSS classes\n */\n className?: string\n\n /**\n * Load event handler\n */\n onLoad?: () => void\n\n /**\n * Error event handler\n */\n onError?: (error: React.SyntheticEvent<HTMLIFrameElement>) => void\n}\n\nexport const CheckoutIframe = forwardRef<HTMLIFrameElement, CheckoutIframeProps>(\n ({ src, height = 600, className, onLoad, onError }, ref) => {\n return (\n <iframe\n ref={ref}\n src={src}\n className={cn(\"w-full border-none\", className)}\n style={{\n height: typeof height === 'number' ? `${height}px` : height,\n minHeight: '400px',\n maxHeight: '80vh'\n }}\n onLoad={onLoad}\n onError={onError}\n // Security attributes\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\"\n allow=\"payment\"\n // Accessibility\n title=\"Secure Checkout\"\n // Performance\n loading=\"lazy\"\n />\n )\n }\n)\n\nCheckoutIframe.displayName = 'CheckoutIframe'","\"use client\";\nimport { useState, useEffect, useRef } from \"react\";\nimport { useBillingOS } from \"../../../providers/BillingOSProvider\";\n\ninterface UseCheckoutSessionOptions {\n enabled: boolean;\n priceId: string;\n customer?: {\n email?: string;\n name?: string;\n taxId?: string;\n };\n couponCode?: string;\n metadata?: Record<string, string>;\n existingSubscriptionId?: string;\n adaptivePricing?: boolean;\n}\n\ninterface UseCheckoutSessionReturn {\n sessionId: string | null;\n sessionUrl: string | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n}\n\nexport function useCheckoutSession({\n enabled,\n priceId,\n customer,\n couponCode,\n metadata,\n existingSubscriptionId,\n adaptivePricing = true,\n}: UseCheckoutSessionOptions): UseCheckoutSessionReturn {\n const { client, appUrl, debug } = useBillingOS();\n const [sessionId, setSessionId] = useState<string | null>(null);\n const [sessionUrl, setSessionUrl] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n // Track which priceId we've already initiated a session for.\n // Using a ref instead of state so React Strict Mode's double-mount\n // doesn't reset it between the first and second effect invocation,\n // preventing the duplicate checkout session creation.\n const initiatedForPriceRef = useRef<string | null>(null);\n\n const createSession = async () => {\n if (!enabled || !priceId || !client) return;\n\n if (debug)\n console.log(\"[BillingOS] Creating checkout session...\", {\n priceId,\n customer,\n });\n\n setLoading(true);\n setError(null);\n\n try {\n // Create checkout session via API\n const session = await client.checkout.createSession({\n priceId,\n customer,\n couponCode,\n metadata,\n existingSubscriptionId,\n // Return URLs will be handled by postMessage instead\n mode: \"embedded\",\n adaptivePricing,\n });\n\n setSessionId(session.id);\n if (debug)\n console.log(\"[BillingOS] Checkout session created:\", session.id);\n\n // Generate iframe URL using appUrl from BillingOSProvider context\n const iframeUrl = `${appUrl}/embed/checkout/${session.id}`;\n setSessionUrl(iframeUrl);\n\n if (debug) console.log(\"[BillingOS] Iframe URL:\", iframeUrl);\n } catch (err) {\n const error =\n err instanceof Error\n ? err\n : new Error(\"Failed to create checkout session\");\n setError(error);\n console.error(\"[useCheckoutSession] Error creating session:\", error);\n } finally {\n setLoading(false);\n }\n };\n\n // Create session when enabled AND client is ready.\n // Guard with a ref so React Strict Mode's double-invocation of effects\n // doesn't fire two simultaneous API calls (state resets between mounts\n // but refs persist, so the second effect sees the guard and skips).\n // Also depends on client so it re-runs when the session token arrives.\n useEffect(() => {\n if (enabled && client && initiatedForPriceRef.current !== priceId) {\n initiatedForPriceRef.current = priceId;\n createSession();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, priceId, client]);\n\n // Cleanup session when component unmounts\n useEffect(() => {\n return () => {\n if (sessionId) {\n // Optionally cancel the session if not completed\n // client.checkout.cancelSession(sessionId).catch(() => {})\n }\n };\n }, [sessionId]);\n\n const refresh = async () => {\n setSessionId(null);\n setSessionUrl(null);\n await createSession();\n };\n\n return {\n sessionId,\n sessionUrl,\n loading,\n error,\n refresh,\n };\n}\n","\"use client\";\nimport { useEffect, useCallback, RefObject } from 'react'\nimport { validateOrigin } from '../utils/security'\nimport type { IframeMessage, ParentMessage } from '../utils/messaging'\n\ninterface UseIframeMessagingOptions {\n iframeRef: RefObject<HTMLIFrameElement | null>\n onMessage: (message: IframeMessage) => void\n targetOrigin?: string\n debug?: boolean\n}\n\ninterface UseIframeMessagingReturn {\n sendMessage: (message: ParentMessage) => void\n isConnected: boolean\n}\n\nexport function useIframeMessaging({\n iframeRef,\n onMessage,\n targetOrigin = '*',\n debug = false\n}: UseIframeMessagingOptions): UseIframeMessagingReturn {\n const isConnected = Boolean(iframeRef.current?.contentWindow)\n\n /**\n * Send message to iframe\n */\n const sendMessage = useCallback((message: ParentMessage) => {\n if (iframeRef.current?.contentWindow) {\n if (debug) {\n console.log('[useIframeMessaging] Sending message:', message)\n }\n iframeRef.current.contentWindow.postMessage(message, targetOrigin)\n } else {\n console.warn('[useIframeMessaging] Cannot send message - iframe not ready')\n }\n }, [iframeRef, targetOrigin, debug])\n\n /**\n * Handle incoming messages from iframe\n */\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n // Validate origin (pass targetOrigin so the configured app URL is always allowed)\n if (targetOrigin !== '*' && !validateOrigin(event.origin, targetOrigin)) {\n if (debug) {\n console.warn(`[BillingOS] Blocked message from unexpected origin: ${event.origin}`)\n }\n return\n }\n\n // Validate message structure\n if (!event.data || typeof event.data !== 'object' || !event.data.type) {\n return\n }\n\n // Check if this is a checkout message\n if (!event.data.type.startsWith('CHECKOUT_') && event.data.type !== 'HEIGHT_CHANGED' && event.data.type !== 'PROCESSING') {\n return\n }\n\n if (debug) {\n console.log('[useIframeMessaging] Received message:', event.data)\n }\n\n // Pass message to handler\n onMessage(event.data as IframeMessage)\n }\n\n window.addEventListener('message', handleMessage)\n\n return () => {\n window.removeEventListener('message', handleMessage)\n }\n }, [onMessage, debug])\n\n return {\n sendMessage,\n isConnected\n }\n}","/**\n * Security utilities for iframe communication\n */\n\n/**\n * Get allowed origins for iframe communication.\n * Pass the appUrl from BillingOSProvider context to include the configured app origin.\n */\nexport function getAllowedOrigins(appUrl?: string): string[] {\n const origins: string[] = []\n\n // Add the configured app URL from context (highest priority)\n if (appUrl) {\n try {\n origins.push(new URL(appUrl).origin)\n } catch {\n // ignore malformed URLs\n }\n }\n\n // Add legacy env var (NEXT_PUBLIC_BILLINGOS_APP_URL takes precedence)\n const envAppUrl =\n (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_BILLINGOS_APP_URL) || ''\n if (envAppUrl && !origins.includes(new URL(envAppUrl).origin)) {\n try {\n origins.push(new URL(envAppUrl).origin)\n } catch {\n // ignore\n }\n }\n\n // Add known BillingOS production domains\n origins.push('https://app.billingos.dev')\n origins.push('https://embed.billingos.dev')\n\n // Add localhost for development\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') {\n origins.push('http://localhost:3000')\n origins.push('http://localhost:3001')\n origins.push('http://127.0.0.1:3000')\n origins.push('http://127.0.0.1:3001')\n }\n\n return origins\n}\n\n/**\n * Validate message origin.\n * Pass appUrl from BillingOSProvider context when available.\n */\nexport function validateOrigin(origin: string, appUrl?: string): boolean {\n const allowedOrigins = getAllowedOrigins(appUrl)\n if (allowedOrigins.includes(origin)) return true\n\n // Allow BillingOS Vercel deployments\n if (origin.endsWith('.vercel.app') && origin.includes('billingos')) return true\n\n // Allow Stripe origins\n if (origin.endsWith('.stripe.com')) return true\n\n return false\n}\n\n/**\n * Generate a random nonce for message verification\n */\nexport function generateNonce(): string {\n return Math.random().toString(36).substring(2, 15) +\n Math.random().toString(36).substring(2, 15)\n}\n\n/**\n * Sanitize URL to prevent XSS\n */\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url)\n // Only allow http and https protocols\n if (!['http:', 'https:'].includes(parsed.protocol)) {\n throw new Error('Invalid protocol')\n }\n return parsed.toString()\n } catch {\n throw new Error('Invalid URL')\n }\n}\n\n/**\n * Create Content Security Policy for iframe\n */\nexport function getIframeCSP(): string {\n return [\n \"default-src 'self'\",\n \"script-src 'self' 'unsafe-inline' https://js.stripe.com\",\n \"connect-src 'self' https://api.stripe.com\",\n \"frame-src https://js.stripe.com https://hooks.stripe.com\",\n \"img-src 'self' data: https:\",\n \"style-src 'self' 'unsafe-inline'\"\n ].join('; ')\n}\n\n/**\n * Verify session token hasn't expired\n */\nexport function isSessionExpired(expiresAt: string | Date): boolean {\n const expiryTime = new Date(expiresAt).getTime()\n return Date.now() > expiryTime\n}","\"use client\";\nimport { useQuery, useMutation, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'\nimport { useBillingOS } from '../providers'\nimport type { Entitlement, UsageEvent, UsageMetrics } from '../client'\n\n/**\n * Query keys for entitlement-related queries\n */\nexport const entitlementKeys = {\n all: ['entitlements'] as const,\n lists: () => [...entitlementKeys.all, 'list'] as const,\n list: (customerId: string) => [...entitlementKeys.lists(), customerId] as const,\n checks: () => [...entitlementKeys.all, 'check'] as const,\n check: (customerId: string, featureKey: string) =>\n [...entitlementKeys.checks(), customerId, featureKey] as const,\n usage: (customerId: string, featureKey: string) =>\n [...entitlementKeys.all, 'usage', customerId, featureKey] as const,\n}\n\n/**\n * Check if a customer has access to a specific feature\n *\n * @param customerId - Customer ID to check\n * @param featureKey - Feature key to check access for\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function FeatureGate({ children }: { children: React.ReactNode }) {\n * const { data: entitlement, isLoading } = useCheckEntitlement(\n * 'cus_123',\n * 'advanced_analytics'\n * )\n *\n * if (isLoading) return <div>Checking access...</div>\n * if (!entitlement?.has_access) {\n * return <UpgradePrompt feature=\"advanced_analytics\" />\n * }\n *\n * return <>{children}</>\n * }\n * ```\n */\nexport function useCheckEntitlement(\n customerId: string,\n featureKey: string,\n options?: Omit<UseQueryOptions<Entitlement>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: entitlementKeys.check(customerId, featureKey),\n queryFn: () => client!.checkEntitlement({ customer_id: customerId, feature_key: featureKey }),\n enabled: !!client && !!customerId && !!featureKey,\n staleTime: 1000 * 60, // 1 minute (entitlements are cached server-side)\n ...options,\n })\n}\n\n/**\n * Simplified hook to check if a customer has access to a feature\n * Returns a boolean directly instead of the full Entitlement object\n *\n * @param customerId - Customer ID to check\n * @param featureKey - Feature key to check access for\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function PremiumFeature() {\n * const hasAccess = useHasFeature('cus_123', 'premium_features')\n *\n * if (!hasAccess) {\n * return <div>Upgrade to access this feature</div>\n * }\n *\n * return <div>Premium feature content here</div>\n * }\n * ```\n */\nexport function useHasFeature(\n customerId: string,\n featureKey: string,\n options?: Omit<UseQueryOptions<Entitlement>, 'queryKey' | 'queryFn'>\n): boolean {\n const { data } = useCheckEntitlement(customerId, featureKey, options)\n return data?.has_access || false\n}\n\n/**\n * Get all entitlements for a customer\n *\n * @param customerId - Customer ID\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function EntitlementsList({ customerId }: { customerId: string }) {\n * const { data: entitlements, isLoading } = useEntitlements(customerId)\n *\n * if (isLoading) return <div>Loading...</div>\n *\n * return (\n * <ul>\n * {entitlements?.map(entitlement => (\n * <li key={entitlement.feature_key}>\n * {entitlement.feature_key}: {entitlement.has_access ? '✓' : '✗'}\n * {entitlement.limit && ` (${entitlement.usage}/${entitlement.limit})`}\n * </li>\n * ))}\n * </ul>\n * )\n * }\n * ```\n */\nexport function useEntitlements(\n customerId: string,\n options?: Omit<UseQueryOptions<Entitlement[]>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: entitlementKeys.list(customerId),\n queryFn: () => client!.listEntitlements(customerId),\n enabled: !!client && !!customerId,\n ...options,\n })\n}\n\n/**\n * Track a usage event for a customer\n *\n * @param options - React Query mutation options\n *\n * @example\n * ```tsx\n * function APICallButton() {\n * const trackUsage = useTrackUsage({\n * onSuccess: () => {\n * console.log('Usage tracked')\n * }\n * })\n *\n * const handleAPICall = async () => {\n * // Make API call\n * await makeAPICall()\n *\n * // Track usage\n * trackUsage.mutate({\n * customer_id: 'cus_123',\n * feature_key: 'api_calls',\n * quantity: 1\n * })\n * }\n *\n * return <button onClick={handleAPICall}>Make API Call</button>\n * }\n * ```\n */\nexport function useTrackUsage(\n options?: Omit<UseMutationOptions<void, Error, UsageEvent>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (event: UsageEvent) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.trackUsage(event)\n },\n onSuccess: (_data, variables, _context) => {\n // Invalidate usage metrics for this feature\n queryClient.invalidateQueries({\n queryKey: entitlementKeys.usage(variables.customer_id || '', variables.feature_key),\n })\n // Invalidate entitlement check (usage affects has_access)\n queryClient.invalidateQueries({\n queryKey: entitlementKeys.check(variables.customer_id || '', variables.feature_key),\n })\n },\n })\n}\n\n/**\n * Get usage metrics for a customer and feature\n *\n * @param customerId - Customer ID\n * @param featureKey - Feature key\n * @param options - React Query options\n *\n * @example\n * ```tsx\n * function UsageDisplay({ customerId }: { customerId: string }) {\n * const { data: metrics, isLoading } = useUsageMetrics(\n * customerId,\n * 'api_calls'\n * )\n *\n * if (isLoading) return <div>Loading...</div>\n *\n * const percentage = metrics?.limit\n * ? (metrics.current_usage / metrics.limit) * 100\n * : 0\n *\n * return (\n * <div>\n * <h3>API Usage</h3>\n * <p>{metrics?.current_usage} / {metrics?.limit || '∞'} calls</p>\n * <progress value={percentage} max={100} />\n * <p>Period: {metrics?.period_start} - {metrics?.period_end}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useUsageMetrics(\n customerId: string,\n featureKey: string,\n options?: Omit<UseQueryOptions<UsageMetrics>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: entitlementKeys.usage(customerId, featureKey),\n queryFn: () => client!.getUsageMetrics(customerId, featureKey),\n enabled: !!client && !!customerId && !!featureKey,\n ...options,\n })\n}\n\n/**\n * Check if a customer is approaching their usage limit\n *\n * @param customerId - Customer ID\n * @param featureKey - Feature key\n * @param threshold - Threshold percentage (0-100) to warn at (default: 80)\n * @param options - React Query options\n * @returns Boolean indicating if customer is approaching limit\n *\n * @example\n * ```tsx\n * function UsageWarning({ customerId }: { customerId: string }) {\n * const isApproachingLimit = useIsApproachingLimit(\n * customerId,\n * 'api_calls',\n * 80 // Warn at 80%\n * )\n *\n * if (!isApproachingLimit) return null\n *\n * return (\n * <Alert variant=\"warning\">\n * You're approaching your API call limit. Upgrade to increase your quota.\n * </Alert>\n * )\n * }\n * ```\n */\nexport function useIsApproachingLimit(\n customerId: string,\n featureKey: string,\n threshold = 80,\n options?: Omit<UseQueryOptions<UsageMetrics>, 'queryKey' | 'queryFn'>\n): boolean {\n const { data: metrics } = useUsageMetrics(customerId, featureKey, options)\n\n if (!metrics || !metrics.limit) return false\n\n const percentage = (metrics.current_usage / metrics.limit) * 100\n return percentage >= threshold\n}\n","\"use client\";\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useBillingOS } from '../providers/BillingOSProvider'\n\n/**\n * Feature access response\n */\nexport interface FeatureAccess {\n feature_key: string\n has_access: boolean\n limit?: number\n usage?: number\n metadata?: Record<string, any>\n}\n\n/**\n * Feature entitlement\n */\nexport interface FeatureEntitlement {\n feature_key: string\n feature_title: string\n feature_type: 'boolean_flag' | 'usage_quota' | 'numeric_limit'\n granted_at: string\n product_name: string\n subscription_status: string\n properties?: Record<string, any>\n}\n\n/**\n * Usage metric\n */\nexport interface UsageMetric {\n feature_key: string\n feature_title: string\n product_name: string\n consumed: number\n limit: number\n remaining: number\n percentage_used: number\n period_start: string\n period_end: string\n resets_in_days: number\n}\n\n/**\n * Hook to check if user has access to a feature\n */\nexport function useFeature(featureKey: string, options?: {\n refetchInterval?: number\n enabled?: boolean\n}) {\n const { client } = useBillingOS()\n\n return useQuery<FeatureAccess>({\n queryKey: ['billingos', 'features', featureKey],\n queryFn: async () => {\n return await client!.get<FeatureAccess>(\n `/v1/features/check?feature_key=${featureKey}`\n )\n },\n refetchInterval: options?.refetchInterval,\n enabled: !!client && options?.enabled !== false,\n })\n}\n\n/**\n * Hook to track usage for a feature\n */\nexport function useTrackUsage() {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async ({\n featureKey,\n quantity,\n metadata\n }: {\n featureKey: string\n quantity: number\n metadata?: Record<string, any>\n }) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return await client.post('/v1/features/track-usage', {\n feature_key: featureKey,\n quantity,\n metadata,\n })\n },\n onSuccess: (_, variables) => {\n // Invalidate the feature check query to refresh usage\n queryClient.invalidateQueries({\n queryKey: ['billingos', 'features', variables.featureKey]\n })\n // Also invalidate usage metrics\n queryClient.invalidateQueries({\n queryKey: ['billingos', 'usage-metrics']\n })\n },\n })\n}\n\n/**\n * Hook to get all feature entitlements for the current user\n */\nexport function useFeatureEntitlements() {\n const { client } = useBillingOS()\n\n return useQuery<{ entitlements: FeatureEntitlement[] }>({\n queryKey: ['billingos', 'entitlements'],\n queryFn: async () => {\n return await client!.get<{ entitlements: FeatureEntitlement[] }>(\n '/v1/features/entitlements'\n )\n },\n enabled: !!client,\n })\n}\n\n/**\n * Hook to get usage metrics for features\n */\nexport function useUsageMetrics(featureKey?: string) {\n const { client } = useBillingOS()\n\n return useQuery<{ metrics: UsageMetric[] }>({\n queryKey: ['billingos', 'usage-metrics', featureKey],\n queryFn: async () => {\n const url = featureKey\n ? `/v1/features/usage-metrics?feature_key=${featureKey}`\n : '/v1/features/usage-metrics'\n return await client!.get<{ metrics: UsageMetric[] }>(url)\n },\n enabled: !!client,\n // Refresh every 30 seconds to keep usage data fresh\n refetchInterval: 30000,\n })\n}\n\n/**\n * Hook that combines feature access check and tracks when access is denied\n */\nexport function useFeatureGate(featureKey: string, options?: {\n onAccessDenied?: () => void\n onQuotaExceeded?: (usage: number, limit: number) => void\n}) {\n const feature = useFeature(featureKey)\n\n // Call callbacks when access is denied\n if (feature.data && !feature.data.has_access) {\n if (feature.data.usage && feature.data.limit && feature.data.usage >= feature.data.limit) {\n options?.onQuotaExceeded?.(feature.data.usage, feature.data.limit)\n } else {\n options?.onAccessDenied?.()\n }\n }\n\n return {\n ...feature,\n hasAccess: feature.data?.has_access || false,\n isQuotaExceeded: feature.data?.usage && feature.data.limit\n ? feature.data.usage >= feature.data.limit\n : false,\n usage: feature.data?.usage || 0,\n limit: feature.data?.limit || 0,\n remaining: feature.data?.limit && feature.data?.usage\n ? Math.max(0, feature.data.limit - feature.data.usage)\n : 0,\n }\n}","\"use client\";\nimport { useQuery } from '@tanstack/react-query'\nimport { useBillingOS } from '../providers/BillingOSProvider'\n\nexport interface Product {\n id: string\n name: string\n description?: string\n features?: string[]\n prices?: Price[]\n}\n\nexport interface Price {\n id: string\n amount: number\n currency: string\n interval?: string\n interval_count?: number\n}\n\n/**\n * Hook to fetch products for pricing table\n */\nexport function useProducts() {\n const { client } = useBillingOS()\n\n return useQuery<{ products: Product[] }>({\n queryKey: ['billingos', 'products'],\n queryFn: async () => {\n return await client!.get<{ products: Product[] }>('/v1/products')\n },\n enabled: !!client,\n })\n}","\"use client\";\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\nconst alertVariants = cva(\n 'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',\n {\n variants: {\n variant: {\n default: 'bg-background text-foreground',\n destructive:\n 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',\n warning:\n 'border-yellow-500/50 bg-yellow-50 text-yellow-900 dark:bg-yellow-900/10 dark:text-yellow-500 [&>svg]:text-yellow-500',\n success:\n 'border-green-500/50 bg-green-50 text-green-900 dark:bg-green-900/10 dark:text-green-500 [&>svg]:text-green-500',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n)\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n))\nAlert.displayName = 'Alert'\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn('mb-1 font-medium leading-none tracking-tight', className)}\n {...props}\n />\n))\nAlertTitle.displayName = 'AlertTitle'\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-sm [&_p]:leading-relaxed', className)}\n {...props}\n />\n))\nAlertDescription.displayName = 'AlertDescription'\n\nexport { Alert, AlertTitle, AlertDescription }\n","\"use client\";\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\nconst badgeVariants = cva(\n 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',\n {\n variants: {\n variant: {\n default:\n 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',\n secondary:\n 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',\n destructive:\n 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',\n outline: 'text-foreground',\n success:\n 'border-transparent bg-green-500 text-white hover:bg-green-500/80',\n warning:\n 'border-transparent bg-yellow-500 text-white hover:bg-yellow-500/80',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\n )\n}\n\nexport { Badge, badgeVariants }\n","\"use client\";\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive:\n 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline:\n 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n return (\n <button\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n )\n }\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\nconst Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'rounded-lg border bg-card text-card-foreground shadow-sm',\n className\n )}\n {...props}\n />\n))\nCard.displayName = 'Card'\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex flex-col space-y-1.5 p-6', className)}\n {...props}\n />\n))\nCardHeader.displayName = 'CardHeader'\n\nconst CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'text-2xl font-semibold leading-none tracking-tight',\n className\n )}\n {...props}\n />\n))\nCardTitle.displayName = 'CardTitle'\n\nconst CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nCardDescription.displayName = 'CardDescription'\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />\n))\nCardContent.displayName = 'CardContent'\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center p-6 pt-0', className)}\n {...props}\n />\n))\nCardFooter.displayName = 'CardFooter'\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {\n onCheckedChange?: (checked: boolean) => void\n}\n\nconst Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n ({ className, onCheckedChange, onChange, ...props }, ref) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange?.(e)\n onCheckedChange?.(e.target.checked)\n }\n\n return (\n <input\n type=\"checkbox\"\n ref={ref}\n onChange={handleChange}\n className={cn(\n 'peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 checked:bg-primary checked:text-primary-foreground',\n className\n )}\n {...props}\n />\n )\n }\n)\nCheckbox.displayName = 'Checkbox'\n\nexport { Checkbox }\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface DrawerContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n}\n\nconst DrawerContext = React.createContext<DrawerContextValue | null>(null)\n\nfunction useDrawerContext() {\n const context = React.useContext(DrawerContext)\n if (!context) {\n throw new Error('Drawer components must be used within a Drawer provider')\n }\n return context\n}\n\ninterface DrawerProps {\n open?: boolean\n onOpenChange?: (open: boolean) => void\n children: React.ReactNode\n}\n\nfunction Drawer({ open = false, onOpenChange, children }: DrawerProps) {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const isOpen = open ?? internalOpen\n const handleOpenChange = onOpenChange ?? setInternalOpen\n\n // Debug logging\n React.useEffect(() => {\n console.log('[Drawer] State:', { open, internalOpen, isOpen })\n }, [open, internalOpen, isOpen])\n\n return (\n <DrawerContext.Provider value={{ open: isOpen, onOpenChange: handleOpenChange }}>\n {children}\n </DrawerContext.Provider>\n )\n}\n\ninterface DrawerTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean\n}\n\nconst DrawerTrigger = React.forwardRef<HTMLButtonElement, DrawerTriggerProps>(\n ({ onClick, ...props }, ref) => {\n const { onOpenChange } = useDrawerContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(true)\n onClick?.(e)\n }}\n {...props}\n />\n )\n }\n)\nDrawerTrigger.displayName = 'DrawerTrigger'\n\nconst DrawerClose = React.forwardRef<\n HTMLButtonElement,\n React.ButtonHTMLAttributes<HTMLButtonElement>\n>(({ onClick, ...props }, ref) => {\n const { onOpenChange } = useDrawerContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(false)\n onClick?.(e)\n }}\n {...props}\n />\n )\n})\nDrawerClose.displayName = 'DrawerClose'\n\nconst DrawerOverlay = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const { onOpenChange } = useDrawerContext()\n\n return (\n <div\n ref={ref}\n onClick={() => onOpenChange(false)}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 transition-opacity duration-300',\n className\n )}\n {...props}\n />\n )\n})\nDrawerOverlay.displayName = 'DrawerOverlay'\n\ninterface DrawerContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Whether to prevent closing when clicking outside or pressing ESC\n */\n preventClose?: boolean\n /**\n * Callback when user attempts to close but it's prevented\n */\n onCloseAttempt?: () => void\n}\n\nconst DrawerContent = React.forwardRef<HTMLDivElement, DrawerContentProps>(\n ({ className, children, preventClose = false, onCloseAttempt, ...props }, ref) => {\n const { open, onOpenChange } = useDrawerContext()\n const [isDragging, setIsDragging] = React.useState(false)\n const [dragY, setDragY] = React.useState(0)\n const contentRef = React.useRef<HTMLDivElement>(null)\n const startYRef = React.useRef(0)\n\n // Handle escape key\n React.useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n if (preventClose) {\n onCloseAttempt?.()\n } else {\n onOpenChange(false)\n }\n }\n }\n if (open) {\n document.addEventListener('keydown', handleEscape)\n document.body.style.overflow = 'hidden'\n }\n return () => {\n document.removeEventListener('keydown', handleEscape)\n document.body.style.overflow = ''\n }\n }, [open, onOpenChange, preventClose, onCloseAttempt])\n\n // Handle drag to close (mobile)\n const handleDragStart = (e: React.TouchEvent | React.MouseEvent) => {\n if (preventClose) return\n setIsDragging(true)\n const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY\n startYRef.current = clientY\n }\n\n const handleDragMove = (e: React.TouchEvent | React.MouseEvent) => {\n if (!isDragging || preventClose) return\n const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY\n const delta = clientY - startYRef.current\n if (delta > 0) {\n setDragY(delta)\n }\n }\n\n const handleDragEnd = () => {\n if (!isDragging) return\n setIsDragging(false)\n // Close if dragged more than 80px\n if (dragY > 80 && !preventClose) {\n onOpenChange(false)\n }\n setDragY(0)\n }\n\n const handleOverlayClick = () => {\n if (preventClose) {\n onCloseAttempt?.()\n } else {\n onOpenChange(false)\n }\n }\n\n // Debug logging\n console.log('[DrawerContent] Rendering, open:', open, 'preventClose:', preventClose)\n\n if (!open) {\n console.log('[DrawerContent] Not rendering because open is false')\n return null\n }\n\n return (\n <div className=\"fixed inset-0 z-50\">\n <div\n className=\"fixed inset-0 bg-black/80 transition-opacity duration-300\"\n onClick={handleOverlayClick}\n />\n <div\n ref={ref}\n className={cn(\n // Base styles\n 'fixed z-50 bg-background shadow-lg transition-transform duration-300 ease-out',\n // Mobile: bottom sheet\n 'inset-x-0 bottom-0 rounded-t-[10px] border-t',\n // Desktop: centered modal\n 'md:inset-auto md:left-1/2 md:top-1/2 md:-translate-x-1/2 md:-translate-y-1/2',\n 'md:rounded-lg md:border md:max-w-[500px] md:w-full md:max-h-[90vh]',\n className\n )}\n style={{\n transform: isDragging ? `translateY(${dragY}px)` : undefined,\n }}\n onClick={(e) => e.stopPropagation()}\n onTouchStart={handleDragStart}\n onTouchMove={handleDragMove}\n onTouchEnd={handleDragEnd}\n onMouseDown={handleDragStart}\n onMouseMove={handleDragMove}\n onMouseUp={handleDragEnd}\n onMouseLeave={handleDragEnd}\n {...props}\n >\n {/* Drag handle (mobile only) */}\n <div className=\"md:hidden flex justify-center pt-4 pb-2\">\n <div className=\"w-12 h-1.5 rounded-full bg-muted-foreground/30\" />\n </div>\n {/* Close button */}\n <button\n type=\"button\"\n onClick={() => {\n if (preventClose) {\n onCloseAttempt?.()\n } else {\n onOpenChange(false)\n }\n }}\n className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"h-4 w-4\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n <span className=\"sr-only\">Close</span>\n </button>\n <div ref={contentRef} className=\"px-6 pb-6 pt-2 md:pt-6 overflow-y-auto max-h-[80vh] md:max-h-[calc(90vh-2rem)]\">\n {children}\n </div>\n </div>\n </div>\n )\n }\n)\nDrawerContent.displayName = 'DrawerContent'\n\nconst DrawerHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)}\n {...props}\n />\n)\nDrawerHeader.displayName = 'DrawerHeader'\n\nconst DrawerFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}\n {...props}\n />\n)\nDrawerFooter.displayName = 'DrawerFooter'\n\nconst DrawerTitle = React.forwardRef<\n HTMLHeadingElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn('text-lg font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n))\nDrawerTitle.displayName = 'DrawerTitle'\n\nconst DrawerDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nDrawerDescription.displayName = 'DrawerDescription'\n\nexport {\n Drawer,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n}\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = 'Input'\n\nexport { Input }\n","\"use client\";\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\nconst labelVariants = cva(\n 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'\n)\n\nexport interface LabelProps\n extends React.LabelHTMLAttributes<HTMLLabelElement>,\n VariantProps<typeof labelVariants> {}\n\nconst Label = React.forwardRef<HTMLLabelElement, LabelProps>(\n ({ className, ...props }, ref) => (\n <label ref={ref} className={cn(labelVariants(), className)} {...props} />\n )\n)\nLabel.displayName = 'Label'\n\nexport { Label }\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface ProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: number\n max?: number\n indicatorClassName?: string\n}\n\nconst Progress = React.forwardRef<HTMLDivElement, ProgressProps>(\n ({ className, value = 0, max = 100, indicatorClassName, ...props }, ref) => {\n const percentage = Math.min(Math.max((value / max) * 100, 0), 100)\n\n return (\n <div\n ref={ref}\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={value}\n className={cn(\n 'relative h-4 w-full overflow-hidden rounded-full bg-secondary',\n className\n )}\n {...props}\n >\n <div\n className={cn(\n 'h-full bg-primary transition-all',\n indicatorClassName\n )}\n style={{ width: `${percentage}%` }}\n />\n </div>\n )\n }\n)\nProgress.displayName = 'Progress'\n\nexport { Progress }\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface RadioGroupContextValue {\n value: string\n onValueChange: (value: string) => void\n name: string\n}\n\nconst RadioGroupContext = React.createContext<RadioGroupContextValue | null>(null)\n\nfunction useRadioGroupContext() {\n const context = React.useContext(RadioGroupContext)\n if (!context) {\n throw new Error('RadioGroup components must be used within a RadioGroup provider')\n }\n return context\n}\n\ninterface RadioGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n name?: string\n}\n\nconst RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>(\n ({ className, value, defaultValue, onValueChange, name = 'radio-group', children, ...props }, ref) => {\n const [internalValue, setInternalValue] = React.useState(defaultValue ?? '')\n const currentValue = value ?? internalValue\n const handleValueChange = onValueChange ?? setInternalValue\n\n return (\n <RadioGroupContext.Provider value={{ value: currentValue, onValueChange: handleValueChange, name }}>\n <div\n ref={ref}\n role=\"radiogroup\"\n className={cn('grid gap-2', className)}\n {...props}\n >\n {children}\n </div>\n </RadioGroupContext.Provider>\n )\n }\n)\nRadioGroup.displayName = 'RadioGroup'\n\ninterface RadioGroupItemProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {\n value: string\n}\n\nconst RadioGroupItem = React.forwardRef<HTMLInputElement, RadioGroupItemProps>(\n ({ className, value, ...props }, ref) => {\n const { value: groupValue, onValueChange, name } = useRadioGroupContext()\n const isChecked = groupValue === value\n\n return (\n <input\n ref={ref}\n type=\"radio\"\n name={name}\n value={value}\n checked={isChecked}\n onChange={() => onValueChange(value)}\n className={cn(\n 'aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n {...props}\n />\n )\n }\n)\nRadioGroupItem.displayName = 'RadioGroupItem'\n\nexport { RadioGroup, RadioGroupItem }\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface ScrollAreaProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * The orientation of the scrollable area\n */\n orientation?: 'vertical' | 'horizontal' | 'both'\n \n /**\n * Always show the custom scrollbar (instead of only on hover)\n */\n alwaysShowScrollbar?: boolean\n}\n\nconst ScrollArea = React.forwardRef<HTMLDivElement, ScrollAreaProps>(\n ({ className, children, orientation = 'vertical', alwaysShowScrollbar = false, ...props }, ref) => {\n const [showScrollbar, setShowScrollbar] = React.useState(false)\n const [scrollbarHeight, setScrollbarHeight] = React.useState(0)\n const [scrollbarTop, setScrollbarTop] = React.useState(0)\n const viewportRef = React.useRef<HTMLDivElement>(null)\n\n const handleScroll = React.useCallback(() => {\n const viewport = viewportRef.current\n if (!viewport) return\n\n const { scrollTop, scrollHeight, clientHeight } = viewport\n\n // Only show scrollbar if there's actually scrollable content\n const hasScrollableContent = scrollHeight > clientHeight\n \n if (!hasScrollableContent && !alwaysShowScrollbar) {\n setScrollbarHeight(0)\n setScrollbarTop(0)\n return\n }\n\n // Calculate scrollbar dimensions\n const scrollRatio = clientHeight / scrollHeight\n const thumbHeight = Math.max(scrollRatio * clientHeight, 30) // Min 30px\n const maxScrollTop = scrollHeight - clientHeight\n const scrollProgress = maxScrollTop > 0 ? scrollTop / maxScrollTop : 0\n const maxThumbTop = clientHeight - thumbHeight\n const thumbTop = scrollProgress * maxThumbTop\n\n setScrollbarHeight(hasScrollableContent ? thumbHeight : 0)\n setScrollbarTop(thumbTop)\n }, [alwaysShowScrollbar])\n\n React.useEffect(() => {\n const viewport = viewportRef.current\n if (!viewport) return\n\n // Initial calculation\n handleScroll()\n\n // Create resize observer\n const resizeObserver = new ResizeObserver(handleScroll)\n resizeObserver.observe(viewport)\n\n // Listen for scroll events\n viewport.addEventListener('scroll', handleScroll)\n\n return () => {\n resizeObserver.disconnect()\n viewport.removeEventListener('scroll', handleScroll)\n }\n }, [handleScroll])\n\n const handleScrollbarDrag = React.useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n e.preventDefault()\n const viewport = viewportRef.current\n if (!viewport) return\n\n const { scrollHeight, clientHeight } = viewport\n const maxScrollTop = scrollHeight - clientHeight\n \n if (maxScrollTop <= 0) return // No scrollable content\n\n const scrollbarContainer = e.currentTarget.parentElement?.parentElement\n if (!scrollbarContainer) return\n\n const containerRect = scrollbarContainer.getBoundingClientRect()\n const startY = e.clientY\n const startScrollTop = viewport.scrollTop\n\n const onMouseMove = (moveEvent: MouseEvent) => {\n const deltaY = moveEvent.clientY - startY\n const containerHeight = containerRect.height\n const scrollRatio = deltaY / containerHeight\n const scrollDelta = scrollRatio * maxScrollTop\n \n const newScrollTop = Math.max(0, Math.min(maxScrollTop, startScrollTop + scrollDelta))\n viewport.scrollTop = newScrollTop\n }\n\n const onMouseUp = () => {\n document.removeEventListener('mousemove', onMouseMove)\n document.removeEventListener('mouseup', onMouseUp)\n document.body.style.userSelect = ''\n document.body.style.cursor = ''\n }\n\n document.body.style.userSelect = 'none'\n document.body.style.cursor = 'grabbing'\n document.addEventListener('mousemove', onMouseMove)\n document.addEventListener('mouseup', onMouseUp)\n },\n []\n )\n\n return (\n <div\n ref={ref}\n className={cn('relative overflow-hidden', className)}\n onMouseEnter={() => setShowScrollbar(true)}\n onMouseLeave={() => setShowScrollbar(false)}\n {...props}\n >\n <div\n ref={viewportRef}\n className={cn(\n 'h-full w-full rounded-[inherit]',\n orientation === 'vertical' && 'overflow-y-auto overflow-x-hidden',\n orientation === 'horizontal' && 'overflow-x-auto overflow-y-hidden',\n orientation === 'both' && 'overflow-auto',\n // Hide native scrollbar\n '[&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]'\n )}\n >\n {children}\n </div>\n\n {/* Custom Scrollbar */}\n {(orientation === 'vertical' || orientation === 'both') && (\n <div\n className={cn(\n 'absolute top-0 right-0 w-2.5 h-full transition-opacity duration-150',\n alwaysShowScrollbar || showScrollbar ? 'opacity-100' : 'opacity-0'\n )}\n >\n <div className=\"relative h-full w-full\">\n {/* Track - Make it visible */}\n <div className=\"absolute inset-0 rounded-full bg-gray-100 hover:bg-gray-200\" />\n {/* Thumb */}\n {scrollbarHeight > 0 && (\n <div\n className=\"absolute right-0.5 w-1.5 rounded-full bg-gray-400 hover:bg-gray-600 transition-colors cursor-pointer\"\n style={{\n height: `${scrollbarHeight}px`,\n top: `${scrollbarTop}px`,\n }}\n onMouseDown={handleScrollbarDrag}\n />\n )}\n </div>\n </div>\n )}\n </div>\n )\n }\n)\nScrollArea.displayName = 'ScrollArea'\n\nconst ScrollBar = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & {\n orientation?: 'vertical' | 'horizontal'\n }\n>(({ className, orientation = 'vertical', ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex touch-none select-none transition-colors',\n orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-[1px]',\n orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-[1px]',\n className\n )}\n {...props}\n />\n))\nScrollBar.displayName = 'ScrollBar'\n\nexport { ScrollArea, ScrollBar }\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {\n onValueChange?: (value: string) => void\n}\n\nconst Select = React.forwardRef<HTMLSelectElement, SelectProps>(\n ({ className, children, onValueChange, onChange, ...props }, ref) => {\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n onChange?.(e)\n onValueChange?.(e.target.value)\n }\n\n return (\n <select\n ref={ref}\n onChange={handleChange}\n className={cn(\n 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n {...props}\n >\n {children}\n </select>\n )\n }\n)\nSelect.displayName = 'Select'\n\nconst SelectOption = React.forwardRef<\n HTMLOptionElement,\n React.OptionHTMLAttributes<HTMLOptionElement>\n>(({ className, ...props }, ref) => (\n <option ref={ref} className={cn('', className)} {...props} />\n))\nSelectOption.displayName = 'SelectOption'\n\nexport { Select, SelectOption }\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface SeparatorProps extends React.HTMLAttributes<HTMLDivElement> {\n orientation?: 'horizontal' | 'vertical'\n decorative?: boolean\n}\n\nconst Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(\n (\n { className, orientation = 'horizontal', decorative = true, ...props },\n ref\n ) => (\n <div\n ref={ref}\n role={decorative ? 'none' : 'separator'}\n aria-orientation={decorative ? undefined : orientation}\n className={cn(\n 'shrink-0 bg-border',\n orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',\n className\n )}\n {...props}\n />\n )\n)\nSeparator.displayName = 'Separator'\n\nexport { Separator }\n","\"use client\";\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/utils/cn'\n\ninterface SheetContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n}\n\nconst SheetContext = React.createContext<SheetContextValue | null>(null)\n\nfunction useSheetContext() {\n const context = React.useContext(SheetContext)\n if (!context) {\n throw new Error('Sheet components must be used within a Sheet provider')\n }\n return context\n}\n\ninterface SheetProps {\n open?: boolean\n onOpenChange?: (open: boolean) => void\n children: React.ReactNode\n}\n\nfunction Sheet({ open = false, onOpenChange, children }: SheetProps) {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const isOpen = open ?? internalOpen\n const handleOpenChange = onOpenChange ?? setInternalOpen\n\n return (\n <SheetContext.Provider value={{ open: isOpen, onOpenChange: handleOpenChange }}>\n {children}\n </SheetContext.Provider>\n )\n}\n\ninterface SheetTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean\n}\n\nconst SheetTrigger = React.forwardRef<HTMLButtonElement, SheetTriggerProps>(\n ({ onClick, ...props }, ref) => {\n const { onOpenChange } = useSheetContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(true)\n onClick?.(e)\n }}\n {...props}\n />\n )\n }\n)\nSheetTrigger.displayName = 'SheetTrigger'\n\nconst SheetClose = React.forwardRef<\n HTMLButtonElement,\n React.ButtonHTMLAttributes<HTMLButtonElement>\n>(({ onClick, ...props }, ref) => {\n const { onOpenChange } = useSheetContext()\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={(e) => {\n onOpenChange(false)\n onClick?.(e)\n }}\n {...props}\n />\n )\n})\nSheetClose.displayName = 'SheetClose'\n\nconst SheetOverlay = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const { onOpenChange } = useSheetContext()\n\n return (\n <div\n ref={ref}\n onClick={() => onOpenChange(false)}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 transition-opacity',\n className\n )}\n {...props}\n />\n )\n})\nSheetOverlay.displayName = 'SheetOverlay'\n\nconst sheetVariants = cva(\n 'fixed z-50 gap-4 bg-background p-6 shadow-lg transition-transform duration-300 ease-in-out',\n {\n variants: {\n side: {\n top: 'inset-x-0 top-0 border-b',\n bottom: 'inset-x-0 bottom-0 border-t',\n left: 'inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',\n right: 'inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',\n },\n },\n defaultVariants: {\n side: 'right',\n },\n }\n)\n\ninterface SheetContentProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof sheetVariants> {}\n\nconst SheetContent = React.forwardRef<HTMLDivElement, SheetContentProps>(\n ({ side = 'right', className, children, ...props }, ref) => {\n const { open, onOpenChange } = useSheetContext()\n\n // Handle escape key\n React.useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onOpenChange(false)\n }\n }\n if (open) {\n document.addEventListener('keydown', handleEscape)\n document.body.style.overflow = 'hidden'\n }\n return () => {\n document.removeEventListener('keydown', handleEscape)\n document.body.style.overflow = ''\n }\n }, [open, onOpenChange])\n\n if (!open) return null\n\n const getTransform = () => {\n switch (side) {\n case 'top':\n return open ? 'translateY(0)' : 'translateY(-100%)'\n case 'bottom':\n return open ? 'translateY(0)' : 'translateY(100%)'\n case 'left':\n return open ? 'translateX(0)' : 'translateX(-100%)'\n case 'right':\n return open ? 'translateX(0)' : 'translateX(100%)'\n default:\n return 'translateX(0)'\n }\n }\n\n return (\n <div className=\"fixed inset-0 z-50\">\n <SheetOverlay />\n <div\n ref={ref}\n style={{ transform: getTransform() }}\n className={cn(sheetVariants({ side }), className)}\n onClick={(e) => e.stopPropagation()}\n {...props}\n >\n {children}\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"h-4 w-4\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n <span className=\"sr-only\">Close</span>\n </button>\n </div>\n </div>\n )\n }\n)\nSheetContent.displayName = 'SheetContent'\n\nconst SheetHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col space-y-2 text-center sm:text-left',\n className\n )}\n {...props}\n />\n)\nSheetHeader.displayName = 'SheetHeader'\n\nconst SheetFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n className\n )}\n {...props}\n />\n)\nSheetFooter.displayName = 'SheetFooter'\n\nconst SheetTitle = React.forwardRef<\n HTMLHeadingElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn('text-lg font-semibold text-foreground', className)}\n {...props}\n />\n))\nSheetTitle.displayName = 'SheetTitle'\n\nconst SheetDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nSheetDescription.displayName = 'SheetDescription'\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n","\"use client\";\nimport { cn } from '@/utils/cn'\n\nfunction Skeleton({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn('animate-pulse rounded-md bg-muted', className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n","\"use client\";\nimport { cn } from '../../utils/cn'\n\nexport interface SwitchProps {\n checked: boolean\n onCheckedChange: (checked: boolean) => void\n className?: string\n 'aria-label'?: string\n 'data-testid'?: string\n}\n\nexport function Switch({ checked, onCheckedChange, className, ...props }: SwitchProps) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n onClick={() => onCheckedChange(!checked)}\n className={cn(\n 'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n checked ? 'bg-blue-600' : 'bg-gray-300',\n className\n )}\n {...props}\n >\n <span\n className={cn(\n 'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out',\n checked ? 'translate-x-5' : 'translate-x-0'\n )}\n />\n </button>\n )\n}\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\ninterface TabsContextValue {\n value: string\n onValueChange: (value: string) => void\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null)\n\nfunction useTabsContext() {\n const context = React.useContext(TabsContext)\n if (!context) {\n throw new Error('Tabs components must be used within a Tabs provider')\n }\n return context\n}\n\ninterface TabsProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n}\n\nconst Tabs = React.forwardRef<HTMLDivElement, TabsProps>(\n ({ className, value, defaultValue, onValueChange, children, ...props }, ref) => {\n const [internalValue, setInternalValue] = React.useState(defaultValue ?? '')\n const currentValue = value ?? internalValue\n const handleValueChange = onValueChange ?? setInternalValue\n\n return (\n <TabsContext.Provider value={{ value: currentValue, onValueChange: handleValueChange }}>\n <div ref={ref} className={cn('', className)} {...props}>\n {children}\n </div>\n </TabsContext.Provider>\n )\n }\n)\nTabs.displayName = 'Tabs'\n\nconst TabsList = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"tablist\"\n className={cn(\n 'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',\n className\n )}\n {...props}\n />\n))\nTabsList.displayName = 'TabsList'\n\ninterface TabsTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n value: string\n}\n\nconst TabsTrigger = React.forwardRef<HTMLButtonElement, TabsTriggerProps>(\n ({ className, value, ...props }, ref) => {\n const { value: currentValue, onValueChange } = useTabsContext()\n const isSelected = currentValue === value\n\n return (\n <button\n ref={ref}\n role=\"tab\"\n type=\"button\"\n aria-selected={isSelected}\n data-state={isSelected ? 'active' : 'inactive'}\n onClick={() => onValueChange(value)}\n className={cn(\n 'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n isSelected\n ? 'bg-background text-foreground shadow-sm'\n : 'hover:bg-background/50 hover:text-foreground',\n className\n )}\n {...props}\n />\n )\n }\n)\nTabsTrigger.displayName = 'TabsTrigger'\n\ninterface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string\n}\n\nconst TabsContent = React.forwardRef<HTMLDivElement, TabsContentProps>(\n ({ className, value, children, ...props }, ref) => {\n const { value: currentValue } = useTabsContext()\n const isSelected = currentValue === value\n\n if (!isSelected) return null\n\n return (\n <div\n ref={ref}\n role=\"tabpanel\"\n data-state={isSelected ? 'active' : 'inactive'}\n className={cn(\n 'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n }\n)\nTabsContent.displayName = 'TabsContent'\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n","\"use client\";\nimport * as React from 'react'\nimport { cn } from '@/utils/cn'\n\nconst Textarea = React.forwardRef<\n HTMLTextAreaElement,\n React.ComponentProps<'textarea'>\n>(({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n 'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n className\n )}\n ref={ref}\n {...props}\n />\n )\n})\nTextarea.displayName = 'Textarea'\n\nexport { Textarea }\n","\"use client\";\nimport { useState, useEffect, useRef, useCallback } from 'react'\nimport { Sheet, SheetContent, SheetHeader, SheetTitle } from '../ui/sheet'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog'\nimport { PortalIframe } from './PortalIframe'\nimport { usePortalSession } from './hooks/usePortalSession'\nimport { usePortalMessaging, IframeMessage } from './hooks/usePortalMessaging'\nimport { PricingTable } from '../PricingTable'\nimport { cn } from '../../utils/cn'\nimport { Alert, AlertDescription } from '../ui/alert'\n\ntype PortalState = 'loading' | 'ready' | 'error'\ntype PortalTab = 'subscription' | 'invoices' | 'payment' | 'settings'\n\nexport interface CustomerPortalProps {\n /**\n * Open/close state (for drawer/modal mode)\n */\n isOpen?: boolean\n\n /**\n * Callback when user closes portal\n */\n onClose?: () => void\n\n /**\n * Display mode\n * - 'drawer': Slide-in from right (default)\n * - 'modal': Centered modal\n * - 'page': Full-page view\n */\n mode?: 'drawer' | 'modal' | 'page'\n\n /**\n * Default tab to show\n */\n defaultTab?: PortalTab\n\n /**\n * Optional: Custom theme\n */\n theme?: 'light' | 'dark'\n\n /**\n * Optional: Custom class name\n */\n className?: string\n\n /**\n * Optional: Customer ID to load specific customer\n */\n customerId?: string\n\n /**\n * Optional: Custom metadata\n */\n metadata?: Record<string, any>\n\n /**\n * Callback when subscription is updated\n */\n onSubscriptionUpdate?: (subscription: any) => void\n\n /**\n * Callback when subscription is cancelled\n */\n onSubscriptionCancel?: () => void\n\n /**\n * Callback when payment method is added\n */\n onPaymentMethodAdd?: () => void\n\n /**\n * Callback when payment method is updated\n */\n onPaymentMethodUpdate?: () => void\n\n /**\n * Debug mode for development\n */\n debug?: boolean\n}\n\nexport function CustomerPortal({\n isOpen = false,\n onClose,\n mode = 'drawer',\n defaultTab = 'subscription',\n theme = 'light',\n className,\n customerId,\n metadata,\n onSubscriptionUpdate,\n onSubscriptionCancel,\n onPaymentMethodAdd,\n onPaymentMethodUpdate,\n debug = false\n}: CustomerPortalProps) {\n const [state, setState] = useState<PortalState>('loading')\n const [error, setError] = useState<Error | null>(null)\n const [iframeHeight, setIframeHeight] = useState(600)\n const [showPricingTable, setShowPricingTable] = useState(false)\n const [portalCustomer, setPortalCustomer] = useState<{ email?: string; name?: string } | null>(null)\n const iframeRef = useRef<HTMLIFrameElement>(null)\n\n // Log version on mount (only once)\n useEffect(() => {\n console.log(\n '%c🚀 BillingOS SDK v1.2.0 - Iframe Customer Portal with Smart Pricing Table',\n 'background: linear-gradient(to right, #667eea, #764ba2); color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;'\n )\n console.log('%c📦 Using iframe for instant updates and security', 'color: #10b981; font-weight: 600;')\n console.log('%c🎨 Supports drawer, modal, and page modes', 'color: #8b5cf6; font-weight: 600;')\n if (debug) {\n console.log('[CustomerPortal] Debug mode enabled')\n }\n }, [])\n\n // Create portal session when opened\n const isOpenOrPage = mode === 'page' || isOpen\n const { sessionId, sessionUrl, loading, error: sessionError } = usePortalSession({\n enabled: isOpenOrPage,\n customerId,\n metadata\n })\n\n // Handle iframe messaging\n const handleIframeMessage = useCallback((message: IframeMessage) => {\n if (debug) {\n console.log('[CustomerPortal] Received message from iframe:', message.type, message)\n }\n\n switch (message.type) {\n case 'PORTAL_READY':\n console.log('[CustomerPortal] Portal is ready')\n setState('ready')\n break\n\n case 'PORTAL_CLOSE':\n console.log('[CustomerPortal] User requested close')\n onClose?.()\n break\n\n case 'SUBSCRIPTION_UPDATED':\n console.log('[CustomerPortal] Subscription updated')\n onSubscriptionUpdate?.(message.payload)\n break\n\n case 'SUBSCRIPTION_CANCELLED':\n console.log('[CustomerPortal] Subscription cancelled')\n onSubscriptionCancel?.()\n break\n\n case 'PAYMENT_METHOD_ADDED':\n console.log('[CustomerPortal] Payment method added')\n onPaymentMethodAdd?.()\n break\n\n case 'PAYMENT_METHOD_UPDATED':\n console.log('[CustomerPortal] Payment method updated')\n onPaymentMethodUpdate?.()\n break\n\n case 'HEIGHT_CHANGED':\n if (message.payload?.height) {\n setIframeHeight(message.payload.height)\n if (debug) {\n console.log('[CustomerPortal] Height changed to:', message.payload.height)\n }\n }\n break\n\n case 'OPEN_PRICING_TABLE':\n console.log('[CustomerPortal] Opening pricing table for plan change')\n if (message.payload?.customer) {\n console.log('[CustomerPortal] Received customer data for prefill:', message.payload.customer)\n setPortalCustomer(message.payload.customer)\n }\n setShowPricingTable(true)\n break\n\n case 'CLOSE_PRICING_TABLE':\n console.log('[CustomerPortal] Closing pricing table')\n setShowPricingTable(false)\n break\n\n case 'ERROR':\n setState('error')\n const errorMessage = message.payload?.error || 'An error occurred'\n const err = new Error(errorMessage)\n setError(err)\n break\n\n default:\n break\n }\n }, [debug, onClose, onSubscriptionUpdate, onSubscriptionCancel, onPaymentMethodAdd, onPaymentMethodUpdate])\n\n const { sendMessage } = usePortalMessaging({\n iframeRef,\n onMessage: handleIframeMessage,\n debug\n })\n\n // Send initialization message when iframe is ready\n useEffect(() => {\n if (sessionId && state === 'ready') {\n sendMessage({\n type: 'INIT_PORTAL',\n sessionId,\n config: {\n theme,\n defaultTab\n }\n })\n }\n }, [sessionId, state, theme, defaultTab, sendMessage])\n\n // Reset state when closed\n useEffect(() => {\n if (!isOpenOrPage) {\n setState('loading')\n setError(null)\n setIframeHeight(600)\n }\n }, [isOpenOrPage])\n\n // Handle session creation error\n useEffect(() => {\n if (sessionError) {\n setState('error')\n setError(sessionError)\n }\n }, [sessionError])\n\n const showSpinner = loading || state === 'loading'\n const showError = state === 'error' && error\n\n // Portal content\n const portalContent = (\n <>\n {/* Iframe Badge */}\n <div className=\"absolute top-2 right-2 z-20 flex items-center gap-1 bg-gradient-to-r from-blue-600 to-purple-600 text-white text-xs font-medium px-2 py-1 rounded-full shadow-lg\">\n <svg className=\"w-3 h-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clipRule=\"evenodd\" />\n </svg>\n <span>Secure Iframe</span>\n </div>\n\n {showError ? (\n <div className=\"p-8\">\n <Alert variant=\"destructive\">\n <AlertDescription>{error.message}</AlertDescription>\n </Alert>\n </div>\n ) : (\n <>\n {showSpinner && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white z-10\">\n <div className=\"flex flex-col items-center\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600\"></div>\n <p className=\"mt-4 text-gray-600 font-medium\">Loading portal...</p>\n <p className=\"mt-2 text-xs text-gray-500\">Iframe-based • Always up-to-date</p>\n </div>\n </div>\n )}\n\n {sessionUrl && (\n <PortalIframe\n ref={iframeRef}\n src={sessionUrl}\n height={iframeHeight}\n className={cn(\n \"transition-opacity duration-300\",\n showSpinner ? \"opacity-0\" : \"opacity-100\"\n )}\n onLoad={() => {\n console.log(\n '%c✅ Portal iframe loaded successfully',\n 'color: #10b981; font-weight: 600;',\n `\\nURL: ${sessionUrl}`\n )\n if (debug) {\n console.log('[CustomerPortal] Full iframe details:', {\n sessionUrl,\n sessionId,\n state,\n height: iframeHeight\n })\n }\n }}\n />\n )}\n </>\n )}\n\n {debug && (\n <div className=\"absolute bottom-0 left-0 right-0 bg-black/80 text-white p-2 text-xs\">\n <div>State: {state}</div>\n <div>Session: {sessionId || 'Creating...'}</div>\n {error && <div>Error: {error.message}</div>}\n </div>\n )}\n </>\n )\n\n // Render based on mode\n const mainPortal = mode === 'page' ? (\n <div className={cn('relative w-full', className)}>\n {portalContent}\n </div>\n ) : mode === 'modal' ? (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onClose?.()}>\n <DialogContent className={cn('sm:max-w-[800px] p-0 overflow-hidden max-h-[90vh] relative', className)}>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>Customer Portal</DialogTitle>\n </DialogHeader>\n {portalContent}\n </DialogContent>\n </Dialog>\n ) : (\n // Default: drawer mode\n <Sheet open={isOpen} onOpenChange={(open) => !open && onClose?.()}>\n <SheetContent\n side=\"right\"\n className={cn('w-full sm:max-w-[600px] p-0 overflow-hidden', className)}\n >\n <SheetHeader className=\"sr-only\">\n <SheetTitle>Customer Portal</SheetTitle>\n </SheetHeader>\n {portalContent}\n </SheetContent>\n </Sheet>\n )\n\n return (\n <>\n {mainPortal}\n\n {/* PricingTable Modal for Plan Changes */}\n <Dialog open={showPricingTable} onOpenChange={setShowPricingTable}>\n <DialogContent className=\"sm:max-w-6xl max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle>Change Your Plan</DialogTitle>\n </DialogHeader>\n <PricingTable\n useCheckoutModal={true}\n theme={theme}\n customer={portalCustomer || undefined}\n onPlanChanged={(subscription) => {\n console.log('[CustomerPortal] Plan changed successfully:', subscription)\n // Close the pricing table\n setShowPricingTable(false)\n // Clear customer data\n setPortalCustomer(null)\n // Send message back to portal iframe to refresh\n sendMessage({\n type: 'UPDATE_CONFIG',\n payload: { refresh: true }\n })\n // Notify parent app\n onSubscriptionUpdate?.(subscription)\n }}\n />\n </DialogContent>\n </Dialog>\n </>\n )\n}\n","\"use client\";\nimport { forwardRef } from 'react'\nimport { cn } from '../../utils/cn'\n\ninterface PortalIframeProps {\n src: string\n height?: number\n className?: string\n onLoad?: () => void\n}\n\nexport const PortalIframe = forwardRef<HTMLIFrameElement, PortalIframeProps>(\n ({ src, height = 600, className, onLoad }, ref) => {\n return (\n <iframe\n ref={ref}\n src={src}\n className={cn('w-full border-0', className)}\n style={{ height: `${height}px` }}\n allow=\"payment\"\n sandbox=\"allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox\"\n onLoad={onLoad}\n title=\"Customer Portal\"\n />\n )\n }\n)\n\nPortalIframe.displayName = 'PortalIframe'\n","\"use client\";\nimport { useState, useEffect } from 'react'\nimport { useBillingOS } from '../../../providers/BillingOSProvider'\n\ninterface UsePortalSessionOptions {\n enabled: boolean\n customerId?: string\n metadata?: Record<string, any>\n}\n\ninterface UsePortalSessionReturn {\n sessionId: string | null\n sessionUrl: string | null\n loading: boolean\n error: Error | null\n refresh: () => Promise<void>\n}\n\nexport function usePortalSession({\n enabled,\n customerId,\n metadata\n}: UsePortalSessionOptions): UsePortalSessionReturn {\n const { client, appUrl, debug } = useBillingOS()\n const [sessionId, setSessionId] = useState<string | null>(null)\n const [sessionUrl, setSessionUrl] = useState<string | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const createSession = async () => {\n if (!enabled || !client) return\n\n if (debug) console.log('[BillingOS] Creating portal session...')\n\n setLoading(true)\n setError(null)\n\n try {\n // Create portal session via API\n const session = await client.portal.createSession({\n customerId,\n metadata\n })\n\n setSessionId(session.id)\n if (debug) console.log('[BillingOS] Portal session created:', session.id)\n\n // Generate iframe URL using appUrl from BillingOSProvider context\n const iframeUrl = `${appUrl}/embed/portal/${session.id}`\n setSessionUrl(iframeUrl)\n\n if (debug) console.log('[BillingOS] Iframe URL:', iframeUrl)\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to create portal session')\n setError(error)\n console.error('[usePortalSession] Error creating session:', error)\n } finally {\n setLoading(false)\n }\n }\n\n // Create session when enabled AND client is ready.\n // client starts as null while the session token is being fetched (sessionTokenUrl),\n // so we depend on client to re-run when the token arrives.\n useEffect(() => {\n if (enabled && client && !sessionId) {\n createSession()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, client])\n\n // Cleanup session when component unmounts\n useEffect(() => {\n return () => {\n // Optionally invalidate session\n // if (sessionId) {\n // client.portal.invalidateSession(sessionId).catch(() => {})\n // }\n }\n }, [sessionId])\n\n const refresh = async () => {\n setSessionId(null)\n setSessionUrl(null)\n await createSession()\n }\n\n return {\n sessionId,\n sessionUrl,\n loading,\n error,\n refresh\n }\n}\n","\"use client\";\nimport { useEffect, useCallback, RefObject } from 'react'\n\nexport interface IframeMessage {\n type:\n | 'PORTAL_READY'\n | 'PORTAL_CLOSE'\n | 'SUBSCRIPTION_UPDATED'\n | 'SUBSCRIPTION_CANCELLED'\n | 'PAYMENT_METHOD_ADDED'\n | 'PAYMENT_METHOD_UPDATED'\n | 'HEIGHT_CHANGED'\n | 'OPEN_PRICING_TABLE'\n | 'CLOSE_PRICING_TABLE'\n | 'ERROR'\n payload?: any\n}\n\nexport interface ParentMessage {\n type: 'INIT_PORTAL' | 'UPDATE_CONFIG' | 'CLOSE_PORTAL'\n sessionId?: string\n config?: {\n theme?: 'light' | 'dark' | 'auto'\n locale?: string\n defaultTab?: string\n }\n payload?: any\n}\n\ninterface UsePortalMessagingOptions {\n iframeRef: RefObject<HTMLIFrameElement | null>\n onMessage: (message: IframeMessage) => void\n debug?: boolean\n}\n\ninterface UsePortalMessagingReturn {\n sendMessage: (message: ParentMessage) => void\n}\n\nexport function usePortalMessaging({\n iframeRef,\n onMessage,\n debug = false\n}: UsePortalMessagingOptions): UsePortalMessagingReturn {\n\n /**\n * Send message to iframe\n */\n const sendMessage = useCallback((message: ParentMessage) => {\n const iframe = iframeRef.current\n if (!iframe || !iframe.contentWindow) {\n console.warn('[usePortalMessaging] Iframe not ready')\n return\n }\n\n if (debug) {\n console.log('[usePortalMessaging] 📤 Sending to iframe:', message)\n }\n\n // Get target origin from iframe src\n const iframeSrc = iframe.src\n const targetOrigin = new URL(iframeSrc).origin\n\n iframe.contentWindow.postMessage(message, targetOrigin)\n }, [iframeRef, debug])\n\n /**\n * Listen for messages from iframe\n */\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n // Validate message structure\n if (!event.data || typeof event.data !== 'object' || !event.data.type) {\n return\n }\n\n // Validate origin (should be from BillingOS app)\n const iframe = iframeRef.current\n if (!iframe) return\n\n const iframeSrc = iframe.src\n if (!iframeSrc) return\n\n const expectedOrigin = new URL(iframeSrc).origin\n if (event.origin !== expectedOrigin && process.env.NODE_ENV !== 'development') {\n console.warn(`[usePortalMessaging] Message from unexpected origin: ${event.origin}`)\n return\n }\n\n const message = event.data as IframeMessage\n\n if (debug) {\n console.log('[usePortalMessaging] 📥 Received from iframe:', message)\n }\n\n onMessage(message)\n }\n\n window.addEventListener('message', handleMessage)\n\n return () => {\n window.removeEventListener('message', handleMessage)\n }\n }, [iframeRef, onMessage, debug])\n\n return {\n sendMessage\n }\n}\n","\"use client\";\nimport * as React from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { Skeleton } from '../ui/skeleton'\nimport { Alert, AlertDescription } from '../ui/alert'\nimport { Button } from '../ui/button'\nimport { Badge } from '../ui/badge'\nimport { Switch } from '../ui/switch'\nimport { cn } from '../../utils/cn'\nimport { useProducts } from './hooks/useProducts'\nimport { PricingCard } from './PricingCard'\nimport { PaymentBottomSheet } from '../PaymentBottomSheet'\nimport { CheckoutModal } from '../CheckoutModal'\nimport { useBillingOS } from '../../providers/BillingOSProvider'\n\nexport interface PricingTableProps {\n planIds?: string[]\n showIntervalToggle?: boolean\n defaultInterval?: 'month' | 'year'\n onSelectPlan?: (priceId: string) => void\n theme?: 'light' | 'dark'\n title?: string\n description?: string\n /** Use the iframe-based checkout modal instead of bottom sheet */\n useCheckoutModal?: boolean\n /** Callback when plan is changed */\n onPlanChanged?: (subscription: any) => void\n /** Customer info to prefill in checkout (overrides context) */\n customer?: { email?: string; name?: string }\n /** Footer note below the cards. Pass null to hide it. */\n footerText?: string | null\n /** Render only the cards — no section wrapper, header, or footer text */\n compact?: boolean\n}\n\n/** Collect all unique features across all products (by feature.name) */\nfunction getAllFeatures(products: Array<{ features: Array<{ name: string; title: string; type: string }> }>) {\n const seen = new Map<string, { name: string; title: string; type: string }>()\n products.forEach((product) => {\n product.features.forEach((f) => {\n if (!seen.has(f.name)) seen.set(f.name, { name: f.name, title: f.title, type: f.type })\n })\n })\n return Array.from(seen.values())\n}\n\nexport function PricingTable({\n planIds,\n showIntervalToggle = true,\n defaultInterval = 'month',\n onSelectPlan,\n theme,\n title = 'Simple, transparent pricing',\n description = 'Choose the perfect plan for your needs. No hidden fees, cancel anytime.',\n useCheckoutModal = false,\n onPlanChanged,\n customer: customerProp,\n footerText = 'All plans include SSL security and 99.9% uptime SLA',\n compact = false,\n}: PricingTableProps) {\n const [isYearly, setIsYearly] = React.useState(defaultInterval === 'year')\n const [selectedPriceId, setSelectedPriceId] = React.useState<string | null>(null)\n const [isPaymentOpen, setIsPaymentOpen] = React.useState(false)\n const [showSuccessMessage, setShowSuccessMessage] = React.useState(false)\n\n const { customerEmail, customerName, debug } = useBillingOS()\n const finalCustomerEmail = customerProp?.email || customerEmail\n const finalCustomerName = customerProp?.name || customerName\n const queryClient = useQueryClient()\n\n const { data, isLoading, error, refetch } = useProducts({ planIds })\n const currentSubscription = data?.currentSubscription ?? null\n\n // Sort by monthly price ascending (free first)\n const products = React.useMemo(() => {\n return [...(data?.products ?? [])].sort((a, b) => {\n const aAmt = a.prices.find((p) => p.interval === 'month')?.amount ?? 0\n const bAmt = b.prices.find((p) => p.interval === 'month')?.amount ?? 0\n return aAmt - bAmt\n })\n }, [data])\n\n const allFeatures = React.useMemo(() => getAllFeatures(products), [products])\n\n const hasYearlyPricing = products.some((p) => p.prices.some((pr) => pr.interval === 'year'))\n\n const selectedInterval = isYearly ? 'year' : 'month'\n\n // Current plan's price amount for upgrade/downgrade comparison\n const currentPlanAmount = React.useMemo(() => {\n const currentProduct = products.find((p) => p.isCurrentPlan)\n return (\n currentProduct?.prices.find((p) => p.interval === selectedInterval)?.amount ??\n currentProduct?.prices[0]?.amount ??\n 0\n )\n }, [products, selectedInterval])\n\n const handleSelectPlan = (priceId: string) => {\n if (onSelectPlan) {\n onSelectPlan(priceId)\n } else {\n setSelectedPriceId(priceId)\n setIsPaymentOpen(true)\n }\n }\n\n const handlePaymentSuccess = React.useCallback(\n async (subscription?: any) => {\n if (debug) console.log('[BillingOS] Payment success:', subscription)\n setIsPaymentOpen(false)\n setSelectedPriceId(null)\n setShowSuccessMessage(true)\n setTimeout(() => setShowSuccessMessage(false), 5000)\n if (onPlanChanged) onPlanChanged(subscription)\n await queryClient.invalidateQueries({ queryKey: ['products'], refetchType: 'all' })\n if (subscription) {\n queryClient.setQueryData(['products', planIds], (oldData: any) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n currentSubscription: subscription,\n products: oldData.products?.map((p: any) => ({\n ...p,\n isCurrentPlan: p.prices?.some((pr: any) => pr.id === subscription.priceId) ?? false,\n })),\n }\n })\n }\n await refetch()\n },\n [debug, queryClient, refetch, planIds, onPlanChanged]\n )\n\n // ── Loading ──────────────────────────────────────────────────────────────\n if (isLoading) {\n return (\n <section className={cn('py-20 px-4 sm:px-6 lg:px-8 bg-slate-50 min-h-screen', theme === 'dark' && 'dark')}>\n <div className=\"max-w-5xl mx-auto\">\n <div className=\"text-center mb-16\">\n <Skeleton className=\"h-12 w-72 mx-auto mb-4\" />\n <Skeleton className=\"h-5 w-96 mx-auto\" />\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-8 max-w-3xl mx-auto\">\n <Skeleton className=\"h-[480px] rounded-2xl\" />\n <Skeleton className=\"h-[480px] rounded-2xl\" />\n </div>\n </div>\n </section>\n )\n }\n\n // ── Error ────────────────────────────────────────────────────────────────\n if (error) {\n return (\n <section className={cn('py-20 px-4', theme === 'dark' && 'dark')}>\n <div className=\"max-w-md mx-auto\">\n <Alert variant=\"destructive\">\n <AlertDescription>{error.message || 'Failed to load pricing plans'}</AlertDescription>\n </Alert>\n <div className=\"mt-4 flex justify-center\">\n <Button onClick={() => refetch()}>Try Again</Button>\n </div>\n </div>\n </section>\n )\n }\n\n // ── Empty ────────────────────────────────────────────────────────────────\n if (products.length === 0) {\n return (\n <section className={cn('py-20 px-4 text-center', theme === 'dark' && 'dark')}>\n <p className=\"text-muted-foreground\">No pricing plans available</p>\n </section>\n )\n }\n\n const paymentComponent = !onSelectPlan && selectedPriceId ? (\n <>\n {useCheckoutModal ? (\n <CheckoutModal\n open={isPaymentOpen}\n onOpenChange={(open) => { if (!open) { setIsPaymentOpen(false); setSelectedPriceId(null) } }}\n priceId={selectedPriceId}\n customer={{ email: finalCustomerEmail, name: finalCustomerName }}\n onSuccess={handlePaymentSuccess}\n existingSubscriptionId={currentSubscription?.id}\n theme={theme}\n />\n ) : (\n <PaymentBottomSheet\n priceId={selectedPriceId}\n isOpen={isPaymentOpen}\n onClose={() => { setIsPaymentOpen(false); setSelectedPriceId(null) }}\n onSuccess={handlePaymentSuccess}\n existingSubscriptionId={currentSubscription?.id}\n theme={theme}\n />\n )}\n </>\n ) : null\n\n const cardsGrid = (\n <div\n className={cn(\n 'grid gap-8 items-start',\n products.length === 1 && 'grid-cols-1 max-w-sm mx-auto',\n products.length === 2 && 'grid-cols-1 md:grid-cols-2 max-w-3xl mx-auto',\n products.length >= 3 && 'grid-cols-1 md:grid-cols-3'\n )}\n >\n {products.map((product) => (\n <PricingCard\n key={product.id}\n product={product}\n allFeatures={allFeatures}\n isYearly={isYearly}\n currentSubscription={currentSubscription}\n currentPlanAmount={currentPlanAmount}\n onSelectPlan={handleSelectPlan}\n theme={theme}\n />\n ))}\n </div>\n )\n\n if (compact) {\n return (\n <div className={cn(theme === 'dark' && 'dark')}>\n {cardsGrid}\n {paymentComponent}\n </div>\n )\n }\n\n return (\n <section\n className={cn(\n 'py-20 px-4 sm:px-6 lg:px-8 bg-slate-50 min-h-screen',\n theme === 'dark' && 'dark'\n )}\n >\n <div className=\"max-w-5xl mx-auto\">\n {/* Success notification */}\n {showSuccessMessage && (\n <div className=\"mb-8 p-4 bg-green-50 border border-green-200 rounded-xl flex items-center gap-3\">\n <svg className=\"w-5 h-5 text-green-600 flex-shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n <p className=\"text-green-800 font-medium text-sm\">\n Payment successful! Your subscription has been updated.\n </p>\n </div>\n )}\n\n {/* Header */}\n <div className=\"text-center mb-16\">\n {title && (\n <h1 className=\"text-4xl md:text-5xl font-bold text-slate-900 tracking-tight mb-4\">\n {title}\n </h1>\n )}\n {description && (\n <p className=\"text-lg text-slate-500 max-w-2xl mx-auto\">{description}</p>\n )}\n </div>\n\n {/* Billing toggle */}\n {showIntervalToggle && hasYearlyPricing && (\n <div className=\"flex items-center justify-center gap-4 mb-16\">\n <span className={cn('text-sm font-medium transition-colors', !isYearly ? 'text-slate-900' : 'text-slate-400')}>\n Monthly\n </span>\n <Switch\n checked={isYearly}\n onCheckedChange={setIsYearly}\n aria-label=\"Billing frequency\"\n />\n <span className={cn('text-sm font-medium transition-colors', isYearly ? 'text-slate-900' : 'text-slate-400')}>\n Yearly\n </span>\n {isYearly && (\n <Badge className=\"bg-emerald-100 text-emerald-700 border-0 ml-2\">\n Save up to 40%\n </Badge>\n )}\n </div>\n )}\n\n {cardsGrid}\n\n {/* Footer */}\n {footerText && (\n <div className=\"text-center mt-16\">\n <p className=\"text-sm text-slate-400\">{footerText}</p>\n </div>\n )}\n </div>\n\n {paymentComponent}\n </section>\n )\n}\n","\"use client\";\nimport { useQuery } from '@tanstack/react-query'\nimport { useBillingOS } from '../../../providers/BillingOSProvider'\nimport type { GetProductsResponse } from '../../../client/types'\n\nexport interface UseProductsOptions {\n /**\n * Optional array of plan IDs to filter\n */\n planIds?: string[]\n /**\n * Whether to enable the query\n */\n enabled?: boolean\n}\n\n/**\n * Hook to fetch products for pricing table\n */\nexport function useProducts(options: UseProductsOptions = {}) {\n const { client } = useBillingOS()\n const { planIds, enabled = true } = options\n\n return useQuery<GetProductsResponse, Error>({\n queryKey: ['products', planIds],\n queryFn: async () => {\n return client!.getProducts(planIds)\n },\n enabled: !!client && enabled,\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 10 * 60 * 1000, // 10 minutes\n })\n}\n","\"use client\";\nimport { Check, X } from 'lucide-react'\nimport { Badge } from '../ui/badge'\nimport { Button } from '../ui/button'\nimport { cn } from '../../utils/cn'\nimport type { PricingProduct, PricingPrice, PricingCurrentSubscription } from '../../client/types'\n\nexport interface PricingCardProps {\n product: PricingProduct\n /** All unique features across all products, for consistent row layout */\n allFeatures: Array<{ name: string; title: string; type: string }>\n isYearly: boolean\n currentSubscription: PricingCurrentSubscription | null\n currentPlanAmount: number\n onSelectPlan: (priceId: string) => void\n theme?: 'light' | 'dark'\n}\n\n\nfunction formatPrice(price: PricingPrice) {\n const amount = price.amount / 100\n return amount % 1 === 0\n ? `$${amount.toFixed(0)}`\n : `$${amount.toFixed(2)}`\n}\n\nfunction formatLimit(limit: number, unit?: string): string | null {\n if (!limit) return null\n const n =\n limit >= 1000\n ? `${(limit / 1000).toFixed(limit % 1000 === 0 ? 0 : 1)}k`\n : limit.toLocaleString()\n return unit ? `${n} ${unit}` : n\n}\n\nfunction getYearlySavings(monthly: number, yearly: number) {\n const yearlyFromMonthly = monthly * 12\n return Math.round(((yearlyFromMonthly - yearly) / yearlyFromMonthly) * 100)\n}\n\nexport function PricingCard({\n product,\n allFeatures,\n isYearly,\n currentSubscription,\n currentPlanAmount,\n onSelectPlan,\n}: PricingCardProps) {\n const monthlyPrice = product.prices.find((p) => p.interval === 'month')\n const yearlyPrice = product.prices.find((p) => p.interval === 'year')\n const currentPrice = isYearly && yearlyPrice ? yearlyPrice : monthlyPrice\n\n const savings =\n monthlyPrice && yearlyPrice\n ? getYearlySavings(monthlyPrice.amount, yearlyPrice.amount)\n : 0\n\n const isHighlighted = product.highlighted || product.isCurrentPlan\n const isFree = (monthlyPrice?.amount ?? 0) === 0\n\n // CTA label\n const getButtonLabel = () => {\n if (product.isCurrentPlan) return 'Current Plan'\n if (!currentSubscription) return isFree ? 'Get Started Free' : 'Get Started'\n const thisAmount = currentPrice?.amount ?? 0\n if (thisAmount > currentPlanAmount) return 'Upgrade Now'\n if (thisAmount < currentPlanAmount) return 'Downgrade'\n return 'Switch Plan'\n }\n\n const handleClick = () => {\n if (!product.isCurrentPlan && currentPrice) {\n onSelectPlan(currentPrice.id)\n }\n }\n\n return (\n <div\n className={cn(\n 'relative rounded-2xl border bg-white p-8 transition-all duration-300',\n isHighlighted\n ? 'border-blue-200 ring-2 ring-blue-600 shadow-xl shadow-blue-500/10 md:scale-105 z-10'\n : 'border-slate-200 hover:border-slate-300 hover:shadow-lg hover:-translate-y-1'\n )}\n >\n {/* Floating badge */}\n {(product.highlighted || product.isCurrentPlan) && (\n <div className=\"absolute -top-3 left-1/2 -translate-x-1/2\">\n <Badge\n className={cn(\n 'border-0 px-4 py-1 text-xs font-semibold',\n product.isCurrentPlan ? 'bg-emerald-600 text-white' : 'bg-blue-600 text-white'\n )}\n >\n {product.isCurrentPlan ? 'Current Plan' : 'Most Popular'}\n </Badge>\n </div>\n )}\n\n {/* Header */}\n <div className=\"mb-6\">\n <h3 className=\"text-xl font-semibold text-slate-900 mb-1\">{product.name}</h3>\n {product.description && (\n <p className=\"text-sm text-slate-500\">{product.description}</p>\n )}\n </div>\n\n {/* Price */}\n <div className=\"mb-6\">\n <div className=\"flex items-baseline gap-1\">\n <span className=\"text-4xl font-bold text-slate-900\">\n {currentPrice ? formatPrice(currentPrice) : '$0'}\n </span>\n <span className=\"text-slate-500 text-sm\">{isYearly ? '/year' : '/mo'}</span>\n </div>\n {isYearly && savings > 0 && (\n <p className=\"text-sm text-emerald-600 font-medium mt-1\">Save {savings}% yearly</p>\n )}\n {!isYearly && yearlyPrice && savings > 0 && (\n <p className=\"text-sm text-slate-400 mt-1\">Switch to yearly & save {savings}%</p>\n )}\n </div>\n\n {/* Trial badge */}\n {product.trialDays > 0 && !product.isCurrentPlan && (\n <div className=\"mb-6\">\n <Badge variant=\"outline\" className=\"bg-amber-50 text-amber-700 border-amber-200\">\n {product.trialDays}-day free trial\n </Badge>\n </div>\n )}\n\n {/* CTA */}\n <Button\n disabled={product.isCurrentPlan}\n onClick={handleClick}\n className={cn(\n 'w-full mb-8 h-11 rounded-xl font-medium transition-all border-0',\n product.isCurrentPlan\n ? 'bg-slate-100 text-slate-400 cursor-not-allowed hover:bg-slate-100'\n : isHighlighted\n ? 'bg-blue-600 hover:bg-blue-700 text-white shadow-md shadow-blue-500/25'\n : 'bg-slate-100 hover:bg-slate-200 text-slate-700'\n )}\n >\n {getButtonLabel()}\n </Button>\n\n {/* Features */}\n <div className=\"space-y-4\">\n <p className=\"text-xs font-semibold uppercase tracking-wider text-slate-400\">\n What's included\n </p>\n <ul className=\"space-y-3\">\n {allFeatures.map((featureMeta) => {\n const productFeature = product.features.find((f) => f.name === featureMeta.name)\n const hasFeature = !!productFeature\n const limit = productFeature?.properties?.limit\n const unit = productFeature?.properties?.unit\n const displayValue =\n hasFeature && typeof limit === 'number' && limit !== -1\n ? formatLimit(limit, unit)\n : null\n\n return (\n <li\n key={featureMeta.name}\n className={cn(\n 'flex items-center gap-3 text-sm',\n hasFeature ? 'text-slate-700' : 'text-slate-300'\n )}\n >\n {/* Check / X */}\n <div\n className={cn(\n 'flex items-center justify-center w-5 h-5 rounded-full flex-shrink-0',\n hasFeature ? 'bg-blue-100' : 'bg-slate-100'\n )}\n >\n {hasFeature ? (\n <Check className=\"w-3 h-3 text-blue-600\" />\n ) : (\n <X className=\"w-3 h-3 text-slate-400\" />\n )}\n </div>\n\n {/* Label */}\n <span className=\"flex-1\">\n {limit === -1 ? `Unlimited ${featureMeta.title}` : featureMeta.title}\n </span>\n\n {/* Value pill */}\n {displayValue && (\n <span className=\"flex-shrink-0 text-xs bg-slate-100 text-slate-500 font-medium px-2 py-0.5 rounded\">\n {displayValue}\n </span>\n )}\n </li>\n )\n })}\n </ul>\n </div>\n </div>\n )\n}\n","\"use client\";\nimport * as React from 'react'\nimport { loadStripe } from '@stripe/stripe-js'\nimport { Elements } from '@stripe/react-stripe-js'\nimport { useQueryClient } from '@tanstack/react-query'\nimport type { Stripe, Appearance } from '@stripe/stripe-js'\nimport {\n Drawer,\n DrawerContent,\n DrawerHeader,\n DrawerTitle,\n DrawerDescription,\n} from '../ui/drawer'\nimport { ErrorBoundary } from '../ErrorBoundary'\nimport { Card, CardContent } from '../ui/card'\nimport { Badge } from '../ui/badge'\nimport { Skeleton } from '../ui/skeleton'\nimport { Alert, AlertDescription } from '../ui/alert'\nimport { Button } from '../ui/button'\nimport { Separator } from '../ui/separator'\nimport { useBillingOS } from '../../providers/BillingOSProvider'\nimport { useCreateCheckout } from './hooks/useCheckout'\nimport { PaymentForm } from './PaymentForm'\nimport { DemoPaymentForm } from './DemoPaymentForm'\nimport { BILLINGOS_STRIPE_PUBLISHABLE_KEY, isValidStripeKey, isValidClientSecret } from '../../config/stripe'\n\nexport interface PaymentBottomSheetProps {\n /**\n * Price ID to purchase\n */\n priceId: string\n\n /**\n * Open/close state\n */\n isOpen: boolean\n\n /**\n * Callback when user closes sheet\n */\n onClose: () => void\n\n /**\n * Callback when payment succeeds\n */\n onSuccess: (subscriptionId: string) => void\n\n /**\n * Optional: Subscription ID if upgrading\n */\n existingSubscriptionId?: string\n\n /**\n * Optional: Custom theme\n */\n theme?: 'light' | 'dark'\n}\n\ntype SheetState = 'loading' | 'ready' | 'processing' | 'success' | 'error'\n\nexport function PaymentBottomSheet({\n priceId,\n isOpen,\n onClose,\n onSuccess,\n existingSubscriptionId,\n theme,\n}: PaymentBottomSheetProps) {\n // Debug logging\n console.log('[PaymentBottomSheet v0.1.3] Rendering with checkout fix:', {\n priceId,\n isOpen,\n existingSubscriptionId,\n theme\n })\n\n const { customerEmail, customerName } = useBillingOS()\n const queryClient = useQueryClient()\n const [stripePromise, setStripePromise] = React.useState<Promise<Stripe | null> | null>(null)\n const [sheetState, setSheetState] = React.useState<SheetState>('loading')\n const [error, setError] = React.useState<string | null>(null)\n const [isProcessing, setIsProcessing] = React.useState(false)\n const [isDemoMode, setIsDemoMode] = React.useState(false)\n\n // Log state changes\n React.useEffect(() => {\n console.log('[PaymentBottomSheet] State changed:', {\n sheetState,\n error,\n isProcessing,\n isDemoMode,\n hasStripePromise: !!stripePromise\n })\n }, [sheetState, error, isProcessing, isDemoMode, stripePromise])\n\n // Create checkout session\n const {\n data: checkoutData,\n error: checkoutError,\n refetch: refetchCheckout,\n } = useCreateCheckout(\n isOpen\n ? {\n priceId,\n customerEmail,\n customerName,\n existingSubscriptionId,\n }\n : null,\n {\n enabled: isOpen,\n }\n )\n\n // The API returns the checkout session directly\n const checkoutSession = checkoutData\n\n // Log checkout session data\n React.useEffect(() => {\n console.log('[PaymentBottomSheet] Checkout session data:', {\n hasCheckoutData: !!checkoutData,\n checkoutSession: checkoutSession,\n checkoutError: checkoutError?.message,\n isOpen\n })\n }, [checkoutData, checkoutSession, checkoutError, isOpen])\n\n // Initialize Stripe when checkout session is ready\n React.useEffect(() => {\n console.log('[PaymentBottomSheet] Stripe initialization effect triggered')\n if (checkoutSession) {\n const validKey = isValidStripeKey(BILLINGOS_STRIPE_PUBLISHABLE_KEY)\n const validSecret = isValidClientSecret(checkoutSession.clientSecret)\n\n console.log('[PaymentBottomSheet] Stripe validation:', {\n publishableKey: BILLINGOS_STRIPE_PUBLISHABLE_KEY,\n validKey,\n clientSecret: checkoutSession.clientSecret?.substring(0, 20) + '...',\n validSecret,\n stripeAccountId: checkoutSession.stripeAccountId\n })\n\n if (validKey && validSecret) {\n // Use BillingOS platform Stripe key with merchant's Connect account ID\n console.log('[PaymentBottomSheet] Loading Stripe with valid credentials')\n const stripe = loadStripe(BILLINGOS_STRIPE_PUBLISHABLE_KEY, {\n stripeAccount: checkoutSession.stripeAccountId,\n })\n setStripePromise(stripe)\n setIsDemoMode(false)\n } else {\n // Demo mode - invalid credentials\n console.log('[PaymentBottomSheet] Invalid Stripe credentials, entering demo mode')\n setIsDemoMode(true)\n }\n setSheetState('ready')\n }\n }, [checkoutSession])\n\n // Handle checkout error\n React.useEffect(() => {\n if (checkoutError) {\n setError(checkoutError.message || 'Failed to create checkout session')\n setSheetState('error')\n }\n }, [checkoutError])\n\n // Reset state when closed\n React.useEffect(() => {\n if (!isOpen) {\n setSheetState('loading')\n setError(null)\n setStripePromise(null)\n setIsDemoMode(false)\n }\n }, [isOpen])\n\n const handlePaymentSuccess = (subscriptionId: string) => {\n setSheetState('success')\n\n // Invalidate products query to refresh pricing table with new subscription status\n queryClient.invalidateQueries({ queryKey: ['billingos', 'products'] })\n console.log('💫 Invalidated products query - PricingTable will auto-refresh')\n\n setTimeout(() => {\n onSuccess(subscriptionId)\n }, 1500)\n }\n\n const handlePaymentError = (errorMessage: string) => {\n setError(errorMessage)\n }\n\n const handleClose = () => {\n console.log('[PaymentBottomSheet] handleClose called, isProcessing:', isProcessing)\n if (isProcessing) {\n // Show confirmation if payment is processing\n const confirmed = window.confirm(\n 'Your payment is being processed. Are you sure you want to close?'\n )\n if (!confirmed) return\n }\n onClose()\n }\n\n const handleRetry = () => {\n setError(null)\n setSheetState('loading')\n refetchCheckout()\n }\n\n // Stripe appearance based on theme\n const appearance: Appearance = {\n theme: theme === 'dark' ? 'night' : 'stripe',\n variables: {\n colorPrimary: '#3B82F6',\n borderRadius: '8px',\n },\n }\n\n const formatAmount = (cents: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(cents / 100)\n }\n\n const formatInterval = (interval: string) => {\n switch (interval) {\n case 'day':\n return 'day'\n case 'week':\n return 'week'\n case 'month':\n return 'month'\n case 'year':\n return 'year'\n default:\n return interval\n }\n }\n\n // Log render\n console.log('[PaymentBottomSheet] Rendering drawer with isOpen:', isOpen, 'sheetState:', sheetState)\n\n return (\n <ErrorBoundary\n fallback={(error, reset) => (\n <div style={{ padding: '20px', maxWidth: '400px', margin: '0 auto' }}>\n <Alert variant=\"destructive\">\n <AlertDescription>\n Failed to load payment form: {error?.message || 'Unknown error'}\n </AlertDescription>\n </Alert>\n <div className=\"mt-4 flex gap-2\">\n <Button variant=\"outline\" onClick={onClose}>Cancel</Button>\n <Button onClick={reset}>Try Again</Button>\n </div>\n </div>\n )}\n onError={(error, errorInfo) => {\n console.error('[PaymentBottomSheet] Error caught by boundary:', error)\n console.error('[PaymentBottomSheet] Error info:', errorInfo)\n }}\n >\n <Drawer open={isOpen} onOpenChange={(open) => {\n console.log('[PaymentBottomSheet] Drawer.onOpenChange called with open:', open)\n if (!open) {\n handleClose()\n }\n }}>\n <DrawerContent\n preventClose={isProcessing}\n onCloseAttempt={() => {\n window.alert('Please wait while your payment is being processed.')\n }}\n >\n <DrawerHeader className=\"text-center sm:text-left\">\n <DrawerTitle>\n {sheetState === 'success'\n ? 'Payment Successful!'\n : existingSubscriptionId\n ? 'Complete Your Upgrade'\n : 'Complete Payment'}\n </DrawerTitle>\n {sheetState !== 'success' && checkoutSession && (\n <DrawerDescription>\n {existingSubscriptionId ? 'Upgrading to' : 'Subscribing to'}:{' '}\n <span className=\"font-medium\">{checkoutSession.product.name}</span>\n </DrawerDescription>\n )}\n </DrawerHeader>\n\n {/* Loading State */}\n {sheetState === 'loading' && (\n <div className=\"space-y-6 py-4\">\n <Skeleton className=\"h-20 w-full\" />\n <Skeleton className=\"h-40 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n </div>\n )}\n\n {/* Error State */}\n {sheetState === 'error' && (\n <div className=\"space-y-4 py-4\">\n <Alert variant=\"destructive\">\n <AlertDescription>\n {error || 'Something went wrong. Please try again.'}\n </AlertDescription>\n </Alert>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" onClick={onClose} className=\"flex-1\">\n Cancel\n </Button>\n <Button onClick={handleRetry} className=\"flex-1\">\n Try Again\n </Button>\n </div>\n </div>\n )}\n\n {/* Success State */}\n {sheetState === 'success' && checkoutSession && (\n <div className=\"flex flex-col items-center justify-center py-8 space-y-4\">\n <div className=\"w-16 h-16 rounded-full bg-green-100 flex items-center justify-center\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-green-600\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </div>\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold\">Payment Successful!</p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Your subscription to {checkoutSession.product.name} is now active.\n </p>\n </div>\n </div>\n )}\n\n {/* Processing State */}\n {sheetState === 'processing' && (\n <div className=\"flex flex-col items-center justify-center py-8 space-y-4\">\n <div className=\"w-16 h-16 rounded-full bg-primary/10 flex items-center justify-center\">\n <svg\n className=\"animate-spin h-8 w-8 text-primary\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n </div>\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold\">Processing Payment...</p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Please don't close this window.\n </p>\n </div>\n </div>\n )}\n\n {/* Ready State - Show Payment Form */}\n {sheetState === 'ready' && checkoutSession && (\n <div className=\"space-y-6\">\n {/* Demo Mode Banner */}\n {isDemoMode && (\n <Alert>\n <AlertDescription className=\"text-sm\">\n <strong>Demo Mode:</strong> This is a preview with mock data. In production,\n a real Stripe payment form will appear here.\n </AlertDescription>\n </Alert>\n )}\n\n {/* Plan Summary */}\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex items-start justify-between\">\n <div>\n <h3 className=\"font-semibold\">{checkoutSession.product.name}</h3>\n <p className=\"text-2xl font-bold mt-1\">\n {formatAmount(checkoutSession.amount, checkoutSession.currency)}\n <span className=\"text-sm font-normal text-muted-foreground\">\n /{formatInterval(checkoutSession.product.interval)}\n </span>\n </p>\n </div>\n <Badge variant=\"secondary\">\n {existingSubscriptionId ? 'Upgrade' : 'New'}\n </Badge>\n </div>\n\n {/* Features */}\n {checkoutSession.product.features.length > 0 && (\n <div className=\"mt-4 space-y-2\">\n <p className=\"text-sm font-medium text-muted-foreground\">\n Features Included:\n </p>\n <ul className=\"space-y-1\">\n {checkoutSession.product.features.map((feature, index) => (\n <li key={index} className=\"flex items-center gap-2 text-sm\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-green-500\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n {feature}\n </li>\n ))}\n </ul>\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Proration Details (for upgrades) */}\n {checkoutSession.proration && (\n <Card>\n <CardContent className=\"pt-4\">\n <h4 className=\"font-medium mb-3\">Amount Due Today:</h4>\n <div className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <span>{checkoutSession.product.name}</span>\n <span>\n {formatAmount(\n checkoutSession.proration.charged,\n checkoutSession.currency\n )}\n </span>\n </div>\n <div className=\"flex justify-between text-green-600\">\n <span>Credit (unused time)</span>\n <span>\n -\n {formatAmount(\n checkoutSession.proration.credited,\n checkoutSession.currency\n )}\n </span>\n </div>\n <Separator />\n <div className=\"flex justify-between font-semibold\">\n <span>Total Due Now</span>\n <span>\n {formatAmount(\n checkoutSession.proration.total,\n checkoutSession.currency\n )}\n </span>\n </div>\n </div>\n <p className=\"text-xs text-muted-foreground mt-3 flex items-start gap-1\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"mt-0.5 flex-shrink-0\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 16v-4\" />\n <path d=\"M12 8h.01\" />\n </svg>\n {checkoutSession.proration.explanation}\n </p>\n </CardContent>\n </Card>\n )}\n\n {/* Amount Due (no proration) */}\n {!checkoutSession.proration && (\n <Card>\n <CardContent className=\"pt-4\">\n <div className=\"flex justify-between items-center\">\n <span className=\"font-medium\">Amount Due Today:</span>\n <span className=\"text-xl font-bold\">\n {formatAmount(checkoutSession.amount, checkoutSession.currency)}\n </span>\n </div>\n </CardContent>\n </Card>\n )}\n\n <Separator />\n\n {/* Payment Form - Demo or Real Stripe */}\n {isDemoMode ? (\n <DemoPaymentForm\n checkoutSession={checkoutSession}\n onSuccess={handlePaymentSuccess}\n isProcessing={isProcessing}\n setIsProcessing={setIsProcessing}\n />\n ) : stripePromise ? (\n <Elements\n stripe={stripePromise}\n options={{\n clientSecret: checkoutSession.clientSecret,\n appearance,\n }}\n >\n <PaymentForm\n checkoutSession={checkoutSession}\n onSuccess={handlePaymentSuccess}\n onError={handlePaymentError}\n isProcessing={isProcessing}\n setIsProcessing={setIsProcessing}\n />\n </Elements>\n ) : null}\n </div>\n )}\n </DrawerContent>\n </Drawer>\n </ErrorBoundary>\n )\n}\n","\"use client\";\nimport * as React from 'react'\n\ninterface ErrorBoundaryState {\n hasError: boolean\n error: Error | null\n}\n\ninterface ErrorBoundaryProps {\n children: React.ReactNode\n fallback?: (error: Error | null, reset: () => void) => React.ReactNode\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void\n}\n\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props)\n this.state = { hasError: false, error: null }\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n // Update state so the next render will show the fallback UI\n return { hasError: true, error }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n // Log the error to console in development\n console.error('[ErrorBoundary] Caught error:', error)\n console.error('[ErrorBoundary] Error info:', errorInfo)\n\n // Call the optional error handler\n this.props.onError?.(error, errorInfo)\n }\n\n reset = () => {\n this.setState({ hasError: false, error: null })\n }\n\n render() {\n if (this.state.hasError) {\n // If a custom fallback is provided, use it\n if (this.props.fallback) {\n return this.props.fallback(this.state.error, this.reset)\n }\n\n // Default fallback UI\n return (\n <div style={{\n padding: '20px',\n border: '1px solid #ef4444',\n borderRadius: '8px',\n backgroundColor: '#fee2e2',\n color: '#991b1b',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n }}>\n <h3 style={{ margin: '0 0 10px 0', fontSize: '16px', fontWeight: 'bold' }}>\n Payment Error\n </h3>\n <p style={{ margin: '0 0 10px 0', fontSize: '14px' }}>\n {this.state.error?.message || 'An unexpected error occurred while loading the payment form.'}\n </p>\n <button\n onClick={this.reset}\n style={{\n padding: '8px 16px',\n border: 'none',\n borderRadius: '6px',\n backgroundColor: '#ef4444',\n color: 'white',\n fontSize: '14px',\n cursor: 'pointer',\n fontWeight: '500',\n }}\n >\n Try Again\n </button>\n </div>\n )\n }\n\n return this.props.children\n }\n}\n\n// Hook for using error boundary programmatically\nexport function useErrorHandler() {\n const [error, setError] = React.useState<Error | null>(null)\n\n React.useEffect(() => {\n if (error) {\n throw error\n }\n }, [error])\n\n return setError\n}","\"use client\";\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useBillingOS } from '../../../providers/BillingOSProvider'\nimport type {\n CreateCheckoutInput,\n CreateCheckoutResponse,\n ConfirmCheckoutResponse,\n} from '../../../client/types'\n\n/**\n * Hook to create a checkout session\n */\nexport function useCreateCheckout(\n input: CreateCheckoutInput | null,\n options?: {\n enabled?: boolean\n onSuccess?: (data: CreateCheckoutResponse) => void\n onError?: (error: Error) => void\n }\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: ['checkout', input?.priceId, input?.existingSubscriptionId],\n queryFn: async () => {\n if (!input) throw new Error('Checkout input is required')\n return client!.createCheckout(input)\n },\n enabled: !!client && options?.enabled !== false && !!input,\n staleTime: 0, // Always fetch fresh checkout session\n gcTime: 0, // Don't cache checkout sessions\n })\n}\n\n/**\n * Hook to confirm a checkout after payment\n */\nexport function useConfirmCheckout(options?: {\n onSuccess?: (data: ConfirmCheckoutResponse) => void\n onError?: (error: Error) => void\n}) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async ({\n clientSecret,\n paymentMethodId,\n }: {\n clientSecret: string\n paymentMethodId: string\n }) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.confirmCheckout(clientSecret, paymentMethodId)\n },\n onSuccess: (data) => {\n // Invalidate subscription queries after successful checkout\n queryClient.invalidateQueries({ queryKey: ['portal'] })\n queryClient.invalidateQueries({ queryKey: ['subscriptions'] })\n options?.onSuccess?.(data)\n },\n onError: (error) => {\n options?.onError?.(error as Error)\n },\n })\n}\n","\"use client\";\nimport * as React from 'react'\nimport {\n PaymentElement,\n ExpressCheckoutElement,\n useStripe,\n useElements,\n} from '@stripe/react-stripe-js'\nimport type { StripeExpressCheckoutElementConfirmEvent } from '@stripe/stripe-js'\nimport { Button } from '../ui/button'\nimport { Alert, AlertDescription } from '../ui/alert'\nimport { Separator } from '../ui/separator'\nimport { cn } from '@/utils/cn'\nimport type { CheckoutSession } from '../../client/types'\nimport { useBillingOS } from '../../providers/BillingOSProvider'\n\ninterface PaymentFormProps {\n checkoutSession: CheckoutSession\n onSuccess: (subscriptionId: string) => void\n onError?: (error: string) => void\n isProcessing: boolean\n setIsProcessing: (processing: boolean) => void\n}\n\nexport function PaymentForm({\n checkoutSession,\n onSuccess,\n onError,\n isProcessing,\n setIsProcessing,\n}: PaymentFormProps) {\n const { client } = useBillingOS()\n const stripe = useStripe()\n const elements = useElements()\n const [error, setError] = React.useState<string | null>(null)\n const [isExpressCheckoutReady, setIsExpressCheckoutReady] = React.useState(false)\n\n const formatAmount = (cents: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(cents / 100)\n }\n\n const totalAmount = checkoutSession.proration?.total ?? checkoutSession.amount\n const formattedAmount = formatAmount(totalAmount, checkoutSession.currency)\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!stripe || !elements) {\n return\n }\n\n setIsProcessing(true)\n setError(null)\n\n try {\n // Confirm payment with Stripe\n const { error: submitError, paymentIntent } = await stripe.confirmPayment({\n elements,\n confirmParams: {\n return_url: `${window.location.origin}/billing/success`,\n },\n redirect: 'if_required',\n })\n\n if (submitError) {\n setError(submitError.message || 'Payment failed')\n onError?.(submitError.message || 'Payment failed')\n setIsProcessing(false)\n return\n }\n\n // Payment successful - confirm with backend to create subscription\n if (paymentIntent?.status === 'succeeded' && paymentIntent.payment_method) {\n try {\n const result = await client!.confirmCheckout(\n checkoutSession.clientSecret,\n paymentIntent.payment_method as string\n )\n\n if (result.success) {\n onSuccess(result.subscriptionId)\n } else {\n throw new Error(result.message || 'Failed to create subscription')\n }\n } catch (confirmError) {\n const message = confirmError instanceof Error ? confirmError.message : 'Failed to complete checkout'\n setError(message)\n onError?.(message)\n setIsProcessing(false)\n return\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Payment failed'\n setError(message)\n onError?.(message)\n } finally {\n setIsProcessing(false)\n }\n }\n\n const handleExpressCheckout = async (_event: StripeExpressCheckoutElementConfirmEvent) => {\n if (!stripe || !elements) {\n return\n }\n\n setIsProcessing(true)\n setError(null)\n\n try {\n const { error: submitError } = await stripe.confirmPayment({\n elements,\n clientSecret: checkoutSession.clientSecret,\n confirmParams: {\n return_url: `${window.location.origin}/billing/success`,\n },\n redirect: 'if_required',\n })\n\n if (submitError) {\n setError(submitError.message || 'Payment failed')\n onError?.(submitError.message || 'Payment failed')\n setIsProcessing(false)\n return\n }\n\n // Express checkout successful\n onSuccess(checkoutSession.id)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Payment failed'\n setError(message)\n onError?.(message)\n } finally {\n setIsProcessing(false)\n }\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {/* Express Checkout (Apple Pay, Google Pay, Link) */}\n <div className={cn(!isExpressCheckoutReady && 'hidden')}>\n <ExpressCheckoutElement\n options={{\n wallets: {\n applePay: 'auto',\n googlePay: 'auto',\n },\n }}\n onConfirm={handleExpressCheckout}\n onReady={() => setIsExpressCheckoutReady(true)}\n />\n </div>\n\n {/* Separator */}\n {isExpressCheckoutReady && (\n <div className=\"relative\">\n <div className=\"absolute inset-0 flex items-center\">\n <Separator className=\"w-full\" />\n </div>\n <div className=\"relative flex justify-center text-xs uppercase\">\n <span className=\"bg-background px-2 text-muted-foreground\">\n or pay with card\n </span>\n </div>\n </div>\n )}\n\n {/* Card Payment Form */}\n <div className=\"space-y-4\">\n <PaymentElement\n options={{\n layout: 'tabs',\n }}\n />\n </div>\n\n {/* Error Message */}\n {error && (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n {/* Submit Button */}\n <Button\n type=\"submit\"\n className=\"w-full\"\n size=\"lg\"\n disabled={!stripe || isProcessing}\n >\n {isProcessing ? (\n <span className=\"flex items-center gap-2\">\n <svg\n className=\"animate-spin h-4 w-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n Processing...\n </span>\n ) : checkoutSession.proration ? (\n `Upgrade Now - ${formattedAmount}`\n ) : (\n `Subscribe - ${formattedAmount}`\n )}\n </Button>\n\n {/* Security Badge */}\n <div className=\"flex items-center justify-center gap-2 text-xs text-muted-foreground\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n <span>Secured by Stripe • Cancel anytime</span>\n </div>\n </form>\n )\n}\n","\"use client\";\nimport * as React from 'react'\nimport { Button } from '../ui/button'\nimport { Input } from '../ui/input'\nimport { Label } from '../ui/label'\nimport type { CheckoutSession } from '../../client/types'\n\ninterface DemoPaymentFormProps {\n checkoutSession: CheckoutSession\n onSuccess: (subscriptionId: string) => void\n isProcessing: boolean\n setIsProcessing: (processing: boolean) => void\n}\n\nexport function DemoPaymentForm({\n checkoutSession,\n onSuccess,\n isProcessing,\n setIsProcessing,\n}: DemoPaymentFormProps) {\n const [cardNumber, setCardNumber] = React.useState('')\n const [expiry, setExpiry] = React.useState('')\n const [cvc, setCvc] = React.useState('')\n\n const formatAmount = (cents: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n }).format(cents / 100)\n }\n\n const totalAmount = checkoutSession.proration?.total ?? checkoutSession.amount\n const formattedAmount = formatAmount(totalAmount, checkoutSession.currency)\n\n const formatCardNumber = (value: string) => {\n const digits = value.replace(/\\D/g, '')\n const groups = digits.match(/.{1,4}/g)\n return groups ? groups.join(' ').substring(0, 19) : ''\n }\n\n const formatExpiry = (value: string) => {\n const digits = value.replace(/\\D/g, '')\n if (digits.length >= 2) {\n return `${digits.slice(0, 2)}/${digits.slice(2, 4)}`\n }\n return digits\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n setIsProcessing(true)\n\n // Simulate payment processing\n await new Promise((resolve) => setTimeout(resolve, 2000))\n\n // Simulate success\n onSuccess(`sub_demo_${Date.now()}`)\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {/* Mock Express Checkout Buttons */}\n <div className=\"grid grid-cols-2 gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"h-12\"\n disabled={isProcessing}\n onClick={() => {\n setIsProcessing(true)\n setTimeout(() => onSuccess(`sub_demo_apple_${Date.now()}`), 2000)\n }}\n >\n <svg viewBox=\"0 0 24 24\" className=\"w-5 h-5 mr-2\" fill=\"currentColor\">\n <path d=\"M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z\" />\n </svg>\n Apple Pay\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"h-12\"\n disabled={isProcessing}\n onClick={() => {\n setIsProcessing(true)\n setTimeout(() => onSuccess(`sub_demo_google_${Date.now()}`), 2000)\n }}\n >\n <svg viewBox=\"0 0 24 24\" className=\"w-5 h-5 mr-2\">\n <path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\" />\n <path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" />\n <path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </svg>\n Google Pay\n </Button>\n </div>\n\n {/* Separator */}\n <div className=\"relative\">\n <div className=\"absolute inset-0 flex items-center\">\n <span className=\"w-full border-t\" />\n </div>\n <div className=\"relative flex justify-center text-xs uppercase\">\n <span className=\"bg-background px-2 text-muted-foreground\">\n or pay with card\n </span>\n </div>\n </div>\n\n {/* Card Form */}\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"card-number\">Card number</Label>\n <Input\n id=\"card-number\"\n placeholder=\"1234 5678 9012 3456\"\n value={cardNumber}\n onChange={(e) => setCardNumber(formatCardNumber(e.target.value))}\n disabled={isProcessing}\n maxLength={19}\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"expiry\">Expiry date</Label>\n <Input\n id=\"expiry\"\n placeholder=\"MM/YY\"\n value={expiry}\n onChange={(e) => setExpiry(formatExpiry(e.target.value))}\n disabled={isProcessing}\n maxLength={5}\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"cvc\">CVC</Label>\n <Input\n id=\"cvc\"\n placeholder=\"123\"\n value={cvc}\n onChange={(e) => setCvc(e.target.value.replace(/\\D/g, '').substring(0, 4))}\n disabled={isProcessing}\n maxLength={4}\n />\n </div>\n </div>\n </div>\n\n {/* Submit Button */}\n <Button\n type=\"submit\"\n className=\"w-full\"\n size=\"lg\"\n disabled={isProcessing}\n >\n {isProcessing ? (\n <span className=\"flex items-center gap-2\">\n <svg\n className=\"animate-spin h-4 w-4\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n Processing...\n </span>\n ) : checkoutSession.proration ? (\n `Upgrade Now - ${formattedAmount}`\n ) : (\n `Subscribe - ${formattedAmount}`\n )}\n </Button>\n\n {/* Security Badge */}\n <div className=\"flex items-center justify-center gap-2 text-xs text-muted-foreground\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n <span>Secured by Stripe - Cancel anytime</span>\n </div>\n </form>\n )\n}\n","/**\n * Stripe Configuration for BillingOS SDK\n *\n * This file contains the BillingOS platform's Stripe publishable key.\n * This key is bundled with the SDK and is safe to expose publicly.\n *\n * Merchants never see or configure this - it's completely internal to BillingOS.\n * Payments are routed to merchant's Stripe Connect accounts via the stripeAccount parameter.\n */\n\n/**\n * BillingOS Platform Stripe Publishable Key\n *\n * This is the platform's key (not the merchant's).\n * It's paired with the merchant's Stripe Connect account ID to route payments correctly.\n */\nexport const BILLINGOS_STRIPE_PUBLISHABLE_KEY =\n 'pk_test_51SihBODiEfx9xR94hb9APIlKq2CEr3uJqjQ1j98VdO5i30EGWi4HieGFjy1O3lEF3OWangT10RYr2Kae4CxfAvYd00xEVl0Raw'\n\n/**\n * Check if a Stripe key is valid format\n */\nexport function isValidStripeKey(key: string): boolean {\n return Boolean(key && (key.startsWith('pk_live_') || key.startsWith('pk_test_')) && key.length > 20)\n}\n\n/**\n * Check if a client secret is valid format\n */\nexport function isValidClientSecret(secret: string): boolean {\n // Valid client secrets look like: pi_xxx_secret_xxx or seti_xxx_secret_xxx\n return Boolean(secret && /^(pi|seti)_[a-zA-Z0-9]+_secret_[a-zA-Z0-9]+$/.test(secret))\n}\n","\"use client\";\nimport { useQuery, useMutation, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query'\nimport { useBillingOS } from '../../../providers'\nimport type {\n CustomerPortalData,\n PortalUpdateSubscriptionInput,\n PortalUpdateSubscriptionResponse,\n PortalCancelSubscriptionInput,\n PortalCancelSubscriptionResponse,\n AddPaymentMethodInput,\n AddPaymentMethodResponse,\n SetupIntentResponse,\n RetryInvoiceResponse,\n UpdateCustomerBillingInput,\n CustomerBillingInfo,\n} from '../../../client/types'\n\n/**\n * Query keys for portal-related queries\n */\nexport const portalKeys = {\n all: ['portal'] as const,\n data: () => [...portalKeys.all, 'data'] as const,\n setupIntent: () => [...portalKeys.all, 'setupIntent'] as const,\n}\n\n/**\n * Fetch all portal data for the current customer\n * Returns subscription, invoices, payment methods, customer info, and available plans\n */\nexport function usePortalData(\n options?: Omit<UseQueryOptions<CustomerPortalData>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: portalKeys.data(),\n queryFn: () => client!.getCustomerPortal(),\n enabled: !!client,\n staleTime: 1000 * 60 * 5, // 5 minutes\n ...options,\n })\n}\n\n/**\n * Update subscription (upgrade/downgrade)\n */\nexport function useUpdatePortalSubscription(\n subscriptionId: string,\n options?: Omit<\n UseMutationOptions<PortalUpdateSubscriptionResponse, Error, PortalUpdateSubscriptionInput>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: PortalUpdateSubscriptionInput) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.updatePortalSubscription(subscriptionId, input)\n },\n onSuccess: (...args) => {\n // Invalidate portal data to refresh subscription info\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Cancel subscription with feedback\n */\nexport function useCancelPortalSubscription(\n subscriptionId: string,\n options?: Omit<\n UseMutationOptions<PortalCancelSubscriptionResponse, Error, PortalCancelSubscriptionInput>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: PortalCancelSubscriptionInput) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.cancelPortalSubscription(subscriptionId, input)\n },\n onSuccess: (...args) => {\n // Invalidate portal data to refresh subscription status\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Reactivate a canceled subscription\n */\nexport function useReactivatePortalSubscription(\n subscriptionId: string,\n options?: Omit<UseMutationOptions<void, Error, void>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: () => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.reactivatePortalSubscription(subscriptionId)\n },\n onSuccess: (...args) => {\n // Invalidate portal data to refresh subscription status\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Get setup intent for adding a new payment method\n */\nexport function useSetupIntent(\n options?: Omit<UseQueryOptions<SetupIntentResponse>, 'queryKey' | 'queryFn'>\n) {\n const { client } = useBillingOS()\n\n return useQuery({\n queryKey: portalKeys.setupIntent(),\n queryFn: () => client!.getSetupIntent(),\n enabled: false, // Only fetch when explicitly requested\n ...options,\n })\n}\n\n/**\n * Add a payment method\n */\nexport function useAddPaymentMethod(\n options?: Omit<\n UseMutationOptions<AddPaymentMethodResponse, Error, AddPaymentMethodInput>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: AddPaymentMethodInput) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.addPaymentMethod(input)\n },\n onSuccess: (...args) => {\n // Invalidate portal data to refresh payment methods\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Remove a payment method\n */\nexport function useRemovePaymentMethod(\n options?: Omit<UseMutationOptions<void, Error, string>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (paymentMethodId: string) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.removePaymentMethod(paymentMethodId)\n },\n onSuccess: (...args) => {\n // Invalidate portal data to refresh payment methods\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Set default payment method\n */\nexport function useSetDefaultPaymentMethod(\n options?: Omit<UseMutationOptions<void, Error, string>, 'mutationFn'>\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (paymentMethodId: string) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.setDefaultPaymentMethod(paymentMethodId)\n },\n onSuccess: (...args) => {\n // Invalidate portal data to refresh payment methods\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Retry a failed invoice\n */\nexport function useRetryInvoice(\n options?: Omit<\n UseMutationOptions<RetryInvoiceResponse, Error, { invoiceId: string; paymentMethodId?: string }>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: ({ invoiceId, paymentMethodId }) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.retryInvoice(invoiceId, paymentMethodId)\n },\n onSuccess: (...args) => {\n // Invalidate portal data to refresh invoice status\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n\n/**\n * Update customer billing information\n */\nexport function useUpdateCustomerBilling(\n options?: Omit<\n UseMutationOptions<CustomerBillingInfo, Error, UpdateCustomerBillingInput>,\n 'mutationFn'\n >\n) {\n const { client } = useBillingOS()\n const queryClient = useQueryClient()\n\n return useMutation({\n ...options,\n mutationFn: (input: UpdateCustomerBillingInput) => {\n if (!client) throw new Error('[BillingOS] No active session')\n return client.updateCustomerBilling(input)\n },\n onSuccess: (...args) => {\n // Invalidate portal data to refresh customer info\n queryClient.invalidateQueries({ queryKey: portalKeys.data() })\n options?.onSuccess?.(...args)\n },\n })\n}\n","\"use client\";\nimport { Progress } from '../../ui/progress'\nimport { cn } from '@/utils/cn'\nimport type { PortalUsageInfo } from '../../../client/types'\n\ninterface UsageBarProps {\n title: string\n usage: PortalUsageInfo\n unit?: string\n className?: string\n}\n\nfunction formatNumber(num: number): string {\n if (num >= 1000000) {\n return `${(num / 1000000).toFixed(1)}M`\n }\n if (num >= 1000) {\n return `${(num / 1000).toFixed(1)}K`\n }\n return num.toLocaleString()\n}\n\nfunction getProgressColor(percentage: number): string {\n if (percentage >= 90) return 'bg-destructive'\n if (percentage >= 75) return 'bg-yellow-500'\n return 'bg-primary'\n}\n\nexport function UsageBar({ title, usage, unit, className }: UsageBarProps) {\n const { consumed, limit, percentage, resetDate } = usage\n\n const formattedConsumed = formatNumber(consumed)\n const formattedLimit = formatNumber(limit)\n const progressColor = getProgressColor(percentage)\n\n return (\n <div className={cn('space-y-2', className)}>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-medium\">{title}</span>\n <span className=\"text-muted-foreground\">\n {formattedConsumed} / {formattedLimit} {unit && `(${unit})`}\n </span>\n </div>\n <Progress\n value={percentage}\n max={100}\n className=\"h-2\"\n indicatorClassName={progressColor}\n />\n <div className=\"flex items-center justify-between text-xs text-muted-foreground\">\n <span>{Math.round(percentage)}% used</span>\n {resetDate && (\n <span>\n Resets: {new Date(resetDate).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}\n </span>\n )}\n </div>\n </div>\n )\n}\n","\"use client\";\nimport { cn } from '@/utils/cn'\nimport type { PortalFeatureWithUsage } from '../../../client/types'\n\ninterface FeatureListProps {\n features: PortalFeatureWithUsage[]\n className?: string\n}\n\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n )\n}\n\nexport function FeatureList({ features, className }: FeatureListProps) {\n // Filter to only show boolean features that are enabled\n const booleanFeatures = features.filter(\n (f) => f.type === 'boolean_flag' && f.enabled\n )\n\n if (booleanFeatures.length === 0) {\n return null\n }\n\n return (\n <div className={cn('space-y-2', className)}>\n <h4 className=\"text-sm font-medium text-muted-foreground\">Included Features</h4>\n <ul className=\"space-y-1.5\">\n {booleanFeatures.map((feature) => (\n <li key={feature.id} className=\"flex items-center gap-2 text-sm\">\n <CheckIcon className=\"text-green-500\" />\n <span>{feature.title}</span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n","\"use client\";\nimport { Alert, AlertTitle, AlertDescription } from '../../ui/alert'\nimport { Button } from '../../ui/button'\nimport { cn } from '@/utils/cn'\n\ninterface WarningBannerProps {\n type: 'trial_ending' | 'payment_failed' | 'subscription_canceled' | 'past_due'\n message: string\n actionLabel?: string\n onAction?: () => void\n className?: string\n}\n\nfunction AlertTriangleIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n )\n}\n\nfunction getTitle(type: WarningBannerProps['type']): string {\n switch (type) {\n case 'trial_ending':\n return 'Trial Ending Soon'\n case 'payment_failed':\n return 'Payment Failed'\n case 'subscription_canceled':\n return 'Subscription Canceled'\n case 'past_due':\n return 'Payment Past Due'\n default:\n return 'Warning'\n }\n}\n\nfunction getVariant(type: WarningBannerProps['type']): 'warning' | 'destructive' {\n switch (type) {\n case 'payment_failed':\n case 'past_due':\n return 'destructive'\n default:\n return 'warning'\n }\n}\n\nexport function WarningBanner({\n type,\n message,\n actionLabel,\n onAction,\n className,\n}: WarningBannerProps) {\n const title = getTitle(type)\n const variant = getVariant(type)\n\n return (\n <Alert variant={variant} className={cn('', className)}>\n <AlertTriangleIcon />\n <AlertTitle>{title}</AlertTitle>\n <AlertDescription className=\"flex items-center justify-between\">\n <span>{message}</span>\n {actionLabel && onAction && (\n <Button\n size=\"sm\"\n variant={variant === 'destructive' ? 'outline' : 'default'}\n onClick={onAction}\n className=\"ml-4\"\n >\n {actionLabel}\n </Button>\n )}\n </AlertDescription>\n </Alert>\n )\n}\n","/**\n * Currency utilities for formatting and converting money values\n */\n\n/**\n * Convert cents to dollar string\n * @param cents - Amount in cents\n * @param showCents - Force showing cents even if amount is whole dollars\n * @param pretty - Use locale formatting with thousand separators\n * @returns Formatted dollar string\n *\n * @example\n * getCentsInDollarString(1000) // \"10\"\n * getCentsInDollarString(1050, true) // \"10.50\"\n * getCentsInDollarString(1000000, false, true) // \"10,000\"\n */\nexport const getCentsInDollarString = (\n cents: number,\n showCents = false,\n pretty = false,\n): string => {\n const dollars = cents / 100\n\n const precision = cents % 100 === 0 && !showCents ? 0 : 2\n\n if (pretty) {\n return dollars.toLocaleString('en-US', {\n maximumFractionDigits: precision,\n minimumFractionDigits: precision,\n })\n }\n\n return dollars.toFixed(precision)\n}\n\n/**\n * Format cents as currency with symbol\n * @param cents - Amount in cents\n * @param currency - Currency code (e.g., 'USD', 'EUR')\n * @param minimumFractionDigits - Minimum decimal places\n * @param notation - Number notation style\n * @param maximumFractionDigits - Maximum decimal places\n * @returns Formatted currency string with symbol\n *\n * @example\n * formatCurrencyAndAmount(1050, 'USD') // \"$10.50\"\n * formatCurrencyAndAmount(1000000, 'USD', 0, 'compact') // \"$10K\"\n * formatCurrencyAndAmount(5000, 'EUR') // \"€50.00\"\n */\nexport const formatCurrencyAndAmount = (\n cents: number,\n currency: string,\n minimumFractionDigits?: number,\n notation?: 'standard' | 'scientific' | 'engineering' | 'compact',\n maximumFractionDigits?: number,\n): string => {\n const currencyNumberFormat = new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency,\n minimumFractionDigits,\n maximumFractionDigits,\n notation,\n })\n return currencyNumberFormat.format(cents / 100)\n}\n\n/**\n * Convert cents to float (dollars)\n * @param cents - Amount in cents\n * @returns Amount in dollars as a float\n *\n * @example\n * convertCentsToFloat(1050) // 10.5\n */\nexport const convertCentsToFloat = (cents: number): number => {\n return cents / 100\n}\n\n/**\n * Convert float (dollars) to cents\n * @param amount - Amount in dollars\n * @returns Amount in cents as an integer\n *\n * @example\n * convertFloatToCents(10.5) // 1050\n */\nexport const convertFloatToCents = (amount: number): number => {\n return Math.round(amount * 100)\n}\n\n/**\n * Format currency in compact notation (e.g., $1.2K, $3.5M)\n * @param cents - Amount in cents\n * @param currency - Currency code\n * @returns Compact formatted currency string\n *\n * @example\n * formatCurrencyCompact(1200000, 'USD') // \"$12K\"\n * formatCurrencyCompact(3500000000, 'USD') // \"$35M\"\n */\nexport const formatCurrencyCompact = (cents: number, currency: string): string => {\n return formatCurrencyAndAmount(cents, currency, 0, 'compact', 1)\n}\n\n/**\n * Format currency without cents (whole dollars only)\n * @param cents - Amount in cents\n * @param currency - Currency code\n * @returns Formatted currency string without cents\n *\n * @example\n * formatCurrencyWhole(1050, 'USD') // \"$10\"\n * formatCurrencyWhole(1099, 'USD') // \"$11\" (rounds)\n */\nexport const formatCurrencyWhole = (cents: number, currency: string): string => {\n return formatCurrencyAndAmount(cents, currency, 0, 'standard', 0)\n}\n\n/**\n * Get currency symbol for a currency code\n * @param currency - Currency code (e.g., 'USD', 'EUR')\n * @returns Currency symbol (e.g., '$', '€')\n *\n * @example\n * getCurrencySymbol('USD') // \"$\"\n * getCurrencySymbol('EUR') // \"€\"\n * getCurrencySymbol('GBP') // \"£\"\n */\nexport const getCurrencySymbol = (currency: string): string => {\n const formatter = new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency,\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n })\n\n // Format zero to extract symbol\n const parts = formatter.formatToParts(0)\n const symbolPart = parts.find((part) => part.type === 'currency')\n return symbolPart?.value || currency\n}\n\n/**\n * Format a price range (e.g., \"$10 - $50\")\n * @param minCents - Minimum amount in cents\n * @param maxCents - Maximum amount in cents\n * @param currency - Currency code\n * @returns Formatted price range string\n *\n * @example\n * formatPriceRange(1000, 5000, 'USD') // \"$10 - $50\"\n */\nexport const formatPriceRange = (\n minCents: number,\n maxCents: number,\n currency: string,\n): string => {\n const min = formatCurrencyAndAmount(minCents, currency)\n const max = formatCurrencyAndAmount(maxCents, currency)\n return `${min} - ${max}`\n}\n\n/**\n * Check if an amount is zero\n * @param cents - Amount in cents\n * @returns True if amount is zero\n */\nexport const isZeroAmount = (cents: number): boolean => {\n return cents === 0\n}\n\n/**\n * Check if an amount is negative\n * @param cents - Amount in cents\n * @returns True if amount is negative\n */\nexport const isNegativeAmount = (cents: number): boolean => {\n return cents < 0\n}\n\n/**\n * Calculate percentage of an amount\n * @param cents - Amount in cents\n * @param percentage - Percentage (0-100)\n * @returns Calculated amount in cents\n *\n * @example\n * calculatePercentage(10000, 20) // 2000 (20% of $100)\n */\nexport const calculatePercentage = (cents: number, percentage: number): number => {\n return Math.round((cents * percentage) / 100)\n}\n\n/**\n * Add amounts together\n * @param amounts - Array of amounts in cents\n * @returns Sum in cents\n *\n * @example\n * addAmounts([1000, 2000, 3000]) // 6000\n */\nexport const addAmounts = (...amounts: number[]): number => {\n return amounts.reduce((sum, amount) => sum + amount, 0)\n}\n\n/**\n * Money utilities namespace for convenience\n */\nexport const Money = {\n format: formatCurrencyAndAmount,\n formatCompact: formatCurrencyCompact,\n formatWhole: formatCurrencyWhole,\n formatRange: formatPriceRange,\n fromCents: convertCentsToFloat,\n toCents: convertFloatToCents,\n getSymbol: getCurrencySymbol,\n isZero: isZeroAmount,\n isNegative: isNegativeAmount,\n calculatePercentage,\n add: addAmounts,\n}\n","\"use client\";\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from '../../ui/card'\nimport { Badge } from '../../ui/badge'\nimport { Button } from '../../ui/button'\nimport { Skeleton } from '../../ui/skeleton'\nimport { UsageBar } from '../components/UsageBar'\nimport { FeatureList } from '../components/FeatureList'\nimport { WarningBanner } from '../components/WarningBanner'\nimport { Money } from '../../../utils/money'\nimport { cn } from '@/utils/cn'\nimport type { PortalSubscription, PortalAvailablePlan } from '../../../client/types'\n\ninterface SubscriptionTabProps {\n subscription: PortalSubscription | null\n availablePlans: PortalAvailablePlan[]\n onChangePlan: () => void\n onCancelSubscription: () => void\n onReactivate: () => void\n onAddPaymentMethod: () => void\n isLoading?: boolean\n className?: string\n}\n\nfunction formatInterval(interval: string, intervalCount: number): string {\n if (intervalCount === 1) {\n return interval\n }\n return `${intervalCount} ${interval}s`\n}\n\nfunction getStatusBadge(status: PortalSubscription['status'], cancelAtPeriodEnd: boolean) {\n if (cancelAtPeriodEnd) {\n return <Badge variant=\"warning\">Cancels at period end</Badge>\n }\n\n switch (status) {\n case 'active':\n return <Badge variant=\"success\">Active</Badge>\n case 'trialing':\n return <Badge variant=\"secondary\">Trial</Badge>\n case 'past_due':\n return <Badge variant=\"destructive\">Past Due</Badge>\n case 'canceled':\n return <Badge variant=\"outline\">Canceled</Badge>\n case 'unpaid':\n return <Badge variant=\"destructive\">Unpaid</Badge>\n default:\n return <Badge variant=\"outline\">{status}</Badge>\n }\n}\n\nfunction NoSubscription({ onBrowsePlans }: { onBrowsePlans: () => void }) {\n return (\n <Card>\n <CardContent className=\"flex flex-col items-center justify-center py-12 text-center\">\n <p className=\"text-muted-foreground mb-4\">You don't have an active subscription.</p>\n <Button onClick={onBrowsePlans}>Browse Plans</Button>\n </CardContent>\n </Card>\n )\n}\n\nfunction SubscriptionTabSkeleton() {\n return (\n <div className=\"space-y-6\">\n <Card>\n <CardHeader>\n <Skeleton className=\"h-6 w-32\" />\n <Skeleton className=\"h-4 w-48\" />\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-4 w-36\" />\n <div className=\"flex gap-2\">\n <Skeleton className=\"h-9 w-32\" />\n <Skeleton className=\"h-9 w-40\" />\n </div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <Skeleton className=\"h-5 w-20\" />\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <Skeleton className=\"h-12 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n </CardContent>\n </Card>\n </div>\n )\n}\n\nexport function SubscriptionTab({\n subscription,\n onChangePlan,\n onCancelSubscription,\n onReactivate,\n onAddPaymentMethod,\n isLoading,\n className,\n}: SubscriptionTabProps) {\n if (isLoading) {\n return <SubscriptionTabSkeleton />\n }\n\n if (!subscription) {\n return <NoSubscription onBrowsePlans={onChangePlan} />\n }\n\n const {\n product,\n price,\n status,\n currentPeriodEnd,\n cancelAtPeriodEnd,\n trialEnd,\n features,\n } = subscription\n\n const formattedPrice = Money.format(price.amount, price.currency)\n const interval = formatInterval(price.interval, price.intervalCount)\n const nextBillingDate = new Date(currentPeriodEnd).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n })\n\n // Filter usage-based features\n const usageFeatures = features.filter(\n (f) => (f.type === 'usage_quota' || f.type === 'numeric_limit') && f.usage\n )\n\n // Check for trial ending soon (within 3 days)\n const isTrialEndingSoon =\n status === 'trialing' &&\n trialEnd &&\n new Date(trialEnd).getTime() - Date.now() < 3 * 24 * 60 * 60 * 1000\n\n return (\n <div className={cn('space-y-6', className)}>\n {/* Warning Banners */}\n {status === 'past_due' && (\n <WarningBanner\n type=\"past_due\"\n message=\"Your last payment was declined. Update your payment method to avoid service interruption.\"\n actionLabel=\"Update Payment\"\n onAction={onAddPaymentMethod}\n />\n )}\n\n {isTrialEndingSoon && trialEnd && (\n <WarningBanner\n type=\"trial_ending\"\n message={`Your trial ends on ${new Date(trialEnd).toLocaleDateString()}. Add a payment method to continue.`}\n actionLabel=\"Add Payment Method\"\n onAction={onAddPaymentMethod}\n />\n )}\n\n {cancelAtPeriodEnd && (\n <WarningBanner\n type=\"subscription_canceled\"\n message={`Your subscription will end on ${nextBillingDate}. You'll have access until then.`}\n actionLabel=\"Reactivate\"\n onAction={onReactivate}\n />\n )}\n\n {/* Current Plan Card */}\n <Card>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <div>\n <CardTitle>{product.name}</CardTitle>\n <CardDescription>\n {formattedPrice} / {interval}\n </CardDescription>\n </div>\n {getStatusBadge(status, cancelAtPeriodEnd)}\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"text-sm text-muted-foreground\">\n <p>\n {cancelAtPeriodEnd ? 'Access until' : 'Next billing'}:{' '}\n <span className=\"font-medium text-foreground\">{nextBillingDate}</span>\n </p>\n </div>\n\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"outline\" onClick={onChangePlan}>\n View Other Plans\n </Button>\n {!cancelAtPeriodEnd && status !== 'canceled' && (\n <Button\n variant=\"ghost\"\n className=\"text-destructive hover:text-destructive\"\n onClick={onCancelSubscription}\n >\n Cancel Subscription\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n\n {/* Usage Section */}\n {usageFeatures.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Usage This Billing Period</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n {usageFeatures.map((feature) => (\n <UsageBar\n key={feature.id}\n title={feature.title}\n usage={feature.usage!}\n unit={feature.properties.unit as string | undefined}\n />\n ))}\n </CardContent>\n </Card>\n )}\n\n {/* Features Section */}\n {features.some((f) => f.type === 'boolean_flag' && f.enabled) && (\n <Card>\n <CardContent className=\"pt-6\">\n <FeatureList features={features} />\n </CardContent>\n </Card>\n )}\n </div>\n )\n}\n","\"use client\";\nimport { Card, CardContent } from '../../ui/card'\nimport { Badge } from '../../ui/badge'\nimport { Button } from '../../ui/button'\nimport { cn } from '@/utils/cn'\nimport { Money } from '../../../utils/money'\nimport type { PortalInvoice } from '../../../client/types'\n\ninterface InvoiceCardProps {\n invoice: PortalInvoice\n onRetry?: (invoiceId: string) => void\n onDownload?: (pdfUrl: string) => void\n isRetrying?: boolean\n className?: string\n}\n\nfunction DownloadIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <polyline points=\"7 10 12 15 17 10\" />\n <line x1=\"12\" x2=\"12\" y1=\"15\" y2=\"3\" />\n </svg>\n )\n}\n\nfunction getStatusBadge(status: PortalInvoice['status']) {\n switch (status) {\n case 'paid':\n return <Badge variant=\"success\">Paid</Badge>\n case 'open':\n return <Badge variant=\"secondary\">Open</Badge>\n case 'failed':\n return <Badge variant=\"destructive\">Failed</Badge>\n case 'void':\n return <Badge variant=\"outline\">Void</Badge>\n default:\n return <Badge variant=\"outline\">{status}</Badge>\n }\n}\n\nexport function InvoiceCard({\n invoice,\n onRetry,\n onDownload,\n isRetrying,\n className,\n}: InvoiceCardProps) {\n const formattedDate = new Date(invoice.date).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n })\n\n const formattedAmount = Money.format(invoice.amount, invoice.currency)\n\n return (\n <Card className={cn('', className)}>\n <CardContent className=\"p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{invoice.number}</span>\n {getStatusBadge(invoice.status)}\n </div>\n <p className=\"text-sm text-muted-foreground\">{formattedDate}</p>\n {invoice.lineItems.length > 0 && (\n <p className=\"text-sm text-muted-foreground\">\n {invoice.lineItems[0].description}\n </p>\n )}\n </div>\n <div className=\"text-right\">\n <p className=\"font-semibold\">{formattedAmount}</p>\n </div>\n </div>\n\n {invoice.status === 'failed' && invoice.failureReason && (\n <div className=\"mt-3 rounded-md bg-destructive/10 p-2 text-sm text-destructive\">\n {invoice.failureReason}\n </div>\n )}\n\n <div className=\"mt-4 flex items-center gap-2\">\n {invoice.status === 'failed' && onRetry && (\n <Button\n size=\"sm\"\n variant=\"default\"\n onClick={() => onRetry(invoice.id)}\n disabled={isRetrying}\n >\n {isRetrying ? 'Retrying...' : 'Retry Payment'}\n </Button>\n )}\n {invoice.pdfUrl && onDownload && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => onDownload(invoice.pdfUrl!)}\n >\n <DownloadIcon className=\"mr-1\" />\n Download PDF\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n )\n}\n","\"use client\";\nimport { Card, CardContent } from '../../ui/card'\nimport { Skeleton } from '../../ui/skeleton'\nimport { InvoiceCard } from '../components/InvoiceCard'\nimport { cn } from '@/utils/cn'\nimport type { PortalInvoice } from '../../../client/types'\n\ninterface InvoicesTabProps {\n invoices: PortalInvoice[]\n onRetryInvoice: (invoiceId: string) => void\n onDownloadInvoice: (pdfUrl: string) => void\n retryingInvoiceId?: string\n isLoading?: boolean\n className?: string\n}\n\nfunction NoInvoices() {\n return (\n <Card>\n <CardContent className=\"flex flex-col items-center justify-center py-12 text-center\">\n <p className=\"text-muted-foreground\">No invoices yet.</p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Your first invoice will appear here after your first billing cycle.\n </p>\n </CardContent>\n </Card>\n )\n}\n\nfunction InvoicesTabSkeleton() {\n return (\n <div className=\"space-y-4\">\n {[1, 2, 3].map((i) => (\n <Card key={i}>\n <CardContent className=\"p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-5 w-32\" />\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-4 w-48\" />\n </div>\n <Skeleton className=\"h-5 w-16\" />\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Skeleton className=\"h-8 w-24\" />\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )\n}\n\nexport function InvoicesTab({\n invoices,\n onRetryInvoice,\n onDownloadInvoice,\n retryingInvoiceId,\n isLoading,\n className,\n}: InvoicesTabProps) {\n if (isLoading) {\n return <InvoicesTabSkeleton />\n }\n\n if (invoices.length === 0) {\n return <NoInvoices />\n }\n\n return (\n <div className={cn('space-y-4', className)}>\n <h3 className=\"font-medium\">Invoice History</h3>\n {invoices.map((invoice) => (\n <InvoiceCard\n key={invoice.id}\n invoice={invoice}\n onRetry={onRetryInvoice}\n onDownload={onDownloadInvoice}\n isRetrying={retryingInvoiceId === invoice.id}\n />\n ))}\n </div>\n )\n}\n","\"use client\";\nimport { Card, CardContent } from '../../ui/card'\nimport { Badge } from '../../ui/badge'\nimport { Button } from '../../ui/button'\nimport { cn } from '@/utils/cn'\nimport type { PortalPaymentMethod, PortalCardDetails } from '../../../client/types'\n\ninterface PaymentMethodCardProps {\n paymentMethod: PortalPaymentMethod\n onSetDefault?: (id: string) => void\n onRemove?: (id: string) => void\n isSettingDefault?: boolean\n isRemoving?: boolean\n className?: string\n}\n\nfunction getCardIcon(brand: PortalCardDetails['brand']) {\n // Simple card brand icons using unicode/emoji\n const icons: Record<string, string> = {\n visa: '💳',\n mastercard: '💳',\n amex: '💳',\n discover: '💳',\n diners: '💳',\n jcb: '💳',\n unionpay: '💳',\n }\n return icons[brand] || '💳'\n}\n\nfunction formatCardBrand(brand: string): string {\n const brandNames: Record<string, string> = {\n visa: 'Visa',\n mastercard: 'Mastercard',\n amex: 'American Express',\n discover: 'Discover',\n diners: 'Diners Club',\n jcb: 'JCB',\n unionpay: 'UnionPay',\n }\n return brandNames[brand] || brand.charAt(0).toUpperCase() + brand.slice(1)\n}\n\nexport function PaymentMethodCard({\n paymentMethod,\n onSetDefault,\n onRemove,\n isSettingDefault,\n isRemoving,\n className,\n}: PaymentMethodCardProps) {\n const { id, card, isDefault } = paymentMethod\n\n if (!card) {\n return null\n }\n\n const expiryDate = `${card.expMonth.toString().padStart(2, '0')}/${card.expYear}`\n\n return (\n <Card className={cn('', className)}>\n <CardContent className=\"p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-3\">\n <span className=\"text-2xl\">{getCardIcon(card.brand)}</span>\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">\n {formatCardBrand(card.brand)} •••• {card.last4}\n </span>\n {isDefault && <Badge variant=\"secondary\">Default</Badge>}\n </div>\n <p className=\"text-sm text-muted-foreground\">Expires {expiryDate}</p>\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 flex items-center gap-2\">\n {!isDefault && onSetDefault && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => onSetDefault(id)}\n disabled={isSettingDefault}\n >\n {isSettingDefault ? 'Setting...' : 'Set as Default'}\n </Button>\n )}\n {onRemove && !isDefault && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => onRemove(id)}\n disabled={isRemoving}\n className=\"text-destructive hover:text-destructive\"\n >\n {isRemoving ? 'Removing...' : 'Remove'}\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n )\n}\n","\"use client\";\nimport { Card, CardContent } from '../../ui/card'\nimport { Button } from '../../ui/button'\nimport { Skeleton } from '../../ui/skeleton'\nimport { PaymentMethodCard } from '../components/PaymentMethodCard'\nimport { cn } from '@/utils/cn'\nimport type { PortalPaymentMethod } from '../../../client/types'\n\ninterface PaymentMethodsTabProps {\n paymentMethods: PortalPaymentMethod[]\n onAddPaymentMethod: () => void\n onSetDefault: (id: string) => void\n onRemove: (id: string) => void\n settingDefaultId?: string\n removingId?: string\n isLoading?: boolean\n className?: string\n}\n\nfunction PlusIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <path d=\"M5 12h14\" />\n <path d=\"M12 5v14\" />\n </svg>\n )\n}\n\nfunction NoPaymentMethods({ onAdd }: { onAdd: () => void }) {\n return (\n <Card>\n <CardContent className=\"flex flex-col items-center justify-center py-12 text-center\">\n <p className=\"text-muted-foreground mb-4\">No payment methods on file.</p>\n <Button onClick={onAdd}>\n <PlusIcon className=\"mr-2\" />\n Add Payment Method\n </Button>\n </CardContent>\n </Card>\n )\n}\n\nfunction PaymentMethodsTabSkeleton() {\n return (\n <div className=\"space-y-4\">\n {[1, 2].map((i) => (\n <Card key={i}>\n <CardContent className=\"p-4\">\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"h-8 w-8 rounded\" />\n <div className=\"space-y-2\">\n <Skeleton className=\"h-5 w-40\" />\n <Skeleton className=\"h-4 w-24\" />\n </div>\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Skeleton className=\"h-8 w-28\" />\n <Skeleton className=\"h-8 w-20\" />\n </div>\n </CardContent>\n </Card>\n ))}\n <Skeleton className=\"h-10 w-44\" />\n </div>\n )\n}\n\nexport function PaymentMethodsTab({\n paymentMethods,\n onAddPaymentMethod,\n onSetDefault,\n onRemove,\n settingDefaultId,\n removingId,\n isLoading,\n className,\n}: PaymentMethodsTabProps) {\n if (isLoading) {\n return <PaymentMethodsTabSkeleton />\n }\n\n if (paymentMethods.length === 0) {\n return <NoPaymentMethods onAdd={onAddPaymentMethod} />\n }\n\n // Sort to show default first\n const sortedMethods = [...paymentMethods].sort((a, b) => {\n if (a.isDefault && !b.isDefault) return -1\n if (!a.isDefault && b.isDefault) return 1\n return 0\n })\n\n return (\n <div className={cn('space-y-4', className)}>\n <h3 className=\"font-medium\">Payment Methods</h3>\n {sortedMethods.map((method) => (\n <PaymentMethodCard\n key={method.id}\n paymentMethod={method}\n onSetDefault={onSetDefault}\n onRemove={onRemove}\n isSettingDefault={settingDefaultId === method.id}\n isRemoving={removingId === method.id}\n />\n ))}\n <Button variant=\"outline\" onClick={onAddPaymentMethod}>\n <PlusIcon className=\"mr-2\" />\n Add New Payment Method\n </Button>\n </div>\n )\n}\n","\"use client\";\nimport { useState } from 'react'\nimport { Card, CardContent, CardHeader, CardTitle } from '../../ui/card'\nimport { Button } from '../../ui/button'\nimport { Input } from '../../ui/input'\nimport { Label } from '../../ui/label'\nimport { Select, SelectOption } from '../../ui/select'\nimport { Skeleton } from '../../ui/skeleton'\nimport { cn } from '@/utils/cn'\nimport type { PortalCustomer, PortalAddress } from '../../../client/types'\n\nconst COUNTRIES = [\n { code: 'US', name: 'United States' },\n { code: 'CA', name: 'Canada' },\n { code: 'GB', name: 'United Kingdom' },\n { code: 'AU', name: 'Australia' },\n { code: 'DE', name: 'Germany' },\n { code: 'FR', name: 'France' },\n { code: 'JP', name: 'Japan' },\n { code: 'IN', name: 'India' },\n { code: 'BR', name: 'Brazil' },\n { code: 'MX', name: 'Mexico' },\n]\n\ninterface SettingsTabProps {\n customer: PortalCustomer\n onSave: (data: { name?: string; email?: string; billingAddress?: PortalAddress }) => void\n isSaving?: boolean\n isLoading?: boolean\n className?: string\n}\n\nfunction SettingsTabSkeleton() {\n return (\n <div className=\"space-y-6\">\n <Card>\n <CardHeader>\n <Skeleton className=\"h-5 w-40\" />\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-12\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-12\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <Skeleton className=\"h-5 w-32\" />\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n <div className=\"grid grid-cols-2 gap-4\">\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n </CardContent>\n </Card>\n <Skeleton className=\"h-10 w-28\" />\n </div>\n )\n}\n\nexport function SettingsTab({\n customer,\n onSave,\n isSaving,\n isLoading,\n className,\n}: SettingsTabProps) {\n const [values, setValues] = useState({\n name: customer.name || '',\n email: customer.email || '',\n line1: customer.billingAddress?.line1 || '',\n line2: customer.billingAddress?.line2 || '',\n city: customer.billingAddress?.city || '',\n state: customer.billingAddress?.state || '',\n postalCode: customer.billingAddress?.postalCode || '',\n country: customer.billingAddress?.country || 'US',\n })\n const [errors, setErrors] = useState<Record<string, string>>({})\n\n if (isLoading) {\n return <SettingsTabSkeleton />\n }\n\n const set = (field: keyof typeof values) => (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {\n setValues((prev) => ({ ...prev, [field]: e.target.value }))\n if (errors[field]) setErrors((prev) => { const next = { ...prev }; delete next[field]; return next })\n }\n\n const validate = () => {\n const next: Record<string, string> = {}\n if (!values.name.trim()) next.name = 'Name is required'\n if (!values.email.trim()) {\n next.email = 'Email is required'\n } else if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(values.email)) {\n next.email = 'Invalid email address'\n }\n return next\n }\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault()\n const validationErrors = validate()\n if (Object.keys(validationErrors).length > 0) {\n setErrors(validationErrors)\n return\n }\n\n const billingAddress: PortalAddress | undefined =\n values.line1 || values.city || values.state || values.postalCode\n ? {\n line1: values.line1,\n line2: values.line2,\n city: values.city,\n state: values.state,\n postalCode: values.postalCode,\n country: values.country,\n }\n : undefined\n\n onSave({ name: values.name, email: values.email, billingAddress })\n }\n\n // Track if any field changed from the original customer data\n const isDirty =\n values.name !== (customer.name || '') ||\n values.email !== (customer.email || '') ||\n values.line1 !== (customer.billingAddress?.line1 || '') ||\n values.line2 !== (customer.billingAddress?.line2 || '') ||\n values.city !== (customer.billingAddress?.city || '') ||\n values.state !== (customer.billingAddress?.state || '') ||\n values.postalCode !== (customer.billingAddress?.postalCode || '') ||\n values.country !== (customer.billingAddress?.country || 'US')\n\n return (\n <form onSubmit={handleSubmit} className={cn('space-y-6', className)}>\n {/* Personal Information */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Personal Information</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"name\">Name</Label>\n <Input\n id=\"name\"\n value={values.name}\n onChange={set('name')}\n placeholder=\"Your name\"\n />\n {errors.name && (\n <p className=\"text-sm text-destructive\">{errors.name}</p>\n )}\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n value={values.email}\n onChange={set('email')}\n placeholder=\"your@email.com\"\n />\n {errors.email && (\n <p className=\"text-sm text-destructive\">{errors.email}</p>\n )}\n </div>\n </CardContent>\n </Card>\n\n {/* Billing Address */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Billing Address</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"line1\">Address Line 1</Label>\n <Input\n id=\"line1\"\n value={values.line1}\n onChange={set('line1')}\n placeholder=\"123 Main St\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"line2\">Address Line 2</Label>\n <Input\n id=\"line2\"\n value={values.line2}\n onChange={set('line2')}\n placeholder=\"Apt 4B (optional)\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"city\">City</Label>\n <Input\n id=\"city\"\n value={values.city}\n onChange={set('city')}\n placeholder=\"San Francisco\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"state\">State/Province</Label>\n <Input\n id=\"state\"\n value={values.state}\n onChange={set('state')}\n placeholder=\"CA\"\n />\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"postalCode\">ZIP/Postal Code</Label>\n <Input\n id=\"postalCode\"\n value={values.postalCode}\n onChange={set('postalCode')}\n placeholder=\"94102\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"country\">Country</Label>\n <Select id=\"country\" value={values.country} onChange={set('country')}>\n {COUNTRIES.map((country) => (\n <SelectOption key={country.code} value={country.code}>\n {country.name}\n </SelectOption>\n ))}\n </Select>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <Button type=\"submit\" disabled={isSaving || !isDirty}>\n {isSaving ? 'Saving...' : 'Save Changes'}\n </Button>\n </form>\n )\n}\n","\"use client\";\nimport * as React from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '../../ui/dialog'\nimport { Card, CardContent } from '../../ui/card'\nimport { Button } from '../../ui/button'\nimport { Badge } from '../../ui/badge'\nimport { Alert, AlertDescription } from '../../ui/alert'\nimport { Skeleton } from '../../ui/skeleton'\nimport { Money } from '../../../utils/money'\nimport { cn } from '@/utils/cn'\nimport { ProrationPreview } from '../components/ProrationPreview'\nimport { useAvailablePlans, usePreviewPlanChange, useChangePlan } from '../../../hooks/useSubscription'\nimport type { AvailablePlan, PreviewChangeResponse } from '../../../client/types'\n\ninterface ChangePlanModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n subscriptionId: string\n onSuccess?: () => void\n}\n\nfunction PlanCard({\n plan,\n isSelected,\n isCurrent,\n onSelect,\n disabled,\n}: {\n plan: AvailablePlan\n isSelected: boolean\n isCurrent: boolean\n onSelect: () => void\n disabled?: boolean\n}) {\n const formattedPrice = Money.format(plan.amount, plan.currency)\n const isUpgrade = !isCurrent && plan.amount > 0\n const isDowngrade = !isCurrent && !isUpgrade\n\n return (\n <Card\n className={cn(\n 'cursor-pointer transition-all hover:border-primary',\n isSelected && 'ring-2 ring-primary',\n isCurrent && 'opacity-60',\n disabled && 'pointer-events-none opacity-50'\n )}\n onClick={() => !isCurrent && !disabled && onSelect()}\n >\n <CardContent className=\"p-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-semibold\">{plan.product_name}</span>\n {isCurrent && <Badge variant=\"secondary\">Current</Badge>}\n {isUpgrade && <Badge variant=\"default\">Upgrade</Badge>}\n {isDowngrade && <Badge variant=\"outline\">Downgrade</Badge>}\n </div>\n {plan.description && (\n <p className=\"text-xs text-muted-foreground mt-1\">{plan.description}</p>\n )}\n <p className=\"text-sm font-medium mt-2\">\n {plan.is_free ? 'Free' : `${formattedPrice} / ${plan.interval}`}\n </p>\n </div>\n {!isCurrent && (\n <div className=\"h-5 w-5 rounded-full border-2 border-primary flex items-center justify-center flex-shrink-0 ml-3\">\n {isSelected && (\n <div className=\"h-2.5 w-2.5 rounded-full bg-primary\" />\n )}\n </div>\n )}\n </div>\n </CardContent>\n </Card>\n )\n}\n\nexport function ChangePlanModal({\n open,\n onOpenChange,\n subscriptionId,\n onSuccess,\n}: ChangePlanModalProps) {\n const [selectedPlan, setSelectedPlan] = React.useState<AvailablePlan | null>(null)\n const [preview, setPreview] = React.useState<PreviewChangeResponse | null>(null)\n const [showConfirmation, setShowConfirmation] = React.useState(false)\n\n // Fetch available plans\n const { data: availablePlans, isLoading: isLoadingPlans, error: plansError } = useAvailablePlans(\n subscriptionId,\n { enabled: open }\n )\n\n // Preview mutation\n const previewMutation = usePreviewPlanChange()\n\n // Change plan mutation\n const changePlanMutation = useChangePlan({\n onSuccess: () => {\n onSuccess?.()\n onOpenChange(false)\n },\n })\n\n // Reset state when modal opens/closes\n React.useEffect(() => {\n if (!open) {\n setSelectedPlan(null)\n setPreview(null)\n setShowConfirmation(false)\n }\n }, [open])\n\n // Handle plan selection and fetch preview\n const handleSelectPlan = async (plan: AvailablePlan) => {\n setSelectedPlan(plan)\n setShowConfirmation(false)\n setPreview(null)\n\n // Fetch preview\n try {\n const previewData = await previewMutation.mutateAsync({\n subscriptionId,\n input: {\n new_price_id: plan.price_id,\n effective_date: 'immediate', // Can be made configurable in Phase 2\n },\n })\n\n setPreview(previewData)\n setShowConfirmation(true)\n } catch (error) {\n console.error('Failed to preview plan change:', error)\n setSelectedPlan(null)\n }\n }\n\n // Handle plan change confirmation\n const handleConfirm = async () => {\n if (!selectedPlan || !preview) return\n\n try {\n await changePlanMutation.mutateAsync({\n subscriptionId,\n input: {\n new_price_id: selectedPlan.price_id,\n confirm_amount: preview.proration.immediate_payment,\n effective_date: 'immediate',\n },\n })\n } catch (error) {\n console.error('Failed to change plan:', error)\n }\n }\n\n const allPlans = [\n ...(availablePlans?.available_upgrades || []),\n ...(availablePlans?.available_downgrades || []),\n ]\n\n const currentPlanId = availablePlans?.current_plan?.price_id\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-2xl max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle>\n {showConfirmation ? 'Confirm Plan Change' : 'Change Your Plan'}\n </DialogTitle>\n {!showConfirmation && availablePlans?.current_plan && (\n <DialogDescription>\n You're currently on:{' '}\n <strong>\n {availablePlans.current_plan.product_name} (\n {Money.format(\n availablePlans.current_plan.amount,\n availablePlans.current_plan.currency\n )}\n /{availablePlans.current_plan.interval})\n </strong>\n </DialogDescription>\n )}\n </DialogHeader>\n\n <div className=\"py-4\">\n {/* Loading State */}\n {isLoadingPlans && (\n <div className=\"space-y-3\">\n <Skeleton className=\"h-20 w-full\" />\n <Skeleton className=\"h-20 w-full\" />\n <Skeleton className=\"h-20 w-full\" />\n </div>\n )}\n\n {/* Error State */}\n {plansError && (\n <Alert variant=\"destructive\">\n <AlertDescription>\n Failed to load available plans. Please try again.\n </AlertDescription>\n </Alert>\n )}\n\n {/* Plan Selection View */}\n {!isLoadingPlans && !plansError && !showConfirmation && (\n <div className=\"space-y-3\">\n {allPlans.length === 0 ? (\n <Alert>\n <AlertDescription>\n No other plans are currently available. Contact support if you need assistance.\n </AlertDescription>\n </Alert>\n ) : (\n <>\n {allPlans.map((plan) => (\n <PlanCard\n key={plan.price_id}\n plan={plan}\n isSelected={selectedPlan?.price_id === plan.price_id}\n isCurrent={plan.price_id === currentPlanId}\n onSelect={() => handleSelectPlan(plan)}\n disabled={previewMutation.isPending}\n />\n ))}\n\n {/* Restrictions */}\n {availablePlans?.restrictions && availablePlans.restrictions.length > 0 && (\n <Alert className=\"mt-4\">\n <AlertDescription>\n <p className=\"font-semibold mb-2\">Plan Change Restrictions:</p>\n <ul className=\"list-disc list-inside space-y-1 text-sm\">\n {availablePlans.restrictions.map((restriction, idx) => (\n <li key={idx}>{restriction}</li>\n ))}\n </ul>\n </AlertDescription>\n </Alert>\n )}\n </>\n )}\n </div>\n )}\n\n {/* Preview Loading State */}\n {previewMutation.isPending && selectedPlan && (\n <div className=\"flex items-center justify-center py-8\">\n <div className=\"flex items-center gap-2\">\n <svg className=\"animate-spin h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n <span>Calculating proration...</span>\n </div>\n </div>\n )}\n\n {/* Preview Error State */}\n {previewMutation.isError && (\n <Alert variant=\"destructive\">\n <AlertDescription>\n Failed to calculate proration. Please try again.\n </AlertDescription>\n </Alert>\n )}\n\n {/* Confirmation View with Proration */}\n {showConfirmation && preview && (\n <div>\n <Alert className=\"mb-4\">\n <AlertDescription className=\"text-sm\">\n Please review the details below before confirming your plan change.\n </AlertDescription>\n </Alert>\n\n <ProrationPreview preview={preview} />\n </div>\n )}\n </div>\n\n <DialogFooter>\n {!showConfirmation ? (\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n Cancel\n </Button>\n ) : (\n <>\n <Button\n variant=\"outline\"\n onClick={() => {\n setShowConfirmation(false)\n setPreview(null)\n setSelectedPlan(null)\n }}\n disabled={changePlanMutation.isPending}\n >\n Back\n </Button>\n <Button\n onClick={handleConfirm}\n disabled={changePlanMutation.isPending}\n >\n {changePlanMutation.isPending ? (\n <span className=\"flex items-center gap-2\">\n <svg className=\"animate-spin h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n Processing...\n </span>\n ) : (\n `Confirm ${preview?.change_type === 'upgrade' ? 'Upgrade' : 'Downgrade'}`\n )}\n </Button>\n </>\n )}\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","\"use client\";\nimport { Card, CardContent, CardHeader, CardTitle } from '../../ui/card'\nimport { Alert, AlertDescription } from '../../ui/alert'\nimport { Badge } from '../../ui/badge'\nimport { Money } from '../../../utils/money'\nimport type { PreviewChangeResponse } from '../../../client/types'\n\ninterface ProrationPreviewProps {\n preview: PreviewChangeResponse\n}\n\nexport function ProrationPreview({ preview }: ProrationPreviewProps) {\n const { current_plan, new_plan, proration, change_type, next_billing_date, notes } = preview\n\n const isUpgrade = change_type === 'upgrade'\n\n return (\n <div className=\"space-y-4\">\n {/* Plan Comparison */}\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">Plan Change Summary</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {/* Current Plan */}\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">Current Plan:</span>\n <div className=\"text-right\">\n <div className=\"font-medium\">{current_plan.product_name}</div>\n <div className=\"text-muted-foreground text-xs\">\n {Money.format(current_plan.amount, current_plan.currency)} / {current_plan.interval}\n </div>\n </div>\n </div>\n\n {/* Arrow */}\n <div className=\"flex justify-center\">\n <svg\n className=\"w-4 h-4 text-muted-foreground\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 14l-7 7m0 0l-7-7m7 7V3\" />\n </svg>\n </div>\n\n {/* New Plan */}\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">New Plan:</span>\n <div className=\"text-right\">\n <div className=\"font-medium flex items-center gap-2 justify-end\">\n {new_plan.product_name}\n <Badge variant={isUpgrade ? 'default' : 'secondary'} className=\"text-xs\">\n {isUpgrade ? 'Upgrade' : 'Downgrade'}\n </Badge>\n </div>\n <div className=\"text-muted-foreground text-xs\">\n {Money.format(new_plan.amount, new_plan.currency)} / {new_plan.interval}\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n\n {/* Proration Breakdown */}\n {isUpgrade && proration.immediate_payment > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">Billing Details</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {/* Credit for unused time */}\n {proration.unused_time_credit > 0 && (\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-muted-foreground\">Credit for unused time:</span>\n <span className=\"text-green-600 font-medium\">\n -{Money.format(proration.unused_time_credit, current_plan.currency)}\n </span>\n </div>\n )}\n\n {/* New plan charge */}\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-muted-foreground\">Prorated charge for new plan:</span>\n <span className=\"font-medium\">\n {Money.format(proration.new_plan_charge, new_plan.currency)}\n </span>\n </div>\n\n {/* Divider */}\n <div className=\"border-t my-2\" />\n\n {/* Total */}\n <div className=\"flex justify-between text-base font-semibold\">\n <span>Due Today:</span>\n <span>{Money.format(proration.immediate_payment, new_plan.currency)}</span>\n </div>\n\n {/* Next billing date */}\n <div className=\"text-xs text-muted-foreground mt-3\">\n Next billing: {new Date(next_billing_date).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n })}\n </div>\n </CardContent>\n </Card>\n )}\n\n {/* Downgrade Notice */}\n {!isUpgrade && (\n <Alert>\n <AlertDescription className=\"text-sm\">\n Your plan will change to <strong>{new_plan.product_name}</strong> on{' '}\n <strong>\n {new Date(next_billing_date).toLocaleDateString(undefined, {\n month: 'long',\n day: 'numeric',\n year: 'numeric',\n })}\n </strong>\n . You'll keep access to your current plan features until then.\n </AlertDescription>\n </Alert>\n )}\n\n {/* Additional Notes */}\n {notes && notes.length > 0 && (\n <Alert>\n <AlertDescription>\n <ul className=\"list-disc list-inside space-y-1 text-sm\">\n {notes.map((note, idx) => (\n <li key={idx}>{note}</li>\n ))}\n </ul>\n </AlertDescription>\n </Alert>\n )}\n </div>\n )\n}\n","\"use client\";\nimport * as React from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '../../ui/dialog'\nimport { Button } from '../../ui/button'\nimport { Checkbox } from '../../ui/checkbox'\nimport { RadioGroup, RadioGroupItem } from '../../ui/radio-group'\nimport { Textarea } from '../../ui/textarea'\nimport { Label } from '../../ui/label'\nimport type { PortalCancelSubscriptionInput } from '../../../client/types'\n\ntype CancellationReason = PortalCancelSubscriptionInput['cancellationReason']\n\ninterface CancelSubscriptionModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n periodEndDate: string\n onConfirm: (input: PortalCancelSubscriptionInput) => void\n isCanceling?: boolean\n}\n\nconst CANCELLATION_REASONS: { value: CancellationReason; label: string }[] = [\n { value: 'too_expensive', label: 'Too expensive' },\n { value: 'missing_features', label: 'Missing features I need' },\n { value: 'found_alternative', label: 'Found a better alternative' },\n { value: 'no_longer_needed', label: 'No longer need the service' },\n { value: 'other', label: 'Other' },\n]\n\nexport function CancelSubscriptionModal({\n open,\n onOpenChange,\n periodEndDate,\n onConfirm,\n isCanceling,\n}: CancelSubscriptionModalProps) {\n const [selectedReasons, setSelectedReasons] = React.useState<CancellationReason[]>([])\n const [feedback, setFeedback] = React.useState('')\n const [cancelTiming, setCancelTiming] = React.useState<'period_end' | 'immediately'>('period_end')\n\n // Reset form when modal opens\n React.useEffect(() => {\n if (open) {\n setSelectedReasons([])\n setFeedback('')\n setCancelTiming('period_end')\n }\n }, [open])\n\n const formattedEndDate = new Date(periodEndDate).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n })\n\n const toggleReason = (reason: CancellationReason) => {\n setSelectedReasons((prev) =>\n prev.includes(reason)\n ? prev.filter((r) => r !== reason)\n : [...prev, reason]\n )\n }\n\n const handleConfirm = () => {\n onConfirm({\n cancelAtPeriodEnd: cancelTiming === 'period_end',\n cancellationReason: selectedReasons[0], // API accepts single reason\n feedback: feedback || undefined,\n })\n }\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>Cancel Subscription</DialogTitle>\n <DialogDescription>\n We're sorry to see you go! Help us improve by telling us why you're canceling.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-6 py-4\">\n {/* Reasons */}\n <div className=\"space-y-3\">\n <Label className=\"text-sm font-medium\">Reason for canceling</Label>\n {CANCELLATION_REASONS.map((reason) => (\n <label\n key={reason.value}\n className=\"flex items-center gap-2 cursor-pointer\"\n >\n <Checkbox\n checked={selectedReasons.includes(reason.value)}\n onCheckedChange={() => toggleReason(reason.value)}\n />\n <span className=\"text-sm\">{reason.label}</span>\n </label>\n ))}\n </div>\n\n {/* Feedback */}\n <div className=\"space-y-2\">\n <Label htmlFor=\"feedback\" className=\"text-sm font-medium\">\n Additional feedback (optional)\n </Label>\n <Textarea\n id=\"feedback\"\n value={feedback}\n onChange={(e) => setFeedback(e.target.value)}\n placeholder=\"What could we have done better?\"\n className=\"resize-none\"\n rows={3}\n />\n </div>\n\n {/* Timing */}\n <div className=\"space-y-3\">\n <Label className=\"text-sm font-medium\">When would you like to cancel?</Label>\n <RadioGroup\n value={cancelTiming}\n onValueChange={(v) => setCancelTiming(v as 'period_end' | 'immediately')}\n >\n <label className=\"flex items-start gap-2 cursor-pointer\">\n <RadioGroupItem value=\"period_end\" className=\"mt-1\" />\n <div>\n <span className=\"text-sm font-medium\">Cancel at period end ({formattedEndDate})</span>\n <p className=\"text-xs text-muted-foreground\">\n You'll keep access until then.\n </p>\n </div>\n </label>\n <label className=\"flex items-start gap-2 cursor-pointer\">\n <RadioGroupItem value=\"immediately\" className=\"mt-1\" />\n <div>\n <span className=\"text-sm font-medium\">Cancel immediately</span>\n <p className=\"text-xs text-muted-foreground\">\n You'll lose access now. No refunds.\n </p>\n </div>\n </label>\n </RadioGroup>\n </div>\n </div>\n\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={isCanceling}\n >\n Keep Subscription\n </Button>\n <Button\n variant=\"destructive\"\n onClick={handleConfirm}\n disabled={isCanceling}\n >\n {isCanceling ? 'Canceling...' : 'Confirm Cancellation'}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","\"use client\";\nimport * as React from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '../../ui/dialog'\nimport { Button } from '../../ui/button'\nimport { Checkbox } from '../../ui/checkbox'\nimport { Label } from '../../ui/label'\nimport { Skeleton } from '../../ui/skeleton'\nimport { cn } from '@/utils/cn'\n\n// Stripe imports\nimport {\n Elements,\n CardElement,\n useStripe,\n useElements,\n} from '@stripe/react-stripe-js'\nimport { loadStripe, type Stripe } from '@stripe/stripe-js'\n\ninterface AddPaymentMethodModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n onSuccess: (paymentMethodId: string, setAsDefault: boolean) => void\n clientSecret?: string\n stripePublishableKey?: string\n isLoading?: boolean\n}\n\n// Card element styling\nconst cardElementOptions = {\n style: {\n base: {\n fontSize: '16px',\n color: 'hsl(var(--foreground))',\n '::placeholder': {\n color: 'hsl(var(--muted-foreground))',\n },\n },\n invalid: {\n color: 'hsl(var(--destructive))',\n },\n },\n}\n\ninterface PaymentFormProps {\n clientSecret: string\n onSuccess: (paymentMethodId: string, setAsDefault: boolean) => void\n onCancel: () => void\n}\n\nfunction PaymentForm({ clientSecret, onSuccess, onCancel }: PaymentFormProps) {\n const stripe = useStripe()\n const elements = useElements()\n const [isSubmitting, setIsSubmitting] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const [setAsDefault, setSetAsDefault] = React.useState(true)\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!stripe || !elements) {\n return\n }\n\n setIsSubmitting(true)\n setError(null)\n\n const cardElement = elements.getElement(CardElement)\n if (!cardElement) {\n setError('Card element not found')\n setIsSubmitting(false)\n return\n }\n\n try {\n const { setupIntent, error: setupError } = await stripe.confirmCardSetup(\n clientSecret,\n {\n payment_method: {\n card: cardElement,\n },\n }\n )\n\n if (setupError) {\n setError(setupError.message || 'Failed to set up payment method')\n setIsSubmitting(false)\n return\n }\n\n if (setupIntent?.payment_method) {\n onSuccess(setupIntent.payment_method as string, setAsDefault)\n }\n } catch (err) {\n setError('An unexpected error occurred')\n setIsSubmitting(false)\n }\n }\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label>Card Details</Label>\n <div className=\"rounded-md border border-input bg-background p-3\">\n <CardElement options={cardElementOptions} />\n </div>\n </div>\n\n {error && (\n <p className=\"text-sm text-destructive\">{error}</p>\n )}\n\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <Checkbox\n checked={setAsDefault}\n onCheckedChange={(checked) => setSetAsDefault(checked as boolean)}\n />\n <span className=\"text-sm\">Set as default payment method</span>\n </label>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={isSubmitting}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={!stripe || isSubmitting}>\n {isSubmitting ? 'Adding...' : 'Add Card'}\n </Button>\n </DialogFooter>\n\n <p className=\"text-xs text-muted-foreground text-center flex items-center justify-center gap-1\">\n <LockIcon className=\"h-3 w-3\" />\n Secured by Stripe\n </p>\n </form>\n )\n}\n\nfunction LockIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('h-4 w-4', className)}\n >\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </svg>\n )\n}\n\nfunction LoadingSkeleton() {\n return (\n <div className=\"space-y-6\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-12 w-full\" />\n </div>\n <div className=\"flex items-center gap-2\">\n <Skeleton className=\"h-4 w-4\" />\n <Skeleton className=\"h-4 w-48\" />\n </div>\n <div className=\"flex justify-end gap-2\">\n <Skeleton className=\"h-10 w-20\" />\n <Skeleton className=\"h-10 w-24\" />\n </div>\n </div>\n )\n}\n\n// Stripe promise cache\nlet stripePromise: Promise<Stripe | null> | null = null\n\nfunction getStripePromise(publishableKey: string) {\n if (!stripePromise) {\n stripePromise = loadStripe(publishableKey)\n }\n return stripePromise\n}\n\nexport function AddPaymentMethodModal({\n open,\n onOpenChange,\n onSuccess,\n clientSecret,\n stripePublishableKey,\n isLoading,\n}: AddPaymentMethodModalProps) {\n const handleCancel = () => {\n onOpenChange(false)\n }\n\n const handleSuccess = (paymentMethodId: string, setAsDefault: boolean) => {\n onSuccess(paymentMethodId, setAsDefault)\n onOpenChange(false)\n }\n\n const showForm = !isLoading && clientSecret && stripePublishableKey\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>Add Payment Method</DialogTitle>\n <DialogDescription>\n Enter your card details below. Your card will be saved for future payments.\n </DialogDescription>\n </DialogHeader>\n\n {isLoading && <LoadingSkeleton />}\n\n {showForm && (\n <Elements stripe={getStripePromise(stripePublishableKey)}>\n <PaymentForm\n clientSecret={clientSecret}\n onSuccess={handleSuccess}\n onCancel={handleCancel}\n />\n </Elements>\n )}\n\n {!isLoading && !showForm && (\n <div className=\"py-8 text-center text-muted-foreground\">\n <p>Unable to load payment form. Please try again.</p>\n <Button variant=\"outline\" className=\"mt-4\" onClick={handleCancel}>\n Close\n </Button>\n </div>\n )}\n </DialogContent>\n </Dialog>\n )\n}\n","\"use client\";\nimport * as React from 'react'\nimport { BannerNudge } from './BannerNudge'\nimport { ToastNudge } from './ToastNudge'\nimport { ModalNudge } from './ModalNudge'\nimport type { NudgeTrigger } from '../../client/types'\n\nexport interface UpgradeNudgeProps {\n /**\n * Nudge trigger data (from API or usage check)\n */\n trigger: NudgeTrigger\n\n /**\n * Display style\n * - 'banner': Top banner (non-intrusive)\n * - 'toast': Toast notification (bottom-right)\n * - 'modal': Modal dialog (more prominent)\n */\n style?: 'banner' | 'toast' | 'modal'\n\n /**\n * Auto-dismiss after N milliseconds (0 = no auto-dismiss)\n */\n autoDismiss?: number\n\n /**\n * Callback when user clicks upgrade\n */\n onUpgrade?: (priceId: string) => void\n\n /**\n * Callback when user dismisses nudge\n */\n onDismiss?: () => void\n\n /**\n * Optional: Custom theme\n */\n theme?: 'light' | 'dark'\n}\n\n// Store dismissal timestamp\nfunction storeDismissal(trigger: NudgeTrigger): void {\n if (typeof window === 'undefined') return\n\n const dismissalKey = `nudge_dismissed_${trigger.type}_${trigger.feature || 'general'}`\n localStorage.setItem(dismissalKey, Date.now().toString())\n}\n\nexport function UpgradeNudge({\n trigger,\n style = 'banner',\n autoDismiss = 0,\n onUpgrade,\n onDismiss,\n theme,\n}: UpgradeNudgeProps) {\n const [isVisible, setIsVisible] = React.useState(true)\n\n // Reset visibility when trigger changes (for demo purposes)\n React.useEffect(() => {\n setIsVisible(true)\n }, [trigger, style])\n\n // Auto-dismiss timer (autoDismiss is in milliseconds)\n React.useEffect(() => {\n if (autoDismiss > 0 && isVisible) {\n const timer = setTimeout(() => {\n handleDismiss()\n }, autoDismiss)\n\n return () => clearTimeout(timer)\n }\n }, [autoDismiss, isVisible])\n\n // Handle keyboard escape\n React.useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && isVisible) {\n handleDismiss()\n }\n }\n\n window.addEventListener('keydown', handleKeyDown)\n return () => window.removeEventListener('keydown', handleKeyDown)\n }, [isVisible])\n\n const handleDismiss = () => {\n setIsVisible(false)\n storeDismissal(trigger)\n onDismiss?.()\n }\n\n const handleUpgrade = () => {\n onUpgrade?.(trigger.suggestedPlan.priceId)\n }\n\n if (!isVisible) return null\n\n switch (style) {\n case 'banner':\n return (\n <BannerNudge\n trigger={trigger}\n onUpgrade={handleUpgrade}\n onDismiss={handleDismiss}\n theme={theme}\n />\n )\n case 'toast':\n return (\n <ToastNudge\n trigger={trigger}\n onUpgrade={handleUpgrade}\n onDismiss={handleDismiss}\n theme={theme}\n />\n )\n case 'modal':\n return (\n <ModalNudge\n trigger={trigger}\n onUpgrade={handleUpgrade}\n onDismiss={handleDismiss}\n theme={theme}\n />\n )\n default:\n return null\n }\n}\n","\"use client\";\nimport { Alert, AlertDescription, AlertTitle } from '../ui/alert'\nimport { Button } from '../ui/button'\nimport { cn } from '../../utils/cn'\nimport type { NudgeTrigger } from '../../client/types'\n\nexport interface BannerNudgeProps {\n trigger: NudgeTrigger\n onUpgrade: () => void\n onDismiss: () => void\n theme?: 'light' | 'dark'\n}\n\nexport function BannerNudge({\n trigger,\n onUpgrade,\n onDismiss,\n}: BannerNudgeProps) {\n const isUrgent = trigger.actual && trigger.actual >= 95\n\n return (\n <div\n className={cn(\n 'fixed top-0 left-0 right-0 z-50 animate-in slide-in-from-top duration-300',\n 'px-4 py-2'\n )}\n role={isUrgent ? 'alert' : 'status'}\n >\n <Alert\n variant={isUrgent ? 'destructive' : 'default'}\n className=\"max-w-4xl mx-auto flex items-center justify-between\"\n >\n <div className=\"flex items-start gap-3 flex-1\">\n {/* Icon */}\n <div className=\"flex-shrink-0 mt-0.5\">\n {isUrgent ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-destructive\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-amber-500\"\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z\" />\n <line x1=\"12\" x2=\"12\" y1=\"9\" y2=\"13\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"17\" y2=\"17\" />\n </svg>\n )}\n </div>\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n <AlertTitle className=\"mb-1 font-semibold\">\n {trigger.message.title}\n </AlertTitle>\n <AlertDescription className=\"text-sm\">\n {trigger.message.body}\n </AlertDescription>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-2 ml-4 flex-shrink-0\">\n <Button\n size=\"sm\"\n onClick={onUpgrade}\n >\n {trigger.message.cta}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onDismiss}\n >\n Maybe Later\n </Button>\n </div>\n </Alert>\n </div>\n )\n}\n","\"use client\";\nimport { Card, CardContent, CardHeader, CardTitle } from '../ui/card'\nimport { Button } from '../ui/button'\nimport { cn } from '../../utils/cn'\nimport type { NudgeTrigger } from '../../client/types'\n\nexport interface ToastNudgeProps {\n trigger: NudgeTrigger\n onUpgrade: () => void\n onDismiss: () => void\n theme?: 'light' | 'dark'\n}\n\nexport function ToastNudge({\n trigger,\n onUpgrade,\n onDismiss,\n}: ToastNudgeProps) {\n const isUrgent = trigger.actual && trigger.actual >= 95\n\n return (\n <div\n className={cn(\n 'fixed bottom-4 right-4 z-50 animate-in slide-in-from-bottom-4 duration-400',\n 'w-80 max-w-[calc(100vw-2rem)]'\n )}\n role=\"status\"\n aria-live=\"polite\"\n >\n <Card className=\"shadow-lg border-2\">\n <CardHeader className=\"pb-2 pr-8 relative\">\n {/* Close button */}\n <button\n onClick={onDismiss}\n className=\"absolute top-3 right-3 p-1 rounded-md hover:bg-muted transition-colors\"\n aria-label=\"Dismiss\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n\n {/* Icon and Title */}\n <div className=\"flex items-start gap-2\">\n {isUrgent ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-destructive flex-shrink-0 mt-0.5\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-amber-500 flex-shrink-0 mt-0.5\"\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z\" />\n <line x1=\"12\" x2=\"12\" y1=\"9\" y2=\"13\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"17\" y2=\"17\" />\n </svg>\n )}\n <CardTitle className=\"text-base font-semibold leading-tight\">\n {trigger.message.title}\n </CardTitle>\n </div>\n </CardHeader>\n\n <CardContent className=\"pt-0 pb-4\">\n <p className=\"text-sm text-muted-foreground mb-4\">\n {trigger.message.body}\n </p>\n\n <Button\n className=\"w-full\"\n size=\"sm\"\n onClick={onUpgrade}\n >\n {trigger.message.cta}\n </Button>\n </CardContent>\n </Card>\n </div>\n )\n}\n","\"use client\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '../ui/dialog'\nimport { Card, CardContent } from '../ui/card'\nimport { Button } from '../ui/button'\nimport { Badge } from '../ui/badge'\nimport type { NudgeTrigger } from '../../client/types'\n\nexport interface ModalNudgeProps {\n trigger: NudgeTrigger\n onUpgrade: () => void\n onDismiss: () => void\n theme?: 'light' | 'dark'\n}\n\nexport function ModalNudge({\n trigger,\n onUpgrade,\n onDismiss,\n}: ModalNudgeProps) {\n const isUrgent = trigger.actual && trigger.actual >= 100\n\n // Format price for display\n const formatPrice = (amount: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n }).format(amount / 100)\n }\n\n return (\n <Dialog open onOpenChange={(open) => !open && onDismiss()}>\n <DialogContent\n className=\"sm:max-w-md\"\n role={isUrgent ? 'alertdialog' : 'dialog'}\n >\n <DialogHeader>\n <div className=\"flex items-center gap-2\">\n {isUrgent ? (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-destructive\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n ) : (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-amber-500\"\n >\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z\" />\n <line x1=\"12\" x2=\"12\" y1=\"9\" y2=\"13\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"17\" y2=\"17\" />\n </svg>\n )}\n <DialogTitle>{trigger.message.title}</DialogTitle>\n </div>\n <DialogDescription className=\"pt-2\">\n {trigger.message.body}\n </DialogDescription>\n </DialogHeader>\n\n {/* Suggested Plan Card */}\n <Card className=\"border-2 border-primary/20\">\n <CardContent className=\"pt-4\">\n <div className=\"flex items-start justify-between mb-4\">\n <div>\n <h3 className=\"font-semibold text-lg\">\n {trigger.suggestedPlan.name}\n </h3>\n <div className=\"flex items-baseline gap-1 mt-1\">\n <span className=\"text-2xl font-bold\">\n {formatPrice(\n trigger.suggestedPlan.price.amount,\n trigger.suggestedPlan.price.currency\n )}\n </span>\n <span className=\"text-muted-foreground text-sm\">\n / {trigger.suggestedPlan.price.interval}\n </span>\n </div>\n </div>\n <Badge variant=\"secondary\">Recommended</Badge>\n </div>\n\n {/* Highlights */}\n <div className=\"space-y-2\">\n <p className=\"text-sm font-medium text-muted-foreground\">\n What you'll get:\n </p>\n <ul className=\"space-y-2\">\n {trigger.suggestedPlan.highlights.map((highlight, index) => (\n <li key={index} className=\"flex items-start gap-2 text-sm\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"text-green-500 flex-shrink-0 mt-0.5\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n {highlight}\n </li>\n ))}\n </ul>\n </div>\n </CardContent>\n </Card>\n\n <DialogFooter className=\"flex-col sm:flex-row gap-2\">\n <Button\n variant=\"outline\"\n onClick={onDismiss}\n className=\"sm:flex-1\"\n >\n Maybe Later\n </Button>\n <Button\n onClick={onUpgrade}\n className=\"sm:flex-1\"\n >\n {trigger.message.cta} - {formatPrice(\n trigger.suggestedPlan.price.amount,\n trigger.suggestedPlan.price.currency\n )}/{trigger.suggestedPlan.price.interval}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","\"use client\";\nimport { useQuery } from '@tanstack/react-query'\nimport { useBillingOS } from '../../../providers/BillingOSProvider'\nimport type { UsageCheckResponse } from '../../../client/types'\n\nexport interface UseUsageCheckOptions {\n /**\n * Whether to enable the query\n */\n enabled?: boolean\n /**\n * Refetch interval in milliseconds (0 = no auto refetch)\n */\n refetchInterval?: number\n}\n\n/**\n * Hook to check usage and get nudge trigger\n */\nexport function useUsageCheck(options: UseUsageCheckOptions = {}) {\n const { client } = useBillingOS()\n const { enabled = true, refetchInterval = 0 } = options\n\n return useQuery<UsageCheckResponse, Error>({\n queryKey: ['usageCheck'],\n queryFn: async () => {\n return client!.checkUsage()\n },\n enabled: !!client && enabled,\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 10 * 60 * 1000, // 10 minutes\n refetchInterval: refetchInterval > 0 ? refetchInterval : undefined,\n })\n}\n","\"use client\";\nimport React from 'react'\nimport { useFeatureGate } from '../../hooks/useFeature'\n\nexport interface FeatureGateProps {\n /**\n * The feature key to check access for\n */\n feature: string\n\n /**\n * Content to render when user has access\n */\n children: React.ReactNode\n\n /**\n * Content to render when access is denied (optional)\n */\n fallback?: React.ReactNode\n\n /**\n * Content to render while loading (optional)\n */\n loading?: React.ReactNode\n\n /**\n * Callback when access is denied\n */\n onAccessDenied?: () => void\n\n /**\n * Callback when quota is exceeded\n */\n onQuotaExceeded?: (usage: number, limit: number) => void\n\n /**\n * Whether to show remaining usage in a badge\n */\n showUsageBadge?: boolean\n}\n\n/**\n * FeatureGate component for conditional rendering based on feature access\n *\n * @example\n * ```tsx\n * <FeatureGate\n * feature=\"advanced_analytics\"\n * fallback={<UpgradePrompt feature=\"Advanced Analytics\" />}\n * >\n * <AdvancedAnalyticsDashboard />\n * </FeatureGate>\n * ```\n */\nexport function FeatureGate({\n feature,\n children,\n fallback,\n loading,\n onAccessDenied,\n onQuotaExceeded,\n showUsageBadge = false,\n}: FeatureGateProps) {\n const {\n hasAccess,\n isLoading,\n isError,\n usage,\n limit,\n remaining,\n } = useFeatureGate(feature, {\n onAccessDenied,\n onQuotaExceeded,\n })\n\n if (isLoading) {\n return <>{loading || <FeatureGateLoading />}</>\n }\n\n if (isError || !hasAccess) {\n return <>{fallback || <FeatureGateDenied feature={feature} />}</>\n }\n\n // If user has access and usage badge is requested, wrap with usage indicator\n if (showUsageBadge && limit > 0) {\n return (\n <div className=\"relative\">\n {children}\n <UsageBadge usage={usage} limit={limit} remaining={remaining} />\n </div>\n )\n }\n\n return <>{children}</>\n}\n\n/**\n * Default loading component\n */\nfunction FeatureGateLoading() {\n return (\n <div className=\"flex items-center justify-center p-4\">\n <div className=\"animate-pulse text-gray-400\">\n Checking access...\n </div>\n </div>\n )\n}\n\n/**\n * Default access denied component\n */\nfunction FeatureGateDenied({ feature }: { feature: string }) {\n return (\n <div className=\"p-4 border border-gray-200 bg-gray-50 rounded-lg\">\n <div className=\"text-center\">\n <svg\n className=\"mx-auto h-12 w-12 text-gray-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n <h3 className=\"mt-2 text-sm font-medium text-gray-900\">\n Feature Locked\n </h3>\n <p className=\"mt-1 text-sm text-gray-500\">\n Upgrade your plan to access {feature.replace(/_/g, ' ')}\n </p>\n </div>\n </div>\n )\n}\n\n/**\n * Usage badge component\n */\nfunction UsageBadge({\n usage,\n limit,\n remaining,\n}: {\n usage: number\n limit: number\n remaining: number\n}) {\n const percentage = Math.min(100, Math.round((usage / limit) * 100))\n\n // Determine color based on usage\n let colorClass = 'bg-green-100 text-green-800'\n if (percentage >= 90) {\n colorClass = 'bg-red-100 text-red-800'\n } else if (percentage >= 75) {\n colorClass = 'bg-yellow-100 text-yellow-800'\n }\n\n return (\n <div className={`absolute top-2 right-2 px-2 py-1 rounded-full text-xs font-medium ${colorClass}`}>\n {remaining.toLocaleString()} / {limit.toLocaleString()} remaining\n </div>\n )\n}","\"use client\";\nimport { useUsageMetrics } from '../../hooks/useFeature'\n\nexport interface UsageDisplayProps {\n /**\n * Optional feature key to show usage for specific feature\n */\n featureKey?: string\n\n /**\n * Custom title\n */\n title?: string\n\n /**\n * Whether to show a progress bar\n */\n showProgress?: boolean\n\n /**\n * Whether to show reset timer\n */\n showResetTimer?: boolean\n\n /**\n * Custom className for styling\n */\n className?: string\n}\n\n/**\n * Component to display usage metrics for features\n *\n * @example\n * ```tsx\n * // Show all usage metrics\n * <UsageDisplay />\n *\n * // Show specific feature usage\n * <UsageDisplay featureKey=\"api_calls\" />\n * ```\n */\nexport function UsageDisplay({\n featureKey,\n title = 'Usage Metrics',\n showProgress = true,\n showResetTimer = true,\n className = '',\n}: UsageDisplayProps) {\n const { data, isLoading, isError } = useUsageMetrics(featureKey)\n\n if (isLoading) {\n return (\n <div className={`p-4 animate-pulse ${className}`}>\n <div className=\"h-4 bg-gray-200 rounded w-1/4 mb-4\"></div>\n <div className=\"space-y-3\">\n <div className=\"h-8 bg-gray-200 rounded\"></div>\n <div className=\"h-8 bg-gray-200 rounded\"></div>\n </div>\n </div>\n )\n }\n\n if (isError || !data?.metrics || data.metrics.length === 0) {\n return (\n <div className={`p-4 text-center text-gray-500 ${className}`}>\n No usage data available\n </div>\n )\n }\n\n return (\n <div className={`p-4 ${className}`}>\n <h3 className=\"text-lg font-semibold mb-4\">{title}</h3>\n <div className=\"space-y-4\">\n {data.metrics.map((metric) => (\n <UsageMetricCard\n key={metric.feature_key}\n metric={metric}\n showProgress={showProgress}\n showResetTimer={showResetTimer}\n />\n ))}\n </div>\n </div>\n )\n}\n\n/**\n * Individual usage metric card\n */\nfunction UsageMetricCard({\n metric,\n showProgress,\n showResetTimer,\n}: {\n metric: any\n showProgress: boolean\n showResetTimer: boolean\n}) {\n const getProgressColor = (percentage: number) => {\n if (percentage >= 90) return 'bg-red-500'\n if (percentage >= 75) return 'bg-yellow-500'\n return 'bg-green-500'\n }\n\n return (\n <div className=\"border border-gray-200 rounded-lg p-4 bg-white\">\n <div className=\"flex justify-between items-start mb-2\">\n <div>\n <h4 className=\"font-medium text-gray-900\">{metric.feature_title}</h4>\n <p className=\"text-sm text-gray-500\">{metric.product_name}</p>\n </div>\n <div className=\"text-right\">\n <div className=\"text-2xl font-semibold\">\n {metric.consumed.toLocaleString()}\n </div>\n <div className=\"text-sm text-gray-500\">\n of {metric.limit.toLocaleString()}\n </div>\n </div>\n </div>\n\n {showProgress && (\n <div className=\"mt-3\">\n <div className=\"w-full bg-gray-200 rounded-full h-2\">\n <div\n className={`h-2 rounded-full transition-all ${getProgressColor(\n metric.percentage_used\n )}`}\n style={{ width: `${Math.min(100, metric.percentage_used)}%` }}\n ></div>\n </div>\n <div className=\"flex justify-between mt-1\">\n <span className=\"text-xs text-gray-500\">\n {metric.percentage_used}% used\n </span>\n <span className=\"text-xs text-gray-500\">\n {metric.remaining.toLocaleString()} remaining\n </span>\n </div>\n </div>\n )}\n\n {showResetTimer && metric.resets_in_days > 0 && (\n <div className=\"mt-2 text-xs text-gray-500\">\n <svg\n className=\"inline-block w-3 h-3 mr-1\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n Resets in {metric.resets_in_days} day{metric.resets_in_days !== 1 ? 's' : ''}\n </div>\n )}\n </div>\n )\n}\n\n/**\n * Compact usage display for inline use\n */\nexport function CompactUsageDisplay({\n featureKey,\n className = '',\n}: {\n featureKey: string\n className?: string\n}) {\n const { data, isLoading } = useUsageMetrics(featureKey)\n\n if (isLoading || !data?.metrics?.[0]) {\n return null\n }\n\n const metric = data.metrics[0]\n const getColor = (percentage: number) => {\n if (percentage >= 90) return 'text-red-600'\n if (percentage >= 75) return 'text-yellow-600'\n return 'text-green-600'\n }\n\n return (\n <div className={`inline-flex items-center gap-2 ${className}`}>\n <span className=\"text-sm text-gray-500\">Usage:</span>\n <span className={`text-sm font-medium ${getColor(metric.percentage_used)}`}>\n {metric.consumed.toLocaleString()} / {metric.limit.toLocaleString()}\n </span>\n {metric.percentage_used >= 90 && (\n <svg\n className=\"w-4 h-4 text-red-500\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z\"\n clipRule=\"evenodd\"\n />\n </svg>\n )}\n </div>\n )\n}","\"use client\";\nimport { useProducts } from '../../hooks/useProducts'\n\nexport interface UpgradePromptProps {\n /**\n * Feature that requires upgrade\n */\n feature?: string\n\n /**\n * Title text\n */\n title?: string\n\n /**\n * Description text\n */\n description?: string\n\n /**\n * Whether it's a quota exceeded prompt\n */\n isQuotaExceeded?: boolean\n\n /**\n * Current usage (for quota exceeded)\n */\n usage?: number\n\n /**\n * Usage limit (for quota exceeded)\n */\n limit?: number\n\n /**\n * Custom className for styling\n */\n className?: string\n\n /**\n * Click handler for upgrade button\n */\n onUpgradeClick?: () => void\n}\n\n/**\n * Component that prompts users to upgrade when they hit limits or access denied features\n *\n * @example\n * ```tsx\n * <UpgradePrompt\n * feature=\"Advanced Analytics\"\n * description=\"Upgrade to Pro to access advanced analytics and reporting\"\n * />\n * ```\n */\nexport function UpgradePrompt({\n feature,\n title = 'Upgrade Required',\n description,\n isQuotaExceeded = false,\n usage,\n limit,\n className = '',\n onUpgradeClick,\n}: UpgradePromptProps) {\n const { data: productsData } = useProducts()\n\n const defaultDescription = isQuotaExceeded\n ? `You've reached your usage limit${feature ? ` for ${feature}` : ''}. Upgrade your plan to continue.`\n : `Upgrade your plan to access${feature ? ` ${feature}` : ' this feature'}.`\n\n const handleUpgradeClick = () => {\n if (onUpgradeClick) {\n onUpgradeClick()\n } else {\n // Scroll to pricing table if it exists\n const pricingTable = document.querySelector('[data-pricing-table]')\n if (pricingTable) {\n pricingTable.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n }\n }\n\n return (\n <div className={`rounded-lg border-2 border-dashed border-gray-300 p-8 ${className}`}>\n <div className=\"text-center\">\n {/* Icon */}\n <div className=\"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-gradient-to-br from-blue-500 to-purple-600\">\n <svg\n className=\"h-6 w-6 text-white\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 10V3L4 14h7v7l9-11h-7z\"\n />\n </svg>\n </div>\n\n {/* Title */}\n <h3 className=\"mt-4 text-lg font-semibold text-gray-900\">\n {title}\n </h3>\n\n {/* Description */}\n <p className=\"mt-2 text-sm text-gray-600\">\n {description || defaultDescription}\n </p>\n\n {/* Usage Info (if quota exceeded) */}\n {isQuotaExceeded && usage !== undefined && limit !== undefined && (\n <div className=\"mt-4 inline-flex items-center gap-2 rounded-full bg-red-50 px-3 py-1\">\n <svg\n className=\"h-4 w-4 text-red-500\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"text-sm font-medium text-red-800\">\n {usage.toLocaleString()} / {limit.toLocaleString()} used\n </span>\n </div>\n )}\n\n {/* Upgrade Button */}\n <div className=\"mt-6\">\n <button\n onClick={handleUpgradeClick}\n className=\"inline-flex items-center rounded-md bg-gradient-to-r from-blue-600 to-purple-600 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:from-blue-700 hover:to-purple-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n <svg\n className=\"mr-2 h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 10l7-7m0 0l7 7m-7-7v18\"\n />\n </svg>\n Upgrade Plan\n </button>\n </div>\n\n {/* Available Plans Preview */}\n {productsData?.products && productsData.products.length > 0 && (\n <div className=\"mt-6 text-xs text-gray-500\">\n Available plans:\n <div className=\"mt-1 flex justify-center gap-2\">\n {productsData.products.slice(0, 3).map((product) => (\n <span\n key={product.id}\n className=\"inline-block rounded-full bg-gray-100 px-2 py-1\"\n >\n {product.name}\n </span>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n )\n}\n\n/**\n * Compact upgrade prompt for inline use\n */\nexport function CompactUpgradePrompt({\n feature,\n onUpgradeClick,\n className = '',\n}: {\n feature?: string\n onUpgradeClick?: () => void\n className?: string\n}) {\n return (\n <div className={`inline-flex items-center gap-2 rounded-md bg-yellow-50 px-3 py-2 ${className}`}>\n <svg\n className=\"h-4 w-4 text-yellow-600\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M10 1.944A11.954 11.954 0 012.166 5C2.056 5.649 2 6.319 2 7c0 5.225 3.34 9.67 8 11.317C14.66 16.67 18 12.225 18 7c0-.682-.057-1.35-.166-2.001A11.954 11.954 0 0110 1.944zM11 14a1 1 0 11-2 0 1 1 0 012 0zm0-7a1 1 0 10-2 0v3a1 1 0 102 0V7z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"text-sm text-yellow-800\">\n Upgrade to access{feature ? ` ${feature}` : ' this feature'}\n </span>\n <button\n onClick={onUpgradeClick}\n className=\"ml-1 text-sm font-medium text-yellow-800 hover:text-yellow-900 underline\"\n >\n Upgrade\n </button>\n </div>\n )\n}","import { format, formatDistance, formatRelative, isAfter, isBefore, parseISO } from 'date-fns'\n\n/**\n * Format a date string or Date object\n * @param date - Date string (ISO) or Date object\n * @param formatStr - Format string (date-fns format)\n * @returns Formatted date string\n *\n * @example\n * formatDate('2024-01-15T10:30:00Z', 'PPP') // \"January 15th, 2024\"\n * formatDate(new Date(), 'yyyy-MM-dd') // \"2024-01-15\"\n */\nexport const formatDate = (date: string | Date, formatStr = 'PPP'): string => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return format(dateObj, formatStr)\n}\n\n/**\n * Format a date as relative time (e.g., \"2 hours ago\")\n * @param date - Date string (ISO) or Date object\n * @param baseDate - Base date to compare against (defaults to now)\n * @returns Relative time string\n *\n * @example\n * formatRelativeTime('2024-01-15T08:30:00Z') // \"2 hours ago\"\n */\nexport const formatRelativeTime = (\n date: string | Date,\n baseDate: Date = new Date(),\n): string => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return formatDistance(dateObj, baseDate, { addSuffix: true })\n}\n\n/**\n * Format a date relative to now (e.g., \"today at 10:30 AM\")\n * @param date - Date string (ISO) or Date object\n * @param baseDate - Base date to compare against (defaults to now)\n * @returns Relative date string\n *\n * @example\n * formatRelativeDate('2024-01-15T10:30:00Z') // \"today at 10:30 AM\"\n */\nexport const formatRelativeDate = (\n date: string | Date,\n baseDate: Date = new Date(),\n): string => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return formatRelative(dateObj, baseDate)\n}\n\n/**\n * Check if a date is in the past\n * @param date - Date string (ISO) or Date object\n * @returns True if date is in the past\n */\nexport const isPast = (date: string | Date): boolean => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return isBefore(dateObj, new Date())\n}\n\n/**\n * Check if a date is in the future\n * @param date - Date string (ISO) or Date object\n * @returns True if date is in the future\n */\nexport const isFuture = (date: string | Date): boolean => {\n const dateObj = typeof date === 'string' ? parseISO(date) : date\n return isAfter(dateObj, new Date())\n}\n\n/**\n * Parse ISO date string to Date object\n * @param date - ISO date string\n * @returns Date object\n */\nexport const parseDate = (date: string): Date => {\n return parseISO(date)\n}\n\n/**\n * Date utilities namespace\n */\nexport const DateUtils = {\n format: formatDate,\n formatRelative: formatRelativeTime,\n formatRelativeDate,\n isPast,\n isFuture,\n parse: parseDate,\n}\n"],"mappings":"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","names":["useProducts","useUsageMetrics","error","import_react_query","import_react","import_react_query","import_react","import_react","import_client","import_react","React","import_jsx_runtime","import_react","import_jsx_runtime","import_react","error","import_react","import_jsx_runtime","error","React","openCheckout","error","import_react_query","import_react_query","useUsageMetrics","import_react_query","React","import_jsx_runtime","import_class_variance_authority","import_jsx_runtime","React","import_class_variance_authority","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_class_variance_authority","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","React","import_class_variance_authority","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","React","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_react","error","import_react","React","import_react_query","import_react_query","useProducts","import_jsx_runtime","React","import_react_stripe_js","import_react_query","React","import_jsx_runtime","import_react_query","React","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime","stripePromise","formatInterval","error","import_jsx_runtime","useProducts","import_jsx_runtime","import_react_query","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","getStatusBadge","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","React","import_react_stripe_js","import_stripe_js","import_jsx_runtime","PaymentForm","React","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","formatPrice","import_jsx_runtime","import_react_query","import_jsx_runtime","import_jsx_runtime","useUsageMetrics","getProgressColor","import_jsx_runtime"]}
|