@runwayml/avatars-react 0.2.2 → 0.5.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/README.md +9 -0
- package/dist/api.cjs +1 -25
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +1 -8
- package/dist/api.d.ts +1 -8
- package/dist/api.js +2 -23
- package/dist/api.js.map +1 -1
- package/dist/index.cjs +152 -148
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -9
- package/dist/index.d.ts +63 -9
- package/dist/index.js +150 -151
- package/dist/index.js.map +1 -1
- package/dist/styles.css +37 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,9 +56,18 @@ The styles use CSS custom properties for easy customization:
|
|
|
56
56
|
|
|
57
57
|
See [`examples/`](./examples) for complete working examples:
|
|
58
58
|
- [`nextjs`](./examples/nextjs) - Next.js App Router
|
|
59
|
+
- [`nextjs-server-actions`](./examples/nextjs-server-actions) - Next.js with Server Actions
|
|
59
60
|
- [`react-router`](./examples/react-router) - React Router v7 framework mode
|
|
60
61
|
- [`express`](./examples/express) - Express + Vite
|
|
61
62
|
|
|
63
|
+
Scaffold an example with one command:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx degit runwayml/avatars-sdk-react/examples/nextjs my-avatar-app
|
|
67
|
+
cd my-avatar-app
|
|
68
|
+
npm install
|
|
69
|
+
```
|
|
70
|
+
|
|
62
71
|
## How It Works
|
|
63
72
|
|
|
64
73
|
1. **Client** calls your server endpoint with the `avatarId`
|
package/dist/api.cjs
CHANGED
|
@@ -2,31 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
// src/api/config.ts
|
|
4
4
|
var DEFAULT_BASE_URL = "https://api.dev.runwayml.com";
|
|
5
|
-
function getBaseUrl() {
|
|
6
|
-
try {
|
|
7
|
-
const envUrl = process.env.RUNWAYML_BASE_URL;
|
|
8
|
-
if (envUrl) return envUrl;
|
|
9
|
-
} catch {
|
|
10
|
-
}
|
|
11
|
-
return DEFAULT_BASE_URL;
|
|
12
|
-
}
|
|
13
|
-
var config = null;
|
|
14
|
-
function configure(options) {
|
|
15
|
-
config = { ...getConfig(), ...options };
|
|
16
|
-
}
|
|
17
|
-
function getConfig() {
|
|
18
|
-
if (!config) {
|
|
19
|
-
config = { baseUrl: getBaseUrl() };
|
|
20
|
-
}
|
|
21
|
-
return config;
|
|
22
|
-
}
|
|
23
|
-
function resetConfig() {
|
|
24
|
-
config = null;
|
|
25
|
-
}
|
|
26
5
|
|
|
27
6
|
// src/api/consume.ts
|
|
28
7
|
async function consumeSession(options) {
|
|
29
|
-
const { sessionId, sessionKey, baseUrl =
|
|
8
|
+
const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;
|
|
30
9
|
const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;
|
|
31
10
|
const response = await fetch(url, {
|
|
32
11
|
method: "POST",
|
|
@@ -44,9 +23,6 @@ async function consumeSession(options) {
|
|
|
44
23
|
return response.json();
|
|
45
24
|
}
|
|
46
25
|
|
|
47
|
-
exports.configure = configure;
|
|
48
26
|
exports.consumeSession = consumeSession;
|
|
49
|
-
exports.getConfig = getConfig;
|
|
50
|
-
exports.resetConfig = resetConfig;
|
|
51
27
|
//# sourceMappingURL=api.cjs.map
|
|
52
28
|
//# sourceMappingURL=api.cjs.map
|
package/dist/api.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts"],"names":[],"mappings":";;;AAAO,IAAM,gBAAA,GAAmB,8BAAA;;;ACGhC,eAAsB,eACpB,OAAA,EACiC;AACjC,EAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAY,OAAA,GAAU,kBAAiB,GAAI,OAAA;AAE9D,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,sBAAA,EAAyB,SAAS,CAAA,QAAA,CAAA;AACxD,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,IAChC,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB,kBAAA;AAAA,MAChB,aAAA,EAAe,UAAU,UAAU,CAAA;AAAA;AACrC,GACD,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,EAAK;AACtC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,2BAAA,EAA8B,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,SAAS,CAAA;AAAA,KAC5D;AAAA,EACF;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB","file":"api.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"]}
|
package/dist/api.d.cts
CHANGED
|
@@ -21,13 +21,6 @@ interface ConsumeSessionOptions {
|
|
|
21
21
|
baseUrl?: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
interface ApiConfig {
|
|
25
|
-
baseUrl: string;
|
|
26
|
-
}
|
|
27
|
-
declare function configure(options: Partial<ApiConfig>): void;
|
|
28
|
-
declare function getConfig(): ApiConfig;
|
|
29
|
-
declare function resetConfig(): void;
|
|
30
|
-
|
|
31
24
|
declare function consumeSession(options: ConsumeSessionOptions): Promise<ConsumeSessionResponse>;
|
|
32
25
|
|
|
33
|
-
export { type
|
|
26
|
+
export { type ConsumeSessionOptions, type ConsumeSessionResponse, consumeSession };
|
package/dist/api.d.ts
CHANGED
|
@@ -21,13 +21,6 @@ interface ConsumeSessionOptions {
|
|
|
21
21
|
baseUrl?: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
interface ApiConfig {
|
|
25
|
-
baseUrl: string;
|
|
26
|
-
}
|
|
27
|
-
declare function configure(options: Partial<ApiConfig>): void;
|
|
28
|
-
declare function getConfig(): ApiConfig;
|
|
29
|
-
declare function resetConfig(): void;
|
|
30
|
-
|
|
31
24
|
declare function consumeSession(options: ConsumeSessionOptions): Promise<ConsumeSessionResponse>;
|
|
32
25
|
|
|
33
|
-
export { type
|
|
26
|
+
export { type ConsumeSessionOptions, type ConsumeSessionResponse, consumeSession };
|
package/dist/api.js
CHANGED
|
@@ -1,30 +1,9 @@
|
|
|
1
1
|
// src/api/config.ts
|
|
2
2
|
var DEFAULT_BASE_URL = "https://api.dev.runwayml.com";
|
|
3
|
-
function getBaseUrl() {
|
|
4
|
-
try {
|
|
5
|
-
const envUrl = process.env.RUNWAYML_BASE_URL;
|
|
6
|
-
if (envUrl) return envUrl;
|
|
7
|
-
} catch {
|
|
8
|
-
}
|
|
9
|
-
return DEFAULT_BASE_URL;
|
|
10
|
-
}
|
|
11
|
-
var config = null;
|
|
12
|
-
function configure(options) {
|
|
13
|
-
config = { ...getConfig(), ...options };
|
|
14
|
-
}
|
|
15
|
-
function getConfig() {
|
|
16
|
-
if (!config) {
|
|
17
|
-
config = { baseUrl: getBaseUrl() };
|
|
18
|
-
}
|
|
19
|
-
return config;
|
|
20
|
-
}
|
|
21
|
-
function resetConfig() {
|
|
22
|
-
config = null;
|
|
23
|
-
}
|
|
24
3
|
|
|
25
4
|
// src/api/consume.ts
|
|
26
5
|
async function consumeSession(options) {
|
|
27
|
-
const { sessionId, sessionKey, baseUrl =
|
|
6
|
+
const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;
|
|
28
7
|
const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;
|
|
29
8
|
const response = await fetch(url, {
|
|
30
9
|
method: "POST",
|
|
@@ -42,6 +21,6 @@ async function consumeSession(options) {
|
|
|
42
21
|
return response.json();
|
|
43
22
|
}
|
|
44
23
|
|
|
45
|
-
export {
|
|
24
|
+
export { consumeSession };
|
|
46
25
|
//# sourceMappingURL=api.js.map
|
|
47
26
|
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts"],"names":[],"mappings":";AAAO,IAAM,gBAAA,GAAmB,8BAAA;;;ACGhC,eAAsB,eACpB,OAAA,EACiC;AACjC,EAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAY,OAAA,GAAU,kBAAiB,GAAI,OAAA;AAE9D,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,sBAAA,EAAyB,SAAS,CAAA,QAAA,CAAA;AACxD,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,IAChC,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB,kBAAA;AAAA,MAChB,aAAA,EAAe,UAAU,UAAU,CAAA;AAAA;AACrC,GACD,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,EAAK;AACtC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,2BAAA,EAA8B,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,SAAS,CAAA;AAAA,KAC5D;AAAA,EACF;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB","file":"api.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"]}
|
package/dist/index.cjs
CHANGED
|
@@ -7,25 +7,10 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
7
7
|
|
|
8
8
|
// src/api/config.ts
|
|
9
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
10
|
|
|
26
11
|
// src/api/consume.ts
|
|
27
12
|
async function consumeSession(options) {
|
|
28
|
-
const { sessionId, sessionKey, baseUrl =
|
|
13
|
+
const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;
|
|
29
14
|
const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;
|
|
30
15
|
const response = await fetch(url, {
|
|
31
16
|
method: "POST",
|
|
@@ -43,92 +28,88 @@ async function consumeSession(options) {
|
|
|
43
28
|
return response.json();
|
|
44
29
|
}
|
|
45
30
|
|
|
31
|
+
// src/utils/suspense-resource.ts
|
|
32
|
+
function createSuspenseResource(promise) {
|
|
33
|
+
let status = "pending";
|
|
34
|
+
let result;
|
|
35
|
+
let error;
|
|
36
|
+
const suspender = promise.then(
|
|
37
|
+
(value) => {
|
|
38
|
+
status = "fulfilled";
|
|
39
|
+
result = value;
|
|
40
|
+
},
|
|
41
|
+
(err) => {
|
|
42
|
+
status = "rejected";
|
|
43
|
+
error = err;
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
return {
|
|
47
|
+
read() {
|
|
48
|
+
switch (status) {
|
|
49
|
+
case "pending":
|
|
50
|
+
throw suspender;
|
|
51
|
+
case "rejected":
|
|
52
|
+
throw error;
|
|
53
|
+
case "fulfilled":
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
46
60
|
// src/hooks/useCredentials.ts
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
var resourceCache = /* @__PURE__ */ new Map();
|
|
62
|
+
function computeKey(options) {
|
|
63
|
+
if (options.credentials) return `direct:${options.credentials.sessionId}`;
|
|
64
|
+
if (options.sessionId && options.sessionKey)
|
|
65
|
+
return `session:${options.sessionId}`;
|
|
66
|
+
return `connect:${options.avatarId}:${options.connectUrl ?? "custom"}`;
|
|
67
|
+
}
|
|
68
|
+
async function fetchCredentials(options) {
|
|
69
|
+
const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } = options;
|
|
70
|
+
if (sessionId && sessionKey) {
|
|
71
|
+
const { url, token, roomName } = await consumeSession({
|
|
72
|
+
sessionId,
|
|
73
|
+
sessionKey,
|
|
74
|
+
baseUrl
|
|
75
|
+
});
|
|
76
|
+
return { sessionId, serverUrl: url, token, roomName };
|
|
77
|
+
}
|
|
78
|
+
if (connect) {
|
|
79
|
+
return connect(avatarId);
|
|
59
80
|
}
|
|
81
|
+
if (connectUrl) {
|
|
82
|
+
const response = await fetch(connectUrl, {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: { "Content-Type": "application/json" },
|
|
85
|
+
body: JSON.stringify({ avatarId })
|
|
86
|
+
});
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
const errorText = await response.text();
|
|
89
|
+
throw new Error(`Failed to connect: ${response.status} ${errorText}`);
|
|
90
|
+
}
|
|
91
|
+
return response.json();
|
|
92
|
+
}
|
|
93
|
+
throw new Error(
|
|
94
|
+
"AvatarCall requires one of: credentials, sessionId+sessionKey, connectUrl, or connect"
|
|
95
|
+
);
|
|
60
96
|
}
|
|
61
97
|
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]);
|
|
98
|
+
const key = computeKey(options);
|
|
100
99
|
react.useEffect(() => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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;
|
|
100
|
+
return () => {
|
|
101
|
+
resourceCache.delete(key);
|
|
102
|
+
};
|
|
103
|
+
}, [key]);
|
|
104
|
+
if (options.credentials) {
|
|
105
|
+
return options.credentials;
|
|
106
|
+
}
|
|
107
|
+
let resource = resourceCache.get(key);
|
|
108
|
+
if (!resource) {
|
|
109
|
+
resource = createSuspenseResource(fetchCredentials(options));
|
|
110
|
+
resourceCache.set(key, resource);
|
|
111
|
+
}
|
|
112
|
+
return resource.read();
|
|
132
113
|
}
|
|
133
114
|
function useLatest(value) {
|
|
134
115
|
const ref = react.useRef(value);
|
|
@@ -263,19 +244,43 @@ function useAvatarSession() {
|
|
|
263
244
|
const context = useAvatarSessionContext();
|
|
264
245
|
return context;
|
|
265
246
|
}
|
|
266
|
-
|
|
247
|
+
|
|
248
|
+
// src/hooks/useAvatarStatus.ts
|
|
249
|
+
function useAvatarStatus() {
|
|
267
250
|
const session = useAvatarSession();
|
|
268
251
|
const { videoTrackRef, hasVideo } = useAvatar();
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
252
|
+
switch (session.state) {
|
|
253
|
+
case "connecting":
|
|
254
|
+
case "idle":
|
|
255
|
+
return { status: "connecting" };
|
|
256
|
+
case "active":
|
|
257
|
+
if (hasVideo && videoTrackRef) {
|
|
258
|
+
return { status: "ready", videoTrackRef };
|
|
259
|
+
}
|
|
260
|
+
return { status: "waiting" };
|
|
261
|
+
case "ending":
|
|
262
|
+
return { status: "ending" };
|
|
263
|
+
case "ended":
|
|
264
|
+
return { status: "ended" };
|
|
265
|
+
case "error":
|
|
266
|
+
return { status: "error", error: session.error };
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function AvatarVideo({ children, ...props }) {
|
|
270
|
+
const avatar = useAvatarStatus();
|
|
271
|
+
const videoStatus = avatar.status === "ready" ? avatar : avatar.status === "connecting" ? { status: "connecting" } : { status: "waiting" };
|
|
275
272
|
if (children) {
|
|
276
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(
|
|
273
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(videoStatus) });
|
|
277
274
|
}
|
|
278
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
275
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
276
|
+
"div",
|
|
277
|
+
{
|
|
278
|
+
...props,
|
|
279
|
+
"data-avatar-video": "",
|
|
280
|
+
"data-avatar-status": videoStatus.status,
|
|
281
|
+
children: videoStatus.status === "ready" && componentsReact.isTrackReference(videoStatus.videoTrackRef) && /* @__PURE__ */ jsxRuntime.jsx(componentsReact.VideoTrack, { trackRef: videoStatus.videoTrackRef })
|
|
282
|
+
}
|
|
283
|
+
);
|
|
279
284
|
}
|
|
280
285
|
function useLocalMedia() {
|
|
281
286
|
const { localParticipant } = componentsReact.useLocalParticipant();
|
|
@@ -330,13 +335,22 @@ function ControlBar({
|
|
|
330
335
|
...props
|
|
331
336
|
}) {
|
|
332
337
|
const session = useAvatarSession();
|
|
333
|
-
const {
|
|
338
|
+
const {
|
|
339
|
+
isMicEnabled,
|
|
340
|
+
isCameraEnabled,
|
|
341
|
+
isScreenShareEnabled,
|
|
342
|
+
toggleMic,
|
|
343
|
+
toggleCamera,
|
|
344
|
+
toggleScreenShare
|
|
345
|
+
} = useLocalMedia();
|
|
334
346
|
const isActive = session.state === "active";
|
|
335
347
|
const state = {
|
|
336
348
|
isMicEnabled,
|
|
337
349
|
isCameraEnabled,
|
|
350
|
+
isScreenShareEnabled,
|
|
338
351
|
toggleMic,
|
|
339
352
|
toggleCamera,
|
|
353
|
+
toggleScreenShare,
|
|
340
354
|
endCall: session.end,
|
|
341
355
|
isActive
|
|
342
356
|
};
|
|
@@ -346,14 +360,14 @@ function ControlBar({
|
|
|
346
360
|
if (!isActive) {
|
|
347
361
|
return null;
|
|
348
362
|
}
|
|
349
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...props, "data-active": isActive, children: [
|
|
363
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...props, "data-avatar-control-bar": "", "data-avatar-active": isActive, children: [
|
|
350
364
|
showMicrophone && /* @__PURE__ */ jsxRuntime.jsx(
|
|
351
365
|
"button",
|
|
352
366
|
{
|
|
353
367
|
type: "button",
|
|
354
368
|
onClick: toggleMic,
|
|
355
|
-
"data-control": "microphone",
|
|
356
|
-
"data-enabled": isMicEnabled,
|
|
369
|
+
"data-avatar-control": "microphone",
|
|
370
|
+
"data-avatar-enabled": isMicEnabled,
|
|
357
371
|
"aria-label": isMicEnabled ? "Mute microphone" : "Unmute microphone",
|
|
358
372
|
children: microphoneIcon
|
|
359
373
|
}
|
|
@@ -363,8 +377,8 @@ function ControlBar({
|
|
|
363
377
|
{
|
|
364
378
|
type: "button",
|
|
365
379
|
onClick: toggleCamera,
|
|
366
|
-
"data-control": "camera",
|
|
367
|
-
"data-enabled": isCameraEnabled,
|
|
380
|
+
"data-avatar-control": "camera",
|
|
381
|
+
"data-avatar-enabled": isCameraEnabled,
|
|
368
382
|
"aria-label": isCameraEnabled ? "Turn off camera" : "Turn on camera",
|
|
369
383
|
children: cameraIcon
|
|
370
384
|
}
|
|
@@ -374,7 +388,8 @@ function ControlBar({
|
|
|
374
388
|
{
|
|
375
389
|
source: livekitClient.Track.Source.ScreenShare,
|
|
376
390
|
showIcon: false,
|
|
377
|
-
"data-control": "screen-share",
|
|
391
|
+
"data-avatar-control": "screen-share",
|
|
392
|
+
"data-avatar-enabled": isScreenShareEnabled,
|
|
378
393
|
"aria-label": "Toggle screen share",
|
|
379
394
|
children: screenShareIcon
|
|
380
395
|
}
|
|
@@ -384,7 +399,8 @@ function ControlBar({
|
|
|
384
399
|
{
|
|
385
400
|
type: "button",
|
|
386
401
|
onClick: session.end,
|
|
387
|
-
"data-control": "end-call",
|
|
402
|
+
"data-avatar-control": "end-call",
|
|
403
|
+
"data-avatar-enabled": true,
|
|
388
404
|
"aria-label": "End call",
|
|
389
405
|
children: phoneIcon
|
|
390
406
|
}
|
|
@@ -458,7 +474,11 @@ var phoneIcon = /* @__PURE__ */ jsxRuntime.jsx(
|
|
|
458
474
|
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" })
|
|
459
475
|
}
|
|
460
476
|
);
|
|
461
|
-
function UserVideo({
|
|
477
|
+
function UserVideo({
|
|
478
|
+
children,
|
|
479
|
+
mirror = true,
|
|
480
|
+
...props
|
|
481
|
+
}) {
|
|
462
482
|
const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();
|
|
463
483
|
const hasVideo = localVideoTrackRef !== null && componentsReact.isTrackReference(localVideoTrackRef);
|
|
464
484
|
const state = {
|
|
@@ -473,9 +493,10 @@ function UserVideo({ children, mirror = true, ...props }) {
|
|
|
473
493
|
"div",
|
|
474
494
|
{
|
|
475
495
|
...props,
|
|
476
|
-
"data-
|
|
477
|
-
"data-
|
|
478
|
-
"data-
|
|
496
|
+
"data-avatar-user-video": "",
|
|
497
|
+
"data-avatar-has-video": hasVideo,
|
|
498
|
+
"data-avatar-camera-enabled": isCameraEnabled,
|
|
499
|
+
"data-avatar-mirror": mirror,
|
|
479
500
|
children: hasVideo && localVideoTrackRef && componentsReact.isTrackReference(localVideoTrackRef) && /* @__PURE__ */ jsxRuntime.jsx(componentsReact.VideoTrack, { trackRef: localVideoTrackRef })
|
|
480
501
|
}
|
|
481
502
|
);
|
|
@@ -487,6 +508,7 @@ function AvatarCall({
|
|
|
487
508
|
credentials: directCredentials,
|
|
488
509
|
connectUrl,
|
|
489
510
|
connect,
|
|
511
|
+
baseUrl,
|
|
490
512
|
avatarImageUrl,
|
|
491
513
|
onEnd,
|
|
492
514
|
onError,
|
|
@@ -495,50 +517,24 @@ function AvatarCall({
|
|
|
495
517
|
...props
|
|
496
518
|
}) {
|
|
497
519
|
const onErrorRef = useLatest(onError);
|
|
498
|
-
const
|
|
520
|
+
const credentials = useCredentials({
|
|
499
521
|
avatarId,
|
|
500
522
|
sessionId,
|
|
501
523
|
sessionKey,
|
|
502
524
|
credentials: directCredentials,
|
|
503
525
|
connectUrl,
|
|
504
526
|
connect,
|
|
505
|
-
|
|
527
|
+
baseUrl
|
|
506
528
|
});
|
|
507
529
|
const handleSessionError = (err) => {
|
|
508
530
|
onErrorRef.current?.(err);
|
|
509
531
|
};
|
|
510
532
|
const backgroundStyle = avatarImageUrl ? { "--avatar-image": `url(${avatarImageUrl})` } : void 0;
|
|
511
|
-
if (status === "idle" || status === "connecting") {
|
|
512
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
513
|
-
"div",
|
|
514
|
-
{
|
|
515
|
-
...props,
|
|
516
|
-
"data-avatar-call": "",
|
|
517
|
-
"data-state": "connecting",
|
|
518
|
-
"data-avatar-id": avatarId,
|
|
519
|
-
style: { ...props.style, ...backgroundStyle }
|
|
520
|
-
}
|
|
521
|
-
);
|
|
522
|
-
}
|
|
523
|
-
if (status === "error" || !credentials) {
|
|
524
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
525
|
-
"div",
|
|
526
|
-
{
|
|
527
|
-
...props,
|
|
528
|
-
"data-avatar-call": "",
|
|
529
|
-
"data-state": "error",
|
|
530
|
-
"data-avatar-id": avatarId,
|
|
531
|
-
"data-error": error?.message,
|
|
532
|
-
style: { ...props.style, ...backgroundStyle }
|
|
533
|
-
}
|
|
534
|
-
);
|
|
535
|
-
}
|
|
536
533
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
537
534
|
"div",
|
|
538
535
|
{
|
|
539
536
|
...props,
|
|
540
537
|
"data-avatar-call": "",
|
|
541
|
-
"data-state": "connected",
|
|
542
538
|
"data-avatar-id": avatarId,
|
|
543
539
|
style: { ...props.style, ...backgroundStyle },
|
|
544
540
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -558,7 +554,10 @@ function AvatarCall({
|
|
|
558
554
|
}
|
|
559
555
|
);
|
|
560
556
|
}
|
|
561
|
-
function ScreenShareVideo({
|
|
557
|
+
function ScreenShareVideo({
|
|
558
|
+
children,
|
|
559
|
+
...props
|
|
560
|
+
}) {
|
|
562
561
|
const { localParticipant } = componentsReact.useLocalParticipant();
|
|
563
562
|
const tracks = componentsReact.useTracks(
|
|
564
563
|
[{ source: livekitClient.Track.Source.ScreenShare, withPlaceholder: false }],
|
|
@@ -579,13 +578,17 @@ function ScreenShareVideo({ children, ...props }) {
|
|
|
579
578
|
if (!isSharing) {
|
|
580
579
|
return null;
|
|
581
580
|
}
|
|
582
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, "data-sharing": isSharing, children: screenShareTrackRef && componentsReact.isTrackReference(screenShareTrackRef) && /* @__PURE__ */ jsxRuntime.jsx(componentsReact.VideoTrack, { trackRef: screenShareTrackRef }) });
|
|
581
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, "data-avatar-screen-share": "", "data-avatar-sharing": isSharing, children: screenShareTrackRef && componentsReact.isTrackReference(screenShareTrackRef) && /* @__PURE__ */ jsxRuntime.jsx(componentsReact.VideoTrack, { trackRef: screenShareTrackRef }) });
|
|
583
582
|
}
|
|
584
583
|
|
|
585
584
|
Object.defineProperty(exports, "AudioRenderer", {
|
|
586
585
|
enumerable: true,
|
|
587
586
|
get: function () { return componentsReact.RoomAudioRenderer; }
|
|
588
587
|
});
|
|
588
|
+
Object.defineProperty(exports, "VideoTrack", {
|
|
589
|
+
enumerable: true,
|
|
590
|
+
get: function () { return componentsReact.VideoTrack; }
|
|
591
|
+
});
|
|
589
592
|
exports.AvatarCall = AvatarCall;
|
|
590
593
|
exports.AvatarSession = AvatarSession;
|
|
591
594
|
exports.AvatarVideo = AvatarVideo;
|
|
@@ -594,6 +597,7 @@ exports.ScreenShareVideo = ScreenShareVideo;
|
|
|
594
597
|
exports.UserVideo = UserVideo;
|
|
595
598
|
exports.useAvatar = useAvatar;
|
|
596
599
|
exports.useAvatarSession = useAvatarSession;
|
|
600
|
+
exports.useAvatarStatus = useAvatarStatus;
|
|
597
601
|
exports.useLocalMedia = useLocalMedia;
|
|
598
602
|
//# sourceMappingURL=index.cjs.map
|
|
599
603
|
//# sourceMappingURL=index.cjs.map
|