# @hiyve/react-room

Pre-built room components for Hiyve SDK — complete video conferencing in 5 lines of code.

## Installation

```bash
npx @hiyve/cli login
npm install @hiyve/react-room
```

### Peer Dependencies (Required)

```bash
npm install react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styled @hiyve/react @hiyve/react-ui @hiyve/core @hiyve/rtc-client @hiyve/utilities
```

### Peer Dependencies (Optional)

Install optional packages to enable additional sidebar tabs and features:

| Package | Enables |
|---------|---------|
| `@hiyve/react-collaboration` | Chat, Polls, Q&A, File Manager tabs |
| `@hiyve/react-intelligence` | Search, AI Intelligence Hub tabs |
| `@hiyve/react-whiteboard` | Whiteboard session tab |
| `@hiyve/react-notes` | Notes session tab |
| `@hiyve/react-assignments` | Assignments session tab |
| `@hiyve/react-capture` | Recording and Streaming controls |
| `@hiyve/react-clips` | Video clip creation and management sidebar tab |
| `@hiyve/cloud` | Cloud AI features (used by intelligence) |

```bash
# Install all optional packages
npm install @hiyve/react-collaboration @hiyve/react-intelligence @hiyve/react-whiteboard @hiyve/react-notes @hiyve/react-assignments @hiyve/react-capture @hiyve/cloud
```

## Quick Start

### Minimal Setup

```tsx
import { HiyveRoom, PrebuiltRoom } from '@hiyve/react-room';

function App() {
  const token = '...'; // from your signaling server

  return (
    <HiyveRoom roomToken={token}>
      <PrebuiltRoom onLeave={() => window.location.href = '/'} />
    </HiyveRoom>
  );
}
```

### With Lobby Flow

```tsx
import { useState } from 'react';
import { HiyveRoom, PrebuiltLobby, PrebuiltRoom } from '@hiyve/react-room';

function App() {
  const [joined, setJoined] = useState(false);
  const [name, setName] = useState('');
  const token = '...';

  if (!joined) {
    return (
      <PrebuiltLobby
        onJoin={(displayName) => {
          setName(displayName);
          setJoined(true);
        }}
        showPreview
      />
    );
  }

  return (
    <HiyveRoom roomToken={token}>
      <PrebuiltRoom userId={name} onLeave={() => setJoined(false)} />
    </HiyveRoom>
  );
}
```

## Components

| Component | Description |
|-----------|-------------|
| `HiyveRoom` | Provider composer — sets up theming, WebRTC connectivity, and optional AI features for all children |
| `PrebuiltRoom` | Complete room UI with video grid, control bar, app bar, and tabbed sidebar |
| `PrebuiltLobby` | Pre-call screen with device preview, device selector, name input, and join button |
| `RemoteCameraPage` | Mobile-optimized page for joining a room as a video-only ghost participant (phone-as-camera) |

### HiyveRoom Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `roomToken` | `string` | _(required)_ | Room token from your signaling server |
| `cloudToken` | `string` | — | Cloud token for AI features |
| `generateToken` | `() => Promise<string>` | — | Async function to generate cloud tokens (alternative to `cloudToken`) |
| `userId` | `string` | — | User ID for cloud features |
| `intelligence` | `boolean` | `false` | Enable AI features (requires `cloudToken` or `generateToken`) |
| `children` | `ReactNode` | _(required)_ | Children to render inside providers |

### PrebuiltRoom Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `userId` | `string` | — | User ID for features requiring identification |
| `roomName` | `string` | — | Room name to display in the app bar |
| `sidebar` | `PrebuiltRoomSidebarConfig` | see below | Sidebar tab configuration |
| `labels` | `Partial<PrebuiltRoomLabels>` | see below | Custom labels |
| `colors` | `Partial<PrebuiltRoomColors>` | see below | Custom colors |
| `styles` | `Partial<PrebuiltRoomStyles>` | see below | Custom styles |
| `onLeave` | `() => void` | — | Called when user clicks leave |
| `onError` | `(error: Error) => void` | — | Called when errors occur |
| `controlBar` | `Partial<PrebuiltRoomControlBarConfig>` | — | ControlBar passthrough props |
| `videoGrid` | `Partial<PrebuiltRoomVideoGridConfig>` | — | VideoGrid passthrough props |
| `participantList` | `Partial<PrebuiltRoomParticipantListConfig>` | — | ParticipantList passthrough props |

