@tbisoftware/phone 2.0.8 → 2.0.9

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.
@@ -0,0 +1,650 @@
1
+ import { jsx as t, jsxs as s, Fragment as se } from "react/jsx-runtime";
2
+ import { useState as v, useRef as $, useEffect as j, useCallback as U, createContext as oe, useContext as ae } from "react";
3
+ import { J as G, d as le, c as K, f as J, P as ce } from "./index-8z_LWKp3.js";
4
+ let _ = null, V = null;
5
+ function ie(e) {
6
+ return `${e.websocketUrl}|${e.sipUri}|${e.authorizationUser}`;
7
+ }
8
+ function de(e) {
9
+ const f = ie(e);
10
+ if (_ && V === f)
11
+ return _;
12
+ if (_ && V !== f) {
13
+ try {
14
+ _.ua.stop();
15
+ } catch {
16
+ }
17
+ _ = null;
18
+ }
19
+ V = f;
20
+ const u = {
21
+ sockets: [new G.WebSocketInterface(e.websocketUrl)],
22
+ uri: e.sipUri,
23
+ password: e.password,
24
+ registrar_server: e.registrarServer,
25
+ display_name: e.displayName,
26
+ authorization_user: e.authorizationUser,
27
+ connection_recovery_min_interval: 2,
28
+ connection_recovery_max_interval: 30
29
+ }, d = new G.UA(u), y = document.createElement("audio");
30
+ y.autoplay = !0;
31
+ const h = {
32
+ ua: d,
33
+ audio: y,
34
+ isStarted: !1,
35
+ listeners: /* @__PURE__ */ new Set()
36
+ };
37
+ return d.on("connecting", () => {
38
+ h.listeners.forEach((o) => o.onConnecting?.());
39
+ }), d.on("connected", () => {
40
+ h.listeners.forEach((o) => o.onConnected?.());
41
+ }), d.on("disconnected", () => {
42
+ h.listeners.forEach((o) => o.onDisconnected?.());
43
+ }), d.on("registered", () => {
44
+ h.listeners.forEach((o) => o.onRegistered?.());
45
+ }), d.on("unregistered", () => {
46
+ h.listeners.forEach((o) => o.onUnregistered?.());
47
+ }), d.on("registrationFailed", (o) => {
48
+ h.listeners.forEach((a) => a.onRegistrationFailed?.(o?.cause));
49
+ }), d.on("newRTCSession", (o) => {
50
+ const a = o.session;
51
+ if (a.direction === "incoming") {
52
+ const n = a.remote_identity, g = n?.uri?.user || "Unknown", z = n?.display_name || void 0;
53
+ h.listeners.forEach((N) => N.onIncomingSession?.(a, g, z)), a.on("peerconnection", () => {
54
+ a.connection.addEventListener("addstream", (N) => {
55
+ var b = document.createElement("audio");
56
+ N.streams !== void 0 && N.streams.length !== 0 && (b.srcObject = N.streams[0], b.play());
57
+ }), a.connection.addEventListener("track", (N) => {
58
+ var b = document.createElement("audio");
59
+ b.srcObject = N.streams[0], b.play();
60
+ });
61
+ });
62
+ return;
63
+ }
64
+ h.listeners.forEach((n) => n.onNewSession?.(a)), a.connection && (a.connection.addEventListener("addstream", (n) => {
65
+ var g = document.createElement("audio");
66
+ n.streams !== void 0 && n.streams.length !== 0 && (g.srcObject = n.streams[0], g.play());
67
+ }), a.connection.addEventListener("track", (n) => {
68
+ var g = document.createElement("audio");
69
+ g.srcObject = n.streams[0], g.play();
70
+ }));
71
+ }), _ = h, h;
72
+ }
73
+ function ue(e) {
74
+ e.isStarted || (e.ua.start(), e.isStarted = !0);
75
+ }
76
+ function me(e, f) {
77
+ e.listeners.add(f);
78
+ }
79
+ function he(e, f) {
80
+ e.listeners.delete(f);
81
+ }
82
+ function fe(e) {
83
+ return {
84
+ isReady: e.ua.isRegistered(),
85
+ isConnected: e.ua.isConnected()
86
+ };
87
+ }
88
+ const X = oe(null);
89
+ function ge({
90
+ config: e,
91
+ children: f,
92
+ onCallStart: i,
93
+ onCallEnd: u,
94
+ onStatusChange: d,
95
+ onIncomingCall: y
96
+ }) {
97
+ const [h, o] = v(""), [a, n] = v("disconnected"), [g, z] = v(null), [N, b] = v(0), [L, D] = v([]), [T, C] = v(!1), [c, I] = v("disconnected"), [m, k] = v(!1), [E, M] = v(null), S = $(null), l = $(null), H = $(null);
98
+ j(() => {
99
+ l.current = g;
100
+ }, [g]);
101
+ const Z = U(() => {
102
+ m || (k(!0), I("connecting"));
103
+ }, [m]);
104
+ j(() => {
105
+ if (!m) return;
106
+ const r = de(e);
107
+ H.current = r;
108
+ const x = fe(r);
109
+ x.isReady ? (C(!0), I("connected")) : x.isConnected && I("connected");
110
+ const R = {
111
+ onConnecting: () => I("connecting"),
112
+ onConnected: () => I("connected"),
113
+ onDisconnected: () => {
114
+ I("disconnected"), C(!1);
115
+ },
116
+ onRegistered: () => {
117
+ C(!0), I("connected");
118
+ },
119
+ onUnregistered: () => C(!1),
120
+ onRegistrationFailed: (w) => {
121
+ console.error("Registration failed:", w), C(!1), I("failed");
122
+ },
123
+ onNewSession: (w) => {
124
+ S.current = w;
125
+ },
126
+ onIncomingSession: (w, p, B) => {
127
+ if (S.current) {
128
+ w.terminate({ status_code: 486, reason_phrase: "Busy Here" });
129
+ return;
130
+ }
131
+ M({ session: w, callerNumber: p, callerName: B }), o(p), n("ringing"), y?.(p, B), w.on("failed", (O) => {
132
+ console.error("Incoming call failed:", O?.cause), n("failed"), P(p, 0, "missed"), M(null), S.current = null, setTimeout(() => n("disconnected"), 3e3);
133
+ }), w.on("ended", () => {
134
+ n("ended");
135
+ const O = l.current, q = O ? Math.floor((Date.now() - O) / 1e3) : 0;
136
+ P(p, q, "completed"), u?.(p, q, "completed"), M(null), S.current = null, setTimeout(() => {
137
+ n("disconnected"), z(null);
138
+ }, 2e3);
139
+ }), w.on("confirmed", () => {
140
+ n("confirmed"), z(Date.now()), M(null);
141
+ });
142
+ }
143
+ };
144
+ return me(r, R), ue(r), () => {
145
+ he(r, R);
146
+ };
147
+ }, [m, e.websocketUrl, e.sipUri, e.password, e.registrarServer, e.displayName, e.authorizationUser]), j(() => {
148
+ d?.(a);
149
+ }, [a, d]), j(() => {
150
+ const r = localStorage.getItem("tbi-phone-call-history");
151
+ if (r)
152
+ try {
153
+ D(JSON.parse(r));
154
+ } catch (x) {
155
+ console.error("Error loading call history", x);
156
+ }
157
+ }, []), j(() => {
158
+ L.length > 0 && localStorage.setItem("tbi-phone-call-history", JSON.stringify(L));
159
+ }, [L]), j(() => {
160
+ if (a === "confirmed" && g) {
161
+ const r = setInterval(() => {
162
+ b(Math.floor((Date.now() - g) / 1e3));
163
+ }, 1e3);
164
+ return () => clearInterval(r);
165
+ } else
166
+ b(0);
167
+ }, [a, g]), j(() => {
168
+ const r = (x) => {
169
+ const R = x.detail.number;
170
+ a === "disconnected" && W(R);
171
+ };
172
+ return window.addEventListener("StartCallEvent", r), () => {
173
+ window.removeEventListener("StartCallEvent", r);
174
+ };
175
+ }, [a]);
176
+ const P = U((r, x, R) => {
177
+ const w = {
178
+ id: Date.now().toString(),
179
+ number: r,
180
+ timestamp: Date.now(),
181
+ duration: x,
182
+ status: R
183
+ };
184
+ D((p) => [w, ...p].slice(0, 50));
185
+ }, []), ee = U(() => {
186
+ S.current && (S.current.terminate(), S.current = null), M(null);
187
+ }, []), te = U(() => {
188
+ if (!E) return;
189
+ const { session: r, callerNumber: x } = E, R = {
190
+ mediaConstraints: { audio: !0, video: !1 }
191
+ };
192
+ try {
193
+ r.answer(R), S.current = r, i?.(x);
194
+ } catch (w) {
195
+ console.error("Failed to answer call:", w), n("failed"), P(x, 0, "missed"), M(null), setTimeout(() => n("disconnected"), 3e3);
196
+ }
197
+ }, [E, i, P]), ne = U(() => {
198
+ if (!E) return;
199
+ const { session: r, callerNumber: x } = E;
200
+ try {
201
+ r.terminate({ status_code: 603, reason_phrase: "Decline" });
202
+ } catch (R) {
203
+ console.error("Failed to reject call:", R);
204
+ }
205
+ P(x, 0, "missed"), M(null), n("disconnected");
206
+ }, [E, P]), W = U((r) => {
207
+ const x = H.current;
208
+ if (!r.trim() || !x) return;
209
+ if (!T) {
210
+ console.warn("Phone is not ready yet. Please wait for registration.");
211
+ return;
212
+ }
213
+ o(r), i?.(r);
214
+ const w = {
215
+ eventHandlers: {
216
+ progress: () => {
217
+ n("progress");
218
+ },
219
+ failed: (p) => {
220
+ console.error("Call failed:", p?.cause), n("failed"), P(r, 0, "failed"), u?.(r, 0, "failed"), S.current = null, setTimeout(() => n("disconnected"), 3e3);
221
+ },
222
+ ended: () => {
223
+ n("ended");
224
+ const p = l.current, B = p ? Math.floor((Date.now() - p) / 1e3) : 0;
225
+ P(r, B, "completed"), u?.(r, B, "completed"), S.current = null, setTimeout(() => {
226
+ n("disconnected"), z(null);
227
+ }, 2e3);
228
+ },
229
+ confirmed: () => {
230
+ n("confirmed"), z(Date.now());
231
+ }
232
+ },
233
+ mediaConstraints: { audio: !0, video: !1 }
234
+ };
235
+ n("progress");
236
+ try {
237
+ const p = x.ua.call(r, w);
238
+ S.current = p;
239
+ } catch (p) {
240
+ console.error("Failed to start call:", p), n("failed"), P(r, 0, "failed"), setTimeout(() => n("disconnected"), 3e3);
241
+ }
242
+ }, [P, i, u, T]), re = {
243
+ status: a,
244
+ callNumber: h,
245
+ setCallNumber: o,
246
+ callHistory: L,
247
+ currentCallDuration: N,
248
+ startCall: W,
249
+ endCall: ee,
250
+ answerCall: te,
251
+ rejectCall: ne,
252
+ isReady: T,
253
+ connectionStatus: c,
254
+ isInitialized: m,
255
+ initialize: Z,
256
+ incomingCall: E
257
+ };
258
+ return /* @__PURE__ */ t(X.Provider, { value: re, children: f });
259
+ }
260
+ function pe() {
261
+ const e = ae(X);
262
+ if (!e)
263
+ throw new Error("usePhone must be used within a PhoneProvider");
264
+ return e;
265
+ }
266
+ const F = ({ className: e }) => /* @__PURE__ */ t("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }), Q = ({ className: e }) => /* @__PURE__ */ t("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t("path", { d: "M15.05 5A7 7 0 0 1 19 8.95M15.05 1A11 11 0 0 1 23 8.94m-1 7.98v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" }) }), xe = ({ className: e }) => /* @__PURE__ */ t("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t("path", { d: "M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.12-.74-.03-1.02.24l-2.2 2.2c-2.83-1.45-5.15-3.76-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 12h2c0-4.97-4.03-9-9-9v2c3.87 0 7 3.13 7 7zm-4 0h2c0-2.76-2.24-5-5-5v2c1.66 0 3 1.34 3 3z" }) }), A = ({ className: e }) => /* @__PURE__ */ t("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t("path", { d: "M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08a.956.956 0 0 1-.29-.7c0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28a11.27 11.27 0 0 0-2.67-1.85.996.996 0 0 1-.56-.9v-3.1C15.15 9.25 13.6 9 12 9z" }) }), Y = ({ className: e }) => /* @__PURE__ */ t("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t("path", { d: "M6.5 5.5 12 11l7-7-1-1-6 6-4.5-4.5H11V3H5v6h1.5V5.5zm17.21 11.17C20.66 13.78 16.54 12 12 12 7.46 12 3.34 13.78.29 16.67c-.18.18-.29.43-.29.71s.11.53.29.71l2.48 2.48c.18.18.43.29.71.29.27 0 .52-.11.7-.28.79-.74 1.69-1.36 2.66-1.85.33-.16.56-.5.56-.9v-3.1c1.45-.48 3-.73 4.6-.73 1.6 0 3.15.25 4.6.72v3.1c0 .39.23.74.56.9.98.49 1.87 1.12 2.67 1.85.18.18.43.28.7.28.28 0 .53-.11.71-.29l2.48-2.48c.18-.18.29-.43.29-.71s-.12-.52-.3-.7z" }) }), ve = ({ className: e }) => /* @__PURE__ */ s("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: [
267
+ /* @__PURE__ */ t("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }),
268
+ /* @__PURE__ */ t("path", { d: "M16 3l-5 5-2-2-1.5 1.5L11 11l6.5-6.5z" })
269
+ ] }), ye = ({ className: e }) => /* @__PURE__ */ s("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: [
270
+ /* @__PURE__ */ t("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }),
271
+ /* @__PURE__ */ t("path", { d: "M19 6.41L17.59 5 15 7.59 12.41 5 11 6.41 13.59 9 11 11.59 12.41 13 15 10.41 17.59 13 19 11.59 16.41 9z" })
272
+ ] }), be = ({ className: e }) => /* @__PURE__ */ t("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t("path", { d: "M13 3a9 9 0 0 0-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.954 8.954 0 0 0 13 21a9 9 0 0 0 0-18zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z" }) }), Ce = ({ className: e }) => /* @__PURE__ */ t("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) }), we = ({ className: e }) => /* @__PURE__ */ t("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t("path", { d: "M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99 7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17 5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6.83z" }) });
273
+ function Ne({ className: e, labels: f }) {
274
+ const {
275
+ status: i,
276
+ callNumber: u,
277
+ setCallNumber: d,
278
+ callHistory: y,
279
+ currentCallDuration: h,
280
+ startCall: o,
281
+ endCall: a,
282
+ answerCall: n,
283
+ rejectCall: g,
284
+ isReady: z,
285
+ connectionStatus: N,
286
+ isInitialized: b,
287
+ initialize: L,
288
+ incomingCall: D
289
+ } = pe(), [T, C] = v(!1), c = { ...le, ...f }, m = (() => {
290
+ switch (i) {
291
+ case "ringing":
292
+ return { text: c.incomingCall, color: "text-blue-500", Icon: Q };
293
+ case "progress":
294
+ return { text: `${c.calling}...`, color: "text-yellow-500", Icon: Q };
295
+ case "confirmed":
296
+ return { text: `${c.inCall} - ${J(h)}`, color: "text-green-500", Icon: xe };
297
+ case "failed":
298
+ return { text: c.callEnded, color: "text-red-500", Icon: Y };
299
+ case "ended":
300
+ return { text: c.callEnded, color: "text-gray-500", Icon: A };
301
+ default:
302
+ return { text: c.inactive, color: "text-gray-300", Icon: F };
303
+ }
304
+ })();
305
+ return /* @__PURE__ */ s("div", { className: K(
306
+ "tbi-phone w-full max-w-md mx-auto bg-white rounded-2xl shadow-lg border border-gray-200 p-2",
307
+ e
308
+ ), children: [
309
+ !b && /* @__PURE__ */ t("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ t(
310
+ "button",
311
+ {
312
+ onClick: L,
313
+ className: "h-8 w-8 flex items-center justify-center rounded-xl bg-gray-100 hover:bg-green-100 hover:text-green-600 text-gray-500 transition-colors",
314
+ type: "button",
315
+ title: c.turnOn,
316
+ children: /* @__PURE__ */ t(we, { className: "w-5 h-5" })
317
+ }
318
+ ) }),
319
+ b && i === "disconnected" && /* @__PURE__ */ s("div", { className: "flex gap-2 items-center", children: [
320
+ /* @__PURE__ */ t(
321
+ "button",
322
+ {
323
+ onClick: () => C(!0),
324
+ className: "h-8 w-8 flex items-center justify-center rounded-xl border border-gray-200 hover:bg-gray-50 transition-colors",
325
+ type: "button",
326
+ children: /* @__PURE__ */ t(be, { className: "w-4 h-4" })
327
+ }
328
+ ),
329
+ /* @__PURE__ */ t(
330
+ "input",
331
+ {
332
+ type: "text",
333
+ value: u,
334
+ onChange: (k) => d(k.target.value),
335
+ onKeyDown: (k) => {
336
+ k.key === "Enter" && o(u);
337
+ },
338
+ placeholder: c.placeholder,
339
+ className: "flex-1 w-full h-8 px-3 rounded-xl border border-gray-200 text-sm focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
340
+ }
341
+ ),
342
+ /* @__PURE__ */ t(
343
+ "button",
344
+ {
345
+ onClick: () => o(u),
346
+ disabled: u.length < 9 || !z,
347
+ className: "h-8 w-8 flex items-center justify-center rounded-xl bg-green-500 hover:bg-green-600 disabled:bg-gray-300 disabled:cursor-not-allowed text-white transition-colors",
348
+ type: "button",
349
+ title: z ? "Call" : "Connecting...",
350
+ children: N === "connecting" ? /* @__PURE__ */ t("div", { className: "w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" }) : /* @__PURE__ */ t(F, { className: "w-4 h-4" })
351
+ }
352
+ )
353
+ ] }),
354
+ i === "progress" && /* @__PURE__ */ s("div", { className: "flex flex-col items-center gap-3 py-6", children: [
355
+ /* @__PURE__ */ s("div", { className: "relative", children: [
356
+ /* @__PURE__ */ t(m.Icon, { className: "w-12 h-12 text-yellow-500 animate-pulse" }),
357
+ /* @__PURE__ */ t("div", { className: "absolute inset-0 rounded-full border-4 border-yellow-500/30 animate-ping" })
358
+ ] }),
359
+ /* @__PURE__ */ s("div", { className: "text-center", children: [
360
+ /* @__PURE__ */ s("p", { className: "text-base font-semibold", children: [
361
+ c.calling,
362
+ " ",
363
+ u
364
+ ] }),
365
+ /* @__PURE__ */ t("p", { className: "text-sm text-gray-500", children: c.waitingResponse })
366
+ ] }),
367
+ /* @__PURE__ */ s(
368
+ "button",
369
+ {
370
+ onClick: a,
371
+ className: "flex items-center gap-2 px-6 py-2 rounded-full bg-red-500 hover:bg-red-600 text-white text-sm font-medium transition-colors",
372
+ type: "button",
373
+ children: [
374
+ /* @__PURE__ */ t(A, { className: "w-4 h-4" }),
375
+ c.cancel
376
+ ]
377
+ }
378
+ )
379
+ ] }),
380
+ i === "ringing" && D && /* @__PURE__ */ s("div", { className: "flex flex-col items-center gap-3 py-6", children: [
381
+ /* @__PURE__ */ s("div", { className: "relative", children: [
382
+ /* @__PURE__ */ t(m.Icon, { className: "w-12 h-12 text-blue-500 animate-bounce" }),
383
+ /* @__PURE__ */ t("div", { className: "absolute inset-0 rounded-full border-4 border-blue-500/30 animate-ping" })
384
+ ] }),
385
+ /* @__PURE__ */ s("div", { className: "text-center", children: [
386
+ /* @__PURE__ */ t("p", { className: "text-sm text-gray-500", children: c.incomingCall }),
387
+ /* @__PURE__ */ t("p", { className: "text-base font-semibold", children: D.callerNumber }),
388
+ D.callerName && /* @__PURE__ */ t("p", { className: "text-sm text-gray-600", children: D.callerName })
389
+ ] }),
390
+ /* @__PURE__ */ s("div", { className: "flex gap-3", children: [
391
+ /* @__PURE__ */ s(
392
+ "button",
393
+ {
394
+ onClick: g,
395
+ className: "flex items-center gap-2 px-6 py-2 rounded-full bg-red-500 hover:bg-red-600 text-white text-sm font-medium transition-colors",
396
+ type: "button",
397
+ children: [
398
+ /* @__PURE__ */ t(A, { className: "w-4 h-4" }),
399
+ c.reject
400
+ ]
401
+ }
402
+ ),
403
+ /* @__PURE__ */ s(
404
+ "button",
405
+ {
406
+ onClick: n,
407
+ className: "flex items-center gap-2 px-6 py-2 rounded-full bg-green-500 hover:bg-green-600 text-white text-sm font-medium transition-colors",
408
+ type: "button",
409
+ children: [
410
+ /* @__PURE__ */ t(F, { className: "w-4 h-4" }),
411
+ c.answer
412
+ ]
413
+ }
414
+ )
415
+ ] })
416
+ ] }),
417
+ i === "confirmed" && /* @__PURE__ */ s("div", { className: "flex flex-col items-center gap-4 py-6", children: [
418
+ /* @__PURE__ */ s("div", { className: "relative", children: [
419
+ /* @__PURE__ */ t(m.Icon, { className: "w-12 h-12 text-green-500" }),
420
+ /* @__PURE__ */ t("div", { className: "absolute inset-0 rounded-full bg-green-500/20 animate-pulse" })
421
+ ] }),
422
+ /* @__PURE__ */ s("div", { className: "text-center space-y-1", children: [
423
+ /* @__PURE__ */ t("p", { className: "text-xl font-bold", children: u }),
424
+ /* @__PURE__ */ t("p", { className: "text-2xl font-mono text-green-600 tabular-nums", children: J(h) })
425
+ ] }),
426
+ /* @__PURE__ */ s(
427
+ "button",
428
+ {
429
+ onClick: a,
430
+ className: "flex items-center gap-2 px-6 py-2 rounded-full bg-red-500 hover:bg-red-600 text-white text-sm font-medium transition-colors",
431
+ type: "button",
432
+ children: [
433
+ /* @__PURE__ */ t(A, { className: "w-4 h-4" }),
434
+ c.hangUp
435
+ ]
436
+ }
437
+ )
438
+ ] }),
439
+ (i === "failed" || i === "ended") && /* @__PURE__ */ s("div", { className: "flex flex-col items-center gap-3 py-6", children: [
440
+ /* @__PURE__ */ t(
441
+ m.Icon,
442
+ {
443
+ className: K(
444
+ "w-12 h-12",
445
+ i === "failed" ? "text-red-500" : "text-gray-500"
446
+ )
447
+ }
448
+ ),
449
+ /* @__PURE__ */ t("div", { className: "text-center", children: /* @__PURE__ */ t("p", { className: "text-base font-semibold", children: m.text }) })
450
+ ] }),
451
+ T && /* @__PURE__ */ s("div", { className: "fixed inset-0 z-50 flex", children: [
452
+ /* @__PURE__ */ t(
453
+ "div",
454
+ {
455
+ className: "fixed inset-0 bg-black/50",
456
+ onClick: () => C(!1)
457
+ }
458
+ ),
459
+ /* @__PURE__ */ t("div", { className: "fixed right-0 top-0 h-full w-full max-w-md bg-white shadow-xl", style: { backgroundColor: "white" }, children: /* @__PURE__ */ s("div", { className: "flex flex-col h-full", children: [
460
+ /* @__PURE__ */ s("div", { className: "flex items-center justify-between p-4 border-b", children: [
461
+ /* @__PURE__ */ s("div", { children: [
462
+ /* @__PURE__ */ t("h2", { className: "text-lg font-semibold", children: c.callHistory }),
463
+ /* @__PURE__ */ t("p", { className: "text-sm text-gray-500", children: y.length === 0 ? c.noCallsRegistered : `${y.length} ${c.callsRegistered}` })
464
+ ] }),
465
+ /* @__PURE__ */ t(
466
+ "button",
467
+ {
468
+ onClick: () => C(!1),
469
+ className: "h-8 w-8 flex items-center justify-center rounded-lg hover:bg-gray-100 transition-colors",
470
+ type: "button",
471
+ children: /* @__PURE__ */ t(Ce, { className: "w-5 h-5" })
472
+ }
473
+ )
474
+ ] }),
475
+ /* @__PURE__ */ t("div", { className: "flex-1 overflow-y-auto p-4", children: y.length === 0 ? /* @__PURE__ */ s("div", { className: "text-center py-12 text-gray-500", children: [
476
+ /* @__PURE__ */ t(A, { className: "w-12 h-12 mx-auto mb-2 opacity-50" }),
477
+ /* @__PURE__ */ t("p", { children: c.noCalls })
478
+ ] }) : /* @__PURE__ */ t("div", { className: "space-y-2", children: y.map((k, E) => /* @__PURE__ */ t(
479
+ Ie,
480
+ {
481
+ entry: k,
482
+ index: E,
483
+ onCall: () => {
484
+ d(k.number), C(!1), o(k.number);
485
+ }
486
+ },
487
+ k.id
488
+ )) }) })
489
+ ] }) })
490
+ ] })
491
+ ] });
492
+ }
493
+ function Ie({
494
+ entry: e,
495
+ index: f,
496
+ onCall: i
497
+ }) {
498
+ const u = () => {
499
+ switch (e.status) {
500
+ case "completed":
501
+ return /* @__PURE__ */ t(ve, { className: "w-4 h-4 text-green-600" });
502
+ case "failed":
503
+ return /* @__PURE__ */ t(ye, { className: "w-4 h-4 text-red-600" });
504
+ case "missed":
505
+ return /* @__PURE__ */ t(Y, { className: "w-4 h-4 text-yellow-600" });
506
+ }
507
+ }, d = () => {
508
+ switch (e.status) {
509
+ case "completed":
510
+ return "bg-green-100";
511
+ case "failed":
512
+ return "bg-red-100";
513
+ case "missed":
514
+ return "bg-yellow-100";
515
+ }
516
+ };
517
+ return /* @__PURE__ */ s(
518
+ "div",
519
+ {
520
+ className: "flex items-center gap-3 p-3 rounded-lg hover:bg-gray-50 transition-colors duration-200",
521
+ style: { animationDelay: `${f * 30}ms` },
522
+ children: [
523
+ /* @__PURE__ */ t("div", { className: K(
524
+ "w-9 h-9 rounded-full flex items-center justify-center shrink-0",
525
+ d()
526
+ ), children: u() }),
527
+ /* @__PURE__ */ s("div", { className: "flex-1 min-w-0", children: [
528
+ /* @__PURE__ */ t("p", { className: "font-medium text-sm truncate", children: e.number }),
529
+ /* @__PURE__ */ s("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [
530
+ /* @__PURE__ */ t("span", { children: new Date(e.timestamp).toLocaleString("es-ES", {
531
+ day: "2-digit",
532
+ month: "2-digit",
533
+ hour: "2-digit",
534
+ minute: "2-digit"
535
+ }) }),
536
+ e.duration > 0 && /* @__PURE__ */ s(se, { children: [
537
+ /* @__PURE__ */ t("span", { children: "•" }),
538
+ /* @__PURE__ */ t("span", { className: "font-mono tabular-nums", children: J(e.duration) })
539
+ ] })
540
+ ] })
541
+ ] }),
542
+ /* @__PURE__ */ t(
543
+ "button",
544
+ {
545
+ onClick: i,
546
+ className: "h-8 w-8 flex items-center justify-center shrink-0 rounded-lg hover:bg-gray-100 transition-colors",
547
+ type: "button",
548
+ children: /* @__PURE__ */ t(F, { className: "w-4 h-4" })
549
+ }
550
+ )
551
+ ]
552
+ }
553
+ );
554
+ }
555
+ function Ee({ config: e, className: f, onCallStart: i, onCallEnd: u, onStatusChange: d, labels: y }) {
556
+ return /* @__PURE__ */ t(
557
+ ge,
558
+ {
559
+ config: e,
560
+ onCallStart: i,
561
+ onCallEnd: u,
562
+ onStatusChange: d,
563
+ children: /* @__PURE__ */ t(Ne, { className: f, labels: y })
564
+ }
565
+ );
566
+ }
567
+ function He(e, f = {}) {
568
+ const {
569
+ onCallStart: i,
570
+ onCallEnd: u,
571
+ onStatusChange: d,
572
+ onConnectionChange: y,
573
+ persistHistory: h = !0,
574
+ historyKey: o = "tbi-phone-call-history"
575
+ } = f, [a, n] = v("disconnected"), [g, z] = v(""), [N, b] = v([]), [L, D] = v(0), [T, C] = v(!1), [c, I] = v("connecting"), m = $(null);
576
+ j(() => {
577
+ const l = new ce(
578
+ e,
579
+ {
580
+ onStatusChange: (H) => {
581
+ n(H), d?.(H);
582
+ },
583
+ onConnectionChange: (H) => {
584
+ I(H), (H === "connected" || H === "disconnected" || H === "failed") && C(l.state.isReady), y?.(H);
585
+ },
586
+ onCallStart: i,
587
+ onCallEnd: u,
588
+ onDurationUpdate: D,
589
+ onHistoryUpdate: b,
590
+ onRegistered: () => C(!0),
591
+ onUnregistered: () => C(!1)
592
+ },
593
+ {
594
+ persistHistory: h,
595
+ historyKey: o
596
+ }
597
+ );
598
+ return l.initialize(), m.current = l, n(l.state.status), z(l.state.callNumber), b(l.state.callHistory), C(l.state.isReady), I(l.state.connectionStatus), () => {
599
+ l.destroy(), m.current = null;
600
+ };
601
+ }, [
602
+ e.websocketUrl,
603
+ e.sipUri,
604
+ e.password,
605
+ e.registrarServer,
606
+ e.displayName,
607
+ e.authorizationUser,
608
+ h,
609
+ o
610
+ ]), j(() => {
611
+ m.current && m.current.setEvents({
612
+ onCallStart: i,
613
+ onCallEnd: u,
614
+ onStatusChange: (l) => {
615
+ n(l), d?.(l);
616
+ },
617
+ onConnectionChange: (l) => {
618
+ I(l), y?.(l);
619
+ }
620
+ });
621
+ }, [i, u, d, y]);
622
+ const k = U((l) => {
623
+ z(l), m.current?.setCallNumber(l);
624
+ }, []), E = U((l) => {
625
+ m.current?.startCall(l);
626
+ }, []), M = U(() => {
627
+ m.current?.endCall();
628
+ }, []), S = U(() => {
629
+ m.current?.clearHistory(), b([]);
630
+ }, []);
631
+ return {
632
+ status: a,
633
+ callNumber: g,
634
+ setCallNumber: k,
635
+ callHistory: N,
636
+ clearCallHistory: S,
637
+ currentCallDuration: L,
638
+ startCall: E,
639
+ endCall: M,
640
+ isReady: T,
641
+ connectionStatus: c,
642
+ ua: m.current?.ua ?? null
643
+ };
644
+ }
645
+ export {
646
+ Ee as P,
647
+ ge as a,
648
+ He as b,
649
+ pe as u
650
+ };