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

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,378 @@
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
+ ### Authentication
26
+
27
+ You can authenticate using either an API Token (recommended for production) or Direct SIP Credentials (useful for testing/development).
28
+
29
+ #### Option 1: API Token (Production)
30
+ The SDK will fetch SIP credentials from your backend using the token.
31
+ ```tsx
32
+ const config = {
33
+ auth: {
34
+ type: 'api-token',
35
+ apiToken: 'YOUR_API_TOKEN',
36
+ // apiBaseUrl: 'https://api.your-backend.com' (Optional)
37
+ }
38
+ };
39
+ ```
40
+
41
+ #### Option 2: Extension Authentication (Plug & Play)
42
+ You can connect using just your extension number. The SDK handles the server configuration automatically.
43
+
44
+ ```tsx
45
+ const config = {
46
+ auth: {
47
+ type: 'extension',
48
+ extension: '1000',
49
+ // password: '...' // Optional override (default: 1234)
50
+ }
51
+ };
52
+ ```
53
+
54
+ ### 1. Wrap your app with DoraCellProvider
55
+
56
+ ```tsx
57
+ import { DoraCellProvider } from '@dora-cell/sdk-react';
58
+
59
+ function App() {
60
+ return (
61
+ <DoraCellProvider
62
+ config={{
63
+ auth: {
64
+ type: 'api-token',
65
+ apiToken: 'your-api-token-here',
66
+ apiBaseUrl: 'https://api.usedora.com'
67
+ },
68
+ debug: true
69
+ }}
70
+ >
71
+ <YourApp />
72
+ </DoraCellProvider>
73
+ );
74
+ }
75
+ ```
76
+
77
+ ### 2. Use hooks in your components
78
+
79
+ ```tsx
80
+ import { useCall, useConnectionStatus } from '@dora-cell/sdk-react';
81
+
82
+ function CallInterface() {
83
+ const {
84
+ call,
85
+ hangup,
86
+ toggleMute,
87
+ callStatus,
88
+ callDuration,
89
+ isMuted,
90
+ currentCall
91
+ } = useCall();
92
+
93
+ const { isConnected, status } = useConnectionStatus();
94
+ const [number, setNumber] = useState('');
95
+
96
+ const handleCall = async () => {
97
+ try {
98
+ await call(number);
99
+ } catch (error) {
100
+ console.error('Call failed:', error);
101
+ }
102
+ };
103
+
104
+ return (
105
+ <div>
106
+ <p>Status: {isConnected ? 'Connected' : 'Disconnected'}</p>
107
+
108
+ {callStatus === 'idle' && (
109
+ <>
110
+ <input
111
+ value={number}
112
+ onChange={(e) => setNumber(e.target.value)}
113
+ placeholder="Enter phone number"
114
+ />
115
+ <button onClick={handleCall} disabled={!isConnected}>
116
+ Call
117
+ </button>
118
+ </>
119
+ )}
120
+
121
+ {callStatus === 'ongoing' && (
122
+ <>
123
+ <p>Call with: {currentCall?.remoteNumber}</p>
124
+ <p>Duration: {callDuration}</p>
125
+ <button onClick={toggleMute}>
126
+ {isMuted ? 'Unmute' : 'Mute'}
127
+ </button>
128
+ <button onClick={hangup}>Hang Up</button>
129
+ </>
130
+ )}
131
+
132
+ {callStatus === 'ringing' && (
133
+ <p>Ringing...</p>
134
+ )}
135
+ </div>
136
+ );
137
+ }
138
+ ```
139
+
140
+ ## API Reference
141
+
142
+ ### DoraCellProvider
143
+
144
+ Wrap your app with this provider to enable SDK functionality.
145
+
146
+ ```tsx
147
+ <DoraCellProvider
148
+ config={{
149
+ auth: {
150
+ type: 'api-token',
151
+ apiToken: string,
152
+ apiBaseUrl?: string
153
+ },
154
+ turnServers?: RTCIceServer[],
155
+ debug?: boolean,
156
+ autoSelectExtension?: boolean
157
+ }}
158
+ >
159
+ {children}
160
+ </DoraCellProvider>
161
+ ```
162
+
163
+ ### useCall()
164
+
165
+ Hook for managing calls.
166
+
167
+ ```typescript
168
+ const {
169
+ // Methods
170
+ call: (phoneNumber: string) => Promise<void>,
171
+ hangup: () => void,
172
+ answerCall: () => void,
173
+ toggleMute: () => void,
174
+
175
+ // State
176
+ callStatus: 'idle' | 'ringing' | 'ongoing',
177
+ callDuration: string, // Formatted as "MM:SS"
178
+ isMuted: boolean,
179
+ currentCall: Call | null,
180
+ error: Error | null
181
+ } = useCall();
182
+ ```
183
+
184
+ **Methods:**
185
+ - `call(phoneNumber)` - Make an outbound call
186
+ - `hangup()` - End the current call
187
+ - `answerCall()` - Answer an incoming call
188
+ - `toggleMute()` - Toggle mute/unmute
189
+
190
+ **State:**
191
+ - `callStatus` - Current call status
192
+ - `callDuration` - Formatted call duration (e.g., "01:23")
193
+ - `isMuted` - Whether the call is muted
194
+ - `currentCall` - Current call object with details
195
+ - `error` - Any call-related errors
196
+
197
+ ### useConnectionStatus()
198
+
199
+ Hook for monitoring connection status.
200
+
201
+ ```typescript
202
+ const {
203
+ isConnected: boolean,
204
+ status: 'disconnected' | 'connecting' | 'connected' | 'error',
205
+ error: Error | null
206
+ } = useConnectionStatus();
207
+ ```
208
+
209
+ ### useDoraCell()
210
+
211
+ Access the underlying SDK instance directly.
212
+
213
+ ```typescript
214
+ const sdk = useDoraCell();
215
+
216
+ // Use SDK methods directly
217
+ sdk.getExtensions();
218
+ sdk.on('call:incoming', (call) => {
219
+ console.log('Incoming call from:', call.remoteNumber);
220
+ });
221
+ ```
222
+
223
+ ### UI Components
224
+
225
+ The SDK includes pre-built UI components for typical call flows.
226
+
227
+ #### CallInterface
228
+ A complete active call modal that handles ringing, connecting, and ongoing call states.
229
+
230
+ ```tsx
231
+ import { CallInterface } from '@dora-cell/sdk-react';
232
+
233
+ function MyApp() {
234
+ const [isOpen, setIsOpen] = useState(false);
235
+
236
+ return (
237
+ <>
238
+ <CallInterface
239
+ isOpen={isOpen}
240
+ onOpenChange={setIsOpen}
241
+ onCallEnded={() => console.log('Call ended')}
242
+ />
243
+ </>
244
+ );
245
+ }
246
+ ```
247
+
248
+ #### Dialpad
249
+ A dialpad component for entering phone numbers and placing calls.
250
+
251
+ ```tsx
252
+ import { Dialpad } from '@dora-cell/sdk-react';
253
+
254
+ function MyApp() {
255
+ return (
256
+ <Dialpad
257
+ onCallInitiated={(number) => console.log('Calling:', number)}
258
+ initialNumber=""
259
+ />
260
+ );
261
+ }
262
+ ```
263
+
264
+ ## Advanced Usage
265
+
266
+ ### Handling Incoming Calls
267
+
268
+ ```tsx
269
+ function IncomingCallHandler() {
270
+ const { currentCall, answerCall, hangup, callStatus } = useCall();
271
+ const sdk = useDoraCell();
272
+
273
+ useEffect(() => {
274
+ const handleIncoming = (call) => {
275
+ // Show notification or UI for incoming call
276
+ console.log('Incoming call from:', call.remoteNumber);
277
+ };
278
+
279
+ sdk.on('call:incoming', handleIncoming);
280
+ return () => sdk.off('call:incoming', handleIncoming);
281
+ }, [sdk]);
282
+
283
+ if (callStatus === 'ringing' && currentCall?.direction === 'inbound') {
284
+ return (
285
+ <div>
286
+ <p>Incoming call from {currentCall.remoteNumber}</p>
287
+ <button onClick={answerCall}>Answer</button>
288
+ <button onClick={hangup}>Decline</button>
289
+ </div>
290
+ );
291
+ }
292
+
293
+ return null;
294
+ }
295
+ ```
296
+
297
+ ### Custom Extension Selection
298
+
299
+ ```tsx
300
+ function CallWithExtension() {
301
+ const sdk = useDoraCell();
302
+ const [selectedExtension, setSelectedExtension] = useState('');
303
+
304
+ const extensions = sdk.getExtensions();
305
+
306
+ const makeCall = async (number: string) => {
307
+ await sdk.call(number, { extension: selectedExtension });
308
+ };
309
+
310
+ return (
311
+ <div>
312
+ <select
313
+ value={selectedExtension}
314
+ onChange={(e) => setSelectedExtension(e.target.value)}
315
+ >
316
+ {extensions.map(ext => (
317
+ <option key={ext} value={ext}>{ext}</option>
318
+ ))}
319
+ </select>
320
+ {/* Rest of your call UI */}
321
+ </div>
322
+ );
323
+ }
324
+ ```
325
+
326
+ ### Error Handling
327
+
328
+ ```tsx
329
+ function CallWithErrorHandling() {
330
+ const { call, error, callStatus } = useCall();
331
+ const [number, setNumber] = useState('');
332
+
333
+ const handleCall = async () => {
334
+ try {
335
+ await call(number);
336
+ } catch (err) {
337
+ console.error('Call failed:', err);
338
+ // Show error to user
339
+ }
340
+ };
341
+
342
+ return (
343
+ <div>
344
+ {error && <div className="error">{error.message}</div>}
345
+ {/* Rest of your UI */}
346
+ </div>
347
+ );
348
+ }
349
+ ```
350
+
351
+ ## TypeScript Support
352
+
353
+ All hooks and components are fully typed. Import types as needed:
354
+
355
+ ```typescript
356
+ import type { Call, CallStatus, ConnectionStatus } from '@dora-cell/sdk';
357
+ import type { DoraCellConfig } from '@dora-cell/sdk-react';
358
+ ```
359
+
360
+ ## Examples
361
+
362
+ See the `/examples` directory in the main repository for complete working examples:
363
+ - `react-app/` - React application with hooks
364
+ - `nextjs-app/` - Next.js application
365
+
366
+ ## Requirements
367
+
368
+ - React 18.0.0 or higher (including React 19)
369
+ - @dora-cell/sdk (peer dependency)
370
+ - jssip (peer dependency)
371
+
372
+ ## License
373
+
374
+ MIT
375
+
376
+ ## Related Packages
377
+
378
+ - [@dora-cell/sdk](https://www.npmjs.com/package/@dora-cell/sdk) - Core VoIP SDK
@@ -0,0 +1,102 @@
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 CallInterfaceProps {
6
+ /**
7
+ * Whether the interface is open/visible
8
+ */
9
+ isOpen?: boolean;
10
+ /**
11
+ * Callback when visibility changes
12
+ */
13
+ onOpenChange?: (open: boolean) => void;
14
+ /**
15
+ * Callback when call ends (useful for invalidating queries)
16
+ */
17
+ onCallEnded?: () => void;
18
+ /**
19
+ * Custom maximize icon component
20
+ */
21
+ maximizeIcon?: React.ReactNode;
22
+ /**
23
+ * Custom minimize icon component
24
+ */
25
+ minimizeIcon?: React.ReactNode;
26
+ }
27
+ declare function CallInterface({ isOpen, onOpenChange, onCallEnded, maximizeIcon, minimizeIcon, }: CallInterfaceProps): react_jsx_runtime.JSX.Element | null;
28
+
29
+ interface DialpadProps {
30
+ /**
31
+ * Callback when call is initiated
32
+ */
33
+ onCallInitiated?: (number: string) => void;
34
+ /**
35
+ * Initial number to populate
36
+ */
37
+ initialNumber?: string;
38
+ /**
39
+ * Whether to show the dialpad keys (0-9)
40
+ */
41
+ showKeys?: boolean;
42
+ /**
43
+ * Custom class name for the container
44
+ */
45
+ className?: string;
46
+ availableExtensions?: Array<{
47
+ label: string;
48
+ value: string;
49
+ }>;
50
+ selectedExtension?: string;
51
+ onExtensionChange?: (ext: string) => void;
52
+ }
53
+ declare function Dialpad({ onCallInitiated, initialNumber, showKeys, className, availableExtensions, selectedExtension, onExtensionChange, }: DialpadProps): react_jsx_runtime.JSX.Element;
54
+
55
+ interface DoraCellContextValue {
56
+ sdk: DoraCell | null;
57
+ connectionStatus: ConnectionStatus;
58
+ currentCall: Call | null;
59
+ callStatus: CallStatus;
60
+ callDuration: string;
61
+ isMuted: boolean;
62
+ isInitialized: boolean;
63
+ error: Error | null;
64
+ call: (phoneNumber: string, extension?: string) => Promise<void>;
65
+ hangup: () => void;
66
+ toggleMute: () => void;
67
+ answerCall: () => void;
68
+ }
69
+ interface DoraCellProviderProps {
70
+ config: DoraCellConfig;
71
+ children: React.ReactNode;
72
+ autoInitialize?: boolean;
73
+ }
74
+ declare function DoraCellProvider({ config, children, autoInitialize, }: DoraCellProviderProps): react_jsx_runtime.JSX.Element;
75
+ /**
76
+ * Hook to access Dora Cell SDK context
77
+ */
78
+ declare function useDoraCell(): DoraCellContextValue;
79
+ /**
80
+ * Hook for making calls
81
+ */
82
+ declare function useCall(): {
83
+ call: (phoneNumber: string, extension?: string) => Promise<void>;
84
+ hangup: () => void;
85
+ toggleMute: () => void;
86
+ answerCall: () => void;
87
+ callStatus: CallStatus;
88
+ callDuration: string;
89
+ isMuted: boolean;
90
+ currentCall: Call | null;
91
+ };
92
+ /**
93
+ * Hook for connection status
94
+ */
95
+ declare function useConnectionStatus(): {
96
+ connectionStatus: ConnectionStatus;
97
+ isInitialized: boolean;
98
+ isConnected: boolean;
99
+ error: Error | null;
100
+ };
101
+
102
+ export { CallInterface, Dialpad, DoraCellProvider, type DoraCellProviderProps, useCall, useConnectionStatus, useDoraCell };
@@ -0,0 +1,102 @@
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 CallInterfaceProps {
6
+ /**
7
+ * Whether the interface is open/visible
8
+ */
9
+ isOpen?: boolean;
10
+ /**
11
+ * Callback when visibility changes
12
+ */
13
+ onOpenChange?: (open: boolean) => void;
14
+ /**
15
+ * Callback when call ends (useful for invalidating queries)
16
+ */
17
+ onCallEnded?: () => void;
18
+ /**
19
+ * Custom maximize icon component
20
+ */
21
+ maximizeIcon?: React.ReactNode;
22
+ /**
23
+ * Custom minimize icon component
24
+ */
25
+ minimizeIcon?: React.ReactNode;
26
+ }
27
+ declare function CallInterface({ isOpen, onOpenChange, onCallEnded, maximizeIcon, minimizeIcon, }: CallInterfaceProps): react_jsx_runtime.JSX.Element | null;
28
+
29
+ interface DialpadProps {
30
+ /**
31
+ * Callback when call is initiated
32
+ */
33
+ onCallInitiated?: (number: string) => void;
34
+ /**
35
+ * Initial number to populate
36
+ */
37
+ initialNumber?: string;
38
+ /**
39
+ * Whether to show the dialpad keys (0-9)
40
+ */
41
+ showKeys?: boolean;
42
+ /**
43
+ * Custom class name for the container
44
+ */
45
+ className?: string;
46
+ availableExtensions?: Array<{
47
+ label: string;
48
+ value: string;
49
+ }>;
50
+ selectedExtension?: string;
51
+ onExtensionChange?: (ext: string) => void;
52
+ }
53
+ declare function Dialpad({ onCallInitiated, initialNumber, showKeys, className, availableExtensions, selectedExtension, onExtensionChange, }: DialpadProps): react_jsx_runtime.JSX.Element;
54
+
55
+ interface DoraCellContextValue {
56
+ sdk: DoraCell | null;
57
+ connectionStatus: ConnectionStatus;
58
+ currentCall: Call | null;
59
+ callStatus: CallStatus;
60
+ callDuration: string;
61
+ isMuted: boolean;
62
+ isInitialized: boolean;
63
+ error: Error | null;
64
+ call: (phoneNumber: string, extension?: string) => Promise<void>;
65
+ hangup: () => void;
66
+ toggleMute: () => void;
67
+ answerCall: () => void;
68
+ }
69
+ interface DoraCellProviderProps {
70
+ config: DoraCellConfig;
71
+ children: React.ReactNode;
72
+ autoInitialize?: boolean;
73
+ }
74
+ declare function DoraCellProvider({ config, children, autoInitialize, }: DoraCellProviderProps): react_jsx_runtime.JSX.Element;
75
+ /**
76
+ * Hook to access Dora Cell SDK context
77
+ */
78
+ declare function useDoraCell(): DoraCellContextValue;
79
+ /**
80
+ * Hook for making calls
81
+ */
82
+ declare function useCall(): {
83
+ call: (phoneNumber: string, extension?: string) => Promise<void>;
84
+ hangup: () => void;
85
+ toggleMute: () => void;
86
+ answerCall: () => void;
87
+ callStatus: CallStatus;
88
+ callDuration: string;
89
+ isMuted: boolean;
90
+ currentCall: Call | null;
91
+ };
92
+ /**
93
+ * Hook for connection status
94
+ */
95
+ declare function useConnectionStatus(): {
96
+ connectionStatus: ConnectionStatus;
97
+ isInitialized: boolean;
98
+ isConnected: boolean;
99
+ error: Error | null;
100
+ };
101
+
102
+ export { CallInterface, Dialpad, DoraCellProvider, type DoraCellProviderProps, useCall, useConnectionStatus, useDoraCell };