@dora-cell/sdk-react 0.1.1-beta.9 → 1.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.
package/README.md CHANGED
@@ -5,374 +5,145 @@ React hooks and components for the Dora Cell VoIP SDK.
5
5
  ## Features
6
6
 
7
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
8
+ ✅ **Context Provider** - Simple setup with `DoraCellProvider`
9
+ ✅ **Pre-built UI** - Includes `Dialpad` and `CallInterface` components
10
+ ✅ **Auto state management** - Automatic call state and connection tracking
12
11
 
13
12
  ## Installation
14
13
 
15
14
  ```bash
16
- npm install @dora-cell/sdk @dora-cell/sdk-react jssip
15
+ npm install @dora-cell/sdk @dora-cell/sdk-react
17
16
  # or
18
- yarn add @dora-cell/sdk @dora-cell/sdk-react jssip
17
+ yarn add @dora-cell/sdk @dora-cell/sdk-react
19
18
  # or
20
- pnpm add @dora-cell/sdk @dora-cell/sdk-react jssip
19
+ pnpm add @dora-cell/sdk @dora-cell/sdk-react
21
20
  ```
22
21
 
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.
22
+ > [!NOTE]
23
+ > `@dora-cell/sdk` is a peer dependency of this package. `jssip` will be installed automatically as a dependency of the SDK.
43
24
 
44
- ```tsx
45
- const config = {
46
- auth: {
47
- type: 'extension',
48
- extension: '1000',
49
- // password: '...' // Optional override (default: 1234)
50
- }
51
- };
52
- ```
25
+ ## Quick Start
53
26
 
54
27
  ### 1. Wrap your app with DoraCellProvider
55
28
 
56
29
  ```tsx
57
- import { DoraCellProvider } from '@dora-cell/sdk-react';
30
+ import { DoraCellProvider } from "@dora-cell/sdk-react";
58
31
 
59
32
  function App() {
60
33
  return (
61
34
  <DoraCellProvider
62
35
  config={{
63
36
  auth: {
64
- type: 'api-token',
65
- apiToken: 'your-api-token-here',
66
- apiBaseUrl: 'https://api.usedora.com'
37
+ type: "extension",
38
+ extension: "1001",
67
39
  },
68
- debug: true
40
+ debug: true,
69
41
  }}
42
+ autoInitialize={true}
70
43
  >
71
- <YourApp />
44
+ <MainApp />
72
45
  </DoraCellProvider>
73
46
  );
74
47
  }
75
48
  ```
76
49
 
77
- ### 2. Use hooks in your components
50
+ ### 2. Use Hooks in your components
78
51
 
79
52
  ```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
- };
53
+ import { useCall, useConnectionStatus } from "@dora-cell/sdk-react";
54
+
55
+ function CallManager() {
56
+ const { call, callStatus, callDuration } = useCall();
57
+ const { isConnected } = useConnectionStatus();
103
58
 
104
59
  return (
105
60
  <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
- )}
61
+ <p>Status: {isConnected ? "Ready" : "Connecting..."}</p>
62
+ {callStatus === "ongoing" && <p>Talking: {callDuration}</p>}
63
+ <button onClick={() => call("08012345678")} disabled={!isConnected}>
64
+ Call Now
65
+ </button>
135
66
  </div>
136
67
  );
137
68
  }
138
69
  ```
139
70
 
140
- ## API Reference
71
+ ## UI Components
141
72
 
142
- ### DoraCellProvider
73
+ We provide high-level components that match the Dora Cell design language.
143
74
 
144
- Wrap your app with this provider to enable SDK functionality.
75
+ ### `CallInterface`
145
76
 
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
- ```
77
+ A slide-over interface that handles the entire call lifecycle (Ringing, Connecting, Ongoing, Mute controls).
162
78
 
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.
79
+ > [!TIP]
80
+ > This component handles audio playback (remote stream and ringtones) automatically. You just need to ensure it's rendered in your tree when a call is active.
229
81
 
230
82
  ```tsx
