@signalwire/web-components 1.0.0-dev-20260311213302 → 1.0.0-dev-20260318132643

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 CHANGED
@@ -214,7 +214,7 @@ Displays call state, status text, and duration timer.
214
214
  |----------|------|---------|-------------|
215
215
  | `call` | `CallStatusCall` | - | Call with status$ observable |
216
216
 
217
- **Status Values:** `idle`, `connecting`, `ringing`, `connected`, `disconnecting`, `disconnected`
217
+ **Status Values:** `new`, `trying`, `ringing`, `connecting`, `connected`, `disconnecting`, `disconnected`, `failed`, `destroyed`
218
218
 
219
219
  **CSS Custom Properties:**
220
220
 
@@ -314,7 +314,7 @@ Dropdown for selecting audio/video input and output devices.
314
314
  | Event | Detail | Description |
315
315
  |-------|--------|-------------|
316
316
  | `sw-tab-change` | `{ tab: 'microphone' \| 'camera' \| 'speaker' }` | Tab changed |
317
- | `sw-device-change` | `{ device: DeviceInfo }` | Device selected |
317
+ | `sw-device-change` | `{ device: MediaDeviceInfo }` | Device selected |
318
318
  | `sw-test-speaker` | - | Speaker test triggered |
319
319
 
320
320
  **CSS Custom Properties:**
@@ -668,7 +668,7 @@ sw-call-media::part(video) {
668
668
  ## TypeScript Interfaces
669
669
 
670
670
  ```typescript
671
- import type { Call, LayoutLayer, DeviceInfo, Address } from '@signalwire/web-components';
671
+ import type { Call, CallSelf, DeviceController, LayoutLayer, Participant } from '@signalwire/web-components';
672
672
 
673
673
  // Call object interface
674
674
  interface Call {
@@ -694,12 +694,9 @@ interface LayoutLayer {
694
694
  height: number;
695
695
  }
696
696
 
697
- // Device information
698
- interface DeviceInfo {
699
- deviceId: string;
700
- label: string;
701
- kind: 'audioinput' | 'audiooutput' | 'videoinput';
702
- }
697
+ // DeviceController is imported from @signalwire/js via @signalwire/web-components
698
+ // It provides observables for device lists and selection methods.
699
+ // See @signalwire/js documentation for the full DeviceController interface.
703
700
 
704
701
  // Directory address
705
702
  interface Address {
@@ -11,10 +11,7 @@
11
11
  */
12
12
  import { LitElement } from 'lit';
13
13
  import type { Observable } from 'rxjs';
14
- /**
15
- * Call status types
16
- */
17
- export type CallStatus = 'new' | 'trying' | 'idle' | 'connecting' | 'ringing' | 'connected' | 'disconnecting' | 'disconnected' | 'failed' | 'destroyed';
14
+ import type { CallStatus } from '@signalwire/js';
18
15
  /**
19
16
  * Call interface for status component
20
17
  */
@@ -1 +1 @@
1
- {"version":3,"file":"call-status.d.ts","sourceRoot":"","sources":["../../src/components/call-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAI5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAGvC;;GAEG;AACH,MAAM,MAAM,UAAU,GAClB,KAAK,GACL,QAAQ,GACR,MAAM,GACN,YAAY,GACZ,SAAS,GACT,WAAW,GACX,eAAe,GACf,cAAc,GACd,QAAQ,GACR,WAAW,CAAC;AAEhB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;CACjC;AAED,qBACa,mBAAoB,SAAQ,UAAU;IACjD,MAAM,CAAC,MAAM,0BA2IX;IAEF;;OAEG;IAEH,IAAI,EAAE,cAAc,GAAG,IAAI,CAAQ;IAEnC;;OAEG;IAGH,OAAO,CAAC,WAAW,CAAC,CAAiB;IAErC;;OAEG;IAEH,OAAO,CAAC,MAAM,CAAsB;IAEpC;;OAEG;IAEH,OAAO,CAAC,aAAa,CAAuB;IAE5C;;OAEG;IAEH,OAAO,CAAC,QAAQ,CAAkB;IAElC;;OAEG;IACH,OAAO,CAAC,aAAa,CAAsB;IAE3C;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAAuB;IAE/C,iBAAiB;IAKjB,oBAAoB;IAKpB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAO/C,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,aAAa;IAmBrB,MAAM;CAqBP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,mBAAmB,CAAC;KACvC;CACF"}
1
+ {"version":3,"file":"call-status.d.ts","sourceRoot":"","sources":["../../src/components/call-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAI5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;CACjC;AAED,qBACa,mBAAoB,SAAQ,UAAU;IACjD,MAAM,CAAC,MAAM,0BAsIX;IAEF;;OAEG;IAEH,IAAI,EAAE,cAAc,GAAG,IAAI,CAAQ;IAEnC;;OAEG;IAGH,OAAO,CAAC,WAAW,CAAC,CAAiB;IAErC;;OAEG;IAEH,OAAO,CAAC,MAAM,CAAqB;IAEnC;;OAEG;IAEH,OAAO,CAAC,aAAa,CAAuB;IAE5C;;OAEG;IAEH,OAAO,CAAC,QAAQ,CAAkB;IAElC;;OAEG;IACH,OAAO,CAAC,aAAa,CAAsB;IAE3C;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAAuB;IAE/C,iBAAiB;IAKjB,oBAAoB;IAKpB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAO/C,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,aAAa;IA2BrB,MAAM;CAqBP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,mBAAmB,CAAC;KACvC;CACF"}
@@ -1,15 +1,15 @@
1
1
  import { LitElement as d, html as u, css as p } from "lit";
2
- import { property as f, state as i, customElement as h } from "lit/decorators.js";
2
+ import { property as h, state as i, customElement as f } from "lit/decorators.js";
3
3
  import { consume as m } from "@lit/context";
4
4
  import { callContext as w } from "../context/call-context.js";
5
- var g = Object.defineProperty, b = Object.getOwnPropertyDescriptor, o = (t, s, e, a) => {
6
- for (var r = a > 1 ? void 0 : a ? b(s, e) : s, c = t.length - 1, l; c >= 0; c--)
7
- (l = t[c]) && (r = (a ? l(s, e, r) : l(r)) || r);
8
- return a && r && g(s, e, r), r;
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
9
  };
10
- let n = class extends d {
10
+ let r = class extends d {
11
11
  constructor() {
12
- super(...arguments), this.call = null, this.status = "idle", this.callStartTime = null, this.duration = "0:00", this.subscriptions = [], this.durationInterval = null;
12
+ super(...arguments), this.call = null, this.status = "new", this.callStartTime = null, this.duration = "0:00", this.subscriptions = [], this.durationInterval = null;
13
13
  }
14
14
  connectedCallback() {
15
15
  super.connectedCallback(), this.subscribeToCall();
@@ -52,8 +52,10 @@ let n = class extends d {
52
52
  }
53
53
  getStatusText() {
54
54
  switch (this.status) {
55
- case "idle":
56
- return "Idle";
55
+ case "new":
56
+ return "Ready";
57
+ case "trying":
58
+ return "Trying...";
57
59
  case "connecting":
58
60
  return "Connecting...";
59
61
  case "ringing":
@@ -64,8 +66,14 @@ let n = class extends d {
64
66
  return "Disconnecting...";
65
67
  case "disconnected":
66
68
  return "Disconnected";
67
- default:
68
- return "Unknown";
69
+ case "failed":
70
+ return "Failed";
71
+ case "destroyed":
72
+ return "Ended";
73
+ default: {
74
+ const t = this.status;
75
+ return String(t);
76
+ }
69
77
  }
70
78
  }
71
79
  render() {
@@ -86,7 +94,7 @@ let n = class extends d {
86
94
  `;
87
95
  }
88
96
  };
89
- n.styles = p`
97
+ r.styles = p`
90
98
  :host {
91
99
  /* CSS Custom Properties for theming */
92
100
  --sw-color-primary: #044cf6;
@@ -140,7 +148,7 @@ n.styles = p`
140
148
  flex-shrink: 0;
141
149
  }
142
150
 
143
- .status-indicator.idle {
151
+ .status-indicator.new {
144
152
  background-color: var(--sw-color-text-muted);
145
153
  }
146
154
 
@@ -159,10 +167,20 @@ n.styles = p`
159
167
  animation: pulse 1s ease-in-out infinite;
160
168
  }
161
169
 