### PrebuiltRoomSidebarConfig

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `showParticipants` | `boolean` | `true` | Show participants tab |
| `showChat` | `boolean` | `false` | Show chat tab (requires `@hiyve/react-collaboration`) |
| `showPolls` | `boolean` | `false` | Show polls session tab (requires `@hiyve/react-collaboration`) |
| `showQA` | `boolean` | `false` | Show Q&A session tab (requires `@hiyve/react-collaboration`) |
| `showSearch` | `boolean` | `false` | Show search tab (requires `@hiyve/react-intelligence`) |
| `showFiles` | `boolean` | `false` | Show files tab (requires `@hiyve/react-collaboration`) |
| `showIntelligence` | `boolean` | `false` | Show AI intelligence hub tab (requires `@hiyve/react-intelligence`) |
| `showWhiteboard` | `boolean` | `false` | Show whiteboard session tab (requires `@hiyve/react-whiteboard`) |
| `showNotes` | `boolean` | `false` | Show notes session tab (requires `@hiyve/react-notes`) |
| `showAssignments` | `boolean` | `false` | Show assignments session tab (requires `@hiyve/react-assignments`) |
| `defaultTab` | `string` | `'participants'` | Default open sidebar tab |
| `tabOrder` | `string[]` | -- | Custom tab display order; tabs not listed appear after listed ones |

### PrebuiltLobby Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `onJoin` | `(displayName: string) => void` | _(required)_ | Called when user clicks join |
| `defaultName` | `string` | `''` | Default display name |
| `showPreview` | `boolean` | `true` | Show device preview |
| `showNameInput` | `boolean` | `true` | Show the name input field; when `false`, `defaultName` is passed directly to `onJoin` |
| `labels` | `Partial<PrebuiltLobbyLabels>` | see below | Custom labels |
| `colors` | `Partial<PrebuiltLobbyColors>` | see below | Custom colors |
| `onError` | `(error: Error) => void` | — | Called when errors occur |

### RemoteCameraPage

A minimal, mobile-optimized full-screen page for joining a room as a video-only ghost participant. Designed to be opened on a phone after scanning a QR code from the desktop app. Shows a camera preview, a connect button, and minimal controls (flip camera and disconnect). Audio is always muted.

```tsx
import { RemoteCameraPage } from '@hiyve/react-room';
import { HiyveRoom } from '@hiyve/react-room';

function CameraPage() {
  const params = new URLSearchParams(window.location.search);

  return (
    <HiyveRoom roomToken={params.get('joinToken')!}>
      <RemoteCameraPage
        joinToken={params.get('joinToken')!}
        region={params.get('region')!}
        ghostUserId={params.get('ghostUserId')!}
        onDisconnect={() => window.close()}
      />
    </HiyveRoom>
  );
}
```

#### RemoteCameraPage Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `joinToken` | `string` | _(required)_ | Join token from the QR code URL |
| `region` | `string` | _(required)_ | Room region from the QR code URL |
| `ghostUserId` | `string` | _(required)_ | Ghost userId to join as |
| `onDisconnect` | `() => void` | -- | Called when the user disconnects |
| `preferredFacingMode` | `'user' \| 'environment'` | `'environment'` | Initial camera facing mode (back camera by default) |
| `labels` | `Partial<RemoteCameraPageLabels>` | see below | Custom labels |
| `colors` | `Partial<RemoteCameraPageColors>` | see below | Custom colors |

#### RemoteCameraPage Labels

| Key | Default |
|-----|---------|
| `validating` | `'Validating link...'` |
| `readyTitle` | `'Camera Ready'` |
| `readyDescription` | `'Tap Connect to share your camera with the room.'` |
| `connect` | `'Connect'` |
| `connecting` | `'Connecting...'` |
| `flipCamera` | `'Flip Camera'` |
| `disconnect` | `'End'` |
| `disconnected` | `'Disconnected'` |
| `disconnectedDescription` | `'The camera session has ended.'` |
| `errorTitle` | `'Unable to Connect'` |
| `expired` | `'This link has expired. Please scan a new QR code.'` |
| `invalidLink` | `'Invalid link. Please scan the QR code again.'` |

#### RemoteCameraPage Colors

