@runwayml/avatars-react 0.1.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 ADDED
@@ -0,0 +1,636 @@
1
+ 'use strict';
2
+
3
+ var componentsReact = require('@livekit/components-react');
4
+ var react = require('react');
5
+ var livekitClient = require('livekit-client');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ // src/api/config.ts
9
+ var DEFAULT_BASE_URL = "https://api.dev.runwayml.com";
10
+ function getBaseUrl() {
11
+ try {
12
+ const envUrl = process.env.RUNWAYML_BASE_URL;
13
+ if (envUrl) return envUrl;
14
+ } catch {
15
+ }
16
+ return DEFAULT_BASE_URL;
17
+ }
18
+ var config = null;
19
+ function getConfig() {
20
+ if (!config) {
21
+ config = { baseUrl: getBaseUrl() };
22
+ }
23
+ return config;
24
+ }
25
+
26
+ // src/api/consume.ts
27
+ async function consumeSession(options) {
28
+ const { sessionId, sessionKey, baseUrl = getConfig().baseUrl } = options;
29
+ const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;
30
+ const response = await fetch(url, {
31
+ method: "POST",
32
+ headers: {
33
+ "Content-Type": "application/json",
34
+ Authorization: `Bearer ${sessionKey}`
35
+ }
36
+ });
37
+ if (!response.ok) {
38
+ const errorText = await response.text();
39
+ throw new Error(
40
+ `Failed to consume session: ${response.status} ${errorText}`
41
+ );
42
+ }
43
+ return response.json();
44
+ }
45
+
46
+ // src/hooks/useCredentials.ts
47
+ function credentialsReducer(_state, action) {
48
+ switch (action.type) {
49
+ case "CONNECT":
50
+ return { status: "connecting", credentials: null, error: null };
51
+ case "CONNECTED":
52
+ return {
53
+ status: "connected",
54
+ credentials: action.credentials,
55
+ error: null
56
+ };
57
+ case "ERROR":
58
+ return { status: "error", credentials: null, error: action.error };
59
+ }
60
+ }
61
+ function useCredentials(options) {
62
+ const {
63
+ avatarId,
64
+ sessionId,
65
+ sessionKey,
66
+ credentials: directCredentials,
67
+ connectUrl,
68
+ connect,
69
+ onError
70
+ } = options;
71
+ const [state, dispatch] = react.useReducer(credentialsReducer, {
72
+ status: "idle",
73
+ credentials: null,
74
+ error: null
75
+ });
76
+ const fetchedForRef = react.useRef(null);
77
+ const onErrorRef = react.useRef(onError);
78
+ onErrorRef.current = onError;
79
+ const mode = directCredentials ? "direct" : sessionId && sessionKey ? "session" : connectUrl || connect ? "connect" : null;
80
+ react.useEffect(() => {
81
+ if (mode !== "direct" || !directCredentials) return;
82
+ dispatch({ type: "CONNECTED", credentials: directCredentials });
83
+ }, [mode, directCredentials]);
84
+ react.useEffect(() => {
85
+ if (mode !== "session" || !sessionId || !sessionKey) return;
86
+ if (fetchedForRef.current === sessionId) return;
87
+ fetchedForRef.current = sessionId;
88
+ dispatch({ type: "CONNECT" });
89
+ consumeSession({ sessionId, sessionKey }).then(({ url, token, roomName }) => {
90
+ dispatch({
91
+ type: "CONNECTED",
92
+ credentials: { sessionId, serverUrl: url, token, roomName }
93
+ });
94
+ }).catch((err) => {
95
+ const error = err instanceof Error ? err : new Error(String(err));
96
+ dispatch({ type: "ERROR", error });
97
+ onErrorRef.current?.(error);
98
+ });
99
+ }, [mode, sessionId, sessionKey]);
100
+ react.useEffect(() => {
101
+ if (mode !== "connect") return;
102
+ if (fetchedForRef.current === avatarId) return;
103
+ fetchedForRef.current = avatarId;
104
+ dispatch({ type: "CONNECT" });
105
+ async function fetchCredentials() {
106
+ if (connect) {
107
+ return connect(avatarId);
108
+ }
109
+ if (connectUrl) {
110
+ const response = await fetch(connectUrl, {
111
+ method: "POST",
112
+ headers: { "Content-Type": "application/json" },
113
+ body: JSON.stringify({ avatarId })
114
+ });
115
+ if (!response.ok) {
116
+ const errorText = await response.text();
117
+ throw new Error(`Failed to connect: ${response.status} ${errorText}`);
118
+ }
119
+ return response.json();
120
+ }
121
+ throw new Error("No connect method available");
122
+ }
123
+ fetchCredentials().then((credentials) => {
124
+ dispatch({ type: "CONNECTED", credentials });
125
+ }).catch((err) => {
126
+ const error = err instanceof Error ? err : new Error(String(err));
127
+ dispatch({ type: "ERROR", error });
128
+ onErrorRef.current?.(error);
129
+ });
130
+ }, [mode, avatarId, connectUrl, connect]);
131
+ return state;
132
+ }
133
+ function useLatest(value) {
134
+ const ref = react.useRef(value);
135
+ react.useEffect(() => {
136
+ ref.current = value;
137
+ }, [value]);
138
+ return ref;
139
+ }
140
+ function mapConnectionState(connectionState) {
141
+ switch (connectionState) {
142
+ case livekitClient.ConnectionState.Connecting:
143
+ return "connecting";
144
+ case livekitClient.ConnectionState.Connected:
145
+ return "active";
146
+ case livekitClient.ConnectionState.Reconnecting:
147
+ return "connecting";
148
+ case livekitClient.ConnectionState.Disconnected:
149
+ return "ended";
150
+ default:
151
+ return "ended";
152
+ }
153
+ }
154
+ var AvatarSessionContext = react.createContext(
155
+ null
156
+ );
157
+ function AvatarSession({
158
+ credentials,
159
+ children,
160
+ audio = true,
161
+ video = true,
162
+ onEnd,
163
+ onError
164
+ }) {
165
+ const errorRef = react.useRef(null);
166
+ const handleError = (error) => {
167
+ errorRef.current = error;
168
+ onError?.(error);
169
+ };
170
+ return /* @__PURE__ */ jsxRuntime.jsxs(
171
+ componentsReact.LiveKitRoom,
172
+ {
173
+ serverUrl: credentials.serverUrl,
174
+ token: credentials.token,
175
+ connect: true,
176
+ audio,
177
+ video,
178
+ onDisconnected: () => onEnd?.(),
179
+ onError: handleError,
180
+ options: {
181
+ adaptiveStream: true,
182
+ dynacast: true
183
+ },
184
+ children: [
185
+ /* @__PURE__ */ jsxRuntime.jsx(
186
+ AvatarSessionContextInner,
187
+ {
188
+ sessionId: credentials.sessionId,
189
+ onEnd,
190
+ errorRef,
191
+ children
192
+ }
193
+ ),
194
+ /* @__PURE__ */ jsxRuntime.jsx(componentsReact.RoomAudioRenderer, {})
195
+ ]
196
+ }
197
+ );
198
+ }
199
+ function AvatarSessionContextInner({
200
+ sessionId,
201
+ onEnd,
202
+ errorRef,
203
+ children
204
+ }) {
205
+ const room = componentsReact.useRoomContext();
206
+ const connectionState = componentsReact.useConnectionState();
207
+ const onEndRef = react.useRef(onEnd);
208
+ onEndRef.current = onEnd;
209
+ const end = react.useCallback(async () => {
210
+ try {
211
+ const encoder = new TextEncoder();
212
+ const data = encoder.encode(JSON.stringify({ type: "END_CALL" }));
213
+ await room.localParticipant.publishData(data, { reliable: true });
214
+ } catch {
215
+ }
216
+ await room.disconnect();
217
+ onEndRef.current?.();
218
+ }, [room]);
219
+ const contextValue = {
220
+ state: mapConnectionState(connectionState),
221
+ sessionId,
222
+ error: errorRef.current,
223
+ end
224
+ };
225
+ return /* @__PURE__ */ jsxRuntime.jsx(AvatarSessionContext.Provider, { value: contextValue, children });
226
+ }
227
+ function useAvatarSessionContext() {
228
+ const context = react.useContext(AvatarSessionContext);
229
+ if (!context) {
230
+ throw new Error(
231
+ "useAvatarSessionContext must be used within an AvatarSession"
232
+ );
233
+ }
234
+ return context;
235
+ }
236
+ function useAvatar() {
237
+ const remoteParticipants = componentsReact.useRemoteParticipants();
238
+ const avatarParticipant = remoteParticipants[0] ?? null;
239
+ const avatarIdentity = avatarParticipant?.identity ?? null;
240
+ const [isSpeaking, setIsSpeaking] = react.useState(false);
241
+ react.useEffect(() => {
242
+ if (!avatarParticipant) {
243
+ setIsSpeaking(false);
244
+ return;
245
+ }
246
+ setIsSpeaking(avatarParticipant.isSpeaking);
247
+ const handleIsSpeakingChanged = (speaking) => {
248
+ setIsSpeaking(speaking);
249
+ };
250
+ avatarParticipant.on(
251
+ livekitClient.ParticipantEvent.IsSpeakingChanged,
252
+ handleIsSpeakingChanged
253
+ );
254
+ return () => {
255
+ avatarParticipant.off(
256
+ livekitClient.ParticipantEvent.IsSpeakingChanged,
257
+ handleIsSpeakingChanged
258
+ );
259
+ };
260
+ }, [avatarParticipant]);
261
+ const tracks = componentsReact.useTracks(
262
+ [
263
+ { source: livekitClient.Track.Source.Camera, withPlaceholder: true },
264
+ { source: livekitClient.Track.Source.Microphone, withPlaceholder: true }
265
+ ],
266
+ { onlySubscribed: true }
267
+ );
268
+ let videoTrackRef = null;
269
+ let audioTrackRef = null;
270
+ for (const trackRef of tracks) {
271
+ if (trackRef.participant.identity !== avatarIdentity) continue;
272
+ if (trackRef.source === livekitClient.Track.Source.Camera && !videoTrackRef) {
273
+ videoTrackRef = trackRef;
274
+ } else if (trackRef.source === livekitClient.Track.Source.Microphone && !audioTrackRef) {
275
+ audioTrackRef = trackRef;
276
+ }
277
+ if (videoTrackRef && audioTrackRef) break;
278
+ }
279
+ const hasVideo = videoTrackRef !== null && componentsReact.isTrackReference(videoTrackRef);
280
+ const hasAudio = audioTrackRef !== null && componentsReact.isTrackReference(audioTrackRef);
281
+ return {
282
+ participant: avatarParticipant,
283
+ videoTrackRef,
284
+ audioTrackRef,
285
+ isSpeaking,
286
+ hasVideo,
287
+ hasAudio
288
+ };
289
+ }
290
+
291
+ // src/hooks/useAvatarSession.ts
292
+ function useAvatarSession() {
293
+ const context = useAvatarSessionContext();
294
+ return context;
295
+ }
296
+ function AvatarVideo({ children, ...props }) {
297
+ const session = useAvatarSession();
298
+ const { videoTrackRef, isSpeaking, hasVideo } = useAvatar();
299
+ const isConnecting = session.state === "connecting";
300
+ const state = {
301
+ hasVideo,
302
+ isConnecting,
303
+ isSpeaking,
304
+ trackRef: videoTrackRef
305
+ };
306
+ if (children) {
307
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(state) });
308
+ }
309
+ return /* @__PURE__ */ jsxRuntime.jsx(
310
+ "div",
311
+ {
312
+ ...props,
313
+ "data-has-video": hasVideo,
314
+ "data-connecting": isConnecting,
315
+ "data-speaking": isSpeaking,
316
+ children: hasVideo && videoTrackRef && componentsReact.isTrackReference(videoTrackRef) && /* @__PURE__ */ jsxRuntime.jsx(componentsReact.VideoTrack, { trackRef: videoTrackRef })
317
+ }
318
+ );
319
+ }
320
+ function useLocalMedia() {
321
+ const { localParticipant } = componentsReact.useLocalParticipant();
322
+ const audioDevices = componentsReact.useMediaDevices({ kind: "audioinput" });
323
+ const videoDevices = componentsReact.useMediaDevices({ kind: "videoinput" });
324
+ const hasMic = audioDevices.length > 0;
325
+ const hasCamera = videoDevices.length > 0;
326
+ const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;
327
+ const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;
328
+ const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;
329
+ const isMicEnabledRef = useLatest(isMicEnabled);
330
+ const isCameraEnabledRef = useLatest(isCameraEnabled);
331
+ const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);
332
+ const toggleMic = react.useCallback(() => {
333
+ localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);
334
+ }, [localParticipant, isMicEnabledRef]);
335
+ const toggleCamera = react.useCallback(() => {
336
+ localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);
337
+ }, [localParticipant, isCameraEnabledRef]);
338
+ const toggleScreenShare = react.useCallback(() => {
339
+ localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);
340
+ }, [localParticipant, isScreenShareEnabledRef]);
341
+ const tracks = componentsReact.useTracks(
342
+ [{ source: livekitClient.Track.Source.Camera, withPlaceholder: true }],
343
+ {
344
+ onlySubscribed: false
345
+ }
346
+ );
347
+ const localIdentity = localParticipant?.identity;
348
+ const localVideoTrackRef = tracks.find(
349
+ (trackRef) => trackRef.participant.identity === localIdentity && trackRef.source === livekitClient.Track.Source.Camera
350
+ ) ?? null;
351
+ return {
352
+ hasMic,
353
+ hasCamera,
354
+ isMicEnabled,
355
+ isCameraEnabled,
356
+ isScreenShareEnabled,
357
+ toggleMic,
358
+ toggleCamera,
359
+ toggleScreenShare,
360
+ localVideoTrackRef
361
+ };
362
+ }
363
+ function ControlBar({
364
+ children,
365
+ showMicrophone = true,
366
+ showCamera = true,
367
+ showScreenShare = false,
368
+ showEndCall = true,
369
+ ...props
370
+ }) {
371
+ const session = useAvatarSession();
372
+ const { isMicEnabled, isCameraEnabled, toggleMic, toggleCamera } = useLocalMedia();
373
+ const isActive = session.state === "active";
374
+ const state = {
375
+ isMicEnabled,
376
+ isCameraEnabled,
377
+ toggleMic,
378
+ toggleCamera,
379
+ endCall: session.end,
380
+ isActive
381
+ };
382
+ if (children) {
383
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(state) });
384
+ }
385
+ if (!isActive) {
386
+ return null;
387
+ }
388
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...props, "data-active": isActive, children: [
389
+ showMicrophone && /* @__PURE__ */ jsxRuntime.jsx(
390
+ "button",
391
+ {
392
+ type: "button",
393
+ onClick: toggleMic,
394
+ "data-control": "microphone",
395
+ "data-enabled": isMicEnabled,
396
+ "aria-label": isMicEnabled ? "Mute microphone" : "Unmute microphone",
397
+ children: microphoneIcon
398
+ }
399
+ ),
400
+ showCamera && /* @__PURE__ */ jsxRuntime.jsx(
401
+ "button",
402
+ {
403
+ type: "button",
404
+ onClick: toggleCamera,
405
+ "data-control": "camera",
406
+ "data-enabled": isCameraEnabled,
407
+ "aria-label": isCameraEnabled ? "Turn off camera" : "Turn on camera",
408
+ children: cameraIcon
409
+ }
410
+ ),
411
+ showScreenShare && /* @__PURE__ */ jsxRuntime.jsx(
412
+ componentsReact.TrackToggle,
413
+ {
414
+ source: livekitClient.Track.Source.ScreenShare,
415
+ showIcon: false,
416
+ "data-control": "screen-share",
417
+ "aria-label": "Toggle screen share",
418
+ children: screenShareIcon
419
+ }
420
+ ),
421
+ showEndCall && /* @__PURE__ */ jsxRuntime.jsx(
422
+ "button",
423
+ {
424
+ type: "button",
425
+ onClick: session.end,
426
+ "data-control": "end-call",
427
+ "aria-label": "End call",
428
+ children: phoneIcon
429
+ }
430
+ )
431
+ ] });
432
+ }
433
+ var microphoneIcon = /* @__PURE__ */ jsxRuntime.jsxs(
434
+ "svg",
435
+ {
436
+ width: "20",
437
+ height: "20",
438
+ viewBox: "0 0 24 24",
439
+ fill: "none",
440
+ stroke: "currentColor",
441
+ strokeWidth: "2",
442
+ strokeLinecap: "round",
443
+ strokeLinejoin: "round",
444
+ "aria-hidden": "true",
445
+ children: [
446
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
447
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
448
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
449
+ ]
450
+ }
451
+ );
452
+ var cameraIcon = /* @__PURE__ */ jsxRuntime.jsxs(
453
+ "svg",
454
+ {
455
+ width: "20",
456
+ height: "20",
457
+ viewBox: "0 0 24 24",
458
+ fill: "none",
459
+ stroke: "currentColor",
460
+ strokeWidth: "2",
461
+ strokeLinecap: "round",
462
+ strokeLinejoin: "round",
463
+ "aria-hidden": "true",
464
+ children: [
465
+ /* @__PURE__ */ jsxRuntime.jsx("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" }),
466
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "6", width: "14", height: "12", rx: "2" })
467
+ ]
468
+ }
469
+ );
470
+ var screenShareIcon = /* @__PURE__ */ jsxRuntime.jsxs(
471
+ "svg",
472
+ {
473
+ width: "20",
474
+ height: "20",
475
+ viewBox: "0 0 24 24",
476
+ fill: "none",
477
+ stroke: "currentColor",
478
+ strokeWidth: "2",
479
+ strokeLinecap: "round",
480
+ strokeLinejoin: "round",
481
+ "aria-hidden": "true",
482
+ children: [
483
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "20", height: "14", x: "2", y: "3", rx: "2" }),
484
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", x2: "16", y1: "21", y2: "21" }),
485
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", x2: "12", y1: "17", y2: "21" })
486
+ ]
487
+ }
488
+ );
489
+ var phoneIcon = /* @__PURE__ */ jsxRuntime.jsx(
490
+ "svg",
491
+ {
492
+ width: "20",
493
+ height: "20",
494
+ viewBox: "8 14 24 12",
495
+ fill: "currentColor",
496
+ "aria-hidden": "true",
497
+ children: /* @__PURE__ */ jsxRuntime.jsx("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" })
498
+ }
499
+ );
500
+ function UserVideo({ children, mirror = true, ...props }) {
501
+ const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();
502
+ const hasVideo = localVideoTrackRef !== null && componentsReact.isTrackReference(localVideoTrackRef);
503
+ const state = {
504
+ hasVideo,
505
+ isCameraEnabled,
506
+ trackRef: localVideoTrackRef
507
+ };
508
+ if (children) {
509
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(state) });
510
+ }
511
+ return /* @__PURE__ */ jsxRuntime.jsx(
512
+ "div",
513
+ {
514
+ ...props,
515
+ "data-has-video": hasVideo,
516
+ "data-camera-enabled": isCameraEnabled,
517
+ "data-mirror": mirror,
518
+ children: hasVideo && localVideoTrackRef && componentsReact.isTrackReference(localVideoTrackRef) && /* @__PURE__ */ jsxRuntime.jsx(componentsReact.VideoTrack, { trackRef: localVideoTrackRef })
519
+ }
520
+ );
521
+ }
522
+ function AvatarCall({
523
+ avatarId,
524
+ sessionId,
525
+ sessionKey,
526
+ credentials: directCredentials,
527
+ connectUrl,
528
+ connect,
529
+ avatarImageUrl,
530
+ onEnd,
531
+ onError,
532
+ children,
533
+ ...props
534
+ }) {
535
+ const onErrorRef = useLatest(onError);
536
+ const { status, credentials, error } = useCredentials({
537
+ avatarId,
538
+ sessionId,
539
+ sessionKey,
540
+ credentials: directCredentials,
541
+ connectUrl,
542
+ connect,
543
+ onError
544
+ });
545
+ const handleSessionError = (err) => {
546
+ onErrorRef.current?.(err);
547
+ };
548
+ const backgroundStyle = avatarImageUrl ? { "--avatar-image": `url(${avatarImageUrl})` } : void 0;
549
+ if (status === "idle" || status === "connecting") {
550
+ return /* @__PURE__ */ jsxRuntime.jsx(
551
+ "div",
552
+ {
553
+ ...props,
554
+ "data-avatar-call": "",
555
+ "data-state": "connecting",
556
+ "data-avatar-id": avatarId,
557
+ style: { ...props.style, ...backgroundStyle }
558
+ }
559
+ );
560
+ }
561
+ if (status === "error" || !credentials) {
562
+ return /* @__PURE__ */ jsxRuntime.jsx(
563
+ "div",
564
+ {
565
+ ...props,
566
+ "data-avatar-call": "",
567
+ "data-state": "error",
568
+ "data-avatar-id": avatarId,
569
+ "data-error": error?.message,
570
+ style: { ...props.style, ...backgroundStyle }
571
+ }
572
+ );
573
+ }
574
+ return /* @__PURE__ */ jsxRuntime.jsx(
575
+ "div",
576
+ {
577
+ ...props,
578
+ "data-avatar-call": "",
579
+ "data-state": "connected",
580
+ "data-avatar-id": avatarId,
581
+ style: { ...props.style, ...backgroundStyle },
582
+ children: /* @__PURE__ */ jsxRuntime.jsx(
583
+ AvatarSession,
584
+ {
585
+ credentials,
586
+ onEnd,
587
+ onError: handleSessionError,
588
+ children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
589
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarVideo, {}),
590
+ /* @__PURE__ */ jsxRuntime.jsx(UserVideo, {}),
591
+ /* @__PURE__ */ jsxRuntime.jsx(ControlBar, {})
592
+ ] })
593
+ }
594
+ )
595
+ }
596
+ );
597
+ }
598
+ function ScreenShareVideo({ children, ...props }) {
599
+ const { localParticipant } = componentsReact.useLocalParticipant();
600
+ const tracks = componentsReact.useTracks(
601
+ [{ source: livekitClient.Track.Source.ScreenShare, withPlaceholder: false }],
602
+ { onlySubscribed: false }
603
+ );
604
+ const localIdentity = localParticipant?.identity;
605
+ const screenShareTrackRef = tracks.find(
606
+ (trackRef) => trackRef.participant.identity === localIdentity && trackRef.source === livekitClient.Track.Source.ScreenShare
607
+ ) ?? null;
608
+ const isSharing = screenShareTrackRef !== null && componentsReact.isTrackReference(screenShareTrackRef);
609
+ const state = {
610
+ isSharing,
611
+ trackRef: screenShareTrackRef
612
+ };
613
+ if (children) {
614
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(state) });
615
+ }
616
+ if (!isSharing) {
617
+ return null;
618
+ }
619
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, "data-sharing": isSharing, children: screenShareTrackRef && componentsReact.isTrackReference(screenShareTrackRef) && /* @__PURE__ */ jsxRuntime.jsx(componentsReact.VideoTrack, { trackRef: screenShareTrackRef }) });
620
+ }
621
+
622
+ Object.defineProperty(exports, "AudioRenderer", {
623
+ enumerable: true,
624
+ get: function () { return componentsReact.RoomAudioRenderer; }
625
+ });
626
+ exports.AvatarCall = AvatarCall;
627
+ exports.AvatarSession = AvatarSession;
628
+ exports.AvatarVideo = AvatarVideo;
629
+ exports.ControlBar = ControlBar;
630
+ exports.ScreenShareVideo = ScreenShareVideo;
631
+ exports.UserVideo = UserVideo;
632
+ exports.useAvatar = useAvatar;
633
+ exports.useAvatarSession = useAvatarSession;
634
+ exports.useLocalMedia = useLocalMedia;
635
+ //# sourceMappingURL=index.cjs.map
636
+ //# sourceMappingURL=index.cjs.map