@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.
Files changed (69) hide show
  1. package/dist/3x2-2HQTJDKZ.js +6583 -0
  2. package/dist/3x2-2HQTJDKZ.js.map +1 -0
  3. package/dist/3x2-INKWPNLA.js +6585 -0
  4. package/dist/3x2-INKWPNLA.js.map +1 -0
  5. package/dist/call-BTYlT2SU.d.cts +680 -0
  6. package/dist/call-BTYlT2SU.d.ts +680 -0
  7. package/dist/chunk-2ZSOGGPO.js +169 -0
  8. package/dist/chunk-2ZSOGGPO.js.map +1 -0
  9. package/dist/chunk-3V2L6UTK.js +129 -0
  10. package/dist/chunk-3V2L6UTK.js.map +1 -0
  11. package/dist/chunk-5BGEHMPP.js +945 -0
  12. package/dist/chunk-5BGEHMPP.js.map +1 -0
  13. package/dist/chunk-5WRI5ZAA.js +29 -0
  14. package/dist/chunk-5WRI5ZAA.js.map +1 -0
  15. package/dist/chunk-KAXEMJ7E.js +11 -0
  16. package/dist/chunk-KAXEMJ7E.js.map +1 -0
  17. package/dist/chunk-MHOJHG5E.js +39 -0
  18. package/dist/chunk-MHOJHG5E.js.map +1 -0
  19. package/dist/chunk-MP7CSA24.js +299 -0
  20. package/dist/chunk-MP7CSA24.js.map +1 -0
  21. package/dist/chunk-N2N2EQQJ.js +29 -0
  22. package/dist/chunk-N2N2EQQJ.js.map +1 -0
  23. package/dist/element/index.d.ts +853 -0
  24. package/dist/element/index.js +9635 -0
  25. package/dist/element/index.js.map +1 -0
  26. package/dist/engine-D9nbeY08.d.cts +115 -0
  27. package/dist/engine-Doa6Brkm.d.ts +115 -0
  28. package/dist/index.cjs +2133 -0
  29. package/dist/index.cjs.map +1 -0
  30. package/dist/index.d.cts +62 -0
  31. package/dist/index.d.ts +62 -0
  32. package/dist/index.js +630 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/min-64GIMWWL.js +5456 -0
  35. package/dist/min-64GIMWWL.js.map +1 -0
  36. package/dist/min-ATXYR23R.js +5458 -0
  37. package/dist/min-ATXYR23R.js.map +1 -0
  38. package/dist/react/index.cjs +138 -0
  39. package/dist/react/index.cjs.map +1 -0
  40. package/dist/react/index.d.cts +68 -0
  41. package/dist/react/index.d.ts +68 -0
  42. package/dist/react/index.js +4 -0
  43. package/dist/react/index.js.map +1 -0
  44. package/dist/softphone-DHmhotbf.d.ts +128 -0
  45. package/dist/softphone-DhuhcKCy.d.cts +128 -0
  46. package/dist/softphone.css +1923 -0
  47. package/dist/sources-N4BOEDRL.js +226 -0
  48. package/dist/sources-N4BOEDRL.js.map +1 -0
  49. package/dist/testing/index.cjs +345 -0
  50. package/dist/testing/index.cjs.map +1 -0
  51. package/dist/testing/index.d.cts +66 -0
  52. package/dist/testing/index.d.ts +66 -0
  53. package/dist/testing/index.js +186 -0
  54. package/dist/testing/index.js.map +1 -0
  55. package/dist/ui/index.cjs +15428 -0
  56. package/dist/ui/index.cjs.map +1 -0
  57. package/dist/ui/index.d.cts +188 -0
  58. package/dist/ui/index.d.ts +188 -0
  59. package/dist/ui/index.js +2256 -0
  60. package/dist/ui/index.js.map +1 -0
  61. package/dist/zadarma/index.cjs +1144 -0
  62. package/dist/zadarma/index.cjs.map +1 -0
  63. package/dist/zadarma/index.d.cts +86 -0
  64. package/dist/zadarma/index.d.ts +86 -0
  65. package/dist/zadarma/index.js +5 -0
  66. package/dist/zadarma/index.js.map +1 -0
  67. package/dist/zadarma-engine-DN2SZSQ3.js +5 -0
  68. package/dist/zadarma-engine-DN2SZSQ3.js.map +1 -0
  69. 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 };