| Key | Default |
|-----|---------|
| `background` | `'#000000'` |
| `text` | `'#ffffff'` |
| `textSecondary` | `'rgba(255, 255, 255, 0.7)'` |
| `connectButton` | `'#1976d2'` |
| `disconnectButton` | `'#d32f2f'` |
| `flipButton` | `'rgba(255, 255, 255, 0.2)'` |

## Usage Examples

### Basic Room

```tsx
<HiyveRoom roomToken={token}>
  <PrebuiltRoom onLeave={handleLeave} />
</HiyveRoom>
```

### Sidebar Configuration

Control which sidebar tabs are available:

```tsx
<PrebuiltRoom
  onLeave={handleLeave}
  sidebar={{
    showParticipants: true,
    showChat: true,
    showPolls: true,
    showQA: true,
    showFiles: true,
    showWhiteboard: true,
    showNotes: true,
    showAssignments: true,
    showSearch: false,
    showIntelligence: false,
    defaultTab: 'chat',
  }}
/>
```

### Sub-Component Customization

Customize the ControlBar, VideoGrid, and ParticipantList rendered inside PrebuiltRoom:

```tsx
<PrebuiltRoom
  onLeave={handleLeave}
  controlBar={{
    showScreenShare: false,
    showHandRaise: true,
    showRecordingMenu: true,
    colors: { background: 'rgba(0, 0, 0, 0.9)' },
  }}
  videoGrid={{
    showNames: true,
    styles: { gap: 12, padding: 16 },
    colors: { dominantBorder: '#00ff88' },
  }}
  participantList={{
    showSpeakingIndicator: true,
  }}
/>
```

### Custom Labels and Colors

```tsx
<PrebuiltRoom
  onLeave={handleLeave}
  labels={{ roomTitle: 'Team Standup' }}
  colors={{
    appBarBackground: '#0d1b2a',
    appBarText: '#e0e0e0',
    background: '#1b263b',
  }}
  styles={{
    appBarHeight: 48,
    sidebarWidth: 400,
  }}
/>
```

### Intelligence-Enabled Room

```tsx
<HiyveRoom
  roomToken={token}
  cloudToken={cloudToken}
  userId="user-123"
  intelligence
>
  <PrebuiltRoom
    userId="user-123"
    onLeave={handleLeave}
    sidebar={{ showSearch: true, showIntelligence: true }}
  />
</HiyveRoom>
```

### Custom Lobby

```tsx
<PrebuiltLobby
  onJoin={handleJoin}
  defaultName="Guest"
  showPreview
  labels={{
    title: 'Welcome to the Meeting',
    joinButton: 'Enter Room',
    namePlaceholder: 'Your display name',
  }}
  colors={{
    background: '#0a0a1a',
    cardBackground: '#1a1a2e',
    primaryColor: '#4caf50',
  }}
/>
```

## Sub-Component Customization

PrebuiltRoom renders `ControlBar`, `VideoGrid`, and `ParticipantList` from `@hiyve/react-ui`. You can pass props to each sub-component directly:

```tsx
<PrebuiltRoom
  controlBar={{ /* ControlBar props */ }}
  videoGrid={{ /* VideoGrid props */ }}
  participantList={{ /* ParticipantList props */ }}
/>
```

### Managed Props

PrebuiltRoom handles certain capabilities automatically. The following props are managed and cannot be overridden via passthrough:

| Sub-Component | Managed Props | Reason |
|---------------|---------------|--------|
| `ControlBar` | `layout`, `onLayoutChange`, `onLeave`, `onError` | Layout switching, leave, and error handling are coordinated by PrebuiltRoom |
| `VideoGrid` | `layout`, `localVideoElementId` | Layout mode and local video element are managed automatically |
| `ParticipantList` | _(none)_ | All props are passed through |

### Examples

**Hide screen share and show hand raise:**

```tsx
<PrebuiltRoom
  onLeave={handleLeave}
  controlBar={{ showScreenShare: false, showHandRaise: true }}
/>
```

**Customize video grid spacing and dominant speaker highlight:**

```tsx
<PrebuiltRoom
  onLeave={handleLeave}
  videoGrid={{
    styles: { gap: 16, padding: 20 },
    colors: { dominantBorder: '#ff6b35' },
  }}
/>
```

**Pass labels to ControlBar for i18n:**

