> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nowramp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# React Components

> Drop-in React components for crypto checkout with @nowramp/form.

# React Components (@nowramp/form)

The `@nowramp/form` package provides ready-to-use React components for crypto on/off-ramp checkout. It handles currency selection, quote comparison, wallet input, and provider checkout — all within your app, no iframe needed.

## Installation

```bash theme={null}
npm install @nowramp/form
# or
yarn add @nowramp/form
# or
pnpm add @nowramp/form
```

<Info>
  `@nowramp/form` has peer dependencies on `react` and `react-dom` (18+). The `@nowramp/sdk` package is bundled automatically.
</Info>

## Quick Start

```tsx theme={null}
import { RampForm } from '@nowramp/form';

function BuyCrypto() {
  return (
    <RampForm
      projectId="your_project_id"
      apiUrl="https://api.nowramp.com"
      onComplete={(tx) => console.log('Done!', tx.orderId)}
    />
  );
}
```

***

## RampForm Component

The main component that renders the complete checkout form with currency selection, quote comparison, wallet input, and provider checkout.

### Basic Usage (Partner Dashboard Pattern)

This is the minimal setup used in partner dashboard integrations:

```tsx theme={null}
<RampForm
  projectId={projectId}
  apiUrl={process.env.NEXT_PUBLIC_API_URL}
  customerId={externalUserId}
  theme={theme}
  borderColor={theme === 'dark' ? '#333333' : '#e2e8f0'}
  borderRadius="10px"
  defaultFiatAmount="250"
/>
```

### Full Branding (Hosted Checkout Pattern)

For hosted checkout flows with complete brand customization:

```tsx theme={null}
<RampForm
  projectId={config.projectId}
  apiUrl="https://api.nowramp.com"
  flowType="buy"
  customerId={customerId}
  theme="dark"
  accentColor={branding.accentColor}
  bgColor={branding.bgDarkest}
  surfaceColor={branding.bgMedium}
  inputBgColor={branding.bgLight}
  textColor={branding.textPrimary}
  textSecondaryColor={branding.textSecondary}
  textMutedColor={branding.textMuted}
  successColor={branding.accentColor}
  borderColor="#222222"
  borderRadius="10px"
  showFlowToggle={false}
  showThemeToggle={false}
  defaultFiatCurrency="USD"
  defaultFiatAmount="100"
  defaultCryptoCurrency="ETH"
  defaultNetwork="ethereum"
  defaultWalletAddress="0x742d35Cc..."
  fieldLocks={{
    destinationAddress: { locked: true, value: '0x742d35Cc...' },
    destinationCurrency: { locked: true, value: 'ETH' },
  }}
  onDone={() => router.push('/success')}
  onError={(err) => setError(err.message)}
/>
```

### Props Reference

#### Core Props

| Prop         | Type              | Default                   | Description                  |
| ------------ | ----------------- | ------------------------- | ---------------------------- |
| `projectId`  | `string`          | **Required**              | Your NowRamp project ID      |
| `apiUrl`     | `string`          | `https://api.nowramp.com` | API base URL                 |
| `flowType`   | `'buy' \| 'sell'` | `'buy'`                   | Buy crypto or sell crypto    |
| `customerId` | `string`          | —                         | External customer ID         |
| `brandId`    | `string`          | —                         | Brand/config slug identifier |

#### Default Values

| Prop                    | Type     | Default | Description                      |
| ----------------------- | -------- | ------- | -------------------------------- |
| `defaultFiatCurrency`   | `string` | `'USD'` | Initial fiat currency            |
| `defaultCryptoCurrency` | `string` | —       | Initial crypto currency          |
| `defaultNetwork`        | `string` | —       | Initial blockchain network       |
| `defaultFiatAmount`     | `string` | —       | Initial fiat amount              |
| `defaultCryptoAmount`   | `string` | —       | Initial crypto amount (for sell) |
| `defaultWalletAddress`  | `string` | —       | Pre-filled wallet address        |
| `defaultGateway`        | `string` | —       | Pre-selected gateway ID          |

#### Theme & Styling

| Prop                 | Type                | Default   | Description                               |
| -------------------- | ------------------- | --------- | ----------------------------------------- |
| `theme`              | `'light' \| 'dark'` | `'light'` | Color theme                               |
| `skinId`             | `string`            | —         | Skin preset ID                            |
| `accentColor`        | `string`            | —         | Primary/accent color (hex)                |
| `bgColor`            | `string`            | —         | Main background color (hex)               |
| `bgImage`            | `string`            | —         | Background image URL                      |
| `surfaceColor`       | `string`            | —         | Card/surface background (hex)             |
| `inputBgColor`       | `string`            | —         | Input/pill background (hex)               |
| `textColor`          | `string`            | —         | Primary text color (hex)                  |
| `textSecondaryColor` | `string`            | —         | Secondary/label text (hex)                |
| `textMutedColor`     | `string`            | —         | Muted text color (hex)                    |
| `successColor`       | `string`            | —         | Success indicator color (hex)             |
| `borderColor`        | `string`            | —         | Border color (hex)                        |
| `borderRadius`       | `string`            | —         | Border radius (CSS value, e.g., `'10px'`) |

