@signalwire/web-components 4.0.0-beta.1 → 4.0.0-beta.10
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 +106 -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 +163 -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 +114 -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 +68 -0
- package/dist/components/call-status.d.ts.map +1 -0
- package/dist/components/call-status.js +254 -0
- package/dist/components/call-status.js.map +1 -0
- package/dist/components/click-to-call.d.ts +123 -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 +224 -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 +60 -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 +103 -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 +20 -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 +94 -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 +116 -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 +101 -0
- package/dist/types/index.d.ts +44 -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,254 @@
|
|
|
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, n = (t, s, e, a) => {
|
|
6
|
+
for (var o = a > 1 ? void 0 : a ? x(s, e) : s, c = t.length - 1, l; c >= 0; c--)
|
|
7
|
+
(l = t[c]) && (o = (a ? l(s, e, o) : l(o)) || o);
|
|
8
|
+
return a && o && g(s, e, o), o;
|
|
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 "disconnecting":
|
|
66
|
+
return "Disconnecting...";
|
|
67
|
+
case "disconnected":
|
|
68
|
+
return "Disconnected";
|
|
69
|
+
case "failed":
|
|
70
|
+
return "Failed";
|
|
71
|
+
case "destroyed":
|
|
72
|
+
return "Ended";
|
|
73
|
+
default: {
|
|
74
|
+
const t = this.status;
|
|
75
|
+
return String(t);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
render() {
|
|
80
|
+
const t = this.getStatusText(), s = this.status === "connected";
|
|
81
|
+
return u`
|
|
82
|
+
<div class="container" part="container">
|
|
83
|
+
<span class="status-indicator ${this.status}" aria-hidden="true"></span>
|
|
84
|
+
<span
|
|
85
|
+
class="status-text ${this.status}"
|
|
86
|
+
part="status-text"
|
|
87
|
+
role="status"
|
|
88
|
+
aria-live="polite"
|
|
89
|
+
>
|
|
90
|
+
${t}
|
|
91
|
+
</span>
|
|
92
|
+
${s ? u`<span class="duration" part="duration">${this.duration}</span>` : null}
|
|
93
|
+
</div>
|
|
94
|
+
`;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
r.styles = p`
|
|
98
|
+
:host {
|
|
99
|
+
/* CSS Custom Properties for theming */
|
|
100
|
+
--sw-color-primary: #044cf6;
|
|
101
|
+
--sw-color-success: #10b981;
|
|
102
|
+
--sw-color-warning: #f59e0b;
|
|
103
|
+
--sw-color-danger: #ef4444;
|
|
104
|
+
--sw-color-text: #1f2937;
|
|
105
|
+
--sw-color-text-muted: #6b7280;
|
|
106
|
+
--sw-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
107
|
+
--sw-font-size-sm: 14px;
|
|
108
|
+
--sw-font-size-base: 16px;
|
|
109
|
+
--sw-font-size-lg: 18px;
|
|
110
|
+
--sw-space-1: 4px;
|
|
111
|
+
--sw-space-2: 8px;
|
|
112
|
+
--sw-space-3: 12px;
|
|
113
|
+
--sw-border-radius: 8px;
|
|
114
|
+
|
|
115
|
+
display: inline-flex;
|
|
116
|
+
align-items: center;
|
|
117
|
+
gap: var(--sw-space-2);
|
|
118
|
+
font-family: var(--sw-font-family);
|
|
119
|
+
font-size: var(--sw-font-size-base);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* Dark mode support */
|
|
123
|
+
:host([data-theme='dark']) {
|
|
124
|
+
--sw-color-text: #f9fafb;
|
|
125
|
+
--sw-color-text-muted: #9ca3af;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@media (prefers-color-scheme: dark) {
|
|
129
|
+
:host(:not([data-theme='light'])) {
|
|
130
|
+
--sw-color-text: #f9fafb;
|
|
131
|
+
--sw-color-text-muted: #9ca3af;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.container {
|
|
136
|
+
display: inline-flex;
|
|
137
|
+
align-items: center;
|
|
138
|
+
gap: var(--sw-space-2);
|
|
139
|
+
padding: var(--sw-space-2) var(--sw-space-3);
|
|
140
|
+
border-radius: var(--sw-border-radius);
|
|
141
|
+
color: var(--sw-color-text);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.status-indicator {
|
|
145
|
+
width: 10px;
|
|
146
|
+
height: 10px;
|
|
147
|
+
border-radius: 50%;
|
|
148
|
+
flex-shrink: 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.status-indicator.new {
|
|
152
|
+
background-color: var(--sw-color-text-muted);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.status-indicator.connecting,
|
|
156
|
+
.status-indicator.ringing {
|
|
157
|
+
background-color: var(--sw-color-warning);
|
|
158
|
+
animation: pulse 1.5s ease-in-out infinite;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.status-indicator.connected {
|
|
162
|
+
background-color: var(--sw-color-success);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.status-indicator.disconnecting {
|
|
166
|
+
background-color: var(--sw-color-danger);
|
|
167
|
+
animation: pulse 1s ease-in-out infinite;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.status-indicator.trying {
|
|
171
|
+
background-color: var(--sw-color-warning);
|
|
172
|
+
animation: pulse 1.5s ease-in-out infinite;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.status-indicator.disconnected,
|
|
176
|
+
.status-indicator.failed {
|
|
177
|
+
background-color: var(--sw-color-danger);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.status-indicator.destroyed {
|
|
181
|
+
background-color: var(--sw-color-text-muted);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@keyframes pulse {
|
|
185
|
+
0%,
|
|
186
|
+
100% {
|
|
187
|
+
opacity: 1;
|
|
188
|
+
transform: scale(1);
|
|
189
|
+
}
|
|
190
|
+
50% {
|
|
191
|
+
opacity: 0.5;
|
|
192
|
+
transform: scale(1.1);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.status-text {
|
|
197
|
+
font-weight: 500;
|
|
198
|
+
white-space: nowrap;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.status-text.trying,
|
|
202
|
+
.status-text.connecting,
|
|
203
|
+
.status-text.ringing {
|
|
204
|
+
color: var(--sw-color-warning);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.status-text.disconnecting {
|
|
208
|
+
color: var(--sw-color-danger);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.status-text.connected {
|
|
212
|
+
color: var(--sw-color-success);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.status-text.disconnected,
|
|
216
|
+
.status-text.failed {
|
|
217
|
+
color: var(--sw-color-danger);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.status-text.new,
|
|
221
|
+
.status-text.destroyed {
|
|
222
|
+
color: var(--sw-color-text-muted);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.duration {
|
|
226
|
+
font-variant-numeric: tabular-nums;
|
|
227
|
+
color: var(--sw-color-text-muted);
|
|
228
|
+
font-size: var(--sw-font-size-sm);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
`;
|
|
232
|
+
n([
|
|
233
|
+
h({ attribute: !1 })
|
|
234
|
+
], r.prototype, "call", 2);
|
|
235
|
+
n([
|
|
236
|
+
m({ context: w, subscribe: !0 }),
|
|
237
|
+
i()
|
|
238
|
+
], r.prototype, "contextCall", 2);
|
|
239
|
+
n([
|
|
240
|
+
i()
|
|
241
|
+
], r.prototype, "status", 2);
|
|
242
|
+
n([
|
|
243
|
+
i()
|
|
244
|
+
], r.prototype, "callStartTime", 2);
|
|
245
|
+
n([
|
|
246
|
+
i()
|
|
247
|
+
], r.prototype, "duration", 2);
|
|
248
|
+
r = n([
|
|
249
|
+
f("sw-call-status")
|
|
250
|
+
], r);
|
|
251
|
+
export {
|
|
252
|
+
r as CallStatusComponent
|
|
253
|
+
};
|
|
254
|
+
//# 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\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 /**\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 '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,123 @@
|
|
|
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
|
+
import { LitElement } from 'lit';
|
|
17
|
+
import type { Observable } from 'rxjs';
|
|
18
|
+
/**
|
|
19
|
+
* Call status type
|
|
20
|
+
*/
|
|
21
|
+
export type ClickToCallStatus = 'idle' | 'connecting' | 'connected' | 'disconnecting' | 'error';
|
|
22
|
+
/**
|
|
23
|
+
* Self participant interface for click-to-call component
|
|
24
|
+
*/
|
|
25
|
+
export interface ClickToCallSelf {
|
|
26
|
+
audioMuted$: Observable<boolean>;
|
|
27
|
+
mute(): Promise<void>;
|
|
28
|
+
unmute(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Call interface for click-to-call component
|
|
32
|
+
*/
|
|
33
|
+
export interface ClickToCallCall {
|
|
34
|
+
status$: Observable<string>;
|
|
35
|
+
hangup(): Promise<void>;
|
|
36
|
+
self$?: Observable<ClickToCallSelf>;
|
|
37
|
+
self?: ClickToCallSelf;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Client interface for click-to-call component
|
|
41
|
+
*/
|
|
42
|
+
export interface ClickToCallClient {
|
|
43
|
+
dial(destination: string, options?: {
|
|
44
|
+
audio?: boolean;
|
|
45
|
+
video?: boolean;
|
|
46
|
+
}): Promise<ClickToCallCall>;
|
|
47
|
+
}
|
|
48
|
+
export declare class ClickToCallComponent extends LitElement {
|
|
49
|
+
static styles: import("lit").CSSResult;
|
|
50
|
+
/**
|
|
51
|
+
* Client for initiating calls (SignalWire)
|
|
52
|
+
*/
|
|
53
|
+
client: ClickToCallClient | null;
|
|
54
|
+
/**
|
|
55
|
+
* Destination address to call
|
|
56
|
+
*/
|
|
57
|
+
destination: string;
|
|
58
|
+
/**
|
|
59
|
+
* Button label when idle
|
|
60
|
+
*/
|
|
61
|
+
label: string;
|
|
62
|
+
/**
|
|
63
|
+
* Audio-only mode (no video)
|
|
64
|
+
*/
|
|
65
|
+
audioOnly: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Current call status
|
|
68
|
+
*/
|
|
69
|
+
private status;
|
|
70
|
+
/**
|
|
71
|
+
* Current call object
|
|
72
|
+
*/
|
|
73
|
+
private call;
|
|
74
|
+
/**
|
|
75
|
+
* Is audio muted
|
|
76
|
+
*/
|
|
77
|
+
private audioMuted;
|
|
78
|
+
/**
|
|
79
|
+
* Self participant reference for mute/unmute operations
|
|
80
|
+
*/
|
|
81
|
+
private selfParticipant;
|
|
82
|
+
/**
|
|
83
|
+
* Call duration in seconds
|
|
84
|
+
*/
|
|
85
|
+
private callDuration;
|
|
86
|
+
/**
|
|
87
|
+
* Error message
|
|
88
|
+
*/
|
|
89
|
+
private errorMessage;
|
|
90
|
+
/**
|
|
91
|
+
* RxJS subscriptions for cleanup
|
|
92
|
+
*/
|
|
93
|
+
private subscriptions;
|
|
94
|
+
/**
|
|
95
|
+
* Duration timer interval
|
|
96
|
+
*/
|
|
97
|
+
private durationInterval;
|
|
98
|
+
/**
|
|
99
|
+
* Call start time
|
|
100
|
+
*/
|
|
101
|
+
private callStartTime;
|
|
102
|
+
disconnectedCallback(): void;
|
|
103
|
+
private initiateCall;
|
|
104
|
+
private subscribeToCall;
|
|
105
|
+
private startDurationTimer;
|
|
106
|
+
private stopDurationTimer;
|
|
107
|
+
private formatDuration;
|
|
108
|
+
private handleCallEnded;
|
|
109
|
+
private toggleMute;
|
|
110
|
+
private hangup;
|
|
111
|
+
private cleanup;
|
|
112
|
+
private renderIdleState;
|
|
113
|
+
private renderConnectingState;
|
|
114
|
+
private renderConnectedState;
|
|
115
|
+
private renderErrorState;
|
|
116
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
117
|
+
}
|
|
118
|
+
declare global {
|
|
119
|
+
interface HTMLElementTagNameMap {
|
|
120
|
+
'sw-click-to-call': ClickToCallComponent;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# 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;;;;;;;;;;;;;;GAcG;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,CAAC,CAAC;IACjC,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"}
|