npm package: @plutaslab/stripe-kit-react
Description: React components and hooks for Stripe Kit
Author: Plutas Labs
Latest version: 0.1.0

# @plutaslab/stripe-kit-react

React components and hooks for Stripe Kit.

## Installation

```bash
npm install @plutaslab/stripe-kit-react @stripe/stripe-js
# or
pnpm add @plutaslab/stripe-kit-react @stripe/stripe-js
# or
yarn add @plutaslab/stripe-kit-react @stripe/stripe-js
```

## Quick Start

### 1. Wrap your app with StripeKitProvider

```tsx
import { StripeKitProvider } from '@plutaslab/stripe-kit-react'

function App() {
  return (
    <StripeKitProvider
      publishableKey={process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!}
      apiBaseUrl="/api/stripe"
    >
      <YourApp />
    </StripeKitProvider>
  )
}
```

### 2. Use the CheckoutButton

```tsx
import { CheckoutButton } from '@plutaslab/stripe-kit-react'

function PricingPage() {
  return (
    <CheckoutButton
      priceId="price_xxx"
      mode="subscription"
      successUrl="/success"
      cancelUrl="/pricing"
    >
      Subscribe Now
    </CheckoutButton>
  )
}
```

### 3. Display a Pricing Table

```tsx
import { PricingTable } from '@plutaslab/stripe-kit-react'

const plans = [
  {
    id: 'basic',
    priceId: 'price_basic',
    name: 'Basic',
    price: 999, // $9.99
    interval: 'month',
    features: ['10 projects', 'Basic analytics', 'Email support'],
  },
  {
    id: 'pro',
    priceId: 'price_pro',
    name: 'Pro',
    price: 2999, // $29.99
    interval: 'month',
    features: ['Unlimited projects', 'Advanced analytics', 'Priority support'],
    highlighted: true,
    badge: 'Most Popular',
  },
]

function PricingPage() {
  return <PricingTable plans={plans} successUrl="/success" />
}
```

## Hooks

### useCheckout

```tsx
import { useCheckout } from '@plutaslab/stripe-kit-react'

function CustomCheckout() {
  const { checkout, isLoading, error } = useCheckout()

  const handlePurchase = async () => {
    await checkout({
      priceId: 'price_xxx',
      mode: 'subscription',
    })
  }

  return (
    <button onClick={handlePurchase} disabled={isLoading}>
      {isLoading ? 'Loading...' : 'Purchase'}
    </button>
  )
}
```

### useSubscription

```tsx
import { useSubscription } from '@plutaslab/stripe-kit-react'

function SubscriptionManager() {
  const {
    subscription,
    isActive,
    isTrialing,
    willCancel,
    cancel,
    resume,
    changePlan,
  } = useSubscription()

  if (!subscription) {
    return <p>No active subscription</p>
  }

  return (
    <div>
      <p>Status: {subscription.status}</p>
      <p>Plan: {subscription.productName}</p>

      {willCancel ? (
        <button onClick={resume}>Resume Subscription</button>
      ) : (
        <button onClick={() => cancel({ atPeriodEnd: true })}>
          Cancel at Period End
        </button>
      )}
    </div>
  )
}
```

## Components

### CheckoutButton

A button that initiates Stripe Checkout.

```tsx
<CheckoutButton
  priceId="price_xxx"
  mode="subscription" // 'payment' | 'subscription' | 'setup'
  successUrl="/success"
  cancelUrl="/pricing"
  customerId="cus_xxx" // optional
  customerEmail="user@example.com" // optional
  metadata={{ userId: '123' }}
  onCheckoutStart={() => console.log('Starting checkout')}
  onCheckoutError={(error) => console.error(error)}
>
  Subscribe
</CheckoutButton>
```

### PricingTable

A complete pricing table with checkout integration.

```tsx
<PricingTable
  plans={plans}
  currentPlanId="basic" // Show "Current Plan" for existing subscribers
  customerId="cus_xxx"
  successUrl="/success"
  cancelUrl="/pricing"
  onPlanSelect={(plan) => console.log('Selected:', plan.name)}
  onCheckoutStart={(plan) => analytics.track('checkout_start', plan)}
  onCheckoutError={(error, plan) => console.error(error)}
/>
```

### SubscriptionStatus

Display subscription status with management actions.

```tsx
<SubscriptionStatus
  customerId="cus_xxx"
  showActions={true}
  showPlanDetails={true}
  onCancel={() => console.log('Canceled')}
  onResume={() => console.log('Resumed')}
/>
```

### PaymentForm

A placeholder payment form (use with @stripe/react-stripe-js for production).

```tsx
import { Elements } from '@stripe/react-stripe-js'
import { loadStripe } from '@stripe/stripe-js'
import { PaymentForm } from '@plutaslab/stripe-kit-react'

const stripePromise = loadStripe('pk_test_xxx')

function Checkout({ clientSecret }) {
  return (
    <Elements stripe={stripePromise} options={{ clientSecret }}>
      <PaymentForm
        clientSecret={clientSecret}
        onSubmit={async (paymentMethodId) => {
          // Handle payment
        }}
        onSuccess={() => router.push('/success')}
        onError={(error) => console.error(error)}
      />
    </Elements>
  )
}
```

## API Routes

The components expect API routes at your `apiBaseUrl`:

### POST /api/stripe/checkout

Creates a checkout session.

```ts
// app/api/stripe/checkout/route.ts (Next.js App Router)
import { stripe } from '@plutaslab/stripe-kit-next'

export async function POST(request: Request) {
  const body = await request.json()

  const session = await stripe.checkout.createSession({
    priceIds: [body.priceId],
    mode: body.mode,
    successUrl: body.successUrl,
    cancelUrl: body.cancelUrl,
    customerId: body.customerId,
    customerEmail: body.customerEmail,
  })

  return Response.json({
    sessionId: session.id,
    url: session.url,
  })
}
```

### POST /api/stripe/portal

Creates a customer portal session.

### GET /api/stripe/subscription

Returns the current user's subscription.

### POST /api/stripe/subscription/:id/cancel

Cancels a subscription.

### POST /api/stripe/subscription/:id/resume

Resumes a canceled subscription.

## TypeScript

All components and hooks are fully typed. Types are exported:

```tsx
import type {
  CheckoutButtonProps,
  PricingTableProps,
  PricingPlan,
  SubscriptionStatusProps,
  UseCheckoutResult,
  UseSubscriptionResult,
} from '@plutaslab/stripe-kit-react'
```

## License

MIT