farvex 1.0.1 → 2.0.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.
@@ -1,9 +1,50 @@
1
+ "use client";
1
2
  'use strict';
2
3
 
3
4
  var componentsReact = require('@livekit/components-react');
4
5
  var livekitClient = require('livekit-client');
6
+ var jsxRuntime = require('react/jsx-runtime');
5
7
 
6
-
8
+ // src/livekit/index.ts
9
+ var SessionRoom = ({
10
+ session,
11
+ controls,
12
+ audio = true,
13
+ video = false,
14
+ onConnected,
15
+ onDisconnected,
16
+ onError,
17
+ ...props
18
+ }) => {
19
+ if (!session?.join) {
20
+ return null;
21
+ }
22
+ const sessionId = session.sessionId;
23
+ return /* @__PURE__ */ jsxRuntime.jsx(
24
+ componentsReact.LiveKitRoom,
25
+ {
26
+ ...props,
27
+ serverUrl: session.join.url,
28
+ token: session.join.token,
29
+ connect: true,
30
+ audio,
31
+ video,
32
+ onConnected: () => {
33
+ controls?.mediaConnected(sessionId);
34
+ onConnected?.();
35
+ },
36
+ onDisconnected: (reason) => {
37
+ controls?.mediaDisconnected(sessionId);
38
+ onDisconnected?.(reason);
39
+ },
40
+ onError: (error) => {
41
+ controls?.mediaFailed(error, sessionId);
42
+ onError?.(error);
43
+ }
44
+ },
45
+ sessionId
46
+ );
47
+ };
7
48
 
