@signalwire/web-components 4.0.0-beta.1 → 4.0.0-beta.11
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/README.md +9 -10
- package/dist/components/audio-level.d.ts +114 -0
- package/dist/components/audio-level.d.ts.map +1 -0
- package/dist/components/audio-level.js +203 -0
- package/dist/components/audio-level.js.map +1 -0
- package/dist/components/call-controls.d.ts +183 -0
- package/dist/components/call-controls.d.ts.map +1 -0
- package/dist/components/call-controls.js +606 -0
- package/dist/components/call-controls.js.map +1 -0
- package/dist/components/call-media.d.ts +118 -0
- package/dist/components/call-media.d.ts.map +1 -0
- package/dist/components/call-media.js +219 -0
- package/dist/components/call-media.js.map +1 -0
- package/dist/components/call-status.d.ts +83 -0
- package/dist/components/call-status.d.ts.map +1 -0
- package/dist/components/call-status.js +255 -0
- package/dist/components/call-status.js.map +1 -0
- package/dist/components/click-to-call.d.ts +151 -0
- package/dist/components/click-to-call.d.ts.map +1 -0
- package/dist/components/click-to-call.js +428 -0
- package/dist/components/click-to-call.js.map +1 -0
- package/dist/components/device-selector.d.ts +238 -0
- package/dist/components/device-selector.d.ts.map +1 -0
- package/dist/components/device-selector.js +685 -0
- package/dist/components/device-selector.js.map +1 -0
- package/dist/components/dialpad.d.ts +74 -0
- package/dist/components/dialpad.d.ts.map +1 -0
- package/dist/components/dialpad.js +372 -0
- package/dist/components/dialpad.js.map +1 -0
- package/dist/components/directory.d.ts +125 -0
- package/dist/components/directory.d.ts.map +1 -0
- package/dist/components/directory.js +503 -0
- package/dist/components/directory.js.map +1 -0
- package/dist/components/example-button.d.ts +21 -0
- package/dist/components/example-button.d.ts.map +1 -0
- package/dist/components/example-button.js +74 -0
- package/dist/components/example-button.js.map +1 -0
- package/dist/components/participant-controls.d.ts +123 -0
- package/dist/components/participant-controls.d.ts.map +1 -0
- package/dist/components/participant-controls.js +468 -0
- package/dist/components/participant-controls.js.map +1 -0
- package/dist/components/participants.d.ts +120 -0
- package/dist/components/participants.d.ts.map +1 -0
- package/dist/components/participants.js +394 -0
- package/dist/components/participants.js.map +1 -0
- package/dist/components/self-media.d.ts +78 -0
- package/dist/components/self-media.d.ts.map +1 -0
- package/dist/components/self-media.js +129 -0
- package/dist/components/self-media.js.map +1 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/context/call-context.d.ts +13 -0
- package/dist/context/call-context.d.ts.map +1 -0
- package/dist/context/call-context.js +6 -0
- package/dist/context/call-context.js.map +1 -0
- package/dist/context/index.d.ts +2 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -5644
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +122 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/debounce.d.ts +10 -0
- package/dist/utils/debounce.d.ts.map +1 -0
- package/dist/utils/debounce.js +13 -0
- package/dist/utils/debounce.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/video.d.ts +34 -0
- package/dist/utils/video.d.ts.map +1 -0
- package/dist/utils/video.js +26 -0
- package/dist/utils/video.js.map +1 -0
- package/package.json +70 -3
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { LitElement as d, html as u, css as p } from "lit";
|
|
2
|
+
import { property as h, state as i, customElement as f } from "lit/decorators.js";
|
|
3
|
+
import { consume as m } from "@lit/context";
|
|
4
|
+
import { callContext as w } from "../context/call-context.js";
|
|
5
|
+
var g = Object.defineProperty, x = Object.getOwnPropertyDescriptor, o = (t, s, e, a) => {
|
|
6
|
+
for (var n = a > 1 ? void 0 : a ? x(s, e) : s, c = t.length - 1, l; c >= 0; c--)
|
|
7
|
+
(l = t[c]) && (n = (a ? l(s, e, n) : l(n)) || n);
|
|
8
|
+
return a && n && g(s, e, n), n;
|
|
9
|
+
};
|
|
10
|
+
let r = class extends d {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments), this.call = null, this.status = "new", this.callStartTime = null, this.duration = "0:00", this.subscriptions = [], this.durationInterval = null;
|
|
13
|
+
}
|
|
14
|
+
connectedCallback() {
|
|
15
|
+
super.connectedCallback(), this.subscribeToCall();
|
|
16
|
+
}
|
|
17
|
+
disconnectedCallback() {
|
|
18
|
+
super.disconnectedCallback(), this.cleanup();
|
|
19
|
+
}
|
|
20
|
+
updated(t) {
|
|
21
|
+
(t.has("call") || t.has("contextCall")) && (this.cleanup(), this.subscribeToCall());
|
|
22
|
+
}
|
|
23
|
+
get activeCall() {
|
|
24
|
+
return this.call || this.contextCall || null;
|
|
25
|
+
}
|
|
26
|
+
subscribeToCall() {
|
|
27
|
+
const t = this.activeCall;
|
|
28
|
+
if (!(t != null && t.status$)) return;
|
|
29
|
+
const s = t.status$.subscribe((e) => {
|
|
30
|
+
const a = this.status;
|
|
31
|
+
this.status = e, e === "connected" && a !== "connected" ? this.startDurationTimer() : e !== "connected" && this.stopDurationTimer();
|
|
32
|
+
});
|
|
33
|
+
this.subscriptions.push(s);
|
|
34
|
+
}
|
|
35
|
+
startDurationTimer() {
|
|
36
|
+
this.callStartTime = Date.now(), this.duration = "0:00", this.durationInterval = window.setInterval(() => {
|
|
37
|
+
if (this.callStartTime) {
|
|
38
|
+
const t = Math.floor((Date.now() - this.callStartTime) / 1e3);
|
|
39
|
+
this.duration = this.formatDuration(t);
|
|
40
|
+
}
|
|
41
|
+
}, 1e3);
|
|
42
|
+
}
|
|
43
|
+
stopDurationTimer() {
|
|
44
|
+
this.durationInterval && (clearInterval(this.durationInterval), this.durationInterval = null), this.callStartTime = null, this.duration = "0:00";
|
|
45
|
+
}
|
|
46
|
+
formatDuration(t) {
|
|
47
|
+
const s = Math.floor(t / 3600), e = Math.floor(t % 3600 / 60), a = t % 60;
|
|
48
|
+
return s > 0 ? `${s}:${e.toString().padStart(2, "0")}:${a.toString().padStart(2, "0")}` : `${e}:${a.toString().padStart(2, "0")}`;
|
|
49
|
+
}
|
|
50
|
+
cleanup() {
|
|
51
|
+
this.subscriptions.forEach((t) => t.unsubscribe()), this.subscriptions = [], this.stopDurationTimer();
|
|
52
|
+
}
|
|
53
|
+
getStatusText() {
|
|
54
|
+
switch (this.status) {
|
|
55
|
+
case "new":
|
|
56
|
+
return "Ready";
|
|
57
|
+
case "trying":
|
|
58
|
+
return "Trying...";
|
|
59
|
+
case "connecting":
|
|
60
|
+
return "Connecting...";
|
|
61
|
+
case "ringing":
|
|
62
|
+
return "Ringing...";
|
|
63
|
+
case "connected":
|
|
64
|
+
return "Connected";
|
|
65
|
+
case "recovering":
|
|
66
|
+
return "Reconnecting...";
|
|
67
|
+
case "disconnecting":
|
|
68
|
+
return "Disconnecting...";
|
|
69
|
+
case "disconnected":
|
|
70
|
+
return "Disconnected";
|
|
71
|
+
case "failed":
|
|
72
|
+
return "Failed";
|
|
73
|
+
case "destroyed":
|
|
74
|
+
return "Ended";
|
|
75
|
+
default: {
|
|
76
|
+
const t = this.status;
|
|
77
|
+
return String(t);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
render() {
|
|
82
|
+
const t = this.getStatusText(), s = this.status === "connected";
|
|
83
|
+
return u`
|
|
84
|
+
<div class="container" part="container">
|
|
85
|
+
<span class="status-indicator ${this.status}" aria-hidden="true"></span>
|
|
86
|
+
<span
|
|
87
|
+
class="status-text ${this.status}"
|
|
88
|
+
part="status-text"
|
|
89
|
+
role="status"
|
|
90
|
+
aria-live="polite"
|
|
91
|
+
>
|
|
92
|
+
${t}
|
|
93
|
+
</span>
|
|
94
|
+
${s ? u`<span class="duration" part="duration">${this.duration}</span>` : null}
|
|
95
|
+
</div>
|
|
96
|
+
`;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
r.styles = p`
|
|
100
|
+
:host {
|
|
101
|
+
/* CSS Custom Properties for theming */
|
|
102
|
+
--sw-color-primary: #044cf6;
|
|
103
|
+
--sw-color-success: #10b981;
|
|
104
|
+
--sw-color-warning: #f59e0b;
|
|
105
|
+
--sw-color-danger: #ef4444;
|
|
106
|
+
--sw-color-text: #1f2937;
|
|
107
|
+
--sw-color-text-muted: #6b7280;
|
|
108
|
+
--sw-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
109
|
+
--sw-font-size-sm: 14px;
|
|
110
|
+
--sw-font-size-base: 16px;
|
|
111
|
+
--sw-font-size-lg: 18px;
|
|
112
|
+
--sw-space-1: 4px;
|
|
113
|
+
--sw-space-2: 8px;
|
|
114
|
+
--sw-space-3: 12px;
|
|
115
|
+
--sw-border-radius: 8px;
|
|
116
|
+
|
|
117
|
+
display: inline-flex;
|
|
118
|
+
align-items: center;
|
|
119
|
+
gap: var(--sw-space-2);
|
|
120
|
+
font-family: var(--sw-font-family);
|
|
121
|
+
font-size: var(--sw-font-size-base);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Dark mode support */
|
|
125
|
+
:host([data-theme='dark']) {
|
|
126
|
+
--sw-color-text: #f9fafb;
|
|
127
|
+
--sw-color-text-muted: #9ca3af;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@media (prefers-color-scheme: dark) {
|
|
131
|
+
:host(:not([data-theme='light'])) {
|
|
132
|
+
--sw-color-text: #f9fafb;
|
|
133
|
+
--sw-color-text-muted: #9ca3af;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.container {
|
|
138
|
+
display: inline-flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
gap: var(--sw-space-2);
|
|
141
|
+
padding: var(--sw-space-2) var(--sw-space-3);
|
|
142
|
+
border-radius: var(--sw-border-radius);
|
|
143
|
+
color: var(--sw-color-text);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.status-indicator {
|
|
147
|
+
width: 10px;
|
|
148
|
+
height: 10px;
|
|
149
|
+
border-radius: 50%;
|
|
150
|
+
flex-shrink: 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.status-indicator.new {
|
|
154
|
+
background-color: var(--sw-color-text-muted);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.status-indicator.connecting,
|
|
158
|
+
.status-indicator.ringing {
|
|
159
|
+
background-color: var(--sw-color-warning);
|
|
160
|
+
animation: pulse 1.5s ease-in-out infinite;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.status-indicator.connected {
|
|
164
|
+
background-color: var(--sw-color-success);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.status-indicator.disconnecting {
|
|
168
|
+
background-color: var(--sw-color-danger);
|
|
169
|
+
animation: pulse 1s ease-in-out infinite;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.status-indicator.trying {
|
|
173
|
+
background-color: var(--sw-color-warning);
|
|
174
|
+
animation: pulse 1.5s ease-in-out infinite;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.status-indicator.disconnected,
|
|
178
|
+
.status-indicator.failed {
|
|
179
|
+
background-color: var(--sw-color-danger);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.status-indicator.destroyed {
|
|
183
|
+
background-color: var(--sw-color-text-muted);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
@keyframes pulse {
|
|
187
|
+
0%,
|
|
188
|
+
100% {
|
|
189
|
+
opacity: 1;
|
|
190
|
+
transform: scale(1);
|
|
191
|
+
}
|
|
192
|
+
50% {
|
|
193
|
+
opacity: 0.5;
|
|
194
|
+
transform: scale(1.1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.status-text {
|
|
199
|
+
font-weight: 500;
|
|
200
|
+
white-space: nowrap;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.status-text.trying,
|
|
204
|
+
.status-text.connecting,
|
|
205
|
+
.status-text.ringing {
|
|
206
|
+
color: var(--sw-color-warning);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.status-text.disconnecting {
|
|
210
|
+
color: var(--sw-color-danger);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.status-text.connected {
|
|
214
|
+
color: var(--sw-color-success);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.status-text.disconnected,
|
|
218
|
+
.status-text.failed {
|
|
219
|
+
color: var(--sw-color-danger);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.status-text.new,
|
|
223
|
+
.status-text.destroyed {
|
|
224
|
+
color: var(--sw-color-text-muted);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.duration {
|
|
228
|
+
font-variant-numeric: tabular-nums;
|
|
229
|
+
color: var(--sw-color-text-muted);
|
|
230
|
+
font-size: var(--sw-font-size-sm);
|
|
231
|
+
}
|
|
232
|
+
`;
|
|
233
|
+
o([
|
|
234
|
+
h({ attribute: !1 })
|
|
235
|
+
], r.prototype, "call", 2);
|
|
236
|
+
o([
|
|
237
|
+
m({ context: w, subscribe: !0 }),
|
|
238
|
+
i()
|
|
239
|
+
], r.prototype, "contextCall", 2);
|
|
240
|
+
o([
|
|
241
|
+
i()
|
|
242
|
+
], r.prototype, "status", 2);
|
|
243
|
+
o([
|
|
244
|
+
i()
|
|
245
|
+
], r.prototype, "callStartTime", 2);
|
|
246
|
+
o([
|
|
247
|
+
i()
|
|
248
|
+
], r.prototype, "duration", 2);
|
|
249
|
+
r = o([
|
|
250
|
+
f("sw-call-status")
|
|
251
|
+
], r);
|
|
252
|
+
export {
|
|
253
|
+
r as CallStatusComponent
|
|
254
|
+
};
|
|
255
|
+
//# sourceMappingURL=call-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-status.js","sources":["../../src/components/call-status.ts"],"sourcesContent":["/**\n * Call Status Component\n *\n * Displays current call state with status text and duration timer.\n * Shows animated indicators for transient states (connecting, ringing, disconnecting).\n *\n * @example\n * ```html\n * <sw-call-status .call=${call}></sw-call-status>\n * ```\n *\n * @cssprop [--sw-color-primary=#044cf6] - Primary brand color\n * @cssprop [--sw-color-success=#10b981] - Success/connected indicator color\n * @cssprop [--sw-color-warning=#f59e0b] - Warning/connecting indicator color\n * @cssprop [--sw-color-danger=#ef4444] - Danger/disconnecting indicator color\n * @cssprop [--sw-color-text=#1f2937] - Primary text color\n * @cssprop [--sw-color-text-muted=#6b7280] - Secondary/muted text and duration color\n * @cssprop [--sw-font-family=-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif] - Font family\n * @cssprop [--sw-font-size-sm=14px] - Small font size for duration\n * @cssprop [--sw-font-size-base=16px] - Base font size for status text\n * @cssprop [--sw-font-size-lg=18px] - Large font size\n * @cssprop [--sw-space-1=4px] - Smallest spacing unit\n * @cssprop [--sw-space-2=8px] - Small spacing unit\n * @cssprop [--sw-space-3=12px] - Medium spacing unit\n * @cssprop [--sw-border-radius=8px] - Border radius for container\n */\n\nimport { LitElement, html, css } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { consume } from '@lit/context';\nimport { Subscription } from 'rxjs';\nimport type { Observable } from 'rxjs';\nimport type { CallStatus } from '@signalwire/js';\nimport { callContext } from '../context/index.js';\n\n/**\n * Call interface for status component\n */\nexport interface CallStatusCall {\n status$: Observable<CallStatus>;\n}\n\n@customElement('sw-call-status')\nexport class CallStatusComponent extends LitElement {\n static styles = css`\n :host {\n /* CSS Custom Properties for theming */\n --sw-color-primary: #044cf6;\n --sw-color-success: #10b981;\n --sw-color-warning: #f59e0b;\n --sw-color-danger: #ef4444;\n --sw-color-text: #1f2937;\n --sw-color-text-muted: #6b7280;\n --sw-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --sw-font-size-sm: 14px;\n --sw-font-size-base: 16px;\n --sw-font-size-lg: 18px;\n --sw-space-1: 4px;\n --sw-space-2: 8px;\n --sw-space-3: 12px;\n --sw-border-radius: 8px;\n\n display: inline-flex;\n align-items: center;\n gap: var(--sw-space-2);\n font-family: var(--sw-font-family);\n font-size: var(--sw-font-size-base);\n }\n\n /* Dark mode support */\n :host([data-theme='dark']) {\n --sw-color-text: #f9fafb;\n --sw-color-text-muted: #9ca3af;\n }\n\n @media (prefers-color-scheme: dark) {\n :host(:not([data-theme='light'])) {\n --sw-color-text: #f9fafb;\n --sw-color-text-muted: #9ca3af;\n }\n }\n\n .container {\n display: inline-flex;\n align-items: center;\n gap: var(--sw-space-2);\n padding: var(--sw-space-2) var(--sw-space-3);\n border-radius: var(--sw-border-radius);\n color: var(--sw-color-text);\n }\n\n .status-indicator {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .status-indicator.new {\n background-color: var(--sw-color-text-muted);\n }\n\n .status-indicator.connecting,\n .status-indicator.ringing {\n background-color: var(--sw-color-warning);\n animation: pulse 1.5s ease-in-out infinite;\n }\n\n .status-indicator.connected {\n background-color: var(--sw-color-success);\n }\n\n .status-indicator.disconnecting {\n background-color: var(--sw-color-danger);\n animation: pulse 1s ease-in-out infinite;\n }\n\n .status-indicator.trying {\n background-color: var(--sw-color-warning);\n animation: pulse 1.5s ease-in-out infinite;\n }\n\n .status-indicator.disconnected,\n .status-indicator.failed {\n background-color: var(--sw-color-danger);\n }\n\n .status-indicator.destroyed {\n background-color: var(--sw-color-text-muted);\n }\n\n @keyframes pulse {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.5;\n transform: scale(1.1);\n }\n }\n\n .status-text {\n font-weight: 500;\n white-space: nowrap;\n }\n\n .status-text.trying,\n .status-text.connecting,\n .status-text.ringing {\n color: var(--sw-color-warning);\n }\n\n .status-text.disconnecting {\n color: var(--sw-color-danger);\n }\n\n .status-text.connected {\n color: var(--sw-color-success);\n }\n\n .status-text.disconnected,\n .status-text.failed {\n color: var(--sw-color-danger);\n }\n\n .status-text.new,\n .status-text.destroyed {\n color: var(--sw-color-text-muted);\n }\n\n .duration {\n font-variant-numeric: tabular-nums;\n color: var(--sw-color-text-muted);\n font-size: var(--sw-font-size-sm);\n }\n `;\n\n /**\n * Call object with status$ observable\n */\n @property({ attribute: false })\n call: CallStatusCall | null = null;\n\n /**\n * Call from context (if nested in sw-call-media)\n */\n @consume({ context: callContext, subscribe: true })\n @state()\n private contextCall?: CallStatusCall;\n\n /**\n * Current call status\n */\n @state()\n private status: CallStatus = 'new';\n\n /**\n * Call start time for duration calculation\n */\n @state()\n private callStartTime: number | null = null;\n\n /**\n * Formatted duration string\n */\n @state()\n private duration: string = '0:00';\n\n /**\n * RxJS subscriptions for cleanup\n */\n private subscriptions: Subscription[] = [];\n\n /**\n * Duration timer interval\n */\n private durationInterval: number | null = null;\n\n connectedCallback() {\n super.connectedCallback();\n this.subscribeToCall();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.cleanup();\n }\n\n updated(changedProperties: Map<string, unknown>) {\n if (changedProperties.has('call') || changedProperties.has('contextCall')) {\n this.cleanup();\n this.subscribeToCall();\n }\n }\n\n private get activeCall(): CallStatusCall | null {\n return this.call || this.contextCall || null;\n }\n\n private subscribeToCall() {\n const call = this.activeCall;\n if (!call?.status$) return;\n\n const statusSub = call.status$.subscribe((status) => {\n const prevStatus = this.status;\n this.status = status;\n\n // Start duration timer when connected\n if (status === 'connected' && prevStatus !== 'connected') {\n this.startDurationTimer();\n } else if (status !== 'connected') {\n this.stopDurationTimer();\n }\n });\n\n this.subscriptions.push(statusSub);\n }\n\n private startDurationTimer() {\n this.callStartTime = Date.now();\n this.duration = '0:00';\n\n this.durationInterval = window.setInterval(() => {\n if (this.callStartTime) {\n const elapsed = Math.floor((Date.now() - this.callStartTime) / 1000);\n this.duration = this.formatDuration(elapsed);\n }\n }, 1000);\n }\n\n private stopDurationTimer() {\n if (this.durationInterval) {\n clearInterval(this.durationInterval);\n this.durationInterval = null;\n }\n this.callStartTime = null;\n this.duration = '0:00';\n }\n\n private formatDuration(seconds: number): string {\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const secs = seconds % 60;\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n }\n return `${minutes}:${secs.toString().padStart(2, '0')}`;\n }\n\n private cleanup() {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.subscriptions = [];\n this.stopDurationTimer();\n }\n\n private getStatusText(): string {\n switch (this.status) {\n case 'new':\n return 'Ready';\n case 'trying':\n return 'Trying...';\n case 'connecting':\n return 'Connecting...';\n case 'ringing':\n return 'Ringing...';\n case 'connected':\n return 'Connected';\n case 'recovering':\n return 'Reconnecting...';\n case 'disconnecting':\n return 'Disconnecting...';\n case 'disconnected':\n return 'Disconnected';\n case 'failed':\n return 'Failed';\n case 'destroyed':\n return 'Ended';\n default: {\n const _exhaustive: never = this.status;\n return String(_exhaustive);\n }\n }\n }\n\n render() {\n const statusText = this.getStatusText();\n const showDuration = this.status === 'connected';\n\n return html`\n <div class=\"container\" part=\"container\">\n <span class=\"status-indicator ${this.status}\" aria-hidden=\"true\"></span>\n <span\n class=\"status-text ${this.status}\"\n part=\"status-text\"\n role=\"status\"\n aria-live=\"polite\"\n >\n ${statusText}\n </span>\n ${showDuration\n ? html`<span class=\"duration\" part=\"duration\">${this.duration}</span>`\n : null}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-call-status': CallStatusComponent;\n }\n}\n"],"names":["CallStatusComponent","LitElement","changedProperties","call","statusSub","status","prevStatus","elapsed","seconds","hours","minutes","secs","sub","_exhaustive","statusText","showDuration","html","css","__decorateClass","property","consume","callContext","state","customElement"],"mappings":"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"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Click to Call Component
|
|
3
|
+
*
|
|
4
|
+
* A single button widget to initiate calls to a preconfigured destination.
|
|
5
|
+
* Shows minimal UI with call status, duration, and basic controls.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```html
|
|
9
|
+
* <sw-click-to-call
|
|
10
|
+
* destination="sip:support@example.com"
|
|
11
|
+
* .client=${signalWire}
|
|
12
|
+
* label="Call Support"
|
|
13
|
+
* ></sw-click-to-call>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @fires sw-dial - Fired when a call is initiated. Detail: `{ destination: string }`
|
|
17
|
+
* @fires sw-hangup - Fired when the hangup button is clicked.
|
|
18
|
+
* @fires sw-mute-toggle - Fired when the mute button is toggled. Detail: `{ muted: boolean }`
|
|
19
|
+
*
|
|
20
|
+
* @cssprop [--sw-color-primary=#044cf6] - Primary brand color
|
|
21
|
+
* @cssprop [--sw-color-primary-hover=#0339c4] - Primary color on hover
|
|
22
|
+
* @cssprop [--sw-color-success=#10b981] - Success/positive color
|
|
23
|
+
* @cssprop [--sw-color-success-hover=#0ea472] - Success color on hover
|
|
24
|
+
* @cssprop [--sw-color-danger=#ef4444] - Danger/destructive color
|
|
25
|
+
* @cssprop [--sw-color-danger-hover=#dc2626] - Danger color on hover
|
|
26
|
+
* @cssprop [--sw-color-warning=#f59e0b] - Warning color
|
|
27
|
+
* @cssprop [--sw-color-text=#1f2937] - Primary text color
|
|
28
|
+
* @cssprop [--sw-color-text-muted=#6b7280] - Secondary/muted text color
|
|
29
|
+
* @cssprop [--sw-color-text-inverse=#ffffff] - Inverse text color for buttons
|
|
30
|
+
* @cssprop [--sw-color-background=#ffffff] - Component background color
|
|
31
|
+
* @cssprop [--sw-color-background-hover=#f3f4f6] - Background color on hover
|
|
32
|
+
* @cssprop [--sw-color-border=#e5e7eb] - Border color
|
|
33
|
+
* @cssprop [--sw-font-family=-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif] - Font family
|
|
34
|
+
* @cssprop [--sw-font-size-sm=12px] - Small font size
|
|
35
|
+
* @cssprop [--sw-font-size-base=14px] - Base font size
|
|
36
|
+
* @cssprop [--sw-font-size-lg=16px] - Large font size
|
|
37
|
+
* @cssprop [--sw-space-1=4px] - Smallest spacing unit
|
|
38
|
+
* @cssprop [--sw-space-2=8px] - Small spacing unit
|
|
39
|
+
* @cssprop [--sw-space-3=12px] - Medium spacing unit
|
|
40
|
+
* @cssprop [--sw-space-4=16px] - Large spacing unit
|
|
41
|
+
* @cssprop [--sw-border-radius=8px] - Border radius for containers
|
|
42
|
+
* @cssprop [--sw-border-radius-full=9999px] - Fully rounded border radius for circular buttons
|
|
43
|
+
*/
|
|
44
|
+
import { LitElement } from 'lit';
|
|
45
|
+
import type { Observable } from 'rxjs';
|
|
46
|
+
/**
|
|
47
|
+
* Call status type
|
|
48
|
+
*/
|
|
49
|
+
export type ClickToCallStatus = 'idle' | 'connecting' | 'connected' | 'disconnecting' | 'error';
|
|
50
|
+
/**
|
|
51
|
+
* Self participant interface for click-to-call component
|
|
52
|
+
*/
|
|
53
|
+
export interface ClickToCallSelf {
|
|
54
|
+
audioMuted$: Observable<boolean | undefined>;
|
|
55
|
+
mute(): Promise<void>;
|
|
56
|
+
unmute(): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Call interface for click-to-call component
|
|
60
|
+
*/
|
|
61
|
+
export interface ClickToCallCall {
|
|
62
|
+
status$: Observable<string>;
|
|
63
|
+
hangup(): Promise<void>;
|
|
64
|
+
self$?: Observable<ClickToCallSelf>;
|
|
65
|
+
self?: ClickToCallSelf;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Client interface for click-to-call component
|
|
69
|
+
*/
|
|
70
|
+
export interface ClickToCallClient {
|
|
71
|
+
dial(destination: string, options?: {
|
|
72
|
+
audio?: boolean;
|
|
73
|
+
video?: boolean;
|
|
74
|
+
}): Promise<ClickToCallCall>;
|
|
75
|
+
}
|
|
76
|
+
export declare class ClickToCallComponent extends LitElement {
|
|
77
|
+
static styles: import("lit").CSSResult;
|
|
78
|
+
/**
|
|
79
|
+
* Client for initiating calls (SignalWire)
|
|
80
|
+
*/
|
|
81
|
+
client: ClickToCallClient | null;
|
|
82
|
+
/**
|
|
83
|
+
* Destination address to call
|
|
84
|
+
*/
|
|
85
|
+
destination: string;
|
|
86
|
+
/**
|
|
87
|
+
* Button label when idle
|
|
88
|
+
*/
|
|
89
|
+
label: string;
|
|
90
|
+
/**
|
|
91
|
+
* Audio-only mode (no video)
|
|
92
|
+
*/
|
|
93
|
+
audioOnly: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Current call status
|
|
96
|
+
*/
|
|
97
|
+
private status;
|
|
98
|
+
/**
|
|
99
|
+
* Current call object
|
|
100
|
+
*/
|
|
101
|
+
private call;
|
|
102
|
+
/**
|
|
103
|
+
* Is audio muted
|
|
104
|
+
*/
|
|
105
|
+
private audioMuted;
|
|
106
|
+
/**
|
|
107
|
+
* Self participant reference for mute/unmute operations
|
|
108
|
+
*/
|
|
109
|
+
private selfParticipant;
|
|
110
|
+
/**
|
|
111
|
+
* Call duration in seconds
|
|
112
|
+
*/
|
|
113
|
+
private callDuration;
|
|
114
|
+
/**
|
|
115
|
+
* Error message
|
|
116
|
+
*/
|
|
117
|
+
private errorMessage;
|
|
118
|
+
/**
|
|
119
|
+
* RxJS subscriptions for cleanup
|
|
120
|
+
*/
|
|
121
|
+
private subscriptions;
|
|
122
|
+
/**
|
|
123
|
+
* Duration timer interval
|
|
124
|
+
*/
|
|
125
|
+
private durationInterval;
|
|
126
|
+
/**
|
|
127
|
+
* Call start time
|
|
128
|
+
*/
|
|
129
|
+
private callStartTime;
|
|
130
|
+
disconnectedCallback(): void;
|
|
131
|
+
private initiateCall;
|
|
132
|
+
private subscribeToCall;
|
|
133
|
+
private startDurationTimer;
|
|
134
|
+
private stopDurationTimer;
|
|
135
|
+
private formatDuration;
|
|
136
|
+
private handleCallEnded;
|
|
137
|
+
private toggleMute;
|
|
138
|
+
private hangup;
|
|
139
|
+
private cleanup;
|
|
140
|
+
private renderIdleState;
|
|
141
|
+
private renderConnectingState;
|
|
142
|
+
private renderConnectedState;
|
|
143
|
+
private renderErrorState;
|
|
144
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
145
|
+
}
|
|
146
|
+
declare global {
|
|
147
|
+
interface HTMLElementTagNameMap {
|
|
148
|
+
'sw-click-to-call': ClickToCallComponent;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=click-to-call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"click-to-call.d.ts","sourceRoot":"","sources":["../../src/components/click-to-call.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAG5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAEvC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,eAAe,GAAG,OAAO,CAAC;AAEhG;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,UAAU,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IAC7C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,KAAK,CAAC,EAAE,UAAU,CAAC,eAAe,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CACF,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC7C,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7B;AAED,qBACa,oBAAqB,SAAQ,UAAU;IAClD,MAAM,CAAC,MAAM,0BA+MX;IAEF;;OAEG;IAEH,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAQ;IAExC;;OAEG;IAEH,WAAW,EAAE,MAAM,CAAM;IAEzB;;OAEG;IAEH,KAAK,EAAE,MAAM,CAAU;IAEvB;;OAEG;IAEH,SAAS,EAAE,OAAO,CAAQ;IAE1B;;OAEG;IAEH,OAAO,CAAC,MAAM,CAA6B;IAE3C;;OAEG;IAEH,OAAO,CAAC,IAAI,CAAgC;IAE5C;;OAEG;IAEH,OAAO,CAAC,UAAU,CAAkB;IAEpC;;OAEG;IACH,OAAO,CAAC,eAAe,CAAgC;IAEvD;;OAEG;IAEH,OAAO,CAAC,YAAY,CAAa;IAEjC;;OAEG;IAEH,OAAO,CAAC,YAAY,CAAc;IAElC;;OAEG;IACH,OAAO,CAAC,aAAa,CAAsB;IAE3C;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAAuB;IAE/C;;OAEG;IACH,OAAO,CAAC,aAAa,CAAuB;IAE5C,oBAAoB;YAKN,YAAY;IAkC1B,OAAO,CAAC,eAAe;IAgCvB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,eAAe;YAgBT,UAAU;YAsBV,MAAM;IAYpB,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,oBAAoB;IAiD5B,OAAO,CAAC,gBAAgB;IASxB,MAAM;CAeP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,oBAAoB,CAAC;KAC1C;CACF"}
|