npm package: @queuezero/react
Description: React components and hooks for QueueZero viral waitlists
Author: QueueZero Team
Latest version: 0.1.12

# @queuezero/react

React components and hooks for QueueZero viral waitlists.

## Installation

```bash
npm install @queuezero/react
```

## Quick Start

```tsx
import { WaitlistProvider, WaitlistForm, WaitlistStatus, ReferralShare } from '@queuezero/react';

function App() {
  // Get referral code from URL if present
  const referrerCode = new URLSearchParams(window.location.search).get('ref');

  return (
    <WaitlistProvider 
      campaign="my-campaign"
      config={{ apiUrl: 'https://api.queuezero.io' }}
    >
      <WaitlistForm 
        referrerCode={referrerCode || undefined}
        onSuccess={(res) => console.log('Joined at position:', res.position)}
      />
      <WaitlistStatus />
      <ReferralShare showSocialButtons />
    </WaitlistProvider>
  );
}
```

## Components

### WaitlistProvider

Wraps your app to provide waitlist context to all child components.

```tsx
<WaitlistProvider 
  campaign="my-campaign"
  config={{ 
    apiUrl: 'https://api.queuezero.io',
    baseUrl: 'https://myapp.com' 
  }}
>
  {children}
</WaitlistProvider>
```

### WaitlistForm

A ready-to-use signup form.

```tsx
// Basic
<WaitlistForm />

// With options
<WaitlistForm
  referrerCode="ABC123"
  metadata={{ role: 'Developer' }}
  placeholder="Enter your work email"
  buttonText="Get Early Access"
  onSuccess={(response) => console.log(response)}
  onError={(error) => console.error(error)}
/>

// Custom render
<WaitlistForm>
  {({ email, setEmail, submit, loading, error }) => (
    <div>
      <input value={email} onChange={(e) => setEmail(e.target.value)} />
      <button onClick={submit}>{loading ? '...' : 'Join'}</button>
    </div>
  )}
</WaitlistForm>

// Modal mode
<WaitlistForm
  displayMode="modal"
  triggerText="Join Our Waitlist"
  modalSize="md"
// Headless modal mode (attaches to existing buttons)
<WaitlistForm
  displayMode="modal"
  attachToText="Join Waitlist"
  modalSize="md"
/>
```

#### Modal Mode Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `displayMode` | `'inline' \| 'modal'` | `'inline'` | Display as inline form or modal |
| `triggerText` | `string` | `'Join Waitlist'` | Button text (modal mode only) |
| `attachToText` | `string` | - | Text to match for auto-attaching modal (headless mode) |
| `modalSize` | `'sm' \| 'md' \| 'lg'` | `'md'` | Modal width (modal mode only) |

The modal automatically uses your campaign's branding (logo, cover image, theme color) from the API.

### WaitlistStatus

Displays position, score, and referral count.

```tsx
// Basic
<WaitlistStatus />

// With options
<WaitlistStatus
  showScore
  showReferrals
  positionLabel="Your position:"
/>

// Custom render
<WaitlistStatus>
  {(status) => (
    <div>
      <h2>#{status.position}</h2>
      <p>{status.priority_score} points</p>
    </div>
  )}
</WaitlistStatus>
```

### ReferralShare

Share referral link with copy and social buttons.

```tsx
// Basic
<ReferralShare />

// With social buttons
<ReferralShare 
  showSocialButtons 
  shareMessage="Join me on this awesome waitlist!"
/>

// Custom render
<ReferralShare>
  {({ link, code, copy, copied }) => (
    <div>
      <code>{code}</code>
      <button onClick={copy}>{copied ? 'Copied!' : 'Copy'}</button>
    </div>
  )}
</ReferralShare>
```

## Hooks

### useWaitlistContext

Access waitlist state inside the provider.

```tsx
import { useWaitlistContext } from '@queuezero/react';

function MyComponent() {
  const { status, loading, join, getReferralLink } = useWaitlistContext();
  
  if (loading) return <div>Loading...</div>;
  if (!status) return <button onClick={() => join('user@example.com')}>Join</button>;
  
  return (
    <div>
      <p>Position: #{status.position}</p>
      <p>Share: {getReferralLink()}</p>
    </div>
  );
}
```

### useWaitlist

Standalone hook (without provider) for simpler use cases.

```tsx
import { useWaitlist } from '@queuezero/react';

function WaitlistPage() {
  const { status, join, loading, getReferralLink } = useWaitlist('my-campaign', {
    apiUrl: 'https://api.queuezero.io',
  });
  
  // ...
}
```

## Styling

Components use `qz-*` class names for easy styling:

```css
/* Form */
.qz-form { }
.qz-form-row { display: flex; gap: 8px; }
.qz-form-input { flex: 1; padding: 12px; }
.qz-form-button { padding: 12px 24px; }
.qz-form-error { color: red; margin-top: 8px; }

/* Status */
.qz-status { display: flex; gap: 16px; }
.qz-status-item { }
.qz-status-label { font-size: 12px; color: #666; }
.qz-status-value { font-size: 24px; font-weight: bold; }

/* Share */
.qz-share { }
.qz-share-input { flex: 1; padding: 8px; }
.qz-share-copy-button { padding: 8px 16px; }
.qz-share-social { display: flex; gap: 8px; margin-top: 8px; }
```

## TypeScript

Full TypeScript support with exported types:

```tsx
import type { 
  WaitlistProviderProps,
  WaitlistFormProps,
  UserStatus,
  SubmitResponse 
} from '@queuezero/react';
```

## License

MIT