@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/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { forwardRef, createElement, createContext, useState, useRef, useEffect,
2
2
  import { DoraCell } from '@dora-cell/sdk';
3
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
 
5
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/shared/src/utils.js
5
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/shared/src/utils.js
6
6
  var toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
7
7
  var toCamelCase = (string) => string.replace(
8
8
  /^([A-Z])|[\s-_]+(\w)/g,
@@ -23,7 +23,7 @@ var hasA11yProp = (props) => {
23
23
  }
24
24
  };
25
25
 
26
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/defaultAttributes.js
26
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/defaultAttributes.js
27
27
  var defaultAttributes = {
28
28
  xmlns: "http://www.w3.org/2000/svg",
29
29
  width: 24,
@@ -36,7 +36,7 @@ var defaultAttributes = {
36
36
  strokeLinejoin: "round"
37
37
  };
38
38
 
39
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/Icon.js
39
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/Icon.js
40
40
  var Icon = forwardRef(
41
41
  ({
42
42
  color = "currentColor",
@@ -67,7 +67,7 @@ var Icon = forwardRef(
67
67
  )
68
68
  );
69
69
 
70
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/createLucideIcon.js
70
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/createLucideIcon.js
71
71
  var createLucideIcon = (iconName, iconNode) => {
72
72
  const Component = forwardRef(
73
73
  ({ className, ...props }, ref) => createElement(Icon, {
@@ -85,21 +85,21 @@ var createLucideIcon = (iconName, iconNode) => {
85
85
  return Component;
86
86
  };
87
87
 
88
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/arrow-down-left.js
88
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/arrow-down-left.js
89
89
  var __iconNode = [
90
90
  ["path", { d: "M17 7 7 17", key: "15tmo1" }],
91
91
  ["path", { d: "M17 17H7V7", key: "1org7z" }]
92
92
  ];
93
93
  var ArrowDownLeft = createLucideIcon("arrow-down-left", __iconNode);
94
94
 
95
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/arrow-up-right.js
95
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/arrow-up-right.js
96
96
  var __iconNode2 = [
97
97
  ["path", { d: "M7 7h10v10", key: "1tivn9" }],
98
98
  ["path", { d: "M7 17 17 7", key: "1vkiza" }]
99
99
  ];
100
100
  var ArrowUpRight = createLucideIcon("arrow-up-right", __iconNode2);
101
101
 
102
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/delete.js
102
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/delete.js
103
103
  var __iconNode3 = [
104
104
  [
105
105
  "path",
@@ -113,7 +113,7 @@ var __iconNode3 = [
113
113
  ];
114
114
  var Delete = createLucideIcon("delete", __iconNode3);
115
115
 
116
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/maximize.js
116
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/maximize.js
117
117
  var __iconNode4 = [
118
118
  ["path", { d: "M8 3H5a2 2 0 0 0-2 2v3", key: "1dcmit" }],
119
119
  ["path", { d: "M21 8V5a2 2 0 0 0-2-2h-3", key: "1e4gt3" }],
@@ -122,7 +122,7 @@ var __iconNode4 = [
122
122
  ];
123
123
  var Maximize = createLucideIcon("maximize", __iconNode4);
124
124
 
125
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/mic-off.js
125
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/mic-off.js
126
126
  var __iconNode5 = [
127
127
  ["path", { d: "M12 19v3", key: "npa21l" }],
128
128
  ["path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33", key: "1gzdoj" }],
@@ -133,7 +133,7 @@ var __iconNode5 = [
133
133
  ];
134
134
  var MicOff = createLucideIcon("mic-off", __iconNode5);
135
135
 
136
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/mic.js
136
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/mic.js
137
137
  var __iconNode6 = [
138
138
  ["path", { d: "M12 19v3", key: "npa21l" }],
139
139
  ["path", { d: "M19 10v2a7 7 0 0 1-14 0v-2", key: "1vc78b" }],
@@ -141,7 +141,7 @@ var __iconNode6 = [
141
141
  ];
142
142
  var Mic = createLucideIcon("mic", __iconNode6);
143
143
 
144
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/minimize-2.js
144
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/minimize-2.js
145
145
  var __iconNode7 = [
146
146
  ["path", { d: "m14 10 7-7", key: "oa77jy" }],
147
147
  ["path", { d: "M20 10h-6V4", key: "mjg0md" }],
@@ -150,7 +150,7 @@ var __iconNode7 = [
150
150
  ];
151
151
  var Minimize2 = createLucideIcon("minimize-2", __iconNode7);
152
152
 
153
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/phone.js
153
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/phone.js
154
154
  var __iconNode8 = [
155
155
  [
156
156
  "path",
@@ -162,14 +162,14 @@ var __iconNode8 = [
162
162
  ];
163
163
  var Phone = createLucideIcon("phone", __iconNode8);
164
164
 
165
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/user.js
165
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/user.js
166
166
  var __iconNode9 = [
167
167
  ["path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2", key: "975kel" }],
168
168
  ["circle", { cx: "12", cy: "7", r: "4", key: "17ys0d" }]
169
169
  ];
170
170
  var User = createLucideIcon("user", __iconNode9);
171
171
 
172
- // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/x.js
172
+ // ../../node_modules/.pnpm/lucide-react@0.555.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/x.js
173
173
  var __iconNode10 = [
174
174
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
175
175
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
@@ -189,10 +189,10 @@ function CallInterface({
189
189
  isMuted,
190
190
  hangup,
191
191
  answerCall,
192
- toggleMute
192
+ toggleMute,
193
+ callError
193
194
  } = useCall();
194
195
  const [isMinimized, setIsMinimized] = useState(false);
195
- const [localMuted, setLocalMuted] = useState(false);
196
196
  const [wasConnected, setWasConnected] = useState(false);
197
197
  const [closeCountdown, setCloseCountdown] = useState(null);
198
198
  const [connectingCountdown, setConnectingCountdown] = useState(null);
@@ -202,15 +202,18 @@ function CallInterface({
202
202
  const remoteNumber = currentCall?.remoteNumber || "Unknown";
203
203
  const displayName = remoteNumber;
204
204
  useEffect(() => {
205
- if (!audioRef.current) return;
206
- }, [currentCall]);
205
+ if (currentCall && audioRef.current) {
206
+ const stream = currentCall.getRemoteStream();
207
+ if (stream && audioRef.current.srcObject !== stream) {
208
+ audioRef.current.srcObject = stream;
209
+ }
210
+ }
211
+ }, [currentCall, callStatus]);
207
212
  useEffect(() => {
208
213
  if (callStatus === "ringing" && isIncoming) {
209
214
  onOpenChange?.(true);
210
- if (ringtoneRef.current) {
211
- ringtoneRef.current.play().catch(() => {
212
- });
213
- }
215
+ ringtoneRef.current?.play().catch(() => {
216
+ });
214
217
  } else {
215
218
  if (ringtoneRef.current) {
216
219
  ringtoneRef.current.pause();
@@ -219,6 +222,9 @@ function CallInterface({
219
222
  }
220
223
  }, [callStatus, isIncoming, onOpenChange]);
221
224
  useEffect(() => {
225
+ if (callStatus === "connecting" || callStatus === "ringing") {
226
+ setWasConnected(false);
227
+ }
222
228
  if (callStatus === "ongoing") {
223
229
  setWasConnected(true);
224
230
  }
@@ -226,33 +232,31 @@ function CallInterface({
226
232
  useEffect(() => {
227
233
  if (isOpen && callStatus === "ended") {
228
234
  onCallEnded?.();
229
- const closeDelay = wasConnected ? 1e3 : 5e3;
230
- const countdownStart = Date.now();
231
- const countdownInterval = setInterval(() => {
232
- const elapsed = Date.now() - countdownStart;
233
- const remaining = Math.max(0, closeDelay - elapsed);
234
- const seconds = Math.ceil(remaining / 1e3);
235
- setCloseCountdown(seconds);
235
+ const closeDelay = wasConnected ? 1500 : 3e3;
236
+ const start = Date.now();
237
+ const iv = setInterval(() => {
238
+ const remaining = Math.max(0, closeDelay - (Date.now() - start));
239
+ setCloseCountdown(Math.ceil(remaining / 1e3));
236
240
  if (remaining <= 0) {
237
- clearInterval(countdownInterval);
241
+ clearInterval(iv);
238
242
  onOpenChange?.(false);
243
+ setIsMinimized(false);
239
244
  }
240
245
  }, 100);
241
- return () => clearInterval(countdownInterval);
246
+ return () => clearInterval(iv);
242
247
  } else {
243
248
  setCloseCountdown(null);
244
249
  }
245
250
  }, [callStatus, isOpen, onOpenChange, wasConnected, onCallEnded]);
246
251
  useEffect(() => {
247
- let interval;
248
- const isConnecting = callStatus === "connecting";
249
- if (isOpen && isConnecting && !isIncoming) {
252
+ let iv;
253
+ if (isOpen && callStatus === "connecting" && !isIncoming) {
250
254
  setConnectingCountdown(60);
251
- interval = setInterval(() => {
255
+ iv = setInterval(() => {
252
256
  setConnectingCountdown((prev) => {
253
257
  if (prev === null || prev <= 0) {
254
- clearInterval(interval);
255
- hangup();
258
+ clearInterval(iv);
259
+ if (callStatus === "connecting") hangup();
256
260
  return 0;
257
261
  }
258
262
  return prev - 1;
@@ -261,7 +265,7 @@ function CallInterface({
261
265
  } else {
262
266
  setConnectingCountdown(null);
263
267
  }
264
- return () => clearInterval(interval);
268
+ return () => clearInterval(iv);
265
269
  }, [callStatus, isOpen, isIncoming, hangup]);
266
270
  if (!isOpen && callStatus === "idle") return null;
267
271
  return /* @__PURE__ */ jsxs(
@@ -269,9 +273,9 @@ function CallInterface({
269
273
  {
270
274
  role: "dialog",
271
275
  "aria-label": "Call interface",
272
- className: `fixed top-14 md:top-16 right-0 md:right-4 z-50 transform transition-all duration-300 ease-in-out bg-[#1E1E1E] shadow-xl ${isOpen ? "translate-x-0" : "translate-x-[110%]"} ${isMinimized ? "w-48 h-20 rounded-2xl p-4 flex items-center justify-between" : "w-full sm:w-96 md:max-w-sm max-h-[calc(100vh-3.5rem)] md:max-h-[calc(100vh-4rem)] rounded-none md:rounded-2xl"}`,
276
+ className: `dora-fixed dora-top-14 md:dora-top-16 dora-right-0 md:dora-right-4 dora-z-50 dora-transform dora-transition-all dora-duration-300 dora-ease-in-out dora-bg-[#1E1E1E] dora-shadow-xl ${isOpen ? "dora-translate-x-0" : "dora-translate-x-[110%]"} ${isMinimized ? "dora-w-48 dora-h-20 dora-rounded-2xl dora-p-4 dora-flex dora-items-center dora-justify-between" : "dora-w-full sm:dora-w-96 md:dora-max-w-sm max-h-[calc(100vh-3.5rem)] md:dora-max-h-[calc(100vh-4rem)] dora-rounded-none md:dora-rounded-2xl"}`,
273
277
  children: [
274
- /* @__PURE__ */ jsx("audio", { ref: audioRef, autoPlay: true, className: "hidden" }),
278
+ /* @__PURE__ */ jsx("audio", { ref: audioRef, autoPlay: true, className: "dora-hidden" }),
275
279
  /* @__PURE__ */ jsx(
276
280
  "audio",
277
281
  {
@@ -279,75 +283,73 @@ function CallInterface({
279
283
  src: "https://assets.mixkit.co/active_storage/sfx/2358/2358-preview.mp3",
280
284
  loop: true,
281
285
  preload: "auto",
282
- className: "hidden"
286
+ className: "dora-hidden"
283
287
  }
284
288
  ),
285
- isMinimized ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between w-full h-full", children: [
289
+ isMinimized ? /* @__PURE__ */ jsxs("div", { className: "dora-flex dora-items-center dora-justify-between dora-w-full dora-h-full", children: [
286
290
  /* @__PURE__ */ jsx(
287
291
  "button",
288
292
  {
289
293
  onClick: () => setIsMinimized(false),
290
- className: "w-10 h-10 rounded-full bg-[#2A2A2A] flex items-center justify-center text-slate-400 hover:text-white transition-colors",
291
- "aria-label": "Maximize call interface",
294
+ className: "dora-w-10 dora-h-10 dora-rounded-full dora-bg-[#2A2A2A] dora-flex dora-items-center dora-justify-center dora-text-slate-400 hover:dora-text-white dora-transition-colors",
295
+ "aria-label": "Maximize",
292
296
  children: maximizeIcon || /* @__PURE__ */ jsx(Maximize, { size: 18 })
293
297
  }
294
298
  ),
295
- /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
296
- /* @__PURE__ */ jsx("div", { className: "w-11 h-11 rounded-full bg-white flex items-center justify-center -mr-3", children: /* @__PURE__ */ jsx("span", { className: "text-xl text-slate-900 font-bold", children: displayName.charAt(0).toUpperCase() }) }),
299
+ /* @__PURE__ */ jsxs("div", { className: "dora-relative dora-flex dora-items-center", children: [
300
+ /* @__PURE__ */ jsx("div", { className: "dora-w-11 dora-h-11 dora-rounded-full dora-bg-white dora-flex dora-items-center dora-justify-center dora--mr-3", children: /* @__PURE__ */ jsx("span", { className: "dora-text-xl dora-text-slate-900 dora-font-bold", children: displayName.charAt(0).toUpperCase() }) }),
297
301
  /* @__PURE__ */ jsx(
298
302
  "button",
299
303
  {
300
304
  onClick: hangup,
301
- className: "w-11 h-11 rounded-full bg-red-500 text-white flex items-center justify-center shadow-lg hover:bg-red-600 transition-colors z-10",
305
+ className: "dora-w-11 dora-h-11 dora-rounded-full dora-bg-red-500 dora-text-white dora-flex dora-items-center dora-justify-center dora-shadow-lg hover:dora-bg-red-600 dora-transition-colors dora-z-10",
302
306
  "aria-label": "End call",
303
- children: /* @__PURE__ */ jsx(Phone, { size: 18, className: "transform rotate-135" })
307
+ children: /* @__PURE__ */ jsx(Phone, { size: 18, className: "dora-transform dora-rotate-[135deg]" })
304
308
  }
305
309
  )
306
310
  ] })
307
- ] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col py-4 md:py-6 gap-2.5 md:gap-3.5 px-3 md:px-5 relative", children: [
311
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "dora-flex dora-flex-col dora-py-4 md:dora-py-6 dora-gap-2.5 md:dora-gap-3.5 dora-px-3 md:dora-px-5 dora-relative", children: [
308
312
  /* @__PURE__ */ jsx(
309
313
  "button",
310
314
  {
311
315
  onClick: () => setIsMinimized(true),
312
- className: "absolute top-2 right-2 text-slate-500 hover:text-white transition-colors",
316
+ className: "dora-absolute dora-top-2 dora-right-2 dora-text-slate-500 hover:dora-text-white dora-transition-colors",
313
317
  "aria-label": "Minimize",
314
318
  children: minimizeIcon || /* @__PURE__ */ jsx(Minimize2, { size: 16 })
315
319
  }
316
320
  ),
317
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-2 items-start md:items-center", children: [
318
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 md:gap-4 min-w-0", children: [
319
- /* @__PURE__ */ jsx("div", { className: "w-9 md:w-11 h-9 md:h-11 rounded-full bg-white flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx("span", { className: "text-lg md:text-2xl text-slate-900 font-bold", children: displayName.charAt(0).toUpperCase() }) }),
320
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
321
- /* @__PURE__ */ jsx("h2", { className: "text-base md:text-xl font-normal text-white truncate", children: isIncoming ? displayName : displayName === "Unknown" ? "Outgoing Call" : displayName }),
322
- /* @__PURE__ */ jsxs("p", { className: "text-slate-400 text-xs md:text-sm truncate", children: [
321
+ /* @__PURE__ */ jsxs("div", { className: "dora-flex dora-justify-between dora-gap-2 dora-items-start md:dora-items-center", children: [
322
+ /* @__PURE__ */ jsxs("div", { className: "dora-flex dora-items-center dora-gap-2.5 md:dora-gap-4 dora-min-w-0", children: [
323
+ /* @__PURE__ */ jsx("div", { className: "dora-w-9 md:dora-w-11 dora-h-9 md:dora-h-11 dora-rounded-full dora-bg-white dora-flex dora-items-center dora-justify-center dora-shrink-0", children: /* @__PURE__ */ jsx("span", { className: "dora-text-lg md:dora-text-2xl dora-text-slate-900 dora-font-bold", children: displayName.charAt(0).toUpperCase() }) }),
324
+ /* @__PURE__ */ jsxs("div", { className: "dora-min-w-0 dora-flex-1", children: [
325
+ /* @__PURE__ */ jsx("h2", { className: "dora-text-base md:dora-text-xl dora-font-normal dora-text-white dora-truncate", children: isIncoming ? displayName : displayName === "Unknown" ? "Outgoing Call" : displayName }),
326
+ /* @__PURE__ */ jsxs("p", { className: "dora-text-slate-400 dora-text-xs md:dora-text-sm dora-truncate", children: [
323
327
  remoteNumber,
324
328
  " \u2022",
325
329
  " ",
326
- isMuted ? /* @__PURE__ */ jsx("span", { className: "text-xs text-[#F99578]", children: "Call mute" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
330
+ isMuted ? /* @__PURE__ */ jsx("span", { className: "dora-text-[#F99578]", children: "Call muted" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
327
331
  (callStatus === "connecting" || callStatus === "ringing") && /* @__PURE__ */ jsx("span", { children: isIncoming ? "Incoming Call..." : callStatus === "connecting" ? "Connecting..." : "Ringing..." }),
328
- callStatus === "ongoing" && /* @__PURE__ */ jsx("span", { children: "On Call" })
332
+ callStatus === "ongoing" && /* @__PURE__ */ jsx("span", { children: "On Call" }),
333
+ callStatus === "ended" && /* @__PURE__ */ jsx("span", { children: "Call Ended" })
329
334
  ] })
330
335
  ] })
331
336
  ] })
332
337
  ] }),
333
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1.5 md:gap-3 shrink-0", children: [
338
+ /* @__PURE__ */ jsxs("div", { className: "dora-flex dora-items-center dora-justify-center dora-gap-1.5 md:dora-gap-3 dora-shrink-0", children: [
334
339
  isIncoming && callStatus === "ringing" && /* @__PURE__ */ jsx(
335
340
  "button",
336
341
  {
337
342
  onClick: answerCall,
338
- className: "rounded-full bg-green-500 text-white hover:bg-green-600 transition-colors w-8 md:w-9 h-8 md:h-9 flex items-center justify-center shrink-0",
339
- "aria-label": "Answer call",
343
+ className: "dora-rounded-full dora-bg-green-500 dora-text-white hover:dora-bg-green-600 dora-transition-colors dora-w-8 md:dora-w-9 dora-h-8 md:dora-h-9 dora-flex dora-items-center dora-justify-center dora-shrink-0",
344
+ "aria-label": "Answer",
340
345
  children: /* @__PURE__ */ jsx(Phone, { size: 18 })
341
346
  }
342
347
  ),
343
348
  (callStatus === "ongoing" || isIncoming && callStatus === "ringing") && /* @__PURE__ */ jsx(
344
349
  "button",
345
350
  {
346
- onClick: () => {
347
- toggleMute();
348
- setLocalMuted((s) => !s);
349
- },
350
- className: `rounded-full transition-colors w-8 md:w-9 h-8 md:h-9 flex items-center justify-center shrink-0 bg-slate-700 hover:bg-slate-600 ${isMuted ? "text-white " : " text-slate-400 "}`,
351
+ onClick: toggleMute,
352
+ className: `dora-rounded-full dora-transition-colors dora-w-8 md:dora-w-9 dora-h-8 md:dora-h-9 dora-flex dora-items-center dora-justify-center dora-shrink-0 ${isMuted ? "dora-bg-slate-700 hover:dora-bg-slate-600 dora-text-white" : "dora-bg-[#2A2A2A] hover:dora-bg-[#333333] dora-text-slate-400"}`,
351
353
  "aria-label": "Toggle mute",
352
354
  children: isMuted ? /* @__PURE__ */ jsx(MicOff, { size: 18 }) : /* @__PURE__ */ jsx(Mic, { size: 18 })
353
355
  }
@@ -356,31 +358,53 @@ function CallInterface({
356
358
  "button",
357
359
  {
358
360
  onClick: hangup,
359
- className: "rounded-full bg-red-600 text-white hover:bg-red-700 transition-colors w-8 md:w-9 h-8 md:h-9 flex items-center justify-center shrink-0",
360
- "aria-label": isIncoming && callStatus === "ringing" ? "Decline call" : "End call",
361
- children: /* @__PURE__ */ jsx(Phone, { size: 18, className: "transform rotate-135" })
361
+ className: "dora-rounded-full dora-bg-red-600 dora-text-white hover:dora-bg-red-700 dora-transition-colors dora-w-8 md:dora-w-9 dora-h-8 md:dora-h-9 dora-flex dora-items-center dora-justify-center dora-shrink-0",
362
+ "aria-label": isIncoming && callStatus === "ringing" ? "Decline" : "End call",
363
+ children: /* @__PURE__ */ jsx(Phone, { size: 18, className: "dora-transform dora-rotate-[135deg]" })
362
364
  }
363
365
  )
364
366
  ] })
365
367
  ] }),
366
- /* @__PURE__ */ jsx("div", { className: "flex-1 border border-[#282828]" }),
367
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
368
- /* @__PURE__ */ jsxs("div", { className: "text-slate-400 text-xs md:text-sm font-light tracking-wide flex items-center gap-1", children: [
369
- /* @__PURE__ */ jsxs("div", { children: [
370
- (callStatus === "connecting" || callStatus === "ringing") && /* @__PURE__ */ jsx("span", { children: isIncoming ? "Incoming call" : "Outgoing call" }),
371
- callStatus === "ongoing" && /* @__PURE__ */ jsx("span", { children: "Ongoing" }),
372
- callStatus === "ended" && /* @__PURE__ */ jsx("span", { children: "Call ended" })
373
- ] }),
374
- (callStatus === "connecting" || callStatus === "ringing" || callStatus === "ongoing") && (isIncoming ? /* @__PURE__ */ jsx(ArrowDownLeft, { className: "inline-block ml-1 text-green-400", size: 16 }) : /* @__PURE__ */ jsx(ArrowUpRight, { className: "inline-block ml-1 text-blue-400", size: 16 }))
368
+ /* @__PURE__ */ jsx("div", { className: "dora-flex-1 dora-border-t dora-border-[#282828] dora-mt-2 dora-mb-2" }),
369
+ callError && callStatus === "ended" && /* @__PURE__ */ jsxs("div", { className: "dora-bg-red-900/20 dora-border dora-border-red-500/30 dora-rounded-lg dora-p-2 md:dora-p-3 dora-mb-2 md:dora-mb-3", children: [
370
+ /* @__PURE__ */ jsx("p", { className: "dora-text-red-400 dora-text-xs md:dora-text-sm dora-font-medium", children: "Call Failed" }),
371
+ /* @__PURE__ */ jsx("p", { className: "dora-text-red-300 dora-text-xs dora-mt-0.5 md:dora-mt-1", children: callError }),
372
+ closeCountdown !== null && /* @__PURE__ */ jsxs("div", { className: "dora-mt-1.5 md:dora-mt-2", children: [
373
+ /* @__PURE__ */ jsx("div", { className: "dora-w-full dora-bg-red-900/30 dora-rounded-full dora-h-1.5 dora-overflow-hidden", children: /* @__PURE__ */ jsx(
374
+ "div",
375
+ {
376
+ className: "dora-bg-red-500 dora-h-full dora-transition-all dora-duration-100",
377
+ style: {
378
+ width: `${Math.max(
379
+ 0,
380
+ closeCountdown / (wasConnected ? 1 : 5) * 100
381
+ )}%`
382
+ }
383
+ }
384
+ ) }),
385
+ /* @__PURE__ */ jsxs("p", { className: "dora-text-xs dora-text-red-300 dora-mt-0.5 md:dora-mt-1 dora-text-center", children: [
386
+ "Closing in ",
387
+ closeCountdown,
388
+ "s"
389
+ ] })
390
+ ] })
391
+ ] }),
392
+ /* @__PURE__ */ jsxs("div", { className: "dora-flex dora-justify-between dora-items-center", children: [
393
+ /* @__PURE__ */ jsxs("div", { className: "dora-text-slate-400 dora-text-xs md:dora-text-sm dora-font-light dora-tracking-wide dora-flex dora-items-center dora-gap-1", children: [
394
+ (callStatus === "connecting" || callStatus === "ringing") && /* @__PURE__ */ jsx("span", { children: isIncoming ? "Incoming call" : "Outgoing call" }),
395
+ callStatus === "ongoing" && /* @__PURE__ */ jsx("span", { children: "Ongoing" }),
396
+ callStatus === "ended" && /* @__PURE__ */ jsx("span", { children: "Call ended" }),
397
+ (callStatus === "connecting" || callStatus === "ringing" || callStatus === "ongoing") && (isIncoming ? /* @__PURE__ */ jsx(ArrowDownLeft, { className: "dora-inline-block dora-ml-1 dora-text-green-400", size: 16 }) : /* @__PURE__ */ jsx(ArrowUpRight, { className: "dora-inline-block dora-ml-1 dora-text-blue-400", size: 16 }))
375
398
  ] }),
376
- callStatus === "ongoing" && /* @__PURE__ */ jsx("div", { className: "bg-[#272727] h-6 md:h-7.5 rounded-full px-3 md:px-4.5 text-white font-normal text-xs md:text-sm flex items-center justify-center", children: /* @__PURE__ */ jsxs("span", { children: [
377
- " ",
378
- callDuration,
379
- " "
399
+ callStatus === "ongoing" && /* @__PURE__ */ jsx("div", { className: "dora-bg-[#272727] dora-h-6 md:dora-h-7 dora-rounded-full dora-px-3 md:dora-px-4 dora-text-white dora-font-normal dora-text-xs md:dora-text-sm dora-flex dora-items-center dora-justify-center", children: /* @__PURE__ */ jsx("span", { children: callDuration }) }),
400
+ callStatus === "ended" && closeCountdown !== null && /* @__PURE__ */ jsx("div", { className: "dora-bg-[#272727] dora-h-6 md:dora-h-7 dora-rounded-full dora-px-3 md:dora-px-4 dora-text-slate-400 dora-font-normal dora-text-xs dora-flex dora-items-center dora-justify-center dora-gap-1", children: /* @__PURE__ */ jsxs("span", { children: [
401
+ "Closing in ",
402
+ closeCountdown,
403
+ "s"
380
404
  ] }) }),
381
- (connectingCountdown !== null || callStatus === "ringing") && !isIncoming && callStatus !== "ongoing" && /* @__PURE__ */ jsxs("div", { className: "bg-[#272727] h-8 rounded-full px-3 md:px-4 text-white font-normal text-xs md:text-sm flex items-center justify-center gap-2", children: [
382
- /* @__PURE__ */ jsx("span", { className: "text-[#F99578] whitespace-nowrap", children: callStatus === "ringing" ? "Ringing..." : "Call connecting..." }),
383
- callStatus === "connecting" && connectingCountdown && /* @__PURE__ */ jsxs("span", { className: "font-mono ml-1", children: [
405
+ (connectingCountdown !== null || callStatus === "ringing") && !isIncoming && callStatus !== "ongoing" && callStatus !== "ended" && /* @__PURE__ */ jsxs("div", { className: "dora-bg-[#272727] dora-h-8 dora-rounded-full dora-px-3 md:dora-px-4 dora-text-white dora-font-normal dora-text-xs md:dora-text-sm dora-flex dora-items-center dora-justify-center dora-gap-2", children: [
406
+ /* @__PURE__ */ jsx("span", { className: "dora-text-[#F99578] dora-whitespace-nowrap", children: callStatus === "ringing" ? "Ringing..." : "Connecting..." }),
407
+ callStatus === "connecting" && connectingCountdown && /* @__PURE__ */ jsxs("span", { className: "dora-font-mono dora-ml-1 dora-text-slate-400", children: [
384
408
  Math.floor(connectingCountdown / 60),
385
409
  ":",
386
410
  String(connectingCountdown % 60).padStart(2, "0")
@@ -402,6 +426,7 @@ function Dialpad({
402
426
  onExtensionChange
403
427
  }) {
404
428
  const { call, callStatus } = useCall();
429
+ const { isConnected } = useConnectionStatus();
405
430
  const [number, setNumber] = useState(initialNumber);
406
431
  const [keysVisible, setKeysVisible] = useState(showKeys);
407
432
  const append = (digit) => setNumber((s) => s + digit);
@@ -415,24 +440,24 @@ function Dialpad({
415
440
  console.error("Call failed", e);
416
441
  }
417
442
  };
418
- const isCallDisabled = !number || number.trim() === "" || callStatus === "ringing" || callStatus === "ongoing" || callStatus === "connecting";
419
- return /* @__PURE__ */ jsxs("div", { className: `space-y-4 ${className}`, children: [
420
- availableExtensions.length > 0 && /* @__PURE__ */ jsxs("div", { className: "gap-2 bg-[#F6F7F9] rounded-lg flex items-center justify-between p-2 md:p-2.5 mb-4", children: [
421
- /* @__PURE__ */ jsx("div", { className: "text-xs md:text-sm text-neutral-500 font-normal whitespace-nowrap", children: "Caller ID" }),
443
+ const isCallDisabled = !number || number.trim() === "" || !isConnected || callStatus === "ringing" || callStatus === "ongoing" || callStatus === "connecting";
444
+ return /* @__PURE__ */ jsxs("div", { className: `dora-space-y-4 ${className}`, children: [
445
+ availableExtensions.length > 0 && /* @__PURE__ */ jsxs("div", { className: "dora-gap-2 dora-bg-[#F6F7F9] dora-rounded-lg dora-flex dora-items-center dora-justify-between dora-p-2 md:dora-p-2.5 dora-mb-4", children: [
446
+ /* @__PURE__ */ jsx("div", { className: "dora-text-xs md:dora-text-sm dora-text-neutral-500 dora-font-normal dora-whitespace-nowrap", children: "Caller ID" }),
422
447
  /* @__PURE__ */ jsx(
423
448
  "select",
424
449
  {
425
- className: "bg-transparent text-sm font-medium outline-none",
450
+ className: "dora-bg-transparent dora-text-sm dora-font-medium dora-outline-none",
426
451
  value: selectedExtension,
427
452
  onChange: (e) => onExtensionChange?.(e.target.value),
428
453
  children: availableExtensions.map((ext) => /* @__PURE__ */ jsx("option", { value: ext.value, children: ext.label }, ext.value))
429
454
  }
430
455
  )
431
456
  ] }),
432
- /* @__PURE__ */ jsxs("div", { className: "space-y-2 md:space-y-3 bg-[#F6F7F9] p-2 md:p-2.5 rounded-lg", children: [
433
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 md:gap-3", children: [
434
- /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex items-center bg-white rounded-md px-3 h-10 border border-transparent focus-within:border-green-500 transition-colors", children: [
435
- /* @__PURE__ */ jsx(User, { className: "text-gray-400 mr-2", size: 18 }),
457
+ /* @__PURE__ */ jsxs("div", { className: "dora-space-y-2 md:dora-space-y-3 dora-bg-[#F6F7F9] dora-p-2 md:dora-p-2.5 dora-rounded-lg", children: [
458
+ /* @__PURE__ */ jsxs("div", { className: "dora-flex dora-items-center dora-gap-2 md:dora-gap-3", children: [
459
+ /* @__PURE__ */ jsxs("div", { className: "dora-flex-1 dora-min-w-0 dora-flex dora-items-center dora-bg-white dora-rounded-md dora-px-3 dora-h-10 dora-border dora-border-transparent focus-within:dora-border-green-500 dora-transition-colors", children: [
460
+ /* @__PURE__ */ jsx(User, { className: "dora-text-gray-400 dora-mr-2", size: 18 }),
436
461
  /* @__PURE__ */ jsx(
437
462
  "input",
438
463
  {
@@ -440,53 +465,64 @@ function Dialpad({
440
465
  placeholder: "Enter number",
441
466
  value: number,
442
467
  onChange: (e) => setNumber(e.target.value),
443
- className: "bg-transparent border-none outline-none w-full text-base"
468
+ className: "dora-bg-transparent dora-border-none dora-outline-none dora-w-full dora-text-base dora-text-black"
444
469
  }
445
470
  )
446
471
  ] }),
447
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
472
+ /* @__PURE__ */ jsx(
448
473
  "button",
449
474
  {
450
475
  disabled: isCallDisabled,
451
- className: "bg-green-500 text-white hover:bg-green-600 rounded-lg h-9 md:h-10 w-9 md:w-11 flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
452
476
  onClick: handleCall,
453
477
  title: "Place Call",
478
+ className: "dora-bg-green-500 dora-text-white hover:dora-bg-green-600 dora-rounded-lg dora-h-9 md:dora-h-10 dora-w-9 md:dora-w-11 dora-flex dora-items-center dora-justify-center disabled:dora-opacity-50 disabled:dora-cursor-not-allowed dora-transition-colors",
454
479
  children: /* @__PURE__ */ jsx(Phone, { size: 16, fill: "currentColor" })
455
480
  }
456
- ) })
481
+ )
457
482
  ] }),
458
- /* @__PURE__ */ jsx("div", { children: keysVisible ? /* @__PURE__ */ jsxs("div", { className: "pt-3", children: [
459
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3 mb-3", children: /* @__PURE__ */ jsxs(
483
+ /* @__PURE__ */ jsx("div", { children: keysVisible ? /* @__PURE__ */ jsxs("div", { className: "dora-pt-3", children: [
484
+ /* @__PURE__ */ jsx("div", { className: "dora-flex dora-items-center dora-gap-3 dora-mb-3", children: /* @__PURE__ */ jsxs(
460
485
  "button",
461
486
  {
462
487
  onClick: () => setKeysVisible(false),
463
- className: "px-2 md:px-2.5 h-8 bg-white rounded-full shadow text-neutral-500 flex items-center gap-1.5 md:gap-2 text-xs md:text-sm font-normal hover:bg-gray-50 transition-colors",
488
+ className: "dora-px-2 md:dora-px-2.5 dora-h-8 dora-bg-white dora-rounded-full dora-shadow dora-text-neutral-500 dora-flex dora-items-center dora-gap-1.5 md:dora-gap-2 dora-text-xs md:dora-text-sm dora-font-normal hover:dora-bg-gray-50 dora-transition-colors",
464
489
  children: [
465
490
  /* @__PURE__ */ jsx(X, { color: "red", size: 16 }),
466
491
  " Close keypad"
467
492
  ]
468
493
  }
469
494
  ) }),
470
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2 md:gap-3", children: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "0", "del"].map(
471
- (d) => /* @__PURE__ */ jsx(
472
- "button",
473
- {
474
- onClick: () => d === "del" ? backspace() : append(d),
475
- className: "h-10 md:h-12 bg-white rounded-xl shadow flex items-center justify-center text-base md:text-lg font-medium hover:bg-gray-50 active:bg-gray-100 transition-colors",
476
- "aria-label": d === "del" ? "Delete" : `Dial ${d}`,
477
- children: d === "del" ? /* @__PURE__ */ jsx(Delete, { size: 18 }) : d
478
- },
479
- d
480
- )
481
- ) })
482
- ] }) : /* @__PURE__ */ jsx("div", { className: "pt-2 md:pt-3", children: /* @__PURE__ */ jsxs(
495
+ /* @__PURE__ */ jsx("div", { className: "dora-grid dora-grid-cols-3 dora-gap-2 md:dora-gap-3", children: [
496
+ "1",
497
+ "2",
498
+ "3",
499
+ "4",
500
+ "5",
501
+ "6",
502
+ "7",
503
+ "8",
504
+ "9",
505
+ "+",
506
+ "0",
507
+ "del"
508
+ ].map((d) => /* @__PURE__ */ jsx(
509
+ "button",
510
+ {
511
+ onClick: () => d === "del" ? backspace() : append(d),
512
+ className: "dora-h-10 md:dora-h-12 dora-bg-white dora-rounded-xl dora-shadow dora-flex dora-items-center dora-justify-center dora-text-base md:dora-text-lg dora-font-medium dora-text-slate-900 hover:dora-bg-gray-50 active:dora-bg-gray-100 dora-transition-colors",
513
+ "aria-label": d === "del" ? "Delete" : `Dial ${d}`,
514
+ children: d === "del" ? /* @__PURE__ */ jsx(Delete, { size: 18 }) : d
515
+ },
516
+ d
517
+ )) })
518
+ ] }) : /* @__PURE__ */ jsx("div", { className: "dora-pt-2 md:dora-pt-3", children: /* @__PURE__ */ jsxs(
483
519
  "button",
484
520
  {
485
521
  onClick: () => setKeysVisible(true),
486
- className: "rounded-full bg-[#EDEEF1] h-9 md:h-10 flex justify-center items-center px-3 md:px-4 w-full text-xs md:text-sm hover:bg-[#E3E4E8] transition-colors",
522
+ className: "dora-rounded-full dora-bg-[#EDEEF1] dora-h-9 md:dora-h-10 dora-flex dora-justify-center dora-items-center dora-px-3 md:dora-px-4 dora-w-full dora-text-xs md:dora-text-sm hover:dora-bg-[#E3E4E8] dora-transition-colors",
487
523
  children: [
488
- /* @__PURE__ */ jsx("span", { className: "mr-2", children: "\u{1F522}" }),
489
- /* @__PURE__ */ jsx("span", { className: "text-xs md:text-sm text-neutral-500 font-normal ml-1.5", children: "Open dialer" })
524
+ /* @__PURE__ */ jsx("span", { className: "dora-mr-2", children: "\u{1F522}" }),
525
+ /* @__PURE__ */ jsx("span", { className: "dora-text-xs md:dora-text-sm dora-text-neutral-500 dora-font-normal dora-ml-1.5", children: "Open dialer" })
490
526
  ]
491
527
  }
492
528
  ) }) })
@@ -658,7 +694,7 @@ function useDoraCell() {
658
694
  return context;
659
695
  }
660
696
  function useCall() {
661
- const { call, hangup, toggleMute, answerCall, callStatus, callDuration, isMuted, currentCall } = useDoraCell();
697
+ const { call, hangup, toggleMute, answerCall, callStatus, callDuration, isMuted, currentCall, error } = useDoraCell();
662
698
  return {
663
699
  call,
664
700
  hangup,
@@ -667,7 +703,8 @@ function useCall() {
667
703
  callStatus,
668
704
  callDuration,
669
705
  isMuted,
670
- currentCall
706
+ currentCall,
707
+ callError: error?.message
671
708
  };
672
709
  }
673
710
  function useConnectionStatus() {