npm package: @subgames/react
Description: Official React SDK for sub.games tier-gating
Latest version: 1.0.0

# @subgames/react

Official React SDK for [sub.games](https://sub.games) tier-gating. Provides typed React bindings around the vanilla JS SDK (`@subgames/sdk`).

## Install

```bash
npm install @subgames/react
# or
bun add @subgames/react
```

React 18+ is required as a peer dependency.

## Quick Start

Wrap your app with `<SubGamesProvider>` and use the `useSubGames()` hook to access the SDK:

```tsx
import { SubGamesProvider, useSubGames } from '@subgames/react';

function App() {
  return (
    <SubGamesProvider config={{ gameKey: 'my-game' }}>
      <Game />
    </SubGamesProvider>
  );
}

function Game() {
  const { sdk, loading, error } = useSubGames();

  if (loading || !sdk) return <div>Loading...</div>;

  return <button onClick={() => sdk.promptLogin()}>Login</button>;
}
```

## API

### `<SubGamesProvider>`

Loads the SubGames SDK script and initializes the SDK instance.

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `config` | `SubGamesConfig` | **required** | SDK configuration passed to `SubGamesSDK.init()`. |
| `scriptUrl` | `string` | `https://sdk.sub.games/sdk.js` | URL of the SDK script. Override for local dev. |

#### `SubGamesConfig`

```ts
interface SubGamesConfig {
  gameKey: string;    // Your game's unique key
  apiUrl?: string;    // API base URL (default: https://api.sub.games)
  appUrl?: string;    // App base URL (default: https://sub.games)
  overlay?: boolean;  // Enable floating overlay UI
}
```

### `useSubGames()`

Returns the SDK context. Must be used within a `<SubGamesProvider>`.

```ts
const { sdk, loading, error } = useSubGames();
```

| Field | Type | Description |
|-------|------|-------------|
| `sdk` | `ISubGamesSDK \| null` | SDK instance. `null` until loaded. |
| `loading` | `boolean` | `true` while the script is loading. |
| `error` | `Error \| null` | Error if the script failed to load. |

### SDK Methods

All methods on `sdk` are fully typed. These mirror the [vanilla JS SDK](https://docs.sub.games):

```ts
// Player & Auth
sdk.isLoggedIn(): boolean
sdk.getPlayer(): Promise<PlayerInfo | null>
sdk.getToken(): string | null
sdk.setToken(token: string): void
sdk.logout(): void

// Tiers
sdk.getPlayerTier(): Promise<PlayerTier>
sdk.requireTier(tier: PlayerTier, feature?: string): Promise<boolean>

// Prompts
sdk.promptLogin(): Promise<void>
sdk.promptSubscribe(targetTier?: PlayerTier, feature?: string): Promise<void>

// Game State
sdk.pause(): void
sdk.unpause(): void
sdk.isPaused(): boolean

// Events
sdk.on(event, handler): void
sdk.off(event, handler): void
```

### Types

```ts
type PlayerTier = 'none' | 'free' | 'supporter' | 'founder';

interface PlayerInfo {
  id: string;
  email: string;
  displayName: string | null;
  avatarUrl: string | null;
}

interface SubGamesEventMap {
  login: () => void;
  logout: () => void;
  tierChange: (tier: PlayerTier) => void;
  pause: () => void;
  unpause: () => void;
}
```

## How It Works

The provider injects the vanilla JS SDK's IIFE script (`sdk.js`) into the page via a `<script>` tag. Once loaded, it calls `SubGamesSDK.init()` with your config and exposes the resulting instance through React context. This means you get the full SDK functionality with zero re-implementation — just typed React bindings on top.