8
49
  Object.defineProperty(exports, "LiveKitRoom", {
9
50
  enumerable: true,
@@ -81,5 +122,6 @@ Object.defineProperty(exports, "Track", {
81
122
  enumerable: true,
82
123
  get: function () { return livekitClient.Track; }
83
124
  });
125
+ exports.SessionRoom = SessionRoom;
84
126
  //# sourceMappingURL=index.cjs.map
85
127
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs","sourcesContent":[]}
1
+ {"version":3,"sources":["../../src/livekit/session-room.tsx"],"names":["jsx","LiveKitRoom"],"mappings":";;;;;;;AAmBO,IAAM,cAAc,CAAC;AAAA,EAC1B,OAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA,GAAQ,IAAA;AAAA,EACR,KAAA,GAAQ,KAAA;AAAA,EACR,WAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AAAA,EACA,GAAG;AACL,CAAA,KAAwB;AACtB,EAAA,IAAI,CAAC,SAAS,IAAA,EAAM;AAClB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,YAAY,OAAA,CAAQ,SAAA;AAE1B,EAAA,uBACEA,cAAA;AAAA,IAACC,2BAAA;AAAA,IAAA;AAAA,MAEE,GAAG,KAAA;AAAA,MACJ,SAAA,EAAW,QAAQ,IAAA,CAAK,GAAA;AAAA,MACxB,KAAA,EAAO,QAAQ,IAAA,CAAK,KAAA;AAAA,MACpB,OAAA,EAAO,IAAA;AAAA,MACP,KAAA;AAAA,MACA,KAAA;AAAA,MACA,aAAa,MAAM;AACjB,QAAA,QAAA,EAAU,eAAe,SAAS,CAAA;AAClC,QAAA,WAAA,IAAc;AAAA,MAChB,CAAA;AAAA,MACA,cAAA,EAAgB,CAAC,MAAA,KAAW;AAC1B,QAAA,QAAA,EAAU,kBAAkB,SAAS,CAAA;AACrC,QAAA,cAAA,GAAiB,MAAM,CAAA;AAAA,MACzB,CAAA;AAAA,MACA,OAAA,EAAS,CAAC,KAAA,KAAU;AAClB,QAAA,QAAA,EAAU,WAAA,CAAY,OAAO,SAAS,CAAA;AACtC,QAAA,OAAA,GAAU,KAAK,CAAA;AAAA,MACjB;AAAA,KAAA;AAAA,IAlBK;AAAA,GAmBP;AAEJ","file":"index.cjs","sourcesContent":["import { LiveKitRoom } from \"@livekit/components-react\";\nimport type { ComponentProps } from \"react\";\n\nimport type { CurrentSession } from \"../core/types\";\nimport type { Nullable } from \"../shared/types\";\n\ntype LiveKitRoomProps = ComponentProps<typeof LiveKitRoom>;\n\nexport type SessionRoomControls = {\n mediaConnected: (sessionId?: string) => void;\n mediaDisconnected: (sessionId?: string) => void;\n mediaFailed: (error: Error, sessionId?: string) => void;\n};\n\nexport type SessionRoomProps = Omit<LiveKitRoomProps, \"serverUrl\" | \"token\" | \"connect\"> & {\n session: Nullable<CurrentSession>;\n controls?: SessionRoomControls;\n};\n\nexport const SessionRoom = ({\n session,\n controls,\n audio = true,\n video = false,\n onConnected,\n onDisconnected,\n onError,\n ...props\n}: SessionRoomProps) => {\n if (!session?.join) {\n return null;\n }\n\n const sessionId = session.sessionId;\n\n return (\n <LiveKitRoom\n key={sessionId}\n {...props}\n serverUrl={session.join.url}\n token={session.join.token}\n connect\n audio={audio}\n video={video}\n onConnected={() => {\n controls?.mediaConnected(sessionId);\n onConnected?.();\n }}\n onDisconnected={(reason) => {\n controls?.mediaDisconnected(sessionId);\n onDisconnected?.(reason);\n }}\n onError={(error) => {\n controls?.mediaFailed(error, sessionId);\n onError?.(error);\n }}\n />\n );\n};\n"]}
@@ -1,2 +1,20 @@
1
+ import { LiveKitRoom } from '@livekit/components-react';
1
2
  export { LiveKitRoom, RoomAudioRenderer, RoomContext, StartAudio, useConnectionState, useIsMuted, useIsSpeaking, useLocalParticipant, useMediaDeviceSelect, useParticipants, useRemoteParticipants, useRoomContext, useTracks } from '@livekit/components-react';
2
3
  export { ConnectionQuality, ConnectionState, DisconnectReason, Participant as LiveKitParticipant, LocalParticipant, RemoteParticipant, Room, RoomEvent, Track, TrackPublication } from 'livekit-client';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
5
+ import { ComponentProps } from 'react';
6
+ import { N as Nullable, c as CurrentSession } from '../types-BjVaSMZ6.cjs';
7
+
8
+ type LiveKitRoomProps = ComponentProps<typeof LiveKitRoom>;
9
+ type SessionRoomControls = {
10
+ mediaConnected: (sessionId?: string) => void;
11
+ mediaDisconnected: (sessionId?: string) => void;
12
+ mediaFailed: (error: Error, sessionId?: string) => void;
13
+ };
14
+ type SessionRoomProps = Omit<LiveKitRoomProps, "serverUrl" | "token" | "connect"> & {
15
+ session: Nullable<CurrentSession>;
16
+ controls?: SessionRoomControls;
17
+ };
18
+ declare const SessionRoom: ({ session, controls, audio, video, onConnected, onDisconnected, onError, ...props }: SessionRoomProps) => react_jsx_runtime.JSX.Element | null;
19
+
20
+ export { SessionRoom, type SessionRoomControls, type SessionRoomProps };
@@ -1,2 +1,20 @@
1
+ import { LiveKitRoom } from '@livekit/components-react';
1
2
  export { LiveKitRoom, RoomAudioRenderer, RoomContext, StartAudio, useConnectionState, useIsMuted, useIsSpeaking, useLocalParticipant, useMediaDeviceSelect, useParticipants, useRemoteParticipants, useRoomContext, useTracks } from '@livekit/components-react';
2
3
  export { ConnectionQuality, ConnectionState, DisconnectReason, Participant as LiveKitParticipant, LocalParticipant, RemoteParticipant, Room, RoomEvent, Track, TrackPublication } from 'livekit-client';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
5
+ import { ComponentProps } from 'react';
6
+ import { N as Nullable, c as CurrentSession } from '../types-BjVaSMZ6.js';
7
+
8
+ type LiveKitRoomProps = ComponentProps<typeof LiveKitRoom>;
9
+ type SessionRoomControls = {
10
+ mediaConnected: (sessionId?: string) => void;
11
+ mediaDisconnected: (sessionId?: string) => void;
12
+ mediaFailed: (error: Error, sessionId?: string) => void;
13
+ };
14
+ type SessionRoomProps = Omit<LiveKitRoomProps, "serverUrl" | "token" | "connect"> & {
15
+ session: Nullable<CurrentSession>;
16
+ controls?: SessionRoomControls;
17
+ };
18
+ declare const SessionRoom: ({ session, controls, audio, video, onConnected, onDisconnected, onError, ...props }: SessionRoomProps) => react_jsx_runtime.JSX.Element | null;
19
+
20
+ export { SessionRoom, type SessionRoomControls, type SessionRoomProps };
@@ -1,4 +1,50 @@
1
+ "use client";
2
+ import { LiveKitRoom } from '@livekit/components-react';
1
3
  export { LiveKitRoom, RoomAudioRenderer, RoomContext, StartAudio, useConnectionState, useIsMuted, useIsSpeaking, useLocalParticipant, useMediaDeviceSelect, useParticipants, useRemoteParticipants, useRoomContext, useTracks } from '@livekit/components-react';
2
4
  export { ConnectionQuality, ConnectionState, DisconnectReason, Room, RoomEvent, Track } from 'livekit-client';
5
+ import { jsx } from 'react/jsx-runtime';
6
+
7
+ // src/livekit/index.ts
8
+ var SessionRoom = ({
9
+ session,
10
+ controls,
11
+ audio = true,
12
+ video = false,
13
+ onConnected,
14
+ onDisconnected,
15
+ onError,
16
+ ...props
17
+ }) => {
18
+ if (!session?.join) {
19
+ return null;
20
+ }
21
+ const sessionId = session.sessionId;
22
+ return /* @__PURE__ */ jsx(
23
+ LiveKitRoom,
24
+ {
25
+ ...props,
26
+ serverUrl: session.join.url,
27
+ token: session.join.token,
28
+ connect: true,
29
+ audio,
30
+ video,
31
+ onConnected: () => {
32
+ controls?.mediaConnected(sessionId);
33
+ onConnected?.();
34
+ },
35
+ onDisconnected: (reason) => {
36
+ controls?.mediaDisconnected(sessionId);
37
+ onDisconnected?.(reason);
38
+ },
39
+ onError: (error) => {
40
+ controls?.mediaFailed(error, sessionId);
41
+ onError?.(error);
42
+ }
43
+ },
44
+ sessionId
45
+ );
46
+ };
47
+
48
+ export { SessionRoom };
3
49
  //# sourceMappingURL=index.js.map
4
50
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js","sourcesContent":[]}
1
+ {"version":3,"sources":["../../src/livekit/session-room.tsx"],"names":[],"mappings":";;;;;;AAmBO,IAAM,cAAc,CAAC;AAAA,EAC1B,OAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA,GAAQ,IAAA;AAAA,EACR,KAAA,GAAQ,KAAA;AAAA,EACR,WAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AAAA,EACA,GAAG;AACL,CAAA,KAAwB;AACtB,EAAA,IAAI,CAAC,SAAS,IAAA,EAAM;AAClB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,YAAY,OAAA,CAAQ,SAAA;AAE1B,EAAA,uBACE,GAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MAEE,GAAG,KAAA;AAAA,MACJ,SAAA,EAAW,QAAQ,IAAA,CAAK,GAAA;AAAA,MACxB,KAAA,EAAO,QAAQ,IAAA,CAAK,KAAA;AAAA,MACpB,OAAA,EAAO,IAAA;AAAA,MACP,KAAA;AAAA,MACA,KAAA;AAAA,MACA,aAAa,MAAM;AACjB,QAAA,QAAA,EAAU,eAAe,SAAS,CAAA;AAClC,QAAA,WAAA,IAAc;AAAA,MAChB,CAAA;AAAA,MACA,cAAA,EAAgB,CAAC,MAAA,KAAW;AAC1B,QAAA,QAAA,EAAU,kBAAkB,SAAS,CAAA;AACrC,QAAA,cAAA,GAAiB,MAAM,CAAA;AAAA,MACzB,CAAA;AAAA,MACA,OAAA,EAAS,CAAC,KAAA,KAAU;AAClB,QAAA,QAAA,EAAU,WAAA,CAAY,OAAO,SAAS,CAAA;AACtC,QAAA,OAAA,GAAU,KAAK,CAAA;AAAA,MACjB;AAAA,KAAA;AAAA,IAlBK;AAAA,GAmBP;AAEJ","file":"index.js","sourcesContent":["import { LiveKitRoom } from \"@livekit/components-react\";\nimport type { ComponentProps } from \"react\";\n\nimport type { CurrentSession } from \"../core/types\";\nimport type { Nullable } from \"../shared/types\";\n\ntype LiveKitRoomProps = ComponentProps<typeof LiveKitRoom>;\n\nexport type SessionRoomControls = {\n mediaConnected: (sessionId?: string) => void;\n mediaDisconnected: (sessionId?: string) => void;\n mediaFailed: (error: Error, sessionId?: string) => void;\n};\n\nexport type SessionRoomProps = Omit<LiveKitRoomProps, \"serverUrl\" | \"token\" | \"connect\"> & {\n session: Nullable<CurrentSession>;\n controls?: SessionRoomControls;\n};\n\nexport const SessionRoom = ({\n session,\n controls,\n audio = true,\n video = false,\n onConnected,\n onDisconnected,\n onError,\n ...props\n}: SessionRoomProps) => {\n if (!session?.join) {\n return null;\n }\n\n const sessionId = session.sessionId;\n\n return (\n <LiveKitRoom\n key={sessionId}\n {...props}\n serverUrl={session.join.url}\n token={session.join.token}\n connect\n audio={audio}\n video={video}\n onConnected={() => {\n controls?.mediaConnected(sessionId);\n onConnected?.();\n }}\n onDisconnected={(reason) => {\n controls?.mediaDisconnected(sessionId);\n onDisconnected?.(reason);\n }}\n onError={(error) => {\n controls?.mediaFailed(error, sessionId);\n onError?.(error);\n }}\n />\n );\n};\n"]}
@@ -6,6 +6,7 @@ var jsxRuntime = require('react/jsx-runtime');
6
6
 
7
7
  // src/react/index.tsx
8
8
  var CallpadContext = react.createContext(null);
9
+ var emptyCurrentSession = { current: null, incoming: [], busy: false };
9
10
  var CallpadProvider = ({
10
11
  client,
11
12
  connect = false,
@@ -53,11 +54,23 @@ var useSessions = () => {
53
54
  var useSession = (sessionId) => {
54
55
  const client = useCallpad();
55
56
  return react.useSyncExternalStore(
56
- (notify) => client.subscribe(sessionId ? `session:${sessionId}` : "sessions", notify),
57
- () => client.sessions.get(sessionId),
57
+ (notify) => sessionId ? client.subscribe(`session:${sessionId}`, notify) : () => void 0,
58
+ () => sessionId ? client.sessions.get(sessionId) : null,
58
59
  () => null
59
60
  );
60
61
  };
62
+ var useCurrentSession = () => {
63
+ const client = useCallpad();
64
+ return react.useSyncExternalStore(
65
+ client.session.subscribe,
66
+ client.session.get,
67
+ () => emptyCurrentSession
68
+ );
69
+ };
70
+ var useCurrentSessionActions = () => {
71
+ const client = useCallpad();
72
+ return client.session;
73
+ };
61
74
  var useIncomingInvites = () => {
62
75
  const client = useCallpad();
63
76
  return react.useSyncExternalStore(
@@ -113,6 +126,8 @@ var durationOf = (session, now) => {
113
126
  exports.CallpadProvider = CallpadProvider;
114
127
  exports.useCallpad = useCallpad;
115
128
  exports.useCan = useCan;
129
+ exports.useCurrentSession = useCurrentSession;
130
+ exports.useCurrentSessionActions = useCurrentSessionActions;
116
131
  exports.useIncomingInvite = useIncomingInvite;
117
132
  exports.useIncomingInvites = useIncomingInvites;
118
133
  exports.useSession = useSession;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/index.tsx"],"names":["createContext","useEffect","useContext","useSyncExternalStore","useState"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\n\nimport type { Nullable } from \"../shared/types\";\nimport type {\n ClientStatus,\n HostClient,\n SessionAction,\n SessionClient,\n SessionDuration,\n SessionInvite,\n VoiceSession,\n} from \"../core/types\";\n\nconst CallpadContext = createContext<SessionClient | HostClient | null>(null);\n\ntype CallpadClient = SessionClient | HostClient;\n\nexport type CallpadProviderProps<TClient extends CallpadClient = CallpadClient> = {\n client: TClient;\n connect?: boolean;\n disposeOnUnmount?: boolean;\n children: ReactNode;\n};\n\nexport const CallpadProvider = <TClient extends CallpadClient>({\n client,\n connect = false,\n disposeOnUnmount = false,\n children,\n}: CallpadProviderProps<TClient>) => {\n useEffect(() => {\n if (!connect) {\n return;\n }\n void client.connect().catch(() => undefined);\n return () => {\n if (disposeOnUnmount) {\n void client.dispose();\n return;\n }\n void client.disconnect();\n };\n }, [client, connect, disposeOnUnmount]);\n\n return <CallpadContext.Provider value={client}>{children}</CallpadContext.Provider>;\n};\n\nexport const useCallpad = <TClient extends CallpadClient = SessionClient>(): TClient => {\n const client = useContext(CallpadContext);\n if (!client) {\n throw new Error(\"CallpadProvider is required\");\n }\n return client as TClient;\n};\n\nexport const useStatus = (): ClientStatus => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"status\", notify),\n () => client.status,\n () => \"idle\",\n );\n};\n\nexport const useSessions = (): readonly VoiceSession[] => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"sessions\", notify),\n () => client.sessions.list(),\n () => [],\n );\n};\n\nexport const useSession = (sessionId?: string): Nullable<VoiceSession> => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(sessionId ? `session:${sessionId}` : \"sessions\", notify),\n () => client.sessions.get(sessionId),\n () => null,\n );\n};\n\nexport const useIncomingInvites = (): readonly SessionInvite[] => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"invites\", notify),\n () => client.invites.list(),\n () => [],\n );\n};\n\nexport const useIncomingInvite = (): Nullable<SessionInvite> => {\n const invites = useIncomingInvites();\n return invites[0] ?? null;\n};\n\nexport const useCan = (sessionId: string | undefined, action: SessionAction): boolean => {\n const client = useCallpad();\n const session = useSession(sessionId);\n if (!session) {\n return false;\n }\n return client.sessions.can(session, action);\n};\n\nexport const useSessionDuration = (sessionId?: string): SessionDuration => {\n const session = useSession(sessionId);\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n if (!session || session.state === \"ended\") {\n return;\n }\n setNow(Date.now());\n const timer = window.setInterval(() => {\n setNow(Date.now());\n }, 1000);\n return () => {\n window.clearInterval(timer);\n };\n }, [session]);\n\n return durationOf(session, now);\n};\n\nconst durationOf = (session: Nullable<VoiceSession>, now: number): SessionDuration => {\n if (!session) {\n return { seconds: 0, startedAt: null, endedAt: null, running: false };\n }\n const startedAt = session.answeredAt ?? session.createdAt;\n const endedAt = session.endedAt;\n const end = endedAt ? Date.parse(endedAt) : now;\n return {\n seconds: Math.max(0, Math.floor((end - Date.parse(startedAt)) / 1000)),\n startedAt,\n endedAt,\n running: !endedAt && session.state !== \"ended\",\n };\n};\n"]}
1
+ {"version":3,"sources":["../../src/react/index.tsx"],"names":["createContext","useEffect","useContext","useSyncExternalStore","useState"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\n\nimport type { Nullable } from \"../shared/types\";\nimport type {\n ClientStatus,\n CurrentSessionSnapshot,\n HostClient,\n SessionAction,\n SessionClient,\n SessionDuration,\n SessionInvite,\n VoiceSession,\n} from \"../core/types\";\n\nconst CallpadContext = createContext<SessionClient | HostClient | null>(null);\n\ntype CallpadClient = SessionClient | HostClient;\n\nconst emptyCurrentSession: CurrentSessionSnapshot = { current: null, incoming: [], busy: false };\n\nexport type CallpadProviderProps<TClient extends CallpadClient = CallpadClient> = {\n client: TClient;\n connect?: boolean;\n disposeOnUnmount?: boolean;\n children: ReactNode;\n};\n\nexport const CallpadProvider = <TClient extends CallpadClient>({\n client,\n connect = false,\n disposeOnUnmount = false,\n children,\n}: CallpadProviderProps<TClient>) => {\n useEffect(() => {\n if (!connect) {\n return;\n }\n void client.connect().catch(() => undefined);\n return () => {\n if (disposeOnUnmount) {\n void client.dispose();\n return;\n }\n void client.disconnect();\n };\n }, [client, connect, disposeOnUnmount]);\n\n return <CallpadContext.Provider value={client}>{children}</CallpadContext.Provider>;\n};\n\nexport const useCallpad = <TClient extends CallpadClient = SessionClient>(): TClient => {\n const client = useContext(CallpadContext);\n if (!client) {\n throw new Error(\"CallpadProvider is required\");\n }\n return client as TClient;\n};\n\nexport const useStatus = (): ClientStatus => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"status\", notify),\n () => client.status,\n () => \"idle\",\n );\n};\n\nexport const useSessions = (): readonly VoiceSession[] => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"sessions\", notify),\n () => client.sessions.list(),\n () => [],\n );\n};\n\nexport const useSession = (sessionId: Nullable<string>): Nullable<VoiceSession> => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => (sessionId ? client.subscribe(`session:${sessionId}`, notify) : () => undefined),\n () => (sessionId ? client.sessions.get(sessionId) : null),\n () => null,\n );\n};\n\nexport const useCurrentSession = (): CurrentSessionSnapshot => {\n const client = useCallpad();\n return useSyncExternalStore(\n client.session.subscribe,\n client.session.get,\n () => emptyCurrentSession,\n );\n};\n\nexport const useCurrentSessionActions = <\n TControls extends CallpadClient[\"session\"] = CallpadClient[\"session\"],\n>(): TControls => {\n const client = useCallpad();\n return client.session as TControls;\n};\n\nexport const useIncomingInvites = (): readonly SessionInvite[] => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"invites\", notify),\n () => client.invites.list(),\n () => [],\n );\n};\n\nexport const useIncomingInvite = (): Nullable<SessionInvite> => {\n const invites = useIncomingInvites();\n return invites[0] ?? null;\n};\n\nexport const useCan = (sessionId: Nullable<string>, action: SessionAction): boolean => {\n const client = useCallpad();\n const session = useSession(sessionId);\n if (!session) {\n return false;\n }\n return client.sessions.can(session, action);\n};\n\nexport const useSessionDuration = (sessionId: Nullable<string>): SessionDuration => {\n const session = useSession(sessionId);\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n if (!session || session.state === \"ended\") {\n return;\n }\n setNow(Date.now());\n const timer = window.setInterval(() => {\n setNow(Date.now());\n }, 1000);\n return () => {\n window.clearInterval(timer);\n };\n }, [session]);\n\n return durationOf(session, now);\n};\n\nconst durationOf = (session: Nullable<VoiceSession>, now: number): SessionDuration => {\n if (!session) {\n return { seconds: 0, startedAt: null, endedAt: null, running: false };\n }\n const startedAt = session.answeredAt ?? session.createdAt;\n const endedAt = session.endedAt;\n const end = endedAt ? Date.parse(endedAt) : now;\n return {\n seconds: Math.max(0, Math.floor((end - Date.parse(startedAt)) / 1000)),\n startedAt,\n endedAt,\n running: !endedAt && session.state !== \"ended\",\n };\n};\n"]}
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { j as SessionClient, H as HostClient, S as SessionAction, N as Nullable, m as SessionInvite, t as VoiceSession, l as SessionDuration, b as ClientStatus } from '../types-Dgwrb3rf.cjs';
3
+ import { m as SessionClient, H as HostClient, N as Nullable, l as SessionAction, d as CurrentSessionSnapshot, r as SessionInvite, G as VoiceSession, q as SessionDuration, b as ClientStatus } from '../types-BjVaSMZ6.cjs';
4
4
 
5
5
  type CallpadClient = SessionClient | HostClient;
6
6
  type CallpadProviderProps<TClient extends CallpadClient = CallpadClient> = {
@@ -13,10 +13,12 @@ declare const CallpadProvider: <TClient extends CallpadClient>({ client, connect
13
13
  declare const useCallpad: <TClient extends CallpadClient = SessionClient>() => TClient;
14
14
  declare const useStatus: () => ClientStatus;
15
15
  declare const useSessions: () => readonly VoiceSession[];
16
- declare const useSession: (sessionId?: string) => Nullable<VoiceSession>;
16
+ declare const useSession: (sessionId: Nullable<string>) => Nullable<VoiceSession>;
17
+ declare const useCurrentSession: () => CurrentSessionSnapshot;
18
+ declare const useCurrentSessionActions: <TControls extends CallpadClient["session"] = CallpadClient["session"]>() => TControls;
17
19
  declare const useIncomingInvites: () => readonly SessionInvite[];
18
20
  declare const useIncomingInvite: () => Nullable<SessionInvite>;
19
- declare const useCan: (sessionId: string | undefined, action: SessionAction) => boolean;
20
- declare const useSessionDuration: (sessionId?: string) => SessionDuration;
21
+ declare const useCan: (sessionId: Nullable<string>, action: SessionAction) => boolean;
22
+ declare const useSessionDuration: (sessionId: Nullable<string>) => SessionDuration;
21
23
 
22
- export { CallpadProvider, type CallpadProviderProps, useCallpad, useCan, useIncomingInvite, useIncomingInvites, useSession, useSessionDuration, useSessions, useStatus };
24
+ export { CallpadProvider, type CallpadProviderProps, useCallpad, useCan, useCurrentSession, useCurrentSessionActions, useIncomingInvite, useIncomingInvites, useSession, useSessionDuration, useSessions, useStatus };
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { j as SessionClient, H as HostClient, S as SessionAction, N as Nullable, m as SessionInvite, t as VoiceSession, l as SessionDuration, b as ClientStatus } from '../types-Dgwrb3rf.js';
3
+ import { m as SessionClient, H as HostClient, N as Nullable, l as SessionAction, d as CurrentSessionSnapshot, r as SessionInvite, G as VoiceSession, q as SessionDuration, b as ClientStatus } from '../types-BjVaSMZ6.js';
4
4
 
5
5
  type CallpadClient = SessionClient | HostClient;
6
6
  type CallpadProviderProps<TClient extends CallpadClient = CallpadClient> = {
@@ -13,10 +13,12 @@ declare const CallpadProvider: <TClient extends CallpadClient>({ client, connect
13
13
  declare const useCallpad: <TClient extends CallpadClient = SessionClient>() => TClient;
14
14
  declare const useStatus: () => ClientStatus;
15
15
  declare const useSessions: () => readonly VoiceSession[];
16
- declare const useSession: (sessionId?: string) => Nullable<VoiceSession>;
16
+ declare const useSession: (sessionId: Nullable<string>) => Nullable<VoiceSession>;
17
+ declare const useCurrentSession: () => CurrentSessionSnapshot;
18
+ declare const useCurrentSessionActions: <TControls extends CallpadClient["session"] = CallpadClient["session"]>() => TControls;
17
19
  declare const useIncomingInvites: () => readonly SessionInvite[];
18
20
  declare const useIncomingInvite: () => Nullable<SessionInvite>;
19
- declare const useCan: (sessionId: string | undefined, action: SessionAction) => boolean;
20
- declare const useSessionDuration: (sessionId?: string) => SessionDuration;
21
+ declare const useCan: (sessionId: Nullable<string>, action: SessionAction) => boolean;
22
+ declare const useSessionDuration: (sessionId: Nullable<string>) => SessionDuration;
21
23
 
22
- export { CallpadProvider, type CallpadProviderProps, useCallpad, useCan, useIncomingInvite, useIncomingInvites, useSession, useSessionDuration, useSessions, useStatus };
24
+ export { CallpadProvider, type CallpadProviderProps, useCallpad, useCan, useCurrentSession, useCurrentSessionActions, useIncomingInvite, useIncomingInvites, useSession, useSessionDuration, useSessions, useStatus };
@@ -4,6 +4,7 @@ import { jsx } from 'react/jsx-runtime';
4
4
 
5
5
  // src/react/index.tsx
6
6
  var CallpadContext = createContext(null);
7
+ var emptyCurrentSession = { current: null, incoming: [], busy: false };
7
8
  var CallpadProvider = ({
8
9
  client,
9
10
  connect = false,
@@ -51,11 +52,23 @@ var useSessions = () => {
51
52
  var useSession = (sessionId) => {
52
53
  const client = useCallpad();
53
54
  return useSyncExternalStore(
54
- (notify) => client.subscribe(sessionId ? `session:${sessionId}` : "sessions", notify),
55
- () => client.sessions.get(sessionId),
55
+ (notify) => sessionId ? client.subscribe(`session:${sessionId}`, notify) : () => void 0,
56
+ () => sessionId ? client.sessions.get(sessionId) : null,
56
57
  () => null
57
58
  );
58
59
  };
60
+ var useCurrentSession = () => {
61
+ const client = useCallpad();
62
+ return useSyncExternalStore(
63
+ client.session.subscribe,
64
+ client.session.get,
65
+ () => emptyCurrentSession
66
+ );
67
+ };
68
+ var useCurrentSessionActions = () => {
69
+ const client = useCallpad();
70
+ return client.session;
71
+ };
59
72
  var useIncomingInvites = () => {
60
73
  const client = useCallpad();
61
74
  return useSyncExternalStore(
@@ -108,6 +121,6 @@ var durationOf = (session, now) => {
108
121
  };
109
122
  };
110
123
 
111
- export { CallpadProvider, useCallpad, useCan, useIncomingInvite, useIncomingInvites, useSession, useSessionDuration, useSessions, useStatus };
124
+ export { CallpadProvider, useCallpad, useCan, useCurrentSession, useCurrentSessionActions, useIncomingInvite, useIncomingInvites, useSession, useSessionDuration, useSessions, useStatus };
112
125
  //# sourceMappingURL=index.js.map
113
126
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/index.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\n\nimport type { Nullable } from \"../shared/types\";\nimport type {\n ClientStatus,\n HostClient,\n SessionAction,\n SessionClient,\n SessionDuration,\n SessionInvite,\n VoiceSession,\n} from \"../core/types\";\n\nconst CallpadContext = createContext<SessionClient | HostClient | null>(null);\n\ntype CallpadClient = SessionClient | HostClient;\n\nexport type CallpadProviderProps<TClient extends CallpadClient = CallpadClient> = {\n client: TClient;\n connect?: boolean;\n disposeOnUnmount?: boolean;\n children: ReactNode;\n};\n\nexport const CallpadProvider = <TClient extends CallpadClient>({\n client,\n connect = false,\n disposeOnUnmount = false,\n children,\n}: CallpadProviderProps<TClient>) => {\n useEffect(() => {\n if (!connect) {\n return;\n }\n void client.connect().catch(() => undefined);\n return () => {\n if (disposeOnUnmount) {\n void client.dispose();\n return;\n }\n void client.disconnect();\n };\n }, [client, connect, disposeOnUnmount]);\n\n return <CallpadContext.Provider value={client}>{children}</CallpadContext.Provider>;\n};\n\nexport const useCallpad = <TClient extends CallpadClient = SessionClient>(): TClient => {\n const client = useContext(CallpadContext);\n if (!client) {\n throw new Error(\"CallpadProvider is required\");\n }\n return client as TClient;\n};\n\nexport const useStatus = (): ClientStatus => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"status\", notify),\n () => client.status,\n () => \"idle\",\n );\n};\n\nexport const useSessions = (): readonly VoiceSession[] => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"sessions\", notify),\n () => client.sessions.list(),\n () => [],\n );\n};\n\nexport const useSession = (sessionId?: string): Nullable<VoiceSession> => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(sessionId ? `session:${sessionId}` : \"sessions\", notify),\n () => client.sessions.get(sessionId),\n () => null,\n );\n};\n\nexport const useIncomingInvites = (): readonly SessionInvite[] => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"invites\", notify),\n () => client.invites.list(),\n () => [],\n );\n};\n\nexport const useIncomingInvite = (): Nullable<SessionInvite> => {\n const invites = useIncomingInvites();\n return invites[0] ?? null;\n};\n\nexport const useCan = (sessionId: string | undefined, action: SessionAction): boolean => {\n const client = useCallpad();\n const session = useSession(sessionId);\n if (!session) {\n return false;\n }\n return client.sessions.can(session, action);\n};\n\nexport const useSessionDuration = (sessionId?: string): SessionDuration => {\n const session = useSession(sessionId);\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n if (!session || session.state === \"ended\") {\n return;\n }\n setNow(Date.now());\n const timer = window.setInterval(() => {\n setNow(Date.now());\n }, 1000);\n return () => {\n window.clearInterval(timer);\n };\n }, [session]);\n\n return durationOf(session, now);\n};\n\nconst durationOf = (session: Nullable<VoiceSession>, now: number): SessionDuration => {\n if (!session) {\n return { seconds: 0, startedAt: null, endedAt: null, running: false };\n }\n const startedAt = session.answeredAt ?? session.createdAt;\n const endedAt = session.endedAt;\n const end = endedAt ? Date.parse(endedAt) : now;\n return {\n seconds: Math.max(0, Math.floor((end - Date.parse(startedAt)) / 1000)),\n startedAt,\n endedAt,\n running: !endedAt && session.state !== \"ended\",\n };\n};\n"]}
1
+ {"version":3,"sources":["../../src/react/index.tsx"],"names":[],"mappings":";;;;AAqBA,IAAM,cAAA,GAAiB,cAAiD,IAAI,CAAA;AAI5E,IAAM,mBAAA,GAA8C,EAAE,OAAA,EAAS,IAAA,EAAM,UAAU,EAAC,EAAG,MAAM,KAAA,EAAM;AASxF,IAAM,kBAAkB,CAAgC;AAAA,EAC7D,MAAA;AAAA,EACA,OAAA,GAAU,KAAA;AAAA,EACV,gBAAA,GAAmB,KAAA;AAAA,EACnB;AACF,CAAA,KAAqC;AACnC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA;AAAA,IACF;AACA,IAAA,KAAK,MAAA,CAAO,OAAA,EAAQ,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAC3C,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,gBAAA,EAAkB;AACpB,QAAA,KAAK,OAAO,OAAA,EAAQ;AACpB,QAAA;AAAA,MACF;AACA,MAAA,KAAK,OAAO,UAAA,EAAW;AAAA,IACzB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,gBAAgB,CAAC,CAAA;AAEtC,EAAA,2BAAQ,cAAA,CAAe,QAAA,EAAf,EAAwB,KAAA,EAAO,QAAS,QAAA,EAAS,CAAA;AAC3D;AAEO,IAAM,aAAa,MAA8D;AACtF,EAAA,MAAM,MAAA,GAAS,WAAW,cAAc,CAAA;AACxC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,MAAM,6BAA6B,CAAA;AAAA,EAC/C;AACA,EAAA,OAAO,MAAA;AACT;AAEO,IAAM,YAAY,MAAoB;AAC3C,EAAA,MAAM,SAAS,UAAA,EAAW;AAC1B,EAAA,OAAO,oBAAA;AAAA,IACL,CAAC,MAAA,KAAW,MAAA,CAAO,SAAA,CAAU,UAAU,MAAM,CAAA;AAAA,IAC7C,MAAM,MAAA,CAAO,MAAA;AAAA,IACb,MAAM;AAAA,GACR;AACF;AAEO,IAAM,cAAc,MAA+B;AACxD,EAAA,MAAM,SAAS,UAAA,EAAW;AAC1B,EAAA,OAAO,oBAAA;AAAA,IACL,CAAC,MAAA,KAAW,MAAA,CAAO,SAAA,CAAU,YAAY,MAAM,CAAA;AAAA,IAC/C,MAAM,MAAA,CAAO,QAAA,CAAS,IAAA,EAAK;AAAA,IAC3B,MAAM;AAAC,GACT;AACF;AAEO,IAAM,UAAA,GAAa,CAAC,SAAA,KAAwD;AACjF,EAAA,MAAM,SAAS,UAAA,EAAW;AAC1B,EAAA,OAAO,oBAAA;AAAA,IACL,CAAC,MAAA,KAAY,SAAA,GAAY,MAAA,CAAO,SAAA,CAAU,WAAW,SAAS,CAAA,CAAA,EAAI,MAAM,CAAA,GAAI,MAAM,MAAA;AAAA,IAClF,MAAO,SAAA,GAAY,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,SAAS,CAAA,GAAI,IAAA;AAAA,IACpD,MAAM;AAAA,GACR;AACF;AAEO,IAAM,oBAAoB,MAA8B;AAC7D,EAAA,MAAM,SAAS,UAAA,EAAW;AAC1B,EAAA,OAAO,oBAAA;AAAA,IACL,OAAO,OAAA,CAAQ,SAAA;AAAA,IACf,OAAO,OAAA,CAAQ,GAAA;AAAA,IACf,MAAM;AAAA,GACR;AACF;AAEO,IAAM,2BAA2B,MAEtB;AAChB,EAAA,MAAM,SAAS,UAAA,EAAW;AAC1B,EAAA,OAAO,MAAA,CAAO,OAAA;AAChB;AAEO,IAAM,qBAAqB,MAAgC;AAChE,EAAA,MAAM,SAAS,UAAA,EAAW;AAC1B,EAAA,OAAO,oBAAA;AAAA,IACL,CAAC,MAAA,KAAW,MAAA,CAAO,SAAA,CAAU,WAAW,MAAM,CAAA;AAAA,IAC9C,MAAM,MAAA,CAAO,OAAA,CAAQ,IAAA,EAAK;AAAA,IAC1B,MAAM;AAAC,GACT;AACF;AAEO,IAAM,oBAAoB,MAA+B;AAC9D,EAAA,MAAM,UAAU,kBAAA,EAAmB;AACnC,EAAA,OAAO,OAAA,CAAQ,CAAC,CAAA,IAAK,IAAA;AACvB;AAEO,IAAM,MAAA,GAAS,CAAC,SAAA,EAA6B,MAAA,KAAmC;AACrF,EAAA,MAAM,SAAS,UAAA,EAAW;AAC1B,EAAA,MAAM,OAAA,GAAU,WAAW,SAAS,CAAA;AACpC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,OAAA,EAAS,MAAM,CAAA;AAC5C;AAEO,IAAM,kBAAA,GAAqB,CAAC,SAAA,KAAiD;AAClF,EAAA,MAAM,OAAA,GAAU,WAAW,SAAS,CAAA;AACpC,EAAA,MAAM,CAAC,KAAK,MAAM,CAAA,GAAI,SAAS,MAAM,IAAA,CAAK,KAAK,CAAA;AAE/C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,IAAW,OAAA,CAAQ,KAAA,KAAU,OAAA,EAAS;AACzC,MAAA;AAAA,IACF;AACA,IAAA,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AACjB,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,WAAA,CAAY,MAAM;AACrC,MAAA,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AAAA,IACnB,GAAG,GAAI,CAAA;AACP,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,cAAc,KAAK,CAAA;AAAA,IAC5B,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,OAAO,UAAA,CAAW,SAAS,GAAG,CAAA;AAChC;AAEA,IAAM,UAAA,GAAa,CAAC,OAAA,EAAiC,GAAA,KAAiC;AACpF,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,EAAE,SAAS,CAAA,EAAG,SAAA,EAAW,MAAM,OAAA,EAAS,IAAA,EAAM,SAAS,KAAA,EAAM;AAAA,EACtE;AACA,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,UAAA,IAAc,OAAA,CAAQ,SAAA;AAChD,EAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AACxB,EAAA,MAAM,GAAA,GAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,GAAI,GAAA;AAC5C,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAA,CAAO,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA,IAAK,GAAI,CAAC,CAAA;AAAA,IACrE,SAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA,EAAS,CAAC,OAAA,IAAW,OAAA,CAAQ,KAAA,KAAU;AAAA,GACzC;AACF,CAAA","file":"index.js","sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\n\nimport type { Nullable } from \"../shared/types\";\nimport type {\n ClientStatus,\n CurrentSessionSnapshot,\n HostClient,\n SessionAction,\n SessionClient,\n SessionDuration,\n SessionInvite,\n VoiceSession,\n} from \"../core/types\";\n\nconst CallpadContext = createContext<SessionClient | HostClient | null>(null);\n\ntype CallpadClient = SessionClient | HostClient;\n\nconst emptyCurrentSession: CurrentSessionSnapshot = { current: null, incoming: [], busy: false };\n\nexport type CallpadProviderProps<TClient extends CallpadClient = CallpadClient> = {\n client: TClient;\n connect?: boolean;\n disposeOnUnmount?: boolean;\n children: ReactNode;\n};\n\nexport const CallpadProvider = <TClient extends CallpadClient>({\n client,\n connect = false,\n disposeOnUnmount = false,\n children,\n}: CallpadProviderProps<TClient>) => {\n useEffect(() => {\n if (!connect) {\n return;\n }\n void client.connect().catch(() => undefined);\n return () => {\n if (disposeOnUnmount) {\n void client.dispose();\n return;\n }\n void client.disconnect();\n };\n }, [client, connect, disposeOnUnmount]);\n\n return <CallpadContext.Provider value={client}>{children}</CallpadContext.Provider>;\n};\n\nexport const useCallpad = <TClient extends CallpadClient = SessionClient>(): TClient => {\n const client = useContext(CallpadContext);\n if (!client) {\n throw new Error(\"CallpadProvider is required\");\n }\n return client as TClient;\n};\n\nexport const useStatus = (): ClientStatus => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"status\", notify),\n () => client.status,\n () => \"idle\",\n );\n};\n\nexport const useSessions = (): readonly VoiceSession[] => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"sessions\", notify),\n () => client.sessions.list(),\n () => [],\n );\n};\n\nexport const useSession = (sessionId: Nullable<string>): Nullable<VoiceSession> => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => (sessionId ? client.subscribe(`session:${sessionId}`, notify) : () => undefined),\n () => (sessionId ? client.sessions.get(sessionId) : null),\n () => null,\n );\n};\n\nexport const useCurrentSession = (): CurrentSessionSnapshot => {\n const client = useCallpad();\n return useSyncExternalStore(\n client.session.subscribe,\n client.session.get,\n () => emptyCurrentSession,\n );\n};\n\nexport const useCurrentSessionActions = <\n TControls extends CallpadClient[\"session\"] = CallpadClient[\"session\"],\n>(): TControls => {\n const client = useCallpad();\n return client.session as TControls;\n};\n\nexport const useIncomingInvites = (): readonly SessionInvite[] => {\n const client = useCallpad();\n return useSyncExternalStore(\n (notify) => client.subscribe(\"invites\", notify),\n () => client.invites.list(),\n () => [],\n );\n};\n\nexport const useIncomingInvite = (): Nullable<SessionInvite> => {\n const invites = useIncomingInvites();\n return invites[0] ?? null;\n};\n\nexport const useCan = (sessionId: Nullable<string>, action: SessionAction): boolean => {\n const client = useCallpad();\n const session = useSession(sessionId);\n if (!session) {\n return false;\n }\n return client.sessions.can(session, action);\n};\n\nexport const useSessionDuration = (sessionId: Nullable<string>): SessionDuration => {\n const session = useSession(sessionId);\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n if (!session || session.state === \"ended\") {\n return;\n }\n setNow(Date.now());\n const timer = window.setInterval(() => {\n setNow(Date.now());\n }, 1000);\n return () => {\n window.clearInterval(timer);\n };\n }, [session]);\n\n return durationOf(session, now);\n};\n\nconst durationOf = (session: Nullable<VoiceSession>, now: number): SessionDuration => {\n if (!session) {\n return { seconds: 0, startedAt: null, endedAt: null, running: false };\n }\n const startedAt = session.answeredAt ?? session.createdAt;\n const endedAt = session.endedAt;\n const end = endedAt ? Date.parse(endedAt) : now;\n return {\n seconds: Math.max(0, Math.floor((end - Date.parse(startedAt)) / 1000)),\n startedAt,\n endedAt,\n running: !endedAt && session.state !== \"ended\",\n };\n};\n"]}
@@ -8,6 +8,10 @@ declare class CallpadError extends Error {
8
8
  constructor(code: string, message: string, status?: number | undefined);
9
9
  }
10
10
 
11
+ /**
12
+ * Canonical E.164 phone number with a leading plus.
13
+ */
14
+ type E164Phone = string;
11
15
  type RealtimeToken = {
12
16
  url: string;
13
17
  token: string;
@@ -31,7 +35,7 @@ type VoiceParticipant = {
31
35
  userId: number | null;
32
36
  agentId: string | null;
33
37
  contactId: string | null;
34
- phone: string | null;
38
+ phone: E164Phone | null;
35
39
  firstName: string | null;
36
40
  lastName: string | null;
37
41
  profilePhoto: string | null;
@@ -106,6 +110,55 @@ type SessionDuration = {
106
110
  endedAt: Nullable<string>;
107
111
  running: boolean;
108
112
  };
113
+ type SessionPhase = "incoming" | "outgoing" | "connecting" | "active" | "ending" | "ended" | "failed";
114
+ type SessionDirection = "inbound" | "outbound";
115
+ type CurrentSession = {
116
+ phase: SessionPhase;
117
+ direction: SessionDirection;
118
+ sessionId: string;
119
+ participantId: Nullable<string>;
120
+ session: Nullable<VoiceSession>;
121
+ join: Nullable<VoiceJoinGrant>;
122
+ startedBy: "start" | "accept" | "join";
123
+ error: Nullable<CallpadError>;
124
+ createdAt: string;
125
+ answeredAt: Nullable<string>;
126
+ endedAt: Nullable<string>;
127
+ };
128
+ type CurrentSessionSnapshot = {
129
+ current: Nullable<CurrentSession>;
130
+ incoming: readonly SessionInvite[];
131
+ busy: boolean;
132
+ };
133
+ type SessionStartBehavior = "rejectWhileBusy" | "focusExisting" | "allowParallel";
134
+ type SessionMediaRequirement = "required" | "optional";
135
+ type SessionStartOptions = {
136
+ behavior?: SessionStartBehavior;
137
+ media?: SessionMediaRequirement;
138
+ };
139
+ type SessionAcceptOptions = {
140
+ replaceCurrent?: boolean;
141
+ media?: SessionMediaRequirement;
142
+ };
143
+ type SessionJoinOptions = {
144
+ replaceCurrent?: boolean;
145
+ };
146
+ type SessionSyncMode = "merge" | "replaceVisible";
147
+ type SessionSyncOptions = {
148
+ mode?: SessionSyncMode;
149
+ };
150
+ type SessionControls<TStartInput> = {
151
+ get: () => CurrentSessionSnapshot;
152
+ start: (input: TStartInput, options?: SessionStartOptions) => Promise<CurrentSession>;
153
+ accept: (input: ParticipantRef, options?: SessionAcceptOptions) => Promise<CurrentSession>;
154
+ join: (sessionId: string, options?: SessionJoinOptions) => Promise<CurrentSession>;
155
+ end: () => Promise<void>;
156
+ clear: () => void;
157
+ mediaConnected: (sessionId?: string) => void;
158
+ mediaDisconnected: (sessionId?: string) => void;
159
+ mediaFailed: (error: Error, sessionId?: string) => void;
160
+ subscribe: (fn: () => void) => Unsubscribe;
161
+ };
109
162
  type ClientEvents = {
110
163
  status: ClientStatus;
111
164
  "session.added": VoiceSession;
@@ -115,6 +168,14 @@ type ClientEvents = {
115
168
  vendor?: string;
116
169
  version?: number;
117
170
  };
171
+ "session.current.changed": CurrentSessionSnapshot;
172
+ "session.current.started": CurrentSession;
173
+ "session.current.connected": CurrentSession;
174
+ "session.current.ended": CurrentSession;
175
+ "session.current.failed": {
176
+ session: Nullable<CurrentSession>;
177
+ error: CallpadError;
178
+ };
118
179
  error: Error;
119
180
  };
120
181
  type SessionClientConfig = {
@@ -166,8 +227,8 @@ type Invites = {
166
227
  };
167
228
  type Sessions = {
168
229
  list: () => readonly VoiceSession[];
169
- get: (sessionId?: string) => Nullable<VoiceSession>;
170
- sync: (query?: ListQuery) => Promise<readonly VoiceSession[]>;
230
+ get: (sessionId: string) => Nullable<VoiceSession>;
231
+ sync: (query?: ListQuery, options?: SessionSyncOptions) => Promise<readonly VoiceSession[]>;
171
232
  start: (input: CustomerStartInput) => Promise<StartedSession>;
172
233
  join: (sessionId: string) => Promise<VoiceJoinGrant>;
173
234
  accept: (input: ParticipantRef) => Promise<StartedSession>;
@@ -190,17 +251,19 @@ type SessionClient = {
190
251
  readonly status: ClientStatus;
191
252
  readonly sessions: Sessions;
192
253
  readonly invites: Invites;
254
+ readonly session: SessionControls<CustomerStartInput>;
193
255
  connect: () => Promise<void>;
194
256
  disconnect: () => Promise<void>;
195
257
  dispose: () => Promise<void>;
196
258
  on: <K extends keyof ClientEvents>(event: K, fn: (payload: ClientEvents[K]) => void) => Unsubscribe;
197
259
  subscribe: (topic: StoreTopic, fn: () => void) => Unsubscribe;
198
260
  };
199
- type HostClient = Omit<SessionClient, "kind" | "sessions"> & {
261
+ type HostClient = Omit<SessionClient, "kind" | "sessions" | "session"> & {
200
262
  readonly kind: "host";
201
263
  readonly vendor: string;
202
264
  readonly sessions: HostSessions;
265
+ readonly session: SessionControls<HostStartInput>;
203
266
  readonly host: HostControls;
204
267
  };
205
268
 
206
- export { CallpadError as C, type HostClient as H, type Invites as I, type ListQuery as L, type Nullable as N, type ParticipantRef as P, type RealtimeToken as R, type SessionAction as S, type Unsubscribe as U, type VoiceJoinGrant as V, type ClientEvents as a, type ClientStatus as b, type CustomerStartInput as c, type HostClientConfig as d, type HostControls as e, type HostParticipantInput as f, type HostSessions as g, type HostStartInput as h, type ListSessionsResponse as i, type SessionClient as j, type SessionClientConfig as k, type SessionDuration as l, type SessionInvite as m, type SessionRecording as n, type SessionRecordingControl as o, type Sessions as p, type StartedSession as q, type StoreTopic as r, type VoiceParticipant as s, type VoiceSession as t };
269
+ export { type SessionSyncOptions as A, type Sessions as B, CallpadError as C, type StartedSession as D, type StoreTopic as E, type VoiceParticipant as F, type VoiceSession as G, type HostClient as H, type Invites as I, type ListQuery as L, type Nullable as N, type ParticipantRef as P, type RealtimeToken as R, type SessionAcceptOptions as S, type Unsubscribe as U, type VoiceJoinGrant as V, type ClientEvents as a, type ClientStatus as b, type CurrentSession as c, type CurrentSessionSnapshot as d, type CustomerStartInput as e, type HostClientConfig as f, type HostControls as g, type HostParticipantInput as h, type HostSessions as i, type HostStartInput as j, type ListSessionsResponse as k, type SessionAction as l, type SessionClient as m, type SessionClientConfig as n, type SessionControls as o, type SessionDirection as p, type SessionDuration as q, type SessionInvite as r, type SessionJoinOptions as s, type SessionMediaRequirement as t, type SessionPhase as u, type SessionRecording as v, type SessionRecordingControl as w, type SessionStartBehavior as x, type SessionStartOptions as y, type SessionSyncMode as z };
@@ -8,6 +8,10 @@ declare class CallpadError extends Error {
8
8
  constructor(code: string, message: string, status?: number | undefined);
9
9
  }
10
10
 
11
+ /**
12
+ * Canonical E.164 phone number with a leading plus.
13
+ */
14
+ type E164Phone = string;
11
15
  type RealtimeToken = {
12
16
  url: string;
13
17
  token: string;
@@ -31,7 +35,7 @@ type VoiceParticipant = {
31
35
  userId: number | null;
32
36
  agentId: string | null;
33
37
  contactId: string | null;
34
- phone: string | null;
38
+ phone: E164Phone | null;
35
39
  firstName: string | null;
36
40
  lastName: string | null;
37
41
  profilePhoto: string | null;
@@ -106,6 +110,55 @@ type SessionDuration = {
106
110
  endedAt: Nullable<string>;
107
111
  running: boolean;
108
112
  };
113
+ type SessionPhase = "incoming" | "outgoing" | "connecting" | "active" | "ending" | "ended" | "failed";
114
+ type SessionDirection = "inbound" | "outbound";
115
+ type CurrentSession = {
116
+ phase: SessionPhase;
117
+ direction: SessionDirection;
118
+ sessionId: string;
119
+ participantId: Nullable<string>;
120
+ session: Nullable<VoiceSession>;
121
+ join: Nullable<VoiceJoinGrant>;
122
+ startedBy: "start" | "accept" | "join";
123
+ error: Nullable<CallpadError>;
124
+ createdAt: string;
125
+ answeredAt: Nullable<string>;
126
+ endedAt: Nullable<string>;
127
+ };
128
+ type CurrentSessionSnapshot = {
129
+ current: Nullable<CurrentSession>;
130
+ incoming: readonly SessionInvite[];
131
+ busy: boolean;
132
+ };
133
+ type SessionStartBehavior = "rejectWhileBusy" | "focusExisting" | "allowParallel";
134
+ type SessionMediaRequirement = "required" | "optional";
135
+ type SessionStartOptions = {
136
+ behavior?: SessionStartBehavior;
137
+ media?: SessionMediaRequirement;
138
+ };
139
+ type SessionAcceptOptions = {
140
+ replaceCurrent?: boolean;
141
+ media?: SessionMediaRequirement;
142
+ };
143
+ type SessionJoinOptions = {
144
+ replaceCurrent?: boolean;
145
+ };
146
+ type SessionSyncMode = "merge" | "replaceVisible";
147
+ type SessionSyncOptions = {
148
+ mode?: SessionSyncMode;
149
+ };
150
+ type SessionControls<TStartInput> = {
151
+ get: () => CurrentSessionSnapshot;
152
+ start: (input: TStartInput, options?: SessionStartOptions) => Promise<CurrentSession>;
153
+ accept: (input: ParticipantRef, options?: SessionAcceptOptions) => Promise<CurrentSession>;
154
+ join: (sessionId: string, options?: SessionJoinOptions) => Promise<CurrentSession>;
155
+ end: () => Promise<void>;
156
+ clear: () => void;
157
+ mediaConnected: (sessionId?: string) => void;
158
+ mediaDisconnected: (sessionId?: string) => void;
159
+ mediaFailed: (error: Error, sessionId?: string) => void;
160
+ subscribe: (fn: () => void) => Unsubscribe;
161
+ };
109
162
  type ClientEvents = {
110
163
  status: ClientStatus;
111
164
  "session.added": VoiceSession;
@@ -115,6 +168,14 @@ type ClientEvents = {
115
168
  vendor?: string;
116
169
  version?: number;
117
170
  };
171
+ "session.current.changed": CurrentSessionSnapshot;
172
+ "session.current.started": CurrentSession;
173
+ "session.current.connected": CurrentSession;
174
+ "session.current.ended": CurrentSession;
175
+ "session.current.failed": {
176
+ session: Nullable<CurrentSession>;
177
+ error: CallpadError;
178
+ };
118
179
  error: Error;
119
180
  };
120
181
  type SessionClientConfig = {
@@ -166,8 +227,8 @@ type Invites = {
166
227
  };
167
228
  type Sessions = {
168
229
  list: () => readonly VoiceSession[];
169
- get: (sessionId?: string) => Nullable<VoiceSession>;
170
- sync: (query?: ListQuery) => Promise<readonly VoiceSession[]>;
230
+ get: (sessionId: string) => Nullable<VoiceSession>;
231
+ sync: (query?: ListQuery, options?: SessionSyncOptions) => Promise<readonly VoiceSession[]>;
171
232
  start: (input: CustomerStartInput) => Promise<StartedSession>;
172
233
  join: (sessionId: string) => Promise<VoiceJoinGrant>;
173
234
  accept: (input: ParticipantRef) => Promise<StartedSession>;
@@ -190,17 +251,19 @@ type SessionClient = {
190
251
  readonly status: ClientStatus;
191
252
  readonly sessions: Sessions;
192
253
  readonly invites: Invites;
254
+ readonly session: SessionControls<CustomerStartInput>;
193
255
  connect: () => Promise<void>;
194
256
  disconnect: () => Promise<void>;
195
257
  dispose: () => Promise<void>;
196
258
  on: <K extends keyof ClientEvents>(event: K, fn: (payload: ClientEvents[K]) => void) => Unsubscribe;
197
259
  subscribe: (topic: StoreTopic, fn: () => void) => Unsubscribe;
198
260
  };
199
- type HostClient = Omit<SessionClient, "kind" | "sessions"> & {
261
+ type HostClient = Omit<SessionClient, "kind" | "sessions" | "session"> & {
200
262
  readonly kind: "host";
201
263
  readonly vendor: string;
202
264
  readonly sessions: HostSessions;
265
+ readonly session: SessionControls<HostStartInput>;
203
266
  readonly host: HostControls;
204
267
  };
205
268
 
206
- export { CallpadError as C, type HostClient as H, type Invites as I, type ListQuery as L, type Nullable as N, type ParticipantRef as P, type RealtimeToken as R, type SessionAction as S, type Unsubscribe as U, type VoiceJoinGrant as V, type ClientEvents as a, type ClientStatus as b, type CustomerStartInput as c, type HostClientConfig as d, type HostControls as e, type HostParticipantInput as f, type HostSessions as g, type HostStartInput as h, type ListSessionsResponse as i, type SessionClient as j, type SessionClientConfig as k, type SessionDuration as l, type SessionInvite as m, type SessionRecording as n, type SessionRecordingControl as o, type Sessions as p, type StartedSession as q, type StoreTopic as r, type VoiceParticipant as s, type VoiceSession as t };
269
+ export { type SessionSyncOptions as A, type Sessions as B, CallpadError as C, type StartedSession as D, type StoreTopic as E, type VoiceParticipant as F, type VoiceSession as G, type HostClient as H, type Invites as I, type ListQuery as L, type Nullable as N, type ParticipantRef as P, type RealtimeToken as R, type SessionAcceptOptions as S, type Unsubscribe as U, type VoiceJoinGrant as V, type ClientEvents as a, type ClientStatus as b, type CurrentSession as c, type CurrentSessionSnapshot as d, type CustomerStartInput as e, type HostClientConfig as f, type HostControls as g, type HostParticipantInput as h, type HostSessions as i, type HostStartInput as j, type ListSessionsResponse as k, type SessionAction as l, type SessionClient as m, type SessionClientConfig as n, type SessionControls as o, type SessionDirection as p, type SessionDuration as q, type SessionInvite as r, type SessionJoinOptions as s, type SessionMediaRequirement as t, type SessionPhase as u, type SessionRecording as v, type SessionRecordingControl as w, type SessionStartBehavior as x, type SessionStartOptions as y, type SessionSyncMode as z };