@runwayml/avatars-react 0.6.0 → 0.7.0
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/dist/index.cjs +30 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +32 -76
- package/dist/index.js.map +1 -1
- package/dist/styles.css +29 -5
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
|
@@ -77,6 +77,8 @@ function useCredentials(options) {
|
|
|
77
77
|
onError
|
|
78
78
|
} = options;
|
|
79
79
|
const onErrorRef = useLatest(onError);
|
|
80
|
+
const connectRef = useLatest(connect);
|
|
81
|
+
const fetchedKeyRef = react.useRef(null);
|
|
80
82
|
const [state, setState] = react.useState(() => {
|
|
81
83
|
if (directCredentials) {
|
|
82
84
|
return { status: "ready", credentials: directCredentials, error: null };
|
|
@@ -92,6 +94,9 @@ function useCredentials(options) {
|
|
|
92
94
|
});
|
|
93
95
|
return;
|
|
94
96
|
}
|
|
97
|
+
const credentialKey = `${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;
|
|
98
|
+
if (fetchedKeyRef.current === credentialKey) return;
|
|
99
|
+
fetchedKeyRef.current = credentialKey;
|
|
95
100
|
let cancelled = false;
|
|
96
101
|
setState({ status: "loading", credentials: null, error: null });
|
|
97
102
|
async function load() {
|
|
@@ -101,7 +106,7 @@ function useCredentials(options) {
|
|
|
101
106
|
sessionId,
|
|
102
107
|
sessionKey,
|
|
103
108
|
connectUrl,
|
|
104
|
-
connect,
|
|
109
|
+
connect: connectRef.current ?? void 0,
|
|
105
110
|
baseUrl
|
|
106
111
|
};
|
|
107
112
|
const credentials = await fetchCredentials(fetchOptions);
|
|
@@ -120,30 +125,25 @@ function useCredentials(options) {
|
|
|
120
125
|
return () => {
|
|
121
126
|
cancelled = true;
|
|
122
127
|
};
|
|
123
|
-
}, [
|
|
124
|
-
directCredentials,
|
|
125
|
-
avatarId,
|
|
126
|
-
sessionId,
|
|
127
|
-
sessionKey,
|
|
128
|
-
connectUrl,
|
|
129
|
-
connect,
|
|
130
|
-
baseUrl
|
|
131
|
-
]);
|
|
128
|
+
}, [directCredentials, avatarId, sessionId, sessionKey, connectUrl, baseUrl]);
|
|
132
129
|
return state;
|
|
133
130
|
}
|
|
134
|
-
async function hasMediaDevice(kind) {
|
|
131
|
+
async function hasMediaDevice(kind, timeoutMs = 1e3) {
|
|
135
132
|
try {
|
|
136
|
-
const
|
|
137
|
-
|
|
133
|
+
const timeoutPromise = new Promise(
|
|
134
|
+
(resolve) => setTimeout(() => resolve(false), timeoutMs)
|
|
135
|
+
);
|
|
136
|
+
const checkPromise = navigator.mediaDevices.enumerateDevices().then((devices) => devices.some((device) => device.kind === kind));
|
|
137
|
+
return await Promise.race([checkPromise, timeoutPromise]);
|
|
138
138
|
} catch {
|
|
139
139
|
return false;
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
function useDeviceAvailability(requestAudio, requestVideo) {
|
|
143
143
|
const [state, setState] = react.useState({
|
|
144
|
-
audio:
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
audio: requestAudio,
|
|
145
|
+
// Optimistically assume devices exist
|
|
146
|
+
video: requestVideo
|
|
147
147
|
});
|
|
148
148
|
react.useEffect(() => {
|
|
149
149
|
let cancelled = false;
|
|
@@ -155,8 +155,7 @@ function useDeviceAvailability(requestAudio, requestVideo) {
|
|
|
155
155
|
if (!cancelled) {
|
|
156
156
|
setState({
|
|
157
157
|
audio: requestAudio && hasAudio,
|
|
158
|
-
video: requestVideo && hasVideo
|
|
159
|
-
isChecking: false
|
|
158
|
+
video: requestVideo && hasVideo
|
|
160
159
|
});
|
|
161
160
|
}
|
|
162
161
|
}
|
|
@@ -207,21 +206,6 @@ function AvatarSession({
|
|
|
207
206
|
...DEFAULT_ROOM_OPTIONS,
|
|
208
207
|
...__unstable_roomOptions
|
|
209
208
|
};
|
|
210
|
-
if (deviceAvailability.isChecking) {
|
|
211
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
212
|
-
AvatarSessionContext.Provider,
|
|
213
|
-
{
|
|
214
|
-
value: {
|
|
215
|
-
state: "connecting",
|
|
216
|
-
sessionId: credentials.sessionId,
|
|
217
|
-
error: null,
|
|
218
|
-
end: async () => {
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
children
|
|
222
|
-
}
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
209
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
226
210
|
componentsReact.LiveKitRoom,
|
|
227
211
|
{
|
|
@@ -288,34 +272,17 @@ function useAvatarSessionContext() {
|
|
|
288
272
|
}
|
|
289
273
|
return context;
|
|
290
274
|
}
|
|
291
|
-
function LoadingSessionProvider({
|
|
292
|
-
state,
|
|
293
|
-
error,
|
|
294
|
-
children
|
|
295
|
-
}) {
|
|
296
|
-
const contextValue = {
|
|
297
|
-
state,
|
|
298
|
-
sessionId: "",
|
|
299
|
-
error,
|
|
300
|
-
end: async () => {
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AvatarSessionContext.Provider, { value: contextValue, children });
|
|
304
|
-
}
|
|
305
275
|
function useAvatar() {
|
|
306
|
-
const
|
|
307
|
-
const hasRoomContext = room !== void 0;
|
|
308
|
-
const remoteParticipants = componentsReact.useRemoteParticipants({ room });
|
|
276
|
+
const remoteParticipants = componentsReact.useRemoteParticipants();
|
|
309
277
|
const avatarParticipant = remoteParticipants[0] ?? null;
|
|
310
278
|
const videoTracks = componentsReact.useTracks(
|
|
311
279
|
[{ source: livekitClient.Track.Source.Camera, withPlaceholder: true }],
|
|
312
280
|
{
|
|
313
281
|
onlySubscribed: true,
|
|
314
|
-
updateOnlyOn: []
|
|
315
|
-
room: hasRoomContext ? room : void 0
|
|
282
|
+
updateOnlyOn: []
|
|
316
283
|
}
|
|
317
284
|
).filter((ref) => !ref.participant.isLocal);
|
|
318
|
-
const videoTrackRef =
|
|
285
|
+
const videoTrackRef = videoTracks[0] ?? null;
|
|
319
286
|
const hasVideo = videoTrackRef !== null && componentsReact.isTrackReference(videoTrackRef);
|
|
320
287
|
return {
|
|
321
288
|
participant: avatarParticipant,
|
|
@@ -368,9 +335,7 @@ function AvatarVideo({ children, ...props }) {
|
|
|
368
335
|
);
|
|
369
336
|
}
|
|
370
337
|
function useLocalMedia() {
|
|
371
|
-
const
|
|
372
|
-
const hasRoomContext = room !== void 0;
|
|
373
|
-
const { localParticipant } = componentsReact.useLocalParticipant({ room });
|
|
338
|
+
const { localParticipant } = componentsReact.useLocalParticipant();
|
|
374
339
|
const audioDevices = componentsReact.useMediaDevices({ kind: "audioinput" });
|
|
375
340
|
const videoDevices = componentsReact.useMediaDevices({ kind: "videoinput" });
|
|
376
341
|
const hasMic = audioDevices?.length > 0;
|
|
@@ -400,14 +365,13 @@ function useLocalMedia() {
|
|
|
400
365
|
[{ source: livekitClient.Track.Source.Camera, withPlaceholder: true }],
|
|
401
366
|
{
|
|
402
367
|
onlySubscribed: false,
|
|
403
|
-
updateOnlyOn: []
|
|
404
|
-
room: hasRoomContext ? room : void 0
|
|
368
|
+
updateOnlyOn: []
|
|
405
369
|
}
|
|
406
370
|
);
|
|
407
371
|
const localIdentity = localParticipant?.identity;
|
|
408
|
-
const localVideoTrackRef =
|
|
372
|
+
const localVideoTrackRef = tracks.find(
|
|
409
373
|
(trackRef) => trackRef.participant.identity === localIdentity && trackRef.source === livekitClient.Track.Source.Camera
|
|
410
|
-
) ?? null
|
|
374
|
+
) ?? null;
|
|
411
375
|
return {
|
|
412
376
|
hasMic,
|
|
413
377
|
hasCamera,
|
|
@@ -631,6 +595,7 @@ function AvatarCall({
|
|
|
631
595
|
/* @__PURE__ */ jsxRuntime.jsx(ControlBar, {})
|
|
632
596
|
] });
|
|
633
597
|
if (credentialsState.status !== "ready") {
|
|
598
|
+
const status = credentialsState.status === "error" ? "error" : "connecting";
|
|
634
599
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
635
600
|
"div",
|
|
636
601
|
{
|
|
@@ -638,14 +603,7 @@ function AvatarCall({
|
|
|
638
603
|
"data-avatar-call": "",
|
|
639
604
|
"data-avatar-id": avatarId,
|
|
640
605
|
style: { ...props.style, ...backgroundStyle },
|
|
641
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
642
|
-
LoadingSessionProvider,
|
|
643
|
-
{
|
|
644
|
-
state: credentialsState.status === "error" ? "error" : "connecting",
|
|
645
|
-
error: credentialsState.error,
|
|
646
|
-
children: children ?? defaultChildren
|
|
647
|
-
}
|
|
648
|
-
)
|
|
606
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-avatar-video": "", "data-avatar-status": status })
|
|
649
607
|
}
|
|
650
608
|
);
|
|
651
609
|
}
|
|
@@ -673,17 +631,15 @@ function ScreenShareVideo({
|
|
|
673
631
|
children,
|
|
674
632
|
...props
|
|
675
633
|
}) {
|
|
676
|
-
const
|
|
677
|
-
const hasRoomContext = room !== void 0;
|
|
678
|
-
const { localParticipant } = componentsReact.useLocalParticipant({ room });
|
|
634
|
+
const { localParticipant } = componentsReact.useLocalParticipant();
|
|
679
635
|
const tracks = componentsReact.useTracks(
|
|
680
636
|
[{ source: livekitClient.Track.Source.ScreenShare, withPlaceholder: false }],
|
|
681
|
-
{ onlySubscribed: false
|
|
637
|
+
{ onlySubscribed: false }
|
|
682
638
|
);
|
|
683
639
|
const localIdentity = localParticipant?.identity;
|
|
684
|
-
const screenShareTrackRef =
|
|
640
|
+
const screenShareTrackRef = tracks.find(
|
|
685
641
|
(trackRef) => trackRef.participant.identity === localIdentity && trackRef.source === livekitClient.Track.Source.ScreenShare
|
|
686
|
-
) ?? null
|
|
642
|
+
) ?? null;
|
|
687
643
|
const isSharing = screenShareTrackRef !== null && componentsReact.isTrackReference(screenShareTrackRef);
|
|
688
644
|
const state = {
|
|
689
645
|
isSharing,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts","../src/hooks/useLatest.ts","../src/hooks/useCredentials.ts","../src/components/AvatarSession.tsx","../src/hooks/useAvatar.ts","../src/hooks/useAvatarSession.ts","../src/hooks/useAvatarStatus.ts","../src/components/AvatarVideo.tsx","../src/hooks/useLocalMedia.ts","../src/components/ControlBar.tsx","../src/components/UserVideo.tsx","../src/components/AvatarCall.tsx","../src/components/ScreenShareVideo.tsx"],"names":["useRef","useEffect","useState","ConnectionState","createContext","jsx","jsxs","LiveKitRoom","RoomAudioRenderer","useRoomContext","useConnectionState","useCallback","useContext","useMaybeRoomContext","useRemoteParticipants","useTracks","Track","isTrackReference","Fragment","VideoTrack","useLocalParticipant","useMediaDevices","TrackToggle"],"mappings":"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","file":"index.cjs","sourcesContent":["export const DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { DEFAULT_BASE_URL } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nexport function useLatest<T>(value: T): React.RefObject<T> {\n const ref = useRef(value);\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { consumeSession } from '../api/consume';\nimport type { SessionCredentials } from '../types';\nimport { useLatest } from './useLatest';\n\nexport interface UseCredentialsOptions {\n avatarId: string;\n sessionId?: string;\n sessionKey?: string;\n credentials?: SessionCredentials;\n connectUrl?: string;\n connect?: (avatarId: string) => Promise<SessionCredentials>;\n baseUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport type CredentialsState =\n | { status: 'loading'; credentials: null; error: null }\n | { status: 'ready'; credentials: SessionCredentials; error: null }\n | { status: 'error'; credentials: null; error: Error };\n\nasync function fetchCredentials(\n options: UseCredentialsOptions,\n): Promise<SessionCredentials> {\n const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } =\n options;\n\n if (sessionId && sessionKey) {\n const { url, token, roomName } = await consumeSession({\n sessionId,\n sessionKey,\n baseUrl,\n });\n return { sessionId, serverUrl: url, token, roomName };\n }\n\n if (connect) {\n return connect(avatarId);\n }\n\n if (connectUrl) {\n const response = await fetch(connectUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ avatarId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to connect: ${response.status} ${errorText}`);\n }\n\n return response.json();\n }\n\n throw new Error(\n 'AvatarCall requires one of: credentials, sessionId+sessionKey, connectUrl, or connect',\n );\n}\n\nexport function useCredentials(\n options: UseCredentialsOptions,\n): CredentialsState {\n const {\n credentials: directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n onError,\n } = options;\n\n const onErrorRef = useLatest(onError);\n\n const [state, setState] = useState<CredentialsState>(() => {\n if (directCredentials) {\n return { status: 'ready', credentials: directCredentials, error: null };\n }\n return { status: 'loading', credentials: null, error: null };\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: onErrorRef is a stable ref from useLatest - we intentionally read .current at call time\n useEffect(() => {\n if (directCredentials) {\n setState({\n status: 'ready',\n credentials: directCredentials,\n error: null,\n });\n return;\n }\n\n let cancelled = false;\n setState({ status: 'loading', credentials: null, error: null });\n\n async function load() {\n try {\n const fetchOptions: UseCredentialsOptions = {\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n };\n const credentials = await fetchCredentials(fetchOptions);\n if (!cancelled) {\n setState({ status: 'ready', credentials, error: null });\n }\n } catch (err) {\n if (!cancelled) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState({ status: 'error', credentials: null, error });\n onErrorRef.current?.(error);\n }\n }\n }\n\n load();\n\n return () => {\n cancelled = true;\n };\n }, [\n directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n ]);\n\n return state;\n}\n","'use client';\n\n/**\n * AvatarSession Component\n *\n * Provides the session context for avatar interactions.\n * Manages the WebRTC connection and exposes a clean API for child components.\n *\n * @example\n * ```tsx\n * <AvatarSession credentials={credentials} onEnd={handleEnd}>\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarSession>\n * ```\n */\n\nimport {\n LiveKitRoom,\n RoomAudioRenderer,\n useConnectionState,\n useRoomContext,\n} from '@livekit/components-react';\nimport type { RoomOptions } from 'livekit-client';\nimport { ConnectionState } from 'livekit-client';\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n AvatarSessionContextValue,\n AvatarSessionProps,\n SessionState,\n} from '../types';\n\n/**\n * Check if a media device of the given kind is available\n */\nasync function hasMediaDevice(\n kind: 'audioinput' | 'videoinput',\n): Promise<boolean> {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.some((device) => device.kind === kind);\n } catch {\n return false;\n }\n}\n\n/**\n * Hook to check device availability before connecting\n */\nfunction useDeviceAvailability(\n requestAudio: boolean,\n requestVideo: boolean,\n): { audio: boolean; video: boolean; isChecking: boolean } {\n const [state, setState] = useState({\n audio: false,\n video: false,\n isChecking: true,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function checkDevices() {\n const [hasAudio, hasVideo] = await Promise.all([\n requestAudio ? hasMediaDevice('audioinput') : Promise.resolve(false),\n requestVideo ? hasMediaDevice('videoinput') : Promise.resolve(false),\n ]);\n\n if (!cancelled) {\n setState({\n audio: requestAudio && hasAudio,\n video: requestVideo && hasVideo,\n isChecking: false,\n });\n }\n }\n\n checkDevices();\n\n return () => {\n cancelled = true;\n };\n }, [requestAudio, requestVideo]);\n\n return state;\n}\n\nconst DEFAULT_ROOM_OPTIONS: RoomOptions = {\n adaptiveStream: false,\n dynacast: false,\n};\n\n/**\n * Maps WebRTC connection state to session state\n */\nfunction mapConnectionState(connectionState: ConnectionState): SessionState {\n switch (connectionState) {\n case ConnectionState.Connecting:\n return 'connecting';\n case ConnectionState.Connected:\n return 'active';\n case ConnectionState.Reconnecting:\n return 'connecting';\n case ConnectionState.Disconnected:\n return 'ended';\n default:\n return 'ended';\n }\n}\n\nconst AvatarSessionContext = createContext<AvatarSessionContextValue | null>(\n null,\n);\n\n/**\n * AvatarSession component - the main entry point for avatar sessions\n *\n * Establishes a WebRTC connection and provides session state to children.\n * This is a headless component that renders minimal DOM.\n */\nexport function AvatarSession({\n credentials,\n children,\n audio: requestAudio = true,\n video: requestVideo = true,\n onEnd,\n onError,\n __unstable_roomOptions,\n}: AvatarSessionProps) {\n const errorRef = useRef<Error | null>(null);\n\n const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);\n\n const handleError = (error: Error) => {\n errorRef.current = error;\n onError?.(error);\n };\n\n const roomOptions = {\n ...DEFAULT_ROOM_OPTIONS,\n ...__unstable_roomOptions,\n };\n\n if (deviceAvailability.isChecking) {\n return (\n <AvatarSessionContext.Provider\n value={{\n state: 'connecting',\n sessionId: credentials.sessionId,\n error: null,\n end: async () => {},\n }}\n >\n {children}\n </AvatarSessionContext.Provider>\n );\n }\n\n return (\n <LiveKitRoom\n serverUrl={credentials.serverUrl}\n token={credentials.token}\n connect={true}\n audio={deviceAvailability.audio}\n video={deviceAvailability.video}\n onDisconnected={() => onEnd?.()}\n onError={handleError}\n options={roomOptions}\n connectOptions={{\n autoSubscribe: true,\n }}\n >\n <AvatarSessionContextInner\n sessionId={credentials.sessionId}\n onEnd={onEnd}\n errorRef={errorRef}\n >\n {children}\n </AvatarSessionContextInner>\n <RoomAudioRenderer />\n </LiveKitRoom>\n );\n}\n\n/**\n * Inner context provider that has access to the room context\n */\nfunction AvatarSessionContextInner({\n sessionId,\n onEnd,\n errorRef,\n children,\n}: {\n sessionId: string;\n onEnd?: () => void;\n errorRef: React.RefObject<Error | null>;\n children: ReactNode;\n}) {\n const room = useRoomContext();\n const connectionState = useConnectionState();\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n const end = useCallback(async () => {\n try {\n // Send END_CALL message to the avatar\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({ type: 'END_CALL' }));\n await room.localParticipant.publishData(data, { reliable: true });\n } catch {\n // Ignore errors when sending end message\n }\n\n await room.disconnect();\n onEndRef.current?.();\n }, [room]);\n\n const contextValue: AvatarSessionContextValue = {\n state: mapConnectionState(connectionState),\n sessionId,\n error: errorRef.current,\n end,\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n\n/**\n * Hook to access the avatar session context\n * Must be used within an AvatarSession component\n */\nexport function useAvatarSessionContext(): AvatarSessionContextValue {\n const context = useContext(AvatarSessionContext);\n if (!context) {\n throw new Error(\n 'useAvatarSessionContext must be used within an AvatarSession',\n );\n }\n return context;\n}\n\n/**\n * Hook to optionally access the avatar session context\n * Returns null if not within an AvatarSession\n */\nexport function useMaybeAvatarSessionContext(): AvatarSessionContextValue | null {\n return useContext(AvatarSessionContext);\n}\n\n/**\n * Provider for loading/error states before the actual session is established.\n * Used by AvatarCall to provide context during credential fetching.\n */\nexport function LoadingSessionProvider({\n state,\n error,\n children,\n}: {\n state: 'connecting' | 'error';\n error: Error | null;\n children: ReactNode;\n}) {\n const contextValue: AvatarSessionContextValue = {\n state,\n sessionId: '',\n error,\n end: async () => {},\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n","'use client';\n\n/**\n * useAvatar Hook\n *\n * Provides access to the remote avatar participant's video track.\n * Audio is handled automatically by the session.\n * Returns safe defaults when called outside of LiveKitRoom context.\n *\n * @example\n * ```tsx\n * function AvatarDisplay() {\n * const { videoTrackRef, hasVideo } = useAvatar();\n *\n * if (!hasVideo) {\n * return <Placeholder />;\n * }\n *\n * return <VideoTrack trackRef={videoTrackRef} />;\n * }\n * ```\n */\n\nimport {\n isTrackReference,\n useMaybeRoomContext,\n useRemoteParticipants,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { UseAvatarReturn } from '../types';\n\n/**\n * Hook to access the remote avatar participant's video track\n *\n * @returns Avatar participant info and video track reference\n */\nexport function useAvatar(): UseAvatarReturn {\n const room = useMaybeRoomContext();\n const hasRoomContext = room !== undefined;\n\n const remoteParticipants = useRemoteParticipants({ room });\n const avatarParticipant = remoteParticipants[0] ?? null;\n\n // Only subscribe to video - audio is handled automatically by the session\n const videoTracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: true,\n updateOnlyOn: [],\n room: hasRoomContext ? room : undefined,\n },\n ).filter((ref) => !ref.participant.isLocal);\n\n const videoTrackRef = hasRoomContext ? (videoTracks[0] ?? null) : null;\n const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);\n\n return {\n participant: avatarParticipant,\n videoTrackRef,\n hasVideo,\n };\n}\n","'use client';\n\n/**\n * useAvatarSession Hook\n *\n * Provides access to the current avatar session state.\n * Returns a discriminated union based on session state for type-safe UI rendering.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const session = useAvatarSession();\n *\n * if (session.state === 'connecting') {\n * return <Loading />;\n * }\n *\n * if (session.state === 'error') {\n * return <Error message={session.error.message} />;\n * }\n *\n * return <ActiveSession onEnd={session.end} />;\n * }\n * ```\n */\n\nimport { useAvatarSessionContext } from '../components/AvatarSession';\nimport type { AvatarSessionContextValue } from '../types';\n\n/**\n * Discriminated union types for type-safe session state handling\n */\nexport type UseAvatarSessionReturn =\n | { state: 'idle'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'connecting'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'active'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ending'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ended'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'error'; sessionId: string; error: Error; end: () => Promise<void> };\n\n/**\n * Hook to access the current avatar session state\n *\n * @returns Session state as a discriminated union\n */\nexport function useAvatarSession(): UseAvatarSessionReturn {\n const context = useAvatarSessionContext();\n return context as UseAvatarSessionReturn;\n}\n\nexport type { AvatarSessionContextValue };\n","'use client';\n\n/**\n * useAvatarStatus Hook\n *\n * Returns a single discriminated union representing the full avatar lifecycle\n * inside an AvatarSession. Combines session connection state and video\n * track availability into one status value.\n *\n * Must be used within <AvatarCall> or <AvatarSession>.\n *\n * @example\n * ```tsx\n * function MyAvatar() {\n * const avatar = useAvatarStatus();\n *\n * switch (avatar.status) {\n * case 'connecting':\n * return <Spinner />;\n * case 'waiting':\n * return <p>Waiting for video...</p>;\n * case 'ready':\n * return <VideoTrack trackRef={avatar.videoTrackRef} />;\n * case 'error':\n * return <p>{avatar.error.message}</p>;\n * case 'ended':\n * return <p>Call ended</p>;\n * }\n * }\n * ```\n */\n\nimport type { TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport { useAvatar } from './useAvatar';\nimport { useAvatarSession } from './useAvatarSession';\n\nexport type AvatarStatus =\n | { status: 'connecting' }\n | { status: 'waiting' }\n | { status: 'ready'; videoTrackRef: TrackReferenceOrPlaceholder }\n | { status: 'ending' }\n | { status: 'ended' }\n | { status: 'error'; error: Error };\n\nexport function useAvatarStatus(): AvatarStatus {\n const session = useAvatarSession();\n const { videoTrackRef, hasVideo } = useAvatar();\n\n switch (session.state) {\n case 'connecting':\n case 'idle':\n return { status: 'connecting' };\n\n case 'active':\n if (hasVideo && videoTrackRef) {\n return { status: 'ready', videoTrackRef };\n }\n return { status: 'waiting' };\n\n case 'ending':\n return { status: 'ending' };\n\n case 'ended':\n return { status: 'ended' };\n\n case 'error':\n return { status: 'error', error: session.error };\n }\n}\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { type AvatarStatus, useAvatarStatus } from '../hooks/useAvatarStatus';\n\n/** Subset of AvatarStatus relevant to the video display */\nexport type AvatarVideoStatus = Extract<\n AvatarStatus,\n { status: 'connecting' } | { status: 'waiting' } | { status: 'ready' }\n>;\n\nexport interface AvatarVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (status: AvatarVideoStatus) => ReactNode;\n}\n\nexport function AvatarVideo({ children, ...props }: AvatarVideoProps) {\n const avatar = useAvatarStatus();\n\n const videoStatus: AvatarVideoStatus =\n avatar.status === 'ready'\n ? avatar\n : avatar.status === 'connecting'\n ? { status: 'connecting' }\n : { status: 'waiting' };\n\n if (children) {\n return <>{children(videoStatus)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-video=\"\"\n data-avatar-status={videoStatus.status}\n >\n {videoStatus.status === 'ready' &&\n isTrackReference(videoStatus.videoTrackRef) && (\n <VideoTrack trackRef={videoStatus.videoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n useLocalParticipant,\n useMaybeRoomContext,\n useMediaDevices,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport type { UseLocalMediaReturn } from '../types';\nimport { useLatest } from './useLatest';\n\n/**\n * Hook for local media controls (mic, camera, screen share).\n * Returns safe defaults when called outside of LiveKitRoom context.\n */\nexport function useLocalMedia(): UseLocalMediaReturn {\n const room = useMaybeRoomContext();\n const hasRoomContext = room !== undefined;\n\n const { localParticipant } = useLocalParticipant({ room });\n\n const audioDevices = useMediaDevices({ kind: 'audioinput' });\n const videoDevices = useMediaDevices({ kind: 'videoinput' });\n\n const hasMic = audioDevices?.length > 0;\n const hasCamera = videoDevices?.length > 0;\n\n const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;\n const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;\n const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;\n\n const isMicEnabledRef = useLatest(isMicEnabled);\n const isCameraEnabledRef = useLatest(isCameraEnabled);\n const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);\n\n const hasMicRef = useLatest(hasMic);\n const hasCameraRef = useLatest(hasCamera);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleMic = useCallback(() => {\n if (hasMicRef.current || isMicEnabledRef.current) {\n localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleCamera = useCallback(() => {\n if (hasCameraRef.current || isCameraEnabledRef.current) {\n localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleScreenShare = useCallback(() => {\n localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);\n }, [localParticipant]);\n\n const tracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: false,\n updateOnlyOn: [],\n room: hasRoomContext ? room : undefined,\n },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const localVideoTrackRef = hasRoomContext\n ? (tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.Camera,\n ) ?? null)\n : null;\n\n return {\n hasMic,\n hasCamera,\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n localVideoTrackRef,\n };\n}\n","'use client';\n\nimport { TrackToggle } from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useAvatarSession } from '../hooks/useAvatarSession';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\n\nexport interface ControlBarState {\n isMicEnabled: boolean;\n isCameraEnabled: boolean;\n isScreenShareEnabled: boolean;\n toggleMic: () => void;\n toggleCamera: () => void;\n toggleScreenShare: () => void;\n endCall: () => Promise<void>;\n isActive: boolean;\n}\n\nexport interface ControlBarProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n showMicrophone?: boolean;\n showCamera?: boolean;\n showScreenShare?: boolean;\n showEndCall?: boolean;\n children?: (state: ControlBarState) => ReactNode;\n}\n\nexport function ControlBar({\n children,\n showMicrophone = true,\n showCamera = true,\n showScreenShare = false,\n showEndCall = true,\n ...props\n}: ControlBarProps) {\n const session = useAvatarSession();\n const {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n } = useLocalMedia();\n\n const isActive = session.state === 'active';\n\n const state: ControlBarState = {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n endCall: session.end,\n isActive,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isActive) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-control-bar=\"\" data-avatar-active={isActive}>\n {showMicrophone && (\n <button\n type=\"button\"\n onClick={toggleMic}\n data-avatar-control=\"microphone\"\n data-avatar-enabled={isMicEnabled}\n aria-label={isMicEnabled ? 'Mute microphone' : 'Unmute microphone'}\n >\n {microphoneIcon}\n </button>\n )}\n {showCamera && (\n <button\n type=\"button\"\n onClick={toggleCamera}\n data-avatar-control=\"camera\"\n data-avatar-enabled={isCameraEnabled}\n aria-label={isCameraEnabled ? 'Turn off camera' : 'Turn on camera'}\n >\n {cameraIcon}\n </button>\n )}\n {showScreenShare && (\n <TrackToggle\n source={Track.Source.ScreenShare}\n showIcon={false}\n data-avatar-control=\"screen-share\"\n data-avatar-enabled={isScreenShareEnabled}\n aria-label=\"Toggle screen share\"\n >\n {screenShareIcon}\n </TrackToggle>\n )}\n {showEndCall && (\n <button\n type=\"button\"\n onClick={session.end}\n data-avatar-control=\"end-call\"\n data-avatar-enabled={true}\n aria-label=\"End call\"\n >\n {phoneIcon}\n </button>\n )}\n </div>\n );\n}\n\n// Lucide icons (https://lucide.dev) - MIT License\nconst microphoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n);\n\nconst cameraIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n);\n\nconst screenShareIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n);\n\nconst phoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"8 14 24 12\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12.8429 22.5693L11.4018 21.0986C11.2675 20.9626 11.1625 20.7995 11.0935 20.6197C11.0245 20.4399 10.9931 20.2474 11.0013 20.0545C11.0094 19.8616 11.0569 19.6726 11.1408 19.4995C11.2247 19.3265 11.343 19.1732 11.4883 19.0495C13.127 17.7049 15.0519 16.7714 17.1083 16.3239C19.0064 15.892 20.9744 15.892 22.8725 16.3239C24.9374 16.7743 26.8693 17.7147 28.5117 19.0691C28.6565 19.1924 28.7746 19.3451 28.8585 19.5176C28.9423 19.69 28.99 19.8784 28.9986 20.0707C29.0072 20.263 28.9764 20.455 28.9083 20.6345C28.8402 20.814 28.7362 20.9771 28.603 21.1133L27.1619 22.584C26.9311 22.8242 26.6226 22.9706 26.2938 22.9959C25.9651 23.0211 25.6385 22.9235 25.3751 22.7212C24.8531 22.3127 24.2875 21.9657 23.689 21.6869C23.4525 21.5774 23.2517 21.4009 23.1103 21.1785C22.969 20.9561 22.8931 20.697 22.8917 20.4319V19.1867C21.0053 18.6573 19.0139 18.6573 17.1275 19.1867V20.4319C17.1261 20.697 17.0502 20.9561 16.9089 21.1785C16.7676 21.4009 16.5667 21.5774 16.3302 21.6869C15.7317 21.9657 15.1661 22.3127 14.6442 22.7212C14.3779 22.9258 14.0473 23.0233 13.7152 22.9953C13.383 22.9673 13.0726 22.8156 12.8429 22.5693Z\" />\n </svg>\n);\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\nimport type { UseLocalMediaReturn } from '../types';\n\nexport interface UserVideoState {\n hasVideo: boolean;\n isCameraEnabled: boolean;\n trackRef: UseLocalMediaReturn['localVideoTrackRef'];\n}\n\nexport interface UserVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n mirror?: boolean;\n children?: (state: UserVideoState) => ReactNode;\n}\n\nexport function UserVideo({\n children,\n mirror = true,\n ...props\n}: UserVideoProps) {\n const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();\n\n const hasVideo =\n localVideoTrackRef !== null && isTrackReference(localVideoTrackRef);\n\n const state: UserVideoState = {\n hasVideo,\n isCameraEnabled,\n trackRef: localVideoTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-user-video=\"\"\n data-avatar-has-video={hasVideo}\n data-avatar-camera-enabled={isCameraEnabled}\n data-avatar-mirror={mirror}\n >\n {hasVideo &&\n localVideoTrackRef &&\n isTrackReference(localVideoTrackRef) && (\n <VideoTrack trackRef={localVideoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\n/**\n * AvatarCall Component\n *\n * High-level component that handles the complete session lifecycle.\n * Manages credential fetching, connection, and video display internally\n * with a seamless loading experience.\n *\n * @example\n * ```tsx\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\">\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarCall>\n * ```\n */\n\nimport { useCredentials } from '../hooks/useCredentials';\nimport { useLatest } from '../hooks/useLatest';\nimport type { AvatarCallProps } from '../types';\nimport { AvatarSession, LoadingSessionProvider } from './AvatarSession';\nimport { AvatarVideo } from './AvatarVideo';\nimport { ControlBar } from './ControlBar';\nimport { UserVideo } from './UserVideo';\n\nexport function AvatarCall({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n avatarImageUrl,\n onEnd,\n onError,\n children,\n __unstable_roomOptions,\n ...props\n}: AvatarCallProps) {\n const onErrorRef = useLatest(onError);\n\n const credentialsState = useCredentials({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n onError: (err) => onErrorRef.current?.(err),\n });\n\n const handleSessionError = (err: Error) => {\n onErrorRef.current?.(err);\n };\n\n const backgroundStyle = avatarImageUrl\n ? ({ '--avatar-image': `url(${avatarImageUrl})` } as React.CSSProperties)\n : undefined;\n\n const defaultChildren = (\n <>\n <AvatarVideo />\n <UserVideo />\n <ControlBar />\n </>\n );\n\n if (credentialsState.status !== 'ready') {\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <LoadingSessionProvider\n state={credentialsState.status === 'error' ? 'error' : 'connecting'}\n error={credentialsState.error}\n >\n {children ?? defaultChildren}\n </LoadingSessionProvider>\n </div>\n );\n }\n\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <AvatarSession\n credentials={credentialsState.credentials}\n onEnd={onEnd}\n onError={handleSessionError}\n __unstable_roomOptions={__unstable_roomOptions}\n >\n {children ?? defaultChildren}\n </AvatarSession>\n </div>\n );\n}\n","'use client';\n\nimport {\n isTrackReference,\n type TrackReferenceOrPlaceholder,\n useLocalParticipant,\n useMaybeRoomContext,\n useTracks,\n VideoTrack,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nexport interface ScreenShareVideoState {\n isSharing: boolean;\n trackRef: TrackReferenceOrPlaceholder | null;\n}\n\nexport interface ScreenShareVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (state: ScreenShareVideoState) => ReactNode;\n}\n\nexport function ScreenShareVideo({\n children,\n ...props\n}: ScreenShareVideoProps) {\n const room = useMaybeRoomContext();\n const hasRoomContext = room !== undefined;\n\n const { localParticipant } = useLocalParticipant({ room });\n\n const tracks = useTracks(\n [{ source: Track.Source.ScreenShare, withPlaceholder: false }],\n { onlySubscribed: false, room: hasRoomContext ? room : undefined },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const screenShareTrackRef = hasRoomContext\n ? (tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.ScreenShare,\n ) ?? null)\n : null;\n\n const isSharing =\n screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);\n\n const state: ScreenShareVideoState = {\n isSharing,\n trackRef: screenShareTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isSharing) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-screen-share=\"\" data-avatar-sharing={isSharing}>\n {screenShareTrackRef && isTrackReference(screenShareTrackRef) && (\n <VideoTrack trackRef={screenShareTrackRef} />\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts","../src/hooks/useLatest.ts","../src/hooks/useCredentials.ts","../src/components/AvatarSession.tsx","../src/hooks/useAvatar.ts","../src/hooks/useAvatarSession.ts","../src/hooks/useAvatarStatus.ts","../src/components/AvatarVideo.tsx","../src/hooks/useLocalMedia.ts","../src/components/ControlBar.tsx","../src/components/UserVideo.tsx","../src/components/AvatarCall.tsx","../src/components/ScreenShareVideo.tsx"],"names":["useRef","useEffect","useState","ConnectionState","createContext","jsxs","LiveKitRoom","jsx","RoomAudioRenderer","useRoomContext","useConnectionState","useCallback","useContext","useRemoteParticipants","useTracks","Track","isTrackReference","Fragment","VideoTrack","useLocalParticipant","useMediaDevices","TrackToggle"],"mappings":"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","file":"index.cjs","sourcesContent":["export const DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { DEFAULT_BASE_URL } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nexport function useLatest<T>(value: T): React.RefObject<T> {\n const ref = useRef(value);\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { consumeSession } from '../api/consume';\nimport type { SessionCredentials } from '../types';\nimport { useLatest } from './useLatest';\n\nexport interface UseCredentialsOptions {\n avatarId: string;\n sessionId?: string;\n sessionKey?: string;\n credentials?: SessionCredentials;\n connectUrl?: string;\n connect?: (avatarId: string) => Promise<SessionCredentials>;\n baseUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport type CredentialsState =\n | { status: 'loading'; credentials: null; error: null }\n | { status: 'ready'; credentials: SessionCredentials; error: null }\n | { status: 'error'; credentials: null; error: Error };\n\nasync function fetchCredentials(\n options: UseCredentialsOptions,\n): Promise<SessionCredentials> {\n const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } =\n options;\n\n if (sessionId && sessionKey) {\n const { url, token, roomName } = await consumeSession({\n sessionId,\n sessionKey,\n baseUrl,\n });\n return { sessionId, serverUrl: url, token, roomName };\n }\n\n if (connect) {\n return connect(avatarId);\n }\n\n if (connectUrl) {\n const response = await fetch(connectUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ avatarId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to connect: ${response.status} ${errorText}`);\n }\n\n return response.json();\n }\n\n throw new Error(\n 'AvatarCall requires one of: credentials, sessionId+sessionKey, connectUrl, or connect',\n );\n}\n\nexport function useCredentials(\n options: UseCredentialsOptions,\n): CredentialsState {\n const {\n credentials: directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n onError,\n } = options;\n\n const onErrorRef = useLatest(onError);\n const connectRef = useLatest(connect);\n\n const fetchedKeyRef = useRef<string | null>(null);\n\n const [state, setState] = useState<CredentialsState>(() => {\n if (directCredentials) {\n return { status: 'ready', credentials: directCredentials, error: null };\n }\n return { status: 'loading', credentials: null, error: null };\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs are stable - we read .current at call time\n useEffect(() => {\n if (directCredentials) {\n setState({\n status: 'ready',\n credentials: directCredentials,\n error: null,\n });\n return;\n }\n\n const credentialKey = `${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;\n\n if (fetchedKeyRef.current === credentialKey) return;\n fetchedKeyRef.current = credentialKey;\n\n let cancelled = false;\n setState({ status: 'loading', credentials: null, error: null });\n\n async function load() {\n try {\n const fetchOptions: UseCredentialsOptions = {\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect: connectRef.current ?? undefined,\n baseUrl,\n };\n const credentials = await fetchCredentials(fetchOptions);\n if (!cancelled) {\n setState({ status: 'ready', credentials, error: null });\n }\n } catch (err) {\n if (!cancelled) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState({ status: 'error', credentials: null, error });\n onErrorRef.current?.(error);\n }\n }\n }\n\n load();\n\n return () => {\n cancelled = true;\n };\n }, [directCredentials, avatarId, sessionId, sessionKey, connectUrl, baseUrl]);\n\n return state;\n}\n","'use client';\n\n/**\n * AvatarSession Component\n *\n * Provides the session context for avatar interactions.\n * Manages the WebRTC connection and exposes a clean API for child components.\n *\n * @example\n * ```tsx\n * <AvatarSession credentials={credentials} onEnd={handleEnd}>\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarSession>\n * ```\n */\n\nimport {\n LiveKitRoom,\n RoomAudioRenderer,\n useConnectionState,\n useRoomContext,\n} from '@livekit/components-react';\nimport type { RoomOptions } from 'livekit-client';\nimport { ConnectionState } from 'livekit-client';\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n AvatarSessionContextValue,\n AvatarSessionProps,\n SessionState,\n} from '../types';\n\n/**\n * Check if a media device of the given kind is available\n * Returns within timeout to avoid blocking the connection\n */\nasync function hasMediaDevice(\n kind: 'audioinput' | 'videoinput',\n timeoutMs = 1000,\n): Promise<boolean> {\n try {\n const timeoutPromise = new Promise<boolean>((resolve) =>\n setTimeout(() => resolve(false), timeoutMs),\n );\n const checkPromise = navigator.mediaDevices\n .enumerateDevices()\n .then((devices) => devices.some((device) => device.kind === kind));\n\n return await Promise.race([checkPromise, timeoutPromise]);\n } catch {\n return false;\n }\n}\n\n/**\n * Hook to check device availability before connecting.\n * Completes quickly to avoid blocking the connection.\n */\nfunction useDeviceAvailability(\n requestAudio: boolean,\n requestVideo: boolean,\n): { audio: boolean; video: boolean } {\n const [state, setState] = useState({\n audio: requestAudio, // Optimistically assume devices exist\n video: requestVideo,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function checkDevices() {\n const [hasAudio, hasVideo] = await Promise.all([\n requestAudio ? hasMediaDevice('audioinput') : Promise.resolve(false),\n requestVideo ? hasMediaDevice('videoinput') : Promise.resolve(false),\n ]);\n\n if (!cancelled) {\n setState({\n audio: requestAudio && hasAudio,\n video: requestVideo && hasVideo,\n });\n }\n }\n\n checkDevices();\n\n return () => {\n cancelled = true;\n };\n }, [requestAudio, requestVideo]);\n\n return state;\n}\n\nconst DEFAULT_ROOM_OPTIONS: RoomOptions = {\n adaptiveStream: false,\n dynacast: false,\n};\n\n/**\n * Maps WebRTC connection state to session state\n */\nfunction mapConnectionState(connectionState: ConnectionState): SessionState {\n switch (connectionState) {\n case ConnectionState.Connecting:\n return 'connecting';\n case ConnectionState.Connected:\n return 'active';\n case ConnectionState.Reconnecting:\n return 'connecting';\n case ConnectionState.Disconnected:\n return 'ended';\n default:\n return 'ended';\n }\n}\n\nconst AvatarSessionContext = createContext<AvatarSessionContextValue | null>(\n null,\n);\n\n/**\n * AvatarSession component - the main entry point for avatar sessions\n *\n * Establishes a WebRTC connection and provides session state to children.\n * This is a headless component that renders minimal DOM.\n */\nexport function AvatarSession({\n credentials,\n children,\n audio: requestAudio = true,\n video: requestVideo = true,\n onEnd,\n onError,\n __unstable_roomOptions,\n}: AvatarSessionProps) {\n const errorRef = useRef<Error | null>(null);\n\n const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);\n\n const handleError = (error: Error) => {\n errorRef.current = error;\n onError?.(error);\n };\n\n const roomOptions = {\n ...DEFAULT_ROOM_OPTIONS,\n ...__unstable_roomOptions,\n };\n\n return (\n <LiveKitRoom\n serverUrl={credentials.serverUrl}\n token={credentials.token}\n connect={true}\n audio={deviceAvailability.audio}\n video={deviceAvailability.video}\n onDisconnected={() => onEnd?.()}\n onError={handleError}\n options={roomOptions}\n connectOptions={{\n autoSubscribe: true,\n }}\n >\n <AvatarSessionContextInner\n sessionId={credentials.sessionId}\n onEnd={onEnd}\n errorRef={errorRef}\n >\n {children}\n </AvatarSessionContextInner>\n <RoomAudioRenderer />\n </LiveKitRoom>\n );\n}\n\n/**\n * Inner context provider that has access to the room context\n */\nfunction AvatarSessionContextInner({\n sessionId,\n onEnd,\n errorRef,\n children,\n}: {\n sessionId: string;\n onEnd?: () => void;\n errorRef: React.RefObject<Error | null>;\n children: ReactNode;\n}) {\n const room = useRoomContext();\n const connectionState = useConnectionState();\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n const end = useCallback(async () => {\n try {\n // Send END_CALL message to the avatar\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({ type: 'END_CALL' }));\n await room.localParticipant.publishData(data, { reliable: true });\n } catch {\n // Ignore errors when sending end message\n }\n\n await room.disconnect();\n onEndRef.current?.();\n }, [room]);\n\n const contextValue: AvatarSessionContextValue = {\n state: mapConnectionState(connectionState),\n sessionId,\n error: errorRef.current,\n end,\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n\n/**\n * Hook to access the avatar session context\n * Must be used within an AvatarSession component\n */\nexport function useAvatarSessionContext(): AvatarSessionContextValue {\n const context = useContext(AvatarSessionContext);\n if (!context) {\n throw new Error(\n 'useAvatarSessionContext must be used within an AvatarSession',\n );\n }\n return context;\n}\n\n/**\n * Hook to optionally access the avatar session context\n * Returns null if not within an AvatarSession\n */\nexport function useMaybeAvatarSessionContext(): AvatarSessionContextValue | null {\n return useContext(AvatarSessionContext);\n}\n","'use client';\n\n/**\n * useAvatar Hook\n *\n * Provides access to the remote avatar participant's video track.\n * Audio is handled automatically by the session.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n *\n * @example\n * ```tsx\n * function AvatarDisplay() {\n * const { videoTrackRef, hasVideo } = useAvatar();\n *\n * if (!hasVideo) {\n * return <Placeholder />;\n * }\n *\n * return <VideoTrack trackRef={videoTrackRef} />;\n * }\n * ```\n */\n\nimport {\n isTrackReference,\n useRemoteParticipants,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { UseAvatarReturn } from '../types';\n\n/**\n * Hook to access the remote avatar participant's video track\n *\n * @returns Avatar participant info and video track reference\n */\nexport function useAvatar(): UseAvatarReturn {\n const remoteParticipants = useRemoteParticipants();\n const avatarParticipant = remoteParticipants[0] ?? null;\n\n // Only subscribe to video - audio is handled automatically by the session\n const videoTracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: true,\n updateOnlyOn: [],\n },\n ).filter((ref) => !ref.participant.isLocal);\n\n const videoTrackRef = videoTracks[0] ?? null;\n const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);\n\n return {\n participant: avatarParticipant,\n videoTrackRef,\n hasVideo,\n };\n}\n","'use client';\n\n/**\n * useAvatarSession Hook\n *\n * Provides access to the current avatar session state.\n * Returns a discriminated union based on session state for type-safe UI rendering.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const session = useAvatarSession();\n *\n * if (session.state === 'connecting') {\n * return <Loading />;\n * }\n *\n * if (session.state === 'error') {\n * return <Error message={session.error.message} />;\n * }\n *\n * return <ActiveSession onEnd={session.end} />;\n * }\n * ```\n */\n\nimport { useAvatarSessionContext } from '../components/AvatarSession';\nimport type { AvatarSessionContextValue } from '../types';\n\n/**\n * Discriminated union types for type-safe session state handling\n */\nexport type UseAvatarSessionReturn =\n | { state: 'idle'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'connecting'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'active'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ending'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ended'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'error'; sessionId: string; error: Error; end: () => Promise<void> };\n\n/**\n * Hook to access the current avatar session state\n *\n * @returns Session state as a discriminated union\n */\nexport function useAvatarSession(): UseAvatarSessionReturn {\n const context = useAvatarSessionContext();\n return context as UseAvatarSessionReturn;\n}\n\nexport type { AvatarSessionContextValue };\n","'use client';\n\n/**\n * useAvatarStatus Hook\n *\n * Returns a single discriminated union representing the full avatar lifecycle\n * inside an AvatarSession. Combines session connection state and video\n * track availability into one status value.\n *\n * Must be used within <AvatarCall> or <AvatarSession>.\n *\n * @example\n * ```tsx\n * function MyAvatar() {\n * const avatar = useAvatarStatus();\n *\n * switch (avatar.status) {\n * case 'connecting':\n * return <Spinner />;\n * case 'waiting':\n * return <p>Waiting for video...</p>;\n * case 'ready':\n * return <VideoTrack trackRef={avatar.videoTrackRef} />;\n * case 'error':\n * return <p>{avatar.error.message}</p>;\n * case 'ended':\n * return <p>Call ended</p>;\n * }\n * }\n * ```\n */\n\nimport type { TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport { useAvatar } from './useAvatar';\nimport { useAvatarSession } from './useAvatarSession';\n\nexport type AvatarStatus =\n | { status: 'connecting' }\n | { status: 'waiting' }\n | { status: 'ready'; videoTrackRef: TrackReferenceOrPlaceholder }\n | { status: 'ending' }\n | { status: 'ended' }\n | { status: 'error'; error: Error };\n\nexport function useAvatarStatus(): AvatarStatus {\n const session = useAvatarSession();\n const { videoTrackRef, hasVideo } = useAvatar();\n\n switch (session.state) {\n case 'connecting':\n case 'idle':\n return { status: 'connecting' };\n\n case 'active':\n if (hasVideo && videoTrackRef) {\n return { status: 'ready', videoTrackRef };\n }\n return { status: 'waiting' };\n\n case 'ending':\n return { status: 'ending' };\n\n case 'ended':\n return { status: 'ended' };\n\n case 'error':\n return { status: 'error', error: session.error };\n }\n}\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { type AvatarStatus, useAvatarStatus } from '../hooks/useAvatarStatus';\n\n/** Subset of AvatarStatus relevant to the video display */\nexport type AvatarVideoStatus = Extract<\n AvatarStatus,\n { status: 'connecting' } | { status: 'waiting' } | { status: 'ready' }\n>;\n\nexport interface AvatarVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (status: AvatarVideoStatus) => ReactNode;\n}\n\nexport function AvatarVideo({ children, ...props }: AvatarVideoProps) {\n const avatar = useAvatarStatus();\n\n const videoStatus: AvatarVideoStatus =\n avatar.status === 'ready'\n ? avatar\n : avatar.status === 'connecting'\n ? { status: 'connecting' }\n : { status: 'waiting' };\n\n if (children) {\n return <>{children(videoStatus)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-video=\"\"\n data-avatar-status={videoStatus.status}\n >\n {videoStatus.status === 'ready' &&\n isTrackReference(videoStatus.videoTrackRef) && (\n <VideoTrack trackRef={videoStatus.videoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n useLocalParticipant,\n useMediaDevices,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport type { UseLocalMediaReturn } from '../types';\nimport { useLatest } from './useLatest';\n\n/**\n * Hook for local media controls (mic, camera, screen share).\n *\n * Must be used within an AvatarSession or AvatarCall component.\n * For use outside the session context, use AvatarSession directly\n * and manage your own loading states.\n */\nexport function useLocalMedia(): UseLocalMediaReturn {\n const { localParticipant } = useLocalParticipant();\n\n const audioDevices = useMediaDevices({ kind: 'audioinput' });\n const videoDevices = useMediaDevices({ kind: 'videoinput' });\n\n const hasMic = audioDevices?.length > 0;\n const hasCamera = videoDevices?.length > 0;\n\n const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;\n const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;\n const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;\n\n const isMicEnabledRef = useLatest(isMicEnabled);\n const isCameraEnabledRef = useLatest(isCameraEnabled);\n const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);\n\n const hasMicRef = useLatest(hasMic);\n const hasCameraRef = useLatest(hasCamera);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleMic = useCallback(() => {\n if (hasMicRef.current || isMicEnabledRef.current) {\n localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleCamera = useCallback(() => {\n if (hasCameraRef.current || isCameraEnabledRef.current) {\n localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleScreenShare = useCallback(() => {\n localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);\n }, [localParticipant]);\n\n const tracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: false,\n updateOnlyOn: [],\n },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const localVideoTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.Camera,\n ) ?? null;\n\n return {\n hasMic,\n hasCamera,\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n localVideoTrackRef,\n };\n}\n","'use client';\n\nimport { TrackToggle } from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useAvatarSession } from '../hooks/useAvatarSession';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\n\nexport interface ControlBarState {\n isMicEnabled: boolean;\n isCameraEnabled: boolean;\n isScreenShareEnabled: boolean;\n toggleMic: () => void;\n toggleCamera: () => void;\n toggleScreenShare: () => void;\n endCall: () => Promise<void>;\n isActive: boolean;\n}\n\nexport interface ControlBarProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n showMicrophone?: boolean;\n showCamera?: boolean;\n showScreenShare?: boolean;\n showEndCall?: boolean;\n children?: (state: ControlBarState) => ReactNode;\n}\n\nexport function ControlBar({\n children,\n showMicrophone = true,\n showCamera = true,\n showScreenShare = false,\n showEndCall = true,\n ...props\n}: ControlBarProps) {\n const session = useAvatarSession();\n const {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n } = useLocalMedia();\n\n const isActive = session.state === 'active';\n\n const state: ControlBarState = {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n endCall: session.end,\n isActive,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isActive) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-control-bar=\"\" data-avatar-active={isActive}>\n {showMicrophone && (\n <button\n type=\"button\"\n onClick={toggleMic}\n data-avatar-control=\"microphone\"\n data-avatar-enabled={isMicEnabled}\n aria-label={isMicEnabled ? 'Mute microphone' : 'Unmute microphone'}\n >\n {microphoneIcon}\n </button>\n )}\n {showCamera && (\n <button\n type=\"button\"\n onClick={toggleCamera}\n data-avatar-control=\"camera\"\n data-avatar-enabled={isCameraEnabled}\n aria-label={isCameraEnabled ? 'Turn off camera' : 'Turn on camera'}\n >\n {cameraIcon}\n </button>\n )}\n {showScreenShare && (\n <TrackToggle\n source={Track.Source.ScreenShare}\n showIcon={false}\n data-avatar-control=\"screen-share\"\n data-avatar-enabled={isScreenShareEnabled}\n aria-label=\"Toggle screen share\"\n >\n {screenShareIcon}\n </TrackToggle>\n )}\n {showEndCall && (\n <button\n type=\"button\"\n onClick={session.end}\n data-avatar-control=\"end-call\"\n data-avatar-enabled={true}\n aria-label=\"End call\"\n >\n {phoneIcon}\n </button>\n )}\n </div>\n );\n}\n\n// Lucide icons (https://lucide.dev) - MIT License\nconst microphoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n);\n\nconst cameraIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n);\n\nconst screenShareIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n);\n\nconst phoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"8 14 24 12\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12.8429 22.5693L11.4018 21.0986C11.2675 20.9626 11.1625 20.7995 11.0935 20.6197C11.0245 20.4399 10.9931 20.2474 11.0013 20.0545C11.0094 19.8616 11.0569 19.6726 11.1408 19.4995C11.2247 19.3265 11.343 19.1732 11.4883 19.0495C13.127 17.7049 15.0519 16.7714 17.1083 16.3239C19.0064 15.892 20.9744 15.892 22.8725 16.3239C24.9374 16.7743 26.8693 17.7147 28.5117 19.0691C28.6565 19.1924 28.7746 19.3451 28.8585 19.5176C28.9423 19.69 28.99 19.8784 28.9986 20.0707C29.0072 20.263 28.9764 20.455 28.9083 20.6345C28.8402 20.814 28.7362 20.9771 28.603 21.1133L27.1619 22.584C26.9311 22.8242 26.6226 22.9706 26.2938 22.9959C25.9651 23.0211 25.6385 22.9235 25.3751 22.7212C24.8531 22.3127 24.2875 21.9657 23.689 21.6869C23.4525 21.5774 23.2517 21.4009 23.1103 21.1785C22.969 20.9561 22.8931 20.697 22.8917 20.4319V19.1867C21.0053 18.6573 19.0139 18.6573 17.1275 19.1867V20.4319C17.1261 20.697 17.0502 20.9561 16.9089 21.1785C16.7676 21.4009 16.5667 21.5774 16.3302 21.6869C15.7317 21.9657 15.1661 22.3127 14.6442 22.7212C14.3779 22.9258 14.0473 23.0233 13.7152 22.9953C13.383 22.9673 13.0726 22.8156 12.8429 22.5693Z\" />\n </svg>\n);\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\nimport type { UseLocalMediaReturn } from '../types';\n\nexport interface UserVideoState {\n hasVideo: boolean;\n isCameraEnabled: boolean;\n trackRef: UseLocalMediaReturn['localVideoTrackRef'];\n}\n\nexport interface UserVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n mirror?: boolean;\n children?: (state: UserVideoState) => ReactNode;\n}\n\nexport function UserVideo({\n children,\n mirror = true,\n ...props\n}: UserVideoProps) {\n const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();\n\n const hasVideo =\n localVideoTrackRef !== null && isTrackReference(localVideoTrackRef);\n\n const state: UserVideoState = {\n hasVideo,\n isCameraEnabled,\n trackRef: localVideoTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-user-video=\"\"\n data-avatar-has-video={hasVideo}\n data-avatar-camera-enabled={isCameraEnabled}\n data-avatar-mirror={mirror}\n >\n {hasVideo &&\n localVideoTrackRef &&\n isTrackReference(localVideoTrackRef) && (\n <VideoTrack trackRef={localVideoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\n/**\n * AvatarCall Component\n *\n * High-level component that handles the complete session lifecycle.\n * Manages credential fetching, connection, and video display internally\n * with a seamless loading experience.\n *\n * During credential loading, shows a loading state with the avatar image.\n * Once connected, renders children inside the session context.\n *\n * For more control over the loading UI, use AvatarSession directly.\n *\n * @example\n * ```tsx\n * // Simple usage - handles everything automatically\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\" />\n *\n * // Custom children - rendered once connected\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\">\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarCall>\n * ```\n */\n\nimport { useCredentials } from '../hooks/useCredentials';\nimport { useLatest } from '../hooks/useLatest';\nimport type { AvatarCallProps } from '../types';\nimport { AvatarSession } from './AvatarSession';\nimport { AvatarVideo } from './AvatarVideo';\nimport { ControlBar } from './ControlBar';\nimport { UserVideo } from './UserVideo';\n\nexport function AvatarCall({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n avatarImageUrl,\n onEnd,\n onError,\n children,\n __unstable_roomOptions,\n ...props\n}: AvatarCallProps) {\n const onErrorRef = useLatest(onError);\n\n const credentialsState = useCredentials({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n onError: (err) => onErrorRef.current?.(err),\n });\n\n const handleSessionError = (err: Error) => {\n onErrorRef.current?.(err);\n };\n\n const backgroundStyle = avatarImageUrl\n ? ({ '--avatar-image': `url(${avatarImageUrl})` } as React.CSSProperties)\n : undefined;\n\n const defaultChildren = (\n <>\n <AvatarVideo />\n <UserVideo />\n <ControlBar />\n </>\n );\n\n // During credential loading/error, show a simple loading state\n // Children are NOT rendered here because they may use hooks that require LiveKitRoom context\n if (credentialsState.status !== 'ready') {\n const status =\n credentialsState.status === 'error' ? 'error' : 'connecting';\n\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <div data-avatar-video=\"\" data-avatar-status={status} />\n </div>\n );\n }\n\n // Once credentials are ready, render children inside the session context\n // This ensures all hooks have access to the LiveKitRoom context\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <AvatarSession\n credentials={credentialsState.credentials}\n onEnd={onEnd}\n onError={handleSessionError}\n __unstable_roomOptions={__unstable_roomOptions}\n >\n {children ?? defaultChildren}\n </AvatarSession>\n </div>\n );\n}\n","'use client';\n\nimport {\n isTrackReference,\n type TrackReferenceOrPlaceholder,\n useLocalParticipant,\n useTracks,\n VideoTrack,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nexport interface ScreenShareVideoState {\n isSharing: boolean;\n trackRef: TrackReferenceOrPlaceholder | null;\n}\n\nexport interface ScreenShareVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (state: ScreenShareVideoState) => ReactNode;\n}\n\n/**\n * Component for displaying local screen share video.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n */\nexport function ScreenShareVideo({\n children,\n ...props\n}: ScreenShareVideoProps) {\n const { localParticipant } = useLocalParticipant();\n\n const tracks = useTracks(\n [{ source: Track.Source.ScreenShare, withPlaceholder: false }],\n { onlySubscribed: false },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const screenShareTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.ScreenShare,\n ) ?? null;\n\n const isSharing =\n screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);\n\n const state: ScreenShareVideoState = {\n isSharing,\n trackRef: screenShareTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isSharing) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-screen-share=\"\" data-avatar-sharing={isSharing}>\n {screenShareTrackRef && isTrackReference(screenShareTrackRef) && (\n <VideoTrack trackRef={screenShareTrackRef} />\n )}\n </div>\n );\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -212,6 +212,11 @@ interface ScreenShareVideoState {
|
|
|
212
212
|
interface ScreenShareVideoProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
|
|
213
213
|
children?: (state: ScreenShareVideoState) => ReactNode;
|
|
214
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Component for displaying local screen share video.
|
|
217
|
+
*
|
|
218
|
+
* Must be used within an AvatarSession or AvatarCall component.
|
|
219
|
+
*/
|
|
215
220
|
declare function ScreenShareVideo({ children, ...props }: ScreenShareVideoProps): react_jsx_runtime.JSX.Element | null;
|
|
216
221
|
|
|
217
222
|
interface UserVideoState {
|
|
@@ -275,7 +280,10 @@ declare function useAvatarSession(): UseAvatarSessionReturn;
|
|
|
275
280
|
|
|
276
281
|
/**
|
|
277
282
|
* Hook for local media controls (mic, camera, screen share).
|
|
278
|
-
*
|
|
283
|
+
*
|
|
284
|
+
* Must be used within an AvatarSession or AvatarCall component.
|
|
285
|
+
* For use outside the session context, use AvatarSession directly
|
|
286
|
+
* and manage your own loading states.
|
|
279
287
|
*/
|
|
280
288
|
declare function useLocalMedia(): UseLocalMediaReturn;
|
|
281
289
|
|
package/dist/index.d.ts
CHANGED
|
@@ -212,6 +212,11 @@ interface ScreenShareVideoState {
|
|
|
212
212
|
interface ScreenShareVideoProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
|
|
213
213
|
children?: (state: ScreenShareVideoState) => ReactNode;
|
|
214
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Component for displaying local screen share video.
|
|
217
|
+
*
|
|
218
|
+
* Must be used within an AvatarSession or AvatarCall component.
|
|
219
|
+
*/
|
|
215
220
|
declare function ScreenShareVideo({ children, ...props }: ScreenShareVideoProps): react_jsx_runtime.JSX.Element | null;
|
|
216
221
|
|
|
217
222
|
interface UserVideoState {
|
|
@@ -275,7 +280,10 @@ declare function useAvatarSession(): UseAvatarSessionReturn;
|
|
|
275
280
|
|
|
276
281
|
/**
|
|
277
282
|
* Hook for local media controls (mic, camera, screen share).
|
|
278
|
-
*
|
|
283
|
+
*
|
|
284
|
+
* Must be used within an AvatarSession or AvatarCall component.
|
|
285
|
+
* For use outside the session context, use AvatarSession directly
|
|
286
|
+
* and manage your own loading states.
|
|
279
287
|
*/
|
|
280
288
|
declare function useLocalMedia(): UseLocalMediaReturn;
|
|
281
289
|
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { LiveKitRoom, RoomAudioRenderer, useRoomContext, useConnectionState,
|
|
1
|
+
import { LiveKitRoom, RoomAudioRenderer, useRoomContext, useConnectionState, useRemoteParticipants, useTracks, isTrackReference, VideoTrack, useLocalParticipant, useMediaDevices, TrackToggle } from '@livekit/components-react';
|
|
2
2
|
export { RoomAudioRenderer as AudioRenderer, VideoTrack } from '@livekit/components-react';
|
|
3
3
|
import { createContext, useRef, useCallback, useState, useEffect, useContext } from 'react';
|
|
4
4
|
import { Track, ConnectionState } from 'livekit-client';
|
|
5
|
-
import {
|
|
5
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
// src/api/config.ts
|
|
8
8
|
var DEFAULT_BASE_URL = "https://api.dev.runwayml.com";
|
|
@@ -76,6 +76,8 @@ function useCredentials(options) {
|
|
|
76
76
|
onError
|
|
77
77
|
} = options;
|
|
78
78
|
const onErrorRef = useLatest(onError);
|
|
79
|
+
const connectRef = useLatest(connect);
|
|
80
|
+
const fetchedKeyRef = useRef(null);
|
|
79
81
|
const [state, setState] = useState(() => {
|
|
80
82
|
if (directCredentials) {
|
|
81
83
|
return { status: "ready", credentials: directCredentials, error: null };
|
|
@@ -91,6 +93,9 @@ function useCredentials(options) {
|
|
|
91
93
|
});
|
|
92
94
|
return;
|
|
93
95
|
}
|
|
96
|
+
const credentialKey = `${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;
|
|
97
|
+
if (fetchedKeyRef.current === credentialKey) return;
|
|
98
|
+
fetchedKeyRef.current = credentialKey;
|
|
94
99
|
let cancelled = false;
|
|
95
100
|
setState({ status: "loading", credentials: null, error: null });
|
|
96
101
|
async function load() {
|
|
@@ -100,7 +105,7 @@ function useCredentials(options) {
|
|
|
100
105
|
sessionId,
|
|
101
106
|
sessionKey,
|
|
102
107
|
connectUrl,
|
|
103
|
-
connect,
|
|
108
|
+
connect: connectRef.current ?? void 0,
|
|
104
109
|
baseUrl
|
|
105
110
|
};
|
|
106
111
|
const credentials = await fetchCredentials(fetchOptions);
|
|
@@ -119,30 +124,25 @@ function useCredentials(options) {
|
|
|
119
124
|
return () => {
|
|
120
125
|
cancelled = true;
|
|
121
126
|
};
|
|
122
|
-
}, [
|
|
123
|
-
directCredentials,
|
|
124
|
-
avatarId,
|
|
125
|
-
sessionId,
|
|
126
|
-
sessionKey,
|
|
127
|
-
connectUrl,
|
|
128
|
-
connect,
|
|
129
|
-
baseUrl
|
|
130
|
-
]);
|
|
127
|
+
}, [directCredentials, avatarId, sessionId, sessionKey, connectUrl, baseUrl]);
|
|
131
128
|
return state;
|
|
132
129
|
}
|
|
133
|
-
async function hasMediaDevice(kind) {
|
|
130
|
+
async function hasMediaDevice(kind, timeoutMs = 1e3) {
|
|
134
131
|
try {
|
|
135
|
-
const
|
|
136
|
-
|
|
132
|
+
const timeoutPromise = new Promise(
|
|
133
|
+
(resolve) => setTimeout(() => resolve(false), timeoutMs)
|
|
134
|
+
);
|
|
135
|
+
const checkPromise = navigator.mediaDevices.enumerateDevices().then((devices) => devices.some((device) => device.kind === kind));
|
|
136
|
+
return await Promise.race([checkPromise, timeoutPromise]);
|
|
137
137
|
} catch {
|
|
138
138
|
return false;
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
function useDeviceAvailability(requestAudio, requestVideo) {
|
|
142
142
|
const [state, setState] = useState({
|
|
143
|
-
audio:
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
audio: requestAudio,
|
|
144
|
+
// Optimistically assume devices exist
|
|
145
|
+
video: requestVideo
|
|
146
146
|
});
|
|
147
147
|
useEffect(() => {
|
|
148
148
|
let cancelled = false;
|
|
@@ -154,8 +154,7 @@ function useDeviceAvailability(requestAudio, requestVideo) {
|
|
|
154
154
|
if (!cancelled) {
|
|
155
155
|
setState({
|
|
156
156
|
audio: requestAudio && hasAudio,
|
|
157
|
-
video: requestVideo && hasVideo
|
|
158
|
-
isChecking: false
|
|
157
|
+
video: requestVideo && hasVideo
|
|
159
158
|
});
|
|
160
159
|
}
|
|
161
160
|
}
|
|
@@ -206,21 +205,6 @@ function AvatarSession({
|
|
|
206
205
|
...DEFAULT_ROOM_OPTIONS,
|
|
207
206
|
...__unstable_roomOptions
|
|
208
207
|
};
|
|
209
|
-
if (deviceAvailability.isChecking) {
|
|
210
|
-
return /* @__PURE__ */ jsx(
|
|
211
|
-
AvatarSessionContext.Provider,
|
|
212
|
-
{
|
|
213
|
-
value: {
|
|
214
|
-
state: "connecting",
|
|
215
|
-
sessionId: credentials.sessionId,
|
|
216
|
-
error: null,
|
|
217
|
-
end: async () => {
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
children
|
|
221
|
-
}
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
208
|
return /* @__PURE__ */ jsxs(
|
|
225
209
|
LiveKitRoom,
|
|
226
210
|
{
|
|
@@ -287,34 +271,17 @@ function useAvatarSessionContext() {
|
|
|
287
271
|
}
|
|
288
272
|
return context;
|
|
289
273
|
}
|
|
290
|
-
function LoadingSessionProvider({
|
|
291
|
-
state,
|
|
292
|
-
error,
|
|
293
|
-
children
|
|
294
|
-
}) {
|
|
295
|
-
const contextValue = {
|
|
296
|
-
state,
|
|
297
|
-
sessionId: "",
|
|
298
|
-
error,
|
|
299
|
-
end: async () => {
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
return /* @__PURE__ */ jsx(AvatarSessionContext.Provider, { value: contextValue, children });
|
|
303
|
-
}
|
|
304
274
|
function useAvatar() {
|
|
305
|
-
const
|
|
306
|
-
const hasRoomContext = room !== void 0;
|
|
307
|
-
const remoteParticipants = useRemoteParticipants({ room });
|
|
275
|
+
const remoteParticipants = useRemoteParticipants();
|
|
308
276
|
const avatarParticipant = remoteParticipants[0] ?? null;
|
|
309
277
|
const videoTracks = useTracks(
|
|
310
278
|
[{ source: Track.Source.Camera, withPlaceholder: true }],
|
|
311
279
|
{
|
|
312
280
|
onlySubscribed: true,
|
|
313
|
-
updateOnlyOn: []
|
|
314
|
-
room: hasRoomContext ? room : void 0
|
|
281
|
+
updateOnlyOn: []
|
|
315
282
|
}
|
|
316
283
|
).filter((ref) => !ref.participant.isLocal);
|
|
317
|
-
const videoTrackRef =
|
|
284
|
+
const videoTrackRef = videoTracks[0] ?? null;
|
|
318
285
|
const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);
|
|
319
286
|
return {
|
|
320
287
|
participant: avatarParticipant,
|
|
@@ -367,9 +334,7 @@ function AvatarVideo({ children, ...props }) {
|
|
|
367
334
|
);
|
|
368
335
|
}
|
|
369
336
|
function useLocalMedia() {
|
|
370
|
-
const
|
|
371
|
-
const hasRoomContext = room !== void 0;
|
|
372
|
-
const { localParticipant } = useLocalParticipant({ room });
|
|
337
|
+
const { localParticipant } = useLocalParticipant();
|
|
373
338
|
const audioDevices = useMediaDevices({ kind: "audioinput" });
|
|
374
339
|
const videoDevices = useMediaDevices({ kind: "videoinput" });
|
|
375
340
|
const hasMic = audioDevices?.length > 0;
|
|
@@ -399,14 +364,13 @@ function useLocalMedia() {
|
|
|
399
364
|
[{ source: Track.Source.Camera, withPlaceholder: true }],
|
|
400
365
|
{
|
|
401
366
|
onlySubscribed: false,
|
|
402
|
-
updateOnlyOn: []
|
|
403
|
-
room: hasRoomContext ? room : void 0
|
|
367
|
+
updateOnlyOn: []
|
|
404
368
|
}
|
|
405
369
|
);
|
|
406
370
|
const localIdentity = localParticipant?.identity;
|
|
407
|
-
const localVideoTrackRef =
|
|
371
|
+
const localVideoTrackRef = tracks.find(
|
|
408
372
|
(trackRef) => trackRef.participant.identity === localIdentity && trackRef.source === Track.Source.Camera
|
|
409
|
-
) ?? null
|
|
373
|
+
) ?? null;
|
|
410
374
|
return {
|
|
411
375
|
hasMic,
|
|
412
376
|
hasCamera,
|
|
@@ -630,6 +594,7 @@ function AvatarCall({
|
|
|
630
594
|
/* @__PURE__ */ jsx(ControlBar, {})
|
|
631
595
|
] });
|
|
632
596
|
if (credentialsState.status !== "ready") {
|
|
597
|
+
const status = credentialsState.status === "error" ? "error" : "connecting";
|
|
633
598
|
return /* @__PURE__ */ jsx(
|
|
634
599
|
"div",
|
|
635
600
|
{
|
|
@@ -637,14 +602,7 @@ function AvatarCall({
|
|
|
637
602
|
"data-avatar-call": "",
|
|
638
603
|
"data-avatar-id": avatarId,
|
|
639
604
|
style: { ...props.style, ...backgroundStyle },
|
|
640
|
-
children: /* @__PURE__ */ jsx(
|
|
641
|
-
LoadingSessionProvider,
|
|
642
|
-
{
|
|
643
|
-
state: credentialsState.status === "error" ? "error" : "connecting",
|
|
644
|
-
error: credentialsState.error,
|
|
645
|
-
children: children ?? defaultChildren
|
|
646
|
-
}
|
|
647
|
-
)
|
|
605
|
+
children: /* @__PURE__ */ jsx("div", { "data-avatar-video": "", "data-avatar-status": status })
|
|
648
606
|
}
|
|
649
607
|
);
|
|
650
608
|
}
|
|
@@ -672,17 +630,15 @@ function ScreenShareVideo({
|
|
|
672
630
|
children,
|
|
673
631
|
...props
|
|
674
632
|
}) {
|
|
675
|
-
const
|
|
676
|
-
const hasRoomContext = room !== void 0;
|
|
677
|
-
const { localParticipant } = useLocalParticipant({ room });
|
|
633
|
+
const { localParticipant } = useLocalParticipant();
|
|
678
634
|
const tracks = useTracks(
|
|
679
635
|
[{ source: Track.Source.ScreenShare, withPlaceholder: false }],
|
|
680
|
-
{ onlySubscribed: false
|
|
636
|
+
{ onlySubscribed: false }
|
|
681
637
|
);
|
|
682
638
|
const localIdentity = localParticipant?.identity;
|
|
683
|
-
const screenShareTrackRef =
|
|
639
|
+
const screenShareTrackRef = tracks.find(
|
|
684
640
|
(trackRef) => trackRef.participant.identity === localIdentity && trackRef.source === Track.Source.ScreenShare
|
|
685
|
-
) ?? null
|
|
641
|
+
) ?? null;
|
|
686
642
|
const isSharing = screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);
|
|
687
643
|
const state = {
|
|
688
644
|
isSharing,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts","../src/hooks/useLatest.ts","../src/hooks/useCredentials.ts","../src/components/AvatarSession.tsx","../src/hooks/useAvatar.ts","../src/hooks/useAvatarSession.ts","../src/hooks/useAvatarStatus.ts","../src/components/AvatarVideo.tsx","../src/hooks/useLocalMedia.ts","../src/components/ControlBar.tsx","../src/components/UserVideo.tsx","../src/components/AvatarCall.tsx","../src/components/ScreenShareVideo.tsx"],"names":["useEffect","useState","useRef","RoomAudioRenderer","jsx","isTrackReference","useMaybeRoomContext","useCallback","useTracks","Track","Fragment","jsxs","VideoTrack","useLocalParticipant"],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { DEFAULT_BASE_URL } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nexport function useLatest<T>(value: T): React.RefObject<T> {\n const ref = useRef(value);\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { consumeSession } from '../api/consume';\nimport type { SessionCredentials } from '../types';\nimport { useLatest } from './useLatest';\n\nexport interface UseCredentialsOptions {\n avatarId: string;\n sessionId?: string;\n sessionKey?: string;\n credentials?: SessionCredentials;\n connectUrl?: string;\n connect?: (avatarId: string) => Promise<SessionCredentials>;\n baseUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport type CredentialsState =\n | { status: 'loading'; credentials: null; error: null }\n | { status: 'ready'; credentials: SessionCredentials; error: null }\n | { status: 'error'; credentials: null; error: Error };\n\nasync function fetchCredentials(\n options: UseCredentialsOptions,\n): Promise<SessionCredentials> {\n const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } =\n options;\n\n if (sessionId && sessionKey) {\n const { url, token, roomName } = await consumeSession({\n sessionId,\n sessionKey,\n baseUrl,\n });\n return { sessionId, serverUrl: url, token, roomName };\n }\n\n if (connect) {\n return connect(avatarId);\n }\n\n if (connectUrl) {\n const response = await fetch(connectUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ avatarId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to connect: ${response.status} ${errorText}`);\n }\n\n return response.json();\n }\n\n throw new Error(\n 'AvatarCall requires one of: credentials, sessionId+sessionKey, connectUrl, or connect',\n );\n}\n\nexport function useCredentials(\n options: UseCredentialsOptions,\n): CredentialsState {\n const {\n credentials: directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n onError,\n } = options;\n\n const onErrorRef = useLatest(onError);\n\n const [state, setState] = useState<CredentialsState>(() => {\n if (directCredentials) {\n return { status: 'ready', credentials: directCredentials, error: null };\n }\n return { status: 'loading', credentials: null, error: null };\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: onErrorRef is a stable ref from useLatest - we intentionally read .current at call time\n useEffect(() => {\n if (directCredentials) {\n setState({\n status: 'ready',\n credentials: directCredentials,\n error: null,\n });\n return;\n }\n\n let cancelled = false;\n setState({ status: 'loading', credentials: null, error: null });\n\n async function load() {\n try {\n const fetchOptions: UseCredentialsOptions = {\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n };\n const credentials = await fetchCredentials(fetchOptions);\n if (!cancelled) {\n setState({ status: 'ready', credentials, error: null });\n }\n } catch (err) {\n if (!cancelled) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState({ status: 'error', credentials: null, error });\n onErrorRef.current?.(error);\n }\n }\n }\n\n load();\n\n return () => {\n cancelled = true;\n };\n }, [\n directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n ]);\n\n return state;\n}\n","'use client';\n\n/**\n * AvatarSession Component\n *\n * Provides the session context for avatar interactions.\n * Manages the WebRTC connection and exposes a clean API for child components.\n *\n * @example\n * ```tsx\n * <AvatarSession credentials={credentials} onEnd={handleEnd}>\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarSession>\n * ```\n */\n\nimport {\n LiveKitRoom,\n RoomAudioRenderer,\n useConnectionState,\n useRoomContext,\n} from '@livekit/components-react';\nimport type { RoomOptions } from 'livekit-client';\nimport { ConnectionState } from 'livekit-client';\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n AvatarSessionContextValue,\n AvatarSessionProps,\n SessionState,\n} from '../types';\n\n/**\n * Check if a media device of the given kind is available\n */\nasync function hasMediaDevice(\n kind: 'audioinput' | 'videoinput',\n): Promise<boolean> {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.some((device) => device.kind === kind);\n } catch {\n return false;\n }\n}\n\n/**\n * Hook to check device availability before connecting\n */\nfunction useDeviceAvailability(\n requestAudio: boolean,\n requestVideo: boolean,\n): { audio: boolean; video: boolean; isChecking: boolean } {\n const [state, setState] = useState({\n audio: false,\n video: false,\n isChecking: true,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function checkDevices() {\n const [hasAudio, hasVideo] = await Promise.all([\n requestAudio ? hasMediaDevice('audioinput') : Promise.resolve(false),\n requestVideo ? hasMediaDevice('videoinput') : Promise.resolve(false),\n ]);\n\n if (!cancelled) {\n setState({\n audio: requestAudio && hasAudio,\n video: requestVideo && hasVideo,\n isChecking: false,\n });\n }\n }\n\n checkDevices();\n\n return () => {\n cancelled = true;\n };\n }, [requestAudio, requestVideo]);\n\n return state;\n}\n\nconst DEFAULT_ROOM_OPTIONS: RoomOptions = {\n adaptiveStream: false,\n dynacast: false,\n};\n\n/**\n * Maps WebRTC connection state to session state\n */\nfunction mapConnectionState(connectionState: ConnectionState): SessionState {\n switch (connectionState) {\n case ConnectionState.Connecting:\n return 'connecting';\n case ConnectionState.Connected:\n return 'active';\n case ConnectionState.Reconnecting:\n return 'connecting';\n case ConnectionState.Disconnected:\n return 'ended';\n default:\n return 'ended';\n }\n}\n\nconst AvatarSessionContext = createContext<AvatarSessionContextValue | null>(\n null,\n);\n\n/**\n * AvatarSession component - the main entry point for avatar sessions\n *\n * Establishes a WebRTC connection and provides session state to children.\n * This is a headless component that renders minimal DOM.\n */\nexport function AvatarSession({\n credentials,\n children,\n audio: requestAudio = true,\n video: requestVideo = true,\n onEnd,\n onError,\n __unstable_roomOptions,\n}: AvatarSessionProps) {\n const errorRef = useRef<Error | null>(null);\n\n const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);\n\n const handleError = (error: Error) => {\n errorRef.current = error;\n onError?.(error);\n };\n\n const roomOptions = {\n ...DEFAULT_ROOM_OPTIONS,\n ...__unstable_roomOptions,\n };\n\n if (deviceAvailability.isChecking) {\n return (\n <AvatarSessionContext.Provider\n value={{\n state: 'connecting',\n sessionId: credentials.sessionId,\n error: null,\n end: async () => {},\n }}\n >\n {children}\n </AvatarSessionContext.Provider>\n );\n }\n\n return (\n <LiveKitRoom\n serverUrl={credentials.serverUrl}\n token={credentials.token}\n connect={true}\n audio={deviceAvailability.audio}\n video={deviceAvailability.video}\n onDisconnected={() => onEnd?.()}\n onError={handleError}\n options={roomOptions}\n connectOptions={{\n autoSubscribe: true,\n }}\n >\n <AvatarSessionContextInner\n sessionId={credentials.sessionId}\n onEnd={onEnd}\n errorRef={errorRef}\n >\n {children}\n </AvatarSessionContextInner>\n <RoomAudioRenderer />\n </LiveKitRoom>\n );\n}\n\n/**\n * Inner context provider that has access to the room context\n */\nfunction AvatarSessionContextInner({\n sessionId,\n onEnd,\n errorRef,\n children,\n}: {\n sessionId: string;\n onEnd?: () => void;\n errorRef: React.RefObject<Error | null>;\n children: ReactNode;\n}) {\n const room = useRoomContext();\n const connectionState = useConnectionState();\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n const end = useCallback(async () => {\n try {\n // Send END_CALL message to the avatar\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({ type: 'END_CALL' }));\n await room.localParticipant.publishData(data, { reliable: true });\n } catch {\n // Ignore errors when sending end message\n }\n\n await room.disconnect();\n onEndRef.current?.();\n }, [room]);\n\n const contextValue: AvatarSessionContextValue = {\n state: mapConnectionState(connectionState),\n sessionId,\n error: errorRef.current,\n end,\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n\n/**\n * Hook to access the avatar session context\n * Must be used within an AvatarSession component\n */\nexport function useAvatarSessionContext(): AvatarSessionContextValue {\n const context = useContext(AvatarSessionContext);\n if (!context) {\n throw new Error(\n 'useAvatarSessionContext must be used within an AvatarSession',\n );\n }\n return context;\n}\n\n/**\n * Hook to optionally access the avatar session context\n * Returns null if not within an AvatarSession\n */\nexport function useMaybeAvatarSessionContext(): AvatarSessionContextValue | null {\n return useContext(AvatarSessionContext);\n}\n\n/**\n * Provider for loading/error states before the actual session is established.\n * Used by AvatarCall to provide context during credential fetching.\n */\nexport function LoadingSessionProvider({\n state,\n error,\n children,\n}: {\n state: 'connecting' | 'error';\n error: Error | null;\n children: ReactNode;\n}) {\n const contextValue: AvatarSessionContextValue = {\n state,\n sessionId: '',\n error,\n end: async () => {},\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n","'use client';\n\n/**\n * useAvatar Hook\n *\n * Provides access to the remote avatar participant's video track.\n * Audio is handled automatically by the session.\n * Returns safe defaults when called outside of LiveKitRoom context.\n *\n * @example\n * ```tsx\n * function AvatarDisplay() {\n * const { videoTrackRef, hasVideo } = useAvatar();\n *\n * if (!hasVideo) {\n * return <Placeholder />;\n * }\n *\n * return <VideoTrack trackRef={videoTrackRef} />;\n * }\n * ```\n */\n\nimport {\n isTrackReference,\n useMaybeRoomContext,\n useRemoteParticipants,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { UseAvatarReturn } from '../types';\n\n/**\n * Hook to access the remote avatar participant's video track\n *\n * @returns Avatar participant info and video track reference\n */\nexport function useAvatar(): UseAvatarReturn {\n const room = useMaybeRoomContext();\n const hasRoomContext = room !== undefined;\n\n const remoteParticipants = useRemoteParticipants({ room });\n const avatarParticipant = remoteParticipants[0] ?? null;\n\n // Only subscribe to video - audio is handled automatically by the session\n const videoTracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: true,\n updateOnlyOn: [],\n room: hasRoomContext ? room : undefined,\n },\n ).filter((ref) => !ref.participant.isLocal);\n\n const videoTrackRef = hasRoomContext ? (videoTracks[0] ?? null) : null;\n const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);\n\n return {\n participant: avatarParticipant,\n videoTrackRef,\n hasVideo,\n };\n}\n","'use client';\n\n/**\n * useAvatarSession Hook\n *\n * Provides access to the current avatar session state.\n * Returns a discriminated union based on session state for type-safe UI rendering.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const session = useAvatarSession();\n *\n * if (session.state === 'connecting') {\n * return <Loading />;\n * }\n *\n * if (session.state === 'error') {\n * return <Error message={session.error.message} />;\n * }\n *\n * return <ActiveSession onEnd={session.end} />;\n * }\n * ```\n */\n\nimport { useAvatarSessionContext } from '../components/AvatarSession';\nimport type { AvatarSessionContextValue } from '../types';\n\n/**\n * Discriminated union types for type-safe session state handling\n */\nexport type UseAvatarSessionReturn =\n | { state: 'idle'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'connecting'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'active'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ending'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ended'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'error'; sessionId: string; error: Error; end: () => Promise<void> };\n\n/**\n * Hook to access the current avatar session state\n *\n * @returns Session state as a discriminated union\n */\nexport function useAvatarSession(): UseAvatarSessionReturn {\n const context = useAvatarSessionContext();\n return context as UseAvatarSessionReturn;\n}\n\nexport type { AvatarSessionContextValue };\n","'use client';\n\n/**\n * useAvatarStatus Hook\n *\n * Returns a single discriminated union representing the full avatar lifecycle\n * inside an AvatarSession. Combines session connection state and video\n * track availability into one status value.\n *\n * Must be used within <AvatarCall> or <AvatarSession>.\n *\n * @example\n * ```tsx\n * function MyAvatar() {\n * const avatar = useAvatarStatus();\n *\n * switch (avatar.status) {\n * case 'connecting':\n * return <Spinner />;\n * case 'waiting':\n * return <p>Waiting for video...</p>;\n * case 'ready':\n * return <VideoTrack trackRef={avatar.videoTrackRef} />;\n * case 'error':\n * return <p>{avatar.error.message}</p>;\n * case 'ended':\n * return <p>Call ended</p>;\n * }\n * }\n * ```\n */\n\nimport type { TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport { useAvatar } from './useAvatar';\nimport { useAvatarSession } from './useAvatarSession';\n\nexport type AvatarStatus =\n | { status: 'connecting' }\n | { status: 'waiting' }\n | { status: 'ready'; videoTrackRef: TrackReferenceOrPlaceholder }\n | { status: 'ending' }\n | { status: 'ended' }\n | { status: 'error'; error: Error };\n\nexport function useAvatarStatus(): AvatarStatus {\n const session = useAvatarSession();\n const { videoTrackRef, hasVideo } = useAvatar();\n\n switch (session.state) {\n case 'connecting':\n case 'idle':\n return { status: 'connecting' };\n\n case 'active':\n if (hasVideo && videoTrackRef) {\n return { status: 'ready', videoTrackRef };\n }\n return { status: 'waiting' };\n\n case 'ending':\n return { status: 'ending' };\n\n case 'ended':\n return { status: 'ended' };\n\n case 'error':\n return { status: 'error', error: session.error };\n }\n}\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { type AvatarStatus, useAvatarStatus } from '../hooks/useAvatarStatus';\n\n/** Subset of AvatarStatus relevant to the video display */\nexport type AvatarVideoStatus = Extract<\n AvatarStatus,\n { status: 'connecting' } | { status: 'waiting' } | { status: 'ready' }\n>;\n\nexport interface AvatarVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (status: AvatarVideoStatus) => ReactNode;\n}\n\nexport function AvatarVideo({ children, ...props }: AvatarVideoProps) {\n const avatar = useAvatarStatus();\n\n const videoStatus: AvatarVideoStatus =\n avatar.status === 'ready'\n ? avatar\n : avatar.status === 'connecting'\n ? { status: 'connecting' }\n : { status: 'waiting' };\n\n if (children) {\n return <>{children(videoStatus)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-video=\"\"\n data-avatar-status={videoStatus.status}\n >\n {videoStatus.status === 'ready' &&\n isTrackReference(videoStatus.videoTrackRef) && (\n <VideoTrack trackRef={videoStatus.videoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n useLocalParticipant,\n useMaybeRoomContext,\n useMediaDevices,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport type { UseLocalMediaReturn } from '../types';\nimport { useLatest } from './useLatest';\n\n/**\n * Hook for local media controls (mic, camera, screen share).\n * Returns safe defaults when called outside of LiveKitRoom context.\n */\nexport function useLocalMedia(): UseLocalMediaReturn {\n const room = useMaybeRoomContext();\n const hasRoomContext = room !== undefined;\n\n const { localParticipant } = useLocalParticipant({ room });\n\n const audioDevices = useMediaDevices({ kind: 'audioinput' });\n const videoDevices = useMediaDevices({ kind: 'videoinput' });\n\n const hasMic = audioDevices?.length > 0;\n const hasCamera = videoDevices?.length > 0;\n\n const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;\n const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;\n const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;\n\n const isMicEnabledRef = useLatest(isMicEnabled);\n const isCameraEnabledRef = useLatest(isCameraEnabled);\n const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);\n\n const hasMicRef = useLatest(hasMic);\n const hasCameraRef = useLatest(hasCamera);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleMic = useCallback(() => {\n if (hasMicRef.current || isMicEnabledRef.current) {\n localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleCamera = useCallback(() => {\n if (hasCameraRef.current || isCameraEnabledRef.current) {\n localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleScreenShare = useCallback(() => {\n localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);\n }, [localParticipant]);\n\n const tracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: false,\n updateOnlyOn: [],\n room: hasRoomContext ? room : undefined,\n },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const localVideoTrackRef = hasRoomContext\n ? (tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.Camera,\n ) ?? null)\n : null;\n\n return {\n hasMic,\n hasCamera,\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n localVideoTrackRef,\n };\n}\n","'use client';\n\nimport { TrackToggle } from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useAvatarSession } from '../hooks/useAvatarSession';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\n\nexport interface ControlBarState {\n isMicEnabled: boolean;\n isCameraEnabled: boolean;\n isScreenShareEnabled: boolean;\n toggleMic: () => void;\n toggleCamera: () => void;\n toggleScreenShare: () => void;\n endCall: () => Promise<void>;\n isActive: boolean;\n}\n\nexport interface ControlBarProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n showMicrophone?: boolean;\n showCamera?: boolean;\n showScreenShare?: boolean;\n showEndCall?: boolean;\n children?: (state: ControlBarState) => ReactNode;\n}\n\nexport function ControlBar({\n children,\n showMicrophone = true,\n showCamera = true,\n showScreenShare = false,\n showEndCall = true,\n ...props\n}: ControlBarProps) {\n const session = useAvatarSession();\n const {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n } = useLocalMedia();\n\n const isActive = session.state === 'active';\n\n const state: ControlBarState = {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n endCall: session.end,\n isActive,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isActive) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-control-bar=\"\" data-avatar-active={isActive}>\n {showMicrophone && (\n <button\n type=\"button\"\n onClick={toggleMic}\n data-avatar-control=\"microphone\"\n data-avatar-enabled={isMicEnabled}\n aria-label={isMicEnabled ? 'Mute microphone' : 'Unmute microphone'}\n >\n {microphoneIcon}\n </button>\n )}\n {showCamera && (\n <button\n type=\"button\"\n onClick={toggleCamera}\n data-avatar-control=\"camera\"\n data-avatar-enabled={isCameraEnabled}\n aria-label={isCameraEnabled ? 'Turn off camera' : 'Turn on camera'}\n >\n {cameraIcon}\n </button>\n )}\n {showScreenShare && (\n <TrackToggle\n source={Track.Source.ScreenShare}\n showIcon={false}\n data-avatar-control=\"screen-share\"\n data-avatar-enabled={isScreenShareEnabled}\n aria-label=\"Toggle screen share\"\n >\n {screenShareIcon}\n </TrackToggle>\n )}\n {showEndCall && (\n <button\n type=\"button\"\n onClick={session.end}\n data-avatar-control=\"end-call\"\n data-avatar-enabled={true}\n aria-label=\"End call\"\n >\n {phoneIcon}\n </button>\n )}\n </div>\n );\n}\n\n// Lucide icons (https://lucide.dev) - MIT License\nconst microphoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n);\n\nconst cameraIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n);\n\nconst screenShareIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n);\n\nconst phoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"8 14 24 12\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12.8429 22.5693L11.4018 21.0986C11.2675 20.9626 11.1625 20.7995 11.0935 20.6197C11.0245 20.4399 10.9931 20.2474 11.0013 20.0545C11.0094 19.8616 11.0569 19.6726 11.1408 19.4995C11.2247 19.3265 11.343 19.1732 11.4883 19.0495C13.127 17.7049 15.0519 16.7714 17.1083 16.3239C19.0064 15.892 20.9744 15.892 22.8725 16.3239C24.9374 16.7743 26.8693 17.7147 28.5117 19.0691C28.6565 19.1924 28.7746 19.3451 28.8585 19.5176C28.9423 19.69 28.99 19.8784 28.9986 20.0707C29.0072 20.263 28.9764 20.455 28.9083 20.6345C28.8402 20.814 28.7362 20.9771 28.603 21.1133L27.1619 22.584C26.9311 22.8242 26.6226 22.9706 26.2938 22.9959C25.9651 23.0211 25.6385 22.9235 25.3751 22.7212C24.8531 22.3127 24.2875 21.9657 23.689 21.6869C23.4525 21.5774 23.2517 21.4009 23.1103 21.1785C22.969 20.9561 22.8931 20.697 22.8917 20.4319V19.1867C21.0053 18.6573 19.0139 18.6573 17.1275 19.1867V20.4319C17.1261 20.697 17.0502 20.9561 16.9089 21.1785C16.7676 21.4009 16.5667 21.5774 16.3302 21.6869C15.7317 21.9657 15.1661 22.3127 14.6442 22.7212C14.3779 22.9258 14.0473 23.0233 13.7152 22.9953C13.383 22.9673 13.0726 22.8156 12.8429 22.5693Z\" />\n </svg>\n);\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\nimport type { UseLocalMediaReturn } from '../types';\n\nexport interface UserVideoState {\n hasVideo: boolean;\n isCameraEnabled: boolean;\n trackRef: UseLocalMediaReturn['localVideoTrackRef'];\n}\n\nexport interface UserVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n mirror?: boolean;\n children?: (state: UserVideoState) => ReactNode;\n}\n\nexport function UserVideo({\n children,\n mirror = true,\n ...props\n}: UserVideoProps) {\n const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();\n\n const hasVideo =\n localVideoTrackRef !== null && isTrackReference(localVideoTrackRef);\n\n const state: UserVideoState = {\n hasVideo,\n isCameraEnabled,\n trackRef: localVideoTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-user-video=\"\"\n data-avatar-has-video={hasVideo}\n data-avatar-camera-enabled={isCameraEnabled}\n data-avatar-mirror={mirror}\n >\n {hasVideo &&\n localVideoTrackRef &&\n isTrackReference(localVideoTrackRef) && (\n <VideoTrack trackRef={localVideoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\n/**\n * AvatarCall Component\n *\n * High-level component that handles the complete session lifecycle.\n * Manages credential fetching, connection, and video display internally\n * with a seamless loading experience.\n *\n * @example\n * ```tsx\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\">\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarCall>\n * ```\n */\n\nimport { useCredentials } from '../hooks/useCredentials';\nimport { useLatest } from '../hooks/useLatest';\nimport type { AvatarCallProps } from '../types';\nimport { AvatarSession, LoadingSessionProvider } from './AvatarSession';\nimport { AvatarVideo } from './AvatarVideo';\nimport { ControlBar } from './ControlBar';\nimport { UserVideo } from './UserVideo';\n\nexport function AvatarCall({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n avatarImageUrl,\n onEnd,\n onError,\n children,\n __unstable_roomOptions,\n ...props\n}: AvatarCallProps) {\n const onErrorRef = useLatest(onError);\n\n const credentialsState = useCredentials({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n onError: (err) => onErrorRef.current?.(err),\n });\n\n const handleSessionError = (err: Error) => {\n onErrorRef.current?.(err);\n };\n\n const backgroundStyle = avatarImageUrl\n ? ({ '--avatar-image': `url(${avatarImageUrl})` } as React.CSSProperties)\n : undefined;\n\n const defaultChildren = (\n <>\n <AvatarVideo />\n <UserVideo />\n <ControlBar />\n </>\n );\n\n if (credentialsState.status !== 'ready') {\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <LoadingSessionProvider\n state={credentialsState.status === 'error' ? 'error' : 'connecting'}\n error={credentialsState.error}\n >\n {children ?? defaultChildren}\n </LoadingSessionProvider>\n </div>\n );\n }\n\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <AvatarSession\n credentials={credentialsState.credentials}\n onEnd={onEnd}\n onError={handleSessionError}\n __unstable_roomOptions={__unstable_roomOptions}\n >\n {children ?? defaultChildren}\n </AvatarSession>\n </div>\n );\n}\n","'use client';\n\nimport {\n isTrackReference,\n type TrackReferenceOrPlaceholder,\n useLocalParticipant,\n useMaybeRoomContext,\n useTracks,\n VideoTrack,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nexport interface ScreenShareVideoState {\n isSharing: boolean;\n trackRef: TrackReferenceOrPlaceholder | null;\n}\n\nexport interface ScreenShareVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (state: ScreenShareVideoState) => ReactNode;\n}\n\nexport function ScreenShareVideo({\n children,\n ...props\n}: ScreenShareVideoProps) {\n const room = useMaybeRoomContext();\n const hasRoomContext = room !== undefined;\n\n const { localParticipant } = useLocalParticipant({ room });\n\n const tracks = useTracks(\n [{ source: Track.Source.ScreenShare, withPlaceholder: false }],\n { onlySubscribed: false, room: hasRoomContext ? room : undefined },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const screenShareTrackRef = hasRoomContext\n ? (tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.ScreenShare,\n ) ?? null)\n : null;\n\n const isSharing =\n screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);\n\n const state: ScreenShareVideoState = {\n isSharing,\n trackRef: screenShareTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isSharing) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-screen-share=\"\" data-avatar-sharing={isSharing}>\n {screenShareTrackRef && isTrackReference(screenShareTrackRef) && (\n <VideoTrack trackRef={screenShareTrackRef} />\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts","../src/hooks/useLatest.ts","../src/hooks/useCredentials.ts","../src/components/AvatarSession.tsx","../src/hooks/useAvatar.ts","../src/hooks/useAvatarSession.ts","../src/hooks/useAvatarStatus.ts","../src/components/AvatarVideo.tsx","../src/hooks/useLocalMedia.ts","../src/components/ControlBar.tsx","../src/components/UserVideo.tsx","../src/components/AvatarCall.tsx","../src/components/ScreenShareVideo.tsx"],"names":["useRef","useEffect","useState","RoomAudioRenderer","jsx","isTrackReference","useCallback","useTracks","Track","Fragment","jsxs","VideoTrack","useLocalParticipant"],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { DEFAULT_BASE_URL } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nexport function useLatest<T>(value: T): React.RefObject<T> {\n const ref = useRef(value);\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { consumeSession } from '../api/consume';\nimport type { SessionCredentials } from '../types';\nimport { useLatest } from './useLatest';\n\nexport interface UseCredentialsOptions {\n avatarId: string;\n sessionId?: string;\n sessionKey?: string;\n credentials?: SessionCredentials;\n connectUrl?: string;\n connect?: (avatarId: string) => Promise<SessionCredentials>;\n baseUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport type CredentialsState =\n | { status: 'loading'; credentials: null; error: null }\n | { status: 'ready'; credentials: SessionCredentials; error: null }\n | { status: 'error'; credentials: null; error: Error };\n\nasync function fetchCredentials(\n options: UseCredentialsOptions,\n): Promise<SessionCredentials> {\n const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } =\n options;\n\n if (sessionId && sessionKey) {\n const { url, token, roomName } = await consumeSession({\n sessionId,\n sessionKey,\n baseUrl,\n });\n return { sessionId, serverUrl: url, token, roomName };\n }\n\n if (connect) {\n return connect(avatarId);\n }\n\n if (connectUrl) {\n const response = await fetch(connectUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ avatarId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to connect: ${response.status} ${errorText}`);\n }\n\n return response.json();\n }\n\n throw new Error(\n 'AvatarCall requires one of: credentials, sessionId+sessionKey, connectUrl, or connect',\n );\n}\n\nexport function useCredentials(\n options: UseCredentialsOptions,\n): CredentialsState {\n const {\n credentials: directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n onError,\n } = options;\n\n const onErrorRef = useLatest(onError);\n const connectRef = useLatest(connect);\n\n const fetchedKeyRef = useRef<string | null>(null);\n\n const [state, setState] = useState<CredentialsState>(() => {\n if (directCredentials) {\n return { status: 'ready', credentials: directCredentials, error: null };\n }\n return { status: 'loading', credentials: null, error: null };\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs are stable - we read .current at call time\n useEffect(() => {\n if (directCredentials) {\n setState({\n status: 'ready',\n credentials: directCredentials,\n error: null,\n });\n return;\n }\n\n const credentialKey = `${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;\n\n if (fetchedKeyRef.current === credentialKey) return;\n fetchedKeyRef.current = credentialKey;\n\n let cancelled = false;\n setState({ status: 'loading', credentials: null, error: null });\n\n async function load() {\n try {\n const fetchOptions: UseCredentialsOptions = {\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect: connectRef.current ?? undefined,\n baseUrl,\n };\n const credentials = await fetchCredentials(fetchOptions);\n if (!cancelled) {\n setState({ status: 'ready', credentials, error: null });\n }\n } catch (err) {\n if (!cancelled) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState({ status: 'error', credentials: null, error });\n onErrorRef.current?.(error);\n }\n }\n }\n\n load();\n\n return () => {\n cancelled = true;\n };\n }, [directCredentials, avatarId, sessionId, sessionKey, connectUrl, baseUrl]);\n\n return state;\n}\n","'use client';\n\n/**\n * AvatarSession Component\n *\n * Provides the session context for avatar interactions.\n * Manages the WebRTC connection and exposes a clean API for child components.\n *\n * @example\n * ```tsx\n * <AvatarSession credentials={credentials} onEnd={handleEnd}>\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarSession>\n * ```\n */\n\nimport {\n LiveKitRoom,\n RoomAudioRenderer,\n useConnectionState,\n useRoomContext,\n} from '@livekit/components-react';\nimport type { RoomOptions } from 'livekit-client';\nimport { ConnectionState } from 'livekit-client';\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n AvatarSessionContextValue,\n AvatarSessionProps,\n SessionState,\n} from '../types';\n\n/**\n * Check if a media device of the given kind is available\n * Returns within timeout to avoid blocking the connection\n */\nasync function hasMediaDevice(\n kind: 'audioinput' | 'videoinput',\n timeoutMs = 1000,\n): Promise<boolean> {\n try {\n const timeoutPromise = new Promise<boolean>((resolve) =>\n setTimeout(() => resolve(false), timeoutMs),\n );\n const checkPromise = navigator.mediaDevices\n .enumerateDevices()\n .then((devices) => devices.some((device) => device.kind === kind));\n\n return await Promise.race([checkPromise, timeoutPromise]);\n } catch {\n return false;\n }\n}\n\n/**\n * Hook to check device availability before connecting.\n * Completes quickly to avoid blocking the connection.\n */\nfunction useDeviceAvailability(\n requestAudio: boolean,\n requestVideo: boolean,\n): { audio: boolean; video: boolean } {\n const [state, setState] = useState({\n audio: requestAudio, // Optimistically assume devices exist\n video: requestVideo,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function checkDevices() {\n const [hasAudio, hasVideo] = await Promise.all([\n requestAudio ? hasMediaDevice('audioinput') : Promise.resolve(false),\n requestVideo ? hasMediaDevice('videoinput') : Promise.resolve(false),\n ]);\n\n if (!cancelled) {\n setState({\n audio: requestAudio && hasAudio,\n video: requestVideo && hasVideo,\n });\n }\n }\n\n checkDevices();\n\n return () => {\n cancelled = true;\n };\n }, [requestAudio, requestVideo]);\n\n return state;\n}\n\nconst DEFAULT_ROOM_OPTIONS: RoomOptions = {\n adaptiveStream: false,\n dynacast: false,\n};\n\n/**\n * Maps WebRTC connection state to session state\n */\nfunction mapConnectionState(connectionState: ConnectionState): SessionState {\n switch (connectionState) {\n case ConnectionState.Connecting:\n return 'connecting';\n case ConnectionState.Connected:\n return 'active';\n case ConnectionState.Reconnecting:\n return 'connecting';\n case ConnectionState.Disconnected:\n return 'ended';\n default:\n return 'ended';\n }\n}\n\nconst AvatarSessionContext = createContext<AvatarSessionContextValue | null>(\n null,\n);\n\n/**\n * AvatarSession component - the main entry point for avatar sessions\n *\n * Establishes a WebRTC connection and provides session state to children.\n * This is a headless component that renders minimal DOM.\n */\nexport function AvatarSession({\n credentials,\n children,\n audio: requestAudio = true,\n video: requestVideo = true,\n onEnd,\n onError,\n __unstable_roomOptions,\n}: AvatarSessionProps) {\n const errorRef = useRef<Error | null>(null);\n\n const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);\n\n const handleError = (error: Error) => {\n errorRef.current = error;\n onError?.(error);\n };\n\n const roomOptions = {\n ...DEFAULT_ROOM_OPTIONS,\n ...__unstable_roomOptions,\n };\n\n return (\n <LiveKitRoom\n serverUrl={credentials.serverUrl}\n token={credentials.token}\n connect={true}\n audio={deviceAvailability.audio}\n video={deviceAvailability.video}\n onDisconnected={() => onEnd?.()}\n onError={handleError}\n options={roomOptions}\n connectOptions={{\n autoSubscribe: true,\n }}\n >\n <AvatarSessionContextInner\n sessionId={credentials.sessionId}\n onEnd={onEnd}\n errorRef={errorRef}\n >\n {children}\n </AvatarSessionContextInner>\n <RoomAudioRenderer />\n </LiveKitRoom>\n );\n}\n\n/**\n * Inner context provider that has access to the room context\n */\nfunction AvatarSessionContextInner({\n sessionId,\n onEnd,\n errorRef,\n children,\n}: {\n sessionId: string;\n onEnd?: () => void;\n errorRef: React.RefObject<Error | null>;\n children: ReactNode;\n}) {\n const room = useRoomContext();\n const connectionState = useConnectionState();\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n const end = useCallback(async () => {\n try {\n // Send END_CALL message to the avatar\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({ type: 'END_CALL' }));\n await room.localParticipant.publishData(data, { reliable: true });\n } catch {\n // Ignore errors when sending end message\n }\n\n await room.disconnect();\n onEndRef.current?.();\n }, [room]);\n\n const contextValue: AvatarSessionContextValue = {\n state: mapConnectionState(connectionState),\n sessionId,\n error: errorRef.current,\n end,\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n\n/**\n * Hook to access the avatar session context\n * Must be used within an AvatarSession component\n */\nexport function useAvatarSessionContext(): AvatarSessionContextValue {\n const context = useContext(AvatarSessionContext);\n if (!context) {\n throw new Error(\n 'useAvatarSessionContext must be used within an AvatarSession',\n );\n }\n return context;\n}\n\n/**\n * Hook to optionally access the avatar session context\n * Returns null if not within an AvatarSession\n */\nexport function useMaybeAvatarSessionContext(): AvatarSessionContextValue | null {\n return useContext(AvatarSessionContext);\n}\n","'use client';\n\n/**\n * useAvatar Hook\n *\n * Provides access to the remote avatar participant's video track.\n * Audio is handled automatically by the session.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n *\n * @example\n * ```tsx\n * function AvatarDisplay() {\n * const { videoTrackRef, hasVideo } = useAvatar();\n *\n * if (!hasVideo) {\n * return <Placeholder />;\n * }\n *\n * return <VideoTrack trackRef={videoTrackRef} />;\n * }\n * ```\n */\n\nimport {\n isTrackReference,\n useRemoteParticipants,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { UseAvatarReturn } from '../types';\n\n/**\n * Hook to access the remote avatar participant's video track\n *\n * @returns Avatar participant info and video track reference\n */\nexport function useAvatar(): UseAvatarReturn {\n const remoteParticipants = useRemoteParticipants();\n const avatarParticipant = remoteParticipants[0] ?? null;\n\n // Only subscribe to video - audio is handled automatically by the session\n const videoTracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: true,\n updateOnlyOn: [],\n },\n ).filter((ref) => !ref.participant.isLocal);\n\n const videoTrackRef = videoTracks[0] ?? null;\n const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);\n\n return {\n participant: avatarParticipant,\n videoTrackRef,\n hasVideo,\n };\n}\n","'use client';\n\n/**\n * useAvatarSession Hook\n *\n * Provides access to the current avatar session state.\n * Returns a discriminated union based on session state for type-safe UI rendering.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const session = useAvatarSession();\n *\n * if (session.state === 'connecting') {\n * return <Loading />;\n * }\n *\n * if (session.state === 'error') {\n * return <Error message={session.error.message} />;\n * }\n *\n * return <ActiveSession onEnd={session.end} />;\n * }\n * ```\n */\n\nimport { useAvatarSessionContext } from '../components/AvatarSession';\nimport type { AvatarSessionContextValue } from '../types';\n\n/**\n * Discriminated union types for type-safe session state handling\n */\nexport type UseAvatarSessionReturn =\n | { state: 'idle'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'connecting'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'active'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ending'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ended'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'error'; sessionId: string; error: Error; end: () => Promise<void> };\n\n/**\n * Hook to access the current avatar session state\n *\n * @returns Session state as a discriminated union\n */\nexport function useAvatarSession(): UseAvatarSessionReturn {\n const context = useAvatarSessionContext();\n return context as UseAvatarSessionReturn;\n}\n\nexport type { AvatarSessionContextValue };\n","'use client';\n\n/**\n * useAvatarStatus Hook\n *\n * Returns a single discriminated union representing the full avatar lifecycle\n * inside an AvatarSession. Combines session connection state and video\n * track availability into one status value.\n *\n * Must be used within <AvatarCall> or <AvatarSession>.\n *\n * @example\n * ```tsx\n * function MyAvatar() {\n * const avatar = useAvatarStatus();\n *\n * switch (avatar.status) {\n * case 'connecting':\n * return <Spinner />;\n * case 'waiting':\n * return <p>Waiting for video...</p>;\n * case 'ready':\n * return <VideoTrack trackRef={avatar.videoTrackRef} />;\n * case 'error':\n * return <p>{avatar.error.message}</p>;\n * case 'ended':\n * return <p>Call ended</p>;\n * }\n * }\n * ```\n */\n\nimport type { TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport { useAvatar } from './useAvatar';\nimport { useAvatarSession } from './useAvatarSession';\n\nexport type AvatarStatus =\n | { status: 'connecting' }\n | { status: 'waiting' }\n | { status: 'ready'; videoTrackRef: TrackReferenceOrPlaceholder }\n | { status: 'ending' }\n | { status: 'ended' }\n | { status: 'error'; error: Error };\n\nexport function useAvatarStatus(): AvatarStatus {\n const session = useAvatarSession();\n const { videoTrackRef, hasVideo } = useAvatar();\n\n switch (session.state) {\n case 'connecting':\n case 'idle':\n return { status: 'connecting' };\n\n case 'active':\n if (hasVideo && videoTrackRef) {\n return { status: 'ready', videoTrackRef };\n }\n return { status: 'waiting' };\n\n case 'ending':\n return { status: 'ending' };\n\n case 'ended':\n return { status: 'ended' };\n\n case 'error':\n return { status: 'error', error: session.error };\n }\n}\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { type AvatarStatus, useAvatarStatus } from '../hooks/useAvatarStatus';\n\n/** Subset of AvatarStatus relevant to the video display */\nexport type AvatarVideoStatus = Extract<\n AvatarStatus,\n { status: 'connecting' } | { status: 'waiting' } | { status: 'ready' }\n>;\n\nexport interface AvatarVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (status: AvatarVideoStatus) => ReactNode;\n}\n\nexport function AvatarVideo({ children, ...props }: AvatarVideoProps) {\n const avatar = useAvatarStatus();\n\n const videoStatus: AvatarVideoStatus =\n avatar.status === 'ready'\n ? avatar\n : avatar.status === 'connecting'\n ? { status: 'connecting' }\n : { status: 'waiting' };\n\n if (children) {\n return <>{children(videoStatus)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-video=\"\"\n data-avatar-status={videoStatus.status}\n >\n {videoStatus.status === 'ready' &&\n isTrackReference(videoStatus.videoTrackRef) && (\n <VideoTrack trackRef={videoStatus.videoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n useLocalParticipant,\n useMediaDevices,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport type { UseLocalMediaReturn } from '../types';\nimport { useLatest } from './useLatest';\n\n/**\n * Hook for local media controls (mic, camera, screen share).\n *\n * Must be used within an AvatarSession or AvatarCall component.\n * For use outside the session context, use AvatarSession directly\n * and manage your own loading states.\n */\nexport function useLocalMedia(): UseLocalMediaReturn {\n const { localParticipant } = useLocalParticipant();\n\n const audioDevices = useMediaDevices({ kind: 'audioinput' });\n const videoDevices = useMediaDevices({ kind: 'videoinput' });\n\n const hasMic = audioDevices?.length > 0;\n const hasCamera = videoDevices?.length > 0;\n\n const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;\n const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;\n const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;\n\n const isMicEnabledRef = useLatest(isMicEnabled);\n const isCameraEnabledRef = useLatest(isCameraEnabled);\n const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);\n\n const hasMicRef = useLatest(hasMic);\n const hasCameraRef = useLatest(hasCamera);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleMic = useCallback(() => {\n if (hasMicRef.current || isMicEnabledRef.current) {\n localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleCamera = useCallback(() => {\n if (hasCameraRef.current || isCameraEnabledRef.current) {\n localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleScreenShare = useCallback(() => {\n localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);\n }, [localParticipant]);\n\n const tracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: false,\n updateOnlyOn: [],\n },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const localVideoTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.Camera,\n ) ?? null;\n\n return {\n hasMic,\n hasCamera,\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n localVideoTrackRef,\n };\n}\n","'use client';\n\nimport { TrackToggle } from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useAvatarSession } from '../hooks/useAvatarSession';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\n\nexport interface ControlBarState {\n isMicEnabled: boolean;\n isCameraEnabled: boolean;\n isScreenShareEnabled: boolean;\n toggleMic: () => void;\n toggleCamera: () => void;\n toggleScreenShare: () => void;\n endCall: () => Promise<void>;\n isActive: boolean;\n}\n\nexport interface ControlBarProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n showMicrophone?: boolean;\n showCamera?: boolean;\n showScreenShare?: boolean;\n showEndCall?: boolean;\n children?: (state: ControlBarState) => ReactNode;\n}\n\nexport function ControlBar({\n children,\n showMicrophone = true,\n showCamera = true,\n showScreenShare = false,\n showEndCall = true,\n ...props\n}: ControlBarProps) {\n const session = useAvatarSession();\n const {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n } = useLocalMedia();\n\n const isActive = session.state === 'active';\n\n const state: ControlBarState = {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n endCall: session.end,\n isActive,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isActive) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-control-bar=\"\" data-avatar-active={isActive}>\n {showMicrophone && (\n <button\n type=\"button\"\n onClick={toggleMic}\n data-avatar-control=\"microphone\"\n data-avatar-enabled={isMicEnabled}\n aria-label={isMicEnabled ? 'Mute microphone' : 'Unmute microphone'}\n >\n {microphoneIcon}\n </button>\n )}\n {showCamera && (\n <button\n type=\"button\"\n onClick={toggleCamera}\n data-avatar-control=\"camera\"\n data-avatar-enabled={isCameraEnabled}\n aria-label={isCameraEnabled ? 'Turn off camera' : 'Turn on camera'}\n >\n {cameraIcon}\n </button>\n )}\n {showScreenShare && (\n <TrackToggle\n source={Track.Source.ScreenShare}\n showIcon={false}\n data-avatar-control=\"screen-share\"\n data-avatar-enabled={isScreenShareEnabled}\n aria-label=\"Toggle screen share\"\n >\n {screenShareIcon}\n </TrackToggle>\n )}\n {showEndCall && (\n <button\n type=\"button\"\n onClick={session.end}\n data-avatar-control=\"end-call\"\n data-avatar-enabled={true}\n aria-label=\"End call\"\n >\n {phoneIcon}\n </button>\n )}\n </div>\n );\n}\n\n// Lucide icons (https://lucide.dev) - MIT License\nconst microphoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n);\n\nconst cameraIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n);\n\nconst screenShareIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n);\n\nconst phoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"8 14 24 12\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12.8429 22.5693L11.4018 21.0986C11.2675 20.9626 11.1625 20.7995 11.0935 20.6197C11.0245 20.4399 10.9931 20.2474 11.0013 20.0545C11.0094 19.8616 11.0569 19.6726 11.1408 19.4995C11.2247 19.3265 11.343 19.1732 11.4883 19.0495C13.127 17.7049 15.0519 16.7714 17.1083 16.3239C19.0064 15.892 20.9744 15.892 22.8725 16.3239C24.9374 16.7743 26.8693 17.7147 28.5117 19.0691C28.6565 19.1924 28.7746 19.3451 28.8585 19.5176C28.9423 19.69 28.99 19.8784 28.9986 20.0707C29.0072 20.263 28.9764 20.455 28.9083 20.6345C28.8402 20.814 28.7362 20.9771 28.603 21.1133L27.1619 22.584C26.9311 22.8242 26.6226 22.9706 26.2938 22.9959C25.9651 23.0211 25.6385 22.9235 25.3751 22.7212C24.8531 22.3127 24.2875 21.9657 23.689 21.6869C23.4525 21.5774 23.2517 21.4009 23.1103 21.1785C22.969 20.9561 22.8931 20.697 22.8917 20.4319V19.1867C21.0053 18.6573 19.0139 18.6573 17.1275 19.1867V20.4319C17.1261 20.697 17.0502 20.9561 16.9089 21.1785C16.7676 21.4009 16.5667 21.5774 16.3302 21.6869C15.7317 21.9657 15.1661 22.3127 14.6442 22.7212C14.3779 22.9258 14.0473 23.0233 13.7152 22.9953C13.383 22.9673 13.0726 22.8156 12.8429 22.5693Z\" />\n </svg>\n);\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\nimport type { UseLocalMediaReturn } from '../types';\n\nexport interface UserVideoState {\n hasVideo: boolean;\n isCameraEnabled: boolean;\n trackRef: UseLocalMediaReturn['localVideoTrackRef'];\n}\n\nexport interface UserVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n mirror?: boolean;\n children?: (state: UserVideoState) => ReactNode;\n}\n\nexport function UserVideo({\n children,\n mirror = true,\n ...props\n}: UserVideoProps) {\n const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();\n\n const hasVideo =\n localVideoTrackRef !== null && isTrackReference(localVideoTrackRef);\n\n const state: UserVideoState = {\n hasVideo,\n isCameraEnabled,\n trackRef: localVideoTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-user-video=\"\"\n data-avatar-has-video={hasVideo}\n data-avatar-camera-enabled={isCameraEnabled}\n data-avatar-mirror={mirror}\n >\n {hasVideo &&\n localVideoTrackRef &&\n isTrackReference(localVideoTrackRef) && (\n <VideoTrack trackRef={localVideoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\n/**\n * AvatarCall Component\n *\n * High-level component that handles the complete session lifecycle.\n * Manages credential fetching, connection, and video display internally\n * with a seamless loading experience.\n *\n * During credential loading, shows a loading state with the avatar image.\n * Once connected, renders children inside the session context.\n *\n * For more control over the loading UI, use AvatarSession directly.\n *\n * @example\n * ```tsx\n * // Simple usage - handles everything automatically\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\" />\n *\n * // Custom children - rendered once connected\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\">\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarCall>\n * ```\n */\n\nimport { useCredentials } from '../hooks/useCredentials';\nimport { useLatest } from '../hooks/useLatest';\nimport type { AvatarCallProps } from '../types';\nimport { AvatarSession } from './AvatarSession';\nimport { AvatarVideo } from './AvatarVideo';\nimport { ControlBar } from './ControlBar';\nimport { UserVideo } from './UserVideo';\n\nexport function AvatarCall({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n avatarImageUrl,\n onEnd,\n onError,\n children,\n __unstable_roomOptions,\n ...props\n}: AvatarCallProps) {\n const onErrorRef = useLatest(onError);\n\n const credentialsState = useCredentials({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n onError: (err) => onErrorRef.current?.(err),\n });\n\n const handleSessionError = (err: Error) => {\n onErrorRef.current?.(err);\n };\n\n const backgroundStyle = avatarImageUrl\n ? ({ '--avatar-image': `url(${avatarImageUrl})` } as React.CSSProperties)\n : undefined;\n\n const defaultChildren = (\n <>\n <AvatarVideo />\n <UserVideo />\n <ControlBar />\n </>\n );\n\n // During credential loading/error, show a simple loading state\n // Children are NOT rendered here because they may use hooks that require LiveKitRoom context\n if (credentialsState.status !== 'ready') {\n const status =\n credentialsState.status === 'error' ? 'error' : 'connecting';\n\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <div data-avatar-video=\"\" data-avatar-status={status} />\n </div>\n );\n }\n\n // Once credentials are ready, render children inside the session context\n // This ensures all hooks have access to the LiveKitRoom context\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <AvatarSession\n credentials={credentialsState.credentials}\n onEnd={onEnd}\n onError={handleSessionError}\n __unstable_roomOptions={__unstable_roomOptions}\n >\n {children ?? defaultChildren}\n </AvatarSession>\n </div>\n );\n}\n","'use client';\n\nimport {\n isTrackReference,\n type TrackReferenceOrPlaceholder,\n useLocalParticipant,\n useTracks,\n VideoTrack,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nexport interface ScreenShareVideoState {\n isSharing: boolean;\n trackRef: TrackReferenceOrPlaceholder | null;\n}\n\nexport interface ScreenShareVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (state: ScreenShareVideoState) => ReactNode;\n}\n\n/**\n * Component for displaying local screen share video.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n */\nexport function ScreenShareVideo({\n children,\n ...props\n}: ScreenShareVideoProps) {\n const { localParticipant } = useLocalParticipant();\n\n const tracks = useTracks(\n [{ source: Track.Source.ScreenShare, withPlaceholder: false }],\n { onlySubscribed: false },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const screenShareTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.ScreenShare,\n ) ?? null;\n\n const isSharing =\n screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);\n\n const state: ScreenShareVideoState = {\n isSharing,\n trackRef: screenShareTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isSharing) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-screen-share=\"\" data-avatar-sharing={isSharing}>\n {screenShareTrackRef && isTrackReference(screenShareTrackRef) && (\n <VideoTrack trackRef={screenShareTrackRef} />\n )}\n </div>\n );\n}\n"]}
|
package/dist/styles.css
CHANGED
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
}
|
|
40
40
|
[data-avatar-video] {
|
|
41
41
|
flex: 1;
|
|
42
|
+
width: 100%;
|
|
43
|
+
min-height: 0;
|
|
42
44
|
display: flex;
|
|
43
45
|
align-items: center;
|
|
44
46
|
justify-content: center;
|
|
@@ -144,6 +146,27 @@
|
|
|
144
146
|
[data-avatar-user-video][data-avatar-mirror=true] video {
|
|
145
147
|
transform: scaleX(-1);
|
|
146
148
|
}
|
|
149
|
+
[data-avatar-user-video][data-avatar-has-video=false]::before {
|
|
150
|
+
content: "";
|
|
151
|
+
position: absolute;
|
|
152
|
+
top: 50%;
|
|
153
|
+
left: 50%;
|
|
154
|
+
transform: translate(-50%, -50%);
|
|
155
|
+
width: 40%;
|
|
156
|
+
height: 40%;
|
|
157
|
+
background-color: var(--avatar-text-secondary);
|
|
158
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z'/%3E%3C/svg%3E");
|
|
159
|
+
mask-size: contain;
|
|
160
|
+
mask-repeat: no-repeat;
|
|
161
|
+
mask-position: center;
|
|
162
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z'/%3E%3C/svg%3E");
|
|
163
|
+
-webkit-mask-size: contain;
|
|
164
|
+
-webkit-mask-repeat: no-repeat;
|
|
165
|
+
-webkit-mask-position: center;
|
|
166
|
+
}
|
|
167
|
+
[data-avatar-user-video][data-avatar-camera-enabled=false] {
|
|
168
|
+
display: none;
|
|
169
|
+
}
|
|
147
170
|
[data-avatar-screen-share] {
|
|
148
171
|
position: absolute;
|
|
149
172
|
inset: 0;
|
|
@@ -163,8 +186,8 @@
|
|
|
163
186
|
opacity: 0.5;
|
|
164
187
|
}
|
|
165
188
|
}
|
|
166
|
-
[data-avatar-video][data-avatar-status=connecting]::
|
|
167
|
-
[data-avatar-video][data-avatar-status=waiting]::
|
|
189
|
+
[data-avatar-call]:has([data-avatar-video][data-avatar-status=connecting])::after,
|
|
190
|
+
[data-avatar-call]:has([data-avatar-video][data-avatar-status=waiting])::after {
|
|
168
191
|
content: "";
|
|
169
192
|
position: absolute;
|
|
170
193
|
top: 50%;
|
|
@@ -176,7 +199,8 @@
|
|
|
176
199
|
border-top-color: rgba(255, 255, 255, 0.8);
|
|
177
200
|
border-radius: 50%;
|
|
178
201
|
animation: avatar-spin 0.8s linear infinite;
|
|
179
|
-
z-index:
|
|
202
|
+
z-index: 3;
|
|
203
|
+
pointer-events: none;
|
|
180
204
|
}
|
|
181
205
|
@keyframes avatar-spin {
|
|
182
206
|
from {
|
|
@@ -201,8 +225,8 @@
|
|
|
201
225
|
animation: avatar-pulse 2s ease-in-out infinite;
|
|
202
226
|
}
|
|
203
227
|
@media (prefers-reduced-motion: reduce) {
|
|
204
|
-
[data-avatar-video][data-avatar-status=connecting]::
|
|
205
|
-
[data-avatar-video][data-avatar-status=waiting]::
|
|
228
|
+
[data-avatar-call]:has([data-avatar-video][data-avatar-status=connecting])::after,
|
|
229
|
+
[data-avatar-call]:has([data-avatar-video][data-avatar-status=waiting])::after,
|
|
206
230
|
[data-avatar-video][data-avatar-status=connecting]::after,
|
|
207
231
|
[data-avatar-video][data-avatar-status=waiting]::after {
|
|
208
232
|
animation: none;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runwayml/avatars-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "React SDK for real-time AI avatar interactions with GWM-1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -53,7 +53,9 @@
|
|
|
53
53
|
"lint:fix": "biome lint --write src/",
|
|
54
54
|
"format": "biome format --write src/",
|
|
55
55
|
"check": "biome check src/",
|
|
56
|
-
"typecheck": "tsc --noEmit"
|
|
56
|
+
"typecheck": "tsc --noEmit",
|
|
57
|
+
"example:link": "bun run build && bun link && cd examples/react-router && bun link @runwayml/avatars-react",
|
|
58
|
+
"example:dev": "bun run example:link && cd examples/react-router && bun run dev"
|
|
57
59
|
},
|
|
58
60
|
"keywords": [
|
|
59
61
|
"runwayml",
|