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

# React SDK

React bindings for the [Push JS SDK](./sdk): a `<PushWidget>` component that renders the card-entry form, and a `<PushUX>` component that presents the Push-hosted authentication UI in a modal. Together they cover the browser side of a card payment — collect a card, then complete the step-up authentication requested when [authorize-payment](./apireference/authorization/authorize-payment) returns `202 Accepted` (see [Presenting the authentication UI](./card-payments#presenting-the-authentication-ui)).

## Install

```sh theme={null}
npm install @pushcash/react
```

`react` and `react-dom` (`>=16.8 <20`) are peer dependencies. The package loads the Push core from `cdn.pushcash.com` at runtime, so if your site uses a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), include `https://cdn.pushcash.com` in both `script-src` and `frame-src`.

## `<PushWidget>`

Renders the Push card-entry form for a user. Collect a card, then call `tokenize()` through a ref from your submit handler to get a one-time token for [authorize-payment](./apireference/authorization/authorize-payment). Enable your submit button from `onValid`.

### Props (`PushWidgetProps`)

| Prop           | Type         | Required | Description                                                                 |
| -------------- | ------------ | :------: | --------------------------------------------------------------------------- |
| `url`          | `string`     |     ✅    | URL returned from [create-user-url](./apireference/user/create-user-url).   |
| `onValid`      | `() => void` |     ❌    | Called once the entered card is valid. Use it to enable your submit button. |
| `background`   | `string`     |     ❌    | Form background (CSS color value).                                          |
| `fontSize`     | `string`     |     ❌    | Base font size (CSS value, e.g. `14px`).                                    |
| `borderRadius` | `string`     |     ❌    | Corner radius (CSS value, e.g. `12px`).                                     |
| `padding`      | `string`     |     ❌    | Inner padding (CSS value, e.g. `16px`).                                     |
| `color`        | `string`     |     ❌    | Text color (CSS color value).                                               |

### Ref (`PushWidgetRef`)

Attach a ref to call:

| Method     | Type                               | Description                                                                                                                                               |
| ---------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tokenize` | `() => Promise<{ token: string }>` | Generates a one-time token from the entered card for [authorize-payment](./apireference/authorization/authorize-payment). Rejects if the card is invalid. |

### Example

```tsx theme={null}
import { PushWidget } from '@pushcash/react';
import type { PushWidgetRef } from '@pushcash/react';
import { useRef, useState } from 'react';

function CardForm({ url }: { url: string }) {
  const widget = useRef<PushWidgetRef>(null);
  const [ready, setReady] = useState(false);

  return (
    <>
      <PushWidget ref={widget} url={url} onValid={() => setReady(true)} />
      <button
        disabled={!ready}
        onClick={async () => {
          const result = await widget.current?.tokenize();
          if (!result) return;
          // send result.token to your backend, which calls POST /authorize
          await yourBackend.authorize(result.token);
        }}
      >
        Pay
      </button>
    </>
  );
}
```

## `<PushUX>`

Presents the payment UX for a single intent in a modal — a centered dialog on desktop, a full-page sheet on mobile. Render it once you hold an intent `id` (typically after your submit handler's `POST /authorize` returns `202 Accepted`); it opens on mount and renders no markup of its own. Unmount it to end the flow.

### Props (`PushUXProps`)

| Prop       | Type         | Required | Description                                                                                                                                                                          |
| ---------- | ------------ | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `intentId` | `string`     |     ✅    | The intent `id` returned by [authorize-payment](./apireference/authorization/authorize-payment) with a `202 Accepted` response.                                                      |
| `onExit`   | `() => void` |     ✅    | Called exactly once when the flow ends — whether the user completes it or dismisses the modal. It carries no result; retrieve the authoritative outcome from the server (see below). |

`onExit` does not indicate whether the payment succeeded — call [get-an-intent](./apireference/intent/get-an-intent) (or wait for the intent webhook) and inspect `status`.

### Example

```tsx theme={null}
import { PushUX } from '@pushcash/react';

function Checkout({ intentId }: { intentId: string }) {
  return (
    <PushUX
      intentId={intentId}
      onExit={async () => {
        // the flow has ended — fetch the result from your backend
        const intent = await yourBackend.getIntent(intentId);
        console.log(intent.status); // 'approved' | 'declined' | ...
      }}
    />
  );
}
```

Render `<PushUX>` only when you have an intent `id`. A typical checkout collects the card with `<PushWidget>` above, calls `POST /authorize` on submit, and on a `202 Accepted` renders `<PushUX>` with the returned `id`.
