npm package: @rooguy/react
Description: Rooguy Drop-In UI SDK for React
Latest version: 1.0.1

# @rooguy/react

Drop-in React components and headless hooks for adding gamification UI to your React app. Leaderboards, quests, user profiles, storefronts, toast notifications — all with real-time SSE updates, theming, i18n, and accessibility baked in.

## Installation

```bash
npm install @rooguy/react
```

Peer dependencies (you likely already have these):

```bash
npm install react react-dom
```

## Quick Start

Wrap your app with `RooguyProvider` and drop in any widget:

```tsx
import { RooguyProvider, RooguyLeaderboard } from "@rooguy/react";

function App() {
  return (
    <RooguyProvider
      publishableKey="pk_live_abc123"
      userToken="eyJhbGciOi..."
      baseUrl="https://api.rooguy.com"
    >
      <RooguyLeaderboard timeframe="weekly" />
    </RooguyProvider>
  );
}
```

## Provider

`<RooguyProvider>` initializes the SDK, resolves the user, opens an SSE connection for real-time updates, and provides context to all child widgets and hooks.

| Prop             | Type                                     | Required | Description                                                         |
| ---------------- | ---------------------------------------- | -------- | ------------------------------------------------------------------- |
| `publishableKey` | `string`                                 | Yes      | Your project's publishable API key                                  |
| `userToken`      | `string`                                 | No       | JWT identifying the current user. Omit for anonymous read-only mode |
| `baseUrl`        | `string`                                 | No       | API base URL (defaults to production)                               |
| `theme`          | `ThemeConfig`                            | No       | Custom theme overrides (maps to `--rooguy-*` CSS variables)         |
| `i18n`           | `Partial<I18nDictionary>`                | No       | Translation overrides                                               |
| `dir`            | `'ltr' \| 'rtl'`                         | No       | Text direction                                                      |
| `analytics`      | `'full' \| 'interactions-only' \| 'off'` | No       | Analytics tracking mode (default: `'off'`)                          |
| `onError`        | `(error: RooguyError) => void`           | No       | Global error callback                                               |

## Widgets

All widgets accept `classes`, `fallback`, and `i18n` props for customization.

### RooguyLeaderboard

```tsx
<RooguyLeaderboard
  leaderboardId="weekly-top"
  timeframe="weekly"
  highlightCurrentUser
  limit={10}
/>
```

### RooguyQuestList

```tsx
<RooguyQuestList status="in_progress" />
```

### RooguyUserWidget

```tsx
<RooguyUserWidget layout="compact" />
```

### RooguyStorefront

```tsx
<RooguyStorefront limit={12} />
```

### RooguyUserProfile

```tsx
<RooguyUserProfile sections={["header", "stats", "badges", "quests"]} />
```

### RooguyToastProvider

```tsx
<RooguyToastProvider position="top-right" duration={5000} maxVisible={3} />
```

### RooguyGroup

```tsx
<RooguyGroup
  groupId="group-123"
  sections={["header", "members", "leaderboard", "quests", "streaks"]}
  layout="card"
/>
```

### RooguyGroupLeaderboard

```tsx
<RooguyGroupLeaderboard groupType="team" limit={10} />
```

### RooguyTournamentBracket

```tsx
<RooguyTournamentBracket tournamentId="tourney-456" layout="bracket" />
```

### RooguyNotificationCenter

```tsx
<RooguyNotificationCenter layout="dropdown" limit={20} />
```

### RooguyBadgeShowcase

```tsx
<RooguyBadgeShowcase
  sortBy="earned_at"
  filterByCategory="achievement"
  layout="grid"
/>
```

### RooguyStreakWidget

```tsx
<RooguyStreakWidget layout="card" />
```

### RooguyAchievementTimeline

```tsx
<RooguyAchievementTimeline limit={20} filter={["badge", "level_up"]} />
```

### RooguyAhaScore

```tsx
<RooguyAhaScore layout="gauge" />
```

### RooguyProfileShare

```tsx
<RooguyProfileShare shareType="full" expiresInDays={7} />
```

### RooguyQuestionnaire

```tsx
<RooguyQuestionnaire
  questionnaireId="q-789"
  mode="paginated"
  allowRetake
  onComplete={(result) => console.log(result.assignedPersona)}
/>
```

### Widget Variants

V1 widgets support a `variant` prop for alternative visual styles:

