@tbisoftware/phone 2.0.8 → 2.0.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.
@@ -0,0 +1,649 @@
1
+ import { jsx as t, jsxs as s, Fragment as se } from "react/jsx-runtime";
2
+ import { useState as v, useRef as $, useEffect as M, 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), [j, L] = v([]), [T, C] = v(!1), [c, I] = v("disconnected"), [m, k] = v(!1), [E, D] = v(null), S = $(null), l = $(null), H = $(null);
98
+ M(() => {
99
+ l.current = g;
100
+ }, [g]);
101
+ const Z = U(() => {
102
+ m || (k(!0), I("connecting"));
103
+ }, [m]);
104
+ M(() => {
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
+ D({ 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"), D(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"), D(null), S.current = null, setTimeout(() => {
137
+ n("disconnected"), z(null);
138
+ }, 2e3);
139
+ }), w.on("confirmed", () => {
140
+ n("confirmed"), z(Date.now()), D(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]), M(() => {
148
+ d?.(a);
149
+ }, [a, d]), M(() => {
150
+ const r = localStorage.getItem("tbi-phone-call-history");
151
+ if (r)
152
+ try {
153
+ L(JSON.parse(r));
154
+ } catch (x) {
155
+ console.error("Error loading call history", x);
156
+ }
157
+ }, []), M(() => {
158
+ j.length > 0 && localStorage.setItem("tbi-phone-call-history", JSON.stringify(j));
159
+ }, [j]), M(() => {
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]), M(() => {
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
+ L((p) => [w, ...p].slice(0, 50));
185
+ }, []), ee = U(() => {
186
+ S.current && (S.current.terminate(), S.current = null), D(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"), D(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"), D(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: j,
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: j,
288
+ incomingCall: L
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: j,
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 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" && L && /* @__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: L.callerNumber })
388
+ ] }),
389
+ /* @__PURE__ */ s("div", { className: "flex gap-3", children: [
390
+ /* @__PURE__ */ s(
391
+ "button",
392
+ {
393
+ onClick: g,
394
+ 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",
395
+ type: "button",
396
+ children: [
397
+ /* @__PURE__ */ t(A, { className: "w-4 h-4" }),
398
+ c.reject
399
+ ]
400
+ }
401
+ ),
402
+ /* @__PURE__ */ s(
403
+ "button",
404
+ {
405
+ onClick: n,
406
+ 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",
407
+ type: "button",
408
+ children: [
409
+ /* @__PURE__ */ t(F, { className: "w-4 h-4" }),
410
+ c.answer
411
+ ]
412
+ }
413
+ )
414
+ ] })
415
+ ] }),
416
+ i === "confirmed" && /* @__PURE__ */ s("div", { className: "flex flex-col items-center gap-4 py-6", children: [
417
+ /* @__PURE__ */ s("div", { className: "relative", children: [
418
+ /* @__PURE__ */ t(m.Icon, { className: "w-12 h-12 text-green-500" }),
419
+ /* @__PURE__ */ t("div", { className: "absolute inset-0 rounded-full bg-green-500/20 animate-pulse" })
420
+ ] }),
421
+ /* @__PURE__ */ s("div", { className: "text-center space-y-1", children: [
422
+ /* @__PURE__ */ t("p", { className: "text-xl font-bold", children: u }),
423
+ /* @__PURE__ */ t("p", { className: "text-2xl font-mono text-green-600 tabular-nums", children: J(h) })
424
+ ] }),
425
+ /* @__PURE__ */ s(
426
+ "button",
427
+ {
428
+ onClick: a,
429
+ 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",
430
+ type: "button",
431
+ children: [
432
+ /* @__PURE__ */ t(A, { className: "w-4 h-4" }),
433
+ c.hangUp
434
+ ]
435
+ }
436
+ )
437
+ ] }),
438
+ (i === "failed" || i === "ended") && /* @__PURE__ */ s("div", { className: "flex flex-col items-center gap-3 py-6", children: [
439
+ /* @__PURE__ */ t(
440
+ m.Icon,
441
+ {
442
+ className: K(
443
+ "w-12 h-12",
444
+ i === "failed" ? "text-red-500" : "text-gray-500"
445
+ )
446
+ }
447
+ ),
448
+ /* @__PURE__ */ t("div", { className: "text-center", children: /* @__PURE__ */ t("p", { className: "text-base font-semibold", children: m.text }) })
449
+ ] }),
450
+ T && /* @__PURE__ */ s("div", { className: "fixed inset-0 z-50 flex", children: [
451
+ /* @__PURE__ */ t(
452
+ "div",
453
+ {
454
+ className: "fixed inset-0 bg-black/50",
455
+ onClick: () => C(!1)
456
+ }
457
+ ),
458
+ /* @__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: [
459
+ /* @__PURE__ */ s("div", { className: "flex items-center justify-between p-4 border-b", children: [
460
+ /* @__PURE__ */ s("div", { children: [
461
+ /* @__PURE__ */ t("h2", { className: "text-lg font-semibold", children: c.callHistory }),
462
+ /* @__PURE__ */ t("p", { className: "text-sm text-gray-500", children: y.length === 0 ? c.noCallsRegistered : `${y.length} ${c.callsRegistered}` })
463
+ ] }),
464
+ /* @__PURE__ */ t(
465
+ "button",
466
+ {
467
+ onClick: () => C(!1),
468
+ className: "h-8 w-8 flex items-center justify-center rounded-lg hover:bg-gray-100 transition-colors",
469
+ type: "button",
470
+ children: /* @__PURE__ */ t(Ce, { className: "w-5 h-5" })
471
+ }
472
+ )
473
+ ] }),
474
+ /* @__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: [
475
+ /* @__PURE__ */ t(A, { className: "w-12 h-12 mx-auto mb-2 opacity-50" }),
476
+ /* @__PURE__ */ t("p", { children: c.noCalls })
477
+ ] }) : /* @__PURE__ */ t("div", { className: "space-y-2", children: y.map((k, E) => /* @__PURE__ */ t(
478
+ Ie,
479
+ {
480
+ entry: k,
481
+ index: E,
482
+ onCall: () => {
483
+ d(k.number), C(!1), o(k.number);
484
+ }
485
+ },
486
+ k.id
487
+ )) }) })
488
+ ] }) })
489
+ ] })
490
+ ] });
491
+ }
492
+ function Ie({
493
+ entry: e,
494
+ index: f,
495
+ onCall: i
496
+ }) {
497
+ const u = () => {
498
+ switch (e.status) {
499
+ case "completed":
500
+ return /* @__PURE__ */ t(ve, { className: "w-4 h-4 text-green-600" });
501
+ case "failed":
502
+ return /* @__PURE__ */ t(ye, { className: "w-4 h-4 text-red-600" });
503
+ case "missed":
504
+ return /* @__PURE__ */ t(Y, { className: "w-4 h-4 text-yellow-600" });
505
+ }
506
+ }, d = () => {
507
+ switch (e.status) {
508
+ case "completed":
509
+ return "bg-green-100";
510
+ case "failed":
511
+ return "bg-red-100";
512
+ case "missed":
513
+ return "bg-yellow-100";
514
+ }
515
+ };
516
+ return /* @__PURE__ */ s(
517
+ "div",
518
+ {
519
+ className: "flex items-center gap-3 p-3 rounded-lg hover:bg-gray-50 transition-colors duration-200",
520
+ style: { animationDelay: `${f * 30}ms` },
521
+ children: [
522
+ /* @__PURE__ */ t("div", { className: K(
523
+ "w-9 h-9 rounded-full flex items-center justify-center shrink-0",
524
+ d()
525
+ ), children: u() }),
526
+ /* @__PURE__ */ s("div", { className: "flex-1 min-w-0", children: [
527
+ /* @__PURE__ */ t("p", { className: "font-medium text-sm truncate", children: e.number }),
528
+ /* @__PURE__ */ s("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [
529
+ /* @__PURE__ */ t("span", { children: new Date(e.timestamp).toLocaleString("es-ES", {
530
+ day: "2-digit",
531
+ month: "2-digit",
532
+ hour: "2-digit",
533
+ minute: "2-digit"
534
+ }) }),
535
+ e.duration > 0 && /* @__PURE__ */ s(se, { children: [
536
+ /* @__PURE__ */ t("span", { children: "•" }),
537
+ /* @__PURE__ */ t("span", { className: "font-mono tabular-nums", children: J(e.duration) })
538
+ ] })
539
+ ] })
540
+ ] }),
541
+ /* @__PURE__ */ t(
542
+ "button",
543
+ {
544
+ onClick: i,
545
+ className: "h-8 w-8 flex items-center justify-center shrink-0 rounded-lg hover:bg-gray-100 transition-colors",
546
+ type: "button",
547
+ children: /* @__PURE__ */ t(F, { className: "w-4 h-4" })
548
+ }
549
+ )
550
+ ]
551
+ }
552
+ );
553
+ }
554
+ function Ee({ config: e, className: f, onCallStart: i, onCallEnd: u, onStatusChange: d, labels: y }) {
555
+ return /* @__PURE__ */ t(
556
+ ge,
557
+ {
558
+ config: e,
559
+ onCallStart: i,
560
+ onCallEnd: u,
561
+ onStatusChange: d,
562
+ children: /* @__PURE__ */ t(Ne, { className: f, labels: y })
563
+ }
564
+ );
565
+ }
566
+ function He(e, f = {}) {
567
+ const {
568
+ onCallStart: i,
569
+ onCallEnd: u,
570
+ onStatusChange: d,
571
+ onConnectionChange: y,
572
+ persistHistory: h = !0,
573
+ historyKey: o = "tbi-phone-call-history"
574
+ } = f, [a, n] = v("disconnected"), [g, z] = v(""), [N, b] = v([]), [j, L] = v(0), [T, C] = v(!1), [c, I] = v("connecting"), m = $(null);
575
+ M(() => {
576
+ const l = new ce(
577
+ e,
578
+ {
579
+ onStatusChange: (H) => {
580
+ n(H), d?.(H);
581
+ },
582
+ onConnectionChange: (H) => {
583
+ I(H), (H === "connected" || H === "disconnected" || H === "failed") && C(l.state.isReady), y?.(H);
584
+ },
585
+ onCallStart: i,
586
+ onCallEnd: u,
587
+ onDurationUpdate: L,
588
+ onHistoryUpdate: b,
589
+ onRegistered: () => C(!0),
590
+ onUnregistered: () => C(!1)
591
+ },
592
+ {
593
+ persistHistory: h,
594
+ historyKey: o
595
+ }
596
+ );
597
+ 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), () => {
598
+ l.destroy(), m.current = null;
599
+ };
600
+ }, [
601
+ e.websocketUrl,
602
+ e.sipUri,
603
+ e.password,
604
+ e.registrarServer,
605
+ e.displayName,
606
+ e.authorizationUser,
607
+ h,
608
+ o
609
+ ]), M(() => {
610
+ m.current && m.current.setEvents({
611
+ onCallStart: i,
612
+ onCallEnd: u,
613
+ onStatusChange: (l) => {
614
+ n(l), d?.(l);
615
+ },
616
+ onConnectionChange: (l) => {
617
+ I(l), y?.(l);
618
+ }
619
+ });
620
+ }, [i, u, d, y]);
621
+ const k = U((l) => {
622
+ z(l), m.current?.setCallNumber(l);
623
+ }, []), E = U((l) => {
624
+ m.current?.startCall(l);
625
+ }, []), D = U(() => {
626
+ m.current?.endCall();
627
+ }, []), S = U(() => {
628
+ m.current?.clearHistory(), b([]);
629
+ }, []);
630
+ return {
631
+ status: a,
632
+ callNumber: g,
633
+ setCallNumber: k,
634
+ callHistory: N,
635
+ clearCallHistory: S,
636
+ currentCallDuration: j,
637
+ startCall: E,
638
+ endCall: D,
639
+ isReady: T,
640
+ connectionStatus: c,
641
+ ua: m.current?.ua ?? null
642
+ };
643
+ }
644
+ export {
645
+ Ee as P,
646
+ ge as a,
647
+ He as b,
648
+ pe as u
649
+ };