@skippr/live-agent-sdk 0.82.0 → 0.83.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.
@@ -8,7 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
 
9
9
  // src/components/LiveAgent.tsx
10
10
  import { LiveKitRoom, RoomAudioRenderer } from "@livekit/components-react";
11
- import { useCallback as useCallback18, useEffect as useEffect29, useMemo as useMemo7, useRef as useRef23, useState as useState21 } from "react";
11
+ import { useCallback as useCallback18, useEffect as useEffect29, useMemo as useMemo7, useRef as useRef25, useState as useState21 } from "react";
12
12
 
13
13
  // src/capture/useAgentCursor.ts
14
14
  import { useEffect, useState } from "react";
@@ -118,42 +118,177 @@ function useLiveAgent() {
118
118
  }
119
119
 
120
120
  // src/hooks/useSessionHold.ts
121
+ import { useLocalParticipant as useLocalParticipant2 } from "@livekit/components-react/hooks";
122
+ import { Track } from "livekit-client";
123
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef, useState as useState2 } from "react";
124
+
125
+ // src/capture/pausedScreenTrack.ts
126
+ var FALLBACK_WIDTH = 1280;
127
+ var FALLBACK_HEIGHT = 720;
128
+ var DIM_OVERLAY = "rgba(15, 15, 20, 0.55)";
129
+ var AMBER = "#F5B300";
130
+ var LABEL = "Paused";
131
+ var PAUSED_FRAME_FPS = 30;
132
+ var LAST_FRAME_READY_TIMEOUT_MS = 500;
133
+ function drawPausedOverlay(canvas, ctx) {
134
+ const { width, height } = canvas;
135
+ ctx.fillStyle = DIM_OVERLAY;
136
+ ctx.fillRect(0, 0, width, height);
137
+ const fontSize = Math.round(height * 0.07);
138
+ ctx.font = `600 ${fontSize}px system-ui, sans-serif`;
139
+ ctx.textAlign = "center";
140
+ ctx.textBaseline = "middle";
141
+ ctx.fillStyle = AMBER;
142
+ ctx.fillText(LABEL, width / 2, height / 2);
143
+ }
144
+ async function drawLiveScreenFrameInto(ctx, sourceTrack, width, height) {
145
+ const video = document.createElement("video");
146
+ video.muted = true;
147
+ video.srcObject = new MediaStream([sourceTrack]);
148
+ try {
149
+ await video.play();
150
+ await waitForDecodedFrame(video);
151
+ ctx.drawImage(video, 0, 0, width, height);
152
+ return true;
153
+ } catch {
154
+ return false;
155
+ } finally {
156
+ video.srcObject = null;
157
+ }
158
+ }
159
+ async function waitForDecodedFrame(video) {
160
+ if (video.readyState >= video.HAVE_CURRENT_DATA)
161
+ return;
162
+ await new Promise((resolve) => {
163
+ const timeout = setTimeout(resolve, LAST_FRAME_READY_TIMEOUT_MS);
164
+ video.addEventListener("loadeddata", () => {
165
+ clearTimeout(timeout);
166
+ resolve();
167
+ }, { once: true });
168
+ });
169
+ }
170
+ async function createPausedScreenTrack(sourceTrack) {
171
+ const settings = sourceTrack.getSettings();
172
+ const width = settings.width ?? FALLBACK_WIDTH;
173
+ const height = settings.height ?? FALLBACK_HEIGHT;
174
+ const canvas = document.createElement("canvas");
175
+ canvas.width = width;
176
+ canvas.height = height;
177
+ const ctx = canvas.getContext("2d");
178
+ if (!ctx)
179
+ return null;
180
+ const captureStream = canvas.captureStream;
181
+ if (typeof captureStream !== "function")
182
+ return null;
183
+ const capturedLiveFrame = await drawLiveScreenFrameInto(ctx, sourceTrack, width, height);
184
+ if (!capturedLiveFrame) {
185
+ ctx.fillStyle = "#0f0f14";
186
+ ctx.fillRect(0, 0, width, height);
187
+ }
188
+ drawPausedOverlay(canvas, ctx);
189
+ const track = captureStream.call(canvas, PAUSED_FRAME_FPS).getVideoTracks()[0] ?? null;
190
+ if (!track)
191
+ return null;
192
+ track.contentHint = "text";
193
+ return track;
194
+ }
195
+
196
+ // src/hooks/useMediaControls.ts
121
197
  import { useLocalParticipant } from "@livekit/components-react/hooks";
122
- import { useCallback, useEffect as useEffect2, useState as useState2 } from "react";
198
+ import { ScreenSharePresets } from "livekit-client";
199
+ import { useCallback } from "react";
200
+ var SCREEN_SHARE_OPTIONS = {
201
+ video: { displaySurface: "browser" },
202
+ resolution: ScreenSharePresets.h720fps30.resolution,
203
+ contentHint: "detail"
204
+ };
205
+ function useMediaControls() {
206
+ const { localParticipant } = useLocalParticipant();
207
+ const isMuted = !localParticipant.isMicrophoneEnabled;
208
+ const isScreenSharing = localParticipant.isScreenShareEnabled;
209
+ const toggleMute = useCallback(async () => {
210
+ try {
211
+ await localParticipant.setMicrophoneEnabled(isMuted);
212
+ } catch (error) {
213
+ console.error("Failed to toggle microphone:", error);
214
+ }
215
+ }, [localParticipant, isMuted]);
216
+ const toggleScreenShare = useCallback(async () => {
217
+ try {
218
+ await localParticipant.setScreenShareEnabled(!isScreenSharing, SCREEN_SHARE_OPTIONS);
219
+ } catch (error) {
220
+ console.error("Failed to toggle screen share:", error);
221
+ }
222
+ }, [localParticipant, isScreenSharing]);
223
+ return { isMuted, toggleMute, isScreenSharing, toggleScreenShare };
224
+ }
225
+
226
+ // src/hooks/useSessionHold.ts
123
227
  var textEncoder = new TextEncoder;
124
228
  var FALLBACK_PAUSE_TIMEOUT_SECONDS = 120;