231
- import { CallInterface } from '@dora-cell/sdk-react';
83
+ import { CallInterface } from "@dora-cell/sdk-react";
232
84
 
233
- function MyApp() {
85
+ function Dashboard() {
234
86
  const [isOpen, setIsOpen] = useState(false);
235
87
 
236
88
  return (
237
89
  <>
238
- <CallInterface
239
- isOpen={isOpen}
240
- onOpenChange={setIsOpen}
241
- onCallEnded={() => console.log('Call ended')}
242
- />
90
+ {/*
91
+ This should be rendered globally (e.g., in your root layout)
92
+ to handle incoming calls even when the dialer is closed.
93
+ */}
94
+ <CallInterface isOpen={isOpen} onOpenChange={setIsOpen} />
243
95
  </>
244
96
  );
245
97
  }
246
98
  ```
247
99
 
248
- #### Dialpad
249
- A dialpad component for entering phone numbers and placing calls.
100
+ ### `Dialpad`
101
+
102
+ A flexible keypad for entering numbers and initiating calls.
250
103
 
251
104
  ```tsx
252
- import { Dialpad } from '@dora-cell/sdk-react';
105
+ import { Dialpad } from "@dora-cell/sdk-react";
253
106
 
254
- function MyApp() {
107
+ function DialerModal() {
255
108
  return (
256
- <Dialpad
257
- onCallInitiated={(number) => console.log('Calling:', number)}
258
- initialNumber=""
109
+ <Dialpad
110
+ showKeys={true}
111
+ onCallInitiated={(number) => console.log("Placing call to:", number)}
259
112
  />
260
113
  );
261
114
  }
262
115
  ```
263
116
 
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
117
+ ## API Reference
298
118
 
299
- ```tsx
300
- function CallWithExtension() {
301
- const sdk = useDoraCell();
302
- const [selectedExtension, setSelectedExtension] = useState('');
119
+ ### `useCall()`
303
120
 
304
- const extensions = sdk.getExtensions();
121
+ Returns methods and state for the active call.
305
122
 
306
- const makeCall = async (number: string) => {
307
- await sdk.call(number, { extension: selectedExtension });
308
- };
123
+ - `call(number)`: Initiate a call.
124
+ - `hangup()`: End current call.
125
+ - `answerCall()`: Answer incoming call.
126
+ - `toggleMute()`: Toggle microphone.
127
+ - `callStatus`: `'idle' | 'connecting' | 'ringing' | 'ongoing' | 'ended'`.
128
+ - `callDuration`: Formatted string `"00:00"`.
129
+ - `isMuted`: Boolean state.
309
130
 
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
- ```
131
+ ### `useConnectionStatus()`
325
132
 
326
- ### Error Handling
133
+ Returns the SIP registration state.
327
134
 
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
- };
135
+ - `isConnected`: `true` when registered and ready.
136
+ - `connectionStatus`: `'disconnected' | 'connecting' | 'connected' | 'registered' | 'registrationFailed'`.
137
+ - `error`: Any connection error object.
341
138
 
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
139
+ ## Styling
352
140
 
353
- All hooks and components are fully typed. Import types as needed:
141
+ The components use Tailwind CSS internally. To avoid conflicts, all styles are prefixed with `dora-`. You must import the CSS file in your main entry file (e.g., `layout.tsx` or `App.tsx`):
354
142
 
355
- ```typescript
356
- import type { Call, CallStatus, ConnectionStatus } from '@dora-cell/sdk';
357
- import type { DoraCellConfig } from '@dora-cell/sdk-react';
143
+ ```javascript
144
+ import "@dora-cell/sdk-react/styles.css";
358
145
  ```
359
146
 
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
147
  ## License
373
148
 
374
149
  MIT
375
-
376
- ## Related Packages
377
-
378
- - [@dora-cell/sdk](https://www.npmjs.com/package/@dora-cell/sdk) - Core VoIP SDK
package/dist/index.d.mts CHANGED
@@ -3,45 +3,18 @@ import React from 'react';
3
3
  import { DoraCellConfig, CallStatus, Call, ConnectionStatus, DoraCell } from '@dora-cell/sdk';
4
4
 
5
5
  interface CallInterfaceProps {
6
- /**
7
- * Whether the interface is open/visible
8
- */
9
6
  isOpen?: boolean;
10
- /**
11
- * Callback when visibility changes
12
- */
13
7
  onOpenChange?: (open: boolean) => void;
14
- /**
15
- * Callback when call ends (useful for invalidating queries)
16
- */
17
8
  onCallEnded?: () => void;
18
- /**
19
- * Custom maximize icon component
20
- */
21
9
  maximizeIcon?: React.ReactNode;
22
- /**
23
- * Custom minimize icon component
24
- */
25
10
  minimizeIcon?: React.ReactNode;
26
11
  }
27
12
  declare function CallInterface({ isOpen, onOpenChange, onCallEnded, maximizeIcon, minimizeIcon, }: CallInterfaceProps): react_jsx_runtime.JSX.Element | null;
28
13
 
29
14
  interface DialpadProps {
30
- /**
31
- * Callback when call is initiated
32
- */
33
15
  onCallInitiated?: (number: string) => void;
34
- /**
35
- * Initial number to populate
36
- */
37
16
  initialNumber?: string;
38
- /**
39
- * Whether to show the dialpad keys (0-9)
40
- */
41
17
  showKeys?: boolean;
42
- /**
43
- * Custom class name for the container
44
- */
45
18
  className?: string;
46
19
  availableExtensions?: Array<{
47
20
  label: string;
@@ -88,6 +61,7 @@ declare function useCall(): {
88
61
  callDuration: string;
89
62
  isMuted: boolean;
90
63
  currentCall: Call | null;
64
+ callError: string | undefined;
91
65
  };
92
66
  /**
93
67
  * Hook for connection status
package/dist/index.d.ts CHANGED
@@ -3,45 +3,18 @@ import React from 'react';
3
3
  import { DoraCellConfig, CallStatus, Call, ConnectionStatus, DoraCell } from '@dora-cell/sdk';
4
4
 
5
5
  interface CallInterfaceProps {
6
- /**
7
- * Whether the interface is open/visible
8
- */
9
6
  isOpen?: boolean;
10
- /**
11
- * Callback when visibility changes
12
- */
13
7
  onOpenChange?: (open: boolean) => void;
14
- /**
15
- * Callback when call ends (useful for invalidating queries)
16
- */
17
8
  onCallEnded?: () => void;
18
- /**
19
- * Custom maximize icon component
20
- */
21
9
  maximizeIcon?: React.ReactNode;
22
- /**
23
- * Custom minimize icon component
24
- */
25
10
  minimizeIcon?: React.ReactNode;
26
11
  }
27
12
  declare function CallInterface({ isOpen, onOpenChange, onCallEnded, maximizeIcon, minimizeIcon, }: CallInterfaceProps): react_jsx_runtime.JSX.Element | null;
28
13
 
29
14
  interface DialpadProps {
30
- /**
31
- * Callback when call is initiated
32
- */
33
15
  onCallInitiated?: (number: string) => void;
34
- /**
35
- * Initial number to populate
36
- */
37
16
  initialNumber?: string;
38
- /**
39
- * Whether to show the dialpad keys (0-9)
40
- */
41
17
  showKeys?: boolean;
42
- /**
43
- * Custom class name for the container
44
- */
45
18
  className?: string;
46
19
  availableExtensions?: Array<{
47
20
  label: string;
@@ -88,6 +61,7 @@ declare function useCall(): {
88
61
  callDuration: string;
89
62
  isMuted: boolean;
90
63
  currentCall: Call | null;
64
+ callError: string | undefined;
91
65
  };
92
66
  /**
93
67
  * Hook for connection status