#### UI Controls

| Prop                  | Type      | Default | Description                                |
| --------------------- | --------- | ------- | ------------------------------------------ |
| `showFlowToggle`      | `boolean` | `true`  | Show Buy/Sell toggle tabs                  |
| `showSettings`        | `boolean` | `true`  | Show settings menu                         |
| `showThemeToggle`     | `boolean` | `true`  | Show dark/light mode toggle                |
| `showEmail`           | `boolean` | `false` | Show email input field                     |
| `requireEmail`        | `boolean` | `false` | Make email required                        |
| `autoRedirect`        | `boolean` | —       | Auto-redirect for redirect-based checkouts |
| `rateRefreshInterval` | `number`  | —       | Quote refresh interval (seconds)           |
| `statusPollInterval`  | `number`  | `5000`  | Order status poll interval (ms)            |

#### Display Customization

| Prop               | Type     | Description                    |
| ------------------ | -------- | ------------------------------ |
| `explorerUrl`      | `string` | Block explorer URL pattern     |
| `doneButtonText`   | `string` | Custom done button label       |
| `submitButtonText` | `string` | Custom submit button label     |
| `supportEmail`     | `string` | Support email for error screen |
| `assetBaseUrl`     | `string` | CDN base URL for static assets |

#### Field Locks

| Prop         | Type               | Description                                       |
| ------------ | ------------------ | ------------------------------------------------- |
| `fieldLocks` | `FieldLocksConfig` | Lock specific fields to prevent user modification |

```tsx theme={null}
<RampForm
  fieldLocks={{
    destinationAddress: { locked: true, value: '0x742d35Cc...' },
    destinationCurrency: { locked: true, value: 'ETH' },
    sourceAmount: { locked: false, min: 50, max: 5000 },
  }}
/>
```

#### Callbacks

| Prop         | Type                        | Description                         |
| ------------ | --------------------------- | ----------------------------------- |
| `onComplete` | `(tx: Transaction) => void` | Called when transaction completes   |
| `onError`    | `(err: Error) => void`      | Called on error                     |
| `onDone`     | `() => void`                | Called when user clicks done button |

***

## RampProvider + useRamp

For full control over the UI, use `RampProvider` for state management and build your own components.

### RampProvider

Wraps your custom UI with configuration, API state, and form management.

```tsx theme={null}
import { RampProvider, useRamp } from '@nowramp/form';

function App() {
  return (
    <RampProvider
      projectId="your_project_id"
      apiUrl="https://api.nowramp.com"
      flowType="buy"
      customerId="user_123"
      onComplete={(tx) => console.log('Done!', tx)}
    >
      <CustomCheckoutUI />
    </RampProvider>
  );
}
```

### useRamp Hook

Access the full ramp context within a `RampProvider`.

```tsx theme={null}
function CustomCheckoutUI() {
  const {
    // Configuration
    config,           // OnrampSupported | null
    configLoading,    // boolean
    apiConfig,        // { apiUrl, projectId }

    // Form state
    state,            // RampFormState
    dispatch,         // React.Dispatch<RampAction>

    // Quotes
    quotes,           // QuotesResponse | null
    quotesLoading,    // boolean
    fetchQuotes,      // () => void

    // Order
    order,            // CheckoutIntent | null
    orderLoading,     // boolean
    createOrder,      // () => Promise<void>

    // Transaction status
    orderStatus,      // Transaction | null
    orderStatusLoading,

    // Navigation
    goToStep,         // (step: RampStep) => void
    goBack,           // () => void
    canProceed,       // boolean

    // Validation
    amountError,      // string | null
    fieldLocks,       // FieldLocksConfig | null
  } = useRamp();

  if (configLoading) return <div>Loading...</div>;

  return (
    <div>
      <p>Selected: {state.fiatAmount} {state.fiatCurrency}</p>
      <p>Quotes: {quotes?.quotes.length ?? 0} available</p>
      <button onClick={fetchQuotes} disabled={quotesLoading}>
        Refresh Quotes
      </button>
    </div>
  );
}
```

### RampFormState

