@tbisoftware/phone 1.0.12 → 2.0.4

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.
Files changed (48) hide show
  1. package/README.md +266 -108
  2. package/dist/components/phone.d.ts +3 -0
  3. package/dist/components/phone.d.ts.map +1 -0
  4. package/dist/context/PhoneContext.d.ts +23 -0
  5. package/dist/context/PhoneContext.d.ts.map +1 -0
  6. package/dist/core/PhoneManager.d.ts +94 -0
  7. package/dist/core/PhoneManager.d.ts.map +1 -0
  8. package/dist/core/index.cjs +1 -0
  9. package/dist/core/index.d.ts +7 -0
  10. package/dist/core/index.d.ts.map +1 -0
  11. package/dist/core/index.js +7 -0
  12. package/dist/hooks/index.d.ts +2 -0
  13. package/dist/hooks/index.d.ts.map +1 -0
  14. package/dist/hooks/usePhoneManager.d.ts +69 -0
  15. package/dist/hooks/usePhoneManager.d.ts.map +1 -0
  16. package/dist/index-Br8w8pI3.cjs +68 -0
  17. package/dist/index-TymkBND5.js +8237 -0
  18. package/dist/index.cjs +1 -68
  19. package/dist/index.d.ts +9 -1
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +11 -8616
  22. package/dist/react/Phone.d.ts +3 -0
  23. package/dist/react/Phone.d.ts.map +1 -0
  24. package/dist/react/PhoneContext.d.ts +23 -0
  25. package/dist/react/PhoneContext.d.ts.map +1 -0
  26. package/dist/react/index.cjs +1 -0
  27. package/dist/react/index.d.ts +7 -0
  28. package/dist/react/index.d.ts.map +1 -0
  29. package/dist/react/index.js +9 -0
  30. package/dist/react/usePhoneManager.d.ts +67 -0
  31. package/dist/react/usePhoneManager.d.ts.map +1 -0
  32. package/dist/types/index.d.ts +56 -0
  33. package/dist/types/index.d.ts.map +1 -0
  34. package/dist/usePhoneManager-OZM1GaNS.js +536 -0
  35. package/dist/usePhoneManager-uj2opBKT.cjs +1 -0
  36. package/dist/utils/cn.d.ts +5 -0
  37. package/dist/utils/cn.d.ts.map +1 -0
  38. package/dist/utils/formatDuration.d.ts +5 -0
  39. package/dist/utils/formatDuration.d.ts.map +1 -0
  40. package/dist/vue/index.cjs +1 -0
  41. package/dist/vue/index.d.ts +8 -0
  42. package/dist/vue/index.d.ts.map +1 -0
  43. package/dist/vue/index.js +706 -0
  44. package/dist/vue/usePhone.d.ts +59 -0
  45. package/dist/vue/usePhone.d.ts.map +1 -0
  46. package/dist/vue/usePhoneManager.d.ts +72 -0
  47. package/dist/vue/usePhoneManager.d.ts.map +1 -0
  48. package/package.json +34 -4