```tsx
<PrebuiltRoom
  onLeave={handleLeave}
  controlBar={{
    labels: {
      mute: 'Couper le micro',
      unmute: 'Activer le micro',
      shareScreen: 'Partager',
    },
  }}
/>
```

## Customization

### Labels (i18n)

```tsx
import {
  defaultPrebuiltRoomLabels,
  mergePrebuiltRoomLabels,
  defaultPrebuiltLobbyLabels,
  mergePrebuiltLobbyLabels,
} from '@hiyve/react-room';

// Partial override
<PrebuiltRoom labels={{ roomTitle: 'Mon Salon' }} />

// Programmatic merge
const frenchLabels = mergePrebuiltRoomLabels({ roomTitle: 'Mon Salon' });
```

### Colors

```tsx
import { defaultPrebuiltRoomColors, mergePrebuiltRoomColors } from '@hiyve/react-room';

<PrebuiltRoom
  colors={{
    appBarBackground: '#1a237e',
    background: '#0d1117',
  }}
/>
```

### Styles

```tsx
import { defaultPrebuiltRoomStyles, mergePrebuiltRoomStyles } from '@hiyve/react-room';

<PrebuiltRoom styles={{ appBarHeight: 48, sidebarWidth: 320, sidebarVariant: 'temporary' }} />
```

Available style properties: `appBarHeight` (pixels), `sidebarWidth` (pixels), `sidebarVariant` (`'persistent'` or `'temporary'` — persistent pushes content, temporary overlays).

### Available Default/Merge Exports

| Export | Purpose |
|--------|---------|
| `defaultSidebarConfig` / `mergeSidebarConfig` | Sidebar tab visibility and default tab |
| `defaultPrebuiltRoomLabels` / `mergePrebuiltRoomLabels` | Room UI labels |
| `defaultPrebuiltRoomColors` / `mergePrebuiltRoomColors` | Room UI colors |
| `defaultPrebuiltRoomStyles` / `mergePrebuiltRoomStyles` | Room UI dimensions |
| `defaultPrebuiltLobbyLabels` / `mergePrebuiltLobbyLabels` | Lobby labels |
| `defaultPrebuiltLobbyColors` / `mergePrebuiltLobbyColors` | Lobby colors |
| `defaultRemoteCameraPageLabels` / `mergeRemoteCameraPageLabels` | Remote camera page labels |
| `defaultRemoteCameraPageColors` / `mergeRemoteCameraPageColors` | Remote camera page colors |

### Type Exports

All prop interfaces are exported for TypeScript consumers:

```tsx
import type {
  HiyveRoomProps,
  PrebuiltRoomProps,
  PrebuiltRoomSidebarConfig,
  PrebuiltRoomLabels,
  PrebuiltRoomColors,
  PrebuiltRoomStyles,
  PrebuiltRoomControlBarConfig,
  PrebuiltRoomVideoGridConfig,
  PrebuiltRoomParticipantListConfig,
  PrebuiltLobbyProps,
  PrebuiltLobbyLabels,
  PrebuiltLobbyColors,
  RemoteCameraPageProps,
  RemoteCameraPageLabels,
  RemoteCameraPageColors,
} from '@hiyve/react-room';
```

## Features

- Complete video conferencing room in 5 lines of code
- Provider composer handles theming, WebRTC connectivity, and optional AI features
- Pre-call lobby with device preview, device selection, and name input
- App bar with room title and live clock
- Tabbed sidebar with participants, chat, polls, Q&A, files, whiteboard, notes, assignments, search, and AI hub
- Sub-component customization for ControlBar, VideoGrid, and ParticipantList
- Sidebar tabs auto-hide when optional packages are not installed
- Full label, color, and style customization with merge functions
- Dark theme by default
- Layout switching (grid, speaker, sidebar modes)

## Requirements

- Must be wrapped in `HiyveRoom`
- React 18+
- MUI v5 or v6 (`@mui/material`, `@mui/icons-material`) with Emotion
- `@hiyve/react`, `@hiyve/react-ui`, `@hiyve/core`, `@hiyve/rtc-client`, `@hiyve/utilities` as peer dependencies
- Optional: `@hiyve/react-collaboration`, `@hiyve/react-intelligence`, `@hiyve/react-whiteboard`, `@hiyve/react-notes`, `@hiyve/react-assignments`, `@hiyve/react-capture`, `@hiyve/cloud`

## License

MIT
