@naviedu/room-platform-react 0.0.1 → 0.0.3-8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +262 -0
- package/index.d.ts +766 -32
- package/index.esm.js +19621 -7892
- package/package.json +4 -7
- package/styles.css +199 -24
- package/assets/ATTRIBUTION.md +0 -46
- package/assets/presets/alpine-lake-mirror.jpg +0 -0
- package/assets/presets/alpine-lake.jpg +0 -0
- package/assets/presets/canyon-view-mirror.jpg +0 -0
- package/assets/presets/canyon-view.jpg +0 -0
- package/assets/presets/desert-dunes-mirror.jpg +0 -0
- package/assets/presets/desert-dunes.jpg +0 -0
- package/assets/presets/flower-meadow-mirror.jpg +0 -0
- package/assets/presets/flower-meadow.jpg +0 -0
- package/assets/presets/forest-road-mirror.jpg +0 -0
- package/assets/presets/forest-road.jpg +0 -0
- package/assets/presets/naviedu-mirror.jpg +0 -0
- package/assets/presets/naviedu.jpg +0 -0
- package/assets/presets/ocean-cliffs-mirror.jpg +0 -0
- package/assets/presets/ocean-cliffs.jpg +0 -0
- package/assets/presets/tropical-beach-mirror.jpg +0 -0
- package/assets/presets/tropical-beach.jpg +0 -0
- package/assets/presets/waterfall-mist-mirror.jpg +0 -0
- package/assets/presets/waterfall-mist.jpg +0 -0
- package/extensions/room-platform-extensions.d.ts +0 -8
- package/room-action-button.d.ts +0 -11
- package/room-participant-actions.d.ts +0 -9
- package/room-participant-list.d.ts +0 -7
- package/room-participant-tab.d.ts +0 -6
- package/room-platform-active-speaker.d.ts +0 -4
- package/room-platform-background-settings.d.ts +0 -15
- package/room-platform-camera-background-presets.d.ts +0 -8
- package/room-platform-camera-background-storage.d.ts +0 -38
- package/room-platform-control-anchor.d.ts +0 -10
- package/room-platform-control-bar.d.ts +0 -11
- package/room-platform-control-state.d.ts +0 -12
- package/room-platform-current-operation-strip.d.ts +0 -13
- package/room-platform-device-selection.d.ts +0 -7
- package/room-platform-device-settings.d.ts +0 -8
- package/room-platform-local-preview.d.ts +0 -6
- package/room-platform-media-controls.d.ts +0 -1
- package/room-platform-media-runtime.d.ts +0 -2
- package/room-platform-monitor-stage.d.ts +0 -7
- package/room-platform-monitor-video-tile.d.ts +0 -20
- package/room-platform-monitor-viewer.d.ts +0 -8
- package/room-platform-private-room-connection.d.ts +0 -11
- package/room-platform-private-room-context.d.ts +0 -8
- package/room-platform-private-room-control-bar.d.ts +0 -12
- package/room-platform-private-room-experience.d.ts +0 -14
- package/room-platform-private-room-overlay.d.ts +0 -7
- package/room-platform-private-room-stage.d.ts +0 -9
- package/room-platform-private-room-status-banner.d.ts +0 -8
- package/room-platform-provider.d.ts +0 -35
- package/room-platform-room.d.ts +0 -2
- package/room-platform-screen-share-whiteboard-frame.d.ts +0 -11
- package/room-platform-shell.d.ts +0 -17
- package/room-platform-speak-queue.d.ts +0 -16
- package/room-platform-stage-selection.d.ts +0 -14
- package/room-platform-stage.d.ts +0 -13
- package/room-platform-surface-boundary.d.ts +0 -13
- package/room-platform-top-bar.d.ts +0 -7
- package/room-platform-types.d.ts +0 -154
- package/room-platform-ui-primitives.d.ts +0 -60
- package/room-platform-video-tile.d.ts +0 -13
- package/room-platform-video-tracks.d.ts +0 -6
- package/use-room-platform-camera-background.d.ts +0 -34
- package/use-room-platform-private-room-control-actions.d.ts +0 -21
- package/use-room-platform-private-room.d.ts +0 -43
- package/use-room-platform-stage.d.ts +0 -2
- package/use-room-presence.d.ts +0 -2
package/README.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# @naviedu/room-platform-react
|
|
2
|
+
|
|
3
|
+
Embeddable React UI and runtime for NaviEdu Room Platform rooms. The package
|
|
4
|
+
owns the default room experience, LiveKit connection, media controls, speaker
|
|
5
|
+
requests, private rooms, responsive layout, and optional chat and whiteboard
|
|
6
|
+
surfaces.
|
|
7
|
+
|
|
8
|
+
## Requirements
|
|
9
|
+
|
|
10
|
+
- React 18 or 19
|
|
11
|
+
- A Room Platform launch ticket issued by the host backend
|
|
12
|
+
- A public Room Platform API base URL
|
|
13
|
+
- A browser running in a secure context when camera, microphone, or screen
|
|
14
|
+
sharing is required
|
|
15
|
+
|
|
16
|
+
The launch ticket is short-lived and must be obtained server-side. Do not put
|
|
17
|
+
backend credentials or long-lived signing secrets in the browser bundle.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @naviedu/room-platform-react
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`react` and `react-dom` are peer dependencies. Room Platform's published
|
|
26
|
+
runtime dependencies are installed automatically with the package.
|
|
27
|
+
|
|
28
|
+
## Basic usage
|
|
29
|
+
|
|
30
|
+
Render `RoomPlatformRoom` with the launch ticket returned by your backend:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
'use client'
|
|
34
|
+
|
|
35
|
+
import { type RoomLaunchTicketRenewalReason, RoomPlatformRoom } from '@naviedu/room-platform-react'
|
|
36
|
+
|
|
37
|
+
type RoomTicketResponse = { launchToken: string }
|
|
38
|
+
|
|
39
|
+
export function Room({ launchToken }: { launchToken: string }) {
|
|
40
|
+
async function renewLaunchTicket(_reason: RoomLaunchTicketRenewalReason): Promise<RoomTicketResponse> {
|
|
41
|
+
const response = await fetch('/api/room-platform/launch-ticket', {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
credentials: 'include',
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
if (!response.ok) throw new Error('Unable to renew the Room Platform launch ticket')
|
|
47
|
+
|
|
48
|
+
return (await response.json()) as RoomTicketResponse
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<RoomPlatformRoom
|
|
53
|
+
apiBaseUrl="https://api.example.com/room-platform"
|
|
54
|
+
launchToken={launchToken}
|
|
55
|
+
onLaunchTicketRequired={renewLaunchTicket}
|
|
56
|
+
onExit={() => window.history.back()}
|
|
57
|
+
/>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`RoomPlatformRoom` renders its default room UI in an isolated Shadow Root and installs the package stylesheet itself. Do not import `@naviedu/room-platform-react/styles.css` for the default component.
|
|
63
|
+
|
|
64
|
+
`RoomPlatformProvider` is advanced composition only; a consumer using it instead of `RoomPlatformRoom` owns its own DOM and stylesheet boundary.
|
|
65
|
+
|
|
66
|
+
`apiBaseUrl` is the URL prefix before `/rooms`. The package calls these routes
|
|
67
|
+
relative to it:
|
|
68
|
+
|
|
69
|
+
- `POST /rooms/exchange`
|
|
70
|
+
- `GET /rooms/:roomId/control-state`
|
|
71
|
+
- `POST /rooms/:roomId/actions`
|
|
72
|
+
|
|
73
|
+
For example, with `apiBaseUrl="https://api.example.com/room-platform"`, the
|
|
74
|
+
exchange request is sent to
|
|
75
|
+
`https://api.example.com/room-platform/rooms/exchange`.
|
|
76
|
+
|
|
77
|
+
The package renders a full viewport room (`100dvh`). Mount it in a page or
|
|
78
|
+
layout that allows the room to occupy the viewport.
|
|
79
|
+
|
|
80
|
+
## `RoomPlatformRoom` props
|
|
81
|
+
|
|
82
|
+
| Prop | Required | Description |
|
|
83
|
+
| ------------------------ | -------- | ------------------------------------------------------------------------------------ |
|
|
84
|
+
| `apiBaseUrl` | Yes | Room Platform API prefix. Do not append `/rooms`. |
|
|
85
|
+
| `launchToken` | Yes | Initial server-issued launch ticket. |
|
|
86
|
+
| `onLaunchTicketRequired` | Yes | Returns `{ launchToken }` when the current ticket or access session must be renewed. |
|
|
87
|
+
| `extensions` | No | Host-provided top-bar, workspace, sidebar, monitor, and participant extensions. |
|
|
88
|
+
| `onError` | No | Receives connection, media, and action errors. |
|
|
89
|
+
| `onLifecycleEvent` | No | Receives exchange, renewal, and reconnect lifecycle events. |
|
|
90
|
+
| `onExit` | No | Called when the user chooses to leave the room. |
|
|
91
|
+
| `children` | No | Replaces the default workspace while keeping the provider and room runtime. |
|
|
92
|
+
|
|
93
|
+
The default teaching stage selects the available participant camera carrying
|
|
94
|
+
the canonical `room:moderate` capability. Screen share remains primary and the
|
|
95
|
+
moderator camera becomes its overlay. If no moderator camera is available, the
|
|
96
|
+
stage keeps its waiting state and never promotes a student camera. The local
|
|
97
|
+
sidebar preview is hidden only when that selected moderator camera is local;
|
|
98
|
+
its existing desktop breakpoint remains unchanged.
|
|
99
|
+
|
|
100
|
+
The public room keeps one canonical local camera track. It may be preview-only
|
|
101
|
+
before publication, and preview visibility never grants `media:publish_video`.
|
|
102
|
+
|
|
103
|
+
### Error and lifecycle callbacks
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
<RoomPlatformRoom
|
|
107
|
+
// ...required props
|
|
108
|
+
onError={({ error, recoverable, scope }) => {
|
|
109
|
+
console.error(`[room-platform:${scope}]`, error)
|
|
110
|
+
if (!recoverable) {
|
|
111
|
+
// Show the host application's unavailable-room state.
|
|
112
|
+
}
|
|
113
|
+
}}
|
|
114
|
+
onLifecycleEvent={(event) => {
|
|
115
|
+
// Send telemetry to the host backend if needed.
|
|
116
|
+
console.info('Room Platform lifecycle:', event)
|
|
117
|
+
}}
|
|
118
|
+
/>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Lifecycle events are `exchange.succeeded`, `exchange.failed`,
|
|
122
|
+
`renewal.succeeded`, `renewal.failed`, `reconnect.succeeded`, and
|
|
123
|
+
`reconnect.failed`.
|
|
124
|
+
|
|
125
|
+
## Chat and whiteboard boundary
|
|
126
|
+
|
|
127
|
+
Chat and Whiteboard are owned by the Room Platform exchange. The host only
|
|
128
|
+
passes the launch ticket and public Room Platform API base URL shown above;
|
|
129
|
+
there is no public `integrations` prop.
|
|
130
|
+
|
|
131
|
+
After the launch ticket exchange succeeds and LiveKit connects, the package
|
|
132
|
+
hydrates the Chat and Whiteboard projection returned by Room Platform. The
|
|
133
|
+
projection contains only the short-lived, already-authorized runtime data
|
|
134
|
+
needed by the package. On renewal, the complete projection is replaced.
|
|
135
|
+
|
|
136
|
+
Each integration degrades independently. An `available: false` Chat or
|
|
137
|
+
Whiteboard projection disables only that surface; LiveKit, the other
|
|
138
|
+
integration, and private-room invite, accept, and media flows remain usable.
|
|
139
|
+
LiveKit exchange/connection failure is the only fatal case for mounting the
|
|
140
|
+
room integrations.
|
|
141
|
+
|
|
142
|
+
Consumers must not provide or derive Chat/Whiteboard credentials, internal or
|
|
143
|
+
service endpoints, integration room IDs, or permission objects. Do not expose
|
|
144
|
+
app/HMAC secrets or call Chat/Whiteboard services directly from the host. The
|
|
145
|
+
Room Platform exchange is the trust boundary and supplies the public runtime
|
|
146
|
+
projection after server-side authorization.
|
|
147
|
+
|
|
148
|
+
Whiteboard uses the exchanged Room Platform `roomId` for its room context and
|
|
149
|
+
is created lazily only when Whiteboard is available and a screen share starts.
|
|
150
|
+
Stopping a share deactivates its board; every new share receives a new
|
|
151
|
+
`shareSessionKey`. No board is mounted before sharing begins.
|
|
152
|
+
|
|
153
|
+
## Extensions
|
|
154
|
+
|
|
155
|
+
Extensions keep host-specific UI outside the shared room implementation. Every
|
|
156
|
+
extension receives `RoomPlatformExtensionProps`:
|
|
157
|
+
|
|
158
|
+
Host extensions with independent framework CSS must own their own DOM and
|
|
159
|
+
stylesheet boundary.
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import type { RoomPlatformExtensionProps } from '@naviedu/room-platform-react'
|
|
163
|
+
|
|
164
|
+
function HostToolbar({ actions, capabilities, connectionStatus, roomId }: RoomPlatformExtensionProps) {
|
|
165
|
+
const canModerate = capabilities.includes('room:moderate')
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<div>
|
|
169
|
+
<span>{connectionStatus}</span>
|
|
170
|
+
<span>{roomId}</span>
|
|
171
|
+
{canModerate ? (
|
|
172
|
+
<button type="button" onClick={() => void actions.perform('speak.request')}>
|
|
173
|
+
Request to speak
|
|
174
|
+
</button>
|
|
175
|
+
) : null}
|
|
176
|
+
</div>
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
;<RoomPlatformRoom
|
|
181
|
+
// ...required props
|
|
182
|
+
extensions={{
|
|
183
|
+
topBarTrailing: HostToolbar,
|
|
184
|
+
sidebarTabs: [{ id: 'materials', title: 'Materials', component: HostMaterialsTab }],
|
|
185
|
+
mainWorkspace: {
|
|
186
|
+
component: HostWorkspace,
|
|
187
|
+
},
|
|
188
|
+
}}
|
|
189
|
+
/>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Available extension slots are:
|
|
193
|
+
|
|
194
|
+
- `topBarLeading` and `topBarTrailing`
|
|
195
|
+
- `mainWorkspace` for the practice workspace overlay
|
|
196
|
+
- `sidebarTabs`
|
|
197
|
+
- `participantTab` in `default` or `replace` mode
|
|
198
|
+
- `monitor` with a host-provided participant roster and eligibility flag
|
|
199
|
+
|
|
200
|
+
`actions.perform` sends a Room Platform action and accepts an optional string
|
|
201
|
+
payload. Check `actions.hasCapability(...)` before rendering privileged
|
|
202
|
+
controls, and use `actions.isPending(...)` to disable controls during an
|
|
203
|
+
in-flight action.
|
|
204
|
+
|
|
205
|
+
## Advanced composition
|
|
206
|
+
|
|
207
|
+
Use `RoomPlatformProvider` and `useRoomPlatform` when the host needs to render
|
|
208
|
+
a custom room surface instead of `RoomPlatformRoom`'s default workspace:
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import { RoomPlatformProvider, type RoomPlatformProviderProps, useRoomPlatform } from '@naviedu/room-platform-react'
|
|
212
|
+
|
|
213
|
+
function CustomRoomSurface() {
|
|
214
|
+
const { localMedia, setLocalMediaEnabled, status } = useRoomPlatform()
|
|
215
|
+
|
|
216
|
+
return (
|
|
217
|
+
<button
|
|
218
|
+
type="button"
|
|
219
|
+
disabled={status !== 'connected'}
|
|
220
|
+
onClick={() => void setLocalMediaEnabled('camera', !localMedia.camera)}
|
|
221
|
+
>
|
|
222
|
+
{localMedia.camera ? 'Turn camera off' : 'Turn camera on'}
|
|
223
|
+
</button>
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function CustomRoom(props: {
|
|
228
|
+
apiBaseUrl: string
|
|
229
|
+
launchToken: string
|
|
230
|
+
onLaunchTicketRequired: RoomPlatformProviderProps['onLaunchTicketRequired']
|
|
231
|
+
}) {
|
|
232
|
+
return (
|
|
233
|
+
<RoomPlatformProvider {...props}>
|
|
234
|
+
<CustomRoomSurface />
|
|
235
|
+
</RoomPlatformProvider>
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Use `RoomPlatformRoom` unless a custom surface is required. It composes the
|
|
241
|
+
provider, LiveKit media runtime, private-room runtime, default stage, controls,
|
|
242
|
+
and sidebar for you.
|
|
243
|
+
|
|
244
|
+
## Publishing and local verification
|
|
245
|
+
|
|
246
|
+
From the repository root:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
yarn nx run @naviedu/room-platform-react:build
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The publishable package is written to
|
|
253
|
+
`dist/libs/features/room-platform-react`. Inspect it before publishing:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
cd dist/libs/features/room-platform-react
|
|
257
|
+
npm pack --dry-run
|
|
258
|
+
npm publish --access public
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
The package embeds the required shared UI source during bundling, so consumers
|
|
262
|
+
do not need private workspace aliases such as `@navi/ui` or `@navi/utils`.
|