```tsx
<RooguyLeaderboard timeframe="weekly" variant="podium" />
<RooguyQuestList status="in_progress" variant="checklist" />
<RooguyStorefront limit={12} variant="compact" />
<RooguyUserWidget layout="compact" variant="avatar-only" />
<RooguyToastProvider position="top-right" variant="minimal" />
```

## Headless Hooks

Use hooks directly when you want full control over rendering:

```tsx
import { useLeaderboard, useQuests, useUserProfile } from "@rooguy/react";

function CustomLeaderboard() {
  const { rankings, isLoading, currentUserRank } = useLeaderboard({
    timeframe: "weekly",
  });

  if (isLoading) return <p>Loading...</p>;

  return (
    <ul>
      {rankings.map((entry) => (
        <li key={entry.userId}>
          {entry.displayName}: {entry.points} pts
        </li>
      ))}
    </ul>
  );
}
```

### Available Hooks

| Hook                        | Returns                                                                                                                                |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `useLeaderboard(opts)`      | `rankings`, `pagination`, `isLoading`, `error`, `refetch`, `currentUserRank`                                                           |
| `useQuests(opts)`           | `quests`, `isLoading`, `error`, `refetch`, `claimReward`                                                                               |
| `useUserProfile()`          | `user`, `isLoading`, `error`, `refetch`                                                                                                |
| `useStorefront(opts)`       | `items`, `pagination`, `isLoading`, `error`, `purchase`, `userBalance`                                                                 |
| `useRooguyEvents(opts)`     | `events`, `lastEvent`, `connectionStatus`, `clearEvents`                                                                               |
| `useRooguy()`               | `trackEvent`                                                                                                                           |
| `useExperiments()`          | `activeExperiments`, `cohorts`                                                                                                         |
| `useFullProfile(opts)`      | `profile`, `badges`, `streaks`, `quests`, `inventory`, `activity`, `isLoading`, `error`                                                |
| `useGroup(opts)`            | `group`, `members`, `leaderboard`, `quests`, `streaks`, `buffs`, `inventory`, `isLoading`, `error`, `refetch`, `sections`              |
| `useGroupLeaderboard(opts)` | `groups`, `pagination`, `isLoading`, `error`, `refetch`, `currentUserGroup`                                                            |
| `useTournament(opts)`       | `tournament`, `participants`, `rounds`, `isLoading`, `error`, `refetch`                                                                |
| `useNotifications(opts)`    | `notifications`, `unreadCount`, `isLoading`, `error`, `markAsRead`, `markAllAsRead`, `refetch`, `pagination`                           |
| `useBadges(opts)`           | `badges`, `isLoading`, `error`, `refetch`, `totalCount`                                                                                |
| `useStreaks(opts)`          | `streaks`, `isLoading`, `error`, `refetch`                                                                                             |
| `useAchievements(opts)`     | `achievements`, `pagination`, `isLoading`, `error`, `refetch`                                                                          |
| `useAhaScore()`             | `currentScore`, `declarativeScore`, `inferredScore`, `status`, `isLoading`, `error`, `refetch`                                         |
| `useProfileShare()`         | `generateShareLink`, `shareUrl`, `isGenerating`, `error`, `previewData`                                                                |
| `useQuestionnaire(opts)`    | `questionnaire`, `questions`, `answers`, `setAnswer`, `submit`, `isSubmitting`, `isCompleted`, `assignedPersona`, `isLoading`, `error` |
| `useAnalytics()`            | `trackEvent`, `trackImpression`, `trackInteraction`, `sessionId`                                                                       |

All hooks throw a descriptive error if used outside of `<RooguyProvider>`.

## Theming

Override any CSS variable via the `theme` prop or directly in CSS:

```tsx
<RooguyProvider
  publishableKey="pk_live_abc123"
  theme={{
    primaryColor: '#6366f1',
    borderRadius: '12px',
    fontFamily: 'Inter, sans-serif',
  }}
>
```

All CSS classes use the `rooguy-` prefix. Use the `classes` prop on any widget to inject your own class names onto specific elements.

## Internationalization

```tsx
<RooguyProvider
  publishableKey="pk_live_abc123"
  i18n={{ rank: 'Rang', points: 'Punkte', claim: 'Einlösen' }}
>
```

Widget-level `i18n` overrides take highest precedence (widget > provider > defaults).

## Accessibility

- Semantic HTML (`<ol>`, `<progress>`, `<section>`, `<dialog>`)
- ARIA attributes on all interactive elements
- `aria-live="polite"` for toast notifications
- Focus trap in modals
- Keyboard navigable
- RTL support via `dir` prop