@coventia/softphone 0.1.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.
- package/dist/3x2-2HQTJDKZ.js +6583 -0
- package/dist/3x2-2HQTJDKZ.js.map +1 -0
- package/dist/3x2-INKWPNLA.js +6585 -0
- package/dist/3x2-INKWPNLA.js.map +1 -0
- package/dist/call-BTYlT2SU.d.cts +680 -0
- package/dist/call-BTYlT2SU.d.ts +680 -0
- package/dist/chunk-2ZSOGGPO.js +169 -0
- package/dist/chunk-2ZSOGGPO.js.map +1 -0
- package/dist/chunk-3V2L6UTK.js +129 -0
- package/dist/chunk-3V2L6UTK.js.map +1 -0
- package/dist/chunk-5BGEHMPP.js +945 -0
- package/dist/chunk-5BGEHMPP.js.map +1 -0
- package/dist/chunk-5WRI5ZAA.js +29 -0
- package/dist/chunk-5WRI5ZAA.js.map +1 -0
- package/dist/chunk-KAXEMJ7E.js +11 -0
- package/dist/chunk-KAXEMJ7E.js.map +1 -0
- package/dist/chunk-MHOJHG5E.js +39 -0
- package/dist/chunk-MHOJHG5E.js.map +1 -0
- package/dist/chunk-MP7CSA24.js +299 -0
- package/dist/chunk-MP7CSA24.js.map +1 -0
- package/dist/chunk-N2N2EQQJ.js +29 -0
- package/dist/chunk-N2N2EQQJ.js.map +1 -0
- package/dist/element/index.d.ts +853 -0
- package/dist/element/index.js +9635 -0
- package/dist/element/index.js.map +1 -0
- package/dist/engine-D9nbeY08.d.cts +115 -0
- package/dist/engine-Doa6Brkm.d.ts +115 -0
- package/dist/index.cjs +2133 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +62 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.js +630 -0
- package/dist/index.js.map +1 -0
- package/dist/min-64GIMWWL.js +5456 -0
- package/dist/min-64GIMWWL.js.map +1 -0
- package/dist/min-ATXYR23R.js +5458 -0
- package/dist/min-ATXYR23R.js.map +1 -0
- package/dist/react/index.cjs +138 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +68 -0
- package/dist/react/index.d.ts +68 -0
- package/dist/react/index.js +4 -0
- package/dist/react/index.js.map +1 -0
- package/dist/softphone-DHmhotbf.d.ts +128 -0
- package/dist/softphone-DhuhcKCy.d.cts +128 -0
- package/dist/softphone.css +1923 -0
- package/dist/sources-N4BOEDRL.js +226 -0
- package/dist/sources-N4BOEDRL.js.map +1 -0
- package/dist/testing/index.cjs +345 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +66 -0
- package/dist/testing/index.d.ts +66 -0
- package/dist/testing/index.js +186 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/ui/index.cjs +15428 -0
- package/dist/ui/index.cjs.map +1 -0
- package/dist/ui/index.d.cts +188 -0
- package/dist/ui/index.d.ts +188 -0
- package/dist/ui/index.js +2256 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/zadarma/index.cjs +1144 -0
- package/dist/zadarma/index.cjs.map +1 -0
- package/dist/zadarma/index.d.cts +86 -0
- package/dist/zadarma/index.d.ts +86 -0
- package/dist/zadarma/index.js +5 -0
- package/dist/zadarma/index.js.map +1 -0
- package/dist/zadarma-engine-DN2SZSQ3.js +5 -0
- package/dist/zadarma-engine-DN2SZSQ3.js.map +1 -0
- package/package.json +123 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { g as Contact, u as ContactsSource, v as HistorySource, a as Call } from '../call-BTYlT2SU.cjs';
|
|
4
|
+
export { w as CallHistoryEntry, x as ContactsPage } from '../call-BTYlT2SU.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Shaped like a Lucide icon (`size`, `className`, both optional — every SVG prop Lucide's own icons
|
|
8
|
+
* take is optional too, so a real Lucide component satisfies this structurally) WITHOUT naming
|
|
9
|
+
* `lucide-react`'s own exported type. A host should not need that package installed just to satisfy
|
|
10
|
+
* ours — this accepts Lucide itself, or any icon set built the same shape.
|
|
11
|
+
*/
|
|
12
|
+
type ContactActionIcon = (props: {
|
|
13
|
+
readonly size?: number | string;
|
|
14
|
+
readonly className?: string;
|
|
15
|
+
}) => ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* The one customisable action on a contact's detail page — was the legacy's hard-wired "Ver
|
|
18
|
+
* mensajes" (`useNavigate('/chats?wa_id=…')`), now genuinely the host's: whatever `onClick` does,
|
|
19
|
+
* under whatever `label` fits it. "Open a support ticket," "Ver ficha en el CRM," anything.
|
|
20
|
+
*
|
|
21
|
+
* Omit `contactAction` entirely and the row simply does not exist — the detail page is then just
|
|
22
|
+
* the avatar, the name, the phone number, and the call button. A row with a hardcoded label and no
|
|
23
|
+
* handler would be worse than no row at all.
|
|
24
|
+
*
|
|
25
|
+
* Deliberately NOT a render prop (no arbitrary React node accepted here). Every other host-supplied
|
|
26
|
+
* piece of this widget is DATA — a contacts function, a history array, a callback — never a chunk of
|
|
27
|
+
* JSX to render as-is; that is what keeps the widget looking like one thing instead of drifting row
|
|
28
|
+
* by row. `icon` is optional so a partner without a natural icon for their action is not forced to
|
|
29
|
+
* pick one.
|
|
30
|
+
*/
|
|
31
|
+
interface ContactAction {
|
|
32
|
+
readonly label: string;
|
|
33
|
+
readonly icon?: ContactActionIcon;
|
|
34
|
+
readonly onClick: (contact: Contact) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* `'system'` (default) follows the OS via `prefers-color-scheme`. Pin it to match the HOST's theme
|
|
39
|
+
* instead — the CRM toggles dark with a class (next-themes), not the OS, so a dark OS + light app
|
|
40
|
+
* would otherwise render a dark widget inside a light page.
|
|
41
|
+
*
|
|
42
|
+
* const { resolvedTheme } = useTheme();
|
|
43
|
+
* <SoftphoneWidget theme={resolvedTheme} />
|
|
44
|
+
*/
|
|
45
|
+
type SoftphoneTheme = 'light' | 'dark' | 'system';
|
|
46
|
+
interface SoftphoneWidgetProps {
|
|
47
|
+
/** Light, dark, or follow the OS (default). See `SoftphoneTheme`. */
|
|
48
|
+
readonly theme?: SoftphoneTheme;
|
|
49
|
+
/**
|
|
50
|
+
* Override the Contactos tab with your own source. Rarely needed — `coventia` already supplies it.
|
|
51
|
+
* Passing this WITHOUT `coventia` also works, and is how a non-Coventia host would drive the tab.
|
|
52
|
+
*/
|
|
53
|
+
readonly contacts?: ContactsSource;
|
|
54
|
+
/**
|
|
55
|
+
* Override the Historial tab. Rarely correct: Coventia receives the Zadarma events and stores the
|
|
56
|
+
* calls, so a host-built history is a different, smaller thing than the real one (SPEC §6.6).
|
|
57
|
+
*
|
|
58
|
+
* The tab's own "Todas"/"Perdidas" and person filters call this with `missed`/`userId` — an
|
|
59
|
+
* override that ignores them still works, it just always returns everything regardless of which
|
|
60
|
+
* filter is selected, which reads as the filter UI being broken. The person filter itself has no
|
|
61
|
+
* override point: it always reads `softphone.sources.listAgents`, Coventia's own org directory.
|
|
62
|
+
*/
|
|
63
|
+
readonly history?: HistorySource;
|
|
64
|
+
/**
|
|
65
|
+
* Ask for the microphone before showing the dialer. **On by default.**
|
|
66
|
+
*
|
|
67
|
+
* A softphone without a microphone is not a softphone, so this is not a feature to opt into — an
|
|
68
|
+
* integrator who does not know to add a gate would otherwise ship a dialer that looks fine and
|
|
69
|
+
* fails on the first call, with the browser's permission modal appearing over a ringing
|
|
70
|
+
* conversation. Being on by default means the failure mode requires a deliberate choice.
|
|
71
|
+
*
|
|
72
|
+
* Set `false` when the mic is somebody else's problem: a demo driven by `MockProvider`, a
|
|
73
|
+
* supervisor view that only watches, or a host that already prompted and wraps the widget itself
|
|
74
|
+
* (see `MicPermissionGate`).
|
|
75
|
+
*/
|
|
76
|
+
readonly requireMic?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Play call audio: the remote party, the inbound ring, the outbound ringback, and a short cue when
|
|
79
|
+
* a connected call ends — by either side. **On by default.**
|
|
80
|
+
*
|
|
81
|
+
* The remote-party half is not a nicety — nothing else attaches the `MediaStream`, so with this
|
|
82
|
+
* off a connected call is silent in both directions. Turn it off only if the host attaches
|
|
83
|
+
* `call.remoteStream` itself (see `CallEvent.RemoteStream`), or for a supervisor view that watches
|
|
84
|
+
* without listening.
|
|
85
|
+
*/
|
|
86
|
+
readonly sounds?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The action row on a contact's detail page. Tapping a contact in the list always opens that page
|
|
89
|
+
* now (avatar, name, phone, `Llamar`) — this is the one optional extra row on it. See
|
|
90
|
+
* `ContactAction`. Renamed from `onContactAction`, which fired directly on tap with no detail page
|
|
91
|
+
* in between; that page is what this replaces "open a contact" with (SPEC §4).
|
|
92
|
+
*/
|
|
93
|
+
readonly contactAction?: ContactAction;
|
|
94
|
+
/**
|
|
95
|
+
* A second, independent action chip — this one on the INCOMING call screen, next to the
|
|
96
|
+
* "Dispositivos" chip, while the phone is ringing. Only shown once the caller resolves to a real
|
|
97
|
+
* contact (`resolveContact` has to have actually matched them; SPEC §4) — the legacy softphone's
|
|
98
|
+
* own "Ver mensajes" button used the identical "known contacts only" gate, for the same reason:
|
|
99
|
+
* there is nothing useful to open for a number that isn't anyone yet.
|
|
100
|
+
*
|
|
101
|
+
* Deliberately a SEPARATE prop from `contactAction`, not the same value reused — what is worth
|
|
102
|
+
* surfacing while someone is actively calling you is not necessarily the same thing that belongs
|
|
103
|
+
* on that contact's static detail page days later. Same `ContactAction` shape (label, optional
|
|
104
|
+
* icon, `onClick(contact)`) because it is the same KIND of thing, just a different instance a host
|
|
105
|
+
* can configure independently, or omit entirely to show only "Dispositivos" there, as today.
|
|
106
|
+
*/
|
|
107
|
+
readonly incomingCallAction?: ContactAction;
|
|
108
|
+
/** Extra class on the root, for host layout. */
|
|
109
|
+
readonly className?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The softphone widget (legacy ZadarmaWidget) — the drop-in call UI. Wrap it in a
|
|
114
|
+
* `<SoftphoneProvider softphone={…}>` and that is all: it asks for the microphone ITSELF
|
|
115
|
+
* (`requireMic`, on by default), so no integrator has to know that a phone needs one.
|
|
116
|
+
*
|
|
117
|
+
* When a call is live, the call screen takes the whole body and the tabs hide. Otherwise the tabbed
|
|
118
|
+
* interface (Teclado / Contactos / Historial) shows. Contactos/Historial appear only when their data
|
|
119
|
+
* source is provided — the widget stays useful as a bare dialer with no backend at all.
|
|
120
|
+
*/
|
|
121
|
+
declare function SoftphoneWidget(props: SoftphoneWidgetProps): react.JSX.Element;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Gate arbitrary children on microphone permission.
|
|
125
|
+
*
|
|
126
|
+
* **`SoftphoneWidget` now gates itself** (`requireMic`, on by default), so most integrations need
|
|
127
|
+
* nothing here — a softphone without a microphone is not a softphone, and making the gate opt-in
|
|
128
|
+
* meant every integrator had to know to opt in or ship something that fails mid-call.
|
|
129
|
+
*
|
|
130
|
+
* This stays exported for hosts that want the prompt somewhere else: their own modal, a page-level
|
|
131
|
+
* onboarding step, or wrapping something larger than the widget.
|
|
132
|
+
*/
|
|
133
|
+
declare function MicPermissionGate({ children }: Readonly<{
|
|
134
|
+
children: ReactNode;
|
|
135
|
+
}>): react.JSX.Element;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The keypad view (legacy IdleView). Strings are Spanish (SPEC §2.4).
|
|
139
|
+
*
|
|
140
|
+
* Layout is three flex rows — head (fixed) / keypad (flex:1) / foot (fixed) — so the keypad absorbs
|
|
141
|
+
* whatever height is left. Sizing keys by aspect-ratio instead would overflow the shell and push the
|
|
142
|
+
* call button under the tab bar.
|
|
143
|
+
*/
|
|
144
|
+
interface DialpadProps {
|
|
145
|
+
/** The outcome of the last attempt — "Sin respuesta", "Llamada rechazada". Non-fatal only. */
|
|
146
|
+
readonly outcome?: {
|
|
147
|
+
readonly code: string;
|
|
148
|
+
readonly text: string;
|
|
149
|
+
} | null;
|
|
150
|
+
/** Called on any action that supersedes that outcome: a digit, a backspace, a dial. */
|
|
151
|
+
readonly onIntent?: () => void;
|
|
152
|
+
}
|
|
153
|
+
declare function Dialpad({ outcome, onIntent }?: DialpadProps): react.JSX.Element;
|
|
154
|
+
|
|
155
|
+
/** The active-call view: incoming, outgoing and in-call in one, switched on call.state. */
|
|
156
|
+
declare function CallScreen({ call, incomingCallAction, }: Readonly<{
|
|
157
|
+
call: Call;
|
|
158
|
+
incomingCallAction?: ContactAction;
|
|
159
|
+
}>): react.JSX.Element | null;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The Contactos tab — decoupled. Data comes from an injected `ContactsSource`; contacts are
|
|
163
|
+
* `Contact { id, name, phone }` (never `wa_id`, SPEC §4). Tapping a contact always opens its detail
|
|
164
|
+
* page (`ContactDetail`) — `contactAction` customises the ONE extra row on it, not what tapping the
|
|
165
|
+
* list itself does; there is no bypass of the detail page from here.
|
|
166
|
+
*/
|
|
167
|
+
declare function ContactsTab({ source, contactAction, }: Readonly<{
|
|
168
|
+
source: ContactsSource;
|
|
169
|
+
contactAction?: ContactAction;
|
|
170
|
+
}>): react.JSX.Element;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* The Historial tab — decoupled. Entries come from an injected `HistorySource` (SPEC §4). Tapping a
|
|
174
|
+
* row always opens its detail page (`HistoryDetail`) — the row's own call button places a call
|
|
175
|
+
* directly, without opening it. Same split `ContactsTab`/`ContactDetail` already settled on, for the
|
|
176
|
+
* same reason: a row-wide tap target and a specific, separate action live at different button.
|
|
177
|
+
*
|
|
178
|
+
* The two filters (status, person) are local UI state — `HistorySource` merely accepts them as
|
|
179
|
+
* optional params, same as `ContactsSource` accepts `search`, so a host's own override can honour
|
|
180
|
+
* them or ignore them. The person directory behind the second filter is different: it is always
|
|
181
|
+
* Coventia's own org membership (there is no partner override point for it, unlike `contacts`), so
|
|
182
|
+
* it is read straight off `softphone.sources` rather than threaded through as a prop.
|
|
183
|
+
*/
|
|
184
|
+
declare function HistoryTab({ source }: Readonly<{
|
|
185
|
+
source: HistorySource;
|
|
186
|
+
}>): react.JSX.Element;
|
|
187
|
+
|
|
188
|
+
export { CallScreen, ContactsSource, ContactsTab, Dialpad, HistorySource, HistoryTab, MicPermissionGate, type SoftphoneTheme, SoftphoneWidget, type SoftphoneWidgetProps };
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { g as Contact, u as ContactsSource, v as HistorySource, a as Call } from '../call-BTYlT2SU.js';
|
|
4
|
+
export { w as CallHistoryEntry, x as ContactsPage } from '../call-BTYlT2SU.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Shaped like a Lucide icon (`size`, `className`, both optional — every SVG prop Lucide's own icons
|
|
8
|
+
* take is optional too, so a real Lucide component satisfies this structurally) WITHOUT naming
|
|
9
|
+
* `lucide-react`'s own exported type. A host should not need that package installed just to satisfy
|
|
10
|
+
* ours — this accepts Lucide itself, or any icon set built the same shape.
|
|
11
|
+
*/
|
|
12
|
+
type ContactActionIcon = (props: {
|
|
13
|
+
readonly size?: number | string;
|
|
14
|
+
readonly className?: string;
|
|
15
|
+
}) => ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* The one customisable action on a contact's detail page — was the legacy's hard-wired "Ver
|
|
18
|
+
* mensajes" (`useNavigate('/chats?wa_id=…')`), now genuinely the host's: whatever `onClick` does,
|
|
19
|
+
* under whatever `label` fits it. "Open a support ticket," "Ver ficha en el CRM," anything.
|
|
20
|
+
*
|
|
21
|
+
* Omit `contactAction` entirely and the row simply does not exist — the detail page is then just
|
|
22
|
+
* the avatar, the name, the phone number, and the call button. A row with a hardcoded label and no
|
|
23
|
+
* handler would be worse than no row at all.
|
|
24
|
+
*
|
|
25
|
+
* Deliberately NOT a render prop (no arbitrary React node accepted here). Every other host-supplied
|
|
26
|
+
* piece of this widget is DATA — a contacts function, a history array, a callback — never a chunk of
|
|
27
|
+
* JSX to render as-is; that is what keeps the widget looking like one thing instead of drifting row
|
|
28
|
+
* by row. `icon` is optional so a partner without a natural icon for their action is not forced to
|
|
29
|
+
* pick one.
|
|
30
|
+
*/
|
|
31
|
+
interface ContactAction {
|
|
32
|
+
readonly label: string;
|
|
33
|
+
readonly icon?: ContactActionIcon;
|
|
34
|
+
readonly onClick: (contact: Contact) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* `'system'` (default) follows the OS via `prefers-color-scheme`. Pin it to match the HOST's theme
|
|
39
|
+
* instead — the CRM toggles dark with a class (next-themes), not the OS, so a dark OS + light app
|
|
40
|
+
* would otherwise render a dark widget inside a light page.
|
|
41
|
+
*
|
|
42
|
+
* const { resolvedTheme } = useTheme();
|
|
43
|
+
* <SoftphoneWidget theme={resolvedTheme} />
|
|
44
|
+
*/
|
|
45
|
+
type SoftphoneTheme = 'light' | 'dark' | 'system';
|
|
46
|
+
interface SoftphoneWidgetProps {
|
|
47
|
+
/** Light, dark, or follow the OS (default). See `SoftphoneTheme`. */
|
|
48
|
+
readonly theme?: SoftphoneTheme;
|
|
49
|
+
/**
|
|
50
|
+
* Override the Contactos tab with your own source. Rarely needed — `coventia` already supplies it.
|
|
51
|
+
* Passing this WITHOUT `coventia` also works, and is how a non-Coventia host would drive the tab.
|
|
52
|
+
*/
|
|
53
|
+
readonly contacts?: ContactsSource;
|
|
54
|
+
/**
|
|
55
|
+
* Override the Historial tab. Rarely correct: Coventia receives the Zadarma events and stores the
|
|
56
|
+
* calls, so a host-built history is a different, smaller thing than the real one (SPEC §6.6).
|
|
57
|
+
*
|
|
58
|
+
* The tab's own "Todas"/"Perdidas" and person filters call this with `missed`/`userId` — an
|
|
59
|
+
* override that ignores them still works, it just always returns everything regardless of which
|
|
60
|
+
* filter is selected, which reads as the filter UI being broken. The person filter itself has no
|
|
61
|
+
* override point: it always reads `softphone.sources.listAgents`, Coventia's own org directory.
|
|
62
|
+
*/
|
|
63
|
+
readonly history?: HistorySource;
|
|
64
|
+
/**
|
|
65
|
+
* Ask for the microphone before showing the dialer. **On by default.**
|
|
66
|
+
*
|
|
67
|
+
* A softphone without a microphone is not a softphone, so this is not a feature to opt into — an
|
|
68
|
+
* integrator who does not know to add a gate would otherwise ship a dialer that looks fine and
|
|
69
|
+
* fails on the first call, with the browser's permission modal appearing over a ringing
|
|
70
|
+
* conversation. Being on by default means the failure mode requires a deliberate choice.
|
|
71
|
+
*
|
|
72
|
+
* Set `false` when the mic is somebody else's problem: a demo driven by `MockProvider`, a
|
|
73
|
+
* supervisor view that only watches, or a host that already prompted and wraps the widget itself
|
|
74
|
+
* (see `MicPermissionGate`).
|
|
75
|
+
*/
|
|
76
|
+
readonly requireMic?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Play call audio: the remote party, the inbound ring, the outbound ringback, and a short cue when
|
|
79
|
+
* a connected call ends — by either side. **On by default.**
|
|
80
|
+
*
|
|
81
|
+
* The remote-party half is not a nicety — nothing else attaches the `MediaStream`, so with this
|
|
82
|
+
* off a connected call is silent in both directions. Turn it off only if the host attaches
|
|
83
|
+
* `call.remoteStream` itself (see `CallEvent.RemoteStream`), or for a supervisor view that watches
|
|
84
|
+
* without listening.
|
|
85
|
+
*/
|
|
86
|
+
readonly sounds?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The action row on a contact's detail page. Tapping a contact in the list always opens that page
|
|
89
|
+
* now (avatar, name, phone, `Llamar`) — this is the one optional extra row on it. See
|
|
90
|
+
* `ContactAction`. Renamed from `onContactAction`, which fired directly on tap with no detail page
|
|
91
|
+
* in between; that page is what this replaces "open a contact" with (SPEC §4).
|
|
92
|
+
*/
|
|
93
|
+
readonly contactAction?: ContactAction;
|
|
94
|
+
/**
|
|
95
|
+
* A second, independent action chip — this one on the INCOMING call screen, next to the
|
|
96
|
+
* "Dispositivos" chip, while the phone is ringing. Only shown once the caller resolves to a real
|
|
97
|
+
* contact (`resolveContact` has to have actually matched them; SPEC §4) — the legacy softphone's
|
|
98
|
+
* own "Ver mensajes" button used the identical "known contacts only" gate, for the same reason:
|
|
99
|
+
* there is nothing useful to open for a number that isn't anyone yet.
|
|
100
|
+
*
|
|
101
|
+
* Deliberately a SEPARATE prop from `contactAction`, not the same value reused — what is worth
|
|
102
|
+
* surfacing while someone is actively calling you is not necessarily the same thing that belongs
|
|
103
|
+
* on that contact's static detail page days later. Same `ContactAction` shape (label, optional
|
|
104
|
+
* icon, `onClick(contact)`) because it is the same KIND of thing, just a different instance a host
|
|
105
|
+
* can configure independently, or omit entirely to show only "Dispositivos" there, as today.
|
|
106
|
+
*/
|
|
107
|
+
readonly incomingCallAction?: ContactAction;
|
|
108
|
+
/** Extra class on the root, for host layout. */
|
|
109
|
+
readonly className?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The softphone widget (legacy ZadarmaWidget) — the drop-in call UI. Wrap it in a
|
|
114
|
+
* `<SoftphoneProvider softphone={…}>` and that is all: it asks for the microphone ITSELF
|
|
115
|
+
* (`requireMic`, on by default), so no integrator has to know that a phone needs one.
|
|
116
|
+
*
|
|
117
|
+
* When a call is live, the call screen takes the whole body and the tabs hide. Otherwise the tabbed
|
|
118
|
+
* interface (Teclado / Contactos / Historial) shows. Contactos/Historial appear only when their data
|
|
119
|
+
* source is provided — the widget stays useful as a bare dialer with no backend at all.
|
|
120
|
+
*/
|
|
121
|
+
declare function SoftphoneWidget(props: SoftphoneWidgetProps): react.JSX.Element;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Gate arbitrary children on microphone permission.
|
|
125
|
+
*
|
|
126
|
+
* **`SoftphoneWidget` now gates itself** (`requireMic`, on by default), so most integrations need
|
|
127
|
+
* nothing here — a softphone without a microphone is not a softphone, and making the gate opt-in
|
|
128
|
+
* meant every integrator had to know to opt in or ship something that fails mid-call.
|
|
129
|
+
*
|
|
130
|
+
* This stays exported for hosts that want the prompt somewhere else: their own modal, a page-level
|
|
131
|
+
* onboarding step, or wrapping something larger than the widget.
|
|
132
|
+
*/
|
|
133
|
+
declare function MicPermissionGate({ children }: Readonly<{
|
|
134
|
+
children: ReactNode;
|
|
135
|
+
}>): react.JSX.Element;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The keypad view (legacy IdleView). Strings are Spanish (SPEC §2.4).
|
|
139
|
+
*
|
|
140
|
+
* Layout is three flex rows — head (fixed) / keypad (flex:1) / foot (fixed) — so the keypad absorbs
|
|
141
|
+
* whatever height is left. Sizing keys by aspect-ratio instead would overflow the shell and push the
|
|
142
|
+
* call button under the tab bar.
|
|
143
|
+
*/
|
|
144
|
+
interface DialpadProps {
|
|
145
|
+
/** The outcome of the last attempt — "Sin respuesta", "Llamada rechazada". Non-fatal only. */
|
|
146
|
+
readonly outcome?: {
|
|
147
|
+
readonly code: string;
|
|
148
|
+
readonly text: string;
|
|
149
|
+
} | null;
|
|
150
|
+
/** Called on any action that supersedes that outcome: a digit, a backspace, a dial. */
|
|
151
|
+
readonly onIntent?: () => void;
|
|
152
|
+
}
|
|
153
|
+
declare function Dialpad({ outcome, onIntent }?: DialpadProps): react.JSX.Element;
|
|
154
|
+
|
|
155
|
+
/** The active-call view: incoming, outgoing and in-call in one, switched on call.state. */
|
|
156
|
+
declare function CallScreen({ call, incomingCallAction, }: Readonly<{
|
|
157
|
+
call: Call;
|
|
158
|
+
incomingCallAction?: ContactAction;
|
|
159
|
+
}>): react.JSX.Element | null;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The Contactos tab — decoupled. Data comes from an injected `ContactsSource`; contacts are
|
|
163
|
+
* `Contact { id, name, phone }` (never `wa_id`, SPEC §4). Tapping a contact always opens its detail
|
|
164
|
+
* page (`ContactDetail`) — `contactAction` customises the ONE extra row on it, not what tapping the
|
|
165
|
+
* list itself does; there is no bypass of the detail page from here.
|
|
166
|
+
*/
|
|
167
|
+
declare function ContactsTab({ source, contactAction, }: Readonly<{
|
|
168
|
+
source: ContactsSource;
|
|
169
|
+
contactAction?: ContactAction;
|
|
170
|
+
}>): react.JSX.Element;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* The Historial tab — decoupled. Entries come from an injected `HistorySource` (SPEC §4). Tapping a
|
|
174
|
+
* row always opens its detail page (`HistoryDetail`) — the row's own call button places a call
|
|
175
|
+
* directly, without opening it. Same split `ContactsTab`/`ContactDetail` already settled on, for the
|
|
176
|
+
* same reason: a row-wide tap target and a specific, separate action live at different button.
|
|
177
|
+
*
|
|
178
|
+
* The two filters (status, person) are local UI state — `HistorySource` merely accepts them as
|
|
179
|
+
* optional params, same as `ContactsSource` accepts `search`, so a host's own override can honour
|
|
180
|
+
* them or ignore them. The person directory behind the second filter is different: it is always
|
|
181
|
+
* Coventia's own org membership (there is no partner override point for it, unlike `contacts`), so
|
|
182
|
+
* it is read straight off `softphone.sources` rather than threaded through as a prop.
|
|
183
|
+
*/
|
|
184
|
+
declare function HistoryTab({ source }: Readonly<{
|
|
185
|
+
source: HistorySource;
|
|
186
|
+
}>): react.JSX.Element;
|
|
187
|
+
|
|
188
|
+
export { CallScreen, ContactsSource, ContactsTab, Dialpad, HistorySource, HistoryTab, MicPermissionGate, type SoftphoneTheme, SoftphoneWidget, type SoftphoneWidgetProps };
|