162
- .status-indicator.disconnected {
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 {
163
177
  background-color: var(--sw-color-danger);
164
178
  }
165
179
 
180
+ .status-indicator.destroyed {
181
+ background-color: var(--sw-color-text-muted);
182
+ }
183
+
166
184
  @keyframes pulse {
167
185
  0%,
168
186
  100% {
@@ -180,6 +198,7 @@ n.styles = p`
180
198
  white-space: nowrap;
181
199
  }
182
200
 
201
+ .status-text.trying,
183
202
  .status-text.connecting,
184
203
  .status-text.ringing {
185
204
  color: var(--sw-color-warning);
@@ -193,59 +212,43 @@ n.styles = p`
193
212
  color: var(--sw-color-success);
194
213
  }
195
214
 
196
- .status-text.disconnected {
215
+ .status-text.disconnected,
216
+ .status-text.failed {
197
217
  color: var(--sw-color-danger);
198
218
  }
199
219
 
220
+ .status-text.new,
221
+ .status-text.destroyed {
222
+ color: var(--sw-color-text-muted);
223
+ }
224
+
200
225
  .duration {
201
226
  font-variant-numeric: tabular-nums;
202
227
  color: var(--sw-color-text-muted);
203
228
  font-size: var(--sw-font-size-sm);
204
229
  }
205
230
 
206
- /* Animated dots for transient states */
207
- .loading-dots::after {
208
- content: '';
209
- animation: dots 1.5s steps(4, end) infinite;
210
- }
211
-
212
- @keyframes dots {
213
- 0%,
214
- 20% {
215
- content: '';
216
- }
217
- 40% {
218
- content: '.';
219
- }
220
- 60% {
221
- content: '..';
222
- }
223
- 80%,
224
- 100% {
225
- content: '...';
226
- }
227
- }
228
231
  `;
229
- o([
230
- f({ attribute: !1 })
231
- ], n.prototype, "call", 2);
232
- o([
232
+ n([
233
+ h({ attribute: !1 })
234
+ ], r.prototype, "call", 2);
235
+ n([
233
236
  m({ context: w, subscribe: !0 }),
234
237
  i()
235
- ], n.prototype, "contextCall", 2);
236
- o([
238
+ ], r.prototype, "contextCall", 2);
239
+ n([
237
240
  i()
238
- ], n.prototype, "status", 2);
239
- o([
241
+ ], r.prototype, "status", 2);
242
+ n([
240
243
  i()
241
- ], n.prototype, "callStartTime", 2);
242
- o([
244
+ ], r.prototype, "callStartTime", 2);
245
+ n([
243
246
  i()
244
- ], n.prototype, "duration", 2);
245
- n = o([
246
- h("sw-call-status")
247
- ], n);
247
+ ], r.prototype, "duration", 2);
248
+ r = n([
249
+ f("sw-call-status")
250
+ ], r);
248
251
  export {
249
- n as CallStatusComponent
252
+ r as CallStatusComponent
250
253
  };
251
254
  //# sourceMappingURL=call-status.js.map
@@ -1 +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 { callContext } from '../context/index.js';\n\n/**\n * Call status types\n */\nexport type CallStatus =\n | 'new'\n | 'trying'\n | 'idle'\n | 'connecting'\n | 'ringing'\n | 'connected'\n | 'disconnecting'\n | 'disconnected'\n | 'failed'\n | 'destroyed';\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.idle {\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.disconnected {\n background-color: var(--sw-color-danger);\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.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 color: var(--sw-color-danger);\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 /* Animated dots for transient states */\n .loading-dots::after {\n content: '';\n animation: dots 1.5s steps(4, end) infinite;\n }\n\n @keyframes dots {\n 0%,\n 20% {\n content: '';\n }\n 40% {\n content: '.';\n }\n 60% {\n content: '..';\n }\n 80%,\n 100% {\n content: '...';\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 = 'idle';\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 'idle':\n return 'Idle';\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 default:\n return 'Unknown';\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","statusText","showDuration","html","css","__decorateClass","property","consume","callContext","state","customElement"],"mappings":"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"}
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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"}
@@ -11,34 +11,8 @@
11
11
  * ```
12
12
  */
13
13
  import { LitElement } from 'lit';
14
- import type { Observable } from 'rxjs';
14
+ import type { DeviceController } from '@signalwire/js';
15
15
  import './audio-level.js';
16
- /**
17
- * DeviceController interface for observing device lists
18
- */
19
- export interface DeviceController {
20
- readonly audioInputDevices$: Observable<MediaDeviceInfo[]>;
21
- readonly audioOutputDevices$: Observable<MediaDeviceInfo[]>;
22
- readonly videoInputDevices$: Observable<MediaDeviceInfo[]>;
23
- readonly selectedAudioInputDevice$: Observable<MediaDeviceInfo | null>;
24
- readonly selectedAudioOutputDevice$: Observable<MediaDeviceInfo | null>;
25
- readonly selectedVideoInputDevice$: Observable<MediaDeviceInfo | null>;
26
- readonly selectedAudioInputDevice: MediaDeviceInfo | null;
27
- readonly selectedAudioOutputDevice: MediaDeviceInfo | null;
28
- readonly selectedVideoInputDevice: MediaDeviceInfo | null;
29
- readonly audioInputDevices: MediaDeviceInfo[];
30
- readonly audioOutputDevices: MediaDeviceInfo[];
31
- readonly videoInputDevices: MediaDeviceInfo[];
32
- readonly selectedAudioInputDeviceConstraints: MediaTrackConstraints;
33
- readonly selectedVideoInputDeviceConstraints: MediaTrackConstraints;
34
- MediaDeviceInfoToConstraints(MediaDeviceInfo: MediaDeviceInfo | null): MediaTrackConstraints;
35
- selectAudioInputDevice(device: MediaDeviceInfo | null): void;
36
- selectVideoInputDevice(device: MediaDeviceInfo | null): void;
37
- selectAudioOutputDevice(device: MediaDeviceInfo | null): void;
38
- enableDeviceMonitoring(): void;
39
- disableDeviceMonitoring(): void;
40
- getLocalStream?: () => Promise<MediaStream>;
41
- }
42
16
  export declare class DeviceSelector extends LitElement {
43
17
  static styles: import("lit").CSSResult;
44
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"device-selector.d.ts","sourceRoot":"","sources":["../../src/components/device-selector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"device-selector.d.ts","sourceRoot":"","sources":["../../src/components/device-selector.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"device-selector.js","sources":["../../src/components/device-selector.ts"],"sourcesContent":["/**\n * Device Selector Component\n *\n * Dropdown-based selector for choosing audio/video devices. Displays device lists from\n * DeviceController observables with labeled dropdowns for microphone, camera, and speaker.\n * Includes inline preview for video (camera) and audio level (microphone) using browser API.\n *\n * @example\n * ```html\n * <sw-device-selector .deviceController=${deviceController} show-preview></sw-device-selector>\n * ```\n */\n\nimport { LitElement, html, css, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { Subscription } from 'rxjs';\nimport type { Observable } from 'rxjs';\nimport './audio-level.js';\n\n/**\n * DeviceController interface for observing device lists\n */\nexport interface DeviceController {\n // Observable getters for device lists\n readonly audioInputDevices$: Observable<MediaDeviceInfo[]>;\n readonly audioOutputDevices$: Observable<MediaDeviceInfo[]>;\n readonly videoInputDevices$: Observable<MediaDeviceInfo[]>;\n\n // Observable getters for selected devices\n readonly selectedAudioInputDevice$: Observable<MediaDeviceInfo | null>;\n readonly selectedAudioOutputDevice$: Observable<MediaDeviceInfo | null>;\n readonly selectedVideoInputDevice$: Observable<MediaDeviceInfo | null>;\n\n // Current value getters\n readonly selectedAudioInputDevice: MediaDeviceInfo | null;\n readonly selectedAudioOutputDevice: MediaDeviceInfo | null;\n readonly selectedVideoInputDevice: MediaDeviceInfo | null;\n\n readonly audioInputDevices: MediaDeviceInfo[];\n readonly audioOutputDevices: MediaDeviceInfo[];\n readonly videoInputDevices: MediaDeviceInfo[];\n\n // Device constraints\n readonly selectedAudioInputDeviceConstraints: MediaTrackConstraints;\n readonly selectedVideoInputDeviceConstraints: MediaTrackConstraints;\n\n // Methods\n MediaDeviceInfoToConstraints(MediaDeviceInfo: MediaDeviceInfo | null): MediaTrackConstraints;\n selectAudioInputDevice(device: MediaDeviceInfo | null): void;\n selectVideoInputDevice(device: MediaDeviceInfo | null): void;\n selectAudioOutputDevice(device: MediaDeviceInfo | null): void;\n enableDeviceMonitoring(): void;\n disableDeviceMonitoring(): void;\n\n getLocalStream?: () => Promise<MediaStream>;\n}\n\ntype DeviceType = 'microphone' | 'camera' | 'speaker';\n\n@customElement('sw-device-selector')\nexport class DeviceSelector extends LitElement {\n static styles = css`\n :host {\n /* CSS Custom Properties for theming */\n --sw-color-primary: #044cf6;\n --sw-color-primary-hover: #0339c4;\n --sw-color-background: #1a1a1a;\n --sw-color-surface: #2a2a2a;\n --sw-color-surface-hover: #3a3a3a;\n --sw-color-text: #ffffff;\n --sw-color-text-muted: #a0a0a0;\n --sw-color-border: #404040;\n --sw-color-success: #10b981;\n --sw-border-radius: 8px;\n --sw-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --sw-space-1: 4px;\n --sw-space-2: 8px;\n --sw-space-3: 12px;\n --sw-space-4: 16px;\n --sw-space-6: 24px;\n\n display: block;\n font-family: var(--sw-font-family);\n color: var(--sw-color-text);\n }\n\n .container {\n background: var(--sw-color-background);\n border-radius: var(--sw-border-radius);\n border: 1px solid var(--sw-color-border);\n overflow: hidden;\n min-width: 300px;\n padding: var(--sw-space-4);\n }\n\n .device-section {\n margin-bottom: var(--sw-space-4);\n }\n\n .device-section:last-of-type {\n margin-bottom: 0;\n }\n\n .device-label {\n display: flex;\n align-items: center;\n gap: var(--sw-space-2);\n font-size: 14px;\n font-weight: 500;\n color: var(--sw-color-text);\n margin-bottom: var(--sw-space-2);\n }\n\n .device-icon {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n color: var(--sw-color-text-muted);\n }\n\n .device-select-wrapper {\n position: relative;\n }\n\n .device-select {\n width: 100%;\n padding: var(--sw-space-3) var(--sw-space-4);\n padding-right: 36px;\n background: var(--sw-color-surface);\n border: 1px solid var(--sw-color-border);\n border-radius: calc(var(--sw-border-radius) - 4px);\n color: var(--sw-color-text);\n font-size: 14px;\n font-family: var(--sw-font-family);\n cursor: pointer;\n appearance: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n transition:\n border-color 0.2s ease,\n background-color 0.2s ease;\n }\n\n .device-select:hover {\n background: var(--sw-color-surface-hover);\n }\n\n .device-select:focus {\n outline: none;\n border-color: var(--sw-color-primary);\n box-shadow: 0 0 0 2px rgba(4, 76, 246, 0.2);\n }\n\n .device-select:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .device-select option {\n background: var(--sw-color-surface);\n color: var(--sw-color-text);\n padding: var(--sw-space-2);\n }\n\n .select-arrow {\n position: absolute;\n right: var(--sw-space-3);\n top: 50%;\n transform: translateY(-50%);\n width: 16px;\n height: 16px;\n color: var(--sw-color-text-muted);\n pointer-events: none;\n }\n\n .no-devices {\n padding: var(--sw-space-3) var(--sw-space-4);\n background: var(--sw-color-surface);\n border: 1px solid var(--sw-color-border);\n border-radius: calc(var(--sw-border-radius) - 4px);\n color: var(--sw-color-text-muted);\n font-size: 14px;\n }\n\n .device-preview {\n margin-top: var(--sw-space-3);\n }\n\n .video-preview {\n width: 100%;\n aspect-ratio: 16/9;\n background: #000;\n border-radius: calc(var(--sw-border-radius) - 4px);\n overflow: hidden;\n }\n\n .video-preview video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transform: scaleX(-1);\n }\n\n .video-preview-placeholder {\n width: 100%;\n aspect-ratio: 16/9;\n background: var(--sw-color-surface);\n border-radius: calc(var(--sw-border-radius) - 4px);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--sw-color-text-muted);\n font-size: 14px;\n }\n\n .audio-preview {\n display: flex;\n align-items: center;\n gap: var(--sw-space-3);\n padding: var(--sw-space-3);\n background: var(--sw-color-surface);\n border-radius: calc(var(--sw-border-radius) - 4px);\n }\n\n .audio-preview-label {\n font-size: 12px;\n color: var(--sw-color-text-muted);\n flex-shrink: 0;\n }\n\n .audio-level-wrapper {\n flex: 1;\n display: flex;\n justify-content: center;\n }\n\n .test-speaker-btn {\n padding: var(--sw-space-2) var(--sw-space-4);\n background: var(--sw-color-primary);\n color: white;\n border: none;\n border-radius: calc(var(--sw-border-radius) - 4px);\n font-size: 14px;\n cursor: pointer;\n transition: background-color 0.2s ease;\n }\n\n .test-speaker-btn:hover {\n background: var(--sw-color-primary-hover);\n }\n\n .test-speaker-btn:focus {\n outline: none;\n box-shadow:\n 0 0 0 2px var(--sw-color-background),\n 0 0 0 4px var(--sw-color-primary);\n }\n\n .test-speaker-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n /* Scrollbar styling for select on some browsers */\n .device-select::-webkit-scrollbar {\n width: 8px;\n }\n\n .device-select::-webkit-scrollbar-track {\n background: var(--sw-color-background);\n }\n\n .device-select::-webkit-scrollbar-thumb {\n background: var(--sw-color-border);\n border-radius: 4px;\n }\n\n .device-select::-webkit-scrollbar-thumb:hover {\n background: var(--sw-color-text-muted);\n }\n `;\n\n /**\n * Device controller with observables for device lists\n */\n @property({ type: Object }) deviceController?: DeviceController;\n\n /**\n * Whether to show the preview panel\n */\n @property({ type: Boolean, attribute: 'show-preview' }) showPreview = false;\n\n /**\n * Audio input devices\n */\n @state() private _audioInputDevices: MediaDeviceInfo[] = [];\n\n /**\n * Video input devices\n */\n @state() private _videoInputDevices: MediaDeviceInfo[] = [];\n\n /**\n * Audio output devices\n */\n @state() private _audioOutputDevices: MediaDeviceInfo[] = [];\n\n /**\n * Selected audio input device\n */\n @state() private _selectedAudioInput: MediaDeviceInfo | null = null;\n\n /**\n * Selected video input device\n */\n @state() private _selectedVideoInput: MediaDeviceInfo | null = null;\n\n /**\n * Selected audio output device\n */\n @state() private _selectedAudioOutput: MediaDeviceInfo | null = null;\n\n /**\n * Video preview stream from camera\n */\n @state() private _videoPreviewStream: MediaStream | null = null;\n\n /**\n * Audio preview stream from microphone\n */\n @state() private _audioPreviewStream: MediaStream | null = null;\n\n /**\n * Is test audio playing\n */\n @state() private _isTestingAudio = false;\n\n /**\n * Whether the component is currently visible (combines all visibility factors)\n */\n private _isComponentVisible = false;\n\n /**\n * Whether the component is in the viewport (IntersectionObserver)\n */\n private _isInViewport = false;\n\n /**\n * Whether the document/tab is visible\n */\n private _isDocumentVisible = true;\n\n /**\n * Whether the component is CSS-visible (display, visibility, opacity)\n */\n private _isCSSVisible = true;\n\n /**\n * Video element reference\n */\n private _videoElement?: HTMLVideoElement;\n\n /**\n * RxJS subscriptions for cleanup\n */\n private subscriptions: Subscription[] = [];\n\n /**\n * Audio element for speaker test\n */\n private _testAudioElement?: HTMLAudioElement;\n\n /**\n * IntersectionObserver for viewport visibility\n */\n private _intersectionObserver?: IntersectionObserver;\n\n /**\n * Bound handler for document visibility change\n */\n private _boundHandleDocumentVisibility = this.handleDocumentVisibilityChange.bind(this);\n\n /**\n * Interval ID for CSS visibility polling\n */\n private _cssVisibilityCheckInterval?: ReturnType<typeof setInterval>;\n\n /**\n * Flag to prevent concurrent preview initialization\n */\n private _isInitializingPreviews = false;\n\n /**\n * Interval in milliseconds for checking CSS visibility changes\n */\n private static readonly CSS_VISIBILITY_CHECK_INTERVAL_MS = 200;\n\n /**\n * Lifecycle: Component connected to DOM\n */\n connectedCallback() {\n super.connectedCallback();\n this.setupSubscriptions();\n this.setupVisibilityObservers();\n }\n\n /**\n * Lifecycle: React to property changes\n */\n protected updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n if (changedProperties.has('deviceController')) {\n this.cleanupSubscriptions();\n this.setupSubscriptions();\n }\n if (changedProperties.has('showPreview')) {\n if (this.showPreview && this._isComponentVisible) {\n // Only initialize if component is visible\n this.initializePreviews();\n } else if (!this.showPreview) {\n // Always cleanup when showPreview is disabled\n this.cleanupVideoPreviewStream();\n this.cleanupAudioPreviewStream();\n }\n }\n }\n\n /**\n * Lifecycle: Component disconnected from DOM\n */\n disconnectedCallback() {\n super.disconnectedCallback();\n this.cleanupSubscriptions();\n this.cleanupVisibilityObservers();\n this.cleanupVideoPreviewStream();\n this.cleanupAudioPreviewStream();\n this.stopTestAudio();\n }\n\n /**\n * Setup all visibility observers (IntersectionObserver, document visibility, CSS polling)\n */\n private setupVisibilityObservers(): void {\n // Defensive cleanup in case of multiple calls without disconnect\n this.cleanupVisibilityObservers();\n\n // Setup IntersectionObserver for viewport visibility\n this._intersectionObserver = new IntersectionObserver(\n (entries) => {\n const entry = entries[0];\n if (entry) {\n this._isInViewport = entry.isIntersecting;\n this.updateVisibilityState();\n }\n },\n { threshold: 0 }\n );\n this._intersectionObserver.observe(this);\n\n // Setup document visibility change listener\n this._isDocumentVisible = document.visibilityState === 'visible';\n document.addEventListener('visibilitychange', this._boundHandleDocumentVisibility);\n\n // Setup CSS visibility polling (checks opacity, display, visibility)\n this._isCSSVisible = this.checkCSSVisibility();\n this._cssVisibilityCheckInterval = setInterval(() => {\n const wasVisible = this._isCSSVisible;\n this._isCSSVisible = this.checkCSSVisibility();\n if (wasVisible !== this._isCSSVisible) {\n this.updateVisibilityState();\n }\n }, DeviceSelector.CSS_VISIBILITY_CHECK_INTERVAL_MS);\n }\n\n /**\n * Cleanup all visibility observers\n */\n private cleanupVisibilityObservers(): void {\n if (this._intersectionObserver) {\n this._intersectionObserver.disconnect();\n this._intersectionObserver = undefined;\n }\n\n document.removeEventListener('visibilitychange', this._boundHandleDocumentVisibility);\n\n if (this._cssVisibilityCheckInterval) {\n clearInterval(this._cssVisibilityCheckInterval);\n this._cssVisibilityCheckInterval = undefined;\n }\n }\n\n /**\n * Handle document visibility change (tab switching)\n */\n private handleDocumentVisibilityChange(): void {\n this._isDocumentVisible = document.visibilityState === 'visible';\n this.updateVisibilityState();\n }\n\n /**\n * Check if the component is visible via CSS (display, visibility, opacity)\n * Traverses the DOM tree including shadow DOM boundaries\n */\n private checkCSSVisibility(): boolean {\n // Guard against being called when disconnected\n if (!this.isConnected) {\n return false;\n }\n\n let element: HTMLElement | null = this;\n while (element) {\n const style = getComputedStyle(element);\n if (\n style.display === 'none' ||\n style.visibility === 'hidden' ||\n parseFloat(style.opacity) === 0\n ) {\n return false;\n }\n\n // Handle shadow DOM boundaries by traversing through shadow hosts\n if (element.parentElement) {\n element = element.parentElement;\n } else {\n const root = element.getRootNode();\n element = root instanceof ShadowRoot ? (root.host as HTMLElement) : null;\n }\n }\n return true;\n }\n\n /**\n * Update the combined visibility state and manage preview streams accordingly\n */\n private updateVisibilityState(): void {\n const wasVisible = this._isComponentVisible;\n this._isComponentVisible = this._isInViewport && this._isDocumentVisible && this._isCSSVisible;\n\n // Only react if visibility actually changed\n if (wasVisible === this._isComponentVisible) {\n return;\n }\n\n if (this._isComponentVisible && this.showPreview) {\n // Component became visible - start previews\n this.initializePreviews();\n } else if (!this._isComponentVisible) {\n // Component became invisible - stop previews\n this.cleanupVideoPreviewStream();\n this.cleanupAudioPreviewStream();\n }\n }\n\n /**\n * Subscribe to device controller observables\n */\n private setupSubscriptions(): void {\n if (!this.deviceController) return;\n\n // Subscribe to audio input devices\n this.subscriptions.push(\n this.deviceController.audioInputDevices$.subscribe((devices) => {\n this._audioInputDevices = devices;\n })\n );\n\n // Subscribe to video input devices\n this.subscriptions.push(\n this.deviceController.videoInputDevices$.subscribe((devices) => {\n this._videoInputDevices = devices;\n })\n );\n\n // Subscribe to audio output devices\n this.subscriptions.push(\n this.deviceController.audioOutputDevices$.subscribe((devices) => {\n this._audioOutputDevices = devices;\n })\n );\n\n // Subscribe to selected devices if available\n if (this.deviceController.selectedAudioInputDevice$) {\n this.subscriptions.push(\n this.deviceController.selectedAudioInputDevice$.subscribe((device) => {\n this._selectedAudioInput = device;\n })\n );\n }\n\n if (this.deviceController.selectedVideoInputDevice$) {\n this.subscriptions.push(\n this.deviceController.selectedVideoInputDevice$.subscribe((device) => {\n this._selectedVideoInput = device;\n })\n );\n }\n\n if (this.deviceController.selectedAudioOutputDevice$) {\n this.subscriptions.push(\n this.deviceController.selectedAudioOutputDevice$.subscribe((device) => {\n this._selectedAudioOutput = device;\n })\n );\n }\n }\n\n /**\n * Cleanup all subscriptions\n */\n private cleanupSubscriptions(): void {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.subscriptions = [];\n }\n\n /**\n * Cleanup video preview stream\n * Best practice from SDK: Pause video, clear srcObject, remove tracks from stream, then stop tracks\n * @see https://webrtchacks.com/srcobject-intervention/\n */\n private cleanupVideoPreviewStream(): void {\n // Step 1: Pause and clear the video element\n if (this._videoElement) {\n this._videoElement.pause();\n this._videoElement.srcObject = null;\n this._videoElement = undefined;\n }\n\n // Also check for any video element in shadow DOM (in case _videoElement wasn't set)\n const videoElement = this.shadowRoot?.querySelector('video');\n if (videoElement) {\n videoElement.pause();\n videoElement.srcObject = null;\n }\n\n // Step 2: Remove tracks from stream before stopping (SDK pattern)\n if (this._videoPreviewStream) {\n const tracks = this._videoPreviewStream.getTracks();\n tracks.forEach((track: MediaStreamTrack) => {\n // Remove track from stream first (important for proper release)\n this._videoPreviewStream?.removeTrack(track);\n track.stop();\n });\n this._videoPreviewStream = null;\n }\n }\n\n /**\n * Cleanup audio preview stream\n * Best practice from SDK: Release audio components, remove tracks from stream, then stop tracks\n * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/stop\n */\n private cleanupAudioPreviewStream(): void {\n // Step 1: Release resources from all audio-level components synchronously\n // This closes their AudioContext and disconnects MediaStreamAudioSourceNode\n const audioLevelComponents = this.shadowRoot?.querySelectorAll('sw-audio-level');\n audioLevelComponents?.forEach((component) => {\n const audioLevel = component as HTMLElement & {\n releaseResources?: () => void;\n stream?: MediaStream;\n };\n if (audioLevel.releaseResources) {\n audioLevel.releaseResources();\n } else {\n // Fallback for older versions\n audioLevel.stream = undefined;\n }\n });\n\n // Step 2: Remove tracks from stream before stopping (SDK pattern)\n if (this._audioPreviewStream) {\n const tracks = this._audioPreviewStream.getTracks();\n tracks.forEach((track: MediaStreamTrack) => {\n // Remove track from stream first (important for proper release)\n this._audioPreviewStream?.removeTrack(track);\n track.stop();\n });\n this._audioPreviewStream = null;\n }\n }\n\n /**\n * Get video preview stream from browser API\n */\n private async getVideoPreviewStream(deviceId?: string): Promise<void> {\n this.cleanupVideoPreviewStream();\n\n if (!this.showPreview) return;\n\n try {\n const constraints: MediaStreamConstraints = {\n video: deviceId ? { deviceId: { exact: deviceId } } : true,\n audio: false\n };\n this._videoPreviewStream = await navigator.mediaDevices.getUserMedia(constraints);\n this.updateVideoElement();\n } catch (error) {\n console.warn('Failed to get video preview stream:', error);\n this._videoPreviewStream = null;\n }\n }\n\n /**\n * Get audio preview stream from browser API\n */\n private async getAudioPreviewStream(deviceId?: string): Promise<void> {\n this.cleanupAudioPreviewStream();\n\n if (!this.showPreview) return;\n\n try {\n const constraints: MediaStreamConstraints = {\n video: false,\n audio: deviceId ? { deviceId: { exact: deviceId } } : true\n };\n this._audioPreviewStream = await navigator.mediaDevices.getUserMedia(constraints);\n } catch (error) {\n console.warn('Failed to get audio preview stream:', error);\n this._audioPreviewStream = null;\n }\n }\n\n /**\n * Update video element with current stream\n */\n private updateVideoElement(): void {\n if (this._videoElement && this._videoPreviewStream) {\n this._videoElement.srcObject = this._videoPreviewStream;\n }\n }\n\n /**\n * Initialize previews when show-preview is enabled\n */\n private async initializePreviews(): Promise<void> {\n // Prevent concurrent initialization to avoid stream leaks on rapid visibility toggles\n if (!this.showPreview || this._isInitializingPreviews) return;\n\n this._isInitializingPreviews = true;\n try {\n // Get video preview if we have video devices\n if (this._videoInputDevices.length > 0) {\n const deviceId = this._selectedVideoInput?.deviceId;\n await this.getVideoPreviewStream(deviceId);\n }\n\n // Get audio preview if we have audio devices\n if (this._audioInputDevices.length > 0) {\n const deviceId = this._selectedAudioInput?.deviceId;\n await this.getAudioPreviewStream(deviceId);\n }\n } finally {\n this._isInitializingPreviews = false;\n }\n }\n\n /**\n * Handle device selection change from dropdown\n */\n private handleDeviceChange(event: Event, deviceType: DeviceType): void {\n if (!this.deviceController) return;\n\n const select = event.target as HTMLSelectElement;\n const deviceId = select.value;\n\n let device: MediaDeviceInfo | null = null;\n\n switch (deviceType) {\n case 'microphone':\n device = this._audioInputDevices.find((d) => d.deviceId === deviceId) || null;\n this._selectedAudioInput = device;\n this.deviceController.selectAudioInputDevice?.(device);\n // Update audio preview stream with new device\n if (this.showPreview) {\n this.getAudioPreviewStream(deviceId);\n }\n break;\n case 'camera':\n device = this._videoInputDevices.find((d) => d.deviceId === deviceId) || null;\n this._selectedVideoInput = device;\n this.deviceController.selectVideoInputDevice?.(device);\n // Update video preview stream with new device\n if (this.showPreview) {\n this.getVideoPreviewStream(deviceId);\n }\n break;\n case 'speaker':\n device = this._audioOutputDevices.find((d) => d.deviceId === deviceId) || null;\n this._selectedAudioOutput = device;\n this.deviceController.selectAudioOutputDevice?.(device);\n break;\n }\n\n if (device) {\n this.dispatchEvent(\n new CustomEvent('sw-device-change', {\n detail: { device, deviceType },\n bubbles: true,\n composed: true\n })\n );\n }\n }\n\n /**\n * Test speaker by playing a test tone\n */\n private async testSpeaker(): Promise<void> {\n if (this._isTestingAudio) {\n this.stopTestAudio();\n return;\n }\n\n try {\n this._isTestingAudio = true;\n\n // Create oscillator-based test tone\n const audioContext = new AudioContext();\n const oscillator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n\n oscillator.type = 'sine';\n oscillator.frequency.value = 440; // A4 note\n gainNode.gain.value = 0.3;\n\n oscillator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n\n oscillator.start();\n\n // Stop after 1 second\n setTimeout(() => {\n oscillator.stop();\n audioContext.close();\n this._isTestingAudio = false;\n }, 1000);\n\n this.dispatchEvent(\n new CustomEvent('sw-test-speaker', {\n bubbles: true,\n composed: true\n })\n );\n } catch (error) {\n console.error('Failed to play test audio:', error);\n this._isTestingAudio = false;\n }\n }\n\n /**\n * Stop test audio\n */\n private stopTestAudio(): void {\n if (this._testAudioElement) {\n this._testAudioElement.pause();\n this._testAudioElement = undefined;\n }\n this._isTestingAudio = false;\n }\n\n /**\n * Render device icon\n */\n private renderDeviceIcon(deviceType: DeviceType) {\n switch (deviceType) {\n case 'microphone':\n return html`<svg class=\"device-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n d=\"M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.91-3c-.49 0-.9.36-.98.85C16.52 14.2 14.47 16 12 16s-4.52-1.8-4.93-4.15c-.08-.49-.49-.85-.98-.85-.61 0-1.09.54-1 1.14.49 3 2.89 5.35 5.91 5.78V20c0 .55.45 1 1 1s1-.45 1-1v-2.08c3.02-.43 5.42-2.78 5.91-5.78.1-.6-.39-1.14-1-1.14z\"\n />\n </svg>`;\n case 'camera':\n return html`<svg class=\"device-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n d=\"M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z\"\n />\n </svg>`;\n case 'speaker':\n return html`<svg class=\"device-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"\n />\n </svg>`;\n }\n }\n\n /**\n * Render dropdown arrow icon\n */\n private renderSelectArrow() {\n return html`<svg class=\"select-arrow\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M7 10l5 5 5-5z\" />\n </svg>`;\n }\n\n /**\n * Render a device selection section\n */\n private renderDeviceSection(\n deviceType: DeviceType,\n label: string,\n devices: MediaDeviceInfo[],\n selectedDevice: MediaDeviceInfo | null\n ) {\n return html`\n <div class=\"device-section\" part=\"device-section\">\n <label class=\"device-label\" for=\"select-${deviceType}\">\n ${this.renderDeviceIcon(deviceType)}\n <span>${label}</span>\n </label>\n ${devices.length === 0\n ? html`<div class=\"no-devices\">No ${label.toLowerCase()} found</div>`\n : html`\n <div class=\"device-select-wrapper\">\n <select\n id=\"select-${deviceType}\"\n class=\"device-select\"\n part=\"device-select\"\n aria-label=\"${label}\"\n .value=${selectedDevice?.deviceId || ''}\n @change=${(e: Event) => this.handleDeviceChange(e, deviceType)}\n >\n ${devices.map(\n (device) => html`\n <option\n value=\"${device.deviceId}\"\n ?selected=${selectedDevice?.deviceId === device.deviceId}\n >\n ${device.label || `Device ${device.deviceId.slice(0, 8)}`}\n </option>\n `\n )}\n </select>\n ${this.renderSelectArrow()}\n </div>\n `}\n </div>\n `;\n }\n\n /**\n * Render video preview for camera section\n */\n private renderVideoPreview() {\n if (!this.showPreview || this._videoInputDevices.length === 0) {\n return nothing;\n }\n\n return html`\n <div class=\"device-preview\">\n ${this._videoPreviewStream\n ? html`\n <div class=\"video-preview\">\n <video\n autoplay\n playsinline\n muted\n .srcObject=${this._videoPreviewStream}\n @loadedmetadata=${(e: Event) => {\n const video = e.target as HTMLVideoElement;\n this._videoElement = video;\n video.play().catch(() => {});\n }}\n ></video>\n </div>\n `\n : html` <div class=\"video-preview-placeholder\">Click to enable camera preview</div> `}\n </div>\n `;\n }\n\n /**\n * Render audio level preview for microphone section\n */\n private renderAudioPreview() {\n if (!this.showPreview || this._audioInputDevices.length === 0) {\n return nothing;\n }\n\n return html`\n <div class=\"device-preview\">\n <div class=\"audio-preview\">\n <span class=\"audio-preview-label\">Level:</span>\n <div class=\"audio-level-wrapper\">\n ${this._audioPreviewStream\n ? html`\n <sw-audio-level\n .stream=${this._audioPreviewStream}\n bars=\"10\"\n orientation=\"horizontal\"\n maxSize=\"20\"\n ></sw-audio-level>\n `\n : html`\n <span style=\"color: var(--sw-color-text-muted); font-size: 12px;\"\n >No audio input</span\n >\n `}\n </div>\n </div>\n </div>\n `;\n }\n\n /**\n * Render the component\n */\n render() {\n return html`\n <div class=\"container\" part=\"container\">\n ${this.renderDeviceSection(\n 'microphone',\n 'Microphone',\n this._audioInputDevices,\n this._selectedAudioInput\n )}\n ${this.renderAudioPreview()}\n ${this.renderDeviceSection(\n 'camera',\n 'Camera',\n this._videoInputDevices,\n this._selectedVideoInput\n )}\n ${this.renderVideoPreview()}\n ${this.renderDeviceSection(\n 'speaker',\n 'Speaker',\n this._audioOutputDevices,\n this._selectedAudioOutput\n )}\n\n <div class=\"device-section\">\n <button\n class=\"test-speaker-btn\"\n @click=${this.testSpeaker}\n ?disabled=${this._isTestingAudio}\n aria-label=\"Test speaker\"\n >\n ${this._isTestingAudio ? 'Playing...' : 'Test Speaker'}\n </button>\n </div>\n </div>\n `;\n }\n}\n\n/**\n * Declare global type for TypeScript\n */\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-device-selector': DeviceSelector;\n }\n}\n"],"names":["DeviceSelector","LitElement","changedProperties","entries","entry","wasVisible","element","style","root","devices","device","sub","videoElement","_a","track","audioLevelComponents","component","audioLevel","deviceId","constraints","error","_b","event","deviceType","d","_d","_c","_f","_e","audioContext","oscillator","gainNode","html","label","selectedDevice","e","nothing","video","css","__decorateClass","property","state","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"device-selector.js","sources":["../../src/components/device-selector.ts"],"sourcesContent":["/**\n * Device Selector Component\n *\n * Dropdown-based selector for choosing audio/video devices. Displays device lists from\n * DeviceController observables with labeled dropdowns for microphone, camera, and speaker.\n * Includes inline preview for video (camera) and audio level (microphone) using browser API.\n *\n * @example\n * ```html\n * <sw-device-selector .deviceController=${deviceController} show-preview></sw-device-selector>\n * ```\n */\n\nimport { LitElement, html, css, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { Subscription } from 'rxjs';\nimport type { DeviceController } from '@signalwire/js';\nimport './audio-level.js';\n\ntype DeviceType = 'microphone' | 'camera' | 'speaker';\n\n@customElement('sw-device-selector')\nexport class DeviceSelector extends LitElement {\n static styles = css`\n :host {\n /* CSS Custom Properties for theming */\n --sw-color-primary: #044cf6;\n --sw-color-primary-hover: #0339c4;\n --sw-color-background: #1a1a1a;\n --sw-color-surface: #2a2a2a;\n --sw-color-surface-hover: #3a3a3a;\n --sw-color-text: #ffffff;\n --sw-color-text-muted: #a0a0a0;\n --sw-color-border: #404040;\n --sw-color-success: #10b981;\n --sw-border-radius: 8px;\n --sw-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --sw-space-1: 4px;\n --sw-space-2: 8px;\n --sw-space-3: 12px;\n --sw-space-4: 16px;\n --sw-space-6: 24px;\n\n display: block;\n font-family: var(--sw-font-family);\n color: var(--sw-color-text);\n }\n\n .container {\n background: var(--sw-color-background);\n border-radius: var(--sw-border-radius);\n border: 1px solid var(--sw-color-border);\n overflow: hidden;\n min-width: 300px;\n padding: var(--sw-space-4);\n }\n\n .device-section {\n margin-bottom: var(--sw-space-4);\n }\n\n .device-section:last-of-type {\n margin-bottom: 0;\n }\n\n .device-label {\n display: flex;\n align-items: center;\n gap: var(--sw-space-2);\n font-size: 14px;\n font-weight: 500;\n color: var(--sw-color-text);\n margin-bottom: var(--sw-space-2);\n }\n\n .device-icon {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n color: var(--sw-color-text-muted);\n }\n\n .device-select-wrapper {\n position: relative;\n }\n\n .device-select {\n width: 100%;\n padding: var(--sw-space-3) var(--sw-space-4);\n padding-right: 36px;\n background: var(--sw-color-surface);\n border: 1px solid var(--sw-color-border);\n border-radius: calc(var(--sw-border-radius) - 4px);\n color: var(--sw-color-text);\n font-size: 14px;\n font-family: var(--sw-font-family);\n cursor: pointer;\n appearance: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n transition:\n border-color 0.2s ease,\n background-color 0.2s ease;\n }\n\n .device-select:hover {\n background: var(--sw-color-surface-hover);\n }\n\n .device-select:focus {\n outline: none;\n border-color: var(--sw-color-primary);\n box-shadow: 0 0 0 2px rgba(4, 76, 246, 0.2);\n }\n\n .device-select:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .device-select option {\n background: var(--sw-color-surface);\n color: var(--sw-color-text);\n padding: var(--sw-space-2);\n }\n\n .select-arrow {\n position: absolute;\n right: var(--sw-space-3);\n top: 50%;\n transform: translateY(-50%);\n width: 16px;\n height: 16px;\n color: var(--sw-color-text-muted);\n pointer-events: none;\n }\n\n .no-devices {\n padding: var(--sw-space-3) var(--sw-space-4);\n background: var(--sw-color-surface);\n border: 1px solid var(--sw-color-border);\n border-radius: calc(var(--sw-border-radius) - 4px);\n color: var(--sw-color-text-muted);\n font-size: 14px;\n }\n\n .device-preview {\n margin-top: var(--sw-space-3);\n }\n\n .video-preview {\n width: 100%;\n aspect-ratio: 16/9;\n background: #000;\n border-radius: calc(var(--sw-border-radius) - 4px);\n overflow: hidden;\n }\n\n .video-preview video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transform: scaleX(-1);\n }\n\n .video-preview-placeholder {\n width: 100%;\n aspect-ratio: 16/9;\n background: var(--sw-color-surface);\n border-radius: calc(var(--sw-border-radius) - 4px);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--sw-color-text-muted);\n font-size: 14px;\n }\n\n .audio-preview {\n display: flex;\n align-items: center;\n gap: var(--sw-space-3);\n padding: var(--sw-space-3);\n background: var(--sw-color-surface);\n border-radius: calc(var(--sw-border-radius) - 4px);\n }\n\n .audio-preview-label {\n font-size: 12px;\n color: var(--sw-color-text-muted);\n flex-shrink: 0;\n }\n\n .audio-level-wrapper {\n flex: 1;\n display: flex;\n justify-content: center;\n }\n\n .test-speaker-btn {\n padding: var(--sw-space-2) var(--sw-space-4);\n background: var(--sw-color-primary);\n color: white;\n border: none;\n border-radius: calc(var(--sw-border-radius) - 4px);\n font-size: 14px;\n cursor: pointer;\n transition: background-color 0.2s ease;\n }\n\n .test-speaker-btn:hover {\n background: var(--sw-color-primary-hover);\n }\n\n .test-speaker-btn:focus {\n outline: none;\n box-shadow:\n 0 0 0 2px var(--sw-color-background),\n 0 0 0 4px var(--sw-color-primary);\n }\n\n .test-speaker-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n /* Scrollbar styling for select on some browsers */\n .device-select::-webkit-scrollbar {\n width: 8px;\n }\n\n .device-select::-webkit-scrollbar-track {\n background: var(--sw-color-background);\n }\n\n .device-select::-webkit-scrollbar-thumb {\n background: var(--sw-color-border);\n border-radius: 4px;\n }\n\n .device-select::-webkit-scrollbar-thumb:hover {\n background: var(--sw-color-text-muted);\n }\n `;\n\n /**\n * Device controller with observables for device lists\n */\n @property({ type: Object }) deviceController?: DeviceController;\n\n /**\n * Whether to show the preview panel\n */\n @property({ type: Boolean, attribute: 'show-preview' }) showPreview = false;\n\n /**\n * Audio input devices\n */\n @state() private _audioInputDevices: MediaDeviceInfo[] = [];\n\n /**\n * Video input devices\n */\n @state() private _videoInputDevices: MediaDeviceInfo[] = [];\n\n /**\n * Audio output devices\n */\n @state() private _audioOutputDevices: MediaDeviceInfo[] = [];\n\n /**\n * Selected audio input device\n */\n @state() private _selectedAudioInput: MediaDeviceInfo | null = null;\n\n /**\n * Selected video input device\n */\n @state() private _selectedVideoInput: MediaDeviceInfo | null = null;\n\n /**\n * Selected audio output device\n */\n @state() private _selectedAudioOutput: MediaDeviceInfo | null = null;\n\n /**\n * Video preview stream from camera\n */\n @state() private _videoPreviewStream: MediaStream | null = null;\n\n /**\n * Audio preview stream from microphone\n */\n @state() private _audioPreviewStream: MediaStream | null = null;\n\n /**\n * Is test audio playing\n */\n @state() private _isTestingAudio = false;\n\n /**\n * Whether the component is currently visible (combines all visibility factors)\n */\n private _isComponentVisible = false;\n\n /**\n * Whether the component is in the viewport (IntersectionObserver)\n */\n private _isInViewport = false;\n\n /**\n * Whether the document/tab is visible\n */\n private _isDocumentVisible = true;\n\n /**\n * Whether the component is CSS-visible (display, visibility, opacity)\n */\n private _isCSSVisible = true;\n\n /**\n * Video element reference\n */\n private _videoElement?: HTMLVideoElement;\n\n /**\n * RxJS subscriptions for cleanup\n */\n private subscriptions: Subscription[] = [];\n\n /**\n * Audio element for speaker test\n */\n private _testAudioElement?: HTMLAudioElement;\n\n /**\n * IntersectionObserver for viewport visibility\n */\n private _intersectionObserver?: IntersectionObserver;\n\n /**\n * Bound handler for document visibility change\n */\n private _boundHandleDocumentVisibility = this.handleDocumentVisibilityChange.bind(this);\n\n /**\n * Interval ID for CSS visibility polling\n */\n private _cssVisibilityCheckInterval?: ReturnType<typeof setInterval>;\n\n /**\n * Flag to prevent concurrent preview initialization\n */\n private _isInitializingPreviews = false;\n\n /**\n * Interval in milliseconds for checking CSS visibility changes\n */\n private static readonly CSS_VISIBILITY_CHECK_INTERVAL_MS = 200;\n\n /**\n * Lifecycle: Component connected to DOM\n */\n connectedCallback() {\n super.connectedCallback();\n this.setupSubscriptions();\n this.setupVisibilityObservers();\n }\n\n /**\n * Lifecycle: React to property changes\n */\n protected updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n if (changedProperties.has('deviceController')) {\n this.cleanupSubscriptions();\n this.setupSubscriptions();\n }\n if (changedProperties.has('showPreview')) {\n if (this.showPreview && this._isComponentVisible) {\n // Only initialize if component is visible\n this.initializePreviews();\n } else if (!this.showPreview) {\n // Always cleanup when showPreview is disabled\n this.cleanupVideoPreviewStream();\n this.cleanupAudioPreviewStream();\n }\n }\n }\n\n /**\n * Lifecycle: Component disconnected from DOM\n */\n disconnectedCallback() {\n super.disconnectedCallback();\n this.cleanupSubscriptions();\n this.cleanupVisibilityObservers();\n this.cleanupVideoPreviewStream();\n this.cleanupAudioPreviewStream();\n this.stopTestAudio();\n }\n\n /**\n * Setup all visibility observers (IntersectionObserver, document visibility, CSS polling)\n */\n private setupVisibilityObservers(): void {\n // Defensive cleanup in case of multiple calls without disconnect\n this.cleanupVisibilityObservers();\n\n // Setup IntersectionObserver for viewport visibility\n this._intersectionObserver = new IntersectionObserver(\n (entries) => {\n const entry = entries[0];\n if (entry) {\n this._isInViewport = entry.isIntersecting;\n this.updateVisibilityState();\n }\n },\n { threshold: 0 }\n );\n this._intersectionObserver.observe(this);\n\n // Setup document visibility change listener\n this._isDocumentVisible = document.visibilityState === 'visible';\n document.addEventListener('visibilitychange', this._boundHandleDocumentVisibility);\n\n // Setup CSS visibility polling (checks opacity, display, visibility)\n this._isCSSVisible = this.checkCSSVisibility();\n this._cssVisibilityCheckInterval = setInterval(() => {\n const wasVisible = this._isCSSVisible;\n this._isCSSVisible = this.checkCSSVisibility();\n if (wasVisible !== this._isCSSVisible) {\n this.updateVisibilityState();\n }\n }, DeviceSelector.CSS_VISIBILITY_CHECK_INTERVAL_MS);\n }\n\n /**\n * Cleanup all visibility observers\n */\n private cleanupVisibilityObservers(): void {\n if (this._intersectionObserver) {\n this._intersectionObserver.disconnect();\n this._intersectionObserver = undefined;\n }\n\n document.removeEventListener('visibilitychange', this._boundHandleDocumentVisibility);\n\n if (this._cssVisibilityCheckInterval) {\n clearInterval(this._cssVisibilityCheckInterval);\n this._cssVisibilityCheckInterval = undefined;\n }\n }\n\n /**\n * Handle document visibility change (tab switching)\n */\n private handleDocumentVisibilityChange(): void {\n this._isDocumentVisible = document.visibilityState === 'visible';\n this.updateVisibilityState();\n }\n\n /**\n * Check if the component is visible via CSS (display, visibility, opacity)\n * Traverses the DOM tree including shadow DOM boundaries\n */\n private checkCSSVisibility(): boolean {\n // Guard against being called when disconnected\n if (!this.isConnected) {\n return false;\n }\n\n let element: HTMLElement | null = this;\n while (element) {\n const style = getComputedStyle(element);\n if (\n style.display === 'none' ||\n style.visibility === 'hidden' ||\n parseFloat(style.opacity) === 0\n ) {\n return false;\n }\n\n // Handle shadow DOM boundaries by traversing through shadow hosts\n if (element.parentElement) {\n element = element.parentElement;\n } else {\n const root = element.getRootNode();\n element = root instanceof ShadowRoot ? (root.host as HTMLElement) : null;\n }\n }\n return true;\n }\n\n /**\n * Update the combined visibility state and manage preview streams accordingly\n */\n private updateVisibilityState(): void {\n const wasVisible = this._isComponentVisible;\n this._isComponentVisible = this._isInViewport && this._isDocumentVisible && this._isCSSVisible;\n\n // Only react if visibility actually changed\n if (wasVisible === this._isComponentVisible) {\n return;\n }\n\n if (this._isComponentVisible && this.showPreview) {\n // Component became visible - start previews\n this.initializePreviews();\n } else if (!this._isComponentVisible) {\n // Component became invisible - stop previews\n this.cleanupVideoPreviewStream();\n this.cleanupAudioPreviewStream();\n }\n }\n\n /**\n * Subscribe to device controller observables\n */\n private setupSubscriptions(): void {\n if (!this.deviceController) return;\n\n // Subscribe to audio input devices\n this.subscriptions.push(\n this.deviceController.audioInputDevices$.subscribe((devices) => {\n this._audioInputDevices = devices;\n })\n );\n\n // Subscribe to video input devices\n this.subscriptions.push(\n this.deviceController.videoInputDevices$.subscribe((devices) => {\n this._videoInputDevices = devices;\n })\n );\n\n // Subscribe to audio output devices\n this.subscriptions.push(\n this.deviceController.audioOutputDevices$.subscribe((devices) => {\n this._audioOutputDevices = devices;\n })\n );\n\n // Subscribe to selected devices if available\n if (this.deviceController.selectedAudioInputDevice$) {\n this.subscriptions.push(\n this.deviceController.selectedAudioInputDevice$.subscribe((device) => {\n this._selectedAudioInput = device;\n })\n );\n }\n\n if (this.deviceController.selectedVideoInputDevice$) {\n this.subscriptions.push(\n this.deviceController.selectedVideoInputDevice$.subscribe((device) => {\n this._selectedVideoInput = device;\n })\n );\n }\n\n if (this.deviceController.selectedAudioOutputDevice$) {\n this.subscriptions.push(\n this.deviceController.selectedAudioOutputDevice$.subscribe((device) => {\n this._selectedAudioOutput = device;\n })\n );\n }\n }\n\n /**\n * Cleanup all subscriptions\n */\n private cleanupSubscriptions(): void {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.subscriptions = [];\n }\n\n /**\n * Cleanup video preview stream\n * Best practice from SDK: Pause video, clear srcObject, remove tracks from stream, then stop tracks\n * @see https://webrtchacks.com/srcobject-intervention/\n */\n private cleanupVideoPreviewStream(): void {\n // Step 1: Pause and clear the video element\n if (this._videoElement) {\n this._videoElement.pause();\n this._videoElement.srcObject = null;\n this._videoElement = undefined;\n }\n\n // Also check for any video element in shadow DOM (in case _videoElement wasn't set)\n const videoElement = this.shadowRoot?.querySelector('video');\n if (videoElement) {\n videoElement.pause();\n videoElement.srcObject = null;\n }\n\n // Step 2: Remove tracks from stream before stopping (SDK pattern)\n if (this._videoPreviewStream) {\n const tracks = this._videoPreviewStream.getTracks();\n tracks.forEach((track: MediaStreamTrack) => {\n // Remove track from stream first (important for proper release)\n this._videoPreviewStream?.removeTrack(track);\n track.stop();\n });\n this._videoPreviewStream = null;\n }\n }\n\n /**\n * Cleanup audio preview stream\n * Best practice from SDK: Release audio components, remove tracks from stream, then stop tracks\n * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/stop\n */\n private cleanupAudioPreviewStream(): void {\n // Step 1: Release resources from all audio-level components synchronously\n // This closes their AudioContext and disconnects MediaStreamAudioSourceNode\n const audioLevelComponents = this.shadowRoot?.querySelectorAll('sw-audio-level');\n audioLevelComponents?.forEach((component) => {\n const audioLevel = component as HTMLElement & {\n releaseResources?: () => void;\n stream?: MediaStream;\n };\n if (audioLevel.releaseResources) {\n audioLevel.releaseResources();\n } else {\n // Fallback for older versions\n audioLevel.stream = undefined;\n }\n });\n\n // Step 2: Remove tracks from stream before stopping (SDK pattern)\n if (this._audioPreviewStream) {\n const tracks = this._audioPreviewStream.getTracks();\n tracks.forEach((track: MediaStreamTrack) => {\n // Remove track from stream first (important for proper release)\n this._audioPreviewStream?.removeTrack(track);\n track.stop();\n });\n this._audioPreviewStream = null;\n }\n }\n\n /**\n * Get video preview stream from browser API\n */\n private async getVideoPreviewStream(deviceId?: string): Promise<void> {\n this.cleanupVideoPreviewStream();\n\n if (!this.showPreview) return;\n\n try {\n const constraints: MediaStreamConstraints = {\n video: deviceId ? { deviceId: { exact: deviceId } } : true,\n audio: false\n };\n this._videoPreviewStream = await navigator.mediaDevices.getUserMedia(constraints);\n this.updateVideoElement();\n } catch (error) {\n console.warn('Failed to get video preview stream:', error);\n this._videoPreviewStream = null;\n }\n }\n\n /**\n * Get audio preview stream from browser API\n */\n private async getAudioPreviewStream(deviceId?: string): Promise<void> {\n this.cleanupAudioPreviewStream();\n\n if (!this.showPreview) return;\n\n try {\n const constraints: MediaStreamConstraints = {\n video: false,\n audio: deviceId ? { deviceId: { exact: deviceId } } : true\n };\n this._audioPreviewStream = await navigator.mediaDevices.getUserMedia(constraints);\n } catch (error) {\n console.warn('Failed to get audio preview stream:', error);\n this._audioPreviewStream = null;\n }\n }\n\n /**\n * Update video element with current stream\n */\n private updateVideoElement(): void {\n if (this._videoElement && this._videoPreviewStream) {\n this._videoElement.srcObject = this._videoPreviewStream;\n }\n }\n\n /**\n * Initialize previews when show-preview is enabled\n */\n private async initializePreviews(): Promise<void> {\n // Prevent concurrent initialization to avoid stream leaks on rapid visibility toggles\n if (!this.showPreview || this._isInitializingPreviews) return;\n\n this._isInitializingPreviews = true;\n try {\n // Get video preview if we have video devices\n if (this._videoInputDevices.length > 0) {\n const deviceId = this._selectedVideoInput?.deviceId;\n await this.getVideoPreviewStream(deviceId);\n }\n\n // Get audio preview if we have audio devices\n if (this._audioInputDevices.length > 0) {\n const deviceId = this._selectedAudioInput?.deviceId;\n await this.getAudioPreviewStream(deviceId);\n }\n } finally {\n this._isInitializingPreviews = false;\n }\n }\n\n /**\n * Handle device selection change from dropdown\n */\n private handleDeviceChange(event: Event, deviceType: DeviceType): void {\n if (!this.deviceController) return;\n\n const select = event.target as HTMLSelectElement;\n const deviceId = select.value;\n\n let device: MediaDeviceInfo | null = null;\n\n switch (deviceType) {\n case 'microphone':\n device = this._audioInputDevices.find((d) => d.deviceId === deviceId) || null;\n this._selectedAudioInput = device;\n this.deviceController.selectAudioInputDevice?.(device);\n // Update audio preview stream with new device\n if (this.showPreview) {\n this.getAudioPreviewStream(deviceId);\n }\n break;\n case 'camera':\n device = this._videoInputDevices.find((d) => d.deviceId === deviceId) || null;\n this._selectedVideoInput = device;\n this.deviceController.selectVideoInputDevice?.(device);\n // Update video preview stream with new device\n if (this.showPreview) {\n this.getVideoPreviewStream(deviceId);\n }\n break;\n case 'speaker':\n device = this._audioOutputDevices.find((d) => d.deviceId === deviceId) || null;\n this._selectedAudioOutput = device;\n this.deviceController.selectAudioOutputDevice?.(device);\n break;\n }\n\n if (device) {\n this.dispatchEvent(\n new CustomEvent('sw-device-change', {\n detail: { device, deviceType },\n bubbles: true,\n composed: true\n })\n );\n }\n }\n\n /**\n * Test speaker by playing a test tone\n */\n private async testSpeaker(): Promise<void> {\n if (this._isTestingAudio) {\n this.stopTestAudio();\n return;\n }\n\n try {\n this._isTestingAudio = true;\n\n // Create oscillator-based test tone\n const audioContext = new AudioContext();\n const oscillator = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n\n oscillator.type = 'sine';\n oscillator.frequency.value = 440; // A4 note\n gainNode.gain.value = 0.3;\n\n oscillator.connect(gainNode);\n gainNode.connect(audioContext.destination);\n\n oscillator.start();\n\n // Stop after 1 second\n setTimeout(() => {\n oscillator.stop();\n audioContext.close();\n this._isTestingAudio = false;\n }, 1000);\n\n this.dispatchEvent(\n new CustomEvent('sw-test-speaker', {\n bubbles: true,\n composed: true\n })\n );\n } catch (error) {\n console.error('Failed to play test audio:', error);\n this._isTestingAudio = false;\n }\n }\n\n /**\n * Stop test audio\n */\n private stopTestAudio(): void {\n if (this._testAudioElement) {\n this._testAudioElement.pause();\n this._testAudioElement = undefined;\n }\n this._isTestingAudio = false;\n }\n\n /**\n * Render device icon\n */\n private renderDeviceIcon(deviceType: DeviceType) {\n switch (deviceType) {\n case 'microphone':\n return html`<svg class=\"device-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n d=\"M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.91-3c-.49 0-.9.36-.98.85C16.52 14.2 14.47 16 12 16s-4.52-1.8-4.93-4.15c-.08-.49-.49-.85-.98-.85-.61 0-1.09.54-1 1.14.49 3 2.89 5.35 5.91 5.78V20c0 .55.45 1 1 1s1-.45 1-1v-2.08c3.02-.43 5.42-2.78 5.91-5.78.1-.6-.39-1.14-1-1.14z\"\n />\n </svg>`;\n case 'camera':\n return html`<svg class=\"device-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n d=\"M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z\"\n />\n </svg>`;\n case 'speaker':\n return html`<svg class=\"device-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"\n />\n </svg>`;\n }\n }\n\n /**\n * Render dropdown arrow icon\n */\n private renderSelectArrow() {\n return html`<svg class=\"select-arrow\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M7 10l5 5 5-5z\" />\n </svg>`;\n }\n\n /**\n * Render a device selection section\n */\n private renderDeviceSection(\n deviceType: DeviceType,\n label: string,\n devices: MediaDeviceInfo[],\n selectedDevice: MediaDeviceInfo | null\n ) {\n return html`\n <div class=\"device-section\" part=\"device-section\">\n <label class=\"device-label\" for=\"select-${deviceType}\">\n ${this.renderDeviceIcon(deviceType)}\n <span>${label}</span>\n </label>\n ${devices.length === 0\n ? html`<div class=\"no-devices\">No ${label.toLowerCase()} found</div>`\n : html`\n <div class=\"device-select-wrapper\">\n <select\n id=\"select-${deviceType}\"\n class=\"device-select\"\n part=\"device-select\"\n aria-label=\"${label}\"\n .value=${selectedDevice?.deviceId || ''}\n @change=${(e: Event) => this.handleDeviceChange(e, deviceType)}\n >\n ${devices.map(\n (device) => html`\n <option\n value=\"${device.deviceId}\"\n ?selected=${selectedDevice?.deviceId === device.deviceId}\n >\n ${device.label || `Device ${device.deviceId.slice(0, 8)}`}\n </option>\n `\n )}\n </select>\n ${this.renderSelectArrow()}\n </div>\n `}\n </div>\n `;\n }\n\n /**\n * Render video preview for camera section\n */\n private renderVideoPreview() {\n if (!this.showPreview || this._videoInputDevices.length === 0) {\n return nothing;\n }\n\n return html`\n <div class=\"device-preview\">\n ${this._videoPreviewStream\n ? html`\n <div class=\"video-preview\">\n <video\n autoplay\n playsinline\n muted\n .srcObject=${this._videoPreviewStream}\n @loadedmetadata=${(e: Event) => {\n const video = e.target as HTMLVideoElement;\n this._videoElement = video;\n video.play().catch(() => {});\n }}\n ></video>\n </div>\n `\n : html` <div class=\"video-preview-placeholder\">Click to enable camera preview</div> `}\n </div>\n `;\n }\n\n /**\n * Render audio level preview for microphone section\n */\n private renderAudioPreview() {\n if (!this.showPreview || this._audioInputDevices.length === 0) {\n return nothing;\n }\n\n return html`\n <div class=\"device-preview\">\n <div class=\"audio-preview\">\n <span class=\"audio-preview-label\">Level:</span>\n <div class=\"audio-level-wrapper\">\n ${this._audioPreviewStream\n ? html`\n <sw-audio-level\n .stream=${this._audioPreviewStream}\n bars=\"10\"\n orientation=\"horizontal\"\n maxSize=\"20\"\n ></sw-audio-level>\n `\n : html`\n <span style=\"color: var(--sw-color-text-muted); font-size: 12px;\"\n >No audio input</span\n >\n `}\n </div>\n </div>\n </div>\n `;\n }\n\n /**\n * Render the component\n */\n render() {\n return html`\n <div class=\"container\" part=\"container\">\n ${this.renderDeviceSection(\n 'microphone',\n 'Microphone',\n this._audioInputDevices,\n this._selectedAudioInput\n )}\n ${this.renderAudioPreview()}\n ${this.renderDeviceSection(\n 'camera',\n 'Camera',\n this._videoInputDevices,\n this._selectedVideoInput\n )}\n ${this.renderVideoPreview()}\n ${this.renderDeviceSection(\n 'speaker',\n 'Speaker',\n this._audioOutputDevices,\n this._selectedAudioOutput\n )}\n\n <div class=\"device-section\">\n <button\n class=\"test-speaker-btn\"\n @click=${this.testSpeaker}\n ?disabled=${this._isTestingAudio}\n aria-label=\"Test speaker\"\n >\n ${this._isTestingAudio ? 'Playing...' : 'Test Speaker'}\n </button>\n </div>\n </div>\n `;\n }\n}\n\n/**\n * Declare global type for TypeScript\n */\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-device-selector': DeviceSelector;\n }\n}\n"],"names":["DeviceSelector","LitElement","changedProperties","entries","entry","wasVisible","element","style","root","devices","device","sub","videoElement","_a","track","audioLevelComponents","component","audioLevel","deviceId","constraints","error","_b","event","deviceType","d","_d","_c","_f","_e","audioContext","oscillator","gainNode","html","label","selectedDevice","e","nothing","video","css","__decorateClass","property","state","customElement"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -14,7 +14,7 @@ export { DialpadComponent } from './components/dialpad.js';
14
14
  export { ClickToCallComponent } from './components/click-to-call.js';
15
15
  export { DirectoryComponent } from './components/directory.js';
16
16
  export { ParticipantControlsComponent } from './components/participant-controls.js';
17
- export * from './types/index.js';
17
+ export type { Call, CallSelf, DeviceController, LayoutLayer, Participant } from './types/index.js';
18
18
  export * from './context/index.js';
19
19
  export { html, css, LitElement } from 'lit';
20
20
  export type { TemplateResult, CSSResult } from 'lit';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AAGpF,cAAc,kBAAkB,CAAC;AAGjC,cAAc,oBAAoB,CAAC;AAGnC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAQrD;;GAEG;AACH,eAAO,MAAM,OAAO,EAAE,MAAoB,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,KAAK,EAAE,OAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AAGpF,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGnG,cAAc,oBAAoB,CAAC;AAGnC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAQrD;;GAEG;AACH,eAAO,MAAM,OAAO,EAAE,MAAoB,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,KAAK,EAAE,OAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,18 +1,17 @@
1
1
  import { ExampleButton as m } from "./components/example-button.js";
2
- import { CallMedia as a } from "./components/call-media.js";
2
+ import { CallMedia as l } from "./components/call-media.js";
3
3
  import { Participants as f } from "./components/participants.js";
4
- import { SelfMedia as s } from "./components/self-media.js";
5
- import { AudioLevel as d } from "./components/audio-level.js";
4
+ import { SelfMedia as c } from "./components/self-media.js";
5
+ import { AudioLevel as C } from "./components/audio-level.js";
6
6
  import { DeviceSelector as v } from "./components/device-selector.js";
7
7
  import { CallControls as u } from "./components/call-controls.js";
8
8
  import { CallStatusComponent as E } from "./components/call-status.js";
9
- import { DialpadComponent as D } from "./components/dialpad.js";
10
- import { ClickToCallComponent as g } from "./components/click-to-call.js";
11
- import { DirectoryComponent as L } from "./components/directory.js";
12
- import { ParticipantControlsComponent as b } from "./components/participant-controls.js";
13
- import { castParticipants as A, getSelfId as B } from "./types/index.js";
14
- import { LitElement as R, css as T, html as j } from "lit";
15
- import { callContext as z } from "./context/call-context.js";
9
+ import { DialpadComponent as S } from "./components/dialpad.js";
10
+ import { ClickToCallComponent as L } from "./components/click-to-call.js";
11
+ import { DirectoryComponent as P } from "./components/directory.js";
12
+ import { ParticipantControlsComponent as g } from "./components/participant-controls.js";
13
+ import { LitElement as A, css as B, html as R } from "lit";
14
+ import { callContext as j } from "./context/call-context.js";
16
15
  const t = "1.0.0-rc.0", r = !0, e = () => {
17
16
  if (typeof window < "u") {
18
17
  const o = new CustomEvent("signalwire:web-components:ready", {
@@ -23,24 +22,22 @@ const t = "1.0.0-rc.0", r = !0, e = () => {
23
22
  };
24
23
  e();
25
24
  export {
26
- d as AudioLevel,
25
+ C as AudioLevel,
27
26
  u as CallControls,
28
- a as CallMedia,
27
+ l as CallMedia,
29
28
  E as CallStatusComponent,
30
- g as ClickToCallComponent,
29
+ L as ClickToCallComponent,
31
30
  v as DeviceSelector,
32
- D as DialpadComponent,
33
- L as DirectoryComponent,
31
+ S as DialpadComponent,
32
+ P as DirectoryComponent,
34
33
  m as ExampleButton,
35
- R as LitElement,
36
- b as ParticipantControlsComponent,
34
+ A as LitElement,
35
+ g as ParticipantControlsComponent,
37
36
  f as Participants,
38
- s as SelfMedia,
39
- z as callContext,
40
- A as castParticipants,
41
- T as css,
42
- B as getSelfId,
43
- j as html,
37
+ c as SelfMedia,
38
+ j as callContext,
39
+ B as css,
40
+ R as html,
44
41
  r as ready,
45
42
  t as version
46
43
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * @signalwire/web-components\n * UI Components Library built with Lit\n */\n\n// Export components\nexport { ExampleButton } from './components/example-button.js';\nexport { CallMedia } from './components/call-media.js';\nexport { Participants } from './components/participants.js';\nexport { SelfMedia } from './components/self-media.js';\nexport { AudioLevel } from './components/audio-level.js';\nexport { DeviceSelector } from './components/device-selector.js';\nexport { CallControls } from './components/call-controls.js';\nexport { CallStatusComponent } from './components/call-status.js';\nexport { DialpadComponent } from './components/dialpad.js';\nexport { ClickToCallComponent } from './components/click-to-call.js';\nexport { DirectoryComponent } from './components/directory.js';\nexport { ParticipantControlsComponent } from './components/participant-controls.js';\n\n// Export types (re-exported from core)\nexport * from './types/index.js';\n\n// Export context\nexport * from './context/index.js';\n\n// Re-export Lit utilities for convenience\nexport { html, css, LitElement } from 'lit';\nexport type { TemplateResult, CSSResult } from 'lit';\n\n// ============================================================================\n// Library Ready Event (for async/dynamic script loading)\n// ============================================================================\n\ndeclare const __VERSION__: string;\n\n/**\n * Library version from package.json, injected at build time.\n */\nexport const version: string = __VERSION__;\n\n/**\n * Flag indicating the library has been loaded and is ready to use.\n */\nexport const ready: boolean = true;\n\n/**\n * Emits 'signalwire:web-components:ready' event when the library is loaded.\n *\n * Scripts that might load BEFORE the library (check flag first):\n * ```js\n * if (window.SignalWireUI?.ready) {\n * // Library already loaded, use it directly\n * initApp();\n * } else {\n * window.addEventListener('signalwire:web-components:ready', () => initApp());\n * }\n * ```\n */\nconst emitReadyEvent = (): void => {\n if (typeof window !== 'undefined') {\n const event = new CustomEvent('signalwire:web-components:ready', {\n detail: { version: __VERSION__ }\n });\n window.dispatchEvent(event);\n }\n};\n\nemitReadyEvent();\n"],"names":["version","ready","emitReadyEvent","event"],"mappings":";;;;;;;;;;;;;;;AAsCO,MAAMA,IAAkB,cAKlBC,IAAiB,IAexBC,IAAiB,MAAY;AACjC,MAAI,OAAO,SAAW,KAAa;AACjC,UAAMC,IAAQ,IAAI,YAAY,mCAAmC;AAAA,MAC/D,QAAQ,EAAE,SAAS,aAAA;AAAA,IAAY,CAChC;AACD,WAAO,cAAcA,CAAK;AAAA,EAC5B;AACF;AAEAD,EAAA;"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * @signalwire/web-components\n * UI Components Library built with Lit\n */\n\n// Export components\nexport { ExampleButton } from './components/example-button.js';\nexport { CallMedia } from './components/call-media.js';\nexport { Participants } from './components/participants.js';\nexport { SelfMedia } from './components/self-media.js';\nexport { AudioLevel } from './components/audio-level.js';\nexport { DeviceSelector } from './components/device-selector.js';\nexport { CallControls } from './components/call-controls.js';\nexport { CallStatusComponent } from './components/call-status.js';\nexport { DialpadComponent } from './components/dialpad.js';\nexport { ClickToCallComponent } from './components/click-to-call.js';\nexport { DirectoryComponent } from './components/directory.js';\nexport { ParticipantControlsComponent } from './components/participant-controls.js';\n\n// Export types (re-exported from core)\nexport type { Call, CallSelf, DeviceController, LayoutLayer, Participant } from './types/index.js';\n\n// Export context\nexport * from './context/index.js';\n\n// Re-export Lit utilities for convenience\nexport { html, css, LitElement } from 'lit';\nexport type { TemplateResult, CSSResult } from 'lit';\n\n// ============================================================================\n// Library Ready Event (for async/dynamic script loading)\n// ============================================================================\n\ndeclare const __VERSION__: string;\n\n/**\n * Library version from package.json, injected at build time.\n */\nexport const version: string = __VERSION__;\n\n/**\n * Flag indicating the library has been loaded and is ready to use.\n */\nexport const ready: boolean = true;\n\n/**\n * Emits 'signalwire:web-components:ready' event when the library is loaded.\n *\n * Scripts that might load BEFORE the library (check flag first):\n * ```js\n * if (window.SignalWireUI?.ready) {\n * // Library already loaded, use it directly\n * initApp();\n * } else {\n * window.addEventListener('signalwire:web-components:ready', () => initApp());\n * }\n * ```\n */\nconst emitReadyEvent = (): void => {\n if (typeof window !== 'undefined') {\n const event = new CustomEvent('signalwire:web-components:ready', {\n detail: { version: __VERSION__ }\n });\n window.dispatchEvent(event);\n }\n};\n\nemitReadyEvent();\n"],"names":["version","ready","emitReadyEvent","event"],"mappings":";;;;;;;;;;;;;;AAsCO,MAAMA,IAAkB,cAKlBC,IAAiB,IAexBC,IAAiB,MAAY;AACjC,MAAI,OAAO,SAAW,KAAa;AACjC,UAAMC,IAAQ,IAAI,YAAY,mCAAmC;AAAA,MAC/D,QAAQ,EAAE,SAAS,aAAA;AAAA,IAAY,CAChC;AACD,WAAO,cAAcA,CAAK;AAAA,EAC5B;AACF;AAEAD,EAAA;"}
@@ -5,8 +5,8 @@
5
5
  * Other types are defined locally for web-component specific needs.
6
6
  */
7
7
  import type { Observable } from 'rxjs';
8
- import type { Call, LayoutLayer } from '@signalwire/js';
9
- export type { Call, LayoutLayer };
8
+ import type { Call, DeviceController, LayoutLayer } from '@signalwire/js';
9
+ export type { Call, DeviceController, LayoutLayer };
10
10
  /**
11
11
  * Type helper for accessing call.self with proper typing
12
12
  * The SDK's Call.self is typed as unknown for flexibility
@@ -41,27 +41,4 @@ export interface Participant {
41
41
  unmuteVideo?(): Promise<void>;
42
42
  remove?(): Promise<void>;
43
43
  }
44
- /**
45
- * Device info interface matching MediaDeviceInfo structure
46
- */
47
- export interface DeviceInfo {
48
- deviceId: string;
49
- label: string;
50
- kind: 'audioinput' | 'audiooutput' | 'videoinput';
51
- }
52
- /**
53
- * DeviceController interface for observing device lists
54
- */
55
- export interface DeviceController {
56
- audioInputDevices$: Observable<DeviceInfo[]>;
57
- videoInputDevices$: Observable<DeviceInfo[]>;
58
- audioOutputDevices$: Observable<DeviceInfo[]>;
59
- selectedAudioInputDevice$?: Observable<DeviceInfo | null>;
60
- selectedVideoInputDevice$?: Observable<DeviceInfo | null>;
61
- selectedAudioOutputDevice$?: Observable<DeviceInfo | null>;
62
- selectAudioInputDevice?: (device: DeviceInfo) => void;
63
- selectVideoInputDevice?: (device: DeviceInfo) => void;
64
- selectAudioOutputDevice?: (device: DeviceInfo) => void;
65
- getLocalStream?: () => Promise<MediaStream>;
66
- }
67
44
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGxD,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAElC;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE,CAEvE;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,GAAG,aAAa,GAAG,YAAY,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;IAC7C,kBAAkB,EAAE,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;IAC7C,mBAAmB,EAAE,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9C,yBAAyB,CAAC,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC1D,yBAAyB,CAAC,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC1D,0BAA0B,CAAC,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC3D,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtD,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtD,uBAAuB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACvD,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CAC7C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG1E,YAAY,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC;AAEpD;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE,CAEvE;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/types/index.ts"],"sourcesContent":["/**\n * Type definitions for call-media components.\n *\n * Call and LayoutLayer types are imported from the SDK.\n * Other types are defined locally for web-component specific needs.\n */\n\nimport type { Observable } from 'rxjs';\nimport type { Call, LayoutLayer } from '@signalwire/js';\n\n// Re-export SDK types for internal use\nexport type { Call, LayoutLayer };\n\n/**\n * Type helper for accessing call.self with proper typing\n * The SDK's Call.self is typed as unknown for flexibility\n */\nexport interface CallSelf {\n id: string;\n}\n\n/**\n * Helper to safely get self ID from a Call\n */\nexport function getSelfId(call: Call | undefined): string | undefined {\n const self = call?.self as CallSelf | undefined;\n return self?.id;\n}\n\n/**\n * Helper to cast participants from unknown[] to Participant[]\n * The SDK uses unknown[] for flexibility, but web-components knows the shape\n */\nexport function castParticipants(participants: unknown[]): Participant[] {\n return participants as Participant[];\n}\n\n/**\n * Participant interface for call participants\n * Web-component specific with optional methods\n */\nexport interface Participant {\n id: string;\n name?: string;\n name$?: Observable<string>;\n audioMuted?: boolean;\n audioMuted$?: Observable<boolean>;\n videoMuted?: boolean;\n videoMuted$?: Observable<boolean>;\n mute?(): Promise<void>;\n unmute?(): Promise<void>;\n muteVideo?(): Promise<void>;\n unmuteVideo?(): Promise<void>;\n remove?(): Promise<void>;\n}\n\n/**\n * Device info interface matching MediaDeviceInfo structure\n */\nexport interface DeviceInfo {\n deviceId: string;\n label: string;\n kind: 'audioinput' | 'audiooutput' | 'videoinput';\n}\n\n/**\n * DeviceController interface for observing device lists\n */\nexport interface DeviceController {\n audioInputDevices$: Observable<DeviceInfo[]>;\n videoInputDevices$: Observable<DeviceInfo[]>;\n audioOutputDevices$: Observable<DeviceInfo[]>;\n selectedAudioInputDevice$?: Observable<DeviceInfo | null>;\n selectedVideoInputDevice$?: Observable<DeviceInfo | null>;\n selectedAudioOutputDevice$?: Observable<DeviceInfo | null>;\n selectAudioInputDevice?: (device: DeviceInfo) => void;\n selectVideoInputDevice?: (device: DeviceInfo) => void;\n selectAudioOutputDevice?: (device: DeviceInfo) => void;\n getLocalStream?: () => Promise<MediaStream>;\n}\n"],"names":["getSelfId","call","self","castParticipants","participants"],"mappings":"AAwBO,SAASA,EAAUC,GAA4C;AACpE,QAAMC,IAAOD,KAAA,gBAAAA,EAAM;AACnB,SAAOC,KAAA,gBAAAA,EAAM;AACf;AAMO,SAASC,EAAiBC,GAAwC;AACvE,SAAOA;AACT;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/types/index.ts"],"sourcesContent":["/**\n * Type definitions for call-media components.\n *\n * Call and LayoutLayer types are imported from the SDK.\n * Other types are defined locally for web-component specific needs.\n */\n\nimport type { Observable } from 'rxjs';\nimport type { Call, DeviceController, LayoutLayer } from '@signalwire/js';\n\n// Re-export SDK types for internal use\nexport type { Call, DeviceController, LayoutLayer };\n\n/**\n * Type helper for accessing call.self with proper typing\n * The SDK's Call.self is typed as unknown for flexibility\n */\nexport interface CallSelf {\n id: string;\n}\n\n/**\n * Helper to safely get self ID from a Call\n */\nexport function getSelfId(call: Call | undefined): string | undefined {\n const self = call?.self as CallSelf | undefined;\n return self?.id;\n}\n\n/**\n * Helper to cast participants from unknown[] to Participant[]\n * The SDK uses unknown[] for flexibility, but web-components knows the shape\n */\nexport function castParticipants(participants: unknown[]): Participant[] {\n return participants as Participant[];\n}\n\n/**\n * Participant interface for call participants\n * Web-component specific with optional methods\n */\nexport interface Participant {\n id: string;\n name?: string;\n name$?: Observable<string>;\n audioMuted?: boolean;\n audioMuted$?: Observable<boolean>;\n videoMuted?: boolean;\n videoMuted$?: Observable<boolean>;\n mute?(): Promise<void>;\n unmute?(): Promise<void>;\n muteVideo?(): Promise<void>;\n unmuteVideo?(): Promise<void>;\n remove?(): Promise<void>;\n}\n\n"],"names":["getSelfId","call","self","castParticipants","participants"],"mappings":"AAwBO,SAASA,EAAUC,GAA4C;AACpE,QAAMC,IAAOD,KAAA,gBAAAA,EAAM;AACnB,SAAOC,KAAA,gBAAAA,EAAM;AACf;AAMO,SAASC,EAAiBC,GAAwC;AACvE,SAAOA;AACT;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalwire/web-components",
3
- "version": "1.0.0-dev-20260311213302",
3
+ "version": "1.0.0-dev-20260318132643",
4
4
  "description": "UI components library built with Lit",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -115,7 +115,7 @@
115
115
  "rxjs": "^7.8.2"
116
116
  },
117
117
  "peerDependencies": {
118
- "@signalwire/js": "4.0.0-dev-20260311213302"
118
+ "@signalwire/js": "4.0.0-dev-20260318132643"
119
119
  },
120
120
  "devDependencies": {
121
121
  "@playwright/test": "^1.56.1",