@skippr/live-agent-sdk 0.14.0 → 0.15.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 +17 -0
- package/dist/esm/lib-exports.js +599 -170
- package/dist/skippr-sdk.css +1 -1
- package/dist/skippr-sdk.js +116 -116
- package/dist/types/components/LiveAgent.d.ts +2 -1
- package/dist/types/components/LoginFlow.d.ts +8 -0
- package/dist/types/context/LiveAgentContext.d.ts +7 -0
- package/dist/types/hooks/useAuth.d.ts +14 -0
- package/dist/types/hooks/useSession.d.ts +2 -1
- package/package.json +1 -1
package/dist/esm/lib-exports.js
CHANGED
|
@@ -1,34 +1,175 @@
|
|
|
1
1
|
// src/components/LiveAgent.tsx
|
|
2
2
|
import { LiveKitRoom, RoomAudioRenderer } from "@livekit/components-react";
|
|
3
|
-
import { useCallback as
|
|
3
|
+
import { useCallback as useCallback7, useMemo as useMemo4, useState as useState7 } from "react";
|
|
4
4
|
|
|
5
5
|
// src/context/LiveAgentContext.tsx
|
|
6
6
|
import { createContext } from "react";
|
|
7
7
|
var LiveAgentContext = createContext(null);
|
|
8
8
|
|
|
9
|
-
// src/hooks/
|
|
10
|
-
import { useCallback, useState } from "react";
|
|
9
|
+
// src/hooks/useAuth.ts
|
|
10
|
+
import { useCallback, useEffect, useState } from "react";
|
|
11
11
|
var API_URL = "https://skipprapi-production.up.railway.app";
|
|
12
|
-
function
|
|
12
|
+
function storageKey(appKey) {
|
|
13
|
+
return `skippr_auth_${appKey}`;
|
|
14
|
+
}
|
|
15
|
+
function getStoredToken(appKey) {
|
|
16
|
+
try {
|
|
17
|
+
return localStorage.getItem(storageKey(appKey));
|
|
18
|
+
} catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function setStoredToken(appKey, token) {
|
|
23
|
+
try {
|
|
24
|
+
localStorage.setItem(storageKey(appKey), token);
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error("[Skippr] Failed to persist auth token:", e);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function clearStoredToken(appKey) {
|
|
30
|
+
try {
|
|
31
|
+
localStorage.removeItem(storageKey(appKey));
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error("[Skippr] Failed to clear auth token:", e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function useAuth({ appKey }) {
|
|
37
|
+
const [authToken, setAuthToken] = useState(null);
|
|
38
|
+
const [isValidating, setIsValidating] = useState(false);
|
|
39
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
40
|
+
const [error, setError] = useState("");
|
|
41
|
+
const isAuthenticated = authToken !== null;
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!appKey)
|
|
44
|
+
return;
|
|
45
|
+
const stored = getStoredToken(appKey);
|
|
46
|
+
if (!stored)
|
|
47
|
+
return;
|
|
48
|
+
async function validateStoredToken() {
|
|
49
|
+
setIsValidating(true);
|
|
50
|
+
try {
|
|
51
|
+
const res = await fetch(`${API_URL}/v1/auth/validate-token`, {
|
|
52
|
+
headers: { Authorization: `Bearer ${stored}` }
|
|
53
|
+
});
|
|
54
|
+
if (res.ok) {
|
|
55
|
+
setAuthToken(stored);
|
|
56
|
+
} else {
|
|
57
|
+
clearStoredToken(appKey);
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
clearStoredToken(appKey);
|
|
61
|
+
} finally {
|
|
62
|
+
setIsValidating(false);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
validateStoredToken();
|
|
66
|
+
}, [appKey]);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
function handleLogout() {
|
|
69
|
+
setAuthToken(null);
|
|
70
|
+
setError("");
|
|
71
|
+
}
|
|
72
|
+
window.addEventListener("skippr:logout", handleLogout);
|
|
73
|
+
return () => window.removeEventListener("skippr:logout", handleLogout);
|
|
74
|
+
}, []);
|
|
75
|
+
const requestOtp = useCallback(async (email) => {
|
|
76
|
+
if (!appKey)
|
|
77
|
+
return false;
|
|
78
|
+
setIsSubmitting(true);
|
|
79
|
+
setError("");
|
|
80
|
+
try {
|
|
81
|
+
const resp = await fetch(`${API_URL}/v1/auth/request-otp`, {
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: {
|
|
84
|
+
"Content-Type": "application/json",
|
|
85
|
+
"X-App-Key": appKey
|
|
86
|
+
},
|
|
87
|
+
body: JSON.stringify({ email })
|
|
88
|
+
});
|
|
89
|
+
if (!resp.ok) {
|
|
90
|
+
const body = await resp.json().catch(() => ({}));
|
|
91
|
+
throw new Error(body.detail || "Failed to send verification code");
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
} catch (e) {
|
|
95
|
+
setError(e instanceof Error ? e.message : "Failed to send verification code");
|
|
96
|
+
return false;
|
|
97
|
+
} finally {
|
|
98
|
+
setIsSubmitting(false);
|
|
99
|
+
}
|
|
100
|
+
}, [appKey]);
|
|
101
|
+
const verifyOtp = useCallback(async (email, code) => {
|
|
102
|
+
if (!appKey)
|
|
103
|
+
return;
|
|
104
|
+
setIsSubmitting(true);
|
|
105
|
+
setError("");
|
|
106
|
+
try {
|
|
107
|
+
const resp = await fetch(`${API_URL}/v1/auth/verify-otp`, {
|
|
108
|
+
method: "POST",
|
|
109
|
+
headers: {
|
|
110
|
+
"Content-Type": "application/json",
|
|
111
|
+
"X-App-Key": appKey
|
|
112
|
+
},
|
|
113
|
+
body: JSON.stringify({ email, code, recaptchaToken: "sdk" })
|
|
114
|
+
});
|
|
115
|
+
if (!resp.ok) {
|
|
116
|
+
const body = await resp.json().catch(() => ({}));
|
|
117
|
+
throw new Error(body.detail || "Invalid or expired verification code");
|
|
118
|
+
}
|
|
119
|
+
const { token } = await resp.json();
|
|
120
|
+
setStoredToken(appKey, token);
|
|
121
|
+
setAuthToken(token);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
setError(e instanceof Error ? e.message : "Verification failed");
|
|
124
|
+
return;
|
|
125
|
+
} finally {
|
|
126
|
+
setIsSubmitting(false);
|
|
127
|
+
}
|
|
128
|
+
}, [appKey]);
|
|
129
|
+
const logout = useCallback(() => {
|
|
130
|
+
if (appKey)
|
|
131
|
+
clearStoredToken(appKey);
|
|
132
|
+
setAuthToken(null);
|
|
133
|
+
setError("");
|
|
134
|
+
}, [appKey]);
|
|
135
|
+
return {
|
|
136
|
+
isAuthenticated,
|
|
137
|
+
isValidating,
|
|
138
|
+
authToken,
|
|
139
|
+
requestOtp,
|
|
140
|
+
verifyOtp,
|
|
141
|
+
logout,
|
|
142
|
+
error,
|
|
143
|
+
isSubmitting
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/hooks/useSession.ts
|
|
148
|
+
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
149
|
+
var API_URL2 = "https://skipprapi-production.up.railway.app";
|
|
150
|
+
function resolveAuthHeaders(authToken, appKey, userToken) {
|
|
151
|
+
const headers = {};
|
|
13
152
|
if (authToken)
|
|
14
|
-
|
|
153
|
+
headers.Authorization = `Bearer ${authToken}`;
|
|
15
154
|
if (appKey)
|
|
16
|
-
|
|
17
|
-
|
|
155
|
+
headers["X-App-Key"] = appKey;
|
|
156
|
+
if (userToken)
|
|
157
|
+
headers["X-User-Token"] = userToken;
|
|
158
|
+
return headers;
|
|
18
159
|
}
|
|
19
|
-
function useSession({ agentId, authToken, appKey }) {
|
|
20
|
-
const [connection, setConnection] =
|
|
21
|
-
const [shouldConnect, setShouldConnect] =
|
|
22
|
-
const [isStarting, setIsStarting] =
|
|
23
|
-
const [error, setError] =
|
|
24
|
-
const [sessionId, setSessionId] =
|
|
25
|
-
const [sessionToken, setSessionToken] =
|
|
26
|
-
const startSession =
|
|
160
|
+
function useSession({ agentId, authToken, appKey, userToken }) {
|
|
161
|
+
const [connection, setConnection] = useState2(null);
|
|
162
|
+
const [shouldConnect, setShouldConnect] = useState2(false);
|
|
163
|
+
const [isStarting, setIsStarting] = useState2(false);
|
|
164
|
+
const [error, setError] = useState2("");
|
|
165
|
+
const [sessionId, setSessionId] = useState2(null);
|
|
166
|
+
const [sessionToken, setSessionToken] = useState2(null);
|
|
167
|
+
const startSession = useCallback2(async () => {
|
|
27
168
|
setIsStarting(true);
|
|
28
169
|
setError("");
|
|
29
170
|
try {
|
|
30
|
-
const authHeaders = resolveAuthHeaders(authToken, appKey);
|
|
31
|
-
const createResp = await fetch(`${
|
|
171
|
+
const authHeaders = resolveAuthHeaders(authToken, appKey, userToken);
|
|
172
|
+
const createResp = await fetch(`${API_URL2}/v1/sessions`, {
|
|
32
173
|
method: "POST",
|
|
33
174
|
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
34
175
|
body: JSON.stringify({ agentId })
|
|
@@ -38,7 +179,7 @@ function useSession({ agentId, authToken, appKey }) {
|
|
|
38
179
|
}
|
|
39
180
|
const { session } = await createResp.json();
|
|
40
181
|
const sessionHeaders = { "X-Session-Token": session.sessionToken };
|
|
41
|
-
const startResp = await fetch(`${
|
|
182
|
+
const startResp = await fetch(`${API_URL2}/v1/sessions/${session.id}/start`, {
|
|
42
183
|
method: "POST",
|
|
43
184
|
headers: sessionHeaders
|
|
44
185
|
});
|
|
@@ -58,12 +199,12 @@ function useSession({ agentId, authToken, appKey }) {
|
|
|
58
199
|
} finally {
|
|
59
200
|
setIsStarting(false);
|
|
60
201
|
}
|
|
61
|
-
}, [agentId, authToken, appKey]);
|
|
62
|
-
const disconnect =
|
|
202
|
+
}, [agentId, authToken, appKey, userToken]);
|
|
203
|
+
const disconnect = useCallback2(async () => {
|
|
63
204
|
if (sessionId && sessionToken) {
|
|
64
205
|
const sessionHeaders = { "X-Session-Token": sessionToken };
|
|
65
206
|
try {
|
|
66
|
-
await fetch(`${
|
|
207
|
+
await fetch(`${API_URL2}/v1/sessions/${sessionId}/complete`, {
|
|
67
208
|
method: "POST",
|
|
68
209
|
headers: { "Content-Type": "application/json", ...sessionHeaders },
|
|
69
210
|
body: JSON.stringify({})
|
|
@@ -82,7 +223,7 @@ function useSession({ agentId, authToken, appKey }) {
|
|
|
82
223
|
// src/components/Sidebar.tsx
|
|
83
224
|
import { useConnectionState } from "@livekit/components-react";
|
|
84
225
|
import { ConnectionState } from "livekit-client";
|
|
85
|
-
import { useEffect as
|
|
226
|
+
import { useEffect as useEffect6 } from "react";
|
|
86
227
|
|
|
87
228
|
// src/hooks/useCombinedMessages.ts
|
|
88
229
|
import { useVoiceAssistant } from "@livekit/components-react";
|
|
@@ -176,15 +317,15 @@ function useLiveAgent() {
|
|
|
176
317
|
}
|
|
177
318
|
|
|
178
319
|
// src/hooks/usePhaseUpdates.ts
|
|
179
|
-
import { useCallback as
|
|
320
|
+
import { useCallback as useCallback3 } from "react";
|
|
180
321
|
|
|
181
322
|
// src/hooks/useAgentState.ts
|
|
182
323
|
import { useRemoteParticipants } from "@livekit/components-react";
|
|
183
|
-
import { useEffect, useState as
|
|
324
|
+
import { useEffect as useEffect2, useState as useState3 } from "react";
|
|
184
325
|
function useAgentState(attributeKey, parse, initial) {
|
|
185
|
-
const [value, setValue] =
|
|
326
|
+
const [value, setValue] = useState3(initial);
|
|
186
327
|
const remoteParticipants = useRemoteParticipants();
|
|
187
|
-
|
|
328
|
+
useEffect2(() => {
|
|
188
329
|
const agentParticipant = remoteParticipants.find((p) => p.attributes?.[attributeKey]);
|
|
189
330
|
if (agentParticipant) {
|
|
190
331
|
const attr = agentParticipant.attributes?.[attributeKey];
|
|
@@ -230,13 +371,13 @@ function parsePhases(json) {
|
|
|
230
371
|
return null;
|
|
231
372
|
}
|
|
232
373
|
function usePhaseUpdates() {
|
|
233
|
-
const parse =
|
|
374
|
+
const parse = useCallback3(parsePhases, []);
|
|
234
375
|
const phases = useAgentState("phases", parse, []);
|
|
235
376
|
return { phases };
|
|
236
377
|
}
|
|
237
378
|
|
|
238
379
|
// src/hooks/useQuestionUpdates.ts
|
|
239
|
-
import { useCallback as
|
|
380
|
+
import { useCallback as useCallback4 } from "react";
|
|
240
381
|
function parseQuestions(json) {
|
|
241
382
|
try {
|
|
242
383
|
const data = JSON.parse(json);
|
|
@@ -247,7 +388,7 @@ function parseQuestions(json) {
|
|
|
247
388
|
return null;
|
|
248
389
|
}
|
|
249
390
|
function useQuestionUpdates() {
|
|
250
|
-
const parse =
|
|
391
|
+
const parse = useCallback4(parseQuestions, []);
|
|
251
392
|
const questions = useAgentState("questions", parse, []);
|
|
252
393
|
return { questions };
|
|
253
394
|
}
|
|
@@ -388,8 +529,14 @@ var Check = createLucideIcon("check", __iconNode5);
|
|
|
388
529
|
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/circle.js
|
|
389
530
|
var __iconNode6 = [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]];
|
|
390
531
|
var Circle = createLucideIcon("circle", __iconNode6);
|
|
391
|
-
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/
|
|
532
|
+
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mail.js
|
|
392
533
|
var __iconNode7 = [
|
|
534
|
+
["path", { d: "m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7", key: "132q7q" }],
|
|
535
|
+
["rect", { x: "2", y: "4", width: "20", height: "16", rx: "2", key: "izxlao" }]
|
|
536
|
+
];
|
|
537
|
+
var Mail = createLucideIcon("mail", __iconNode7);
|
|
538
|
+
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/message-circle.js
|
|
539
|
+
var __iconNode8 = [
|
|
393
540
|
[
|
|
394
541
|
"path",
|
|
395
542
|
{
|
|
@@ -398,9 +545,9 @@ var __iconNode7 = [
|
|
|
398
545
|
}
|
|
399
546
|
]
|
|
400
547
|
];
|
|
401
|
-
var MessageCircle = createLucideIcon("message-circle",
|
|
548
|
+
var MessageCircle = createLucideIcon("message-circle", __iconNode8);
|
|
402
549
|
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic-off.js
|
|
403
|
-
var
|
|
550
|
+
var __iconNode9 = [
|
|
404
551
|
["path", { d: "M12 19v3", key: "npa21l" }],
|
|
405
552
|
["path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33", key: "1gzdoj" }],
|
|
406
553
|
["path", { d: "M16.95 16.95A7 7 0 0 1 5 12v-2", key: "cqa7eg" }],
|
|
@@ -408,32 +555,32 @@ var __iconNode8 = [
|
|
|
408
555
|
["path", { d: "m2 2 20 20", key: "1ooewy" }],
|
|
409
556
|
["path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12", key: "r2i35w" }]
|
|
410
557
|
];
|
|
411
|
-
var MicOff = createLucideIcon("mic-off",
|
|
558
|
+
var MicOff = createLucideIcon("mic-off", __iconNode9);
|
|
412
559
|
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mic.js
|
|
413
|
-
var
|
|
560
|
+
var __iconNode10 = [
|
|
414
561
|
["path", { d: "M12 19v3", key: "npa21l" }],
|
|
415
562
|
["path", { d: "M19 10v2a7 7 0 0 1-14 0v-2", key: "1vc78b" }],
|
|
416
563
|
["rect", { x: "9", y: "2", width: "6", height: "13", rx: "3", key: "s6n7sd" }]
|
|
417
564
|
];
|
|
418
|
-
var Mic = createLucideIcon("mic",
|
|
565
|
+
var Mic = createLucideIcon("mic", __iconNode10);
|
|
419
566
|
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor-off.js
|
|
420
|
-
var
|
|
567
|
+
var __iconNode11 = [
|
|
421
568
|
["path", { d: "M12 17v4", key: "1riwvh" }],
|
|
422
569
|
["path", { d: "M17 17H4a2 2 0 0 1-2-2V5a2 2 0 0 1 1.184-1.826", key: "cv7jms" }],
|
|
423
570
|
["path", { d: "m2 2 20 20", key: "1ooewy" }],
|
|
424
571
|
["path", { d: "M8 21h8", key: "1ev6f3" }],
|
|
425
572
|
["path", { d: "M8.656 3H20a2 2 0 0 1 2 2v10a2 2 0 0 1-.293 1.042", key: "z8ni2w" }]
|
|
426
573
|
];
|
|
427
|
-
var MonitorOff = createLucideIcon("monitor-off",
|
|
574
|
+
var MonitorOff = createLucideIcon("monitor-off", __iconNode11);
|
|
428
575
|
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor.js
|
|
429
|
-
var
|
|
576
|
+
var __iconNode12 = [
|
|
430
577
|
["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
|
|
431
578
|
["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
|
|
432
579
|
["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
|
|
433
580
|
];
|
|
434
|
-
var Monitor = createLucideIcon("monitor",
|
|
581
|
+
var Monitor = createLucideIcon("monitor", __iconNode12);
|
|
435
582
|
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/phone-off.js
|
|
436
|
-
var
|
|
583
|
+
var __iconNode13 = [
|
|
437
584
|
[
|
|
438
585
|
"path",
|
|
439
586
|
{
|
|
@@ -450,13 +597,13 @@ var __iconNode12 = [
|
|
|
450
597
|
}
|
|
451
598
|
]
|
|
452
599
|
];
|
|
453
|
-
var PhoneOff = createLucideIcon("phone-off",
|
|
600
|
+
var PhoneOff = createLucideIcon("phone-off", __iconNode13);
|
|
454
601
|
// ../../node_modules/.bun/lucide-react@0.563.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/x.js
|
|
455
|
-
var
|
|
602
|
+
var __iconNode14 = [
|
|
456
603
|
["path", { d: "M18 6 6 18", key: "1bl5f8" }],
|
|
457
604
|
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
458
605
|
];
|
|
459
|
-
var X = createLucideIcon("x",
|
|
606
|
+
var X = createLucideIcon("x", __iconNode14);
|
|
460
607
|
// src/components/ui/button.tsx
|
|
461
608
|
import { forwardRef as forwardRef3 } from "react";
|
|
462
609
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -518,10 +665,257 @@ function ChatHeader({ onClose }) {
|
|
|
518
665
|
});
|
|
519
666
|
}
|
|
520
667
|
|
|
668
|
+
// src/components/LoginFlow.tsx
|
|
669
|
+
import { useCallback as useCallback5, useEffect as useEffect3, useRef, useState as useState4 } from "react";
|
|
670
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
671
|
+
var OTP_LENGTH = 6;
|
|
672
|
+
var DIGIT_KEYS = ["d0", "d1", "d2", "d3", "d4", "d5"];
|
|
673
|
+
function LoginFlow({ requestOtp, verifyOtp, error, isSubmitting }) {
|
|
674
|
+
const [step, setStep] = useState4("email");
|
|
675
|
+
const [email, setEmail] = useState4("");
|
|
676
|
+
const handleRequestOtp = useCallback5(async (emailValue) => {
|
|
677
|
+
const success = await requestOtp(emailValue);
|
|
678
|
+
if (success)
|
|
679
|
+
setStep("otp");
|
|
680
|
+
}, [requestOtp]);
|
|
681
|
+
const handleVerifyOtp = useCallback5(async (code) => {
|
|
682
|
+
await verifyOtp(email, code);
|
|
683
|
+
}, [verifyOtp, email]);
|
|
684
|
+
const handleBack = useCallback5(() => {
|
|
685
|
+
setStep("email");
|
|
686
|
+
}, []);
|
|
687
|
+
const handleResend = useCallback5(async () => {
|
|
688
|
+
await requestOtp(email);
|
|
689
|
+
}, [requestOtp, email]);
|
|
690
|
+
if (step === "otp") {
|
|
691
|
+
return /* @__PURE__ */ jsx3(OtpStep, {
|
|
692
|
+
email,
|
|
693
|
+
onSubmit: handleVerifyOtp,
|
|
694
|
+
onResend: handleResend,
|
|
695
|
+
onBack: handleBack,
|
|
696
|
+
error,
|
|
697
|
+
isSubmitting
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
return /* @__PURE__ */ jsx3(EmailStep, {
|
|
701
|
+
email,
|
|
702
|
+
onEmailChange: setEmail,
|
|
703
|
+
onSubmit: handleRequestOtp,
|
|
704
|
+
error,
|
|
705
|
+
isSubmitting
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
function EmailStep({ email, onEmailChange, onSubmit, error, isSubmitting }) {
|
|
709
|
+
function handleSubmit(e) {
|
|
710
|
+
e.preventDefault();
|
|
711
|
+
if (email.trim())
|
|
712
|
+
onSubmit(email.trim());
|
|
713
|
+
}
|
|
714
|
+
return /* @__PURE__ */ jsxs2("div", {
|
|
715
|
+
className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:px-4 skippr:py-4",
|
|
716
|
+
children: [
|
|
717
|
+
/* @__PURE__ */ jsxs2("div", {
|
|
718
|
+
className: "skippr:mb-4 skippr:text-center",
|
|
719
|
+
children: [
|
|
720
|
+
/* @__PURE__ */ jsx3(Mail, {
|
|
721
|
+
className: "skippr:mx-auto skippr:mb-2 skippr:size-6 skippr:text-primary"
|
|
722
|
+
}),
|
|
723
|
+
/* @__PURE__ */ jsx3("p", {
|
|
724
|
+
className: "skippr:text-sm skippr:font-medium skippr:text-foreground",
|
|
725
|
+
children: "Sign in to continue"
|
|
726
|
+
}),
|
|
727
|
+
/* @__PURE__ */ jsx3("p", {
|
|
728
|
+
className: "skippr:mt-1 skippr:text-xs skippr:text-muted-foreground",
|
|
729
|
+
children: "Your email will be used to identify you across sessions"
|
|
730
|
+
})
|
|
731
|
+
]
|
|
732
|
+
}),
|
|
733
|
+
/* @__PURE__ */ jsxs2("form", {
|
|
734
|
+
onSubmit: handleSubmit,
|
|
735
|
+
className: "skippr:flex skippr:flex-col skippr:gap-3",
|
|
736
|
+
children: [
|
|
737
|
+
/* @__PURE__ */ jsx3("input", {
|
|
738
|
+
type: "email",
|
|
739
|
+
placeholder: "you@example.com",
|
|
740
|
+
value: email,
|
|
741
|
+
onChange: (e) => onEmailChange(e.target.value),
|
|
742
|
+
disabled: isSubmitting,
|
|
743
|
+
required: true,
|
|
744
|
+
className: "skippr:w-full skippr:rounded-md skippr:border skippr:border-border skippr:bg-background skippr:px-3 skippr:py-2 skippr:text-sm skippr:text-foreground skippr:placeholder-muted-foreground skippr:outline-none focus:skippr:ring-2 focus:skippr:ring-primary/30 focus:skippr:border-primary disabled:skippr:opacity-50"
|
|
745
|
+
}),
|
|
746
|
+
/* @__PURE__ */ jsx3(Button, {
|
|
747
|
+
type: "submit",
|
|
748
|
+
disabled: isSubmitting || !email.trim(),
|
|
749
|
+
className: "skippr:w-full",
|
|
750
|
+
children: isSubmitting ? /* @__PURE__ */ jsx3(LoaderCircle, {
|
|
751
|
+
className: "skippr:size-4 skippr:animate-spin"
|
|
752
|
+
}) : "Continue"
|
|
753
|
+
}),
|
|
754
|
+
error && /* @__PURE__ */ jsx3("p", {
|
|
755
|
+
className: "skippr:text-xs skippr:text-center skippr:text-destructive",
|
|
756
|
+
children: error
|
|
757
|
+
})
|
|
758
|
+
]
|
|
759
|
+
})
|
|
760
|
+
]
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
|
|
764
|
+
const [digits, setDigits] = useState4(Array(OTP_LENGTH).fill(""));
|
|
765
|
+
const [resendCooldown, setResendCooldown] = useState4(0);
|
|
766
|
+
const inputRefs = useRef([]);
|
|
767
|
+
const submittedRef = useRef(false);
|
|
768
|
+
useEffect3(() => {
|
|
769
|
+
inputRefs.current[0]?.focus();
|
|
770
|
+
}, []);
|
|
771
|
+
useEffect3(() => {
|
|
772
|
+
if (error)
|
|
773
|
+
submittedRef.current = false;
|
|
774
|
+
}, [error]);
|
|
775
|
+
useEffect3(() => {
|
|
776
|
+
if (resendCooldown <= 0)
|
|
777
|
+
return;
|
|
778
|
+
const timer = setTimeout(() => setResendCooldown((c) => c - 1), 1000);
|
|
779
|
+
return () => clearTimeout(timer);
|
|
780
|
+
}, [resendCooldown]);
|
|
781
|
+
const submitCode = useCallback5((code) => {
|
|
782
|
+
if (submittedRef.current || isSubmitting)
|
|
783
|
+
return;
|
|
784
|
+
submittedRef.current = true;
|
|
785
|
+
onSubmit(code);
|
|
786
|
+
}, [onSubmit, isSubmitting]);
|
|
787
|
+
const handleDigitChange = useCallback5((index2, value) => {
|
|
788
|
+
const digit = value.replace(/\D/g, "").slice(-1);
|
|
789
|
+
const newDigits = [...digits];
|
|
790
|
+
newDigits[index2] = digit;
|
|
791
|
+
setDigits(newDigits);
|
|
792
|
+
if (digit && index2 < OTP_LENGTH - 1) {
|
|
793
|
+
inputRefs.current[index2 + 1]?.focus();
|
|
794
|
+
}
|
|
795
|
+
if (digit && index2 === OTP_LENGTH - 1) {
|
|
796
|
+
const code = newDigits.join("");
|
|
797
|
+
if (code.length === OTP_LENGTH)
|
|
798
|
+
submitCode(code);
|
|
799
|
+
}
|
|
800
|
+
}, [digits, submitCode]);
|
|
801
|
+
const handleKeyDown = useCallback5((index2, e) => {
|
|
802
|
+
if (e.key === "Backspace" && !digits[index2] && index2 > 0) {
|
|
803
|
+
inputRefs.current[index2 - 1]?.focus();
|
|
804
|
+
}
|
|
805
|
+
}, [digits]);
|
|
806
|
+
const handlePaste = useCallback5((e) => {
|
|
807
|
+
e.preventDefault();
|
|
808
|
+
const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, OTP_LENGTH);
|
|
809
|
+
if (pasted.length > 0) {
|
|
810
|
+
const newDigits = Array(OTP_LENGTH).fill("");
|
|
811
|
+
for (let i = 0;i < pasted.length; i++) {
|
|
812
|
+
newDigits[i] = pasted[i];
|
|
813
|
+
}
|
|
814
|
+
setDigits(newDigits);
|
|
815
|
+
if (pasted.length === OTP_LENGTH)
|
|
816
|
+
submitCode(pasted);
|
|
817
|
+
else
|
|
818
|
+
inputRefs.current[pasted.length]?.focus();
|
|
819
|
+
}
|
|
820
|
+
}, [submitCode]);
|
|
821
|
+
function handleSubmit(e) {
|
|
822
|
+
e.preventDefault();
|
|
823
|
+
const code = digits.join("");
|
|
824
|
+
if (code.length === OTP_LENGTH)
|
|
825
|
+
submitCode(code);
|
|
826
|
+
}
|
|
827
|
+
function handleResend() {
|
|
828
|
+
onResend();
|
|
829
|
+
setResendCooldown(30);
|
|
830
|
+
setDigits(Array(OTP_LENGTH).fill(""));
|
|
831
|
+
submittedRef.current = false;
|
|
832
|
+
inputRefs.current[0]?.focus();
|
|
833
|
+
}
|
|
834
|
+
return /* @__PURE__ */ jsxs2("div", {
|
|
835
|
+
className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:px-4 skippr:py-4",
|
|
836
|
+
children: [
|
|
837
|
+
/* @__PURE__ */ jsxs2("div", {
|
|
838
|
+
className: "skippr:mb-4 skippr:text-center",
|
|
839
|
+
children: [
|
|
840
|
+
/* @__PURE__ */ jsx3("p", {
|
|
841
|
+
className: "skippr:text-sm skippr:font-medium skippr:text-foreground",
|
|
842
|
+
children: "Enter verification code"
|
|
843
|
+
}),
|
|
844
|
+
/* @__PURE__ */ jsxs2("p", {
|
|
845
|
+
className: "skippr:mt-1 skippr:text-xs skippr:text-muted-foreground",
|
|
846
|
+
children: [
|
|
847
|
+
"We sent a 6-digit code to",
|
|
848
|
+
" ",
|
|
849
|
+
/* @__PURE__ */ jsx3("span", {
|
|
850
|
+
className: "skippr:font-medium skippr:text-foreground",
|
|
851
|
+
children: email
|
|
852
|
+
})
|
|
853
|
+
]
|
|
854
|
+
})
|
|
855
|
+
]
|
|
856
|
+
}),
|
|
857
|
+
/* @__PURE__ */ jsxs2("form", {
|
|
858
|
+
onSubmit: handleSubmit,
|
|
859
|
+
className: "skippr:flex skippr:flex-col skippr:gap-3",
|
|
860
|
+
children: [
|
|
861
|
+
/* @__PURE__ */ jsx3("div", {
|
|
862
|
+
className: "skippr:flex skippr:justify-center skippr:gap-1.5",
|
|
863
|
+
children: digits.map((digit, index2) => /* @__PURE__ */ jsx3("input", {
|
|
864
|
+
ref: (el) => {
|
|
865
|
+
inputRefs.current[index2] = el;
|
|
866
|
+
},
|
|
867
|
+
type: "text",
|
|
868
|
+
inputMode: "numeric",
|
|
869
|
+
maxLength: 1,
|
|
870
|
+
value: digit,
|
|
871
|
+
onChange: (e) => handleDigitChange(index2, e.target.value),
|
|
872
|
+
onKeyDown: (e) => handleKeyDown(index2, e),
|
|
873
|
+
onPaste: handlePaste,
|
|
874
|
+
disabled: isSubmitting,
|
|
875
|
+
className: "skippr:h-10 skippr:w-10 skippr:rounded-md skippr:border skippr:border-border skippr:bg-background skippr:text-center skippr:text-sm skippr:font-semibold skippr:text-foreground skippr:outline-none focus:skippr:ring-2 focus:skippr:ring-primary/30 focus:skippr:border-primary disabled:skippr:opacity-50"
|
|
876
|
+
}, DIGIT_KEYS[index2]))
|
|
877
|
+
}),
|
|
878
|
+
error && /* @__PURE__ */ jsx3("p", {
|
|
879
|
+
className: "skippr:text-xs skippr:text-center skippr:text-destructive",
|
|
880
|
+
children: error
|
|
881
|
+
}),
|
|
882
|
+
/* @__PURE__ */ jsx3(Button, {
|
|
883
|
+
type: "submit",
|
|
884
|
+
disabled: isSubmitting || digits.join("").length !== OTP_LENGTH,
|
|
885
|
+
className: "skippr:w-full",
|
|
886
|
+
children: isSubmitting ? /* @__PURE__ */ jsx3(LoaderCircle, {
|
|
887
|
+
className: "skippr:size-4 skippr:animate-spin"
|
|
888
|
+
}) : "Verify"
|
|
889
|
+
}),
|
|
890
|
+
/* @__PURE__ */ jsxs2("div", {
|
|
891
|
+
className: "skippr:flex skippr:items-center skippr:justify-between skippr:text-xs",
|
|
892
|
+
children: [
|
|
893
|
+
/* @__PURE__ */ jsx3("button", {
|
|
894
|
+
type: "button",
|
|
895
|
+
onClick: onBack,
|
|
896
|
+
disabled: isSubmitting,
|
|
897
|
+
className: "skippr:text-muted-foreground hover:skippr:text-foreground skippr:transition-colors disabled:skippr:opacity-50",
|
|
898
|
+
children: "Change email"
|
|
899
|
+
}),
|
|
900
|
+
/* @__PURE__ */ jsx3("button", {
|
|
901
|
+
type: "button",
|
|
902
|
+
onClick: handleResend,
|
|
903
|
+
disabled: isSubmitting || resendCooldown > 0,
|
|
904
|
+
className: "skippr:text-primary hover:skippr:opacity-80 skippr:transition-opacity disabled:skippr:opacity-50",
|
|
905
|
+
children: resendCooldown > 0 ? `Resend in ${resendCooldown}s` : "Resend code"
|
|
906
|
+
})
|
|
907
|
+
]
|
|
908
|
+
})
|
|
909
|
+
]
|
|
910
|
+
})
|
|
911
|
+
]
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
|
|
521
915
|
// src/components/MeetingControls.tsx
|
|
522
916
|
import { useLocalParticipant as useLocalParticipant3 } from "@livekit/components-react";
|
|
523
917
|
import { ScreenSharePresets } from "livekit-client";
|
|
524
|
-
import { useCallback as
|
|
918
|
+
import { useCallback as useCallback6, useEffect as useEffect4, useRef as useRef2, useState as useState5 } from "react";
|
|
525
919
|
|
|
526
920
|
// src/lib/format.ts
|
|
527
921
|
function formatTime(seconds) {
|
|
@@ -535,12 +929,12 @@ function parseNumber(s) {
|
|
|
535
929
|
}
|
|
536
930
|
|
|
537
931
|
// src/components/SessionWarningBanner.tsx
|
|
538
|
-
import { jsx as
|
|
932
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
539
933
|
var SESSION_WARNING_THRESHOLD_SECS = 60;
|
|
540
934
|
function SessionWarningBanner({ remaining }) {
|
|
541
935
|
if (remaining === null || remaining <= 0 || remaining > SESSION_WARNING_THRESHOLD_SECS)
|
|
542
936
|
return null;
|
|
543
|
-
return /* @__PURE__ */
|
|
937
|
+
return /* @__PURE__ */ jsx4("div", {
|
|
544
938
|
"data-testid": "session-warning-banner",
|
|
545
939
|
className: "skippr:bg-red-50 skippr:px-4 skippr:py-1.5 skippr:text-center skippr:text-xs skippr:font-medium skippr:text-red-700",
|
|
546
940
|
children: "Session ending soon"
|
|
@@ -548,15 +942,15 @@ function SessionWarningBanner({ remaining }) {
|
|
|
548
942
|
}
|
|
549
943
|
|
|
550
944
|
// src/components/MeetingControls.tsx
|
|
551
|
-
import { jsx as
|
|
945
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
552
946
|
function MeetingControls({ onHangUp }) {
|
|
553
947
|
const maxCallDuration = useAgentState("maxCallDuration", parseNumber, null);
|
|
554
948
|
const { localParticipant } = useLocalParticipant3();
|
|
555
949
|
const isMuted = !localParticipant.isMicrophoneEnabled;
|
|
556
950
|
const isScreenSharing = localParticipant.isScreenShareEnabled;
|
|
557
|
-
const endTimeRef =
|
|
558
|
-
const [remaining, setRemaining] =
|
|
559
|
-
|
|
951
|
+
const endTimeRef = useRef2(null);
|
|
952
|
+
const [remaining, setRemaining] = useState5(null);
|
|
953
|
+
useEffect4(() => {
|
|
560
954
|
if (maxCallDuration === null || endTimeRef.current !== null)
|
|
561
955
|
return;
|
|
562
956
|
endTimeRef.current = Date.now() + maxCallDuration * 1000;
|
|
@@ -568,14 +962,14 @@ function MeetingControls({ onHangUp }) {
|
|
|
568
962
|
const id = setInterval(tick, 1000);
|
|
569
963
|
return () => clearInterval(id);
|
|
570
964
|
}, [maxCallDuration]);
|
|
571
|
-
const toggleMute =
|
|
965
|
+
const toggleMute = useCallback6(async () => {
|
|
572
966
|
try {
|
|
573
967
|
await localParticipant.setMicrophoneEnabled(isMuted);
|
|
574
968
|
} catch (e) {
|
|
575
969
|
console.error("Failed to toggle microphone:", e);
|
|
576
970
|
}
|
|
577
971
|
}, [localParticipant, isMuted]);
|
|
578
|
-
const toggleScreenShare =
|
|
972
|
+
const toggleScreenShare = useCallback6(async () => {
|
|
579
973
|
try {
|
|
580
974
|
await localParticipant.setScreenShareEnabled(!isScreenSharing, {
|
|
581
975
|
video: { displaySurface: "browser" },
|
|
@@ -586,54 +980,54 @@ function MeetingControls({ onHangUp }) {
|
|
|
586
980
|
console.error("Failed to toggle screen share:", e);
|
|
587
981
|
}
|
|
588
982
|
}, [localParticipant, isScreenSharing]);
|
|
589
|
-
|
|
983
|
+
useEffect4(() => {
|
|
590
984
|
toggleMute().then(() => toggleScreenShare());
|
|
591
985
|
}, []);
|
|
592
|
-
return /* @__PURE__ */
|
|
986
|
+
return /* @__PURE__ */ jsxs3("div", {
|
|
593
987
|
children: [
|
|
594
|
-
/* @__PURE__ */
|
|
988
|
+
/* @__PURE__ */ jsx5(SessionWarningBanner, {
|
|
595
989
|
remaining
|
|
596
990
|
}),
|
|
597
|
-
/* @__PURE__ */
|
|
991
|
+
/* @__PURE__ */ jsxs3("div", {
|
|
598
992
|
className: "skippr:flex skippr:items-center skippr:justify-between skippr:border-b skippr:px-4 skippr:py-3",
|
|
599
993
|
children: [
|
|
600
|
-
/* @__PURE__ */
|
|
994
|
+
/* @__PURE__ */ jsxs3("div", {
|
|
601
995
|
className: "skippr:flex skippr:items-center skippr:gap-2",
|
|
602
996
|
children: [
|
|
603
|
-
/* @__PURE__ */
|
|
997
|
+
/* @__PURE__ */ jsx5(Button, {
|
|
604
998
|
size: "icon-sm",
|
|
605
999
|
variant: isMuted ? "destructive" : "outline",
|
|
606
1000
|
onClick: toggleMute,
|
|
607
1001
|
"aria-label": isMuted ? "Unmute" : "Mute",
|
|
608
|
-
children: isMuted ? /* @__PURE__ */
|
|
1002
|
+
children: isMuted ? /* @__PURE__ */ jsx5(MicOff, {
|
|
609
1003
|
className: "skippr:size-4"
|
|
610
|
-
}) : /* @__PURE__ */
|
|
1004
|
+
}) : /* @__PURE__ */ jsx5(Mic, {
|
|
611
1005
|
className: "skippr:size-4"
|
|
612
1006
|
})
|
|
613
1007
|
}),
|
|
614
|
-
/* @__PURE__ */
|
|
1008
|
+
/* @__PURE__ */ jsx5(Button, {
|
|
615
1009
|
size: "icon-sm",
|
|
616
1010
|
variant: isScreenSharing ? "default" : "outline",
|
|
617
1011
|
onClick: toggleScreenShare,
|
|
618
1012
|
"aria-label": isScreenSharing ? "Stop sharing" : "Share screen",
|
|
619
|
-
children: isScreenSharing ? /* @__PURE__ */
|
|
1013
|
+
children: isScreenSharing ? /* @__PURE__ */ jsx5(MonitorOff, {
|
|
620
1014
|
className: "skippr:size-4"
|
|
621
|
-
}) : /* @__PURE__ */
|
|
1015
|
+
}) : /* @__PURE__ */ jsx5(Monitor, {
|
|
622
1016
|
className: "skippr:size-4"
|
|
623
1017
|
})
|
|
624
1018
|
})
|
|
625
1019
|
]
|
|
626
1020
|
}),
|
|
627
|
-
remaining !== null && /* @__PURE__ */
|
|
1021
|
+
remaining !== null && /* @__PURE__ */ jsx5("span", {
|
|
628
1022
|
className: cn("skippr:text-sm skippr:font-medium skippr:tabular-nums", remaining <= SESSION_WARNING_THRESHOLD_SECS ? "skippr:text-red-600 skippr:animate-pulse" : "skippr:text-muted-foreground"),
|
|
629
1023
|
children: formatTime(remaining)
|
|
630
1024
|
}),
|
|
631
|
-
/* @__PURE__ */
|
|
1025
|
+
/* @__PURE__ */ jsx5(Button, {
|
|
632
1026
|
size: "icon-sm",
|
|
633
1027
|
variant: "destructive",
|
|
634
1028
|
onClick: onHangUp,
|
|
635
1029
|
"aria-label": "Hang up",
|
|
636
|
-
children: /* @__PURE__ */
|
|
1030
|
+
children: /* @__PURE__ */ jsx5(PhoneOff, {
|
|
637
1031
|
className: "skippr:size-4"
|
|
638
1032
|
})
|
|
639
1033
|
})
|
|
@@ -644,13 +1038,13 @@ function MeetingControls({ onHangUp }) {
|
|
|
644
1038
|
}
|
|
645
1039
|
|
|
646
1040
|
// src/components/MessageList.tsx
|
|
647
|
-
import { useEffect as
|
|
1041
|
+
import { useEffect as useEffect5, useRef as useRef3 } from "react";
|
|
648
1042
|
|
|
649
1043
|
// src/components/ChatInput.tsx
|
|
650
|
-
import { useState as
|
|
651
|
-
import { jsx as
|
|
1044
|
+
import { useState as useState6 } from "react";
|
|
1045
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
652
1046
|
function ChatInput({ sendChatMessage, isSendingChat }) {
|
|
653
|
-
const [inputText, setInputText] =
|
|
1047
|
+
const [inputText, setInputText] = useState6("");
|
|
654
1048
|
const canSend = inputText.trim().length > 0 && !isSendingChat;
|
|
655
1049
|
function handleSubmit(e) {
|
|
656
1050
|
e.preventDefault();
|
|
@@ -660,11 +1054,11 @@ function ChatInput({ sendChatMessage, isSendingChat }) {
|
|
|
660
1054
|
setInputText("");
|
|
661
1055
|
sendChatMessage(text).catch(() => setInputText(text));
|
|
662
1056
|
}
|
|
663
|
-
return /* @__PURE__ */
|
|
1057
|
+
return /* @__PURE__ */ jsxs4("form", {
|
|
664
1058
|
onSubmit: handleSubmit,
|
|
665
1059
|
className: "skippr:flex skippr:items-center skippr:gap-2 skippr:border-t skippr:border-border skippr:px-3 skippr:py-2",
|
|
666
1060
|
children: [
|
|
667
|
-
/* @__PURE__ */
|
|
1061
|
+
/* @__PURE__ */ jsx6("input", {
|
|
668
1062
|
type: "text",
|
|
669
1063
|
value: inputText,
|
|
670
1064
|
onChange: (e) => setInputText(e.target.value),
|
|
@@ -672,12 +1066,12 @@ function ChatInput({ sendChatMessage, isSendingChat }) {
|
|
|
672
1066
|
className: cn("skippr:flex-1 skippr:rounded-lg skippr:border skippr:border-border skippr:bg-background", "skippr:px-3 skippr:py-2 skippr:text-sm skippr:text-foreground", "skippr:placeholder:text-muted-foreground skippr:outline-none", "skippr:focus:ring-1 skippr:focus:ring-ring"),
|
|
673
1067
|
disabled: isSendingChat
|
|
674
1068
|
}),
|
|
675
|
-
/* @__PURE__ */
|
|
1069
|
+
/* @__PURE__ */ jsx6("button", {
|
|
676
1070
|
type: "submit",
|
|
677
1071
|
disabled: !canSend,
|
|
678
1072
|
"aria-label": "Send message",
|
|
679
1073
|
className: cn("skippr:flex skippr:size-9 skippr:shrink-0 skippr:items-center skippr:justify-center", "skippr:rounded-lg skippr:bg-primary skippr:text-primary-foreground", "skippr:transition-opacity", !canSend && "skippr:opacity-50 skippr:cursor-not-allowed"),
|
|
680
|
-
children: /* @__PURE__ */
|
|
1074
|
+
children: /* @__PURE__ */ jsx6(SendHorizontal, {
|
|
681
1075
|
className: "skippr:size-4"
|
|
682
1076
|
})
|
|
683
1077
|
})
|
|
@@ -686,12 +1080,12 @@ function ChatInput({ sendChatMessage, isSendingChat }) {
|
|
|
686
1080
|
}
|
|
687
1081
|
|
|
688
1082
|
// src/components/ChatMessage.tsx
|
|
689
|
-
import { jsx as
|
|
1083
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
690
1084
|
function ChatMessage({ message }) {
|
|
691
1085
|
const isUser = message.role === "user";
|
|
692
|
-
return /* @__PURE__ */
|
|
1086
|
+
return /* @__PURE__ */ jsx7("div", {
|
|
693
1087
|
className: cn("skippr:flex skippr:w-full skippr:px-4 skippr:py-1", isUser ? "skippr:justify-end" : "skippr:justify-start"),
|
|
694
|
-
children: /* @__PURE__ */
|
|
1088
|
+
children: /* @__PURE__ */ jsx7("div", {
|
|
695
1089
|
className: cn("skippr:max-w-[85%] skippr:whitespace-pre-wrap skippr:rounded-2xl skippr:px-4 skippr:py-2.5 skippr:text-sm skippr:leading-relaxed", isUser ? "skippr:rounded-br-sm skippr:bg-primary skippr:text-primary-foreground" : "skippr:rounded-bl-sm skippr:bg-muted skippr:text-foreground"),
|
|
696
1090
|
children: message.content
|
|
697
1091
|
})
|
|
@@ -699,20 +1093,20 @@ function ChatMessage({ message }) {
|
|
|
699
1093
|
}
|
|
700
1094
|
|
|
701
1095
|
// src/components/TypingIndicator.tsx
|
|
702
|
-
import { jsx as
|
|
1096
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
703
1097
|
function TypingIndicator() {
|
|
704
|
-
return /* @__PURE__ */
|
|
1098
|
+
return /* @__PURE__ */ jsx8("div", {
|
|
705
1099
|
className: "skippr:flex skippr:items-center skippr:gap-1 skippr:px-4 skippr:py-3",
|
|
706
|
-
children: /* @__PURE__ */
|
|
1100
|
+
children: /* @__PURE__ */ jsxs5("div", {
|
|
707
1101
|
className: "skippr:flex skippr:items-center skippr:gap-1 skippr:rounded-2xl skippr:rounded-bl-sm skippr:bg-muted skippr:px-4 skippr:py-2.5",
|
|
708
1102
|
children: [
|
|
709
|
-
/* @__PURE__ */
|
|
1103
|
+
/* @__PURE__ */ jsx8("span", {
|
|
710
1104
|
className: "skippr:size-1.5 skippr:animate-bounce skippr:rounded-full skippr:bg-muted-foreground/60 skippr:[animation-delay:0ms]"
|
|
711
1105
|
}),
|
|
712
|
-
/* @__PURE__ */
|
|
1106
|
+
/* @__PURE__ */ jsx8("span", {
|
|
713
1107
|
className: "skippr:size-1.5 skippr:animate-bounce skippr:rounded-full skippr:bg-muted-foreground/60 skippr:[animation-delay:150ms]"
|
|
714
1108
|
}),
|
|
715
|
-
/* @__PURE__ */
|
|
1109
|
+
/* @__PURE__ */ jsx8("span", {
|
|
716
1110
|
className: "skippr:size-1.5 skippr:animate-bounce skippr:rounded-full skippr:bg-muted-foreground/60 skippr:[animation-delay:300ms]"
|
|
717
1111
|
})
|
|
718
1112
|
]
|
|
@@ -721,38 +1115,38 @@ function TypingIndicator() {
|
|
|
721
1115
|
}
|
|
722
1116
|
|
|
723
1117
|
// src/components/MessageList.tsx
|
|
724
|
-
import { jsx as
|
|
1118
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
725
1119
|
function MessageList({
|
|
726
1120
|
messages,
|
|
727
1121
|
isStreaming,
|
|
728
1122
|
sendChatMessage,
|
|
729
1123
|
isSendingChat
|
|
730
1124
|
}) {
|
|
731
|
-
const scrollRef =
|
|
1125
|
+
const scrollRef = useRef3(null);
|
|
732
1126
|
const lastMessage = messages.length > 0 ? messages[messages.length - 1] : undefined;
|
|
733
|
-
|
|
1127
|
+
useEffect5(() => {
|
|
734
1128
|
scrollRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
735
1129
|
}, [messages.length, lastMessage?.content]);
|
|
736
1130
|
const showTyping = isStreaming && lastMessage?.role === "assistant" && lastMessage.content === "";
|
|
737
|
-
return /* @__PURE__ */
|
|
1131
|
+
return /* @__PURE__ */ jsxs6("div", {
|
|
738
1132
|
className: "skippr:flex skippr:min-h-0 skippr:flex-1 skippr:flex-col",
|
|
739
1133
|
children: [
|
|
740
|
-
/* @__PURE__ */
|
|
1134
|
+
/* @__PURE__ */ jsx9("div", {
|
|
741
1135
|
className: "skippr:min-h-0 skippr:flex-1 skippr:overflow-y-auto",
|
|
742
|
-
children: /* @__PURE__ */
|
|
1136
|
+
children: /* @__PURE__ */ jsxs6("div", {
|
|
743
1137
|
className: "skippr:flex skippr:flex-col skippr:gap-1 skippr:py-3",
|
|
744
1138
|
children: [
|
|
745
|
-
messages.map((message) => /* @__PURE__ */
|
|
1139
|
+
messages.map((message) => /* @__PURE__ */ jsx9(ChatMessage, {
|
|
746
1140
|
message
|
|
747
1141
|
}, message.id)),
|
|
748
|
-
showTyping && /* @__PURE__ */
|
|
749
|
-
/* @__PURE__ */
|
|
1142
|
+
showTyping && /* @__PURE__ */ jsx9(TypingIndicator, {}),
|
|
1143
|
+
/* @__PURE__ */ jsx9("div", {
|
|
750
1144
|
ref: scrollRef
|
|
751
1145
|
})
|
|
752
1146
|
]
|
|
753
1147
|
})
|
|
754
1148
|
}),
|
|
755
|
-
/* @__PURE__ */
|
|
1149
|
+
/* @__PURE__ */ jsx9(ChatInput, {
|
|
756
1150
|
sendChatMessage,
|
|
757
1151
|
isSendingChat
|
|
758
1152
|
})
|
|
@@ -761,30 +1155,30 @@ function MessageList({
|
|
|
761
1155
|
}
|
|
762
1156
|
|
|
763
1157
|
// src/components/QuickActions.tsx
|
|
764
|
-
import { jsx as
|
|
1158
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
765
1159
|
function QuickActions({ onStartSession, isStarting, error }) {
|
|
766
|
-
return /* @__PURE__ */
|
|
1160
|
+
return /* @__PURE__ */ jsxs7("div", {
|
|
767
1161
|
className: "skippr:flex skippr:flex-1 skippr:flex-col skippr:items-center skippr:gap-6 skippr:overflow-y-auto skippr:px-4 skippr:py-4",
|
|
768
1162
|
children: [
|
|
769
|
-
/* @__PURE__ */
|
|
1163
|
+
/* @__PURE__ */ jsx10("p", {
|
|
770
1164
|
className: "skippr:mb-1 skippr:text-sm skippr:text-muted-foreground",
|
|
771
1165
|
children: "How can I help you today?"
|
|
772
1166
|
}),
|
|
773
|
-
/* @__PURE__ */
|
|
1167
|
+
/* @__PURE__ */ jsxs7(Button, {
|
|
774
1168
|
variant: "outline",
|
|
775
1169
|
className: "skippr:h-auto skippr:flex-col skippr:gap-1.5 skippr:whitespace-normal skippr:py-3 skippr:text-xs",
|
|
776
1170
|
onClick: onStartSession,
|
|
777
1171
|
disabled: isStarting,
|
|
778
1172
|
children: [
|
|
779
|
-
isStarting ? /* @__PURE__ */
|
|
1173
|
+
isStarting ? /* @__PURE__ */ jsx10(LoaderCircle, {
|
|
780
1174
|
className: "skippr:size-4 skippr:animate-spin skippr:text-primary"
|
|
781
|
-
}) : /* @__PURE__ */
|
|
1175
|
+
}) : /* @__PURE__ */ jsx10(MessageCircleQuestionMark, {
|
|
782
1176
|
className: "skippr:size-4 skippr:text-primary"
|
|
783
1177
|
}),
|
|
784
1178
|
isStarting ? "Starting..." : "Start Session"
|
|
785
1179
|
]
|
|
786
1180
|
}),
|
|
787
|
-
error && /* @__PURE__ */
|
|
1181
|
+
error && /* @__PURE__ */ jsx10("p", {
|
|
788
1182
|
className: "skippr:text-xs skippr:text-destructive",
|
|
789
1183
|
children: error
|
|
790
1184
|
})
|
|
@@ -793,52 +1187,52 @@ function QuickActions({ onStartSession, isStarting, error }) {
|
|
|
793
1187
|
}
|
|
794
1188
|
|
|
795
1189
|
// src/components/SessionAgenda.tsx
|
|
796
|
-
import { jsx as
|
|
1190
|
+
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
797
1191
|
function SessionAgenda({ phases, questions = [] }) {
|
|
798
1192
|
if (phases.length === 0) {
|
|
799
|
-
return /* @__PURE__ */
|
|
1193
|
+
return /* @__PURE__ */ jsxs8("div", {
|
|
800
1194
|
className: "skippr:flex skippr:flex-col skippr:gap-3 skippr:p-4",
|
|
801
1195
|
children: [
|
|
802
|
-
/* @__PURE__ */
|
|
1196
|
+
/* @__PURE__ */ jsx11("h3", {
|
|
803
1197
|
className: "skippr:text-sm skippr:font-semibold",
|
|
804
1198
|
children: "Agenda"
|
|
805
1199
|
}),
|
|
806
|
-
/* @__PURE__ */
|
|
1200
|
+
/* @__PURE__ */ jsx11("p", {
|
|
807
1201
|
className: "skippr:text-xs skippr:text-muted-foreground",
|
|
808
1202
|
children: "Waiting for session..."
|
|
809
1203
|
})
|
|
810
1204
|
]
|
|
811
1205
|
});
|
|
812
1206
|
}
|
|
813
|
-
return /* @__PURE__ */
|
|
1207
|
+
return /* @__PURE__ */ jsxs8("div", {
|
|
814
1208
|
className: "skippr:flex skippr:flex-col skippr:gap-3 skippr:p-4",
|
|
815
1209
|
children: [
|
|
816
|
-
/* @__PURE__ */
|
|
1210
|
+
/* @__PURE__ */ jsx11("h3", {
|
|
817
1211
|
className: "skippr:text-sm skippr:font-semibold",
|
|
818
1212
|
children: "Agenda"
|
|
819
1213
|
}),
|
|
820
|
-
/* @__PURE__ */
|
|
1214
|
+
/* @__PURE__ */ jsx11("ul", {
|
|
821
1215
|
className: "skippr:flex skippr:flex-col skippr:gap-2",
|
|
822
1216
|
children: phases.map((phase) => {
|
|
823
1217
|
const phaseQuestions = questions.filter((q) => q.phaseName === phase.name);
|
|
824
1218
|
const answeredCount = phaseQuestions.filter((q) => q.status === "answered").length;
|
|
825
1219
|
const totalCount = phaseQuestions.length;
|
|
826
|
-
return /* @__PURE__ */
|
|
1220
|
+
return /* @__PURE__ */ jsxs8("li", {
|
|
827
1221
|
className: "skippr:flex skippr:flex-col skippr:gap-0.5",
|
|
828
1222
|
children: [
|
|
829
|
-
/* @__PURE__ */
|
|
1223
|
+
/* @__PURE__ */ jsxs8("div", {
|
|
830
1224
|
className: "skippr:flex skippr:items-center skippr:gap-2 skippr:text-sm",
|
|
831
1225
|
children: [
|
|
832
|
-
/* @__PURE__ */
|
|
1226
|
+
/* @__PURE__ */ jsx11(PhaseIcon, {
|
|
833
1227
|
status: phase.status
|
|
834
1228
|
}),
|
|
835
|
-
/* @__PURE__ */
|
|
1229
|
+
/* @__PURE__ */ jsx11("span", {
|
|
836
1230
|
className: cn(phase.status === "completed" && "skippr:text-muted-foreground skippr:line-through", phase.status === "active" && "skippr:font-medium skippr:text-primary"),
|
|
837
1231
|
children: phase.name
|
|
838
1232
|
})
|
|
839
1233
|
]
|
|
840
1234
|
}),
|
|
841
|
-
totalCount > 0 && /* @__PURE__ */
|
|
1235
|
+
totalCount > 0 && /* @__PURE__ */ jsxs8("span", {
|
|
842
1236
|
className: "skippr:ml-6 skippr:text-xs skippr:text-muted-foreground",
|
|
843
1237
|
children: [
|
|
844
1238
|
answeredCount,
|
|
@@ -856,62 +1250,78 @@ function SessionAgenda({ phases, questions = [] }) {
|
|
|
856
1250
|
}
|
|
857
1251
|
function PhaseIcon({ status }) {
|
|
858
1252
|
if (status === "completed") {
|
|
859
|
-
return /* @__PURE__ */
|
|
1253
|
+
return /* @__PURE__ */ jsx11("div", {
|
|
860
1254
|
className: "skippr:flex skippr:size-4 skippr:shrink-0 skippr:items-center skippr:justify-center skippr:rounded-full skippr:bg-primary",
|
|
861
|
-
children: /* @__PURE__ */
|
|
1255
|
+
children: /* @__PURE__ */ jsx11(Check, {
|
|
862
1256
|
className: "skippr:size-2.5 skippr:text-primary-foreground",
|
|
863
1257
|
strokeWidth: 3
|
|
864
1258
|
})
|
|
865
1259
|
});
|
|
866
1260
|
}
|
|
867
1261
|
if (status === "active") {
|
|
868
|
-
return /* @__PURE__ */
|
|
1262
|
+
return /* @__PURE__ */ jsx11(LoaderCircle, {
|
|
869
1263
|
className: "skippr:size-4 skippr:shrink-0 skippr:text-primary skippr:animate-spin"
|
|
870
1264
|
});
|
|
871
1265
|
}
|
|
872
|
-
return /* @__PURE__ */
|
|
1266
|
+
return /* @__PURE__ */ jsx11(Circle, {
|
|
873
1267
|
className: "skippr:size-4 skippr:shrink-0 skippr:text-muted-foreground"
|
|
874
1268
|
});
|
|
875
1269
|
}
|
|
876
1270
|
|
|
877
1271
|
// src/components/Sidebar.tsx
|
|
878
|
-
import { jsx as
|
|
1272
|
+
import { jsx as jsx12, jsxs as jsxs9, Fragment } from "react/jsx-runtime";
|
|
879
1273
|
function Sidebar() {
|
|
880
|
-
const {
|
|
881
|
-
|
|
1274
|
+
const {
|
|
1275
|
+
isConnected,
|
|
1276
|
+
isStarting,
|
|
1277
|
+
error,
|
|
1278
|
+
startSession,
|
|
1279
|
+
disconnect,
|
|
1280
|
+
isPanelOpen,
|
|
1281
|
+
closePanel,
|
|
1282
|
+
isAuthenticated,
|
|
1283
|
+
isValidating,
|
|
1284
|
+
authError,
|
|
1285
|
+
requestOtp,
|
|
1286
|
+
verifyOtp,
|
|
1287
|
+
isAuthSubmitting
|
|
1288
|
+
} = useLiveAgent();
|
|
1289
|
+
useEffect6(() => {
|
|
882
1290
|
document.body.style.transition = "margin-right 300ms ease-in-out";
|
|
883
1291
|
document.body.style.marginRight = isPanelOpen ? `${SIDEBAR_WIDTH}px` : "0px";
|
|
884
1292
|
}, [isPanelOpen]);
|
|
885
|
-
|
|
1293
|
+
useEffect6(() => {
|
|
886
1294
|
return () => {
|
|
887
1295
|
document.body.style.marginRight = "";
|
|
888
1296
|
document.body.style.transition = "";
|
|
889
1297
|
};
|
|
890
1298
|
}, []);
|
|
891
|
-
return /* @__PURE__ */
|
|
1299
|
+
return /* @__PURE__ */ jsxs9("div", {
|
|
892
1300
|
className: cn("skippr:fixed skippr:top-0 skippr:right-0 skippr:h-full skippr:z-[9999]", "skippr:bg-background skippr:border-l skippr:border-border", "skippr:flex skippr:flex-col", "skippr:transition-all skippr:duration-300 skippr:ease-in-out skippr:overflow-hidden", !isPanelOpen && "skippr:w-0 skippr:border-l-0"),
|
|
893
1301
|
style: { width: isPanelOpen ? SIDEBAR_WIDTH : undefined },
|
|
894
|
-
children:
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
/* @__PURE__ */ jsx11(ChatHeader, {
|
|
906
|
-
onClose: closePanel
|
|
907
|
-
}),
|
|
908
|
-
/* @__PURE__ */ jsx11(QuickActions, {
|
|
909
|
-
onStartSession: startSession,
|
|
910
|
-
isStarting,
|
|
911
|
-
error
|
|
1302
|
+
children: [
|
|
1303
|
+
/* @__PURE__ */ jsx12(ChatHeader, {
|
|
1304
|
+
onClose: closePanel
|
|
1305
|
+
}),
|
|
1306
|
+
isConnected ? /* @__PURE__ */ jsx12(ConnectedContent, {
|
|
1307
|
+
onDisconnect: disconnect
|
|
1308
|
+
}) : isValidating ? /* @__PURE__ */ jsx12("div", {
|
|
1309
|
+
className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
|
|
1310
|
+
children: /* @__PURE__ */ jsx12("p", {
|
|
1311
|
+
className: "skippr:text-sm skippr:text-muted-foreground",
|
|
1312
|
+
children: "Loading..."
|
|
912
1313
|
})
|
|
913
|
-
|
|
914
|
-
|
|
1314
|
+
}) : isAuthenticated ? /* @__PURE__ */ jsx12(QuickActions, {
|
|
1315
|
+
onStartSession: startSession,
|
|
1316
|
+
isStarting,
|
|
1317
|
+
error
|
|
1318
|
+
}) : /* @__PURE__ */ jsx12(LoginFlow, {
|
|
1319
|
+
requestOtp,
|
|
1320
|
+
verifyOtp,
|
|
1321
|
+
error: authError,
|
|
1322
|
+
isSubmitting: isAuthSubmitting
|
|
1323
|
+
})
|
|
1324
|
+
]
|
|
915
1325
|
});
|
|
916
1326
|
}
|
|
917
1327
|
function ConnectedContent({ onDisconnect }) {
|
|
@@ -921,33 +1331,33 @@ function ConnectedContent({ onDisconnect }) {
|
|
|
921
1331
|
const { phases } = usePhaseUpdates();
|
|
922
1332
|
const { questions } = useQuestionUpdates();
|
|
923
1333
|
if (!isConnected) {
|
|
924
|
-
return /* @__PURE__ */
|
|
1334
|
+
return /* @__PURE__ */ jsx12("div", {
|
|
925
1335
|
className: "skippr:flex skippr:flex-1 skippr:items-center skippr:justify-center",
|
|
926
|
-
children: /* @__PURE__ */
|
|
1336
|
+
children: /* @__PURE__ */ jsx12("p", {
|
|
927
1337
|
className: "skippr:text-sm skippr:text-muted-foreground",
|
|
928
1338
|
children: "Connecting..."
|
|
929
1339
|
})
|
|
930
1340
|
});
|
|
931
1341
|
}
|
|
932
1342
|
const isAgentSpeaking = agentState === "speaking";
|
|
933
|
-
return /* @__PURE__ */
|
|
1343
|
+
return /* @__PURE__ */ jsxs9(Fragment, {
|
|
934
1344
|
children: [
|
|
935
|
-
/* @__PURE__ */
|
|
1345
|
+
/* @__PURE__ */ jsx12(MeetingControls, {
|
|
936
1346
|
onHangUp: onDisconnect
|
|
937
1347
|
}),
|
|
938
|
-
/* @__PURE__ */
|
|
1348
|
+
/* @__PURE__ */ jsxs9("div", {
|
|
939
1349
|
className: "skippr:flex skippr:min-h-0 skippr:flex-1",
|
|
940
1350
|
children: [
|
|
941
|
-
/* @__PURE__ */
|
|
1351
|
+
/* @__PURE__ */ jsx12("div", {
|
|
942
1352
|
className: "skippr:w-[260px] skippr:shrink-0 skippr:overflow-y-auto skippr:border-r",
|
|
943
|
-
children: /* @__PURE__ */
|
|
1353
|
+
children: /* @__PURE__ */ jsx12(SessionAgenda, {
|
|
944
1354
|
phases,
|
|
945
1355
|
questions
|
|
946
1356
|
})
|
|
947
1357
|
}),
|
|
948
|
-
/* @__PURE__ */
|
|
1358
|
+
/* @__PURE__ */ jsx12("div", {
|
|
949
1359
|
className: "skippr:flex skippr:min-w-0 skippr:flex-1 skippr:flex-col",
|
|
950
|
-
children: /* @__PURE__ */
|
|
1360
|
+
children: /* @__PURE__ */ jsx12(MessageList, {
|
|
951
1361
|
messages: allMessages,
|
|
952
1362
|
isStreaming: isAgentSpeaking,
|
|
953
1363
|
sendChatMessage,
|
|
@@ -961,44 +1371,49 @@ function ConnectedContent({ onDisconnect }) {
|
|
|
961
1371
|
}
|
|
962
1372
|
|
|
963
1373
|
// src/components/SidebarTrigger.tsx
|
|
964
|
-
import { jsx as
|
|
1374
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
965
1375
|
var TRIGGER_GAP = 16;
|
|
966
1376
|
var TRIGGER_DEFAULT_RIGHT = 24;
|
|
967
1377
|
function SidebarTrigger() {
|
|
968
1378
|
const { isPanelOpen, togglePanel } = useLiveAgent();
|
|
969
|
-
return /* @__PURE__ */
|
|
1379
|
+
return /* @__PURE__ */ jsx13(Button, {
|
|
970
1380
|
size: "icon-lg",
|
|
971
1381
|
onClick: togglePanel,
|
|
972
1382
|
className: "skippr:fixed skippr:bottom-6 skippr:z-[9998] skippr:size-14 skippr:rounded-full skippr:shadow-lg skippr:transition-all skippr:duration-300",
|
|
973
1383
|
style: { right: isPanelOpen ? SIDEBAR_WIDTH + TRIGGER_GAP : TRIGGER_DEFAULT_RIGHT },
|
|
974
1384
|
title: isPanelOpen ? "Close chat" : "Chat with us",
|
|
975
|
-
children: isPanelOpen ? /* @__PURE__ */
|
|
1385
|
+
children: isPanelOpen ? /* @__PURE__ */ jsx13(X, {
|
|
976
1386
|
className: "skippr:size-6"
|
|
977
|
-
}) : /* @__PURE__ */
|
|
1387
|
+
}) : /* @__PURE__ */ jsx13(MessageCircle, {
|
|
978
1388
|
className: "skippr:size-6"
|
|
979
1389
|
})
|
|
980
1390
|
});
|
|
981
1391
|
}
|
|
982
1392
|
|
|
983
1393
|
// src/components/LiveAgent.tsx
|
|
984
|
-
import { jsx as
|
|
1394
|
+
import { jsx as jsx14, jsxs as jsxs10, Fragment as Fragment2 } from "react/jsx-runtime";
|
|
985
1395
|
function LiveAgent({
|
|
986
1396
|
agentId,
|
|
987
|
-
authToken,
|
|
1397
|
+
authToken: authTokenProp,
|
|
988
1398
|
appKey,
|
|
1399
|
+
userToken,
|
|
989
1400
|
defaultOpen = false,
|
|
990
1401
|
children
|
|
991
1402
|
}) {
|
|
1403
|
+
const auth = useAuth({ appKey });
|
|
1404
|
+
const effectiveAuthToken = authTokenProp || auth.authToken || undefined;
|
|
992
1405
|
const { connection, shouldConnect, isStarting, error, startSession, disconnect } = useSession({
|
|
993
1406
|
agentId,
|
|
994
|
-
authToken,
|
|
995
|
-
appKey
|
|
1407
|
+
authToken: effectiveAuthToken,
|
|
1408
|
+
appKey,
|
|
1409
|
+
userToken
|
|
996
1410
|
});
|
|
997
|
-
const [isPanelOpen, setIsPanelOpen] =
|
|
998
|
-
const openPanel =
|
|
999
|
-
const closePanel =
|
|
1000
|
-
const togglePanel =
|
|
1411
|
+
const [isPanelOpen, setIsPanelOpen] = useState7(defaultOpen);
|
|
1412
|
+
const openPanel = useCallback7(() => setIsPanelOpen(true), []);
|
|
1413
|
+
const closePanel = useCallback7(() => setIsPanelOpen(false), []);
|
|
1414
|
+
const togglePanel = useCallback7(() => setIsPanelOpen((prev) => !prev), []);
|
|
1001
1415
|
const isConnected = connection !== null;
|
|
1416
|
+
const isAuthenticated = !!userToken || !!authTokenProp || auth.isAuthenticated;
|
|
1002
1417
|
const ctx = useMemo4(() => ({
|
|
1003
1418
|
connection,
|
|
1004
1419
|
shouldConnect,
|
|
@@ -1010,7 +1425,14 @@ function LiveAgent({
|
|
|
1010
1425
|
isPanelOpen,
|
|
1011
1426
|
openPanel,
|
|
1012
1427
|
closePanel,
|
|
1013
|
-
togglePanel
|
|
1428
|
+
togglePanel,
|
|
1429
|
+
isAuthenticated,
|
|
1430
|
+
isValidating: auth.isValidating,
|
|
1431
|
+
authError: auth.error,
|
|
1432
|
+
requestOtp: auth.requestOtp,
|
|
1433
|
+
verifyOtp: auth.verifyOtp,
|
|
1434
|
+
logoutAuth: auth.logout,
|
|
1435
|
+
isAuthSubmitting: auth.isSubmitting
|
|
1014
1436
|
}), [
|
|
1015
1437
|
connection,
|
|
1016
1438
|
shouldConnect,
|
|
@@ -1022,19 +1444,26 @@ function LiveAgent({
|
|
|
1022
1444
|
isPanelOpen,
|
|
1023
1445
|
openPanel,
|
|
1024
1446
|
closePanel,
|
|
1025
|
-
togglePanel
|
|
1447
|
+
togglePanel,
|
|
1448
|
+
isAuthenticated,
|
|
1449
|
+
auth.isValidating,
|
|
1450
|
+
auth.error,
|
|
1451
|
+
auth.requestOtp,
|
|
1452
|
+
auth.verifyOtp,
|
|
1453
|
+
auth.logout,
|
|
1454
|
+
auth.isSubmitting
|
|
1026
1455
|
]);
|
|
1027
|
-
const widgetContent = /* @__PURE__ */
|
|
1456
|
+
const widgetContent = /* @__PURE__ */ jsxs10(Fragment2, {
|
|
1028
1457
|
children: [
|
|
1029
|
-
connection && /* @__PURE__ */
|
|
1030
|
-
/* @__PURE__ */
|
|
1031
|
-
/* @__PURE__ */
|
|
1458
|
+
connection && /* @__PURE__ */ jsx14(RoomAudioRenderer, {}),
|
|
1459
|
+
/* @__PURE__ */ jsx14(SidebarTrigger, {}),
|
|
1460
|
+
/* @__PURE__ */ jsx14(Sidebar, {}),
|
|
1032
1461
|
children
|
|
1033
1462
|
]
|
|
1034
1463
|
});
|
|
1035
|
-
return /* @__PURE__ */
|
|
1464
|
+
return /* @__PURE__ */ jsx14(LiveAgentContext.Provider, {
|
|
1036
1465
|
value: ctx,
|
|
1037
|
-
children: connection ? /* @__PURE__ */
|
|
1466
|
+
children: connection ? /* @__PURE__ */ jsx14(LiveKitRoom, {
|
|
1038
1467
|
serverUrl: connection.livekitUrl,
|
|
1039
1468
|
token: connection.token,
|
|
1040
1469
|
connect: shouldConnect,
|