@@ -0,0 +1,536 @@
1
+ import { jsx as t, jsxs as o, Fragment as W } from "react/jsx-runtime";
2
+ import { useState as p, useRef as j, useEffect as I, useCallback as k, createContext as q, useContext as G } from "react";
3
+ import { J as F, d as Q, c as _, f as $, P as X } from "./index-TymkBND5.js";
4
+ let z = null, B = null;
5
+ function Y(e) {
6
+ return `${e.websocketUrl}|${e.sipUri}|${e.authorizationUser}`;
7
+ }
8
+ function Z(e) {
9
+ const m = Y(e);
10
+ if (z && B === m)
11
+ return z;
12
+ if (z && B !== m) {
13
+ try {
14
+ z.ua.stop();
15
+ } catch {
16
+ }
17
+ z = null;
18
+ }
19
+ B = m;
20
+ const i = {
21
+ sockets: [new F.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
+ }, a = new F.UA(i), g = document.createElement("audio");
30
+ g.autoplay = !0;
31
+ const h = {
32
+ ua: a,
33
+ audio: g,
34
+ isStarted: !1,
35
+ listeners: /* @__PURE__ */ new Set()
36
+ };
37
+ return a.on("connecting", () => {
38
+ h.listeners.forEach((r) => r.onConnecting?.());
39
+ }), a.on("connected", () => {
40
+ h.listeners.forEach((r) => r.onConnected?.());
41
+ }), a.on("disconnected", () => {
42
+ h.listeners.forEach((r) => r.onDisconnected?.());
43
+ }), a.on("registered", () => {
44
+ h.listeners.forEach((r) => r.onRegistered?.());
45
+ }), a.on("unregistered", () => {
46
+ h.listeners.forEach((r) => r.onUnregistered?.());
47
+ }), a.on("registrationFailed", (r) => {
48
+ h.listeners.forEach((l) => l.onRegistrationFailed?.(r?.cause));
49
+ }), a.on("newRTCSession", (r) => {
50
+ const l = r.session;
51
+ l.direction === "outgoing" && (h.listeners.forEach((d) => d.onNewSession?.(l)), l.connection && (l.connection.addEventListener("addstream", (d) => {
52
+ var x = document.createElement("audio");
53
+ d.streams !== void 0 && d.streams.length !== 0 && (x.srcObject = d.streams[0], x.play());
54
+ }), l.connection.addEventListener("track", (d) => {
55
+ var x = document.createElement("audio");
56
+ x.srcObject = d.streams[0], x.play();
57
+ })));
58
+ }), z = h, h;
59
+ }
60
+ function ee(e) {
61
+ e.isStarted || (e.ua.start(), e.isStarted = !0);
62
+ }
63
+ function te(e, m) {
64
+ e.listeners.add(m);
65
+ }
66
+ function ne(e, m) {
67
+ e.listeners.delete(m);
68
+ }
69
+ function re(e) {
70
+ return {
71
+ isReady: e.ua.isRegistered(),
72
+ isConnected: e.ua.isConnected()
73
+ };
74
+ }
75
+ const K = q(null);
76
+ function se({
77
+ config: e,
78
+ children: m,
79
+ onCallStart: u,
80
+ onCallEnd: i,
81
+ onStatusChange: a
82
+ }) {
83
+ const [g, h] = p(""), [r, l] = p("disconnected"), [d, x] = p(null), [P, N] = p(0), [s, M] = p([]), [b, f] = p(!1), [H, S] = p("connecting"), y = j(null), v = j(null), D = j(null);
84
+ I(() => {
85
+ v.current = d;
86
+ }, [d]), I(() => {
87
+ const n = Z(e);
88
+ D.current = n;
89
+ const C = re(n);
90
+ C.isReady ? (f(!0), S("connected")) : C.isConnected && S("connected");
91
+ const R = {
92
+ onConnecting: () => S("connecting"),
93
+ onConnected: () => S("connected"),
94
+ onDisconnected: () => {
95
+ S("disconnected"), f(!1);
96
+ },
97
+ onRegistered: () => {
98
+ f(!0), S("connected");
99
+ },
100
+ onUnregistered: () => f(!1),
101
+ onRegistrationFailed: (E) => {
102
+ console.error("Registration failed:", E), f(!1), S("failed");
103
+ },
104
+ onNewSession: (E) => {
105
+ y.current = E;
106
+ }
107
+ };
108
+ return te(n, R), ee(n), () => {
109
+ ne(n, R);
110
+ };
111
+ }, [e.websocketUrl, e.sipUri, e.password, e.registrarServer, e.displayName, e.authorizationUser]), I(() => {
112
+ a?.(r);
113
+ }, [r, a]), I(() => {
114
+ const n = localStorage.getItem("tbi-phone-call-history");
115
+ if (n)
116
+ try {
117
+ M(JSON.parse(n));
118
+ } catch (C) {
119
+ console.error("Error loading call history", C);
120
+ }
121
+ }, []), I(() => {
122
+ s.length > 0 && localStorage.setItem("tbi-phone-call-history", JSON.stringify(s));
123
+ }, [s]), I(() => {
124
+ if (r === "confirmed" && d) {
125
+ const n = setInterval(() => {
126
+ N(Math.floor((Date.now() - d) / 1e3));
127
+ }, 1e3);
128
+ return () => clearInterval(n);
129
+ } else
130
+ N(0);
131
+ }, [r, d]), I(() => {
132
+ const n = (C) => {
133
+ const R = C.detail.number;
134
+ r === "disconnected" && L(R);
135
+ };
136
+ return window.addEventListener("StartCallEvent", n), () => {
137
+ window.removeEventListener("StartCallEvent", n);
138
+ };
139
+ }, [r]);
140
+ const U = k((n, C, R) => {
141
+ const E = {
142
+ id: Date.now().toString(),
143
+ number: n,
144
+ timestamp: Date.now(),
145
+ duration: C,
146
+ status: R
147
+ };
148
+ M((w) => [E, ...w].slice(0, 50));
149
+ }, []), A = k(() => {
150
+ y.current && (y.current.terminate(), y.current = null);
151
+ }, []), L = k((n) => {
152
+ const C = D.current;
153
+ if (!n.trim() || !C) return;
154
+ if (!b) {
155
+ console.warn("Phone is not ready yet. Please wait for registration.");
156
+ return;
157
+ }
158
+ h(n), u?.(n);
159
+ const E = {
160
+ eventHandlers: {
161
+ progress: () => {
162
+ l("progress");
163
+ },
164
+ failed: (w) => {
165
+ console.error("Call failed:", w?.cause), l("failed"), U(n, 0, "failed"), i?.(n, 0, "failed"), y.current = null, setTimeout(() => l("disconnected"), 3e3);
166
+ },
167
+ ended: () => {
168
+ l("ended");
169
+ const w = v.current, V = w ? Math.floor((Date.now() - w) / 1e3) : 0;
170
+ U(n, V, "completed"), i?.(n, V, "completed"), y.current = null, setTimeout(() => {
171
+ l("disconnected"), x(null);
172
+ }, 2e3);
173
+ },
174
+ confirmed: () => {
175
+ l("confirmed"), x(Date.now());
176
+ }
177
+ },
178
+ mediaConstraints: { audio: !0, video: !1 }
179
+ };
180
+ l("progress");
181
+ try {
182
+ const w = C.ua.call(n, E);
183
+ y.current = w;
184
+ } catch (w) {
185
+ console.error("Failed to start call:", w), l("failed"), U(n, 0, "failed"), setTimeout(() => l("disconnected"), 3e3);
186
+ }
187
+ }, [U, u, i, b]), c = {
188
+ status: r,
189
+ callNumber: g,
190
+ setCallNumber: h,
191
+ callHistory: s,
192
+ currentCallDuration: P,
193
+ startCall: L,
194
+ endCall: A,
195
+ isReady: b,
196
+ connectionStatus: H
197
+ };
198
+ return /* @__PURE__ */ t(K.Provider, { value: c, children: m });
199
+ }
200
+ function oe() {
201
+ const e = G(K);
202
+ if (!e)
203
+ throw new Error("usePhone must be used within a PhoneProvider");
204
+ return e;
205
+ }
206
+ const O = ({ 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" }) }), ae = ({ 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" }) }), le = ({ 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" }) }), T = ({ 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" }) }), J = ({ 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" }) }), ce = ({ className: e }) => /* @__PURE__ */ o("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: [
207
+ /* @__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" }),
208
+ /* @__PURE__ */ t("path", { d: "M16 3l-5 5-2-2-1.5 1.5L11 11l6.5-6.5z" })
209
+ ] }), ie = ({ className: e }) => /* @__PURE__ */ o("svg", { className: e, viewBox: "0 0 24 24", fill: "currentColor", children: [
210
+ /* @__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" }),
211
+ /* @__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" })
212
+ ] }), de = ({ 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" }) }), ue = ({ 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" }) });
213
+ function he({ className: e, labels: m }) {
214
+ const {
215
+ status: u,
216
+ callNumber: i,
217
+ setCallNumber: a,
218
+ callHistory: g,
219
+ currentCallDuration: h,
220
+ startCall: r,
221
+ endCall: l,
222
+ isReady: d,
223
+ connectionStatus: x
224
+ } = oe(), [P, N] = p(!1), s = { ...Q, ...m }, b = (() => {
225
+ switch (u) {
226
+ case "progress":
227
+ return { text: `${s.calling}...`, color: "text-yellow-500", Icon: ae };
228
+ case "confirmed":
229
+ return { text: `${s.inCall} - ${$(h)}`, color: "text-green-500", Icon: le };
230
+ case "failed":
231
+ return { text: s.callEnded, color: "text-red-500", Icon: J };
232
+ case "ended":
233
+ return { text: s.callEnded, color: "text-gray-500", Icon: T };
234
+ default:
235
+ return { text: s.inactive, color: "text-gray-300", Icon: O };
236
+ }
237
+ })();
238
+ return /* @__PURE__ */ o("div", { className: _(
239
+ "tbi-phone w-full max-w-md mx-auto bg-white rounded-2xl shadow-lg border border-gray-200 p-2",
240
+ e
241
+ ), children: [
242
+ u === "disconnected" && /* @__PURE__ */ o("div", { className: "flex gap-2 items-center", children: [
243
+ /* @__PURE__ */ t(
244
+ "button",
245
+ {
246
+ onClick: () => N(!0),
247
+ className: "h-8 w-8 flex items-center justify-center rounded-xl border border-gray-200 hover:bg-gray-50 transition-colors",
248
+ type: "button",
249
+ children: /* @__PURE__ */ t(de, { className: "w-4 h-4" })
250
+ }
251
+ ),
252
+ /* @__PURE__ */ t(
253
+ "input",
254
+ {
255
+ type: "text",
256
+ value: i,
257
+ onChange: (f) => a(f.target.value),
258
+ onKeyDown: (f) => {
259
+ f.key === "Enter" && r(i);
260
+ },
261
+ placeholder: s.placeholder,
262
+ 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"
263
+ }
264
+ ),
265
+ /* @__PURE__ */ t(
266
+ "button",
267
+ {
268
+ onClick: () => r(i),
269
+ disabled: i.length < 9 || !d,
270
+ 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",
271
+ type: "button",
272
+ title: d ? "Call" : "Connecting...",
273
+ children: x === "connecting" ? /* @__PURE__ */ t("div", { className: "w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" }) : /* @__PURE__ */ t(O, { className: "w-4 h-4" })
274
+ }
275
+ )
276
+ ] }),
277
+ u === "progress" && /* @__PURE__ */ o("div", { className: "flex flex-col items-center gap-3 py-6", children: [
278
+ /* @__PURE__ */ o("div", { className: "relative", children: [
279
+ /* @__PURE__ */ t(b.Icon, { className: "w-12 h-12 text-yellow-500 animate-pulse" }),
280
+ /* @__PURE__ */ t("div", { className: "absolute inset-0 rounded-full border-4 border-yellow-500/30 animate-ping" })
281
+ ] }),
282
+ /* @__PURE__ */ o("div", { className: "text-center", children: [
283
+ /* @__PURE__ */ o("p", { className: "text-base font-semibold", children: [
284
+ s.calling,
285
+ " ",
286
+ i
287
+ ] }),
288
+ /* @__PURE__ */ t("p", { className: "text-sm text-gray-500", children: s.waitingResponse })
289
+ ] }),
290
+ /* @__PURE__ */ o(
291
+ "button",
292
+ {
293
+ onClick: l,
294
+ 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",
295
+ type: "button",
296
+ children: [
297
+ /* @__PURE__ */ t(T, { className: "w-4 h-4" }),
298
+ s.cancel
299
+ ]
300
+ }
301
+ )
302
+ ] }),
303
+ u === "confirmed" && /* @__PURE__ */ o("div", { className: "flex flex-col items-center gap-4 py-6", children: [
304
+ /* @__PURE__ */ o("div", { className: "relative", children: [
305
+ /* @__PURE__ */ t(b.Icon, { className: "w-12 h-12 text-green-500" }),
306
+ /* @__PURE__ */ t("div", { className: "absolute inset-0 rounded-full bg-green-500/20 animate-pulse" })
307
+ ] }),
308
+ /* @__PURE__ */ o("div", { className: "text-center space-y-1", children: [
309
+ /* @__PURE__ */ t("p", { className: "text-xl font-bold", children: i }),
310
+ /* @__PURE__ */ t("p", { className: "text-2xl font-mono text-green-600 tabular-nums", children: $(h) })
311
+ ] }),
312
+ /* @__PURE__ */ o(
313
+ "button",
314
+ {
315
+ onClick: l,
316
+ 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",
317
+ type: "button",
318
+ children: [
319
+ /* @__PURE__ */ t(T, { className: "w-4 h-4" }),
320
+ s.hangUp
321
+ ]
322
+ }
323
+ )
324
+ ] }),
325
+ (u === "failed" || u === "ended") && /* @__PURE__ */ o("div", { className: "flex flex-col items-center gap-3 py-6", children: [
326
+ /* @__PURE__ */ t(
327
+ b.Icon,
328
+ {
329
+ className: _(
330
+ "w-12 h-12",
331
+ u === "failed" ? "text-red-500" : "text-gray-500"
332
+ )
333
+ }
334
+ ),
335
+ /* @__PURE__ */ t("div", { className: "text-center", children: /* @__PURE__ */ t("p", { className: "text-base font-semibold", children: b.text }) })
336
+ ] }),
337
+ P && /* @__PURE__ */ o("div", { className: "fixed inset-0 z-50 flex", children: [
338
+ /* @__PURE__ */ t(
339
+ "div",
340
+ {
341
+ className: "fixed inset-0 bg-black/50",
342
+ onClick: () => N(!1)
343
+ }
344
+ ),
345
+ /* @__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__ */ o("div", { className: "flex flex-col h-full", children: [
346
+ /* @__PURE__ */ o("div", { className: "flex items-center justify-between p-4 border-b", children: [
347
+ /* @__PURE__ */ o("div", { children: [
348
+ /* @__PURE__ */ t("h2", { className: "text-lg font-semibold", children: s.callHistory }),
349
+ /* @__PURE__ */ t("p", { className: "text-sm text-gray-500", children: g.length === 0 ? s.noCallsRegistered : `${g.length} ${s.callsRegistered}` })
350
+ ] }),
351
+ /* @__PURE__ */ t(
352
+ "button",
353
+ {
354
+ onClick: () => N(!1),
355
+ className: "h-8 w-8 flex items-center justify-center rounded-lg hover:bg-gray-100 transition-colors",
356
+ type: "button",
357
+ children: /* @__PURE__ */ t(ue, { className: "w-5 h-5" })
358
+ }
359
+ )
360
+ ] }),
361
+ /* @__PURE__ */ t("div", { className: "flex-1 overflow-y-auto p-4", children: g.length === 0 ? /* @__PURE__ */ o("div", { className: "text-center py-12 text-gray-500", children: [
362
+ /* @__PURE__ */ t(T, { className: "w-12 h-12 mx-auto mb-2 opacity-50" }),
363
+ /* @__PURE__ */ t("p", { children: s.noCalls })
364
+ ] }) : /* @__PURE__ */ t("div", { className: "space-y-2", children: g.map((f, H) => /* @__PURE__ */ t(
365
+ me,
366
+ {
367
+ entry: f,
368
+ index: H,
369
+ onCall: () => {
370
+ a(f.number), N(!1), r(f.number);
371
+ }
372
+ },
373
+ f.id
374
+ )) }) })
375
+ ] }) })
376
+ ] })
377
+ ] });
378
+ }
379
+ function me({
380
+ entry: e,
381
+ index: m,
382
+ onCall: u
383
+ }) {
384
+ const i = () => {
385
+ switch (e.status) {
386
+ case "completed":
387
+ return /* @__PURE__ */ t(ce, { className: "w-4 h-4 text-green-600" });
388
+ case "failed":
389
+ return /* @__PURE__ */ t(ie, { className: "w-4 h-4 text-red-600" });
390
+ case "missed":
391
+ return /* @__PURE__ */ t(J, { className: "w-4 h-4 text-yellow-600" });
392
+ }
393
+ }, a = () => {
394
+ switch (e.status) {
395
+ case "completed":
396
+ return "bg-green-100";
397
+ case "failed":
398
+ return "bg-red-100";
399
+ case "missed":
400
+ return "bg-yellow-100";
401
+ }
402
+ };
403
+ return /* @__PURE__ */ o(
404
+ "div",
405
+ {
406
+ className: "flex items-center gap-3 p-3 rounded-lg hover:bg-gray-50 transition-colors duration-200",
407
+ style: { animationDelay: `${m * 30}ms` },
408
+ children: [
409
+ /* @__PURE__ */ t("div", { className: _(
410
+ "w-9 h-9 rounded-full flex items-center justify-center shrink-0",
411
+ a()
412
+ ), children: i() }),
413
+ /* @__PURE__ */ o("div", { className: "flex-1 min-w-0", children: [
414
+ /* @__PURE__ */ t("p", { className: "font-medium text-sm truncate", children: e.number }),
415
+ /* @__PURE__ */ o("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [
416
+ /* @__PURE__ */ t("span", { children: new Date(e.timestamp).toLocaleString("es-ES", {
417
+ day: "2-digit",
418
+ month: "2-digit",
419
+ hour: "2-digit",
420
+ minute: "2-digit"
421
+ }) }),
422
+ e.duration > 0 && /* @__PURE__ */ o(W, { children: [
423
+ /* @__PURE__ */ t("span", { children: "•" }),
424
+ /* @__PURE__ */ t("span", { className: "font-mono tabular-nums", children: $(e.duration) })
425
+ ] })
426
+ ] })
427
+ ] }),
428
+ /* @__PURE__ */ t(
429
+ "button",
430
+ {
431
+ onClick: u,
432
+ className: "h-8 w-8 flex items-center justify-center shrink-0 rounded-lg hover:bg-gray-100 transition-colors",
433
+ type: "button",
434
+ children: /* @__PURE__ */ t(O, { className: "w-4 h-4" })
435
+ }
436
+ )
437
+ ]
438
+ }
439
+ );
440
+ }
441
+ function xe({ config: e, className: m, onCallStart: u, onCallEnd: i, onStatusChange: a, labels: g }) {
442
+ return /* @__PURE__ */ t(
443
+ se,
444
+ {
445
+ config: e,
446
+ onCallStart: u,
447
+ onCallEnd: i,
448
+ onStatusChange: a,
449
+ children: /* @__PURE__ */ t(he, { className: m, labels: g })
450
+ }
451
+ );
452
+ }
453
+ function ve(e, m = {}) {
454
+ const {
455
+ onCallStart: u,
456
+ onCallEnd: i,
457
+ onStatusChange: a,
458
+ onConnectionChange: g,
459
+ persistHistory: h = !0,
460
+ historyKey: r = "tbi-phone-call-history"
461
+ } = m, [l, d] = p("disconnected"), [x, P] = p(""), [N, s] = p([]), [M, b] = p(0), [f, H] = p(!1), [S, y] = p("connecting"), v = j(null);
462
+ I(() => {
463
+ const c = new X(
464
+ e,
465
+ {
466
+ onStatusChange: (n) => {
467
+ d(n), a?.(n);
468
+ },
469
+ onConnectionChange: (n) => {
470
+ y(n), (n === "connected" || n === "disconnected" || n === "failed") && H(c.state.isReady), g?.(n);
471
+ },
472
+ onCallStart: u,
473
+ onCallEnd: i,
474
+ onDurationUpdate: b,
475
+ onHistoryUpdate: s,
476
+ onRegistered: () => H(!0),
477
+ onUnregistered: () => H(!1)
478
+ },
479
+ {
480
+ persistHistory: h,
481
+ historyKey: r
482
+ }
483
+ );
484
+ return c.initialize(), v.current = c, d(c.state.status), P(c.state.callNumber), s(c.state.callHistory), H(c.state.isReady), y(c.state.connectionStatus), () => {
485
+ c.destroy(), v.current = null;
486
+ };
487
+ }, [
488
+ e.websocketUrl,
489
+ e.sipUri,
490
+ e.password,
491
+ e.registrarServer,
492
+ e.displayName,
493
+ e.authorizationUser,
494
+ h,
495
+ r
496
+ ]), I(() => {
497
+ v.current && v.current.setEvents({
498
+ onCallStart: u,
499
+ onCallEnd: i,
500
+ onStatusChange: (c) => {
501
+ d(c), a?.(c);
502
+ },
503
+ onConnectionChange: (c) => {
504
+ y(c), g?.(c);
505
+ }
506
+ });
507
+ }, [u, i, a, g]);
508
+ const D = k((c) => {
509
+ P(c), v.current?.setCallNumber(c);
510
+ }, []), U = k((c) => {
511
+ v.current?.startCall(c);
512
+ }, []), A = k(() => {
513
+ v.current?.endCall();
514
+ }, []), L = k(() => {
515
+ v.current?.clearHistory(), s([]);
516
+ }, []);
517
+ return {
518
+ status: l,
519
+ callNumber: x,
520
+ setCallNumber: D,
521
+ callHistory: N,
522
+ clearCallHistory: L,
523
+ currentCallDuration: M,
524
+ startCall: U,
525
+ endCall: A,
526
+ isReady: f,
527
+ connectionStatus: S,
528
+ ua: v.current?.ua ?? null
529
+ };
530
+ }
531
+ export {
532
+ xe as P,
533
+ se as a,
534
+ ve as b,
535
+ oe as u
536
+ };
@@ -0,0 +1 @@
1
+ "use strict";const e=require("react/jsx-runtime"),s=require("react"),b=require("./index-Br8w8pI3.cjs");let P=null,L=null;function V(t){return`${t.websocketUrl}|${t.sipUri}|${t.authorizationUser}`}function F(t){const x=V(t);if(P&&L===x)return P;if(P&&L!==x){try{P.ua.stop()}catch{}P=null}L=x;const i={sockets:[new b.JsSIP.WebSocketInterface(t.websocketUrl)],uri:t.sipUri,password:t.password,registrar_server:t.registrarServer,display_name:t.displayName,authorization_user:t.authorizationUser,connection_recovery_min_interval:2,connection_recovery_max_interval:30},o=new b.JsSIP.UA(i),f=document.createElement("audio");f.autoplay=!0;const h={ua:o,audio:f,isStarted:!1,listeners:new Set};return o.on("connecting",()=>{h.listeners.forEach(r=>r.onConnecting?.())}),o.on("connected",()=>{h.listeners.forEach(r=>r.onConnected?.())}),o.on("disconnected",()=>{h.listeners.forEach(r=>r.onDisconnected?.())}),o.on("registered",()=>{h.listeners.forEach(r=>r.onRegistered?.())}),o.on("unregistered",()=>{h.listeners.forEach(r=>r.onUnregistered?.())}),o.on("registrationFailed",r=>{h.listeners.forEach(l=>l.onRegistrationFailed?.(r?.cause))}),o.on("newRTCSession",r=>{const l=r.session;l.direction==="outgoing"&&(h.listeners.forEach(d=>d.onNewSession?.(l)),l.connection&&(l.connection.addEventListener("addstream",d=>{var g=document.createElement("audio");d.streams!==void 0&&d.streams.length!==0&&(g.srcObject=d.streams[0],g.play())}),l.connection.addEventListener("track",d=>{var g=document.createElement("audio");g.srcObject=d.streams[0],g.play()})))}),P=h,h}function K(t){t.isStarted||(t.ua.start(),t.isStarted=!0)}function J(t,x){t.listeners.add(x)}function q(t,x){t.listeners.delete(x)}function W(t){return{isReady:t.ua.isRegistered(),isConnected:t.ua.isConnected()}}const B=s.createContext(null);function _({config:t,children:x,onCallStart:u,onCallEnd:i,onStatusChange:o}){const[f,h]=s.useState(""),[r,l]=s.useState("disconnected"),[d,g]=s.useState(null),[k,w]=s.useState(0),[a,H]=s.useState([]),[j,m]=s.useState(!1),[S,N]=s.useState("connecting"),v=s.useRef(null),p=s.useRef(null),U=s.useRef(null);s.useEffect(()=>{p.current=d},[d]),s.useEffect(()=>{const n=F(t);U.current=n;const y=W(n);y.isReady?(m(!0),N("connected")):y.isConnected&&N("connected");const I={onConnecting:()=>N("connecting"),onConnected:()=>N("connected"),onDisconnected:()=>{N("disconnected"),m(!1)},onRegistered:()=>{m(!0),N("connected")},onUnregistered:()=>m(!1),onRegistrationFailed:E=>{console.error("Registration failed:",E),m(!1),N("failed")},onNewSession:E=>{v.current=E}};return J(n,I),K(n),()=>{q(n,I)}},[t.websocketUrl,t.sipUri,t.password,t.registrarServer,t.displayName,t.authorizationUser]),s.useEffect(()=>{o?.(r)},[r,o]),s.useEffect(()=>{const n=localStorage.getItem("tbi-phone-call-history");if(n)try{H(JSON.parse(n))}catch(y){console.error("Error loading call history",y)}},[]),s.useEffect(()=>{a.length>0&&localStorage.setItem("tbi-phone-call-history",JSON.stringify(a))},[a]),s.useEffect(()=>{if(r==="confirmed"&&d){const n=setInterval(()=>{w(Math.floor((Date.now()-d)/1e3))},1e3);return()=>clearInterval(n)}else w(0)},[r,d]),s.useEffect(()=>{const n=y=>{const I=y.detail.number;r==="disconnected"&&z(I)};return window.addEventListener("StartCallEvent",n),()=>{window.removeEventListener("StartCallEvent",n)}},[r]);const R=s.useCallback((n,y,I)=>{const E={id:Date.now().toString(),number:n,timestamp:Date.now(),duration:y,status:I};H(C=>[E,...C].slice(0,50))},[]),M=s.useCallback(()=>{v.current&&(v.current.terminate(),v.current=null)},[]),z=s.useCallback(n=>{const y=U.current;if(!n.trim()||!y)return;if(!j){console.warn("Phone is not ready yet. Please wait for registration.");return}h(n),u?.(n);const E={eventHandlers:{progress:()=>{l("progress")},failed:C=>{console.error("Call failed:",C?.cause),l("failed"),R(n,0,"failed"),i?.(n,0,"failed"),v.current=null,setTimeout(()=>l("disconnected"),3e3)},ended:()=>{l("ended");const C=p.current,A=C?Math.floor((Date.now()-C)/1e3):0;R(n,A,"completed"),i?.(n,A,"completed"),v.current=null,setTimeout(()=>{l("disconnected"),g(null)},2e3)},confirmed:()=>{l("confirmed"),g(Date.now())}},mediaConstraints:{audio:!0,video:!1}};l("progress");try{const C=y.ua.call(n,E);v.current=C}catch(C){console.error("Failed to start call:",C),l("failed"),R(n,0,"failed"),setTimeout(()=>l("disconnected"),3e3)}},[R,u,i,j]),c={status:r,callNumber:f,setCallNumber:h,callHistory:a,currentCallDuration:k,startCall:z,endCall:M,isReady:j,connectionStatus:S};return e.jsx(B.Provider,{value:c,children:x})}function $(){const t=s.useContext(B);if(!t)throw new Error("usePhone must be used within a PhoneProvider");return t}const T=({className:t})=>e.jsx("svg",{className:t,viewBox:"0 0 24 24",fill:"currentColor",children:e.jsx("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"})}),G=({className:t})=>e.jsx("svg",{className:t,viewBox:"0 0 24 24",fill:"currentColor",children:e.jsx("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"})}),Q=({className:t})=>e.jsx("svg",{className:t,viewBox:"0 0 24 24",fill:"currentColor",children:e.jsx("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"})}),D=({className:t})=>e.jsx("svg",{className:t,viewBox:"0 0 24 24",fill:"currentColor",children:e.jsx("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"})}),O=({className:t})=>e.jsx("svg",{className:t,viewBox:"0 0 24 24",fill:"currentColor",children:e.jsx("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"})}),X=({className:t})=>e.jsxs("svg",{className:t,viewBox:"0 0 24 24",fill:"currentColor",children:[e.jsx("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"}),e.jsx("path",{d:"M16 3l-5 5-2-2-1.5 1.5L11 11l6.5-6.5z"})]}),Y=({className:t})=>e.jsxs("svg",{className:t,viewBox:"0 0 24 24",fill:"currentColor",children:[e.jsx("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"}),e.jsx("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"})]}),Z=({className:t})=>e.jsx("svg",{className:t,viewBox:"0 0 24 24",fill:"currentColor",children:e.jsx("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"})}),ee=({className:t})=>e.jsx("svg",{className:t,viewBox:"0 0 24 24",fill:"currentColor",children:e.jsx("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"})});function te({className:t,labels:x}){const{status:u,callNumber:i,setCallNumber:o,callHistory:f,currentCallDuration:h,startCall:r,endCall:l,isReady:d,connectionStatus:g}=$(),[k,w]=s.useState(!1),a={...b.defaultLabels,...x},j=(()=>{switch(u){case"progress":return{text:`${a.calling}...`,color:"text-yellow-500",Icon:G};case"confirmed":return{text:`${a.inCall} - ${b.formatDuration(h)}`,color:"text-green-500",Icon:Q};case"failed":return{text:a.callEnded,color:"text-red-500",Icon:O};case"ended":return{text:a.callEnded,color:"text-gray-500",Icon:D};default:return{text:a.inactive,color:"text-gray-300",Icon:T}}})();return e.jsxs("div",{className:b.cn("tbi-phone w-full max-w-md mx-auto bg-white rounded-2xl shadow-lg border border-gray-200 p-2",t),children:[u==="disconnected"&&e.jsxs("div",{className:"flex gap-2 items-center",children:[e.jsx("button",{onClick:()=>w(!0),className:"h-8 w-8 flex items-center justify-center rounded-xl border border-gray-200 hover:bg-gray-50 transition-colors",type:"button",children:e.jsx(Z,{className:"w-4 h-4"})}),e.jsx("input",{type:"text",value:i,onChange:m=>o(m.target.value),onKeyDown:m=>{m.key==="Enter"&&r(i)},placeholder:a.placeholder,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"}),e.jsx("button",{onClick:()=>r(i),disabled:i.length<9||!d,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",type:"button",title:d?"Call":"Connecting...",children:g==="connecting"?e.jsx("div",{className:"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"}):e.jsx(T,{className:"w-4 h-4"})})]}),u==="progress"&&e.jsxs("div",{className:"flex flex-col items-center gap-3 py-6",children:[e.jsxs("div",{className:"relative",children:[e.jsx(j.Icon,{className:"w-12 h-12 text-yellow-500 animate-pulse"}),e.jsx("div",{className:"absolute inset-0 rounded-full border-4 border-yellow-500/30 animate-ping"})]}),e.jsxs("div",{className:"text-center",children:[e.jsxs("p",{className:"text-base font-semibold",children:[a.calling," ",i]}),e.jsx("p",{className:"text-sm text-gray-500",children:a.waitingResponse})]}),e.jsxs("button",{onClick:l,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",type:"button",children:[e.jsx(D,{className:"w-4 h-4"}),a.cancel]})]}),u==="confirmed"&&e.jsxs("div",{className:"flex flex-col items-center gap-4 py-6",children:[e.jsxs("div",{className:"relative",children:[e.jsx(j.Icon,{className:"w-12 h-12 text-green-500"}),e.jsx("div",{className:"absolute inset-0 rounded-full bg-green-500/20 animate-pulse"})]}),e.jsxs("div",{className:"text-center space-y-1",children:[e.jsx("p",{className:"text-xl font-bold",children:i}),e.jsx("p",{className:"text-2xl font-mono text-green-600 tabular-nums",children:b.formatDuration(h)})]}),e.jsxs("button",{onClick:l,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",type:"button",children:[e.jsx(D,{className:"w-4 h-4"}),a.hangUp]})]}),(u==="failed"||u==="ended")&&e.jsxs("div",{className:"flex flex-col items-center gap-3 py-6",children:[e.jsx(j.Icon,{className:b.cn("w-12 h-12",u==="failed"?"text-red-500":"text-gray-500")}),e.jsx("div",{className:"text-center",children:e.jsx("p",{className:"text-base font-semibold",children:j.text})})]}),k&&e.jsxs("div",{className:"fixed inset-0 z-50 flex",children:[e.jsx("div",{className:"fixed inset-0 bg-black/50",onClick:()=>w(!1)}),e.jsx("div",{className:"fixed right-0 top-0 h-full w-full max-w-md bg-white shadow-xl",style:{backgroundColor:"white"},children:e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"flex items-center justify-between p-4 border-b",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold",children:a.callHistory}),e.jsx("p",{className:"text-sm text-gray-500",children:f.length===0?a.noCallsRegistered:`${f.length} ${a.callsRegistered}`})]}),e.jsx("button",{onClick:()=>w(!1),className:"h-8 w-8 flex items-center justify-center rounded-lg hover:bg-gray-100 transition-colors",type:"button",children:e.jsx(ee,{className:"w-5 h-5"})})]}),e.jsx("div",{className:"flex-1 overflow-y-auto p-4",children:f.length===0?e.jsxs("div",{className:"text-center py-12 text-gray-500",children:[e.jsx(D,{className:"w-12 h-12 mx-auto mb-2 opacity-50"}),e.jsx("p",{children:a.noCalls})]}):e.jsx("div",{className:"space-y-2",children:f.map((m,S)=>e.jsx(se,{entry:m,index:S,onCall:()=>{o(m.number),w(!1),r(m.number)}},m.id))})})]})})]})]})}function se({entry:t,index:x,onCall:u}){const i=()=>{switch(t.status){case"completed":return e.jsx(X,{className:"w-4 h-4 text-green-600"});case"failed":return e.jsx(Y,{className:"w-4 h-4 text-red-600"});case"missed":return e.jsx(O,{className:"w-4 h-4 text-yellow-600"})}},o=()=>{switch(t.status){case"completed":return"bg-green-100";case"failed":return"bg-red-100";case"missed":return"bg-yellow-100"}};return e.jsxs("div",{className:"flex items-center gap-3 p-3 rounded-lg hover:bg-gray-50 transition-colors duration-200",style:{animationDelay:`${x*30}ms`},children:[e.jsx("div",{className:b.cn("w-9 h-9 rounded-full flex items-center justify-center shrink-0",o()),children:i()}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"font-medium text-sm truncate",children:t.number}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-gray-500",children:[e.jsx("span",{children:new Date(t.timestamp).toLocaleString("es-ES",{day:"2-digit",month:"2-digit",hour:"2-digit",minute:"2-digit"})}),t.duration>0&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"•"}),e.jsx("span",{className:"font-mono tabular-nums",children:b.formatDuration(t.duration)})]})]})]}),e.jsx("button",{onClick:u,className:"h-8 w-8 flex items-center justify-center shrink-0 rounded-lg hover:bg-gray-100 transition-colors",type:"button",children:e.jsx(T,{className:"w-4 h-4"})})]})}function ne({config:t,className:x,onCallStart:u,onCallEnd:i,onStatusChange:o,labels:f}){return e.jsx(_,{config:t,onCallStart:u,onCallEnd:i,onStatusChange:o,children:e.jsx(te,{className:x,labels:f})})}function re(t,x={}){const{onCallStart:u,onCallEnd:i,onStatusChange:o,onConnectionChange:f,persistHistory:h=!0,historyKey:r="tbi-phone-call-history"}=x,[l,d]=s.useState("disconnected"),[g,k]=s.useState(""),[w,a]=s.useState([]),[H,j]=s.useState(0),[m,S]=s.useState(!1),[N,v]=s.useState("connecting"),p=s.useRef(null);s.useEffect(()=>{const c=new b.PhoneManager(t,{onStatusChange:n=>{d(n),o?.(n)},onConnectionChange:n=>{v(n),(n==="connected"||n==="disconnected"||n==="failed")&&S(c.state.isReady),f?.(n)},onCallStart:u,onCallEnd:i,onDurationUpdate:j,onHistoryUpdate:a,onRegistered:()=>S(!0),onUnregistered:()=>S(!1)},{persistHistory:h,historyKey:r});return c.initialize(),p.current=c,d(c.state.status),k(c.state.callNumber),a(c.state.callHistory),S(c.state.isReady),v(c.state.connectionStatus),()=>{c.destroy(),p.current=null}},[t.websocketUrl,t.sipUri,t.password,t.registrarServer,t.displayName,t.authorizationUser,h,r]),s.useEffect(()=>{p.current&&p.current.setEvents({onCallStart:u,onCallEnd:i,onStatusChange:c=>{d(c),o?.(c)},onConnectionChange:c=>{v(c),f?.(c)}})},[u,i,o,f]);const U=s.useCallback(c=>{k(c),p.current?.setCallNumber(c)},[]),R=s.useCallback(c=>{p.current?.startCall(c)},[]),M=s.useCallback(()=>{p.current?.endCall()},[]),z=s.useCallback(()=>{p.current?.clearHistory(),a([])},[]);return{status:l,callNumber:g,setCallNumber:U,callHistory:w,clearCallHistory:z,currentCallDuration:H,startCall:R,endCall:M,isReady:m,connectionStatus:N,ua:p.current?.ua??null}}exports.Phone=ne;exports.PhoneProvider=_;exports.usePhone=$;exports.usePhoneManager=re;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Simple utility to merge class names
3
+ */
4
+ export declare function cn(...classes: (string | undefined | null | false)[]): string;
5
+ //# sourceMappingURL=cn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../src/utils/cn.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,KAAK,CAAC,EAAE,GAAG,MAAM,CAE5E"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Formats a duration in seconds to a human-readable string (HH:MM:SS or MM:SS)
3
+ */
4
+ export declare function formatDuration(seconds: number): string;
5
+ //# sourceMappingURL=formatDuration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatDuration.d.ts","sourceRoot":"","sources":["../../src/utils/formatDuration.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAStD"}