@bravophone/webphone 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,31 +1,31 @@
1
- const Z = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"', me = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
1
+ const Z = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"', fe = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
2
2
  <path class="bp-i-body" d="M15.6 12.8a11 11 0 0 1-4.4-4.4l1-1a1.6 1.6 0 0 0 .3-1.7c-.2-.7-.4-1.4-.5-2.2A1.6 1.6 0 0 0 10.4 2H7.9a1.6 1.6 0 0 0-1.6 1.8 15.8 15.8 0 0 0 2.4 6.9 15.6 15.6 0 0 0 4.8 4.8 15.8 15.8 0 0 0 6.9 2.4 1.6 1.6 0 0 0 1.7-1.6v-2.5a1.6 1.6 0 0 0-1.4-1.6c-.8-.1-1.5-.3-2.2-.5a1.6 1.6 0 0 0-1.7.4z"/>
3
3
  <path class="bp-i-wave bp-i-wave-1" d="M14.5 6.2a4 4 0 0 1 3.3 3.3"/>
4
4
  <path class="bp-i-wave bp-i-wave-2" d="M14.1 2.6a7.6 7.6 0 0 1 7.3 7.3"/>
5
- </svg>`, fe = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
5
+ </svg>`, xe = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
6
6
  <path class="bp-i-bar bp-i-bar-1" d="M4 10v4"/>
7
7
  <path class="bp-i-bar bp-i-bar-2" d="M8.7 6.5v11"/>
8
8
  <path class="bp-i-bar bp-i-bar-3" d="M12 3.5v17"/>
9
9
  <path class="bp-i-bar bp-i-bar-4" d="M15.3 6.5v11"/>
10
10
  <path class="bp-i-bar bp-i-bar-5" d="M20 10v4"/>
11
- </svg>`, xe = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
11
+ </svg>`, we = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
12
12
  <path class="bp-i-body" d="M4 13v-1a8 8 0 0 1 16 0v1"/>
13
13
  <path class="bp-i-body" d="M20 14.5v2a3.5 3.5 0 0 1-3.5 3.5H13"/>
14
14
  <rect class="bp-i-cup" x="1.6" y="12.6" width="4.4" height="6.4" rx="1.8"/>
15
15
  <rect class="bp-i-cup" x="18" y="12.6" width="4.4" height="6.4" rx="1.8"/>
16
- </svg>`, we = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
16
+ </svg>`, ye = `<svg viewBox="0 0 24 24" fill="none" ${Z} aria-hidden="true">
17
17
  <path class="bp-i-body" d="M21 11.5a8.4 8.4 0 0 1-9 8.4 9 9 0 0 1-2.9-.5L3 21.5l1.5-4.6A8.4 8.4 0 0 1 12 3.1a8.4 8.4 0 0 1 9 8.4z"/>
18
18
  <path class="bp-i-hand" d="M14.6 14.4a6.5 6.5 0 0 1-3.2-3.2l.7-.7a1 1 0 0 0 .2-1.1 6 6 0 0 1-.3-1.2 1 1 0 0 0-1-.8H9.6a1 1 0 0 0-1 1.1 9.6 9.6 0 0 0 4.8 7.2 1 1 0 0 0 1.4-.9v-1.2a1 1 0 0 0-.8-1z"/>
19
- </svg>`, ye = `<svg viewBox="0 0 10 16" width="10" height="16" fill="currentColor" aria-hidden="true">
19
+ </svg>`, ve = `<svg viewBox="0 0 10 16" width="10" height="16" fill="currentColor" aria-hidden="true">
20
20
  <circle cx="2.6" cy="2.6" r="1.35"/><circle cx="7.4" cy="2.6" r="1.35"/>
21
21
  <circle cx="2.6" cy="8" r="1.35"/><circle cx="7.4" cy="8" r="1.35"/>
22
22
  <circle cx="2.6" cy="13.4" r="1.35"/><circle cx="7.4" cy="13.4" r="1.35"/>
23
23
  </svg>`, J = {
24
- "phone-waves": me,
25
- waveform: fe,
26
- headset: xe,
27
- "chat-phone": we
28
- }, te = "phone-waves", ve = `
24
+ "phone-waves": fe,
25
+ waveform: xe,
26
+ headset: we,
27
+ "chat-phone": ye
28
+ }, ae = "phone-waves", ke = `
29
29
  .bp-launcher-icon svg { width: 100%; height: 100%; display: block; overflow: visible; }
30
30
 
31
31
  /* Ponto de status no canto do ícone — verde registrado, cinza sem linha. */
@@ -95,7 +95,7 @@ const Z = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
95
95
  .bp-i-wave, .bp-i-body, .bp-i-hand, .bp-i-bar { animation: none !important; }
96
96
  .bp-launcher-icon { transition: none; }
97
97
  }
98
- `, ke = `
98
+ `, Me = `
99
99
  :host { all: initial; }
100
100
  * { box-sizing: border-box; }
101
101
 
@@ -227,6 +227,21 @@ const Z = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
227
227
  /* Uma janela docada nao se redimensiona pelas bordas coladas na viewport. */
228
228
  .bp-root.bp-docked { border-radius: 0; }
229
229
 
