@coventia/softphone 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{call-BTYlT2SU.d.cts → call-VKq1I8yP.d.cts} +158 -5
- package/dist/{call-BTYlT2SU.d.ts → call-VKq1I8yP.d.ts} +158 -5
- package/dist/{chunk-N2N2EQQJ.js → chunk-7R6LOOAI.js} +4 -2
- package/dist/chunk-7R6LOOAI.js.map +1 -0
- package/dist/{chunk-5BGEHMPP.js → chunk-EYEDPD7Y.js} +146 -20
- package/dist/chunk-EYEDPD7Y.js.map +1 -0
- package/dist/{chunk-3V2L6UTK.js → chunk-LMJXX4YM.js} +17 -3
- package/dist/chunk-LMJXX4YM.js.map +1 -0
- package/dist/element/index.d.ts +162 -7
- package/dist/element/index.js +866 -421
- package/dist/element/index.js.map +1 -1
- package/dist/{engine-D9nbeY08.d.cts → engine-BlQBo2Ys.d.cts} +1 -1
- package/dist/{engine-Doa6Brkm.d.ts → engine-C0BOkIcW.d.ts} +1 -1
- package/dist/index.cjs +586 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +335 -8
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +15 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +14 -3
- package/dist/react/index.d.ts +14 -3
- package/dist/react/index.js +2 -2
- package/dist/{softphone-DhuhcKCy.d.cts → softphone-Cyq3hiIM.d.ts} +17 -2
- package/dist/{softphone-DHmhotbf.d.ts → softphone-DlGV12Xp.d.cts} +17 -2
- package/dist/softphone.css +477 -35
- package/dist/{sources-N4BOEDRL.js → sources-IRKNQPWW.js} +108 -5
- package/dist/sources-IRKNQPWW.js.map +1 -0
- package/dist/testing/index.cjs +41 -5
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +8 -2
- package/dist/testing/index.d.ts +8 -2
- package/dist/testing/index.js +41 -5
- package/dist/testing/index.js.map +1 -1
- package/dist/ui/index.cjs +846 -410
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.cts +17 -6
- package/dist/ui/index.d.ts +17 -6
- package/dist/ui/index.js +878 -456
- package/dist/ui/index.js.map +1 -1
- package/dist/zadarma/index.cjs +144 -18
- package/dist/zadarma/index.cjs.map +1 -1
- package/dist/zadarma/index.d.cts +2 -2
- package/dist/zadarma/index.d.ts +2 -2
- package/dist/zadarma/index.js +1 -1
- package/dist/zadarma-engine-L5DEFXUS.js +5 -0
- package/dist/{zadarma-engine-DN2SZSQ3.js.map → zadarma-engine-L5DEFXUS.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-3V2L6UTK.js.map +0 -1
- package/dist/chunk-5BGEHMPP.js.map +0 -1
- package/dist/chunk-N2N2EQQJ.js.map +0 -1
- package/dist/sources-N4BOEDRL.js.map +0 -1
- package/dist/zadarma-engine-DN2SZSQ3.js +0 -5
package/dist/softphone.css
CHANGED
|
@@ -219,6 +219,10 @@
|
|
|
219
219
|
|
|
220
220
|
background: var(--cv-bg);
|
|
221
221
|
overflow: hidden;
|
|
222
|
+
/* The containing block for `.cv-transfer-notices` — it overlays this whole shell, top edge to top
|
|
223
|
+
edge, not just `.cv-body`, so it reads as one seamless panel rather than a strip that starts a few
|
|
224
|
+
pixels short of the shell's own rounded corner. */
|
|
225
|
+
position: relative;
|
|
222
226
|
|
|
223
227
|
/* The frame is the HOST's call. The CRM's panel already draws `border rounded-xl shadow-2xl`, so
|
|
224
228
|
drawing our own put a card inside a card — nested chrome, which is always wrong. Defaulting to
|
|
@@ -236,8 +240,6 @@
|
|
|
236
240
|
.cv-dial-prefix { padding: 0.7rem 0.6rem 0; }
|
|
237
241
|
.cv-dial-head { padding: 0.3rem 0.6rem 0.6rem; }
|
|
238
242
|
.cv-display { font-size: 1.5rem; }
|
|
239
|
-
.cv-controls-row { gap: 1.1rem; }
|
|
240
|
-
|
|
241
243
|
}
|
|
242
244
|
|
|
243
245
|
/* Short hosts. The flex chain already lets the keypad absorb what is left, but below this the keys
|
|
@@ -293,6 +295,140 @@
|
|
|
293
295
|
.cv-tab:disabled { opacity: 0.35; cursor: not-allowed; }
|
|
294
296
|
.cv-tab span { font-size: 10px; font-weight: 600; line-height: 1; letter-spacing: 0.01em; }
|
|
295
297
|
|
|
298
|
+
/* ── Transfer outcome notices (Phase A — transfer-outcome-relay.md §5.5) ──────── */
|
|
299
|
+
/*
|
|
300
|
+
A persistent, dismissable banner OVER `.cv-body`, never a toast and never auto-dismissed — it carries
|
|
301
|
+
an action, and WCAG 2.2.1 requires a time limit to be removable, adjustable or extended.
|
|
302
|
+
|
|
303
|
+
Overlaps rather than reserving its own height, the same reasoning `.cv-dial-outcome`'s own comment
|
|
304
|
+
already gives for why the widget never lets a line of text resize the keypad under a moving finger —
|
|
305
|
+
here that principle cuts the other way: appearing costs nothing but a repaint, not a reflow, so the
|
|
306
|
+
widget's overall height stays identical whether a notice is showing or not, exactly like `.cv-detail`
|
|
307
|
+
overlaying `.cv-body`'s own list rather than pushing it down. It sits over whatever the current tab
|
|
308
|
+
happens to be showing (most often the dialer's country picker and number field — an acceptable loss:
|
|
309
|
+
the agent is not expected to start a fresh manual dial before dealing with a transfer that just failed
|
|
310
|
+
to connect), which is also why it outranks `.cv-detail` in `z-index`.
|
|
311
|
+
|
|
312
|
+
`[data-has-notices='false']` collapses to zero footprint: the element stays mounted (so its
|
|
313
|
+
`role="status"` region exists before the FIRST notice ever arrives — an aria-live region inserted at
|
|
314
|
+
the same moment as its own content is not reliably announced), but an idle widget, the common case,
|
|
315
|
+
covers nothing and costs no paint either.
|
|
316
|
+
*/
|
|
317
|
+
.cv-transfer-notices {
|
|
318
|
+
position: absolute;
|
|
319
|
+
inset: 0 0 auto 0;
|
|
320
|
+
z-index: 3; /* above `.cv-detail`'s 2 — this is the higher-priority thing on screen */
|
|
321
|
+
}
|
|
322
|
+
.cv-transfer-notices[data-has-notices='true'] {
|
|
323
|
+
display: flex;
|
|
324
|
+
flex-direction: column;
|
|
325
|
+
gap: 0.5rem;
|
|
326
|
+
padding: 0.6rem 0.75rem;
|
|
327
|
+
background: var(--cv-bg);
|
|
328
|
+
box-shadow: var(--cv-shadow);
|
|
329
|
+
animation: cv-transfer-notices-in 200ms var(--cv-ease-out) both;
|
|
330
|
+
}
|
|
331
|
+
@keyframes cv-transfer-notices-in {
|
|
332
|
+
from { opacity: 0; transform: translateY(-6px); }
|
|
333
|
+
to { opacity: 1; transform: none; }
|
|
334
|
+
}
|
|
335
|
+
@media (prefers-reduced-motion: reduce) {
|
|
336
|
+
.cv-transfer-notices[data-has-notices='true'] { animation: none; }
|
|
337
|
+
}
|
|
338
|
+
.cv-transfer-notices-count {
|
|
339
|
+
margin: 0;
|
|
340
|
+
font: 600 0.72rem var(--cv-font);
|
|
341
|
+
color: var(--cv-muted);
|
|
342
|
+
text-transform: uppercase;
|
|
343
|
+
letter-spacing: 0.04em;
|
|
344
|
+
}
|
|
345
|
+
.cv-transfer-notice {
|
|
346
|
+
display: flex;
|
|
347
|
+
align-items: flex-start;
|
|
348
|
+
gap: 0.6rem;
|
|
349
|
+
padding: 0.65rem 0.7rem;
|
|
350
|
+
border-radius: var(--cv-radius-key);
|
|
351
|
+
border: 1px solid var(--cv-danger-soft);
|
|
352
|
+
background: var(--cv-surface);
|
|
353
|
+
}
|
|
354
|
+
/* Same shape as `.cv-gate-mark`, smaller — one visual language for "here is a status", not two. */
|
|
355
|
+
.cv-transfer-notice-mark {
|
|
356
|
+
flex-shrink: 0;
|
|
357
|
+
display: grid;
|
|
358
|
+
place-items: center;
|
|
359
|
+
width: 30px;
|
|
360
|
+
height: 30px;
|
|
361
|
+
border-radius: 999px;
|
|
362
|
+
background: var(--cv-danger-soft);
|
|
363
|
+
color: var(--cv-danger);
|
|
364
|
+
}
|
|
365
|
+
.cv-transfer-notice-body { flex: 1; min-width: 0; }
|
|
366
|
+
/*
|
|
367
|
+
Title shares its row with only the dismiss button (24px) — not the whole card's width, and not the
|
|
368
|
+
"Llamar de vuelta" button, which gets its own row below (`.cv-transfer-notice-footer`). The original
|
|
369
|
+
layout put mark + title + subtitle + a full button all in one flex row, leaving the title as little as
|
|
370
|
+
~80px to wrap into at the real ~340px embed width — nearly every word landed on its own line.
|
|
371
|
+
`align-items: flex-start` keeps the dismiss pinned to the first line even when the title wraps to two.
|
|
372
|
+
*/
|
|
373
|
+
.cv-transfer-notice-header { display: flex; align-items: flex-start; gap: 0.4rem; }
|
|
374
|
+
.cv-transfer-notice-title {
|
|
375
|
+
flex: 1;
|
|
376
|
+
min-width: 0;
|
|
377
|
+
margin: 0;
|
|
378
|
+
font: 600 0.82rem var(--cv-font);
|
|
379
|
+
color: var(--cv-text);
|
|
380
|
+
line-height: 1.35;
|
|
381
|
+
}
|
|
382
|
+
.cv-transfer-notice-subtitle {
|
|
383
|
+
margin: 0.15rem 0 0;
|
|
384
|
+
font-size: 0.78rem;
|
|
385
|
+
color: var(--cv-muted);
|
|
386
|
+
line-height: 1.35;
|
|
387
|
+
}
|
|
388
|
+
/* Age and the callback button share a row too, same reasoning as the header — a short fixed-width
|
|
389
|
+
timestamp beside a content-sized button, neither one fighting the title for space above. */
|
|
390
|
+
.cv-transfer-notice-footer {
|
|
391
|
+
display: flex;
|
|
392
|
+
align-items: center;
|
|
393
|
+
justify-content: space-between;
|
|
394
|
+
gap: 0.5rem;
|
|
395
|
+
margin-top: 0.35rem;
|
|
396
|
+
}
|
|
397
|
+
.cv-transfer-notice-age { margin: 0; font-size: 0.7rem; color: var(--cv-faint); flex-shrink: 0; }
|
|
398
|
+
/*
|
|
399
|
+
`.cv-btn.cv-transfer-notice-callback` — TWO classes, not one. Equal-specificity selectors resolve by
|
|
400
|
+
source order, and this rule used to lose its `padding`/`font-size` to the shared `.cv-btn` rule below
|
|
401
|
+
simply because that one appears later in the file; the button rendered at full default CTA size
|
|
402
|
+
instead of this smaller, secondary one, which is what actually forced the title into that ~80px
|
|
403
|
+
column above. The extra class is what makes this override win regardless of source order.
|
|
404
|
+
*/
|
|
405
|
+
.cv-btn.cv-transfer-notice-callback {
|
|
406
|
+
flex-shrink: 0;
|
|
407
|
+
padding: 0.35rem 0.6rem;
|
|
408
|
+
font-size: 0.75rem;
|
|
409
|
+
display: inline-flex;
|
|
410
|
+
align-items: center;
|
|
411
|
+
gap: 0.3rem;
|
|
412
|
+
white-space: nowrap;
|
|
413
|
+
}
|
|
414
|
+
/* Same round icon-only shape as `.cv-search-clear` — one dismiss affordance, not a new one. */
|
|
415
|
+
.cv-transfer-notice-dismiss {
|
|
416
|
+
flex-shrink: 0;
|
|
417
|
+
width: 24px;
|
|
418
|
+
height: 24px;
|
|
419
|
+
display: inline-flex;
|
|
420
|
+
align-items: center;
|
|
421
|
+
justify-content: center;
|
|
422
|
+
border: none;
|
|
423
|
+
border-radius: 999px;
|
|
424
|
+
background: none;
|
|
425
|
+
color: var(--cv-muted);
|
|
426
|
+
cursor: pointer;
|
|
427
|
+
transition: color 0.12s ease, background 0.12s ease, transform 0.1s var(--cv-ease-out);
|
|
428
|
+
}
|
|
429
|
+
.cv-transfer-notice-dismiss:hover { color: var(--cv-text); background: var(--cv-surface-2); }
|
|
430
|
+
.cv-transfer-notice-dismiss:active { transform: scale(0.88); }
|
|
431
|
+
|
|
296
432
|
/* ── Buttons ─────────────────────────────────────────────────────────────────── */
|
|
297
433
|
.cv-btn {
|
|
298
434
|
font: 600 0.875rem var(--cv-font);
|
|
@@ -494,6 +630,16 @@
|
|
|
494
630
|
gap: 0.15rem;
|
|
495
631
|
text-align: center;
|
|
496
632
|
padding: 1rem;
|
|
633
|
+
/*
|
|
634
|
+
A REAL bug, found live (plan T7): the transfer picker's agent list can make this box's content
|
|
635
|
+
taller than the space `flex: 1` actually allocates it — the avatar/name/timer/status ABOVE the
|
|
636
|
+
picker are still shown while transferring, unlike `.cv-call-devices-inline`'s own "swap the
|
|
637
|
+
content" fix for the pre-connect devices screen. Without this, the overflow painted straight past
|
|
638
|
+
`.cv-call`'s own shrunk box and onto `.cv-controls` below it — not scroll, actual overlap, controls
|
|
639
|
+
rendered ON TOP of list rows. `overflow-y: auto` keeps any excess inside THIS box, scrollable,
|
|
640
|
+
exactly like `.cv-presence-list`'s own internal scroll already does for the list itself.
|
|
641
|
+
*/
|
|
642
|
+
overflow-y: auto;
|
|
497
643
|
}
|
|
498
644
|
|
|
499
645
|
.cv-avatar-wrap { position: relative; margin-bottom: 0.85rem; }
|
|
@@ -572,7 +718,7 @@
|
|
|
572
718
|
}
|
|
573
719
|
.cv-badge-hold { color: var(--cv-hold); font-weight: 600; }
|
|
574
720
|
|
|
575
|
-
/* ──
|
|
721
|
+
/* ── Device check (ringing / dialing / in-call) ────────────────────────────────
|
|
576
722
|
Before a call connects there is only ONE other control on screen (Colgar, or
|
|
577
723
|
Rechazar/Contestar) — putting Dispositivos in that same neighbourhood, even
|
|
578
724
|
spaced out, keeps it a mis-tap away from hanging up or answering. The entry
|
|
@@ -588,6 +734,11 @@
|
|
|
588
734
|
cramped and scrolly for just two rows. `.cv-call-devices-inline` REPLACES the
|
|
589
735
|
avatar/name/status block in `.cv-call` instead (see that JSX's own comment) —
|
|
590
736
|
an inline swap, not an overlay, so it gets the full box, not a leftover sliver.
|
|
737
|
+
|
|
738
|
+
Once connected it is the SAME chip and the SAME swap. Dispositivos used to be a fifth control in
|
|
739
|
+
the call row (with a floating popover), which is what forced that row down to 40px buttons and
|
|
740
|
+
9px labels in a 310px host. A set-once setting does not need a slot among the four things you do
|
|
741
|
+
mid-call (mute, hold, transfer, keypad), and the control row stays live under the swap.
|
|
591
742
|
───────────────────────────────────────────────────────────────────────────── */
|
|
592
743
|
.cv-call-devices-chip {
|
|
593
744
|
display: inline-flex;
|
|
@@ -660,16 +811,22 @@
|
|
|
660
811
|
display: flex;
|
|
661
812
|
flex-direction: column;
|
|
662
813
|
align-items: center;
|
|
663
|
-
gap: 0.
|
|
814
|
+
gap: 0.9rem;
|
|
664
815
|
padding: 0.35rem 1rem 1.1rem;
|
|
665
|
-
/* The containing block for `.cv-
|
|
816
|
+
/* The containing block for `.cv-keypad-popover` — see that rule's own comment for why it is
|
|
666
817
|
anchored here rather than to the trigger button. */
|
|
667
818
|
position: relative;
|
|
668
819
|
}
|
|
820
|
+
/* FOUR controls, sized so they never need to shrink to fit. This row held five (Dispositivos too) and
|
|
821
|
+
the only way to fit five in the CRM's 310px host was a 40px button with a 9px label and ~6px gaps —
|
|
822
|
+
below the 44/48px a thumb needs, and below legible for a word read mid-call. The default 48px size
|
|
823
|
+
below was never actually seen: it only applied above a 360px host, which no real embed is.
|
|
824
|
+
Dispositivos is the `.cv-call-chips` chip up by the call info instead (the same entry point the
|
|
825
|
+
ringing and dialing screens already use). 4 × 52 + 3 × 20 = 268px, inside 310 - 2 × 16 padding. */
|
|
669
826
|
.cv-controls-row {
|
|
670
827
|
display: flex;
|
|
671
828
|
justify-content: center;
|
|
672
|
-
gap: 1.
|
|
829
|
+
gap: 1.25rem;
|
|
673
830
|
}
|
|
674
831
|
.cv-controls-primary {
|
|
675
832
|
display: flex;
|
|
@@ -692,9 +849,12 @@
|
|
|
692
849
|
white-space: nowrap;
|
|
693
850
|
user-select: none;
|
|
694
851
|
}
|
|
852
|
+
/* The four secondaries' words get a notch more than Colgar / Rechazar / Contestar's 10px — they are
|
|
853
|
+
the ones read mid-call, and the five-up row used to shrink them to 9px (8px in a sidebar). */
|
|
854
|
+
.cv-controls-row .cv-ctrl-label { font-size: 0.6875rem; }
|
|
695
855
|
.cv-ctrl {
|
|
696
|
-
width:
|
|
697
|
-
height:
|
|
856
|
+
width: 52px;
|
|
857
|
+
height: 52px;
|
|
698
858
|
border-radius: 999px;
|
|
699
859
|
border: 1px solid var(--cv-border-strong);
|
|
700
860
|
background: var(--cv-bg);
|
|
@@ -707,6 +867,11 @@
|
|
|
707
867
|
}
|
|
708
868
|
.cv-ctrl:hover { background: var(--cv-surface); }
|
|
709
869
|
.cv-ctrl:active { transform: scale(0.94); }
|
|
870
|
+
.cv-ctrl:disabled {
|
|
871
|
+
opacity: 0.4;
|
|
872
|
+
cursor: not-allowed;
|
|
873
|
+
pointer-events: none;
|
|
874
|
+
}
|
|
710
875
|
|
|
711
876
|
/* The ON states say what they MEAN, in the widget's own tokens: muted is danger,
|
|
712
877
|
held is hold, transfer-open is accent. Colour is the state, not decoration. */
|
|
@@ -752,56 +917,326 @@
|
|
|
752
917
|
border-color: var(--cv-text);
|
|
753
918
|
}
|
|
754
919
|
|
|
920
|
+
/*
|
|
921
|
+
Sidebar-narrow (this file's own ≤300px tier, up in "Narrow hosts"). The four 52px controls with
|
|
922
|
+
20px gaps need 268px, which a 260px host cannot give — so this tier steps down to 44px with 12px
|
|
923
|
+
gaps (4 × 44 + 3 × 12 = 212px) and reclaims `.cv-controls`'s own horizontal padding, the first
|
|
924
|
+
lever that block's own comment names. 44px is still the Apple HIG minimum tap target; the five-up
|
|
925
|
+
row this replaced went to 36px here.
|
|
926
|
+
|
|
927
|
+
Placed AFTER `.cv-controls`/`.cv-controls-row` above rather than up with this file's other
|
|
928
|
+
`@container` blocks near the top: `gap` and `padding-left`/`-right` here have the same specificity as
|
|
929
|
+
those base rules' own shorthand, so — unlike a compound selector such as `.cv-controls-row .cv-ctrl`,
|
|
930
|
+
which wins on specificity regardless of position — source order is what decides, and a narrower-width
|
|
931
|
+
override declared BEFORE the base rule it means to narrow loses to it. Confirmed live: moved up into
|
|
932
|
+
the "Narrow hosts" section, the `.cv-ctrl` width and label font-size reductions took effect (compound
|
|
933
|
+
selectors) but `gap` and `.cv-controls`'s padding silently did not (plain selectors, later base rule won).
|
|
934
|
+
*/
|
|
935
|
+
@container cv (max-width: 300px) {
|
|
936
|
+
.cv-controls { padding-left: 0.5rem; padding-right: 0.5rem; }
|
|
937
|
+
.cv-controls-row { gap: 0.75rem; }
|
|
938
|
+
.cv-controls-row .cv-ctrl { width: 44px; height: 44px; }
|
|
939
|
+
.cv-controls-row .cv-ctrl-label { font-size: 0.625rem; }
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/*
|
|
943
|
+
The attended-transfer target-entry panel (`docs/specs/transfer-availability.md` §5): an optional
|
|
944
|
+
outcome line, then a row of whatever's actionable (input+button today). Once a consult exists,
|
|
945
|
+
`ConsultScreen` takes over the whole screen instead — this panel is ONLY ever the pre-consult /
|
|
946
|
+
retry-after-failure state now; it used to also cover the consulting/answered phases, which is why
|
|
947
|
+
its rule is a column container built for more than one child even though there's only ever one row
|
|
948
|
+
here today. (History: was two near-duplicate rules — `.cv-transfer` as a bare ROW,
|
|
949
|
+
`.cv-transfer-consult` as a column — until the row version turned out to be a real,
|
|
950
|
+
reproduced-in-browser bug: the optional `.cv-dial-outcome` message rendered as a THIRD item in the
|
|
951
|
+
same horizontal row as the input and button, squeezing the input to its content-minimum. Merged
|
|
952
|
+
rather than patched.)
|
|
953
|
+
*/
|
|
755
954
|
.cv-transfer {
|
|
955
|
+
display: flex;
|
|
956
|
+
flex-direction: column;
|
|
957
|
+
gap: 0.3rem;
|
|
958
|
+
width: 100%;
|
|
959
|
+
padding: 0.2rem 0.25rem 0;
|
|
960
|
+
/* `.cv-call` centres and centre-aligns its normal (avatar) content — same reasoning
|
|
961
|
+
`.cv-call-devices-inline` already opts out of for the OTHER inline swap in this box (its own
|
|
962
|
+
comment): rows read left-aligned everywhere else in the widget, and a centred context line
|
|
963
|
+
sitting directly above a left-aligned input/toggle/list read as two layouts stacked on top of
|
|
964
|
+
each other, found live (2026-09-29). */
|
|
965
|
+
text-align: left;
|
|
966
|
+
/* Found live (2026-09-29): `.cv-call`'s avatar/name/timer block used to sit ABOVE this,
|
|
967
|
+
unconditionally, so this panel only ever got whatever was left over — see the JSX call site's own
|
|
968
|
+
comment. Now that this IS the whole of `.cv-call`'s content while a transfer is in progress
|
|
969
|
+
(a swap, not an addition), it should CLAIM `.cv-call`'s available height, not just sit in it —
|
|
970
|
+
`flex: 1` does that; `min-height: 0` is what lets a flex child actually shrink to fit instead of
|
|
971
|
+
forcing its parent to grow past it (the same reason `.cv-call`/`.cv-view`/`.cv-body` all set it,
|
|
972
|
+
see their own comments). This is what lets `.cv-presence-list` below flex-grow into real room
|
|
973
|
+
instead of needing its own hand-tuned `max-height` guess. */
|
|
974
|
+
flex: 1;
|
|
975
|
+
min-height: 0;
|
|
976
|
+
/* Same entrance `.cv-call-devices-inline` already uses for the analogous inline swap (its own
|
|
977
|
+
comment) — reused, not a second animation invented for this widget's second inline-swap view. */
|
|
978
|
+
animation: cv-call-devices-in 0.18s cubic-bezier(0.2, 0, 0.2, 1);
|
|
979
|
+
}
|
|
980
|
+
@media (prefers-reduced-motion: reduce) {
|
|
981
|
+
.cv-transfer { animation: none; }
|
|
982
|
+
}
|
|
983
|
+
/* The compact "who am I still on the phone with" line while the picker is open — reuses
|
|
984
|
+
`.cv-call-devices-inline`'s own two classes verbatim (`.cv-call-devices-title` for the name,
|
|
985
|
+
`.cv-call-devices-context` for the number/timer line) rather than inventing a second "quiet header"
|
|
986
|
+
style for the same widget; only the tiny stacking gap between them is new.
|
|
987
|
+
|
|
988
|
+
Found live (2026-09-29): `.cv-transfer`'s own `gap` alone gave every section — context, input row,
|
|
989
|
+
mode toggle, results list — the exact same spacing, so nothing read as its own group; the eye had
|
|
990
|
+
no cue for where "who I'm on the phone with" ends and "pick a transfer target" begins. This extra
|
|
991
|
+
`margin-bottom`, on top of the base `gap`, is that cue — the toggle stays close to the list it
|
|
992
|
+
controls (unchanged), only the boundary above the interactive controls opened up. */
|
|
993
|
+
.cv-transfer-context {
|
|
994
|
+
display: flex;
|
|
995
|
+
flex-direction: column;
|
|
996
|
+
gap: 2px;
|
|
997
|
+
flex-shrink: 0;
|
|
998
|
+
margin-bottom: 0.35rem;
|
|
999
|
+
}
|
|
1000
|
+
/* Plan T3: the mode toggle reuses `.cv-segmented` (HistoryTab's own filter control) as-is, but its
|
|
1001
|
+
`margin-bottom` (needed THERE, where the surrounding layout has no gap of its own) is redundant
|
|
1002
|
+
here — `.cv-transfer`'s own `gap` above already spaces every child, so the two would stack. Scoped
|
|
1003
|
+
to this context only; HistoryTab's own copy is untouched. */
|
|
1004
|
+
.cv-transfer .cv-segmented { margin-bottom: 0; flex-shrink: 0; }
|
|
1005
|
+
.cv-transfer .cv-presence-legend { flex-shrink: 0; }
|
|
1006
|
+
/* Same treatment as `.cv-call-status` (the avatar's own "Llamando…"/"En espera" line) — one muted
|
|
1007
|
+
status-line vocabulary for the whole call screen, not a second one invented for this panel. */
|
|
1008
|
+
.cv-transfer-status {
|
|
1009
|
+
margin: 0;
|
|
1010
|
+
font-size: 0.78rem;
|
|
1011
|
+
color: var(--cv-muted);
|
|
1012
|
+
letter-spacing: 0.04em;
|
|
1013
|
+
}
|
|
1014
|
+
/* The target-entry/retry row: an input plus one button. */
|
|
1015
|
+
.cv-transfer-row {
|
|
1016
|
+
display: flex;
|
|
1017
|
+
gap: 0.5rem;
|
|
1018
|
+
}
|
|
1019
|
+
/*
|
|
1020
|
+
Flex items default to `min-width: auto`, which floors them at their CONTENT size rather than letting
|
|
1021
|
+
them shrink or grow to fill the row — `.cv-search`'s own `width: 100%` never actually took effect
|
|
1022
|
+
here, because `.cv-btn`'s text ("Llamar") set an unshrinkable floor and the input, having no
|
|
1023
|
+
`flex-grow`, never reclaimed the space left over. `flex: 1` + `min-width: 0` is what actually makes
|
|
1024
|
+
an input-plus-button row behave like one; `flex: none` keeps the button at its natural size.
|
|
1025
|
+
*/
|
|
1026
|
+
.cv-transfer-row .cv-search {
|
|
1027
|
+
flex: 1;
|
|
1028
|
+
min-width: 0;
|
|
1029
|
+
}
|
|
1030
|
+
/* `max-width` + ellipsis: the label now includes whatever was typed ("Llamar a {typed}", spec §4.5)
|
|
1031
|
+
and `truncateForButton` already bounds that in JS — this is the CSS backstop, so a value that
|
|
1032
|
+
slips past it (a very wide character set, a future copy change) still can't push `.cv-search` down
|
|
1033
|
+
to an unusable sliver the way the pre-truncation button did before this was noticed. */
|
|
1034
|
+
.cv-transfer-row .cv-btn {
|
|
1035
|
+
flex: none;
|
|
1036
|
+
max-width: 60%;
|
|
1037
|
+
overflow: hidden;
|
|
1038
|
+
text-overflow: ellipsis;
|
|
1039
|
+
white-space: nowrap;
|
|
1040
|
+
}
|
|
1041
|
+
/* The consult-answered row: one or two buttons, no input. */
|
|
1042
|
+
.cv-transfer-actions {
|
|
756
1043
|
display: flex;
|
|
757
1044
|
gap: 0.5rem;
|
|
1045
|
+
}
|
|
1046
|
+
.cv-transfer-actions .cv-btn {
|
|
1047
|
+
flex: 1;
|
|
1048
|
+
}
|
|
1049
|
+
/* The ringing phase has only "Cancelar" — a secondary, low-stakes action. Letting the row's own
|
|
1050
|
+
`flex: 1` stretch a LONE button edge to edge reads as oversized for what it is, and nothing else in
|
|
1051
|
+
this widget sizes a single button to the full row; every other `.cv-btn` sizes to its content. */
|
|
1052
|
+
.cv-transfer-actions .cv-btn:only-child {
|
|
1053
|
+
flex: none;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
/*
|
|
1057
|
+
The agent picker (spec §4.5, plan T7) — an inline, always-visible filtered list under the
|
|
1058
|
+
input+button row, not a click-to-open popover like `.cv-person-filter-pop`: the whole point is that
|
|
1059
|
+
typing already filters it, so hiding it behind a second interaction would undo that.
|
|
1060
|
+
|
|
1061
|
+
Redesigned live (2026-09-29): T7 (72px) and T3 (30px) both hand-tuned a `max-height` in PIXELS
|
|
1062
|
+
against whatever else happened to be on screen at the time, and both were broken by the very next
|
|
1063
|
+
addition above the list (T3's own toggle broke T7's number the same way this would keep breaking on
|
|
1064
|
+
the next change) — down to "barely proves the list is scrollable" at 30px, which is what the user
|
|
1065
|
+
was actually seeing: "users cannot almost see any of the listed users." The real fix wasn't a bigger
|
|
1066
|
+
magic number, it was `.cv-transfer`'s own move to `flex: 1` (see its comment) freeing real height
|
|
1067
|
+
from the block that used to sit above this whole panel — `.cv-presence` and this list now flex-grow
|
|
1068
|
+
into whatever's ACTUALLY left after the context line, input row, toggle and legend take their own
|
|
1069
|
+
natural size, on whatever real height the host panel gives `.cv-call` (this SDK's fixed ~310×520
|
|
1070
|
+
embed today, but also whatever a different host gives it tomorrow — no more re-tuning a constant
|
|
1071
|
+
every time something above the list changes). `.cv-call`'s own `overflow-y: auto` (its own comment)
|
|
1072
|
+
is still the last-resort net if content ever genuinely doesn't fit; this just means that net should
|
|
1073
|
+
now rarely, if ever, have to catch anything for a normal agent list.
|
|
1074
|
+
*/
|
|
1075
|
+
.cv-presence {
|
|
1076
|
+
display: flex;
|
|
1077
|
+
flex-direction: column;
|
|
1078
|
+
gap: 0.35rem;
|
|
1079
|
+
flex: 1;
|
|
1080
|
+
min-height: 0;
|
|
1081
|
+
}
|
|
1082
|
+
.cv-presence-list {
|
|
1083
|
+
display: flex;
|
|
1084
|
+
flex-direction: column;
|
|
1085
|
+
gap: 2px;
|
|
1086
|
+
flex: 1;
|
|
1087
|
+
min-height: 0;
|
|
1088
|
+
overflow-y: auto;
|
|
1089
|
+
padding: 0.25rem;
|
|
1090
|
+
border: 1px solid var(--cv-border);
|
|
1091
|
+
border-radius: var(--cv-radius-key);
|
|
1092
|
+
background: var(--cv-surface);
|
|
1093
|
+
}
|
|
1094
|
+
.cv-presence-empty {
|
|
1095
|
+
margin: 0;
|
|
1096
|
+
padding: 0.5rem;
|
|
1097
|
+
text-align: center;
|
|
1098
|
+
font-size: 0.78rem;
|
|
1099
|
+
color: var(--cv-muted);
|
|
1100
|
+
}
|
|
1101
|
+
.cv-presence-item {
|
|
758
1102
|
width: 100%;
|
|
759
|
-
|
|
1103
|
+
display: flex;
|
|
1104
|
+
align-items: center;
|
|
1105
|
+
gap: 0.5rem;
|
|
1106
|
+
padding: 0.4rem 0.5rem;
|
|
1107
|
+
border: none;
|
|
1108
|
+
border-radius: calc(var(--cv-radius) - 4px);
|
|
1109
|
+
background: none;
|
|
1110
|
+
color: var(--cv-text);
|
|
1111
|
+
font: 400 0.8rem var(--cv-font);
|
|
1112
|
+
text-align: left;
|
|
1113
|
+
cursor: pointer;
|
|
1114
|
+
}
|
|
1115
|
+
.cv-presence-item:hover:not(:disabled) { background: var(--cv-surface-2); }
|
|
1116
|
+
/* En llamada rows are a hard block, not just a hint (CallScreen.tsx's own comment on the row has why)
|
|
1117
|
+
— same `:disabled` treatment `.cv-btn`/`.cv-tab` already use elsewhere in this file, not a new pattern. */
|
|
1118
|
+
.cv-presence-item:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
1119
|
+
.cv-presence-dot {
|
|
1120
|
+
flex-shrink: 0;
|
|
1121
|
+
width: 8px;
|
|
1122
|
+
height: 8px;
|
|
1123
|
+
border-radius: 999px;
|
|
1124
|
+
}
|
|
1125
|
+
/* Reuses existing intent tokens rather than inventing new ones — `--cv-accent` already means
|
|
1126
|
+
"good, reachable" (the answer button), `--cv-hold` already means "occupied elsewhere" (the hold
|
|
1127
|
+
toggle), and `--cv-faint` is this file's own DECORATIVE-only tier (see the `--cv-*` legend near the
|
|
1128
|
+
top) — exactly what "no signal for this person" is, no signal being the whole point of that tier. */
|
|
1129
|
+
.cv-presence-dot[data-state='disponible'] { background: var(--cv-accent); }
|
|
1130
|
+
.cv-presence-dot[data-state='en_llamada'] { background: var(--cv-hold); }
|
|
1131
|
+
.cv-presence-dot[data-state='desconectado'] { background: var(--cv-faint); }
|
|
1132
|
+
.cv-presence-name {
|
|
1133
|
+
flex: 1;
|
|
1134
|
+
min-width: 0;
|
|
1135
|
+
overflow: hidden;
|
|
1136
|
+
text-overflow: ellipsis;
|
|
1137
|
+
white-space: nowrap;
|
|
1138
|
+
}
|
|
1139
|
+
.cv-presence-meta {
|
|
1140
|
+
flex-shrink: 0;
|
|
1141
|
+
font-size: 0.72rem;
|
|
1142
|
+
color: var(--cv-muted);
|
|
1143
|
+
}
|
|
1144
|
+
/* Spec §4.6: Desconectado is a HINT, never "can't transfer" — this is what tells the agent so, right
|
|
1145
|
+
under the list it describes. `--cv-muted`, NOT `--cv-faint`: this text is informational (the reader
|
|
1146
|
+
needs it to not misread the state), and `--cv-faint` is reserved for decorative-only content that
|
|
1147
|
+
fails AA on purpose — using it here would repeat the exact tier mistake this file's own `--cv-*`
|
|
1148
|
+
comment block warns against. */
|
|
1149
|
+
.cv-presence-legend {
|
|
1150
|
+
margin: 0;
|
|
1151
|
+
font-size: 0.7rem;
|
|
1152
|
+
color: var(--cv-muted);
|
|
1153
|
+
line-height: 1.35;
|
|
760
1154
|
}
|
|
761
1155
|
|
|
762
1156
|
/*
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
screen
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
Anchored to `.cv-controls`'s own horizontal padding — a container whose width is bounded by ITS
|
|
771
|
-
parent, never the narrow trigger itself — the same fix CountryPicker's own popover needed (see its
|
|
772
|
-
comment).
|
|
1157
|
+
`ConsultScreen`'s "someone is still waiting" banner (`docs/specs/transfer-availability.md` §5, the
|
|
1158
|
+
cross-talk fix) — full-width and tappable, not a passive status line, because the entire reason this
|
|
1159
|
+
screen exists is to make "go back to the caller" impossible to miss. Neutral surface + the same
|
|
1160
|
+
`--cv-hold` colour `.cv-badge-hold` already uses for the same fact elsewhere, not a new soft-fill
|
|
1161
|
+
token: a text/icon tint on a plain surface is already proven legible here, and inventing an
|
|
1162
|
+
unmeasured background-tint pairing risks a real contrast regression this file takes seriously
|
|
1163
|
+
elsewhere (see the `-soft`/`-strong` split's own comments).
|
|
773
1164
|
*/
|
|
774
|
-
.cv-
|
|
1165
|
+
.cv-consult-hold-banner {
|
|
1166
|
+
display: flex;
|
|
1167
|
+
align-items: center;
|
|
1168
|
+
justify-content: center;
|
|
1169
|
+
gap: 0.4rem;
|
|
1170
|
+
width: 100%;
|
|
1171
|
+
padding: 0.5rem 0.75rem;
|
|
1172
|
+
border-radius: 999px;
|
|
1173
|
+
border: 1px solid var(--cv-border);
|
|
1174
|
+
background: var(--cv-surface);
|
|
1175
|
+
color: var(--cv-hold);
|
|
1176
|
+
font: 600 0.78rem var(--cv-font);
|
|
1177
|
+
cursor: pointer;
|
|
1178
|
+
transition: background 0.15s ease, border-color 0.15s ease;
|
|
1179
|
+
}
|
|
1180
|
+
.cv-consult-hold-banner:hover {
|
|
1181
|
+
background: var(--cv-surface-2);
|
|
1182
|
+
border-color: var(--cv-hold);
|
|
1183
|
+
}
|
|
1184
|
+
.cv-consult-hold-banner:active {
|
|
1185
|
+
transform: scale(0.98);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
@keyframes cv-pop-in-up {
|
|
1189
|
+
from { opacity: 0; transform: translateY(4px) scale(0.97); }
|
|
1190
|
+
to { opacity: 1; transform: none; }
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/*
|
|
1194
|
+
The in-call DTMF keypad — the one floating popover left on the call screen. (Dispositivos was the
|
|
1195
|
+
other; it is inline content now, `.cv-call-devices-inline` above, in every call state.)
|
|
1196
|
+
|
|
1197
|
+
Opens UPWARD (`bottom: 100%`): the trigger sits at the bottom of the call screen, and there is no
|
|
1198
|
+
room to open downward. Anchored to `.cv-controls`'s own horizontal padding — a container whose width
|
|
1199
|
+
is bounded by ITS parent, never the narrow trigger itself — the same fix CountryPicker's own popover
|
|
1200
|
+
needed (see its comment): anchoring to a narrow, off-centre trigger let the popover's edge reach
|
|
1201
|
+
`.cv-softphone`'s `overflow: hidden` and get clipped.
|
|
1202
|
+
*/
|
|
1203
|
+
.cv-keypad-popover {
|
|
775
1204
|
position: absolute;
|
|
776
1205
|
z-index: 20;
|
|
777
|
-
display:
|
|
778
|
-
|
|
779
|
-
gap:
|
|
780
|
-
padding: 0.
|
|
1206
|
+
display: grid;
|
|
1207
|
+
grid-template-columns: repeat(3, 1fr);
|
|
1208
|
+
gap: 8px;
|
|
1209
|
+
padding: 0.85rem 1rem;
|
|
781
1210
|
background: var(--cv-surface);
|
|
782
1211
|
border: 1px solid var(--cv-border);
|
|
783
1212
|
border-radius: var(--cv-radius);
|
|
784
1213
|
box-shadow: var(--cv-shadow);
|
|
785
1214
|
}
|
|
786
|
-
.cv-
|
|
1215
|
+
.cv-keypad-popover--above {
|
|
787
1216
|
bottom: 100%;
|
|
788
1217
|
left: 1rem;
|
|
789
1218
|
right: 1rem;
|
|
790
1219
|
margin-bottom: 0.6rem;
|
|
791
1220
|
transform-origin: bottom center;
|
|
792
|
-
animation: cv-
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
1221
|
+
animation: cv-pop-in-up 0.14s cubic-bezier(0.2, 0, 0.2, 1);
|
|
1222
|
+
}
|
|
1223
|
+
/* `.cv-key` already carries the full key look (border, hover, active-scale, digit/letter type) from
|
|
1224
|
+
the pre-call dialer — only the size needs setting here, since this grid has no flex ancestor to
|
|
1225
|
+
stretch the rows the way `.cv-keypad` gets to.
|
|
1226
|
+
|
|
1227
|
+
A fixed HEIGHT, not an `aspect-ratio`. This popover opens upward from `.cv-controls`, so it has
|
|
1228
|
+
(host height - controls block - margin) to work with, and a ratio ties its height to the host's
|
|
1229
|
+
WIDTH, which says nothing about how much height there is. Found live: the CRM's real body is 310×473
|
|
1230
|
+
(a 520px panel minus its 45px header), and a 1.3 ratio made this popover 285px — with the 184px
|
|
1231
|
+
controls block that is 479px, so its top ~7px were clipped by `.cv-softphone`'s `overflow: hidden`.
|
|
1232
|
+
48px keys give a 243px popover at ANY width, fit that host with room to spare, and stay at the
|
|
1233
|
+
44-48px minimum tap target (the old ratio gave 45px keys at a 260px host, 58px at 310). */
|
|
1234
|
+
.cv-keypad-popover .cv-key {
|
|
1235
|
+
height: 48px;
|
|
797
1236
|
}
|
|
798
1237
|
@media (prefers-reduced-motion: reduce) {
|
|
799
|
-
.cv-
|
|
1238
|
+
.cv-keypad-popover--above { animation: none; }
|
|
800
1239
|
}
|
|
801
|
-
/* No per-row override needed here: `.cv-settings-row`/`.cv-settings-note` carry no border,
|
|
802
|
-
background or padding of their own (see the Settings tab block) — this popover's own `gap` and
|
|
803
|
-
`padding` are the only spacing in play, which is what keeps it lighter than the full Ajustes
|
|
804
|
-
page's bordered section for what is meant to be a quick, transient panel. */
|
|
805
1240
|
|
|
806
1241
|
/* ── Lists (contacts / history) ──────────────────────────────────────────────── */
|
|
807
1242
|
.cv-list-head { flex-shrink: 0; padding: 0.85rem 1rem 0.5rem; }
|
|
@@ -814,6 +1249,13 @@
|
|
|
814
1249
|
color: var(--cv-text);
|
|
815
1250
|
font: inherit;
|
|
816
1251
|
transition: border-color 0.15s ease, background 0.15s ease;
|
|
1252
|
+
/* Found live (2026-09-29): in the transfer row specifically, `.cv-btn`'s own `max-width: 60%`
|
|
1253
|
+
(needed for the dynamic "Llamar a {typed}" label) can leave the input narrower than its
|
|
1254
|
+
placeholder text — an `<input>` has no native ellipsis, so it hard-clipped mid-word
|
|
1255
|
+
("...o núm") instead of trailing off cleanly. A real, if rare, risk for ANY `.cv-search` usage
|
|
1256
|
+
wherever it's squeezed, not just this one row — the fix belongs on the base rule. */
|
|
1257
|
+
overflow: hidden;
|
|
1258
|
+
text-overflow: ellipsis;
|
|
817
1259
|
}
|
|
818
1260
|
.cv-search::placeholder { color: var(--cv-muted); }
|
|
819
1261
|
.cv-search:focus { outline: none; border-color: var(--cv-accent); background: var(--cv-bg); }
|