| Field              | Type              | Description                 |
| ------------------ | ----------------- | --------------------------- |
| `step`             | `RampStep`        | Current step in the flow    |
| `flowType`         | `'buy' \| 'sell'` | Current flow type           |
| `fiatCurrency`     | `string`          | Selected fiat currency      |
| `fiatAmount`       | `string`          | Entered fiat amount         |
| `cryptoCurrency`   | `string`          | Selected crypto currency    |
| `cryptoAmount`     | `string`          | Crypto amount               |
| `network`          | `string`          | Selected blockchain network |
| `paymentMethodId`  | `string`          | Selected payment method     |
| `walletAddress`    | `string`          | Entered wallet address      |
| `selectedProvider` | `string \| null`  | Selected gateway ID         |
| `selectedQuote`    | `Quote \| null`   | Selected quote              |
| `customerId`       | `string`          | Customer ID                 |
| `email`            | `string`          | Customer email              |
| `errorMessage`     | `string \| null`  | Current error message       |

### RampStep Values

| Step         | Description                         |
| ------------ | ----------------------------------- |
| `amount`     | Currency and amount selection       |
| `quotes`     | Quote comparison view               |
| `wallet`     | Wallet address entry                |
| `checkout`   | Provider checkout (iframe/redirect) |
| `processing` | Waiting for transaction completion  |
| `complete`   | Success screen                      |
| `error`      | Error screen                        |

***

## Data Hooks

Standalone hooks for direct API access without the full form UI. Use these to build completely custom checkout experiences.

### useRampConfig

Fetches supported gateways, currencies, and payment methods.

```tsx theme={null}
import { useRampConfig } from '@nowramp/form';

function CurrencyPicker() {
  const { config, loading, error, refetch } = useRampConfig(
    { apiUrl: 'https://api.nowramp.com', projectId: 'your_project_id' },
    'buy'
  );

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <select>
      {config?.fiats.map(fiat => (
        <option key={fiat.code} value={fiat.code}>
          {fiat.symbol} {fiat.name}
        </option>
      ))}
    </select>
  );
}
```

**Returns:**

| Field     | Type                      | Description             |
| --------- | ------------------------- | ----------------------- |
| `config`  | `OnrampSupported \| null` | Supported configuration |
| `loading` | `boolean`                 | Loading state           |
| `error`   | `Error \| null`           | Error if failed         |
| `refetch` | `() => Promise<void>`     | Manually refetch        |

### useQuotes

Fetches and ranks quotes from all enabled gateways. Auto-refreshes when params change.

```tsx theme={null}
import { useQuotes } from '@nowramp/form';

function QuoteList() {
  const { quotes, loading, error } = useQuotes(
    { apiUrl: 'https://api.nowramp.com', projectId: 'your_project_id' },
    {
      fiatCurrency: 'USD',
      fiatAmount: '100',
      cryptoCurrency: 'ETH',
      network: 'ethereum'
    }
  );

  if (loading) return <div>Fetching quotes...</div>;

  return (
    <div>
      {quotes?.quotes.map(q => (
        <div key={q.gatewayId}>
          {q.gatewayName}: {q.cryptoAmount} {q.cryptoCurrency}
          {q.isBestRate && <span> (Best Rate)</span>}
        </div>
      ))}
    </div>
  );
}
```

Pass `null` as the second argument to skip fetching (useful when form inputs are incomplete).

**Returns:**

| Field     | Type                     | Description      |
| --------- | ------------------------ | ---------------- |
| `quotes`  | `QuotesResponse \| null` | Ranked quotes    |
| `loading` | `boolean`                | Loading state    |
| `error`   | `Error \| null`          | Error if failed  |
| `refetch` | `() => Promise<void>`    | Manually refetch |

### useCheckoutIntent

Creates a checkout order with a selected gateway.

```tsx theme={null}
import { useCheckoutIntent } from '@nowramp/form';

function CheckoutButton() {
  const { order, loading, error, createOrder, reset } = useCheckoutIntent(
    { apiUrl: 'https://api.nowramp.com', projectId: 'your_project_id' }
  );

  const handleCheckout = async () => {
    const intent = await createOrder({
      gateway: 'gateway_a',
      fiatCurrency: 'USD',
      fiatAmount: '100',
      cryptoCurrency: 'ETH',
      network: 'ethereum',
      walletAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f1bD21'
    });

    if (intent.checkout.method === 'iframe') {
      setIframeUrl(intent.checkout.url);
    } else {
      window.location.href = intent.checkout.url;
    }
  };

  return <button onClick={handleCheckout} disabled={loading}>Checkout</button>;
}
```

**Returns:**

| Field         | Type                                  | Description             |
| ------------- | ------------------------------------- | ----------------------- |
| `order`       | `CheckoutIntent \| null`              | Created checkout intent |
| `loading`     | `boolean`                             | Loading state           |
| `error`       | `Error \| null`                       | Error if failed         |
| `createOrder` | `(params) => Promise<CheckoutIntent>` | Create checkout         |
| `reset`       | `() => void`                          | Reset state             |

### useTransaction

Polls transaction status until it reaches a terminal state.