230
+ /* ---- destaque: "a janela esta aqui" ----
231
+ Disparado ao clicar na aba com o webphone ja aberto. Um halo que cresce e
232
+ some, no lugar de um shake: em interface, tremer significa erro ou acao
233
+ negada (senha errada), e aqui nada deu errado. */
234
+ @keyframes bp-attention {
235
+ 0% { box-shadow: 0 12px 40px rgba(0,0,0,.45), 0 0 0 0 rgba(124,108,245,.55); }
236
+ 55% { box-shadow: 0 12px 40px rgba(0,0,0,.45), 0 0 0 12px rgba(124,108,245,0); }
237
+ 100% { box-shadow: 0 12px 40px rgba(0,0,0,.45), 0 0 0 0 rgba(124,108,245,0); }
238
+ }
239
+ .bp-root.bp-attention { animation: bp-attention .85s ease-out 2; }
240
+
241
+ @media (prefers-reduced-motion: reduce) {
242
+ .bp-root.bp-attention { animation: none; outline: 2px solid #7c6cf5; outline-offset: 2px; }
243
+ }
244
+
230
245
  /* ---- previa de encaixe (docking) ----
231
246
  Fantasma que mostra onde a janela vai parar antes de soltar. */
232
247
  .bp-preview {
@@ -244,7 +259,9 @@ const Z = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
244
259
  .bp-launcher {
245
260
  position: fixed;
246
261
  top: 50%;
247
- z-index: 2147482999;
262
+ /* Acima da janela (2147483000): a aba nunca some, e uma janela docada na
263
+ mesma borda a esconderia. */
264
+ z-index: 2147483001;
248
265
  display: flex;
249
266
  align-items: center;
250
267
  gap: 0;
@@ -341,25 +358,25 @@ const Z = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
341
358
  .bp-launcher[data-badge]:not([data-badge=""]) { animation: none; }
342
359
  }
343
360
 
344
- ${ve}
345
- `, ue = "bravophone:widget:geometry", V = 28, X = 32;
346
- function Me(e) {
361
+ ${ke}
362
+ `, ge = "bravophone:widget:geometry", V = 28, X = 32;
363
+ function Le(e) {
347
364
  try {
348
- const a = localStorage.getItem(ue);
365
+ const a = localStorage.getItem(ge);
349
366
  if (!a) return { ...e };
350
- const n = JSON.parse(a);
351
- return n.dock ? { ...e, ...n, ...U(n.dock, n) } : { ...e, ...n };
367
+ const i = JSON.parse(a);
368
+ return i.dock ? { ...e, ...i, ...P(i.dock, i) } : { ...e, ...i };
352
369
  } catch (a) {
353
370
  return { ...e };
354
371
  }
355
372
  }
356
373
  function K(e) {
357
374
  try {
358
- localStorage.setItem(ue, JSON.stringify(e));
375
+ localStorage.setItem(ge, JSON.stringify(e));
359
376
  } catch (a) {
360
377
  }
361
378
  }
362
- function he(e) {
379
+ function le(e) {
363
380
  return {
364
381
  minWidth: e.minWidth,
365
382
  minHeight: e.minHeight,
@@ -370,144 +387,144 @@ function he(e) {
370
387
  };
371
388
  }
372
389
  function R(e) {
373
- const a = Math.max(0, window.innerWidth - e.width), n = Math.max(0, window.innerHeight - 40);
390
+ const a = Math.max(0, window.innerWidth - e.width), i = Math.max(0, window.innerHeight - 40);
374
391
  return {
375
392
  ...e,
376
393
  x: Math.min(Math.max(0, e.x), a),
377
- y: Math.min(Math.max(0, e.y), n)
394
+ y: Math.min(Math.max(0, e.y), i)
378
395
  };
379
396
  }
380
- function U(e, a) {
381
- const n = window.innerWidth, o = window.innerHeight, i = Math.round(n / 2), s = Math.round(o / 2), u = Math.min(a.width, n);
397
+ function P(e, a) {
398
+ const i = window.innerWidth, o = window.innerHeight, r = Math.round(i / 2), d = Math.round(o / 2), u = Math.min(a.width, i);
382
399
  switch (e) {
383
400
  case "left":
384
401
  return { x: 0, y: 0, width: u, height: o };
385
402
  case "right":
386
- return { x: n - u, y: 0, width: u, height: o };
403
+ return { x: i - u, y: 0, width: u, height: o };
387
404
  case "left-half":
388
- return { x: 0, y: 0, width: i, height: o };
405
+ return { x: 0, y: 0, width: r, height: o };
389
406
  case "right-half":
390
- return { x: n - i, y: 0, width: i, height: o };
407
+ return { x: i - r, y: 0, width: r, height: o };
391
408
  case "top":
392
- return { x: a.x, y: 0, width: u, height: s };
409
+ return { x: a.x, y: 0, width: u, height: d };
393
410
  case "bottom":
394
- return { x: a.x, y: o - s, width: u, height: s };
411
+ return { x: a.x, y: o - d, width: u, height: d };
395
412
  case "top-half":
396
- return { x: 0, y: 0, width: n, height: s };
413
+ return { x: 0, y: 0, width: i, height: d };
397
414
  case "bottom-half":
398
- return { x: 0, y: o - s, width: n, height: s };
415
+ return { x: 0, y: o - d, width: i, height: d };
399
416
  case "max":
400
- return { x: 0, y: 0, width: n, height: o };
417
+ return { x: 0, y: 0, width: i, height: o };
401
418
  default:
402
419
  return { x: a.x, y: a.y, width: a.width, height: a.height };
403
420
  }
404
421
  }
405
- function ze(e, a, n) {
406
- const o = window.innerWidth, i = window.innerHeight, s = e <= V, u = e >= o - V, m = a <= V, t = a >= i - V;
407
- return (m || t) && s ? "left-half" : (m || t) && u ? "right-half" : m ? n || "max" : t ? "bottom-half" : s ? "left" : u ? "right" : null;
422
+ function ze(e, a, i) {
423
+ const o = window.innerWidth, r = window.innerHeight, d = e <= V, u = e >= o - V, f = a <= V, t = a >= r - V;
424
+ return (f || t) && d ? "left-half" : (f || t) && u ? "right-half" : f ? i || "max" : t ? "bottom-half" : d ? "left" : u ? "right" : null;
408
425
  }
409
- function Le({ root: e, handle: a, handles: n, preview: o, geometry: i, limits: s, topDock: u, onChange: m }) {
410
- let t = { ...i }, g = null, p = "", d = null, l = null, x = null, y = null;
411
- const M = () => {
412
- e.style.left = `${t.x}px`, e.style.top = `${t.y}px`, e.style.width = `${t.width}px`, e.style.height = `${t.height}px`, e.classList.toggle("bp-docked", !!t.dock), m == null || m(t);
413
- }, W = (r) => {
426
+ function Se({ root: e, handle: a, handles: i, preview: o, geometry: r, limits: d, topDock: u, onChange: f }) {
427
+ let t = { ...r }, g = null, p = "", c = null, l = null, x = null, w = null;
428
+ const z = () => {
429
+ e.style.left = `${t.x}px`, e.style.top = `${t.y}px`, e.style.width = `${t.width}px`, e.style.height = `${t.height}px`, e.classList.toggle("bp-docked", !!t.dock), f == null || f(t);
430
+ }, C = (n) => {
414
431
  if (o) {
415
- if (!r) {
432
+ if (!n) {
416
433
  o.hidden = !0;
417
434
  return;
418
435
  }
419
- o.hidden = !1, o.style.left = `${r.x}px`, o.style.top = `${r.y}px`, o.style.width = `${r.width}px`, o.style.height = `${r.height}px`;
436
+ o.hidden = !1, o.style.left = `${n.x}px`, o.style.top = `${n.y}px`, o.style.width = `${n.width}px`, o.style.height = `${n.height}px`;
420
437
  }
421
- }, $ = (r, b) => {
422
- const h = he(s);
423
- let { x: v, y: z, width: L, height: H } = d;
424
- p.includes("e") && (L = d.width + r), p.includes("w") && (L = d.width - r), p.includes("s") && (H = d.height + b), p.includes("n") && (H = d.height - b), L = Math.min(h.maxWidth, Math.max(h.minWidth, L)), H = Math.min(h.maxHeight, Math.max(h.minHeight, H)), p.includes("w") && (v = d.x + (d.width - L)), p.includes("n") && (z = d.y + (d.height - H)), p.includes("e") && Math.abs(v + L - window.innerWidth) <= X && (L = window.innerWidth - v), p.includes("w") && Math.abs(v) <= X && (L += v, v = 0), p.includes("s") && Math.abs(z + H - window.innerHeight) <= X && (H = window.innerHeight - z), p.includes("n") && Math.abs(z) <= X && (H += z, z = 0), t = { ...t, x: v, y: z, width: L, height: H, dock: null }, M();
425
- }, j = (r, b, h, v) => {
438
+ }, $ = (n, b) => {
439
+ const h = le(d);
440
+ let { x: v, y: S, width: E, height: H } = c;
441
+ p.includes("e") && (E = c.width + n), p.includes("w") && (E = c.width - n), p.includes("s") && (H = c.height + b), p.includes("n") && (H = c.height - b), E = Math.min(h.maxWidth, Math.max(h.minWidth, E)), H = Math.min(h.maxHeight, Math.max(h.minHeight, H)), p.includes("w") && (v = c.x + (c.width - E)), p.includes("n") && (S = c.y + (c.height - H)), p.includes("e") && Math.abs(v + E - window.innerWidth) <= X && (E = window.innerWidth - v), p.includes("w") && Math.abs(v) <= X && (E += v, v = 0), p.includes("s") && Math.abs(S + H - window.innerHeight) <= X && (H = window.innerHeight - S), p.includes("n") && Math.abs(S) <= X && (H += S, S = 0), t = { ...t, x: v, y: S, width: E, height: H, dock: null }, z();
442
+ }, j = (n, b, h, v) => {
426
443
  if (t.dock) {
427
- const z = y || { width: s.width, height: s.height }, L = l.x / Math.max(1, t.width);
428
- t = { ...t, ...z, dock: null }, l = { x: Math.round(z.width * L), y: Math.min(l.y, 32) }, d = {
429
- ...d,
444
+ const S = w || { width: d.width, height: d.height }, E = l.x / Math.max(1, t.width);
445
+ t = { ...t, ...S, dock: null }, l = { x: Math.round(S.width * E), y: Math.min(l.y, 32) }, c = {
446
+ ...c,
430
447
  x: h - l.x,
431
448
  y: v - l.y,
432
- px: d.px + r,
433
- py: d.py + b
434
- }, r = 0, b = 0;
449
+ px: c.px + n,
450
+ py: c.py + b
451
+ }, n = 0, b = 0;
435
452
  }
436
- t = R({ ...t, x: d.x + r, y: d.y + b }), M(), x = ze(h, v, u), W(x ? U(x, t) : null);
453
+ t = R({ ...t, x: c.x + n, y: c.y + b }), z(), x = ze(h, v, u), C(x ? P(x, t) : null);
437
454
  }, _ = () => {
438
- x && (y = y || { width: t.width, height: t.height }, t = { ...t, ...U(x, t), dock: x }, M());
439
- }, G = (r, b) => (h) => {
440
- h.button === 0 && (r === "drag" && h.target.closest(".bp-btn") || (g = r, p = b || "", d = { px: h.clientX, py: h.clientY, ...t }, l = { x: h.clientX - t.x, y: h.clientY - t.y }, t.dock || (y = { width: t.width, height: t.height }), e.classList.add(r === "drag" ? "bp-dragging" : "bp-resizing"), h.currentTarget.setPointerCapture(h.pointerId), h.preventDefault()));
441
- }, D = (r) => {
442
- if (!g || !d) return;
443
- const b = r.clientX - d.px, h = r.clientY - d.py;
444
- g === "drag" ? j(b, h, r.clientX, r.clientY) : $(b, h);
445
- }, B = (r) => {
455
+ x && (w = w || { width: t.width, height: t.height }, t = { ...t, ...P(x, t), dock: x }, z());
456
+ }, F = (n, b) => (h) => {
457
+ h.button === 0 && (n === "drag" && h.target.closest(".bp-btn") || (g = n, p = b || "", c = { px: h.clientX, py: h.clientY, ...t }, l = { x: h.clientX - t.x, y: h.clientY - t.y }, t.dock || (w = { width: t.width, height: t.height }), e.classList.add(n === "drag" ? "bp-dragging" : "bp-resizing"), h.currentTarget.setPointerCapture(h.pointerId), h.preventDefault()));
458
+ }, A = (n) => {
459
+ if (!g || !c) return;
460
+ const b = n.clientX - c.px, h = n.clientY - c.py;
461
+ g === "drag" ? j(b, h, n.clientX, n.clientY) : $(b, h);
462
+ }, B = (n) => {
446
463
  if (g) {
447
- e.classList.remove("bp-dragging", "bp-resizing"), W(null), g === "drag" && _(), g = null, p = "", d = null, x = null;
464
+ e.classList.remove("bp-dragging", "bp-resizing"), C(null), g === "drag" && _(), g = null, p = "", c = null, x = null;
448
465
  try {
449
- r.currentTarget.releasePointerCapture(r.pointerId);
466
+ n.currentTarget.releasePointerCapture(n.pointerId);
450
467
  } catch (b) {
451
468
  }
452
469
  K(t);
453
470
  }
454
471
  };
455
- a.addEventListener("pointerdown", G("drag")), a.addEventListener("pointermove", D), a.addEventListener("pointerup", B), a.addEventListener("pointercancel", B), (n || []).forEach(({ el: r, dir: b }) => {
456
- r.addEventListener("pointerdown", G("resize", b)), r.addEventListener("pointermove", D), r.addEventListener("pointerup", B), r.addEventListener("pointercancel", B);
472
+ a.addEventListener("pointerdown", F("drag")), a.addEventListener("pointermove", A), a.addEventListener("pointerup", B), a.addEventListener("pointercancel", B), (i || []).forEach(({ el: n, dir: b }) => {
473
+ n.addEventListener("pointerdown", F("resize", b)), n.addEventListener("pointermove", A), n.addEventListener("pointerup", B), n.addEventListener("pointercancel", B);
457
474
  });
458
- const P = () => {
459
- t = t.dock ? { ...t, ...U(t.dock, t) } : R(t), M();
475
+ const U = () => {
476
+ t = t.dock ? { ...t, ...P(t.dock, t) } : R(t), z();
460
477
  };
461
- window.addEventListener("resize", P);
462
- const Y = {
463
- start(r) {
478
+ window.addEventListener("resize", U);
479
+ const G = {
480
+ start(n) {
464
481
  var b, h;
465
- g = "drag", d = { px: r.x, py: r.y, ...t }, l = { x: (b = r.cx) != null ? b : t.width / 2, y: (h = r.cy) != null ? h : 20 }, t.dock || (y = { width: t.width, height: t.height }), e.classList.add("bp-dragging");
482
+ g = "drag", c = { px: n.x, py: n.y, ...t }, l = { x: (b = n.cx) != null ? b : t.width / 2, y: (h = n.cy) != null ? h : 20 }, t.dock || (w = { width: t.width, height: t.height }), e.classList.add("bp-dragging");
466
483
  },
467
- move(r) {
468
- if (g !== "drag" || !d) return;
469
- const b = r.x - d.px, h = r.y - d.py;
470
- j(b, h, d.x + b + l.x, d.y + h + l.y);
484
+ move(n) {
485
+ if (g !== "drag" || !c) return;
486
+ const b = n.x - c.px, h = n.y - c.py;
487
+ j(b, h, c.x + b + l.x, c.y + h + l.y);
471
488
  },
472
489
  end() {
473
- g === "drag" && (e.classList.remove("bp-dragging"), W(null), _(), g = null, d = null, x = null, K(t));
490
+ g === "drag" && (e.classList.remove("bp-dragging"), C(null), _(), g = null, c = null, x = null, K(t));
474
491
  }
475
492
  };
476
- return M(), {
477
- external: Y,
493
+ return z(), {
494
+ external: G,
478
495
  get geometry() {
479
496
  return { ...t };
480
497
  },
481
- set(r) {
482
- const b = he(s), h = { ...t, ...r, dock: null };
483
- h.width = Math.min(b.maxWidth, Math.max(b.minWidth, h.width)), h.height = Math.min(b.maxHeight, Math.max(b.minHeight, h.height)), t = R(h), M(), K(t);
498
+ set(n) {
499
+ const b = le(d), h = { ...t, ...n, dock: null };
500
+ h.width = Math.min(b.maxWidth, Math.max(b.minWidth, h.width)), h.height = Math.min(b.maxHeight, Math.max(b.minHeight, h.height)), t = R(h), z(), K(t);
484
501
  },
485
502
  /** 'left' | 'right' | 'left-half' | 'right-half' | 'max' | 'float' */
486
- dock(r) {
487
- if (!r || r === "float") {
488
- const b = y || { width: s.width, height: s.height };
503
+ dock(n) {
504
+ if (!n || n === "float") {
505
+ const b = w || { width: d.width, height: d.height };
489
506
  t = R({ ...t, ...b, dock: null });
490
507
  } else
491
- t.dock || (y = { width: t.width, height: t.height }), t = { ...t, ...U(r, t), dock: r };
492
- M(), K(t);
508
+ t.dock || (w = { width: t.width, height: t.height }), t = { ...t, ...P(n, t), dock: n };
509
+ z(), K(t);
493
510
  },
494
511
  destroy() {
495
- window.removeEventListener("resize", P);
512
+ window.removeEventListener("resize", U);
496
513
  }
497
514
  };
498
515
  }
499
- const le = "bravophone/v1";
500
- function Se({ frame: e, origin: a, onEvent: n }) {
516
+ const be = "bravophone/v1";
517
+ function Ee({ frame: e, origin: a, onEvent: i }) {
501
518
  const o = /* @__PURE__ */ new Map();
502
- let i = 0, s = !1;
503
- const u = [], m = (g) => {
504
- var d;
519
+ let r = 0, d = !1;
520
+ const u = [], f = (g) => {
521
+ var c;
505
522
  if (g.origin !== a || g.source !== e.contentWindow) return;
506
523
  const p = g.data;
507
- if (!(!p || p.protocol !== le)) {
524
+ if (!(!p || p.protocol !== be)) {
508
525
  if (p.type === "ready") {
509
- for (s = !0; u.length; ) u.shift()();
510
- n == null || n("ready", (d = p.payload) != null ? d : {});
526
+ for (d = !0; u.length; ) u.shift()();
527
+ i == null || i("ready", (c = p.payload) != null ? c : {});
511
528
  return;
512
529
  }
513
530
  if (p.type === "reply") {
@@ -516,41 +533,41 @@ function Se({ frame: e, origin: a, onEvent: n }) {
516
533
  o.delete(p.id), clearTimeout(l.timer), p.error ? l.reject(new Error(p.error)) : l.resolve(p.payload);
517
534
  return;
518
535
  }
519
- p.type === "event" && (n == null || n(p.name, p.payload));
536
+ p.type === "event" && (i == null || i(p.name, p.payload));
520
537
  }
521
538
  };
522
- window.addEventListener("message", m);
523
- function t(g, p, { timeout: d = 15e3 } = {}) {
539
+ window.addEventListener("message", f);
540
+ function t(g, p, { timeout: c = 15e3 } = {}) {
524
541
  return new Promise((l, x) => {
525
- const y = `${Date.now()}-${++i}`, M = () => {
542
+ const w = `${Date.now()}-${++r}`, z = () => {
526
543
  var $;
527
- const W = setTimeout(() => {
528
- o.delete(y), x(new Error(`Bravophone: timeout no comando "${g}"`));
529
- }, d);
530
- o.set(y, { resolve: l, reject: x, timer: W }), ($ = e.contentWindow) == null || $.postMessage(
531
- { protocol: le, type: "command", id: y, command: g, payload: p },
544
+ const C = setTimeout(() => {
545
+ o.delete(w), x(new Error(`Bravophone: timeout no comando "${g}"`));
546
+ }, c);
547
+ o.set(w, { resolve: l, reject: x, timer: C }), ($ = e.contentWindow) == null || $.postMessage(
548
+ { protocol: be, type: "command", id: w, command: g, payload: p },
532
549
  a
533
550
  );
534
551
  };
535
- s ? M() : u.push(M);
552
+ d ? z() : u.push(z);
536
553
  });
537
554
  }
538
555
  return {
539
556
  call: t,
540
557
  get ready() {
541
- return s;
558
+ return d;
542
559
  },
543
560
  destroy() {
544
- window.removeEventListener("message", m), o.forEach(({ reject: g, timer: p }) => {
561
+ window.removeEventListener("message", f), o.forEach(({ reject: g, timer: p }) => {
545
562
  clearTimeout(p), g(new Error("Bravophone: widget destruído"));
546
563
  }), o.clear();
547
564
  }
548
565
  };
549
566
  }
550
- const ge = "bravophone:launcher", Ee = 4, ae = 8;
551
- function He(e) {
567
+ const me = "bravophone:launcher", He = 4, re = 8;
568
+ function Te(e) {
552
569
  try {
553
- const a = localStorage.getItem(ge);
570
+ const a = localStorage.getItem(me);
554
571
  return a ? { ...e, ...JSON.parse(a) } : { ...e };
555
572
  } catch (a) {
556
573
  return { ...e };
@@ -558,76 +575,82 @@ function He(e) {
558
575
  }
559
576
  function ie(e) {
560
577
  try {
561
- localStorage.setItem(ge, JSON.stringify(e));
578
+ localStorage.setItem(me, JSON.stringify(e));
562
579
  } catch (a) {
563
580
  }
564
581
  }
565
- function F(e, a) {
566
- const n = Math.max(ae, window.innerHeight - a - ae);
567
- return Math.min(Math.max(ae, e), n);
582
+ function q(e, a) {
583
+ const i = Math.max(re, window.innerHeight - a - re);
584
+ return Math.min(Math.max(re, e), i);
568
585
  }
569
- function $e({ el: e, side: a, y: n, onOpen: o }) {
570
- let i = { side: a, y: F(n, e.offsetHeight || 48) }, s = null, u = !1;
571
- const m = () => {
572
- e.dataset.side = i.side, e.style.top = `${i.y}px`, e.style.right = i.side === "right" ? "0px" : "auto", e.style.left = i.side === "left" ? "0px" : "auto";
586
+ function $e({ el: e, side: a, y: i, onOpen: o }) {
587
+ let r = { side: a, y: q(i, e.offsetHeight || 48) }, d = null, u = !1;
588
+ const f = () => {
589
+ e.dataset.side = r.side, e.style.top = `${r.y}px`, e.style.right = r.side === "right" ? "0px" : "auto", e.style.left = r.side === "left" ? "0px" : "auto";
573
590
  }, t = (l) => {
574
- l.button === 0 && (s = { py: l.clientY, y: i.y }, u = !1, e.setPointerCapture(l.pointerId));
591
+ l.button === 0 && (d = { py: l.clientY, y: r.y }, u = !1, e.setPointerCapture(l.pointerId));
575
592
  }, g = (l) => {
576
- if (!s) return;
577
- const x = l.clientY - s.py;
578
- !u && Math.abs(x) < Ee || (u || (u = !0, e.classList.add("bp-launcher-dragging")), i.y = F(s.y + x, e.offsetHeight), m());
593
+ if (!d) return;
594
+ const x = l.clientY - d.py;
595
+ !u && Math.abs(x) < He || (u || (u = !0, e.classList.add("bp-launcher-dragging")), r.y = q(d.y + x, e.offsetHeight), f());
579
596
  }, p = (l) => {
580
- if (!s) return;
597
+ if (!d) return;
581
598
  const x = u;
582
- s = null, u = !1, e.classList.remove("bp-launcher-dragging");
599
+ d = null, u = !1, e.classList.remove("bp-launcher-dragging");
583
600
  try {
584
601
  e.releasePointerCapture(l.pointerId);
585
- } catch (y) {
602
+ } catch (w) {
586
603
  }
587
- x ? ie(i) : o == null || o();
604
+ x ? ie(r) : o == null || o();
588
605
  };
589
606
  e.addEventListener("pointerdown", t), e.addEventListener("pointermove", g), e.addEventListener("pointerup", p), e.addEventListener("pointercancel", p), e.addEventListener("keydown", (l) => {
590
607
  (l.key === "Enter" || l.key === " ") && (l.preventDefault(), o == null || o());
591
608
  });
592
- const d = () => {
593
- i.y = F(i.y, e.offsetHeight), m();
609
+ const c = () => {
610
+ r.y = q(r.y, e.offsetHeight), f();
594
611
  };
595
- return window.addEventListener("resize", d), m(), {
612
+ return window.addEventListener("resize", c), f(), {
596
613
  get state() {
597
- return { ...i };
614
+ return { ...r };
598
615
  },
599
616
  setSide(l) {
600
- i.side = l, m(), ie(i);
617
+ r.side = l, f(), ie(r);
601
618
  },
602
619
  moveTo(l) {
603
- i.y = F(l, e.offsetHeight), m(), ie(i);
620
+ r.y = q(l, e.offsetHeight), f(), ie(r);
604
621
  },
605
622
  destroy() {
606
- window.removeEventListener("resize", d);
623
+ window.removeEventListener("resize", c);
607
624
  }
608
625
  };
609
626
  }
610
- const Te = "https://cdn.jsdelivr.net/npm";
611
- function Ie(e, a = "@bravophone/webphone") {
612
- return `${Te}/${a}@${e}/host/`;
627
+ const Ie = "https://cdn.jsdelivr.net/npm";
628
+ function Oe(e, a = "@bravophone/webphone") {
629
+ return `${Ie}/${a}@${e}/host/`;
613
630
  }
614
- function Oe({ version: e, parentOrigin: a, token: n, base: o }) {
615
- const i = o || Ie(e), s = JSON.stringify({ parentOrigin: a, token: n || null }).replace(/</g, "\\u003c");
631
+ function We({ version: e, parentOrigin: a, token: i, base: o }) {
632
+ const r = o || Oe(e), d = JSON.stringify({ parentOrigin: a, token: i || null }).replace(/</g, "\\u003c");
616
633
  return `<!doctype html>
617
634
  <html lang="pt-BR">
618
635
  <head>
619
636
  <meta charset="UTF-8">
620
637
  <meta name="viewport" content="width=device-width,initial-scale=1">
621
638
  <title>Webphone BRAVOPHONE</title>
622
- <link rel="stylesheet" href="${i}css/dark-theme.css">
623
- <link rel="stylesheet" href="${i}styles/theme-fixes.css">
639
+ <!-- CRÍTICO no modo srcdoc. O bundle referencia as imagens por caminho
640
+ RELATIVO (src="images/answer.png"), fora do public_path. Sem <base>,
641
+ elas resolvem contra a página do integrador — o documento herda o
642
+ baseURI do pai — e somem todas: logo, atender, desligar, mudo, hold,
643
+ transferir. Com <base>, resolvem contra o CDN. -->
644
+ <base href="${r}">
645
+ <link rel="stylesheet" href="${r}css/dark-theme.css">
646
+ <link rel="stylesheet" href="${r}styles/theme-fixes.css">
624
647
  <style>
625
648
  html, body { margin: 0; height: 100%; background: #10131c; overflow: hidden; }
626
649
  #app { height: 100%; }
627
650
  </style>
628
651
  <script>
629
652
  (function () {
630
- var cfg = ${s};
653
+ var cfg = ${d};
631
654
  // O guest-bridge lê daqui: em srcdoc não há query string para carregar a
632
655
  // origem do pai.
633
656
  window.__bpParentOrigin = cfg.parentOrigin;
@@ -638,12 +661,12 @@ function Oe({ version: e, parentOrigin: a, token: n, base: o }) {
638
661
  }
639
662
  })();
640
663
  <\/script>
641
- <script src="${i}shim/messages.js"><\/script>
642
- <script src="${i}shim/chrome-shim.js"><\/script>
643
- <script src="${i}js/libwebphone.js"><\/script>
644
- <script src="${i}js/bravophone-route-selector.js"><\/script>
645
- <script defer src="${i}popup.js"><\/script>
646
- <script defer src="${i}shim/guest-bridge.js"><\/script>
664
+ <script src="${r}shim/messages.js"><\/script>
665
+ <script src="${r}shim/chrome-shim.js"><\/script>
666
+ <script src="${r}js/libwebphone.js"><\/script>
667
+ <script src="${r}js/bravophone-route-selector.js"><\/script>
668
+ <script defer src="${r}popup.js"><\/script>
669
+ <script defer src="${r}shim/guest-bridge.js"><\/script>
647
670
  </head>
648
671
  <body>
649
672
  <noscript><strong>O webphone precisa de JavaScript habilitado.</strong></noscript>
@@ -651,7 +674,7 @@ function Oe({ version: e, parentOrigin: a, token: n, base: o }) {
651
674
  </body>
652
675
  </html>`;
653
676
  }
654
- const be = {
677
+ const ue = {
655
678
  // 380x640 é a geometria da janela nativa da extensão — o layout do
656
679
  // webphone é calibrado para ela, então é o ponto de partida aqui também.
657
680
  width: 380,
@@ -664,210 +687,231 @@ const be = {
664
687
  maxHeight: 1400,
665
688
  margin: 24
666
689
  };
667
- function w(e, a = {}, n = []) {
690
+ function y(e, a = {}, i = []) {
668
691
  const o = document.createElement(e);
669
- for (const [i, s] of Object.entries(a))
670
- i === "class" ? o.className = s : i === "text" ? o.textContent = s : s != null && o.setAttribute(i, s);
671
- return n.forEach((i) => o.appendChild(i)), o;
692
+ for (const [r, d] of Object.entries(a))
693
+ r === "class" ? o.className = d : r === "text" ? o.textContent = d : d != null && o.setAttribute(r, d);
694
+ return i.forEach((r) => o.appendChild(r)), o;
672
695
  }
673
- function We(e) {
696
+ function Ce(e) {
674
697
  const {
675
698
  hostUrl: a,
676
- token: n,
699
+ token: i,
677
700
  position: o = "bottom-right",
678
- open: i = !1,
679
- launcher: s = !0,
701
+ open: r = !1,
702
+ launcher: d = !0,
680
703
  title: u = "BRAVOPHONE",
681
- // 'none' preserva 100% da UI do webphone: sem barra de titulo, o arraste
682
- // vem de dentro do iframe. 'bar' adiciona a barra com titulo e controles.
683
- frame: m = "none",
704
+ // 'bar' por padrão: título, indicador de estado e controles visíveis.
705
+ // 'none' preserva 100% da UI do webphone sem barra, o arraste vem de
706
+ // dentro do iframe e só um botão de fechar aparece no hover.
707
+ frame: f = "bar",
684
708
  // O que arrastar até a borda de cima faz. 'max' é o gesto universal;
685
709
  // troque para 'top-half' se preferir as metades verticais no topo.
686
710
  dockTop: t = "max",
687
711
  // Lado da viewport em que a aba de abertura fica colada.
688
712
  launcherSide: g = "right",
689
713
  // Desenho da aba: 'phone-waves' | 'waveform' | 'headset' | 'chat-phone'
690
- launcherIcon: p = te,
691
- // 'hosted' o iframe navega para hostUrl (padrão)
692
- // 'srcdoc' — o iframe roda na origem do site e busca o conteúdo no CDN
693
- mode: d = "hosted",
714
+ launcherIcon: p = ae,
715
+ // 'srcdoc' é o padrão porque é o modo que funciona sem infraestrutura
716
+ // nossa: o webphone vem do CDN, travado nesta versão. 'hosted' navega
717
+ // para hostUrl e depende de um domínio publicado — se ele não existir,
718
+ // o iframe falha em DNS antes de qualquer outra coisa.
719
+ mode: c = "srcdoc",
694
720
  // Base dos assets no modo srcdoc. Padrão: o CDN travado nesta versão.
695
721
  // Serve para desenvolvimento (localhost) e para quem espelhar os assets.
696
722
  hostBase: l,
697
723
  version: x,
698
- emit: y
699
- } = e, M = d === "srcdoc", W = M ? window.location.origin : new URL(a).origin, $ = w("div", { "data-bravophone": "root" });
724
+ emit: w
725
+ } = e, z = c === "srcdoc", C = z ? window.location.origin : new URL(a).origin, $ = y("div", { "data-bravophone": "root" });
700
726
  $.style.cssText = "all:initial;position:static";
701
727
  const j = $.attachShadow({ mode: "open" });
702
- j.appendChild(w("style", { text: ke }));
728
+ j.appendChild(y("style", { text: Me }));
703
729
  const _ = (() => {
704
- var pe;
705
- const { width: c, height: E, margin: O } = be, N = window.innerWidth - c - O, de = window.innerHeight - E - O, ce = {
706
- "bottom-right": { x: N, y: de },
707
- "bottom-left": { x: O, y: de },
708
- "top-right": { x: N, y: O },
709
- "top-left": { x: O, y: O }
730
+ var he;
731
+ const { width: s, height: M, margin: W } = ue, N = window.innerWidth - s - W, ce = window.innerHeight - M - W, pe = {
732
+ "bottom-right": { x: N, y: ce },
733
+ "bottom-left": { x: W, y: ce },
734
+ "top-right": { x: N, y: W },
735
+ "top-left": { x: W, y: W }
710
736
  };
711
- return R({ ...(pe = ce[o]) != null ? pe : ce["bottom-right"], width: c, height: E });
712
- })(), G = R(Me(_)), D = w("span", { class: "bp-status", "data-state": "connecting" }), B = w("button", { class: "bp-btn bp-btn-min", title: "Minimizar", text: "—" }), P = w("button", { class: "bp-btn bp-btn-close", title: "Fechar", text: "×" }), Y = w("div", { class: "bp-header" }, [
713
- D,
714
- w("span", { class: "bp-title", text: u }),
737
+ return R({ ...(he = pe[o]) != null ? he : pe["bottom-right"], width: s, height: M });
738
+ })(), F = R(Le(_)), A = y("span", { class: "bp-status", "data-state": "connecting" }), B = y("button", { class: "bp-btn bp-btn-min", title: "Minimizar", text: "—" }), U = y("button", { class: "bp-btn bp-btn-close", title: "Fechar", text: "×" }), G = y("div", { class: "bp-header" }, [
739
+ A,
740
+ y("span", { class: "bp-title", text: u }),
715
741
  B,
716
- P
717
- ]), r = w("iframe", {
742
+ U
743
+ ]), n = y("iframe", {
718
744
  class: "bp-frame",
719
745
  // allow= é obrigatório no modo hospedado (cross-origin). Em srcdoc o
720
746
  // microfone já é herdado do topo, mas declarar não custa e documenta.
721
747
  allow: "microphone; autoplay; clipboard-write; speaker-selection",
722
748
  title: "Webphone BRAVOPHONE"
723
749
  });
724
- M ? r.setAttribute(
750
+ z ? n.setAttribute(
725
751
  "srcdoc",
726
- Oe({ version: x, parentOrigin: W, token: n, base: l })
727
- ) : r.setAttribute(
752
+ We({ version: x, parentOrigin: C, token: i, base: l })
753
+ ) : n.setAttribute(
728
754
  "src",
729
- Be(new URL(a), { token: n, embed: "1", parent: location.origin })
755
+ Be(new URL(a), { token: i, embed: "1", parent: location.origin })
730
756
  );
731
- const h = ["n", "s", "w", "e", "nw", "ne", "sw", "se"].map((c) => ({
732
- el: w("div", { class: `bp-h bp-h-${c}` }),
733
- dir: c
734
- })), v = w("div", { class: "bp-preview" });
757
+ const h = ["n", "s", "w", "e", "nw", "ne", "sw", "se"].map((s) => ({
758
+ el: y("div", { class: `bp-h bp-h-${s}` }),
759
+ dir: s
760
+ })), v = y("div", { class: "bp-preview" });
735
761
  v.hidden = !0;
736
- const z = w("button", { class: "bp-btn bp-btn-close", title: "Fechar", text: "×" }), L = w("div", { class: "bp-overlay" }, [z]), H = w("div", { class: "bp-body" }, [r, L]), T = w("div", { class: "bp-root" }, [Y, H, ...h.map((c) => c.el)]);
737
- m !== "bar" && T.classList.add("bp-chromeless"), T.hidden = !i;
738
- const Q = w("span", { class: "bp-launcher-icon" });
739
- Q.innerHTML = J[p] || J[te];
740
- const re = w("span", { class: "bp-launcher-grip", "aria-hidden": "true" });
741
- re.innerHTML = ye;
742
- const S = w("div", {
762
+ const S = y("button", { class: "bp-btn bp-btn-close", title: "Fechar", text: "×" }), E = y("div", { class: "bp-overlay" }, [S]), H = y("div", { class: "bp-body" }, [n, E]), k = y("div", { class: "bp-root" }, [G, H, ...h.map((s) => s.el)]);
763
+ f !== "bar" && k.classList.add("bp-chromeless"), k.hidden = !r;
764
+ const Q = y("span", { class: "bp-launcher-icon" });
765
+ Q.innerHTML = J[p] || J[ae];
766
+ const oe = y("span", { class: "bp-launcher-grip", "aria-hidden": "true" });
767
+ oe.innerHTML = ve;
768
+ const T = y("div", {
743
769
  class: "bp-launcher",
744
770
  role: "button",
745
771
  tabindex: "0",
746
772
  title: "Abrir webphone",
747
773
  "aria-label": "Abrir webphone"
748
774
  }, [
749
- re,
775
+ oe,
750
776
  Q,
751
- w("span", { class: "bp-badge" })
777
+ y("span", { class: "bp-badge" })
752
778
  ]);
753
- S.dataset.state = "connecting", S.hidden = !s || i, j.append(v, T, S), document.body.appendChild($);
754
- const oe = He({
779
+ T.dataset.state = "connecting", T.hidden = !d, j.append(v, k, T), document.body.appendChild($);
780
+ const se = Te({
755
781
  side: g,
756
782
  y: Math.round(window.innerHeight / 2 - 24)
757
- }), se = $e({
758
- el: S,
759
- side: oe.side,
760
- y: F(oe.y, 48),
761
- onOpen: () => I.show()
762
- }), A = Le({
763
- root: T,
764
- handle: Y,
783
+ }), de = $e({
784
+ el: T,
785
+ side: se.side,
786
+ y: q(se.y, 48),
787
+ // A aba nunca some, então o clique tem dois papéis: abrir quando fechada,
788
+ // e localizar quando já aberta.
789
+ onOpen: () => O.reveal()
790
+ }), I = Se({
791
+ root: k,
792
+ handle: G,
765
793
  handles: h,
766
794
  preview: v,
767
- geometry: G,
768
- limits: be,
795
+ geometry: F,
796
+ limits: ue,
769
797
  topDock: t,
770
- onChange: (c) => y("resize", { width: c.width, height: c.height, dock: c.dock || null })
771
- }), ee = Se({
772
- frame: r,
773
- origin: W,
774
- onEvent: (c, E) => {
775
- var O;
776
- if (c === "ready" && (D.dataset.state = "ready", S.dataset.state = "ready", n && ee.call("auth", { token: n }).catch(() => {
777
- })), c === "state") {
778
- const N = (O = E == null ? void 0 : E.state) != null ? O : "ready";
779
- D.dataset.state = N, S.dataset.state = N;
798
+ onChange: (s) => w("resize", { width: s.width, height: s.height, dock: s.dock || null })
799
+ }), ee = Ee({
800
+ frame: n,
801
+ origin: C,
802
+ onEvent: (s, M) => {
803
+ var W;
804
+ if (s === "ready" && (A.dataset.state = "ready", T.dataset.state = "ready", i && ee.call("auth", { token: i }).catch(() => {
805
+ })), s === "state") {
806
+ const N = (W = M == null ? void 0 : M.state) != null ? W : "ready";
807
+ A.dataset.state = N, T.dataset.state = N;
780
808
  }
781
- if (c === "call:incoming" && (I.show(), S.dataset.badge = "1", S.dataset.state = "ringing"), c === "call:answered" && (S.dataset.state = "incall"), (c === "call:ended" || c === "call:failed") && (delete S.dataset.badge, S.dataset.state = "ready"), c === "drag:start") {
782
- A.external.start(E);
809
+ if (s === "call:incoming" && (O.show(), T.dataset.badge = "1", T.dataset.state = "ringing"), s === "call:answered" && (T.dataset.state = "incall"), s === "call:ended" && (delete T.dataset.badge, T.dataset.state = "ready"), s === "drag:start") {
810
+ I.external.start(M);
783
811
  return;
784
812
  }
785
- if (c === "drag:move") {
786
- A.external.move(E);
813
+ if (s === "drag:move") {
814
+ I.external.move(M);
787
815
  return;
788
816
  }
789
- if (c === "drag:end") {
790
- A.external.end();
817
+ if (s === "drag:end") {
818
+ I.external.end();
791
819
  return;
792
820
  }
793
- y(c, E);
821
+ w(s, M);
794
822
  }
795
823
  });
796
- let q = !1;
797
- const I = {
824
+ let Y = !1, te = null;
825
+ const O = {
798
826
  el: $,
799
827
  bridge: ee,
800
828
  show() {
801
- T.hidden = !1, S.hidden = !0, y("open");
829
+ k.hidden = !1, w("open");
802
830
  },
803
831
  hide() {
804
- T.hidden = !0, s && (S.hidden = !1), y("close");
832
+ k.hidden = !0, w("close");
805
833
  },
806
834
  toggle() {
807
- T.hidden ? I.show() : I.hide();
835
+ k.hidden ? O.show() : O.hide();
836
+ },
837
+ /**
838
+ * Traz a janela para a atenção do usuário.
839
+ * Fechada: abre. Aberta e fora de vista: traz de volta. Aberta e
840
+ * visível: um halo curto, para o olho encontrá-la.
841
+ */
842
+ reveal() {
843
+ if (k.hidden) {
844
+ O.show();
845
+ return;
846
+ }
847
+ const s = I.geometry;
848
+ (s.x + s.width < 40 || s.x > window.innerWidth - 40 || s.y > window.innerHeight - 40) && I.set({
849
+ x: Math.round((window.innerWidth - s.width) / 2),
850
+ y: Math.round((window.innerHeight - s.height) / 2)
851
+ }), k.classList.remove("bp-attention"), k.offsetWidth, k.classList.add("bp-attention"), clearTimeout(te), te = setTimeout(() => k.classList.remove("bp-attention"), 1800), w("reveal");
808
852
  },
809
853
  get isOpen() {
810
- return !T.hidden;
854
+ return !k.hidden;
811
855
  },
812
- minimize(c) {
813
- if (m !== "bar") {
814
- I.hide();
856
+ minimize(s) {
857
+ if (f !== "bar") {
858
+ O.hide();
815
859
  return;
816
860
  }
817
- q = c != null ? c : !q, T.classList.toggle("bp-minimized", q), B.textContent = q ? "▢" : "—";
861
+ Y = s != null ? s : !Y, k.classList.toggle("bp-minimized", Y), B.textContent = Y ? "▢" : "—";
818
862
  },
819
- move(c, E) {
820
- A.set({ x: c, y: E });
863
+ move(s, M) {
864
+ I.set({ x: s, y: M });
821
865
  },
822
- resize(c, E) {
823
- A.set({ width: c, height: E });
866
+ resize(s, M) {
867
+ I.set({ width: s, height: M });
824
868
  },
825
- dock(c) {
826
- A.dock(c);
869
+ dock(s) {
870
+ I.dock(s);
827
871
  },
828
- setLauncherSide(c) {
829
- se.setSide(c);
872
+ setLauncherSide(s) {
873
+ de.setSide(s);
830
874
  },
831
- setLauncherIcon(c) {
832
- Q.innerHTML = J[c] || J[te];
875
+ setLauncherIcon(s) {
876
+ Q.innerHTML = J[s] || J[ae];
833
877
  },
834
878
  get geometry() {
835
- return A.geometry;
879
+ return I.geometry;
836
880
  },
837
881
  destroy() {
838
- ee.destroy(), A.destroy(), se.destroy(), v.remove(), $.remove();
882
+ clearTimeout(te), ee.destroy(), I.destroy(), de.destroy(), v.remove(), $.remove();
839
883
  }
840
884
  };
841
- return P.addEventListener("click", () => I.hide()), B.addEventListener("click", () => I.minimize()), z.addEventListener("click", () => I.hide()), I;
885
+ return U.addEventListener("click", () => O.hide()), B.addEventListener("click", () => O.minimize()), S.addEventListener("click", () => O.hide()), O;
842
886
  }
843
887
  function Be(e, a) {
844
- const n = new URL(e.href);
845
- for (const [o, i] of Object.entries(a))
846
- i != null && i !== "" && n.searchParams.set(o, i);
847
- return a.token && (n.searchParams.delete("token"), n.hash = `token=${encodeURIComponent(a.token)}`), n.href;
848
- }
849
- const Ae = "https://webphone.bravophone.com/embed/";
850
- let k = null;
851
- const C = /* @__PURE__ */ new Map();
852
- function Ce(e, a) {
853
- var n, o;
854
- (n = C.get(e)) == null || n.forEach((i) => {
888
+ const i = new URL(e.href);
889
+ for (const [o, r] of Object.entries(a))
890
+ r != null && r !== "" && i.searchParams.set(o, r);
891
+ return a.token && (i.searchParams.delete("token"), i.hash = `token=${encodeURIComponent(a.token)}`), i.href;
892
+ }
893
+ const De = "";
894
+ let L = null;
895
+ const D = /* @__PURE__ */ new Map();
896
+ function Ae(e, a) {
897
+ var i, o;
898
+ (i = D.get(e)) == null || i.forEach((r) => {
855
899
  try {
856
- i(a);
857
- } catch (s) {
858
- console.error("[Bravophone] listener falhou:", s);
900
+ r(a);
901
+ } catch (d) {
902
+ console.error("[Bravophone] listener falhou:", d);
859
903
  }
860
- }), (o = C.get("*")) == null || o.forEach((i) => {
904
+ }), (o = D.get("*")) == null || o.forEach((r) => {
861
905
  try {
862
- i({ event: e, payload: a });
863
- } catch (s) {
864
- console.error("[Bravophone] listener falhou:", s);
906
+ r({ event: e, payload: a });
907
+ } catch (d) {
908
+ console.error("[Bravophone] listener falhou:", d);
865
909
  }
866
910
  });
867
911
  }
868
- function f() {
869
- if (!k) throw new Error("Bravophone: chame Bravophone.init() antes.");
870
- return k;
912
+ function m() {
913
+ if (!L) throw new Error("Bravophone: chame Bravophone.init() antes.");
914
+ return L;
871
915
  }
872
916
  const ne = {
873
917
  /**
@@ -886,102 +930,110 @@ const ne = {
886
930
  * precisa estar na allowlist de CORS dos backends.
887
931
  */
888
932
  init(e = {}) {
889
- if (k) return k;
933
+ if (L) return L;
890
934
  if (typeof window == "undefined" || !document.body)
891
935
  throw new Error("Bravophone: init() precisa rodar no browser, após o <body> existir.");
892
- return location.protocol !== "https:" && location.hostname !== "localhost" && console.warn("[Bravophone] Contexto inseguro: o microfone exige HTTPS ou localhost."), k = We({
893
- hostUrl: Ae,
936
+ if (location.protocol !== "https:" && location.hostname !== "localhost" && console.warn("[Bravophone] Contexto inseguro: o microfone exige HTTPS ou localhost."), e.mode === "hosted" && !e.hostUrl)
937
+ throw new Error(
938
+ "Bravophone: mode 'hosted' exige hostUrl. Use mode 'srcdoc' (padrão) para carregar o webphone do CDN sem depender de um host próprio."
939
+ );
940
+ return L = Ce({
941
+ hostUrl: De,
894
942
  version: ne.version,
895
943
  ...e,
896
- emit: Ce
897
- }), k;
944
+ emit: Ae
945
+ }), L;
898
946
  },
899
947
  // ---- Controle da janela ----
900
948
  show() {
901
- f().show();
949
+ m().show();
902
950
  },
903
951
  hide() {
904
- f().hide();
952
+ m().hide();
905
953
  },
906
954
  toggle() {
907
- f().toggle();
955
+ m().toggle();
956
+ },
957
+ /** Abre a janela; se já estiver aberta, traz para a vista e destaca. */
958
+ reveal() {
959
+ m().reveal();
908
960
  },
909
961
  minimize(e) {
910
- f().minimize(e);
962
+ m().minimize(e);
911
963
  },
912
964
  move(e, a) {
913
- f().move(e, a);
965
+ m().move(e, a);
914
966
  },
915
967
  resize(e, a) {
916
- f().resize(e, a);
968
+ m().resize(e, a);
917
969
  },
918
970
  /** 'left' | 'right' | 'left-half' | 'right-half' | 'max' | 'float' */
919
971
  dock(e) {
920
- f().dock(e);
972
+ m().dock(e);
921
973
  },
922
974
  /** Move a aba de abertura para o outro lado da viewport. */
923
975
  setLauncherSide(e) {
924
- f().setLauncherSide(e);
976
+ m().setLauncherSide(e);
925
977
  },
926
978
  /** 'phone-waves' | 'waveform' | 'headset' | 'chat-phone' */
927
979
  setLauncherIcon(e) {
928
- f().setLauncherIcon(e);
980
+ m().setLauncherIcon(e);
929
981
  },
930
982
  get isOpen() {
931
- return k ? k.isOpen : !1;
983
+ return L ? L.isOpen : !1;
932
984
  },
933
985
  get geometry() {
934
- return k ? k.geometry : null;
986
+ return L ? L.geometry : null;
935
987
  },
936
988
  // ---- Telefonia ----
937
989
  /** Disca um número. Aceita formato livre; a normalização é a mesma da extensão. */
938
990
  call(e, a) {
939
- return f().bridge.call("call", { number: e, meta: a });
991
+ return m().bridge.call("call", { number: e, meta: a });
940
992
  },
941
993
  hangup() {
942
- return f().bridge.call("hangup");
994
+ return m().bridge.call("hangup");
943
995
  },
944
996
  answer() {
945
- return f().bridge.call("answer");
997
+ return m().bridge.call("answer");
946
998
  },
947
999
  /** Alterna o mudo — o bundle só expõe toggle, não aceita estado alvo. */
948
1000
  mute() {
949
- return f().bridge.call("mute");
1001
+ return m().bridge.call("mute");
950
1002
  },
951
1003
  /** Alterna a espera. Também toggle. */
952
1004
  hold() {
953
- return f().bridge.call("hold");
1005
+ return m().bridge.call("hold");
954
1006
  },
955
1007
  sendDTMF(e) {
956
- return f().bridge.call("dtmf", { tone: e });
1008
+ return m().bridge.call("dtmf", { tone: e });
957
1009
  },
958
1010
  transfer(e) {
959
- return f().bridge.call("transfer", { to: e });
1011
+ return m().bridge.call("transfer", { to: e });
960
1012
  },
961
1013
  getStatus() {
962
- return f().bridge.call("status");
1014
+ return m().bridge.call("status");
963
1015
  },
964
1016
  setAuth(e) {
965
- return f().bridge.call("auth", { token: e });
1017
+ return m().bridge.call("auth", { token: e });
966
1018
  },
967
1019
  logout() {
968
- return f().bridge.call("logout");
1020
+ return m().bridge.call("logout");
969
1021
  },
970
1022
  // ---- Eventos ----
971
1023
  /** Eventos: ready, state, call:dialing, call:incoming, call:answered,
972
1024
  * call:ended, call:failed, resize, open, close, error. */
973
1025
  on(e, a) {
974
- return C.has(e) || C.set(e, /* @__PURE__ */ new Set()), C.get(e).add(a), () => ne.off(e, a);
1026
+ return D.has(e) || D.set(e, /* @__PURE__ */ new Set()), D.get(e).add(a), () => ne.off(e, a);
975
1027
  },
976
1028
  off(e, a) {
977
- var n;
978
- (n = C.get(e)) == null || n.delete(a);
1029
+ var i;
1030
+ (i = D.get(e)) == null || i.delete(a);
979
1031
  },
980
1032
  destroy() {
981
- k == null || k.destroy(), k = null, C.clear();
1033
+ L == null || L.destroy(), L = null, D.clear();
982
1034
  },
983
1035
  // Substituída em build time pelo valor do package.json (ver vite.config.js).
984
- version: "0.2.0"
1036
+ version: "0.3.0"
985
1037
  };
986
1038
  typeof window != "undefined" && (window.Bravophone = ne);
987
1039
  export {