@dora-cell/sdk-react 0.1.1-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # @dora-cell/sdk-react
2
+
3
+ React hooks and components for the Dora Cell VoIP SDK.
4
+
5
+ ## Features
6
+
7
+ ✅ **React Hooks** - Easy-to-use hooks for call management
8
+ ✅ **Context Provider** - Simple setup with DoraCellProvider
9
+ ✅ **TypeScript support** - Full type definitions included
10
+ ✅ **Auto state management** - Automatic call state and connection tracking
11
+ ✅ **React 18 & 19 compatible** - Works with latest React versions
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @dora-cell/sdk @dora-cell/sdk-react jssip
17
+ # or
18
+ yarn add @dora-cell/sdk @dora-cell/sdk-react jssip
19
+ # or
20
+ pnpm add @dora-cell/sdk @dora-cell/sdk-react jssip
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ### 1. Wrap your app with DoraCellProvider
26
+
27
+ ```tsx
28
+ import { DoraCellProvider } from '@dora-cell/sdk-react';
29
+
30
+ function App() {
31
+ return (
32
+ <DoraCellProvider
33
+ config={{
34
+ auth: {
35
+ type: 'api-token',
36
+ apiToken: 'your-api-token-here',
37
+ apiBaseUrl: 'https://api.usedora.com'
38
+ },
39
+ debug: true
40
+ }}
41
+ >
42
+ <YourApp />
43
+ </DoraCellProvider>
44
+ );
45
+ }
46
+ ```
47
+
48
+ ### 2. Use hooks in your components
49
+
50
+ ```tsx
51
+ import { useCall, useConnectionStatus } from '@dora-cell/sdk-react';
52
+
53
+ function CallInterface() {
54
+ const {
55
+ call,
56
+ hangup,
57
+ toggleMute,
58
+ callStatus,
59
+ callDuration,
60
+ isMuted,
61
+ currentCall
62
+ } = useCall();
63
+
64
+ const { isConnected, status } = useConnectionStatus();
65
+ const [number, setNumber] = useState('');
66
+
67
+ const handleCall = async () => {
68
+ try {
69
+ await call(number);
70
+ } catch (error) {
71
+ console.error('Call failed:', error);
72
+ }
73
+ };
74
+
75
+ return (
76
+ <div>
77
+ <p>Status: {isConnected ? 'Connected' : 'Disconnected'}</p>
78
+
79
+ {callStatus === 'idle' && (
80
+ <>
81
+ <input
82
+ value={number}
83
+ onChange={(e) => setNumber(e.target.value)}
84
+ placeholder="Enter phone number"
85
+ />
86
+ <button onClick={handleCall} disabled={!isConnected}>
87
+ Call
88
+ </button>
89
+ </>
90
+ )}
91
+
92
+ {callStatus === 'ongoing' && (
93
+ <>
94
+ <p>Call with: {currentCall?.remoteNumber}</p>
95
+ <p>Duration: {callDuration}</p>
96
+ <button onClick={toggleMute}>
97
+ {isMuted ? 'Unmute' : 'Mute'}
98
+ </button>
99
+ <button onClick={hangup}>Hang Up</button>
100
+ </>
101
+ )}
102
+
103
+ {callStatus === 'ringing' && (
104
+ <p>Ringing...</p>
105
+ )}
106
+ </div>
107
+ );
108
+ }
109
+ ```
110
+
111
+ ## API Reference
112
+
113
+ ### DoraCellProvider
114
+
115
+ Wrap your app with this provider to enable SDK functionality.
116
+
117
+ ```tsx
118
+ <DoraCellProvider
119
+ config={{
120
+ auth: {
121
+ type: 'api-token',
122
+ apiToken: string,
123
+ apiBaseUrl?: string
124
+ },
125
+ turnServers?: RTCIceServer[],
126
+ debug?: boolean,
127
+ autoSelectExtension?: boolean
128
+ }}
129
+ >
130
+ {children}
131
+ </DoraCellProvider>
132
+ ```
133
+
134
+ ### useCall()
135
+
136
+ Hook for managing calls.
137
+
138
+ ```typescript
139
+ const {
140
+ // Methods
141
+ call: (phoneNumber: string) => Promise<void>,
142
+ hangup: () => void,
143
+ answerCall: () => void,
144
+ toggleMute: () => void,
145
+
146
+ // State
147
+ callStatus: 'idle' | 'ringing' | 'ongoing',
148
+ callDuration: string, // Formatted as "MM:SS"
149
+ isMuted: boolean,
150
+ currentCall: Call | null,
151
+ error: Error | null
152
+ } = useCall();
153
+ ```
154
+
155
+ **Methods:**
156
+ - `call(phoneNumber)` - Make an outbound call
157
+ - `hangup()` - End the current call
158
+ - `answerCall()` - Answer an incoming call
159
+ - `toggleMute()` - Toggle mute/unmute
160
+
161
+ **State:**
162
+ - `callStatus` - Current call status
163
+ - `callDuration` - Formatted call duration (e.g., "01:23")
164
+ - `isMuted` - Whether the call is muted
165
+ - `currentCall` - Current call object with details
166
+ - `error` - Any call-related errors
167
+
168
+ ### useConnectionStatus()
169
+
170
+ Hook for monitoring connection status.
171
+
172
+ ```typescript
173
+ const {
174
+ isConnected: boolean,
175
+ status: 'disconnected' | 'connecting' | 'connected' | 'error',
176
+ error: Error | null
177
+ } = useConnectionStatus();
178
+ ```
179
+
180
+ ### useDoraCell()
181
+
182
+ Access the underlying SDK instance directly.
183
+
184
+ ```typescript
185
+ const sdk = useDoraCell();
186
+
187
+ // Use SDK methods directly
188
+ sdk.getExtensions();
189
+ sdk.on('call:incoming', (call) => {
190
+ console.log('Incoming call from:', call.remoteNumber);
191
+ });
192
+ ```
193
+
194
+ ## Advanced Usage
195
+
196
+ ### Handling Incoming Calls
197
+
198
+ ```tsx
199
+ function IncomingCallHandler() {
200
+ const { currentCall, answerCall, hangup, callStatus } = useCall();
201
+ const sdk = useDoraCell();
202
+
203
+ useEffect(() => {
204
+ const handleIncoming = (call) => {
205
+ // Show notification or UI for incoming call
206
+ console.log('Incoming call from:', call.remoteNumber);
207
+ };
208
+
209
+ sdk.on('call:incoming', handleIncoming);
210
+ return () => sdk.off('call:incoming', handleIncoming);
211
+ }, [sdk]);
212
+
213
+ if (callStatus === 'ringing' && currentCall?.direction === 'inbound') {
214
+ return (
215
+ <div>
216
+ <p>Incoming call from {currentCall.remoteNumber}</p>
217
+ <button onClick={answerCall}>Answer</button>
218
+ <button onClick={hangup}>Decline</button>
219
+ </div>
220
+ );
221
+ }
222
+
223
+ return null;
224
+ }
225
+ ```
226
+
227
+ ### Custom Extension Selection
228
+
229
+ ```tsx
230
+ function CallWithExtension() {
231
+ const sdk = useDoraCell();
232
+ const [selectedExtension, setSelectedExtension] = useState('');
233
+
234
+ const extensions = sdk.getExtensions();
235
+
236
+ const makeCall = async (number: string) => {
237
+ await sdk.call(number, { extension: selectedExtension });
238
+ };
239
+
240
+ return (
241
+ <div>
242
+ <select
243
+ value={selectedExtension}
244
+ onChange={(e) => setSelectedExtension(e.target.value)}
245
+ >
246
+ {extensions.map(ext => (
247
+ <option key={ext} value={ext}>{ext}</option>
248
+ ))}
249
+ </select>
250
+ {/* Rest of your call UI */}
251
+ </div>
252
+ );
253
+ }
254
+ ```
255
+
256
+ ### Error Handling
257
+
258
+ ```tsx
259
+ function CallWithErrorHandling() {
260
+ const { call, error, callStatus } = useCall();
261
+ const [number, setNumber] = useState('');
262
+
263
+ const handleCall = async () => {
264
+ try {
265
+ await call(number);
266
+ } catch (err) {
267
+ console.error('Call failed:', err);
268
+ // Show error to user
269
+ }
270
+ };
271
+
272
+ return (
273
+ <div>
274
+ {error && <div className="error">{error.message}</div>}
275
+ {/* Rest of your UI */}
276
+ </div>
277
+ );
278
+ }
279
+ ```
280
+
281
+ ## TypeScript Support
282
+
283
+ All hooks and components are fully typed. Import types as needed:
284
+
285
+ ```typescript
286
+ import type { Call, CallStatus, ConnectionStatus } from '@dora-cell/sdk';
287
+ import type { DoraCellConfig } from '@dora-cell/sdk-react';
288
+ ```
289
+
290
+ ## Examples
291
+
292
+ See the `/examples` directory in the main repository for complete working examples:
293
+ - `react-app/` - React application with hooks
294
+ - `nextjs-app/` - Next.js application
295
+
296
+ ## Requirements
297
+
298
+ - React 18.0.0 or higher (including React 19)
299
+ - @dora-cell/sdk (peer dependency)
300
+ - jssip (peer dependency)
301
+
302
+ ## License
303
+
304
+ MIT
305
+
306
+ ## Related Packages
307
+
308
+ - [@dora-cell/sdk](https://www.npmjs.com/package/@dora-cell/sdk) - Core VoIP SDK
@@ -0,0 +1,51 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { DoraCellConfig, CallStatus, Call, ConnectionStatus, DoraCell } from '@dora-cell/sdk';
4
+
5
+ interface DoraCellContextValue {
6
+ sdk: DoraCell | null;
7
+ connectionStatus: ConnectionStatus;
8
+ currentCall: Call | null;
9
+ callStatus: CallStatus;
10
+ callDuration: string;
11
+ isMuted: boolean;
12
+ isInitialized: boolean;
13
+ error: Error | null;
14
+ call: (phoneNumber: string, extension?: string) => Promise<void>;
15
+ hangup: () => void;
16
+ toggleMute: () => void;
17
+ answerCall: () => void;
18
+ }
19
+ interface DoraCellProviderProps {
20
+ config: DoraCellConfig;
21
+ children: React.ReactNode;
22
+ autoInitialize?: boolean;
23
+ }
24
+ declare function DoraCellProvider({ config, children, autoInitialize, }: DoraCellProviderProps): react_jsx_runtime.JSX.Element;
25
+ /**
26
+ * Hook to access Dora Cell SDK context
27
+ */
28
+ declare function useDoraCell(): DoraCellContextValue;
29
+ /**
30
+ * Hook for making calls
31
+ */
32
+ declare function useCall(): {
33
+ call: (phoneNumber: string, extension?: string) => Promise<void>;
34
+ hangup: () => void;
35
+ toggleMute: () => void;
36
+ callStatus: CallStatus;
37
+ callDuration: string;
38
+ isMuted: boolean;
39
+ currentCall: Call | null;
40
+ };
41
+ /**
42
+ * Hook for connection status
43
+ */
44
+ declare function useConnectionStatus(): {
45
+ connectionStatus: ConnectionStatus;
46
+ isInitialized: boolean;
47
+ isConnected: boolean;
48
+ error: Error | null;
49
+ };
50
+
51
+ export { DoraCellProvider, type DoraCellProviderProps, useCall, useConnectionStatus, useDoraCell };
@@ -0,0 +1,51 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { DoraCellConfig, CallStatus, Call, ConnectionStatus, DoraCell } from '@dora-cell/sdk';
4
+
5
+ interface DoraCellContextValue {
6
+ sdk: DoraCell | null;
7
+ connectionStatus: ConnectionStatus;
8
+ currentCall: Call | null;
9
+ callStatus: CallStatus;
10
+ callDuration: string;
11
+ isMuted: boolean;
12
+ isInitialized: boolean;
13
+ error: Error | null;
14
+ call: (phoneNumber: string, extension?: string) => Promise<void>;
15
+ hangup: () => void;
16
+ toggleMute: () => void;
17
+ answerCall: () => void;
18
+ }
19
+ interface DoraCellProviderProps {
20
+ config: DoraCellConfig;
21
+ children: React.ReactNode;
22
+ autoInitialize?: boolean;
23
+ }
24
+ declare function DoraCellProvider({ config, children, autoInitialize, }: DoraCellProviderProps): react_jsx_runtime.JSX.Element;
25
+ /**
26
+ * Hook to access Dora Cell SDK context
27
+ */
28
+ declare function useDoraCell(): DoraCellContextValue;
29
+ /**
30
+ * Hook for making calls
31
+ */
32
+ declare function useCall(): {
33
+ call: (phoneNumber: string, extension?: string) => Promise<void>;
34
+ hangup: () => void;
35
+ toggleMute: () => void;
36
+ callStatus: CallStatus;
37
+ callDuration: string;
38
+ isMuted: boolean;
39
+ currentCall: Call | null;
40
+ };
41
+ /**
42
+ * Hook for connection status
43
+ */
44
+ declare function useConnectionStatus(): {
45
+ connectionStatus: ConnectionStatus;
46
+ isInitialized: boolean;
47
+ isConnected: boolean;
48
+ error: Error | null;
49
+ };
50
+
51
+ export { DoraCellProvider, type DoraCellProviderProps, useCall, useConnectionStatus, useDoraCell };
package/dist/index.js ADDED
@@ -0,0 +1,198 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var sdk = require('@dora-cell/sdk');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ var DoraCellContext = react.createContext(void 0);
8
+ function DoraCellProvider({
9
+ config,
10
+ children,
11
+ autoInitialize = true
12
+ }) {
13
+ const [sdk$1] = react.useState(() => new sdk.DoraCell(config));
14
+ const [isInitialized, setIsInitialized] = react.useState(false);
15
+ const [connectionStatus, setConnectionStatus] = react.useState("disconnected");
16
+ const [currentCall, setCurrentCall] = react.useState(null);
17
+ const [callStatus, setCallStatus] = react.useState("idle");
18
+ const [callDuration, setCallDuration] = react.useState("00:00");
19
+ const [isMuted, setIsMuted] = react.useState(false);
20
+ const [error, setError] = react.useState(null);
21
+ const durationIntervalRef = react.useRef(null);
22
+ react.useEffect(() => {
23
+ if (!autoInitialize) return;
24
+ const initializeSdk = async () => {
25
+ try {
26
+ await sdk$1.initialize();
27
+ setIsInitialized(true);
28
+ } catch (err) {
29
+ setError(err instanceof Error ? err : new Error("Failed to initialize SDK"));
30
+ }
31
+ };
32
+ initializeSdk();
33
+ return () => {
34
+ sdk$1.destroy();
35
+ };
36
+ }, [sdk$1, autoInitialize]);
37
+ react.useEffect(() => {
38
+ if (!sdk$1) return;
39
+ const handleConnectionStatus = (state) => {
40
+ setConnectionStatus(state.status);
41
+ if (state.error) {
42
+ setError(new Error(state.error));
43
+ }
44
+ };
45
+ const handleIncomingCall = (call2) => {
46
+ setCurrentCall(call2);
47
+ setCallStatus("ringing");
48
+ };
49
+ const handleOutgoingCall = (call2) => {
50
+ setCurrentCall(call2);
51
+ setCallStatus("connecting");
52
+ };
53
+ const handleCallRinging = (call2) => {
54
+ setCallStatus("ringing");
55
+ };
56
+ const handleCallConnected = (call2) => {
57
+ setCallStatus("ongoing");
58
+ };
59
+ const handleCallEnded = (call2) => {
60
+ setCallStatus("ended");
61
+ setCurrentCall(null);
62
+ setIsMuted(false);
63
+ setTimeout(() => {
64
+ setCallStatus("idle");
65
+ }, 3e3);
66
+ };
67
+ const handleCallFailed = (call2, errorMsg) => {
68
+ setError(new Error(errorMsg));
69
+ setCallStatus("ended");
70
+ setCurrentCall(null);
71
+ };
72
+ const handleError = (err) => {
73
+ setError(err);
74
+ };
75
+ sdk$1.on("connection:status", handleConnectionStatus);
76
+ sdk$1.on("call:incoming", handleIncomingCall);
77
+ sdk$1.on("call:outgoing", handleOutgoingCall);
78
+ sdk$1.on("call:ringing", handleCallRinging);
79
+ sdk$1.on("call:connected", handleCallConnected);
80
+ sdk$1.on("call:ended", handleCallEnded);
81
+ sdk$1.on("call:failed", handleCallFailed);
82
+ sdk$1.on("error", handleError);
83
+ return () => {
84
+ sdk$1.off("connection:status", handleConnectionStatus);
85
+ sdk$1.off("call:incoming", handleIncomingCall);
86
+ sdk$1.off("call:outgoing", handleOutgoingCall);
87
+ sdk$1.off("call:ringing", handleCallRinging);
88
+ sdk$1.off("call:connected", handleCallConnected);
89
+ sdk$1.off("call:ended", handleCallEnded);
90
+ sdk$1.off("call:failed", handleCallFailed);
91
+ sdk$1.off("error", handleError);
92
+ };
93
+ }, [sdk$1]);
94
+ react.useEffect(() => {
95
+ if (callStatus === "ongoing" && currentCall) {
96
+ durationIntervalRef.current = window.setInterval(() => {
97
+ const duration = currentCall.duration;
98
+ const mm = String(Math.floor(duration / 60)).padStart(2, "0");
99
+ const ss = String(duration % 60).padStart(2, "0");
100
+ setCallDuration(`${mm}:${ss}`);
101
+ }, 1e3);
102
+ } else {
103
+ setCallDuration("00:00");
104
+ if (durationIntervalRef.current) {
105
+ clearInterval(durationIntervalRef.current);
106
+ durationIntervalRef.current = null;
107
+ }
108
+ }
109
+ return () => {
110
+ if (durationIntervalRef.current) {
111
+ clearInterval(durationIntervalRef.current);
112
+ }
113
+ };
114
+ }, [callStatus, currentCall]);
115
+ const call = async (phoneNumber, extension) => {
116
+ try {
117
+ setError(null);
118
+ await sdk$1.call(phoneNumber, { extension });
119
+ } catch (err) {
120
+ setError(err instanceof Error ? err : new Error("Failed to make call"));
121
+ throw err;
122
+ }
123
+ };
124
+ const hangup = () => {
125
+ try {
126
+ sdk$1.hangup();
127
+ } catch (err) {
128
+ setError(err instanceof Error ? err : new Error("Failed to hang up"));
129
+ }
130
+ };
131
+ const toggleMute = () => {
132
+ if (!currentCall) return;
133
+ if (isMuted) {
134
+ currentCall.unmute();
135
+ setIsMuted(false);
136
+ } else {
137
+ currentCall.mute();
138
+ setIsMuted(true);
139
+ }
140
+ };
141
+ const answerCall = () => {
142
+ try {
143
+ sdk$1.answerCall();
144
+ } catch (err) {
145
+ setError(err instanceof Error ? err : new Error("Failed to answer call"));
146
+ }
147
+ };
148
+ const contextValue = {
149
+ sdk: sdk$1,
150
+ connectionStatus,
151
+ currentCall,
152
+ callStatus,
153
+ callDuration,
154
+ isMuted,
155
+ isInitialized,
156
+ error,
157
+ call,
158
+ hangup,
159
+ toggleMute,
160
+ answerCall
161
+ };
162
+ return /* @__PURE__ */ jsxRuntime.jsx(DoraCellContext.Provider, { value: contextValue, children });
163
+ }
164
+ function useDoraCell() {
165
+ const context = react.useContext(DoraCellContext);
166
+ if (!context) {
167
+ throw new Error("useDoraCell must be used within DoraCellProvider");
168
+ }
169
+ return context;
170
+ }
171
+ function useCall() {
172
+ const { call, hangup, toggleMute, callStatus, callDuration, isMuted, currentCall } = useDoraCell();
173
+ return {
174
+ call,
175
+ hangup,
176
+ toggleMute,
177
+ callStatus,
178
+ callDuration,
179
+ isMuted,
180
+ currentCall
181
+ };
182
+ }
183
+ function useConnectionStatus() {
184
+ const { connectionStatus, isInitialized, error } = useDoraCell();
185
+ return {
186
+ connectionStatus,
187
+ isInitialized,
188
+ isConnected: connectionStatus === "registered",
189
+ error
190
+ };
191
+ }
192
+
193
+ exports.DoraCellProvider = DoraCellProvider;
194
+ exports.useCall = useCall;
195
+ exports.useConnectionStatus = useConnectionStatus;
196
+ exports.useDoraCell = useDoraCell;
197
+ //# sourceMappingURL=index.js.map
198
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.tsx"],"names":["createContext","sdk","useState","DoraCell","useRef","useEffect","call","useContext"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * React bindings for Dora Cell SDK\n * Provides React Context and hooks for easy integration\n */\n\n'use client';\n\nimport React, { createContext, useContext, useEffect, useState, useRef } from 'react';\nimport { DoraCell } from '@dora-cell/sdk';\nimport type {\n DoraCellConfig,\n Call,\n CallStatus,\n ConnectionStatus,\n ConnectionState,\n} from '@dora-cell/sdk';\n\ninterface DoraCellContextValue {\n sdk: DoraCell | null;\n connectionStatus: ConnectionStatus;\n currentCall: Call | null;\n callStatus: CallStatus;\n callDuration: string;\n isMuted: boolean;\n isInitialized: boolean;\n error: Error | null;\n\n // Methods\n call: (phoneNumber: string, extension?: string) => Promise<void>;\n hangup: () => void;\n toggleMute: () => void;\n answerCall: () => void;\n}\n\nconst DoraCellContext = createContext<DoraCellContextValue | undefined>(undefined);\n\nexport interface DoraCellProviderProps {\n config: DoraCellConfig;\n children: React.ReactNode;\n autoInitialize?: boolean;\n}\n\nexport function DoraCellProvider({\n config,\n children,\n autoInitialize = true,\n}: DoraCellProviderProps) {\n const [sdk] = useState(() => new DoraCell(config));\n const [isInitialized, setIsInitialized] = useState(false);\n const [connectionStatus, setConnectionStatus] = useState<ConnectionStatus>('disconnected');\n const [currentCall, setCurrentCall] = useState<Call | null>(null);\n const [callStatus, setCallStatus] = useState<CallStatus>('idle');\n const [callDuration, setCallDuration] = useState('00:00');\n const [isMuted, setIsMuted] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const durationIntervalRef = useRef<number | null>(null);\n\n // Initialize SDK\n useEffect(() => {\n if (!autoInitialize) return;\n\n const initializeSdk = async () => {\n try {\n await sdk.initialize();\n setIsInitialized(true);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to initialize SDK'));\n }\n };\n\n initializeSdk();\n\n return () => {\n sdk.destroy();\n };\n }, [sdk, autoInitialize]);\n\n // Set up event listeners\n useEffect(() => {\n if (!sdk) return;\n\n const handleConnectionStatus = (state: ConnectionState) => {\n setConnectionStatus(state.status);\n if (state.error) {\n setError(new Error(state.error));\n }\n };\n\n const handleIncomingCall = (call: Call) => {\n setCurrentCall(call);\n setCallStatus('ringing');\n };\n\n const handleOutgoingCall = (call: Call) => {\n setCurrentCall(call);\n setCallStatus('connecting');\n };\n\n const handleCallRinging = (call: Call) => {\n setCallStatus('ringing');\n };\n\n const handleCallConnected = (call: Call) => {\n setCallStatus('ongoing');\n };\n\n const handleCallEnded = (call: Call) => {\n setCallStatus('ended');\n setCurrentCall(null);\n setIsMuted(false);\n\n // Reset to idle after a delay\n setTimeout(() => {\n setCallStatus('idle');\n }, 3000);\n };\n\n const handleCallFailed = (call: Call, errorMsg: string) => {\n setError(new Error(errorMsg));\n setCallStatus('ended');\n setCurrentCall(null);\n };\n\n const handleError = (err: Error) => {\n setError(err);\n };\n\n sdk.on('connection:status', handleConnectionStatus);\n sdk.on('call:incoming', handleIncomingCall);\n sdk.on('call:outgoing', handleOutgoingCall);\n sdk.on('call:ringing', handleCallRinging);\n sdk.on('call:connected', handleCallConnected);\n sdk.on('call:ended', handleCallEnded);\n sdk.on('call:failed', handleCallFailed);\n sdk.on('error', handleError);\n\n return () => {\n sdk.off('connection:status', handleConnectionStatus);\n sdk.off('call:incoming', handleIncomingCall);\n sdk.off('call:outgoing', handleOutgoingCall);\n sdk.off('call:ringing', handleCallRinging);\n sdk.off('call:connected', handleCallConnected);\n sdk.off('call:ended', handleCallEnded);\n sdk.off('call:failed', handleCallFailed);\n sdk.off('error', handleError);\n };\n }, [sdk]);\n\n // Update call duration\n useEffect(() => {\n if (callStatus === 'ongoing' && currentCall) {\n durationIntervalRef.current = window.setInterval(() => {\n const duration = currentCall.duration;\n const mm = String(Math.floor(duration / 60)).padStart(2, '0');\n const ss = String(duration % 60).padStart(2, '0');\n setCallDuration(`${mm}:${ss}`);\n }, 1000);\n } else {\n setCallDuration('00:00');\n if (durationIntervalRef.current) {\n clearInterval(durationIntervalRef.current);\n durationIntervalRef.current = null;\n }\n }\n\n return () => {\n if (durationIntervalRef.current) {\n clearInterval(durationIntervalRef.current);\n }\n };\n }, [callStatus, currentCall]);\n\n // Methods\n const call = async (phoneNumber: string, extension?: string) => {\n try {\n setError(null);\n await sdk.call(phoneNumber, { extension });\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to make call'));\n throw err;\n }\n };\n\n const hangup = () => {\n try {\n sdk.hangup();\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to hang up'));\n }\n };\n\n const toggleMute = () => {\n if (!currentCall) return;\n\n if (isMuted) {\n currentCall.unmute();\n setIsMuted(false);\n } else {\n currentCall.mute();\n setIsMuted(true);\n }\n };\n\n const answerCall = () => {\n try {\n sdk.answerCall();\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to answer call'));\n }\n };\n\n const contextValue: DoraCellContextValue = {\n sdk,\n connectionStatus,\n currentCall,\n callStatus,\n callDuration,\n isMuted,\n isInitialized,\n error,\n call,\n hangup,\n toggleMute,\n answerCall,\n };\n\n return (\n <DoraCellContext.Provider value={contextValue}>\n {children}\n </DoraCellContext.Provider>\n );\n}\n\n/**\n * Hook to access Dora Cell SDK context\n */\nexport function useDoraCell(): DoraCellContextValue {\n const context = useContext(DoraCellContext);\n if (!context) {\n throw new Error('useDoraCell must be used within DoraCellProvider');\n }\n return context;\n}\n\n/**\n * Hook for making calls\n */\nexport function useCall() {\n const { call, hangup, toggleMute, callStatus, callDuration, isMuted, currentCall } = useDoraCell();\n\n return {\n call,\n hangup,\n toggleMute,\n callStatus,\n callDuration,\n isMuted,\n currentCall,\n };\n}\n\n/**\n * Hook for connection status\n */\nexport function useConnectionStatus() {\n const { connectionStatus, isInitialized, error } = useDoraCell();\n\n return {\n connectionStatus,\n isInitialized,\n isConnected: connectionStatus === 'registered',\n error,\n };\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,193 @@
1
+ import { createContext, useState, useRef, useEffect, useContext } from 'react';
2
+ import { DoraCell } from '@dora-cell/sdk';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ var DoraCellContext = createContext(void 0);
6
+ function DoraCellProvider({
7
+ config,
8
+ children,
9
+ autoInitialize = true
10
+ }) {
11
+ const [sdk] = useState(() => new DoraCell(config));
12
+ const [isInitialized, setIsInitialized] = useState(false);
13
+ const [connectionStatus, setConnectionStatus] = useState("disconnected");
14
+ const [currentCall, setCurrentCall] = useState(null);
15
+ const [callStatus, setCallStatus] = useState("idle");
16
+ const [callDuration, setCallDuration] = useState("00:00");
17
+ const [isMuted, setIsMuted] = useState(false);
18
+ const [error, setError] = useState(null);
19
+ const durationIntervalRef = useRef(null);
20
+ useEffect(() => {
21
+ if (!autoInitialize) return;
22
+ const initializeSdk = async () => {
23
+ try {
24
+ await sdk.initialize();
25
+ setIsInitialized(true);
26
+ } catch (err) {
27
+ setError(err instanceof Error ? err : new Error("Failed to initialize SDK"));
28
+ }
29
+ };
30
+ initializeSdk();
31
+ return () => {
32
+ sdk.destroy();
33
+ };
34
+ }, [sdk, autoInitialize]);
35
+ useEffect(() => {
36
+ if (!sdk) return;
37
+ const handleConnectionStatus = (state) => {
38
+ setConnectionStatus(state.status);
39
+ if (state.error) {
40
+ setError(new Error(state.error));
41
+ }
42
+ };
43
+ const handleIncomingCall = (call2) => {
44
+ setCurrentCall(call2);
45
+ setCallStatus("ringing");
46
+ };
47
+ const handleOutgoingCall = (call2) => {
48
+ setCurrentCall(call2);
49
+ setCallStatus("connecting");
50
+ };
51
+ const handleCallRinging = (call2) => {
52
+ setCallStatus("ringing");
53
+ };
54
+ const handleCallConnected = (call2) => {
55
+ setCallStatus("ongoing");
56
+ };
57
+ const handleCallEnded = (call2) => {
58
+ setCallStatus("ended");
59
+ setCurrentCall(null);
60
+ setIsMuted(false);
61
+ setTimeout(() => {
62
+ setCallStatus("idle");
63
+ }, 3e3);
64
+ };
65
+ const handleCallFailed = (call2, errorMsg) => {
66
+ setError(new Error(errorMsg));
67
+ setCallStatus("ended");
68
+ setCurrentCall(null);
69
+ };
70
+ const handleError = (err) => {
71
+ setError(err);
72
+ };
73
+ sdk.on("connection:status", handleConnectionStatus);
74
+ sdk.on("call:incoming", handleIncomingCall);
75
+ sdk.on("call:outgoing", handleOutgoingCall);
76
+ sdk.on("call:ringing", handleCallRinging);
77
+ sdk.on("call:connected", handleCallConnected);
78
+ sdk.on("call:ended", handleCallEnded);
79
+ sdk.on("call:failed", handleCallFailed);
80
+ sdk.on("error", handleError);
81
+ return () => {
82
+ sdk.off("connection:status", handleConnectionStatus);
83
+ sdk.off("call:incoming", handleIncomingCall);
84
+ sdk.off("call:outgoing", handleOutgoingCall);
85
+ sdk.off("call:ringing", handleCallRinging);
86
+ sdk.off("call:connected", handleCallConnected);
87
+ sdk.off("call:ended", handleCallEnded);
88
+ sdk.off("call:failed", handleCallFailed);
89
+ sdk.off("error", handleError);
90
+ };
91
+ }, [sdk]);
92
+ useEffect(() => {
93
+ if (callStatus === "ongoing" && currentCall) {
94
+ durationIntervalRef.current = window.setInterval(() => {
95
+ const duration = currentCall.duration;
96
+ const mm = String(Math.floor(duration / 60)).padStart(2, "0");
97
+ const ss = String(duration % 60).padStart(2, "0");
98
+ setCallDuration(`${mm}:${ss}`);
99
+ }, 1e3);
100
+ } else {
101
+ setCallDuration("00:00");
102
+ if (durationIntervalRef.current) {
103
+ clearInterval(durationIntervalRef.current);
104
+ durationIntervalRef.current = null;
105
+ }
106
+ }
107
+ return () => {
108
+ if (durationIntervalRef.current) {
109
+ clearInterval(durationIntervalRef.current);
110
+ }
111
+ };
112
+ }, [callStatus, currentCall]);
113
+ const call = async (phoneNumber, extension) => {
114
+ try {
115
+ setError(null);
116
+ await sdk.call(phoneNumber, { extension });
117
+ } catch (err) {
118
+ setError(err instanceof Error ? err : new Error("Failed to make call"));
119
+ throw err;
120
+ }
121
+ };
122
+ const hangup = () => {
123
+ try {
124
+ sdk.hangup();
125
+ } catch (err) {
126
+ setError(err instanceof Error ? err : new Error("Failed to hang up"));
127
+ }
128
+ };
129
+ const toggleMute = () => {
130
+ if (!currentCall) return;
131
+ if (isMuted) {
132
+ currentCall.unmute();
133
+ setIsMuted(false);
134
+ } else {
135
+ currentCall.mute();
136
+ setIsMuted(true);
137
+ }
138
+ };
139
+ const answerCall = () => {
140
+ try {
141
+ sdk.answerCall();
142
+ } catch (err) {
143
+ setError(err instanceof Error ? err : new Error("Failed to answer call"));
144
+ }
145
+ };
146
+ const contextValue = {
147
+ sdk,
148
+ connectionStatus,
149
+ currentCall,
150
+ callStatus,
151
+ callDuration,
152
+ isMuted,
153
+ isInitialized,
154
+ error,
155
+ call,
156
+ hangup,
157
+ toggleMute,
158
+ answerCall
159
+ };
160
+ return /* @__PURE__ */ jsx(DoraCellContext.Provider, { value: contextValue, children });
161
+ }
162
+ function useDoraCell() {
163
+ const context = useContext(DoraCellContext);
164
+ if (!context) {
165
+ throw new Error("useDoraCell must be used within DoraCellProvider");
166
+ }
167
+ return context;
168
+ }
169
+ function useCall() {
170
+ const { call, hangup, toggleMute, callStatus, callDuration, isMuted, currentCall } = useDoraCell();
171
+ return {
172
+ call,
173
+ hangup,
174
+ toggleMute,
175
+ callStatus,
176
+ callDuration,
177
+ isMuted,
178
+ currentCall
179
+ };
180
+ }
181
+ function useConnectionStatus() {
182
+ const { connectionStatus, isInitialized, error } = useDoraCell();
183
+ return {
184
+ connectionStatus,
185
+ isInitialized,
186
+ isConnected: connectionStatus === "registered",
187
+ error
188
+ };
189
+ }
190
+
191
+ export { DoraCellProvider, useCall, useConnectionStatus, useDoraCell };
192
+ //# sourceMappingURL=index.mjs.map
193
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.tsx"],"names":["call"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * React bindings for Dora Cell SDK\n * Provides React Context and hooks for easy integration\n */\n\n'use client';\n\nimport React, { createContext, useContext, useEffect, useState, useRef } from 'react';\nimport { DoraCell } from '@dora-cell/sdk';\nimport type {\n DoraCellConfig,\n Call,\n CallStatus,\n ConnectionStatus,\n ConnectionState,\n} from '@dora-cell/sdk';\n\ninterface DoraCellContextValue {\n sdk: DoraCell | null;\n connectionStatus: ConnectionStatus;\n currentCall: Call | null;\n callStatus: CallStatus;\n callDuration: string;\n isMuted: boolean;\n isInitialized: boolean;\n error: Error | null;\n\n // Methods\n call: (phoneNumber: string, extension?: string) => Promise<void>;\n hangup: () => void;\n toggleMute: () => void;\n answerCall: () => void;\n}\n\nconst DoraCellContext = createContext<DoraCellContextValue | undefined>(undefined);\n\nexport interface DoraCellProviderProps {\n config: DoraCellConfig;\n children: React.ReactNode;\n autoInitialize?: boolean;\n}\n\nexport function DoraCellProvider({\n config,\n children,\n autoInitialize = true,\n}: DoraCellProviderProps) {\n const [sdk] = useState(() => new DoraCell(config));\n const [isInitialized, setIsInitialized] = useState(false);\n const [connectionStatus, setConnectionStatus] = useState<ConnectionStatus>('disconnected');\n const [currentCall, setCurrentCall] = useState<Call | null>(null);\n const [callStatus, setCallStatus] = useState<CallStatus>('idle');\n const [callDuration, setCallDuration] = useState('00:00');\n const [isMuted, setIsMuted] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const durationIntervalRef = useRef<number | null>(null);\n\n // Initialize SDK\n useEffect(() => {\n if (!autoInitialize) return;\n\n const initializeSdk = async () => {\n try {\n await sdk.initialize();\n setIsInitialized(true);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to initialize SDK'));\n }\n };\n\n initializeSdk();\n\n return () => {\n sdk.destroy();\n };\n }, [sdk, autoInitialize]);\n\n // Set up event listeners\n useEffect(() => {\n if (!sdk) return;\n\n const handleConnectionStatus = (state: ConnectionState) => {\n setConnectionStatus(state.status);\n if (state.error) {\n setError(new Error(state.error));\n }\n };\n\n const handleIncomingCall = (call: Call) => {\n setCurrentCall(call);\n setCallStatus('ringing');\n };\n\n const handleOutgoingCall = (call: Call) => {\n setCurrentCall(call);\n setCallStatus('connecting');\n };\n\n const handleCallRinging = (call: Call) => {\n setCallStatus('ringing');\n };\n\n const handleCallConnected = (call: Call) => {\n setCallStatus('ongoing');\n };\n\n const handleCallEnded = (call: Call) => {\n setCallStatus('ended');\n setCurrentCall(null);\n setIsMuted(false);\n\n // Reset to idle after a delay\n setTimeout(() => {\n setCallStatus('idle');\n }, 3000);\n };\n\n const handleCallFailed = (call: Call, errorMsg: string) => {\n setError(new Error(errorMsg));\n setCallStatus('ended');\n setCurrentCall(null);\n };\n\n const handleError = (err: Error) => {\n setError(err);\n };\n\n sdk.on('connection:status', handleConnectionStatus);\n sdk.on('call:incoming', handleIncomingCall);\n sdk.on('call:outgoing', handleOutgoingCall);\n sdk.on('call:ringing', handleCallRinging);\n sdk.on('call:connected', handleCallConnected);\n sdk.on('call:ended', handleCallEnded);\n sdk.on('call:failed', handleCallFailed);\n sdk.on('error', handleError);\n\n return () => {\n sdk.off('connection:status', handleConnectionStatus);\n sdk.off('call:incoming', handleIncomingCall);\n sdk.off('call:outgoing', handleOutgoingCall);\n sdk.off('call:ringing', handleCallRinging);\n sdk.off('call:connected', handleCallConnected);\n sdk.off('call:ended', handleCallEnded);\n sdk.off('call:failed', handleCallFailed);\n sdk.off('error', handleError);\n };\n }, [sdk]);\n\n // Update call duration\n useEffect(() => {\n if (callStatus === 'ongoing' && currentCall) {\n durationIntervalRef.current = window.setInterval(() => {\n const duration = currentCall.duration;\n const mm = String(Math.floor(duration / 60)).padStart(2, '0');\n const ss = String(duration % 60).padStart(2, '0');\n setCallDuration(`${mm}:${ss}`);\n }, 1000);\n } else {\n setCallDuration('00:00');\n if (durationIntervalRef.current) {\n clearInterval(durationIntervalRef.current);\n durationIntervalRef.current = null;\n }\n }\n\n return () => {\n if (durationIntervalRef.current) {\n clearInterval(durationIntervalRef.current);\n }\n };\n }, [callStatus, currentCall]);\n\n // Methods\n const call = async (phoneNumber: string, extension?: string) => {\n try {\n setError(null);\n await sdk.call(phoneNumber, { extension });\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to make call'));\n throw err;\n }\n };\n\n const hangup = () => {\n try {\n sdk.hangup();\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to hang up'));\n }\n };\n\n const toggleMute = () => {\n if (!currentCall) return;\n\n if (isMuted) {\n currentCall.unmute();\n setIsMuted(false);\n } else {\n currentCall.mute();\n setIsMuted(true);\n }\n };\n\n const answerCall = () => {\n try {\n sdk.answerCall();\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to answer call'));\n }\n };\n\n const contextValue: DoraCellContextValue = {\n sdk,\n connectionStatus,\n currentCall,\n callStatus,\n callDuration,\n isMuted,\n isInitialized,\n error,\n call,\n hangup,\n toggleMute,\n answerCall,\n };\n\n return (\n <DoraCellContext.Provider value={contextValue}>\n {children}\n </DoraCellContext.Provider>\n );\n}\n\n/**\n * Hook to access Dora Cell SDK context\n */\nexport function useDoraCell(): DoraCellContextValue {\n const context = useContext(DoraCellContext);\n if (!context) {\n throw new Error('useDoraCell must be used within DoraCellProvider');\n }\n return context;\n}\n\n/**\n * Hook for making calls\n */\nexport function useCall() {\n const { call, hangup, toggleMute, callStatus, callDuration, isMuted, currentCall } = useDoraCell();\n\n return {\n call,\n hangup,\n toggleMute,\n callStatus,\n callDuration,\n isMuted,\n currentCall,\n };\n}\n\n/**\n * Hook for connection status\n */\nexport function useConnectionStatus() {\n const { connectionStatus, isInitialized, error } = useDoraCell();\n\n return {\n connectionStatus,\n isInitialized,\n isConnected: connectionStatus === 'registered',\n error,\n };\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@dora-cell/sdk-react",
3
+ "version": "0.1.1-beta.3",
4
+ "description": "React bindings for Dora Cell SDK",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.mjs",
15
+ "require": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "dev": "tsup --watch",
25
+ "type-check": "tsc --noEmit"
26
+ },
27
+ "keywords": [
28
+ "voip",
29
+ "react",
30
+ "hooks",
31
+ "dora-cell"
32
+ ],
33
+ "author": "Dora Cell",
34
+ "license": "MIT",
35
+ "peerDependencies": {
36
+ "@dora-cell/sdk": "^0.1.1-beta.6",
37
+ "react": "^18.0.0 || ^19.0.0",
38
+ "react-dom": "^18.0.0 || ^19.0.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/react": "^19.0.0",
42
+ "@types/react-dom": "^19.0.0",
43
+ "react": "^19.0.0",
44
+ "react-dom": "^19.0.0",
45
+ "tsup": "^8.0.0",
46
+ "typescript": "^5.3.0"
47
+ }
48
+ }