```tsx theme={null}
import { useTransaction } from '@nowramp/form';

function OrderTracker({ orderId }: { orderId: string }) {
  const { status, loading } = useTransaction(
    { apiUrl: 'https://api.nowramp.com' },
    orderId,
    { pollInterval: 5000, initialDelay: 15000 }
  );

  if (!status) return <div>Loading...</div>;

  return (
    <div>
      <p>Status: {status.status}</p>
      {status.transactionHash && (
        <p>TX: {status.transactionHash}</p>
      )}
    </div>
  );
}
```

<Info>
  The `initialDelay` option is useful when embedding a provider checkout iframe — it gives the user time to complete payment before polling starts.
</Info>

**Returns:**

| Field     | Type                  | Description                |
| --------- | --------------------- | -------------------------- |
| `status`  | `Transaction \| null` | Current transaction status |
| `loading` | `boolean`             | Loading state              |
| `error`   | `Error \| null`       | Error if failed            |
| `refetch` | `() => Promise<void>` | Manually refetch           |

***

## Theming

### Light / Dark Mode

```tsx theme={null}
<RampForm projectId="..." theme="dark" />
```

### Custom Colors

Override individual colors for precise brand matching:

```tsx theme={null}
<RampForm
  projectId="..."
  theme="dark"
  accentColor="#6366F1"
  bgColor="#1a1a2e"
  surfaceColor="#16213e"
  inputBgColor="#0f3460"
  textColor="#e0e0e0"
  textSecondaryColor="#a0a0a0"
  textMutedColor="#666666"
  successColor="#6366F1"
  borderColor="#222222"
  borderRadius="10px"
/>
```

**Color mapping guide:**

| Prop                 | Applies to                                         |
| -------------------- | -------------------------------------------------- |
| `accentColor`        | Buttons, links, active states, progress indicators |
| `bgColor`            | Main background of the form                        |
| `surfaceColor`       | Card and panel backgrounds                         |
| `inputBgColor`       | Input fields, pills, dropdowns                     |
| `textColor`          | Primary text, headings                             |
| `textSecondaryColor` | Labels, secondary text                             |
| `textMutedColor`     | Hints, placeholders, disabled text                 |
| `successColor`       | Success indicators, rate display                   |
| `borderColor`        | Borders on cards, inputs, dividers                 |
| `borderRadius`       | Corner rounding on all elements                    |

### Skin Presets

```tsx theme={null}
<RampForm projectId="..." skinId="midnight" />
```

Skins apply a coordinated set of colors and styles. Available skins are exported from the package as `SKINS`.

***

## Standalone Mode (IIFE)

For non-React apps (plain HTML, PHP, WordPress, etc.), use the standalone IIFE build.

```html theme={null}
<script src="https://cdn.example.com/form/latest/nowramp-form.iife.js"></script>
<div id="nowramp"></div>
<script>
  NowRampForm.mount('#nowramp', {
    projectId: 'your_project_id',
    apiUrl: 'https://api.nowramp.com',
    assetBaseUrl: 'https://cdn.example.com/form/latest',
    theme: 'light',
    onComplete: function(tx) {
      console.log('Purchase complete:', tx.orderId);
    }
  });

  // To unmount later:
  // NowRampForm.unmount('#nowramp');
</script>
```

| Function                             | Description                       |
| ------------------------------------ | --------------------------------- |
| `NowRampForm.mount(selector, props)` | Mount the form into a DOM element |
| `NowRampForm.unmount(selector)`      | Unmount a previously mounted form |

The `mount` function accepts the same props as the `RampForm` component.

***

## Next.js Integration

```tsx theme={null}
// app/buy/page.tsx
'use client';

import { RampForm } from '@nowramp/form';

export default function BuyPage() {
  return (
    <div className="max-w-md mx-auto py-8">
      <RampForm
        projectId={process.env.NEXT_PUBLIC_NOWRAMP_PROJECT_ID!}
        apiUrl={process.env.NEXT_PUBLIC_NOWRAMP_API_URL}
        theme="light"
        onComplete={(tx) => {
          window.location.href = `/orders/${tx.orderId}`;
        }}
      />
    </div>
  );
}
```

<Warning>
  Always use the `'use client'` directive in Next.js App Router since `@nowramp/form` uses React hooks and browser APIs.
</Warning>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Multi-Provider Quotes" icon="ranking-star" href="/guides/multi-provider-quotes">
    Build a custom quote comparison UI
  </Card>

  <Card title="Onramp API" icon="code" href="/api/onramp">
    API reference for all onramp endpoints
  </Card>

  <Card title="JavaScript SDK" icon="js" href="/sdk/js-sdk">
    Direct API access without React
  </Card>

  <Card title="Callback URLs" icon="webhook" href="/guides/callback-urls">
    Server-side transaction notifications
  </Card>
</CardGroup>