125
229
  function useSessionHold({
126
230
  pauseSession,
127
- pauseTimeoutSeconds
231
+ pauseTimeoutSeconds,
232
+ captureMode
128
233
  }) {
129
- const { localParticipant } = useLocalParticipant();
234
+ const { localParticipant } = useLocalParticipant2();
130
235
  const timeoutSeconds = pauseTimeoutSeconds ?? FALLBACK_PAUSE_TIMEOUT_SECONDS;
131
236
  const [isHeld, setIsHeld] = useState2(false);
132
237
  const [countdown, setCountdown] = useState2(timeoutSeconds);
133
- const publish = useCallback(async (type) => {
238
+ const screenWasSharedBeforeHoldRef = useRef(false);
239
+ const holdTransitionInFlightRef = useRef(false);
240
+ const publish = useCallback2(async (type) => {
134
241
  await localParticipant.publishData(textEncoder.encode(JSON.stringify({ type })), {
135
242
  reliable: true,
136
243
  topic: SESSION_HOLD_TOPIC
137
244
  });
138
245
  }, [localParticipant]);
139
- const hold = useCallback(async () => {
246
+ const screenShareTrack = useCallback2(() => {
247
+ return localParticipant.getTrackPublication(Track.Source.ScreenShare)?.videoTrack;
248
+ }, [localParticipant]);
249
+ const pauseScreenShareForHold = useCallback2(async () => {
250
+ if (captureMode !== CAPTURE_MODE.Screenshare)
251
+ return;
252
+ screenWasSharedBeforeHoldRef.current = localParticipant.isScreenShareEnabled;
253
+ const track = screenShareTrack();
254
+ const liveScreenTrack = track?.mediaStreamTrack;
255
+ if (!track || !liveScreenTrack)
256
+ return;
257
+ const pausedFrame = await createPausedScreenTrack(liveScreenTrack);
258
+ if (pausedFrame)
259
+ await track.replaceTrack(pausedFrame);
260
+ liveScreenTrack.stop();
261
+ }, [captureMode, localParticipant, screenShareTrack]);
262
+ const resumeScreenShareOnResume = useCallback2(async () => {
263
+ if (captureMode !== CAPTURE_MODE.Screenshare || !screenWasSharedBeforeHoldRef.current)
264
+ return;
265
+ await localParticipant.setScreenShareEnabled(false);
266
+ await localParticipant.setScreenShareEnabled(true, SCREEN_SHARE_OPTIONS);
267
+ }, [captureMode, localParticipant]);
268
+ const micTrack = useCallback2(() => {
269
+ return localParticipant.getTrackPublication(Track.Source.Microphone)?.audioTrack;
270
+ }, [localParticipant]);
271
+ const hold = useCallback2(async () => {
140
272
  try {
141
273
  await localParticipant.setMicrophoneEnabled(false);
274
+ micTrack()?.mediaStreamTrack?.stop();
275
+ await pauseScreenShareForHold();
142
276
  await publish("pause");
143
277
  setIsHeld(true);
144
278
  } catch (error) {
145
279
  console.error("Failed to hold session:", error);
146
280
  }
147
- }, [localParticipant, publish]);
148
- const release = useCallback(async () => {
281
+ }, [localParticipant, publish, pauseScreenShareForHold, micTrack]);
282
+ const release = useCallback2(async () => {
149
283
  try {
150
284
  await localParticipant.setMicrophoneEnabled(true);
285
+ await resumeScreenShareOnResume();
151
286
  await publish("resume");
152
287
  setIsHeld(false);
153
288
  } catch (error) {
154
289
  console.error("Failed to release session:", error);
155
290
  }
156
- }, [localParticipant, publish]);
291
+ }, [localParticipant, publish, resumeScreenShareOnResume]);
157
292
  useEffect2(() => {
158
293
  if (!isHeld) {
159
294
  setCountdown(timeoutSeconds);
@@ -170,12 +305,14 @@ function useSessionHold({
170
305
  pauseSession();
171
306
  }
172
307
  }, [isHeld, countdown, pauseSession]);
173
- const toggle = useCallback(() => {
174
- if (isHeld) {
175
- release();
176
- } else {
177
- hold();
178
- }
308
+ const toggle = useCallback2(() => {
309
+ if (holdTransitionInFlightRef.current)
310
+ return;
311
+ holdTransitionInFlightRef.current = true;
312
+ const transition = isHeld ? release : hold;
313
+ transition().finally(() => {
314
+ holdTransitionInFlightRef.current = false;
315
+ });
179
316
  }, [isHeld, hold, release]);
180
317
  return { isHeld, countdown, toggle };
181
318
  }
@@ -195,7 +332,8 @@ function SessionHoldProvider({ children }) {
195
332
  }
196
333
  const hold = useSessionHold({
197
334
  pauseSession,
198
- pauseTimeoutSeconds: internalCtx.pauseTimeoutSeconds
335
+ pauseTimeoutSeconds: internalCtx.pauseTimeoutSeconds,
336
+ captureMode: internalCtx.captureMode
199
337
  });
200
338
  return /* @__PURE__ */ jsx(SessionHoldContext.Provider, {
201
339
  value: hold,
@@ -226,20 +364,20 @@ function useSharedTranscriptions() {
226
364
  import { createContext as createContext4, useContext as useContext4 } from "react";
227
365
 
228
366
  // src/hooks/useVoiceTurn.ts
229
- import { useLocalParticipant as useLocalParticipant2 } from "@livekit/components-react/hooks";
230
- import { useCallback as useCallback2, useRef, useState as useState3 } from "react";
367
+ import { useLocalParticipant as useLocalParticipant3 } from "@livekit/components-react/hooks";
368
+ import { useCallback as useCallback3, useRef as useRef2, useState as useState3 } from "react";
231
369
  var textEncoder2 = new TextEncoder;
232
370
  function useVoiceTurn() {
233
- const { localParticipant } = useLocalParticipant2();
371
+ const { localParticipant } = useLocalParticipant3();
234
372
  const [isCapturingSpeech, setIsCapturingSpeech] = useState3(false);
235
- const capturingRef = useRef(false);
236
- const publish = useCallback2(async (type) => {
373
+ const capturingRef = useRef2(false);
374
+ const publish = useCallback3(async (type) => {
237
375
  await localParticipant.publishData(textEncoder2.encode(JSON.stringify({ type })), {
238
376
  reliable: true,
239
377
  topic: MIC_MODE_TURN_TOPIC
240
378
  });
241
379
  }, [localParticipant]);
242
- const startRecording = useCallback2(async () => {
380
+ const startRecording = useCallback3(async () => {
243
381
  try {
244
382
  await localParticipant.setMicrophoneEnabled(true);
245
383
  await publish("start");
@@ -247,7 +385,7 @@ function useVoiceTurn() {
247
385
  console.error("Failed to start voice turn:", error);
248
386
  }
249
387
  }, [localParticipant, publish]);
250
- const commitRecording = useCallback2(async () => {
388
+ const commitRecording = useCallback3(async () => {
251
389
  try {
252
390
  await localParticipant.setMicrophoneEnabled(false);
253
391
  await publish("commit");
@@ -255,21 +393,21 @@ function useVoiceTurn() {
255
393
  console.error("Failed to commit voice turn:", error);
256
394
  }
257
395
  }, [localParticipant, publish]);
258
- const start = useCallback2(() => {
396
+ const start = useCallback3(() => {
259
397
  if (capturingRef.current)
260
398
  return;
261
399
  capturingRef.current = true;
262
400
  setIsCapturingSpeech(true);
263
401
  startRecording();
264
402
  }, [startRecording]);
265
- const commit = useCallback2(() => {
403
+ const commit = useCallback3(() => {
266
404
  if (!capturingRef.current)
267
405
  return;
268
406
  capturingRef.current = false;
269
407
  setIsCapturingSpeech(false);
270
408
  commitRecording();
271
409
  }, [commitRecording]);
272
- const toggle = useCallback2(() => {
410
+ const toggle = useCallback3(() => {
273
411
  if (capturingRef.current)
274
412
  commit();
275
413
  else
@@ -298,7 +436,7 @@ function useVoiceTurnContext() {
298
436
  }
299
437
 
300
438
  // src/hooks/useAdoptionGoals.ts
301
- import { useCallback as useCallback3, useEffect as useEffect3, useMemo, useState as useState4 } from "react";
439
+ import { useCallback as useCallback4, useEffect as useEffect3, useMemo, useState as useState4 } from "react";
302
440
 
303
441
  // src/lib/hashMatch.ts
304
442
  function globToRegExp(pattern) {
@@ -368,7 +506,7 @@ function useAdoptionGoals({
368
506
  }) {
369
507
  const [candidates, setCandidates] = useState4([]);
370
508
  const [hash, setHash] = useState4(window.location.hash);
371
- const match = useCallback3(async () => {
509
+ const match = useCallback4(async () => {
372
510
  try {
373
511
  const resp = await authedFetch(`${API_URL}/v1/adoption/goals/match`, {
374
512
  method: "POST",
@@ -418,21 +556,21 @@ function useAdoptionGoals({
418
556
  return hashSpecific;
419
557
  return candidates.filter((goal) => goal.hashPattern === null);
420
558
  }, [candidates, hash]);
421
- const postStatus = useCallback3((goalId, status) => {
559
+ const postStatus = useCallback4((goalId, status) => {
422
560
  authedFetch(`${API_URL}/v1/adoption/goals/${goalId}/status`, {
423
561
  method: "POST",
424
562
  headers: { "Content-Type": "application/json" },
425
563
  body: JSON.stringify({ status })
426
564
  }).catch((e) => console.warn("[Skippr] adoption status update failed", e));
427
565
  }, [authedFetch]);
428
- const attendGoal = useCallback3((goalId) => {
566
+ const attendGoal = useCallback4((goalId) => {
429
567
  postStatus(goalId, "attended" /* Attended */);
430
568
  }, [postStatus]);
431
569
  return { goals, attendGoal };
432
570
  }
433
571
 
434
572
  // src/hooks/useAuth.ts
435
- import { useCallback as useCallback4, useEffect as useEffect4, useState as useState5 } from "react";
573
+ import { useCallback as useCallback5, useEffect as useEffect4, useState as useState5 } from "react";
436
574
  var API_URL2 = "https://specialist.skippr.ai/api";
437
575
  function storageKey(appKey) {
438
576
  return `skippr_auth_${appKey}`;
@@ -498,7 +636,7 @@ function useAuth({ appKey }) {
498
636
  window.addEventListener("skippr:logout", handleLogout);
499
637
  return () => window.removeEventListener("skippr:logout", handleLogout);
500
638
  }, []);
501
- const requestOtp = useCallback4(async (email) => {
639
+ const requestOtp = useCallback5(async (email) => {
502
640
  if (!appKey)
503
641
  return false;
504
642
  setIsSubmitting(true);
@@ -525,7 +663,7 @@ function useAuth({ appKey }) {
525
663
  setIsSubmitting(false);
526
664
  }
527
665
  }, [appKey]);
528
- const verifyOtp = useCallback4(async (email, code) => {
666
+ const verifyOtp = useCallback5(async (email, code) => {
529
667
  if (!appKey)
530
668
  return;
531
669
  setIsSubmitting(true);
@@ -554,7 +692,7 @@ function useAuth({ appKey }) {
554
692
  setIsSubmitting(false);
555
693
  }
556
694
  }, [appKey]);
557
- const logout = useCallback4(async () => {
695
+ const logout = useCallback5(async () => {
558
696
  const token = authToken;
559
697
  if (appKey)
560
698
  clearStoredToken(appKey);
@@ -585,7 +723,7 @@ function useAuth({ appKey }) {
585
723
  }
586
724
 
587
725
  // src/hooks/useAutoStart.ts
588
- import { useEffect as useEffect5, useMemo as useMemo2, useRef as useRef2 } from "react";
726
+ import { useEffect as useEffect5, useMemo as useMemo2, useRef as useRef3 } from "react";
589
727
 
590
728
  // src/lib/agentMode.ts
591
729
  var AGENT_MODE = {
@@ -665,7 +803,7 @@ function useAutoStart({
665
803
  bearerToken,
666
804
  selectModule
667
805
  }) {
668
- const hasAutoStartedRef = useRef2(false);
806
+ const hasAutoStartedRef = useRef3(false);
669
807
  const autoStartModule = useMemo2(() => availableModules.find((m) => {
670
808
  if (!m.uiPreferences?.autoStart)
671
809
  return false;
@@ -704,7 +842,7 @@ function useAutoStart({
704
842
  }
705
843
 
706
844
  // src/hooks/useAvailableModules.ts
707
- import { useCallback as useCallback5, useEffect as useEffect6, useState as useState6 } from "react";
845
+ import { useCallback as useCallback6, useEffect as useEffect6, useState as useState6 } from "react";
708
846
  var EMPTY_DEFAULT = { agentId: null, sessionId: null };
709
847
  var API_URL3 = "https://specialist.skippr.ai/api";
710
848
  function useAvailableModules({
@@ -718,7 +856,7 @@ function useAvailableModules({
718
856
  const [isLoading, setIsLoading] = useState6(false);
719
857
  const [hasResolved, setHasResolved] = useState6(false);
720
858
  const [error, setError] = useState6(null);
721
- const fetchModules = useCallback5(async () => {
859
+ const fetchModules = useCallback6(async () => {
722
860
  setIsLoading(true);
723
861
  setHasResolved(false);
724
862
  setError(null);
@@ -755,7 +893,7 @@ function useAvailableModules({
755
893
  }
756
894
 
757
895
  // src/hooks/usePlanUpdates.ts
758
- import { useCallback as useCallback6 } from "react";
896
+ import { useCallback as useCallback7 } from "react";
759
897
 
760
898
  // src/hooks/useAgentState.ts
761
899
  import { useRemoteParticipants } from "@livekit/components-react/hooks";
@@ -809,12 +947,12 @@ function parsePlan(json) {
809
947
  return null;
810
948
  }
811
949
  function usePlanUpdates() {
812
- const parse = useCallback6(parsePlan, []);
950
+ const parse = useCallback7(parsePlan, []);
813
951
  return useAgentState(PLAN_ATTR, parse, null);
814
952
  }
815
953
 
816
954
  // src/hooks/useSession.ts
817
- import { useCallback as useCallback7, useEffect as useEffect8, useRef as useRef3, useState as useState8 } from "react";
955
+ import { useCallback as useCallback8, useEffect as useEffect8, useRef as useRef4, useState as useState8 } from "react";
818
956
  var API_URL4 = "https://specialist.skippr.ai/api";
819
957
  async function fetchSessionMessages(sessionId, authedFetch) {
820
958
  try {
@@ -880,13 +1018,13 @@ function useSession({
880
1018
  const [pauseTimeoutSeconds, setPauseTimeoutSeconds] = useState8(null);
881
1019
  const [historyMessages, setHistoryMessages] = useState8([]);
882
1020
  const [authFailed, setAuthFailed] = useState8(false);
883
- const tokenRef = useRef3(authToken ? { token: authToken, expiresAt: null } : null);
884
- const getUserTokenRef = useRef3(getUserToken);
1021
+ const tokenRef = useRef4(authToken ? { token: authToken, expiresAt: null } : null);
1022
+ const getUserTokenRef = useRef4(getUserToken);
885
1023
  getUserTokenRef.current = getUserToken ?? (userToken ? () => Promise.resolve(userToken) : undefined);
886
- const failedBearerRef = useRef3(null);
887
- const inFlightExchangeRef = useRef3(null);
888
- const canExchange = useCallback7(() => !!appKey && !!getUserTokenRef.current, [appKey]);
889
- const reExchange = useCallback7(async () => {
1024
+ const failedBearerRef = useRef4(null);
1025
+ const inFlightExchangeRef = useRef4(null);
1026
+ const canExchange = useCallback8(() => !!appKey && !!getUserTokenRef.current, [appKey]);
1027
+ const reExchange = useCallback8(async () => {
890
1028
  if (inFlightExchangeRef.current)
891
1029
  return inFlightExchangeRef.current;
892
1030
  const provider = getUserTokenRef.current;
@@ -906,7 +1044,7 @@ function useSession({
906
1044
  inFlightExchangeRef.current = null;
907
1045
  }
908
1046
  }, [appKey]);
909
- const getValidBearer = useCallback7(async () => {
1047
+ const getValidBearer = useCallback8(async () => {
910
1048
  const current = tokenRef.current;
911
1049
  if (current) {
912
1050
  if (current.expiresAt === null)
@@ -918,7 +1056,7 @@ function useSession({
918
1056
  return reExchange();
919
1057
  return current?.token ?? null;
920
1058
  }, [canExchange, reExchange]);
921
- const authedFetch = useCallback7(async (input, init = {}) => {
1059
+ const authedFetch = useCallback8(async (input, init = {}) => {
922
1060
  const isSecretMode = canExchange();
923
1061
  const onTerminalAuthFailure = () => {
924
1062
  if (isSecretMode)
@@ -979,8 +1117,8 @@ function useSession({
979
1117
  stale = true;
980
1118
  };
981
1119
  }, [authToken, canExchange, reExchange]);
982
- const isStartingRef = useRef3(false);
983
- const pauseOnUnloadRef = useRef3(null);
1120
+ const isStartingRef = useRef4(false);
1121
+ const pauseOnUnloadRef = useRef4(null);
984
1122
  pauseOnUnloadRef.current = connection !== null && !isPaused && sessionId && bearerToken ? { sessionId, bearerToken } : null;
985
1123
  useEffect8(() => {
986
1124
  const onPageHide = () => {
@@ -997,7 +1135,7 @@ function useSession({
997
1135
  window.addEventListener("pagehide", onPageHide);
998
1136
  return () => window.removeEventListener("pagehide", onPageHide);
999
1137
  }, []);
1000
- const startSession = useCallback7(async ({
1138
+ const startSession = useCallback8(async ({
1001
1139
  agentId,
1002
1140
  agentControls,
1003
1141
  existingSessionId,
@@ -1092,7 +1230,7 @@ function useSession({
1092
1230
  setIsStarting(false);
1093
1231
  }
1094
1232
  }, [captureMode, bearerToken, authedFetch, onStart, onStartError]);
1095
- const pauseSession = useCallback7(async () => {
1233
+ const pauseSession = useCallback8(async () => {
1096
1234
  if (!sessionId || !bearerToken)
1097
1235
  return;
1098
1236
  setIsPausing(true);
@@ -1118,7 +1256,7 @@ function useSession({
1118
1256
  setIsPaused(true);
1119
1257
  setIsPausing(false);
1120
1258
  }, [sessionId, bearerToken, authedFetch, pendingScreenStream]);
1121
- const disconnect = useCallback7(async () => {
1259
+ const disconnect = useCallback8(async () => {
1122
1260
  setIsDisconnecting(true);
1123
1261
  try {
1124
1262
  if (sessionId && bearerToken) {
@@ -1523,7 +1661,7 @@ var __iconNode24 = [
1523
1661
  ];
1524
1662
  var X = createLucideIcon("x", __iconNode24);
1525
1663
  // src/components/AgentCursor.tsx
1526
- import { useContext as useContext6, useEffect as useEffect10, useLayoutEffect, useRef as useRef4, useState as useState10 } from "react";
1664
+ import { useContext as useContext6, useEffect as useEffect10, useLayoutEffect, useRef as useRef5, useState as useState10 } from "react";
1527
1665
 
1528
1666
  // src/capture/elementRef.ts
1529
1667
  function safeGetIframeDocument(iframe) {
@@ -1711,13 +1849,13 @@ function AgentCursor({
1711
1849
  const [phase, setPhase] = useState10("idle");
1712
1850
  const [ringBox, setRingBox] = useState10(null);
1713
1851
  const [clickPulse, setClickPulse] = useState10(0);
1714
- const cursorElRef = useRef4(null);
1715
- const pathRef = useRef4(null);
1716
- const prevCursorRef = useRef4(null);
1717
- const traceRef = useRef4(null);
1718
- const timersRef = useRef4(new Set);
1719
- const trackFrameRef = useRef4(null);
1720
- const glideFrameRef = useRef4(null);
1852
+ const cursorElRef = useRef5(null);
1853
+ const pathRef = useRef5(null);
1854
+ const prevCursorRef = useRef5(null);
1855
+ const traceRef = useRef5(null);
1856
+ const timersRef = useRef5(new Set);
1857
+ const trackFrameRef = useRef5(null);
1858
+ const glideFrameRef = useRef5(null);
1721
1859
  const clearTimers = () => {
1722
1860
  for (const t of timersRef.current)
1723
1861
  clearTimeout(t);
@@ -1956,16 +2094,16 @@ function AgentCursor({
1956
2094
  }
1957
2095
 
1958
2096
  // src/components/AutoStartMedia.tsx
1959
- import { useConnectionState, useLocalParticipant as useLocalParticipant3 } from "@livekit/components-react/hooks";
1960
- import { ConnectionState, Track } from "livekit-client";
1961
- import { useEffect as useEffect11, useRef as useRef5 } from "react";
2097
+ import { useConnectionState, useLocalParticipant as useLocalParticipant4 } from "@livekit/components-react/hooks";
2098
+ import { ConnectionState, Track as Track2 } from "livekit-client";
2099
+ import { useEffect as useEffect11, useRef as useRef6 } from "react";
1962
2100
  function AutoStartMedia({
1963
2101
  pendingScreenStream,
1964
2102
  pushOrTapMicMode = false
1965
2103
  }) {
1966
- const { localParticipant } = useLocalParticipant3();
2104
+ const { localParticipant } = useLocalParticipant4();
1967
2105
  const connectionState = useConnectionState();
1968
- const didStartRef = useRef5(false);
2106
+ const didStartRef = useRef6(false);
1969
2107
  useEffect11(() => {
1970
2108
  if (didStartRef.current)
1971
2109
  return;
@@ -1979,7 +2117,7 @@ function AutoStartMedia({
1979
2117
  const videoTrack = pendingScreenStream.getVideoTracks()[0];
1980
2118
  if (videoTrack) {
1981
2119
  videoTrack.contentHint = "detail";
1982
- localParticipant.publishTrack(videoTrack, { source: Track.Source.ScreenShare }).catch((error) => {
2120
+ localParticipant.publishTrack(videoTrack, { source: Track2.Source.ScreenShare }).catch((error) => {
1983
2121
  console.error("Failed to publish screen share track:", error);
1984
2122
  for (const track of pendingScreenStream.getTracks())
1985
2123
  track.stop();
@@ -1991,9 +2129,9 @@ function AutoStartMedia({
1991
2129
  }
1992
2130
 
1993
2131
  // src/components/DomCapture.tsx
1994
- import { useConnectionState as useConnectionState2, useLocalParticipant as useLocalParticipant4 } from "@livekit/components-react/hooks";
1995
- import { ConnectionState as ConnectionState2, ScreenSharePresets, Track as Track2 } from "livekit-client";
1996
- import { useEffect as useEffect12, useRef as useRef6 } from "react";
2132
+ import { useConnectionState as useConnectionState2, useLocalParticipant as useLocalParticipant5 } from "@livekit/components-react/hooks";
2133
+ import { ConnectionState as ConnectionState2, ScreenSharePresets as ScreenSharePresets2, Track as Track3 } from "livekit-client";
2134
+ import { useEffect as useEffect12, useRef as useRef7 } from "react";
1997
2135
 
1998
2136
  // src/capture/a11yUtils.ts
1999
2137
  var ROLE_BY_TAG = {
@@ -2787,7 +2925,7 @@ async function snapToCanvas(element, options = {}) {
2787
2925
  var SNAPSHOT_INTERVAL_MS = 3000;
2788
2926
  var A11Y_PUBLISH_INTERVAL_MS = 2000;
2789
2927
  var FIRST_SNAPSHOT_DELAY_MS = 400;
2790
- var CAPTURE_PRESET = ScreenSharePresets.h1080fps30;
2928
+ var CAPTURE_PRESET = ScreenSharePresets2.h1080fps30;
2791
2929
  var CAPTURE_FPS = CAPTURE_PRESET.encoding.maxFramerate ?? 30;
2792
2930
  var CAPTURE_BITRATE = 4000000;
2793
2931
  var DOM_SNAPSHOT_GZIP_THRESHOLD_BYTES = 14000;
@@ -2823,7 +2961,7 @@ function getCanvasCaptureStream(canvas, fps) {
2823
2961
  }
2824
2962
  return captureStreamFn.call(canvas, fps);
2825
2963
  }
2826
- async function paintViewportSnapshot(canvas, ctx) {
2964
+ async function paintViewportSnapshot(canvas, ctx, isStillWanted) {
2827
2965
  const dpr = window.devicePixelRatio || 1;
2828
2966
  const snapshotCanvas = await snapToCanvas(document.documentElement, {
2829
2967
  filter: shouldIncludeInSnapshot,
@@ -2832,6 +2970,8 @@ async function paintViewportSnapshot(canvas, ctx) {
2832
2970
  fast: false,
2833
2971
  dpr
2834
2972
  });
2973
+ if (!isStillWanted())
2974
+ return;
2835
2975
  const sourceX = window.scrollX * dpr;
2836
2976
  const sourceY = window.scrollY * dpr;
2837
2977
  const sourceWidth = window.innerWidth * dpr;
@@ -2892,9 +3032,13 @@ async function unpublishAndStopTrack(localParticipant, videoTrack) {
2892
3032
  videoTrack.stop();
2893
3033
  }
2894
3034
  function DomCapture({ pushOrTapMicMode = false }) {
2895
- const { localParticipant } = useLocalParticipant4();
3035
+ const { localParticipant } = useLocalParticipant5();
2896
3036
  const connectionState = useConnectionState2();
2897
- const didStartRef = useRef6(false);
3037
+ const { isHeld } = useSessionHoldContext();
3038
+ const didStartRef = useRef7(false);
3039
+ const pausedRef = useRef7(false);
3040
+ const freezeCaptureRef = useRef7(null);
3041
+ const resumeCaptureRef = useRef7(null);
2898
3042
  useEffect12(() => {
2899
3043
  if (didStartRef.current)
2900
3044
  return;
@@ -2916,11 +3060,11 @@ function DomCapture({ pushOrTapMicMode = false }) {
2916
3060
  let snapshotInFlight = false;
2917
3061
  let a11yPublishInFlight = false;
2918
3062
  let consecutiveCaptureFailures = 0;
2919
- if (!pushOrTapMicMode) {
3063
+ if (!pushOrTapMicMode && !localParticipant.isMicrophoneEnabled) {
2920
3064
  localParticipant.setMicrophoneEnabled(true).catch((error) => console.error("Failed to enable microphone:", error));
2921
3065
  }
2922
3066
  localParticipant.publishTrack(videoTrack, {
2923
- source: Track2.Source.ScreenShare,
3067
+ source: Track3.Source.ScreenShare,
2924
3068
  videoEncoding: {
2925
3069
  maxBitrate: CAPTURE_BITRATE,
2926
3070
  maxFramerate: CAPTURE_FPS
@@ -2932,11 +3076,11 @@ function DomCapture({ pushOrTapMicMode = false }) {
2932
3076
  track.stop();
2933
3077
  });
2934
3078
  const tickSnapshot = async () => {
2935
- if (cancelled || snapshotInFlight)
3079
+ if (cancelled || snapshotInFlight || pausedRef.current)
2936
3080
  return;
2937
3081
  snapshotInFlight = true;
2938
3082
  try {
2939
- await paintViewportSnapshot(canvas, ctx);
3083
+ await paintViewportSnapshot(canvas, ctx, () => !cancelled && !pausedRef.current);
2940
3084
  if (cancelled)
2941
3085
  return;
2942
3086
  consecutiveCaptureFailures = 0;
@@ -2952,7 +3096,7 @@ function DomCapture({ pushOrTapMicMode = false }) {
2952
3096
  }
2953
3097
  };
2954
3098
  const tickA11yPublish = async () => {
2955
- if (cancelled || a11yPublishInFlight)
3099
+ if (cancelled || a11yPublishInFlight || pausedRef.current)
2956
3100
  return;
2957
3101
  a11yPublishInFlight = true;
2958
3102
  try {
@@ -2989,9 +3133,20 @@ function DomCapture({ pushOrTapMicMode = false }) {
2989
3133
  scheduleNextSnapshot(FIRST_SNAPSHOT_DELAY_MS);
2990
3134
  tickA11yPublish();
2991
3135
  const a11yPublishTimer = setInterval(tickA11yPublish, A11Y_PUBLISH_INTERVAL_MS);
3136
+ freezeCaptureRef.current = () => {
3137
+ pausedRef.current = true;
3138
+ drawPausedOverlay(canvas, ctx);
3139
+ };
3140
+ resumeCaptureRef.current = () => {
3141
+ pausedRef.current = false;
3142
+ tickA11yPublish();
3143
+ tickSnapshot();
3144
+ };
2992
3145
  return () => {
2993
3146
  cancelled = true;
2994
3147
  didStartRef.current = false;
3148
+ freezeCaptureRef.current = null;
3149
+ resumeCaptureRef.current = null;
2995
3150
  if (snapshotTimer)
2996
3151
  clearTimeout(snapshotTimer);
2997
3152
  clearInterval(a11yPublishTimer);
@@ -3002,12 +3157,19 @@ function DomCapture({ pushOrTapMicMode = false }) {
3002
3157
  track.stop();
3003
3158
  };
3004
3159
  }, [connectionState, localParticipant, pushOrTapMicMode]);
3160
+ useEffect12(() => {
3161
+ if (isHeld) {
3162
+ freezeCaptureRef.current?.();
3163
+ } else {
3164
+ resumeCaptureRef.current?.();
3165
+ }
3166
+ }, [isHeld]);
3005
3167
  return null;
3006
3168
  }
3007
3169
 
3008
3170
  // src/components/HighlightOverlay.tsx
3009
3171
  import { useDataChannel } from "@livekit/components-react/hooks";
3010
- import { useCallback as useCallback8, useEffect as useEffect13, useRef as useRef7 } from "react";
3172
+ import { useCallback as useCallback9, useEffect as useEffect13, useRef as useRef8 } from "react";
3011
3173
  var HIGHLIGHT_AUTO_CLEAR_MS = 25000;
3012
3174
  var textDecoder = new TextDecoder;
3013
3175
  function parseHighlightMessage(payload) {
@@ -3030,16 +3192,16 @@ function parseHighlightMessage(payload) {
3030
3192
  }
3031
3193
  }
3032
3194
  function HighlightOverlay() {
3033
- const targetRef = useRef7(null);
3034
- const autoClearRef = useRef7(null);
3035
- const clear = useCallback8(() => {
3195
+ const targetRef = useRef8(null);
3196
+ const autoClearRef = useRef8(null);
3197
+ const clear = useCallback9(() => {
3036
3198
  if (autoClearRef.current)
3037
3199
  clearTimeout(autoClearRef.current);
3038
3200
  autoClearRef.current = null;
3039
3201
  targetRef.current = null;
3040
3202
  clearCursorTarget("guide");
3041
3203
  }, []);
3042
- const onHighlightMessage = useCallback8((msg) => {
3204
+ const onHighlightMessage = useCallback9((msg) => {
3043
3205
  const parsed = parseHighlightMessage(msg.payload);
3044
3206
  if (!parsed)
3045
3207
  return;
@@ -3078,19 +3240,19 @@ function HighlightOverlay() {
3078
3240
  }
3079
3241
 
3080
3242
  // src/components/MinimizedBubble.tsx
3081
- import { useContext as useContext7, useEffect as useEffect15, useRef as useRef9, useState as useState11 } from "react";
3243
+ import { useContext as useContext7, useEffect as useEffect15, useRef as useRef10, useState as useState11 } from "react";
3082
3244
 
3083
3245
  // src/hooks/useLauncherDrag.ts
3084
- import { useEffect as useEffect14, useRef as useRef8 } from "react";
3246
+ import { useEffect as useEffect14, useRef as useRef9 } from "react";
3085
3247
  import { flushSync } from "react-dom";
3086
3248
  var DRAG_THRESHOLD_PX = 5;
3087
3249
  function useLauncherDrag(containerRef, onDrop, followRefs, reportDragging) {
3088
- const wasDraggedRef = useRef8(false);
3089
- const onDropRef = useRef8(onDrop);
3250
+ const wasDraggedRef = useRef9(false);
3251
+ const onDropRef = useRef9(onDrop);
3090
3252
  onDropRef.current = onDrop;
3091
- const followTargetsRef = useRef8(followRefs);
3253
+ const followTargetsRef = useRef9(followRefs);
3092
3254
  followTargetsRef.current = followRefs;
3093
- const reportDraggingRef = useRef8(reportDragging);
3255
+ const reportDraggingRef = useRef9(reportDragging);
3094
3256
  reportDraggingRef.current = reportDragging;
3095
3257
  useEffect14(() => {
3096
3258
  const el = containerRef.current;
@@ -3472,8 +3634,8 @@ function MinimizedBubble({
3472
3634
  const [goalsAutoHidden, setGoalsAutoHidden] = useState11(false);
3473
3635
  const [isLauncherHovered, setIsLauncherHovered] = useState11(false);
3474
3636
  const [visitHref, setVisitHref] = useState11(() => window.location.href);
3475
- const revealedHrefRef = useRef9(null);
3476
- const hoverContainerRef = useRef9(null);
3637
+ const revealedHrefRef = useRef10(null);
3638
+ const hoverContainerRef = useRef10(null);
3477
3639
  useEffect15(() => subscribeToLocationChange(() => setVisitHref(window.location.href)), []);
3478
3640
  useEffect15(() => {
3479
3641
  const el = hoverContainerRef.current;
@@ -3587,7 +3749,7 @@ function MinimizedBubble({
3587
3749
 
3588
3750
  // src/components/PageActionHandler.tsx
3589
3751
  import { useDataChannel as useDataChannel2 } from "@livekit/components-react/hooks";
3590
- import { useCallback as useCallback9, useEffect as useEffect16, useRef as useRef10 } from "react";
3752
+ import { useCallback as useCallback10, useEffect as useEffect16, useRef as useRef11 } from "react";
3591
3753
  var STEP_MAX_WAIT_MS = 5000;
3592
3754
  var POST_ACTION_SETTLE_SNAPSHOT_MS = 300;
3593
3755
  var TRAILING_ACTION_FLUSH_AFTER_STOP_MS = 1000;
@@ -3805,14 +3967,14 @@ function labelFor(action) {
3805
3967
  }
3806
3968
  }
3807
3969
  function PageActionHandler() {
3808
- const mountedRef = useRef10(true);
3809
- const queueRef = useRef10([]);
3810
- const drainingRef = useRef10(false);
3811
- const settleTimerRef = useRef10(null);
3812
- const endStepRef = useRef10(null);
3813
- const actionsStoppedRef = useRef10(false);
3814
- const ignoreActionsArrivingBeforeRef = useRef10(0);
3815
- const runStep = useCallback9((action) => {
3970
+ const mountedRef = useRef11(true);
3971
+ const queueRef = useRef11([]);
3972
+ const drainingRef = useRef11(false);
3973
+ const settleTimerRef = useRef11(null);
3974
+ const endStepRef = useRef11(null);
3975
+ const actionsStoppedRef = useRef11(false);
3976
+ const ignoreActionsArrivingBeforeRef = useRef11(0);
3977
+ const runStep = useCallback10((action) => {
3816
3978
  return new Promise((resolve) => {
3817
3979
  if (action.type === "scroll_page") {
3818
3980
  let scrolled = false;
@@ -3881,7 +4043,7 @@ function PageActionHandler() {
3881
4043
  });
3882
4044
  });
3883
4045
  }, []);
3884
- const drain = useCallback9(async () => {
4046
+ const drain = useCallback10(async () => {
3885
4047
  if (drainingRef.current)
3886
4048
  return;
3887
4049
  drainingRef.current = true;
@@ -3902,7 +4064,7 @@ function PageActionHandler() {
3902
4064
  }
3903
4065
  }
3904
4066
  }, [runStep]);
3905
- const onMessage = useCallback9((msg) => {
4067
+ const onMessage = useCallback10((msg) => {
3906
4068
  const action = parsePageAction(msg.payload);
3907
4069
  if (!action)
3908
4070
  return;
@@ -3944,16 +4106,16 @@ function PageActionHandler() {
3944
4106
  import { useCallback as useCallback13, useContext as useContext8, useEffect as useEffect21, useState as useState14 } from "react";
3945
4107
 
3946
4108
  // src/hooks/useActionControl.ts
3947
- import { useLocalParticipant as useLocalParticipant5 } from "@livekit/components-react/hooks";
3948
- import { useCallback as useCallback10, useEffect as useEffect17, useState as useState12 } from "react";
4109
+ import { useLocalParticipant as useLocalParticipant6 } from "@livekit/components-react/hooks";
4110
+ import { useCallback as useCallback11, useEffect as useEffect17, useState as useState12 } from "react";
3949
4111
  var textEncoder5 = new TextEncoder;
3950
4112
  function useActionControl() {
3951
- const { localParticipant } = useLocalParticipant5();
4113
+ const { localParticipant } = useLocalParticipant6();
3952
4114
  const plan = usePlanUpdates();
3953
4115
  const [busy, setBusy] = useState12(isActionsBusy);
3954
4116
  useEffect17(() => subscribeActionsBusy(setBusy), []);
3955
4117
  const actionsActive = busy || plan?.state === "executing";
3956
- const requestStop = useCallback10(async () => {
4118
+ const requestStop = useCallback11(async () => {
3957
4119
  stopActions();
3958
4120
  try {
3959
4121
  await localParticipant.publishData(textEncoder5.encode(JSON.stringify({ type: "abort" })), {
@@ -3980,11 +4142,11 @@ function useAgentVoiceState() {
3980
4142
  }
3981
4143
 
3982
4144
  // src/hooks/useAudioLevelBars.ts
3983
- import { useEffect as useEffect18, useRef as useRef11, useState as useState13 } from "react";
4145
+ import { useEffect as useEffect18, useRef as useRef12, useState as useState13 } from "react";
3984
4146
  var TALKING_LEVEL_THRESHOLD = 0.2;
3985
4147
  var TALKING_HOLD_MS = 400;
3986
4148
  function useAudioLevelBars(mediaStreamTrack, { barCount, idleHeightPx, maxGrowthPx, noiseGate }) {
3987
- const barRefs = useRef11([]);
4149
+ const barRefs = useRef12([]);
3988
4150
  const [isTalking, setIsTalking] = useState13(false);
3989
4151
  useEffect18(() => {
3990
4152
  if (!mediaStreamTrack) {
@@ -4037,27 +4199,27 @@ function useAudioLevelBars(mediaStreamTrack, { barCount, idleHeightPx, maxGrowth
4037
4199
  }
4038
4200
 
4039
4201
  // src/hooks/useIdleAutoPause.ts
4040
- import { useCallback as useCallback11, useEffect as useEffect19, useRef as useRef12 } from "react";
4202
+ import { useCallback as useCallback12, useEffect as useEffect19, useRef as useRef13 } from "react";
4041
4203
  function useIdleAutoPause({
4042
4204
  enabled,
4043
4205
  active,
4044
4206
  isHeld,
4045
4207
  pause
4046
4208
  }) {
4047
- const timerRef = useRef12(null);
4048
- const pauseRef = useRef12(pause);
4209
+ const timerRef = useRef13(null);
4210
+ const pauseRef = useRef13(pause);
4049
4211
  pauseRef.current = pause;
4050
- const clearTimer = useCallback11(() => {
4212
+ const clearTimer = useCallback12(() => {
4051
4213
  if (timerRef.current) {
4052
4214
  clearTimeout(timerRef.current);
4053
4215
  timerRef.current = null;
4054
4216
  }
4055
4217
  }, []);
4056
- const armTimer = useCallback11(() => {
4218
+ const armTimer = useCallback12(() => {
4057
4219
  clearTimer();
4058
4220
  timerRef.current = setTimeout(() => pauseRef.current(), IDLE_AUTO_PAUSE_MS);
4059
4221
  }, [clearTimer]);
4060
- const reportActivity = useCallback11(() => {
4222
+ const reportActivity = useCallback12(() => {
4061
4223
  if (enabled && !isHeld)
4062
4224
  armTimer();
4063
4225
  }, [enabled, isHeld, armTimer]);
@@ -4073,7 +4235,7 @@ function useIdleAutoPause({
4073
4235
  }
4074
4236
 
4075
4237
  // src/hooks/useKeyboardPushToTalk.ts
4076
- import { useEffect as useEffect20, useRef as useRef13 } from "react";
4238
+ import { useEffect as useEffect20, useRef as useRef14 } from "react";
4077
4239
  function isEditableTarget() {
4078
4240
  const el = document.activeElement;
4079
4241
  if (!el)
@@ -4087,7 +4249,7 @@ function useKeyboardPushToTalk({
4087
4249
  onCommit,
4088
4250
  onKeyUsed
4089
4251
  }) {
4090
- const handlers = useRef13({ onStart, onCommit, onKeyUsed });
4252
+ const handlers = useRef14({ onStart, onCommit, onKeyUsed });
4091
4253
  handlers.current = { onStart, onCommit, onKeyUsed };
4092
4254
  useEffect20(() => {
4093
4255
  if (!enabled)
@@ -4137,14 +4299,14 @@ function useKeyboardPushToTalk({
4137
4299
  }
4138
4300
 
4139
4301
  // src/hooks/useLiveUserTranscript.ts
4140
- import { useLocalParticipant as useLocalParticipant6 } from "@livekit/components-react/hooks";
4141
- import { useRef as useRef14 } from "react";
4302
+ import { useLocalParticipant as useLocalParticipant7 } from "@livekit/components-react/hooks";
4303
+ import { useRef as useRef15 } from "react";
4142
4304
  function useLiveUserTranscript(active) {
4143
4305
  const transcriptions = useSharedTranscriptions();
4144
- const { localParticipant } = useLocalParticipant6();
4306
+ const { localParticipant } = useLocalParticipant7();
4145
4307
  const localIdentity = localParticipant.identity;
4146
- const priorStreamIdsRef = useRef14(new Set);
4147
- const wasActiveRef = useRef14(false);
4308
+ const priorStreamIdsRef = useRef15(new Set);
4309
+ const wasActiveRef = useRef15(false);
4148
4310
  const userStreams = transcriptions.filter((stream) => stream.participantInfo.identity === localIdentity);
4149
4311
  if (active && !wasActiveRef.current) {
4150
4312
  priorStreamIdsRef.current = new Set(userStreams.map((s) => s.streamInfo.id));
@@ -4155,36 +4317,6 @@ function useLiveUserTranscript(active) {
4155
4317
  return userStreams.filter((stream) => !priorStreamIdsRef.current.has(stream.streamInfo.id)).map((stream) => stream.text.trim()).filter((text) => text.length > 0).join(" ");
4156
4318
  }
4157
4319
 
4158
- // src/hooks/useMediaControls.ts
4159
- import { useLocalParticipant as useLocalParticipant7 } from "@livekit/components-react/hooks";
4160
- import { ScreenSharePresets as ScreenSharePresets2 } from "livekit-client";
4161
- import { useCallback as useCallback12 } from "react";
4162
- var SCREEN_SHARE_OPTIONS = {
4163
- video: { displaySurface: "browser" },
4164
- resolution: ScreenSharePresets2.h720fps30.resolution,
4165
- contentHint: "detail"
4166
- };
4167
- function useMediaControls() {
4168
- const { localParticipant } = useLocalParticipant7();
4169
- const isMuted = !localParticipant.isMicrophoneEnabled;
4170
- const isScreenSharing = localParticipant.isScreenShareEnabled;
4171
- const toggleMute = useCallback12(async () => {
4172
- try {
4173
- await localParticipant.setMicrophoneEnabled(isMuted);
4174
- } catch (error) {
4175
- console.error("Failed to toggle microphone:", error);
4176
- }
4177
- }, [localParticipant, isMuted]);
4178
- const toggleScreenShare = useCallback12(async () => {
4179
- try {
4180
- await localParticipant.setScreenShareEnabled(!isScreenSharing, SCREEN_SHARE_OPTIONS);
4181
- } catch (error) {
4182
- console.error("Failed to toggle screen share:", error);
4183
- }
4184
- }, [localParticipant, isScreenSharing]);
4185
- return { isMuted, toggleMute, isScreenSharing, toggleScreenShare };
4186
- }
4187
-
4188
4320
  // src/hooks/useMicLevel.ts
4189
4321
  import { useLocalParticipant as useLocalParticipant8 } from "@livekit/components-react/hooks";
4190
4322
  var MIC_BARS = 5;
@@ -4795,7 +4927,7 @@ function SessionControlBar() {
4795
4927
  }
4796
4928
 
4797
4929
  // src/components/ShadowHost.tsx
4798
- import { useLayoutEffect as useLayoutEffect2, useRef as useRef15, useState as useState15 } from "react";
4930
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef16, useState as useState15 } from "react";
4799
4931
  import { createPortal } from "react-dom";
4800
4932
  import { jsx as jsx13, Fragment as Fragment2 } from "react/jsx-runtime";
4801
4933
  var PROPERTIES_STYLE_ID = "skippr-tw-properties";
@@ -4812,7 +4944,7 @@ function hoistTailwindProperties(css) {
4812
4944
  return css.replace(PROPERTY_RULE, "");
4813
4945
  }
4814
4946
  function ShadowHost({ children }) {
4815
- const hostRef = useRef15(null);
4947
+ const hostRef = useRef16(null);
4816
4948
  const [shadowRoot, setShadowRoot] = useState15(null);
4817
4949
  const css = `/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
4818
4950
  @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--skippr-font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--skippr-font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--skippr-color-red-50:oklch(97.1% .013 17.38);--skippr-color-red-100:oklch(93.6% .032 17.717);--skippr-color-red-200:oklch(88.5% .062 18.334);--skippr-color-red-300:oklch(80.8% .114 19.571);--skippr-color-red-400:oklch(70.4% .191 22.216);--skippr-color-red-500:oklch(63.7% .237 25.331);--skippr-color-red-600:oklch(57.7% .245 27.325);--skippr-color-red-700:oklch(50.5% .213 27.518);--skippr-color-amber-50:oklch(98.7% .022 95.277);--skippr-color-amber-100:oklch(96.2% .059 95.617);--skippr-color-amber-400:oklch(82.8% .189 84.429);--skippr-color-amber-700:oklch(55.5% .163 48.998);--skippr-color-amber-950:oklch(27.9% .077 45.635);--skippr-color-emerald-400:oklch(76.5% .177 163.223);--skippr-color-neutral-100:oklch(97% 0 0);--skippr-color-neutral-200:oklch(92.2% 0 0);--skippr-color-neutral-500:oklch(55.6% 0 0);--skippr-color-neutral-700:oklch(37.1% 0 0);--skippr-color-black:#000;--skippr-color-white:#fff;--skippr-spacing:.25rem;--skippr-text-xs:.75rem;--skippr-text-xs--line-height:calc(1/.75);--skippr-text-sm:.875rem;--skippr-text-sm--line-height:calc(1.25/.875);--skippr-font-weight-medium:500;--skippr-font-weight-semibold:600;--skippr-leading-tight:1.25;--skippr-leading-snug:1.375;--skippr-leading-relaxed:1.625;--skippr-ease-out:cubic-bezier(0,0,.2,1);--skippr-ease-in-out:cubic-bezier(.4,0,.2,1);--skippr-animate-spin:spin 1s linear infinite;--skippr-animate-ping:ping 1s cubic-bezier(0,0,.2,1)infinite;--skippr-animate-bounce:bounce 1s infinite;--skippr-blur-sm:8px;--skippr-default-transition-duration:.15s;--skippr-default-transition-timing-function:cubic-bezier(.4,0,.2,1);--skippr-default-font-family:var(--skippr-font-sans);--skippr-default-mono-font-family:var(--skippr-font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--skippr-default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--skippr-default-font-feature-settings,normal);font-variation-settings:var(--skippr-default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--skippr-default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--skippr-default-mono-font-feature-settings,normal);font-variation-settings:var(--skippr-default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.skippr\\:pointer-events-none{pointer-events:none}.skippr\\:absolute{position:absolute}.skippr\\:fixed{position:fixed}.skippr\\:relative{position:relative}.skippr\\:sticky{position:sticky}.skippr\\:inset-0{inset:calc(var(--skippr-spacing)*0)}.skippr\\:inset-y-0{inset-block:calc(var(--skippr-spacing)*0)}.skippr\\:top-0{top:calc(var(--skippr-spacing)*0)}.skippr\\:top-1\\/2{top:50%}.skippr\\:top-full{top:100%}.skippr\\:-right-8{right:calc(var(--skippr-spacing)*-8)}.skippr\\:right-0{right:calc(var(--skippr-spacing)*0)}.skippr\\:right-3{right:calc(var(--skippr-spacing)*3)}.skippr\\:right-5{right:calc(var(--skippr-spacing)*5)}.skippr\\:right-6{right:calc(var(--skippr-spacing)*6)}.skippr\\:-bottom-1{bottom:calc(var(--skippr-spacing)*-1)}.skippr\\:-bottom-9{bottom:calc(var(--skippr-spacing)*-9)}.skippr\\:bottom-3{bottom:calc(var(--skippr-spacing)*3)}.skippr\\:bottom-20{bottom:calc(var(--skippr-spacing)*20)}.skippr\\:bottom-full{bottom:100%}.skippr\\:-left-8{left:calc(var(--skippr-spacing)*-8)}.skippr\\:left-0{left:calc(var(--skippr-spacing)*0)}.skippr\\:left-1\\/2{left:50%}.skippr\\:left-2{left:calc(var(--skippr-spacing)*2)}.skippr\\:left-3{left:calc(var(--skippr-spacing)*3)}.skippr\\:left-5{left:calc(var(--skippr-spacing)*5)}.skippr\\:left-6{left:calc(var(--skippr-spacing)*6)}.skippr\\:z-10{z-index:10}.skippr\\:z-20{z-index:20}.skippr\\:z-\\[9998\\]{z-index:9998}.skippr\\:z-\\[9999\\]{z-index:9999}.skippr\\:z-\\[10000\\]{z-index:10000}.skippr\\:order-first{order:-9999}.skippr\\:order-last{order:9999}.skippr\\:mx-auto{margin-inline:auto}.skippr\\:-mt-\\[5px\\]{margin-top:-5px}.skippr\\:-mt-\\[27px\\]{margin-top:-27px}.skippr\\:mt-0\\.5{margin-top:calc(var(--skippr-spacing)*.5)}.skippr\\:mt-1{margin-top:calc(var(--skippr-spacing)*1)}.skippr\\:mt-1\\.5{margin-top:calc(var(--skippr-spacing)*1.5)}.skippr\\:mt-2{margin-top:calc(var(--skippr-spacing)*2)}.skippr\\:mt-3{margin-top:calc(var(--skippr-spacing)*3)}.skippr\\:mt-3\\.5{margin-top:calc(var(--skippr-spacing)*3.5)}.skippr\\:mr-7{margin-right:calc(var(--skippr-spacing)*7)}.skippr\\:-mb-\\[5px\\]{margin-bottom:-5px}.skippr\\:mb-1\\.5{margin-bottom:calc(var(--skippr-spacing)*1.5)}.skippr\\:mb-2{margin-bottom:calc(var(--skippr-spacing)*2)}.skippr\\:mb-3{margin-bottom:calc(var(--skippr-spacing)*3)}.skippr\\:mb-4{margin-bottom:calc(var(--skippr-spacing)*4)}.skippr\\:ml-0\\.5{margin-left:calc(var(--skippr-spacing)*.5)}.skippr\\:ml-1{margin-left:calc(var(--skippr-spacing)*1)}.skippr\\:ml-7{margin-left:calc(var(--skippr-spacing)*7)}.skippr\\:flex{display:flex}.skippr\\:hidden{display:none}.skippr\\:inline-flex{display:inline-flex}.skippr\\:size-1{width:calc(var(--skippr-spacing)*1);height:calc(var(--skippr-spacing)*1)}.skippr\\:size-1\\.5{width:calc(var(--skippr-spacing)*1.5);height:calc(var(--skippr-spacing)*1.5)}.skippr\\:size-2{width:calc(var(--skippr-spacing)*2);height:calc(var(--skippr-spacing)*2)}.skippr\\:size-2\\.5{width:calc(var(--skippr-spacing)*2.5);height:calc(var(--skippr-spacing)*2.5)}.skippr\\:size-3{width:calc(var(--skippr-spacing)*3);height:calc(var(--skippr-spacing)*3)}.skippr\\:size-3\\.5{width:calc(var(--skippr-spacing)*3.5);height:calc(var(--skippr-spacing)*3.5)}.skippr\\:size-4{width:calc(var(--skippr-spacing)*4);height:calc(var(--skippr-spacing)*4)}.skippr\\:size-5{width:calc(var(--skippr-spacing)*5);height:calc(var(--skippr-spacing)*5)}.skippr\\:size-6{width:calc(var(--skippr-spacing)*6);height:calc(var(--skippr-spacing)*6)}.skippr\\:size-7{width:calc(var(--skippr-spacing)*7);height:calc(var(--skippr-spacing)*7)}.skippr\\:size-8{width:calc(var(--skippr-spacing)*8);height:calc(var(--skippr-spacing)*8)}.skippr\\:size-9{width:calc(var(--skippr-spacing)*9);height:calc(var(--skippr-spacing)*9)}.skippr\\:size-10{width:calc(var(--skippr-spacing)*10);height:calc(var(--skippr-spacing)*10)}.skippr\\:size-12{width:calc(var(--skippr-spacing)*12);height:calc(var(--skippr-spacing)*12)}.skippr\\:size-\\[5px\\]{width:5px;height:5px}.skippr\\:size-\\[38px\\]{width:38px;height:38px}.skippr\\:size-full{width:100%;height:100%}.skippr\\:h-0{height:calc(var(--skippr-spacing)*0)}.skippr\\:h-0\\.5{height:calc(var(--skippr-spacing)*.5)}.skippr\\:h-1{height:calc(var(--skippr-spacing)*1)}.skippr\\:h-1\\.5{height:calc(var(--skippr-spacing)*1.5)}.skippr\\:h-2{height:calc(var(--skippr-spacing)*2)}.skippr\\:h-3{height:calc(var(--skippr-spacing)*3)}.skippr\\:h-3\\.5{height:calc(var(--skippr-spacing)*3.5)}.skippr\\:h-4{height:calc(var(--skippr-spacing)*4)}.skippr\\:h-5{height:calc(var(--skippr-spacing)*5)}.skippr\\:h-6{height:calc(var(--skippr-spacing)*6)}.skippr\\:h-7{height:calc(var(--skippr-spacing)*7)}.skippr\\:h-8{height:calc(var(--skippr-spacing)*8)}.skippr\\:h-9{height:calc(var(--skippr-spacing)*9)}.skippr\\:h-10{height:calc(var(--skippr-spacing)*10)}.skippr\\:h-\\[18\\.5px\\]{height:18.5px}.skippr\\:h-\\[36px\\]{height:36px}.skippr\\:h-\\[38px\\]{height:38px}.skippr\\:h-\\[48px\\]{height:48px}.skippr\\:h-\\[54px\\]{height:54px}.skippr\\:h-full{height:100%}.skippr\\:min-h-0{min-height:calc(var(--skippr-spacing)*0)}.skippr\\:min-h-11{min-height:calc(var(--skippr-spacing)*11)}.skippr\\:w-0{width:calc(var(--skippr-spacing)*0)}.skippr\\:w-3\\.5{width:calc(var(--skippr-spacing)*3.5)}.skippr\\:w-4{width:calc(var(--skippr-spacing)*4)}.skippr\\:w-5{width:calc(var(--skippr-spacing)*5)}.skippr\\:w-6{width:calc(var(--skippr-spacing)*6)}.skippr\\:w-7{width:calc(var(--skippr-spacing)*7)}.skippr\\:w-8{width:calc(var(--skippr-spacing)*8)}.skippr\\:w-10{width:calc(var(--skippr-spacing)*10)}.skippr\\:w-40{width:calc(var(--skippr-spacing)*40)}.skippr\\:w-\\[2px\\]{width:2px}.skippr\\:w-\\[3px\\]{width:3px}.skippr\\:w-\\[15\\.4px\\]{width:15.4px}.skippr\\:w-\\[36px\\]{width:36px}.skippr\\:w-\\[38px\\]{width:38px}.skippr\\:w-\\[50px\\]{width:50px}.skippr\\:w-fit{width:fit-content}.skippr\\:w-full{width:100%}.skippr\\:max-w-64{max-width:calc(var(--skippr-spacing)*64)}.skippr\\:max-w-72{max-width:calc(var(--skippr-spacing)*72)}.skippr\\:max-w-\\[80\\%\\]{max-width:80%}.skippr\\:max-w-\\[280px\\]{max-width:280px}.skippr\\:min-w-0{min-width:calc(var(--skippr-spacing)*0)}.skippr\\:min-w-11{min-width:calc(var(--skippr-spacing)*11)}.skippr\\:flex-1{flex:1}.skippr\\:shrink-0{flex-shrink:0}.skippr\\:origin-bottom-left{transform-origin:0 100%}.skippr\\:origin-bottom-right{transform-origin:100% 100%}.skippr\\:origin-center{transform-origin:50%}.skippr\\:origin-left{transform-origin:0}.skippr\\:origin-right{transform-origin:100%}.skippr\\:origin-top-left{transform-origin:0 0}.skippr\\:origin-top-right{transform-origin:100% 0}.skippr\\:-translate-x-1\\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:-translate-x-3{--tw-translate-x:calc(var(--skippr-spacing)*-3);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:-translate-x-7{--tw-translate-x:calc(var(--skippr-spacing)*-7);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:translate-x-3{--tw-translate-x:calc(var(--skippr-spacing)*3);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:translate-x-7{--tw-translate-x:calc(var(--skippr-spacing)*7);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:scale-0{--tw-scale-x:0%;--tw-scale-y:0%;--tw-scale-z:0%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:scale-95{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:scale-\\[0\\.94\\]{scale:.94}.skippr\\:-rotate-90{rotate:-90deg}.skippr\\:rotate-45{rotate:45deg}.skippr\\:rotate-\\[225deg\\]{rotate:225deg}.skippr\\:\\[animation\\:skippr-agent-in_200ms_ease-out\\]{animation:.2s ease-out skippr-agent-in}.skippr\\:\\[animation\\:skippr-agent-in_200ms_ease-out_240ms_both\\]{animation:.2s ease-out .24s both skippr-agent-in}.skippr\\:\\[animation\\:skippr-banner-look_2\\.4s_ease-in-out_infinite\\]{animation:2.4s ease-in-out infinite skippr-banner-look}.skippr\\:\\[animation\\:skippr-finger-tap_1\\.1s_ease-in-out_infinite\\]{animation:1.1s ease-in-out infinite skippr-finger-tap}.skippr\\:\\[animation\\:skippr-orb-in_320ms_cubic-bezier\\(0\\.34\\,1\\.3\\,0\\.64\\,1\\)\\]{animation:.32s cubic-bezier(.34,1.3,.64,1) skippr-orb-in}.skippr\\:\\[animation\\:skippr-stage-fade_240ms_ease-out\\]{animation:.24s ease-out skippr-stage-fade}.skippr\\:\\[animation\\:skippr-tip-in_360ms_cubic-bezier\\(0\\.34\\,1\\.3\\,0\\.64\\,1\\)_backwards\\]{animation:.36s cubic-bezier(.34,1.3,.64,1) backwards skippr-tip-in}.skippr\\:\\[animation\\:skippr-toolset-pop_280ms_cubic-bezier\\(0\\.22\\,1\\,0\\.36\\,1\\)\\]{animation:.28s cubic-bezier(.22,1,.36,1) skippr-toolset-pop}.skippr\\:\\[animation\\:skippr-toolset-pop_440ms_cubic-bezier\\(0\\.22\\,1\\,0\\.36\\,1\\)\\]{animation:.44s cubic-bezier(.22,1,.36,1) skippr-toolset-pop}.skippr\\:animate-\\[skippr-banner-look_2\\.4s_ease-in-out_infinite\\]{animation:2.4s ease-in-out infinite skippr-banner-look}.skippr\\:animate-\\[skippr-bubble-in_0\\.28s_ease-out\\]{animation:.28s ease-out skippr-bubble-in}.skippr\\:animate-\\[skippr-fade-in_0\\.3s_ease-out\\]{animation:.3s ease-out skippr-fade-in}.skippr\\:animate-\\[skippr-pill-content_0\\.22s_ease-out\\]{animation:.22s ease-out skippr-pill-content}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_0\\.3s_infinite\\]{animation:1.1s ease-in-out .3s infinite skippr-speak}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_0\\.6s_infinite\\]{animation:1.1s ease-in-out .6s infinite skippr-speak}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_0\\.15s_infinite\\]{animation:1.1s ease-in-out .15s infinite skippr-speak}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_0\\.45s_infinite\\]{animation:1.1s ease-in-out .45s infinite skippr-speak}.skippr\\:animate-\\[skippr-speak_1\\.1s_ease-in-out_infinite\\]{animation:1.1s ease-in-out infinite skippr-speak}.skippr\\:animate-bounce{animation:var(--skippr-animate-bounce)}.skippr\\:animate-ping{animation:var(--skippr-animate-ping)}.skippr\\:animate-skippr-annotation-pulse{animation:1.8s ease-in-out infinite skippr-annotation-pulse}.skippr\\:animate-skippr-click-ping{animation:.5s ease-out forwards skippr-click-ping}.skippr\\:animate-skippr-cursor-pop{animation:.22s ease-out skippr-cursor-pop}.skippr\\:animate-skippr-press{animation:.5s ease-in-out skippr-press}.skippr\\:animate-skippr-ptt-transmit{animation:1.4s ease-out infinite skippr-ptt-transmit}.skippr\\:animate-skippr-rec-ring{animation:2s ease-out infinite skippr-rec-ring}.skippr\\:animate-skippr-tab-fade{animation:.2s ease-out skippr-tab-fade}.skippr\\:animate-skippr-thinking-dot{animation:1.2s ease-in-out infinite skippr-thinking-dot}.skippr\\:animate-spin{animation:var(--skippr-animate-spin)}.skippr\\:cursor-default{cursor:default}.skippr\\:cursor-grab{cursor:grab}.skippr\\:cursor-not-allowed{cursor:not-allowed}.skippr\\:cursor-pointer{cursor:pointer}.skippr\\:touch-none{touch-action:none}.skippr\\:resize-none{resize:none}.skippr\\:flex-col{flex-direction:column}.skippr\\:flex-col-reverse{flex-direction:column-reverse}.skippr\\:items-center{align-items:center}.skippr\\:items-end{align-items:flex-end}.skippr\\:items-start{align-items:flex-start}.skippr\\:justify-between{justify-content:space-between}.skippr\\:justify-center{justify-content:center}.skippr\\:justify-end{justify-content:flex-end}.skippr\\:justify-start{justify-content:flex-start}.skippr\\:gap-0\\.5{gap:calc(var(--skippr-spacing)*.5)}.skippr\\:gap-1{gap:calc(var(--skippr-spacing)*1)}.skippr\\:gap-1\\.5{gap:calc(var(--skippr-spacing)*1.5)}.skippr\\:gap-2{gap:calc(var(--skippr-spacing)*2)}.skippr\\:gap-2\\.5{gap:calc(var(--skippr-spacing)*2.5)}.skippr\\:gap-3{gap:calc(var(--skippr-spacing)*3)}.skippr\\:gap-\\[2px\\]{gap:2px}.skippr\\:gap-\\[3px\\]{gap:3px}:where(.skippr\\:space-y-0\\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--skippr-spacing)*.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--skippr-spacing)*.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.skippr\\:space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--skippr-spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--skippr-spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.skippr\\:space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--skippr-spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--skippr-spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.skippr\\:space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--skippr-spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--skippr-spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.skippr\\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.skippr\\:overflow-hidden{overflow:hidden}.skippr\\:overflow-y-auto{overflow-y:auto}.skippr\\:rounded{border-radius:.25rem}.skippr\\:rounded-2xl{border-radius:1.125rem}.skippr\\:rounded-\\[1rem\\]{border-radius:1rem}.skippr\\:rounded-\\[10px\\]{border-radius:10px}.skippr\\:rounded-\\[11px\\]{border-radius:11px}.skippr\\:rounded-\\[12px\\]{border-radius:12px}.skippr\\:rounded-\\[14px\\]{border-radius:14px}.skippr\\:rounded-\\[16px\\]{border-radius:16px}.skippr\\:rounded-\\[20px\\]{border-radius:20px}.skippr\\:rounded-full{border-radius:3.40282e38px}.skippr\\:rounded-lg{border-radius:.625rem}.skippr\\:rounded-md{border-radius:.5rem}.skippr\\:rounded-sm{border-radius:.375rem}.skippr\\:rounded-xl{border-radius:.875rem}.skippr\\:rounded-l-\\[18px\\]{border-top-left-radius:18px;border-bottom-left-radius:18px}.skippr\\:rounded-tl-md{border-top-left-radius:.5rem}.skippr\\:rounded-r-\\[18px\\]{border-top-right-radius:18px;border-bottom-right-radius:18px}.skippr\\:border{border-style:var(--tw-border-style);border-width:1px}.skippr\\:border-0{border-style:var(--tw-border-style);border-width:0}.skippr\\:border-2{border-style:var(--tw-border-style);border-width:2px}.skippr\\:border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.skippr\\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.skippr\\:border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.skippr\\:border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.skippr\\:border-\\[\\#2bc0ae\\]{border-color:#2bc0ae}.skippr\\:border-black\\/25{border-color:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:border-black\\/25{border-color:color-mix(in oklab,var(--skippr-color-black)25%,transparent)}}.skippr\\:border-border,.skippr\\:border-input{border-color:oklch(92.3% .003 48.717)}.skippr\\:border-primary\\/20{border-color:oklab(29.9244% .0107414 -.0305411/.2)}.skippr\\:border-r-border{border-right-color:oklch(92.3% .003 48.717)}.skippr\\:border-l-border{border-left-color:oklch(92.3% .003 48.717)}.skippr\\:bg-\\[\\#2bc0ae\\]{background-color:#2bc0ae}.skippr\\:bg-\\[\\#2bc0ae\\]\\/50{background-color:oklab(72.9347% -.121518 -.00545585/.5)}.skippr\\:bg-\\[\\#f4ecd8\\]{background-color:#f4ecd8}.skippr\\:bg-amber-50{background-color:var(--skippr-color-amber-50)}.skippr\\:bg-amber-400{background-color:var(--skippr-color-amber-400)}.skippr\\:bg-background{background-color:oklch(100% 0 0)}.skippr\\:bg-black\\/\\[0\\.07\\]{background-color:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:bg-black\\/\\[0\\.07\\]{background-color:color-mix(in oklab,var(--skippr-color-black)7.0%,transparent)}}.skippr\\:bg-bubble{background-color:#2d2b3d}.skippr\\:bg-bubble\\/95{background-color:oklab(29.9244% .0107414 -.0305411/.95)}.skippr\\:bg-card{background-color:oklch(100% 0 0)}.skippr\\:bg-current{background-color:currentColor}.skippr\\:bg-destructive{background-color:#d94f4f}.skippr\\:bg-emerald-400{background-color:var(--skippr-color-emerald-400)}.skippr\\:bg-foreground{background-color:oklch(14.7% .004 49.25)}.skippr\\:bg-launcher{background-color:#2d2d3f}.skippr\\:bg-muted-foreground\\/20{background-color:oklab(55.3% .00687528 .0110332/.2)}.skippr\\:bg-muted-foreground\\/40{background-color:oklab(55.3% .00687528 .0110332/.4)}.skippr\\:bg-muted\\/50{background-color:oklab(97% -.000282743 .000959196/.5)}.skippr\\:bg-neutral-100{background-color:var(--skippr-color-neutral-100)}.skippr\\:bg-primary{background-color:#2d2b3d}.skippr\\:bg-primary-foreground\\/20{background-color:oklab(100% 0 5.96046e-8/.2)}.skippr\\:bg-primary\\/10{background-color:oklab(29.9244% .0107414 -.0305411/.1)}.skippr\\:bg-red-50{background-color:var(--skippr-color-red-50)}.skippr\\:bg-red-100{background-color:var(--skippr-color-red-100)}.skippr\\:bg-red-400{background-color:var(--skippr-color-red-400)}.skippr\\:bg-red-500{background-color:var(--skippr-color-red-500)}.skippr\\:bg-secondary{background-color:#ffdfb5}.skippr\\:bg-transparent{background-color:#0000}.skippr\\:bg-white,.skippr\\:bg-white\\/15{background-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:bg-white\\/15{background-color:color-mix(in oklab,var(--skippr-color-white)15%,transparent)}}.skippr\\:bg-white\\/70{background-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:bg-white\\/70{background-color:color-mix(in oklab,var(--skippr-color-white)70%,transparent)}}.skippr\\:fill-brand{fill:#2bc0ae}.skippr\\:fill-primary\\/30{fill:oklab(29.9244% .0107414 -.0305411/.3)}.skippr\\:stroke-black\\/15{stroke:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:stroke-black\\/15{stroke:color-mix(in oklab,var(--skippr-color-black)15%,transparent)}}.skippr\\:stroke-bubble{stroke:#2d2b3d}.skippr\\:p-0{padding:calc(var(--skippr-spacing)*0)}.skippr\\:p-0\\.5{padding:calc(var(--skippr-spacing)*.5)}.skippr\\:p-1\\.5{padding:calc(var(--skippr-spacing)*1.5)}.skippr\\:p-2{padding:calc(var(--skippr-spacing)*2)}.skippr\\:p-3{padding:calc(var(--skippr-spacing)*3)}.skippr\\:p-3\\.5{padding:calc(var(--skippr-spacing)*3.5)}.skippr\\:p-4{padding:calc(var(--skippr-spacing)*4)}.skippr\\:px-1{padding-inline:calc(var(--skippr-spacing)*1)}.skippr\\:px-1\\.5{padding-inline:calc(var(--skippr-spacing)*1.5)}.skippr\\:px-2{padding-inline:calc(var(--skippr-spacing)*2)}.skippr\\:px-2\\.5{padding-inline:calc(var(--skippr-spacing)*2.5)}.skippr\\:px-3{padding-inline:calc(var(--skippr-spacing)*3)}.skippr\\:px-3\\.5{padding-inline:calc(var(--skippr-spacing)*3.5)}.skippr\\:px-4{padding-inline:calc(var(--skippr-spacing)*4)}.skippr\\:px-6{padding-inline:calc(var(--skippr-spacing)*6)}.skippr\\:px-8{padding-inline:calc(var(--skippr-spacing)*8)}.skippr\\:py-0\\.5{padding-block:calc(var(--skippr-spacing)*.5)}.skippr\\:py-1{padding-block:calc(var(--skippr-spacing)*1)}.skippr\\:py-1\\.5{padding-block:calc(var(--skippr-spacing)*1.5)}.skippr\\:py-2{padding-block:calc(var(--skippr-spacing)*2)}.skippr\\:py-2\\.5{padding-block:calc(var(--skippr-spacing)*2.5)}.skippr\\:py-3{padding-block:calc(var(--skippr-spacing)*3)}.skippr\\:py-4{padding-block:calc(var(--skippr-spacing)*4)}.skippr\\:py-6{padding-block:calc(var(--skippr-spacing)*6)}.skippr\\:pt-1\\.5{padding-top:calc(var(--skippr-spacing)*1.5)}.skippr\\:pr-2\\.5{padding-right:calc(var(--skippr-spacing)*2.5)}.skippr\\:pr-3{padding-right:calc(var(--skippr-spacing)*3)}.skippr\\:pb-2{padding-bottom:calc(var(--skippr-spacing)*2)}.skippr\\:pl-1\\.5{padding-left:calc(var(--skippr-spacing)*1.5)}.skippr\\:pl-2\\.5{padding-left:calc(var(--skippr-spacing)*2.5)}.skippr\\:pl-3\\.5{padding-left:calc(var(--skippr-spacing)*3.5)}.skippr\\:text-center{text-align:center}.skippr\\:text-left{text-align:left}.skippr\\:font-mono{font-family:var(--skippr-font-mono)}.skippr\\:text-sm{font-size:var(--skippr-text-sm);line-height:var(--tw-leading,var(--skippr-text-sm--line-height))}.skippr\\:text-xs{font-size:var(--skippr-text-xs);line-height:var(--tw-leading,var(--skippr-text-xs--line-height))}.skippr\\:text-\\[10px\\]{font-size:10px}.skippr\\:text-\\[11px\\]{font-size:11px}.skippr\\:text-\\[13px\\]{font-size:13px}.skippr\\:leading-5{--tw-leading:calc(var(--skippr-spacing)*5);line-height:calc(var(--skippr-spacing)*5)}.skippr\\:leading-none{--tw-leading:1;line-height:1}.skippr\\:leading-relaxed{--tw-leading:var(--skippr-leading-relaxed);line-height:var(--skippr-leading-relaxed)}.skippr\\:leading-snug{--tw-leading:var(--skippr-leading-snug);line-height:var(--skippr-leading-snug)}.skippr\\:leading-tight{--tw-leading:var(--skippr-leading-tight);line-height:var(--skippr-leading-tight)}.skippr\\:font-medium{--tw-font-weight:var(--skippr-font-weight-medium);font-weight:var(--skippr-font-weight-medium)}.skippr\\:font-semibold{--tw-font-weight:var(--skippr-font-weight-semibold);font-weight:var(--skippr-font-weight-semibold)}.skippr\\:whitespace-nowrap{white-space:nowrap}.skippr\\:text-\\[\\#2bc0ae\\]{color:#2bc0ae}.skippr\\:text-amber-700{color:var(--skippr-color-amber-700)}.skippr\\:text-amber-950{color:var(--skippr-color-amber-950)}.skippr\\:text-background{color:oklch(100% 0 0)}.skippr\\:text-black,.skippr\\:text-black\\/40{color:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:text-black\\/40{color:color-mix(in oklab,var(--skippr-color-black)40%,transparent)}}.skippr\\:text-brand{color:#2bc0ae}.skippr\\:text-bubble{color:#2d2b3d}.skippr\\:text-chart-3{color:oklch(66.6% .179 58.318)}.skippr\\:text-destructive{color:#d94f4f}.skippr\\:text-foreground{color:oklch(14.7% .004 49.25)}.skippr\\:text-muted-foreground{color:oklch(55.3% .013 58.071)}.skippr\\:text-muted-foreground\\/30{color:oklab(55.3% .00687528 .0110332/.3)}.skippr\\:text-muted-foreground\\/40{color:oklab(55.3% .00687528 .0110332/.4)}.skippr\\:text-muted-foreground\\/60{color:oklab(55.3% .00687528 .0110332/.6)}.skippr\\:text-muted-foreground\\/70{color:oklab(55.3% .00687528 .0110332/.7)}.skippr\\:text-neutral-500{color:var(--skippr-color-neutral-500)}.skippr\\:text-neutral-700{color:var(--skippr-color-neutral-700)}.skippr\\:text-primary{color:#2d2b3d}.skippr\\:text-primary-foreground{color:#fff}.skippr\\:text-primary-foreground\\/70{color:oklab(100% 0 5.96046e-8/.7)}.skippr\\:text-red-400{color:var(--skippr-color-red-400)}.skippr\\:text-red-600{color:var(--skippr-color-red-600)}.skippr\\:text-red-700{color:var(--skippr-color-red-700)}.skippr\\:text-secondary-foreground{color:#613700}.skippr\\:text-white,.skippr\\:text-white\\/60{color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:text-white\\/60{color:color-mix(in oklab,var(--skippr-color-white)60%,transparent)}}.skippr\\:capitalize{text-transform:capitalize}.skippr\\:tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.skippr\\:line-through{text-decoration-line:line-through}.skippr\\:placeholder-muted-foreground::placeholder{color:oklch(55.3% .013 58.071)}.skippr\\:opacity-0{opacity:0}.skippr\\:opacity-40{opacity:.4}.skippr\\:opacity-75{opacity:.75}.skippr\\:opacity-100{opacity:1}.skippr\\:shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[-6px_8px_30px_rgba\\(15\\,18\\,26\\,0\\.32\\)\\]{--tw-shadow:-6px 8px 30px var(--tw-shadow-color,#0f121a52);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_2px_6px_rgba\\(0\\,0\\,0\\,0\\.28\\)\\]{--tw-shadow:0 2px 6px var(--tw-shadow-color,#00000047);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_4px_12px_rgba\\(0\\,0\\,0\\,0\\.12\\)\\]{--tw-shadow:0 4px 12px var(--tw-shadow-color,#0000001f);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_4px_14px_rgba\\(0\\,0\\,0\\,0\\.12\\)\\]{--tw-shadow:0 4px 14px var(--tw-shadow-color,#0000001f);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_4px_14px_rgba\\(239\\,68\\,68\\,0\\.45\\)\\]{--tw-shadow:0 4px 14px var(--tw-shadow-color,#ef444473);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_4px_16px_rgba\\(45\\,43\\,61\\,0\\.45\\)\\,0_2px_4px_rgba\\(0\\,0\\,0\\,0\\.1\\)\\]{--tw-shadow:0 4px 16px var(--tw-shadow-color,#2d2b3d73),0 2px 4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_8px_24px_rgba\\(0\\,0\\,0\\,0\\.18\\)\\]{--tw-shadow:0 8px 24px var(--tw-shadow-color,#0000002e);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_8px_24px_rgba\\(45\\,43\\,61\\,0\\.35\\)\\]{--tw-shadow:0 8px 24px var(--tw-shadow-color,#2d2b3d59);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_8px_30px_rgba\\(0\\,0\\,0\\,0\\.16\\)\\,0_4px_12px_rgba\\(0\\,0\\,0\\,0\\.08\\)\\]{--tw-shadow:0 8px 30px var(--tw-shadow-color,#00000029),0 4px 12px var(--tw-shadow-color,#00000014);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-\\[0_10px_32px_rgba\\(0\\,0\\,0\\,0\\.18\\)\\]{--tw-shadow:0 10px 32px var(--tw-shadow-color,#0000002e);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:ring-1{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:ring-black\\/5{--tw-ring-color:var(--skippr-color-black)}@supports (color:color-mix(in lab, red, red)){.skippr\\:ring-black\\/5{--tw-ring-color:color-mix(in oklab,var(--skippr-color-black)5%,transparent)}}.skippr\\:ring-brand{--tw-ring-color:#2bc0ae}.skippr\\:ring-foreground\\/10{--tw-ring-color:oklab(14.7% .00261104 .00303026/.1)}.skippr\\:ring-white\\/15{--tw-ring-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:ring-white\\/15{--tw-ring-color:color-mix(in oklab,var(--skippr-color-white)15%,transparent)}}.skippr\\:ring-white\\/30{--tw-ring-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:ring-white\\/30{--tw-ring-color:color-mix(in oklab,var(--skippr-color-white)30%,transparent)}}.skippr\\:ring-offset-background{--tw-ring-offset-color:oklch(100% 0 0)}.skippr\\:drop-shadow-\\[0_2px_5px_rgba\\(0\\,0\\,0\\,0\\.4\\)\\]{--tw-drop-shadow-size:drop-shadow(0 2px 5px var(--tw-drop-shadow-color,#0006));--tw-drop-shadow:var(--tw-drop-shadow-size);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.skippr\\:backdrop-blur-sm{--tw-backdrop-blur:blur(var(--skippr-blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.skippr\\:transition-\\[height\\]{transition-property:height;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-\\[opacity\\,transform\\,height\\]{transition-property:opacity,transform,height;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-\\[width\\,margin\\]{transition-property:width,margin;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-\\[width\\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--skippr-default-transition-timing-function));transition-duration:var(--tw-duration,var(--skippr-default-transition-duration))}.skippr\\:duration-75{--tw-duration:75ms;transition-duration:75ms}.skippr\\:duration-100{--tw-duration:.1s;transition-duration:.1s}.skippr\\:duration-150{--tw-duration:.15s;transition-duration:.15s}.skippr\\:duration-200{--tw-duration:.2s;transition-duration:.2s}.skippr\\:duration-300{--tw-duration:.3s;transition-duration:.3s}.skippr\\:duration-\\[400ms\\]{--tw-duration:.4s;transition-duration:.4s}.skippr\\:ease-\\[cubic-bezier\\(0\\.22\\,1\\,0\\.36\\,1\\)\\]{--tw-ease:cubic-bezier(.22,1,.36,1);transition-timing-function:cubic-bezier(.22,1,.36,1)}.skippr\\:ease-\\[cubic-bezier\\(0\\.34\\,1\\.56\\,0\\.64\\,1\\)\\]{--tw-ease:cubic-bezier(.34,1.56,.64,1);transition-timing-function:cubic-bezier(.34,1.56,.64,1)}.skippr\\:ease-in-out{--tw-ease:var(--skippr-ease-in-out);transition-timing-function:var(--skippr-ease-in-out)}.skippr\\:ease-out{--tw-ease:var(--skippr-ease-out);transition-timing-function:var(--skippr-ease-out)}.skippr\\:outline-none{--tw-outline-style:none;outline-style:none}.skippr\\:select-none{-webkit-user-select:none;user-select:none}.skippr\\:\\[animation-delay\\:0ms\\]{animation-delay:0s}.skippr\\:\\[animation-delay\\:150ms\\]{animation-delay:.15s}.skippr\\:\\[animation-delay\\:200ms\\]{animation-delay:.2s}.skippr\\:\\[animation-delay\\:300ms\\]{animation-delay:.3s}.skippr\\:\\[animation-delay\\:400ms\\]{animation-delay:.4s}.skippr\\:\\[overflow-anchor\\:none\\]{overflow-anchor:none}.skippr\\:group-focus-within\\:scale-100:is(:where(.skippr\\:group):focus-within *){--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:group-focus-within\\:opacity-100:is(:where(.skippr\\:group):focus-within *){opacity:1}@media (hover:hover){.skippr\\:group-hover\\:scale-100:is(:where(.skippr\\:group):hover *){--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:group-hover\\:text-red-300:is(:where(.skippr\\:group):hover *){color:var(--skippr-color-red-300)}.skippr\\:group-hover\\:text-white\\/80:is(:where(.skippr\\:group):hover *){color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:group-hover\\:text-white\\/80:is(:where(.skippr\\:group):hover *){color:color-mix(in oklab,var(--skippr-color-white)80%,transparent)}}.skippr\\:group-hover\\:opacity-100:is(:where(.skippr\\:group):hover *){opacity:1}}.skippr\\:placeholder\\:text-muted-foreground::placeholder{color:oklch(55.3% .013 58.071)}@media (hover:hover){.skippr\\:hover\\:-translate-y-0\\.5:hover{--tw-translate-y:calc(var(--skippr-spacing)*-.5);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:hover\\:bg-\\[\\#3a384b\\]:hover{background-color:#3a384b}.skippr\\:hover\\:bg-accent:hover{background-color:#e7e5e4}.skippr\\:hover\\:bg-amber-100:hover{background-color:var(--skippr-color-amber-100)}.skippr\\:hover\\:bg-bubble:hover{background-color:#2d2b3d}.skippr\\:hover\\:bg-destructive\\/90:hover{background-color:oklab(61.4357% .15892 .0698893/.9)}.skippr\\:hover\\:bg-muted:hover{background-color:oklch(97% .001 106.424)}.skippr\\:hover\\:bg-neutral-100:hover{background-color:var(--skippr-color-neutral-100)}.skippr\\:hover\\:bg-neutral-200:hover{background-color:var(--skippr-color-neutral-200)}.skippr\\:hover\\:bg-primary\\/90:hover{background-color:oklab(29.9244% .0107414 -.0305411/.9)}.skippr\\:hover\\:bg-red-200:hover{background-color:var(--skippr-color-red-200)}.skippr\\:hover\\:bg-red-600:hover{background-color:var(--skippr-color-red-600)}.skippr\\:hover\\:bg-secondary\\/80:hover{background-color:oklab(91.9963% .0175391 .0626889/.8)}.skippr\\:hover\\:bg-white\\/10:hover{background-color:var(--skippr-color-white)}@supports (color:color-mix(in lab, red, red)){.skippr\\:hover\\:bg-white\\/10:hover{background-color:color-mix(in oklab,var(--skippr-color-white)10%,transparent)}}.skippr\\:hover\\:text-accent-foreground:hover{color:oklch(21.6% .006 56.043)}.skippr\\:hover\\:text-foreground:hover{color:oklch(14.7% .004 49.25)}.skippr\\:hover\\:text-primary-foreground:hover{color:#fff}.skippr\\:hover\\:brightness-110:hover{--tw-brightness:brightness(110%);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}}.skippr\\:focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.skippr\\:focus-visible\\:ring-brand:focus-visible{--tw-ring-color:#2bc0ae}.skippr\\:focus-visible\\:ring-bubble\\/60:focus-visible{--tw-ring-color:oklab(29.9244% .0107414 -.0305411/.6)}.skippr\\:focus-visible\\:ring-ring:focus-visible{--tw-ring-color:oklch(70.9% .01 56.259)}.skippr\\:focus-visible\\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.skippr\\:focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.skippr\\:active\\:translate-y-0:active{--tw-translate-y:calc(var(--skippr-spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.skippr\\:disabled\\:pointer-events-none:disabled{pointer-events:none}.skippr\\:disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.skippr\\:disabled\\:opacity-50:disabled{opacity:.5}.skippr\\:disabled\\:opacity-60:disabled{opacity:.6}@media (prefers-reduced-motion:reduce){.skippr\\:motion-reduce\\:hidden{display:none}.skippr\\:motion-reduce\\:scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.skippr\\:motion-reduce\\:animate-none{animation:none}}.skippr\\:\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.skippr\\:\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.skippr\\:\\[\\&_svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-4 svg:not([class*=size-]){width:calc(var(--skippr-spacing)*4);height:calc(var(--skippr-spacing)*4)}}@keyframes skippr-tap{0%{transform:scale(1)}45%{transform:scale(.7)}to{transform:scale(1)}}@keyframes skippr-press{0%{transform:scale(1)}55%{transform:scale(1)}85%{transform:scale(.68)}to{transform:scale(1)}}@keyframes skippr-cursor-pop{0%{opacity:0;transform:scale(.5)}to{opacity:1;transform:scale(1)}}@keyframes skippr-click-ping{0%{opacity:.9;transform:translate(-50%,-50%)scale(.4)}to{opacity:0;transform:translate(-50%,-50%)scale(2.4)}}@keyframes skippr-tab-fade{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes skippr-speak{0%,to{opacity:.6;transform:scaleY(.4)}50%{opacity:1;transform:scaleY(1)}}@keyframes skippr-thinking-dot{0%,80%,to{opacity:.2;transform:translateY(0)}40%{opacity:1;transform:translateY(-2px)}}@keyframes skippr-pulse-ring{0%,to{box-shadow:0 0 #2d2b3d66}50%{box-shadow:0 0 0 10px #2d2b3d00}}@keyframes skippr-rec-ring{0%{box-shadow:0 0 #2bc0ae8c}70%{box-shadow:0 0 0 11px #2bc0ae00}to{box-shadow:0 0 #2bc0ae00}}@keyframes skippr-ptt-transmit{0%{box-shadow:0 0 #2bc0ae99,0 0 #2bc0ae59}70%{box-shadow:0 0 0 9px #2bc0ae00,0 0 0 16px #2bc0ae00}to{box-shadow:0 0 #2bc0ae00,0 0 #2bc0ae00}}@keyframes skippr-annotation-pulse{0%,to{box-shadow:0 0 #2bc0ae80}50%{box-shadow:0 0 0 6px #2bc0ae00}}@keyframes skippr-speak-ripple{0%{opacity:.6;transform:scale(1)}to{opacity:0;transform:scale(1.8)}}@keyframes skippr-bar{0%,to{transform:scaleY(.35)}50%{transform:scaleY(1)}}@keyframes skippr-breathe{0%,to{opacity:.85;transform:scale(1)}50%{opacity:1;transform:scale(1.08)}}@keyframes skippr-fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes skippr-wave{0%,to{opacity:.4;transform:scaleY(.4)}50%{opacity:1;transform:scaleY(1)}}@keyframes skippr-bubble-in{0%{opacity:0;transform:translateY(12px)scale(.96)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes skippr-tip-in{0%{opacity:0;transform:translateY(14px)scale(.96)}60%{opacity:1;transform:translateY(-2px)scale(1.01)}to{opacity:1;transform:translateY(0)scale(1)}}@keyframes skippr-pill-content{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}@keyframes skippr-banner-look{0%,to{transform:translate(0)}25%{transform:translate(-2px)}75%{transform:translate(2px)}}@keyframes skippr-finger-tap{0%,to{transform:translateY(0)rotate(0)}50%{transform:translateY(2px)rotate(-6deg)}}@keyframes skippr-toolset-pop{0%{opacity:0;transform:scale(.85)}to{opacity:1;transform:scale(1)}}@keyframes skippr-stage-fade{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes skippr-agent-in{0%{opacity:0;transform:scale(.6)}to{opacity:1;transform:scale(1)}}@keyframes skippr-orb-in{0%{opacity:0;transform:scale(.6)}to{opacity:1;transform:scale(1)}}.skippr-no-scrollbar{scrollbar-width:none;-ms-overflow-style:none}.skippr-no-scrollbar::-webkit-scrollbar{display:none}:host{color:var(--color-foreground)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}`;
@@ -4875,14 +5007,14 @@ function useChatMessages() {
4875
5007
 
4876
5008
  // src/hooks/useStreamingTranscript.ts
4877
5009
  import { useLocalParticipant as useLocalParticipant10 } from "@livekit/components-react/hooks";
4878
- import { useMemo as useMemo5, useRef as useRef16 } from "react";
5010
+ import { useMemo as useMemo5, useRef as useRef17 } from "react";
4879
5011
  function useStreamingTranscript() {
4880
5012
  const transcriptions = useSharedTranscriptions();
4881
5013
  const { localParticipant } = useLocalParticipant10();
4882
5014
  const { isCapturingSpeech } = useVoiceTurnContext();
4883
5015
  const localIdentity = localParticipant.identity;
4884
- const priorUserStreamIdsRef = useRef16(new Set);
4885
- const wasCapturingSpeechRef = useRef16(false);
5016
+ const priorUserStreamIdsRef = useRef17(new Set);
5017
+ const wasCapturingSpeechRef = useRef17(false);
4886
5018
  if (isCapturingSpeech && !wasCapturingSpeechRef.current) {
4887
5019
  priorUserStreamIdsRef.current = new Set(transcriptions.filter((stream) => stream.participantInfo.identity === localIdentity).map((stream) => stream.streamInfo.id));
4888
5020
  }
@@ -4966,7 +5098,7 @@ function usePhaseUpdates() {
4966
5098
  }
4967
5099
 
4968
5100
  // src/hooks/useSessionRemaining.ts
4969
- import { useEffect as useEffect23, useRef as useRef17, useState as useState16 } from "react";
5101
+ import { useEffect as useEffect23, useRef as useRef18, useState as useState16 } from "react";
4970
5102
 
4971
5103
  // src/lib/format.ts
4972
5104
  function formatTime(seconds) {
@@ -4982,7 +5114,7 @@ function parseNumber(s) {
4982
5114
  // src/hooks/useSessionRemaining.ts
4983
5115
  function useSessionRemaining() {
4984
5116
  const maxCallDuration = useAgentState("maxCallDuration", parseNumber, null);
4985
- const endTimeRef = useRef17(null);
5117
+ const endTimeRef = useRef18(null);
4986
5118
  const [remaining, setRemaining] = useState16(null);
4987
5119
  useEffect23(() => {
4988
5120
  if (maxCallDuration === null || endTimeRef.current !== null)
@@ -5001,30 +5133,38 @@ function useSessionRemaining() {
5001
5133
  }
5002
5134
 
5003
5135
  // src/components/ChatHeader.tsx
5004
- import { useContext as useContext12, useRef as useRef19 } from "react";
5136
+ import { useContext as useContext12, useRef as useRef21 } from "react";
5005
5137
 
5006
5138
  // src/hooks/useElapsedSeconds.ts
5007
- import { useEffect as useEffect24, useState as useState17 } from "react";
5008
- function useElapsedSeconds(isRunning) {
5139
+ import { useEffect as useEffect24, useRef as useRef19, useState as useState17 } from "react";
5140
+ function useElapsedSeconds(isRunning, resetSignal) {
5009
5141
  const [elapsed, setElapsed] = useState17(0);
5142
+ const accumulatedSecondsRef = useRef19(0);
5010
5143
  useEffect24(() => {
5011
- if (!isRunning) {
5012
- setElapsed(0);
5013
- return;
5014
- }
5015
- const startedAt = Date.now();
5144
+ accumulatedSecondsRef.current = 0;
5016
5145
  setElapsed(0);
5017
- const id = setInterval(() => {
5018
- setElapsed(Math.floor((Date.now() - startedAt) / 1000));
5019
- }, 1000);
5020
- return () => clearInterval(id);
5146
+ }, [resetSignal]);
5147
+ useEffect24(() => {
5148
+ if (!isRunning)
5149
+ return;
5150
+ const resumedAt = Date.now();
5151
+ const accumulatedSeconds = accumulatedSecondsRef.current;
5152
+ const totalSeconds = () => accumulatedSeconds + Math.floor((Date.now() - resumedAt) / 1000);
5153
+ const tick = () => setElapsed(totalSeconds());
5154
+ tick();
5155
+ const id = setInterval(tick, 1000);
5156
+ return () => {
5157
+ clearInterval(id);
5158
+ accumulatedSecondsRef.current = totalSeconds();
5159
+ setElapsed(accumulatedSecondsRef.current);
5160
+ };
5021
5161
  }, [isRunning]);
5022
5162
  return elapsed;
5023
5163
  }
5024
5164
 
5025
5165
  // src/hooks/useTextMode.ts
5026
5166
  import { useLocalParticipant as useLocalParticipant11 } from "@livekit/components-react/hooks";
5027
- import { useCallback as useCallback15, useContext as useContext11, useRef as useRef18 } from "react";
5167
+ import { useCallback as useCallback15, useContext as useContext11, useRef as useRef20 } from "react";
5028
5168
  var textEncoder6 = new TextEncoder;
5029
5169
  function useTextMode() {
5030
5170
  const ctx = useContext11(LiveAgentContext);
@@ -5033,7 +5173,7 @@ function useTextMode() {
5033
5173
  }
5034
5174
  const { textMode, setTextModeState, sidebarTab, setSidebarTab } = ctx;
5035
5175
  const { localParticipant } = useLocalParticipant11();
5036
- const confirmedTextModeRef = useRef18(false);
5176
+ const confirmedTextModeRef = useRef20(false);
5037
5177
  const toggleTextMode = useCallback15(async () => {
5038
5178
  const next = !textMode;
5039
5179
  setTextModeState(next);
@@ -5073,8 +5213,9 @@ function ChatHeader() {
5073
5213
  controlBarRef,
5074
5214
  setIsDragging
5075
5215
  } = ctx;
5076
- const elapsed = useElapsedSeconds(isConnected);
5077
- const headerRef = useRef19(null);
5216
+ const { isHeld } = useSessionHoldContext();
5217
+ const elapsed = useElapsedSeconds(isConnected && !isHeld, isConnected);
5218
+ const headerRef = useRef21(null);
5078
5219
  const followsPanel = variant === "floating" && isPanelOpen;
5079
5220
  const dragFollowers = followsPanel ? [panelRef, controlBarRef] : null;
5080
5221
  const { wasDraggedRef } = useLauncherDrag(headerRef, commitLauncherDrop, dragFollowers, setIsDragging);
@@ -5086,7 +5227,7 @@ function ChatHeader() {
5086
5227
  className: "skippr:flex skippr:items-center skippr:gap-3",
5087
5228
  children: [
5088
5229
  isConnected && /* @__PURE__ */ jsx14(HeaderModeToggle, {}),
5089
- isConnected && /* @__PURE__ */ jsxs11("div", {
5230
+ isConnected && !isHeld && /* @__PURE__ */ jsxs11("div", {
5090
5231
  className: "skippr:flex skippr:items-center skippr:gap-1.5 skippr:rounded-full skippr:bg-primary-foreground/20 skippr:px-2.5 skippr:py-1",
5091
5232
  children: [
5092
5233
  /* @__PURE__ */ jsxs11("span", {
@@ -5191,7 +5332,7 @@ function LoadingDots({ label }) {
5191
5332
  }
5192
5333
 
5193
5334
  // src/components/LoginFlow.tsx
5194
- import { useCallback as useCallback16, useEffect as useEffect25, useRef as useRef20, useState as useState18 } from "react";
5335
+ import { useCallback as useCallback16, useEffect as useEffect25, useRef as useRef22, useState as useState18 } from "react";
5195
5336
 
5196
5337
  // src/components/ui/button.tsx
5197
5338
  import { forwardRef as forwardRef3 } from "react";
@@ -5319,8 +5460,8 @@ function EmailStep({ email, onEmailChange, onSubmit, error, isSubmitting }) {
5319
5460
  function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
5320
5461
  const [digits, setDigits] = useState18(Array(OTP_LENGTH).fill(""));
5321
5462
  const [resendCooldown, setResendCooldown] = useState18(0);
5322
- const inputRefs = useRef20([]);
5323
- const submittedRef = useRef20(false);
5463
+ const inputRefs = useRef22([]);
5464
+ const submittedRef = useRef22(false);
5324
5465
  useEffect25(() => {
5325
5466
  inputRefs.current[0]?.focus();
5326
5467
  }, []);
@@ -5469,15 +5610,15 @@ function OtpStep({ email, onSubmit, onResend, onBack, error, isSubmitting }) {
5469
5610
  }
5470
5611
 
5471
5612
  // src/components/MessageList.tsx
5472
- import { useCallback as useCallback17, useLayoutEffect as useLayoutEffect3, useRef as useRef22, useState as useState20 } from "react";
5613
+ import { useCallback as useCallback17, useLayoutEffect as useLayoutEffect3, useRef as useRef24, useState as useState20 } from "react";
5473
5614
 
5474
5615
  // src/components/ChatInput.tsx
5475
- import { useEffect as useEffect26, useRef as useRef21, useState as useState19 } from "react";
5616
+ import { useEffect as useEffect26, useRef as useRef23, useState as useState19 } from "react";
5476
5617
  import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
5477
5618
  var MAX_INPUT_HEIGHT = 60;
5478
5619
  function ChatInput({ sendChatMessage, isSendingChat, autoFocus = false }) {
5479
5620
  const [inputText, setInputText] = useState19("");
5480
- const textareaRef = useRef21(null);
5621
+ const textareaRef = useRef23(null);
5481
5622
  const canSend = inputText.trim().length > 0 && !isSendingChat;
5482
5623
  useEffect26(() => {
5483
5624
  if (autoFocus)
@@ -5690,9 +5831,9 @@ function MessageList({
5690
5831
  autoFocus = false,
5691
5832
  readOnly = false
5692
5833
  }) {
5693
- const containerRef = useRef22(null);
5694
- const isPinnedToBottom = useRef22(true);
5695
- const lastSeenMessageId = useRef22(undefined);
5834
+ const containerRef = useRef24(null);
5835
+ const isPinnedToBottom = useRef24(true);
5836
+ const lastSeenMessageId = useRef24(undefined);
5696
5837
  const [showJumpToLatest, setShowJumpToLatest] = useState20(false);
5697
5838
  const lastMessage = messages.length > 0 ? messages[messages.length - 1] : undefined;
5698
5839
  const [dismissedPlanId, setDismissedPlanId] = useState20(null);
@@ -6283,7 +6424,7 @@ function AgentCursorMount({ animated }) {
6283
6424
  function PlanPanelOpener() {
6284
6425
  const plan = usePlanUpdates();
6285
6426
  const { expandPanel } = useLiveAgent();
6286
- const surfacedPlanIdRef = useRef23(null);
6427
+ const surfacedPlanIdRef = useRef25(null);
6287
6428
  useEffect29(() => {
6288
6429
  if (plan?.state !== "proposed" || surfacedPlanIdRef.current === plan.planId)
6289
6430
  return;
@@ -6370,7 +6511,7 @@ function LiveAgent(props) {
6370
6511
  onStartError: expandOnSessionStartError,
6371
6512
  onDisconnect: minimizeOnSessionDisconnect
6372
6513
  });
6373
- const teardownInFlightRef = useRef23(false);
6514
+ const teardownInFlightRef = useRef25(false);
6374
6515
  teardownInFlightRef.current = isPaused || isPausing || isDisconnecting;
6375
6516
  const handleRoomDisconnected = useCallback18(() => {
6376
6517
  if (teardownInFlightRef.current)
@@ -6385,8 +6526,8 @@ function LiveAgent(props) {
6385
6526
  const [textMode, setTextMode] = useState21(false);
6386
6527
  const [panelExpanded, setPanelExpanded] = useState21(false);
6387
6528
  const togglePanelExpanded = useCallback18(() => setPanelExpanded((prev) => !prev), []);
6388
- const panelRef = useRef23(null);
6389
- const controlBarRef = useRef23(null);
6529
+ const panelRef = useRef25(null);
6530
+ const controlBarRef = useRef25(null);
6390
6531
  const [isDragging, setIsDragging] = useState21(false);
6391
6532
  const setTextModeState = useCallback18((enabled) => {
6392
6533
  setTextMode(enabled);
@@ -6472,8 +6613,8 @@ function LiveAgent(props) {
6472
6613
  } catch {}
6473
6614
  }, []);
6474
6615
  const savedLauncherBottom = readSavedLauncherBottom();
6475
- const hasDraggedRef = useRef23(savedLauncherBottom !== null);
6476
- const verticalAlignRef = useRef23(verticalAlign);
6616
+ const hasDraggedRef = useRef25(savedLauncherBottom !== null);
6617
+ const verticalAlignRef = useRef25(verticalAlign);
6477
6618
  const [launcherBottomPx, setLauncherBottomPxState] = useState21(() => savedLauncherBottom !== null ? clampLauncherBottom(savedLauncherBottom) : verticalAlignToBottomPx(verticalAlign));
6478
6619
  const [popsDown, setPopsDown] = useState21(() => launcherPopsDown(launcherBottomPx));
6479
6620
  const setLauncherBottomPx = useCallback18((px) => {
@@ -6484,7 +6625,7 @@ function LiveAgent(props) {
6484
6625
  localStorage.setItem("skippr_widget_bottom", String(px));
6485
6626
  } catch {}
6486
6627
  }, []);
6487
- const launcherBottomPxRef = useRef23(launcherBottomPx);
6628
+ const launcherBottomPxRef = useRef25(launcherBottomPx);
6488
6629
  launcherBottomPxRef.current = launcherBottomPx;
6489
6630
  const commitLauncherDrop = useCallback18(({ side, bottomPx }) => {
6490
6631
  setPositionWithPersist(side);
@@ -6692,47 +6833,49 @@ function LiveAgent(props) {
6692
6833
  onDisconnected: handleRoomDisconnected,
6693
6834
  children: [
6694
6835
  connection && !textMode && /* @__PURE__ */ jsx28(RoomAudioRenderer, {}),
6695
- connection && captureMode === CAPTURE_MODE.Screenshare && /* @__PURE__ */ jsx28(AutoStartMedia, {
6696
- pendingScreenStream,
6697
- pushOrTapMicMode: isRequestResponseMicMode(agentControls?.micMode)
6698
- }),
6699
- connection && captureMode === CAPTURE_MODE.Auto && /* @__PURE__ */ jsx28(DomCapture, {
6700
- pushOrTapMicMode: isRequestResponseMicMode(agentControls?.micMode)
6701
- }),
6702
- /* @__PURE__ */ jsxs22(ShadowHost, {
6836
+ /* @__PURE__ */ jsxs22(SessionHoldProvider, {
6703
6837
  children: [
6704
- connection && captureMode === CAPTURE_MODE.Auto && agentControls?.highlight && /* @__PURE__ */ jsx28(HighlightOverlay, {}),
6705
- connection && captureMode === CAPTURE_MODE.Auto && agentControls?.actions && /* @__PURE__ */ jsx28(PageActionHandler, {}),
6706
- connection && captureMode === CAPTURE_MODE.Auto && agentControls?.actions && /* @__PURE__ */ jsx28(PlanPanelOpener, {}),
6707
- connection && captureMode === CAPTURE_MODE.Auto && (agentControls?.highlight || agentControls?.actions) && /* @__PURE__ */ jsx28(AgentCursorMount, {
6708
- animated: shouldAnimateCursor
6838
+ connection && captureMode === CAPTURE_MODE.Screenshare && /* @__PURE__ */ jsx28(AutoStartMedia, {
6839
+ pendingScreenStream,
6840
+ pushOrTapMicMode: isRequestResponseMicMode(agentControls?.micMode)
6709
6841
  }),
6710
- /* @__PURE__ */ jsx28(SessionHoldProvider, {
6711
- children: /* @__PURE__ */ jsx28(VoiceTurnProvider, {
6712
- children: /* @__PURE__ */ jsx28(TranscriptionsProvider, {
6713
- children: /* @__PURE__ */ jsxs22("div", {
6714
- id: WIDGET_ROOT_ID,
6715
- children: [
6716
- isMinimized && !showControlBar && /* @__PURE__ */ jsx28(MinimizedBubble, {
6717
- welcomeMessage,
6718
- welcomeDismissed,
6719
- onDismissWelcome: dismissWelcome
6720
- }),
6721
- showControlBar && !hideControls && /* @__PURE__ */ jsx28(SessionControlBar, {}),
6722
- /* @__PURE__ */ jsx28(SidebarTrigger, {}),
6723
- /* @__PURE__ */ jsx28(Sidebar, {
6724
- hideControls,
6725
- hideHeader,
6726
- startSessionLabel
6727
- })
6728
- ]
6842
+ connection && captureMode === CAPTURE_MODE.Auto && /* @__PURE__ */ jsx28(DomCapture, {
6843
+ pushOrTapMicMode: isRequestResponseMicMode(agentControls?.micMode)
6844
+ }),
6845
+ /* @__PURE__ */ jsxs22(ShadowHost, {
6846
+ children: [
6847
+ connection && captureMode === CAPTURE_MODE.Auto && agentControls?.highlight && /* @__PURE__ */ jsx28(HighlightOverlay, {}),
6848
+ connection && captureMode === CAPTURE_MODE.Auto && agentControls?.actions && /* @__PURE__ */ jsx28(PageActionHandler, {}),
6849
+ connection && captureMode === CAPTURE_MODE.Auto && agentControls?.actions && /* @__PURE__ */ jsx28(PlanPanelOpener, {}),
6850
+ connection && captureMode === CAPTURE_MODE.Auto && (agentControls?.highlight || agentControls?.actions) && /* @__PURE__ */ jsx28(AgentCursorMount, {
6851
+ animated: shouldAnimateCursor
6852
+ }),
6853
+ /* @__PURE__ */ jsx28(VoiceTurnProvider, {
6854
+ children: /* @__PURE__ */ jsx28(TranscriptionsProvider, {
6855
+ children: /* @__PURE__ */ jsxs22("div", {
6856
+ id: WIDGET_ROOT_ID,
6857
+ children: [
6858
+ isMinimized && !showControlBar && /* @__PURE__ */ jsx28(MinimizedBubble, {
6859
+ welcomeMessage,
6860
+ welcomeDismissed,
6861
+ onDismissWelcome: dismissWelcome
6862
+ }),
6863
+ showControlBar && !hideControls && /* @__PURE__ */ jsx28(SessionControlBar, {}),
6864
+ /* @__PURE__ */ jsx28(SidebarTrigger, {}),
6865
+ /* @__PURE__ */ jsx28(Sidebar, {
6866
+ hideControls,
6867
+ hideHeader,
6868
+ startSessionLabel
6869
+ })
6870
+ ]
6871
+ })
6729
6872
  })
6730
6873
  })
6731
- })
6732
- })
6874
+ ]
6875
+ }),
6876
+ children
6733
6877
  ]
6734
- }),
6735
- children
6878
+ })
6736
6879
  ]
6737
6880
  })
6738
6881
  });
@@ -6743,9 +6886,14 @@ function useIsLocalSpeaking() {
6743
6886
  const { localParticipant } = useLocalParticipant12();
6744
6887
  return useIsSpeaking(localParticipant);
6745
6888
  }
6889
+ // src/hooks/useIsSessionHeld.ts
6890
+ function useIsSessionHeld() {
6891
+ return useSessionHoldContext().isHeld;
6892
+ }
6746
6893
  export {
6747
6894
  useMediaControls,
6748
6895
  useLiveAgent,
6896
+ useIsSessionHeld,
6749
6897
  useIsLocalSpeaking,
6750
6898
  useElapsedSeconds,
6751
6899
  useAgentVoiceState,