@signalwire/web-components 4.0.0-beta.3 → 4.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +3 -1
  2. package/dist/components/audio-level.d.ts +106 -0
  3. package/dist/components/audio-level.d.ts.map +1 -0
  4. package/dist/components/audio-level.js +203 -0
  5. package/dist/components/audio-level.js.map +1 -0
  6. package/dist/components/call-controls.d.ts +163 -0
  7. package/dist/components/call-controls.d.ts.map +1 -0
  8. package/dist/components/call-controls.js +606 -0
  9. package/dist/components/call-controls.js.map +1 -0
  10. package/dist/components/call-media.d.ts +114 -0
  11. package/dist/components/call-media.d.ts.map +1 -0
  12. package/dist/components/call-media.js +215 -0
  13. package/dist/components/call-media.js.map +1 -0
  14. package/dist/components/call-status.d.ts +71 -0
  15. package/dist/components/call-status.d.ts.map +1 -0
  16. package/dist/components/call-status.js +251 -0
  17. package/dist/components/call-status.js.map +1 -0
  18. package/dist/components/click-to-call.d.ts +123 -0
  19. package/dist/components/click-to-call.d.ts.map +1 -0
  20. package/dist/components/click-to-call.js +428 -0
  21. package/dist/components/click-to-call.js.map +1 -0
  22. package/dist/components/device-selector.d.ts +250 -0
  23. package/dist/components/device-selector.d.ts.map +1 -0
  24. package/dist/components/device-selector.js +685 -0
  25. package/dist/components/device-selector.js.map +1 -0
  26. package/dist/components/dialpad.d.ts +60 -0
  27. package/dist/components/dialpad.d.ts.map +1 -0
  28. package/dist/components/dialpad.js +372 -0
  29. package/dist/components/dialpad.js.map +1 -0
  30. package/dist/components/directory.d.ts +103 -0
  31. package/dist/components/directory.d.ts.map +1 -0
  32. package/dist/components/directory.js +503 -0
  33. package/dist/components/directory.js.map +1 -0
  34. package/dist/components/example-button.d.ts +20 -0
  35. package/dist/components/example-button.d.ts.map +1 -0
  36. package/dist/components/example-button.js +74 -0
  37. package/dist/components/example-button.js.map +1 -0
  38. package/dist/components/participant-controls.d.ts +94 -0
  39. package/dist/components/participant-controls.d.ts.map +1 -0
  40. package/dist/components/participant-controls.js +468 -0
  41. package/dist/components/participant-controls.js.map +1 -0
  42. package/dist/components/participants.d.ts +116 -0
  43. package/dist/components/participants.d.ts.map +1 -0
  44. package/dist/components/participants.js +394 -0
  45. package/dist/components/participants.js.map +1 -0
  46. package/dist/components/self-media.d.ts +78 -0
  47. package/dist/components/self-media.d.ts.map +1 -0
  48. package/dist/components/self-media.js +128 -0
  49. package/dist/components/self-media.js.map +1 -0
  50. package/dist/context/call-context.d.ts +13 -0
  51. package/dist/context/call-context.d.ts.map +1 -0
  52. package/dist/context/call-context.js +6 -0
  53. package/dist/context/call-context.js.map +1 -0
  54. package/dist/context/index.d.ts +2 -0
  55. package/dist/context/index.d.ts.map +1 -0
  56. package/dist/index.d.ts +29 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +39 -5645
  59. package/dist/index.js.map +1 -1
  60. package/dist/react.d.ts +101 -0
  61. package/dist/types/index.d.ts +67 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/types/index.js +12 -0
  64. package/dist/types/index.js.map +1 -0
  65. package/dist/utils/debounce.d.ts +10 -0
  66. package/dist/utils/debounce.d.ts.map +1 -0
  67. package/dist/utils/debounce.js +13 -0
  68. package/dist/utils/debounce.js.map +1 -0
  69. package/dist/utils/index.d.ts +3 -0
  70. package/dist/utils/index.d.ts.map +1 -0
  71. package/dist/utils/video.d.ts +34 -0
  72. package/dist/utils/video.d.ts.map +1 -0
  73. package/dist/utils/video.js +26 -0
  74. package/dist/utils/video.js.map +1 -0
  75. package/package.json +70 -3
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Call Media Component
3
+ *
4
+ * Root component that renders remote video stream and provides call context
5
+ * to child components. Manages aspect ratio with ResizeObserver and handles
6
+ * video stream lifecycle.
7
+ *
8
+ * @example
9
+ * ```html
10
+ * <call-media .call=${call}>
11
+ * <participants>
12
+ * <self-media mirror=${true}></self-media>
13
+ * </participants>
14
+ * </call-media>
15
+ * ```
16
+ */
17
+ import { LitElement } from 'lit';
18
+ import type { Call } from '../types/index.js';
19
+ export declare class CallMedia extends LitElement {
20
+ static styles: import("lit").CSSResult;
21
+ /**
22
+ * Call object with observable streams and properties
23
+ */
24
+ call?: Call;
25
+ /**
26
+ * Provides call context to child components
27
+ * Note: Used by @provide decorator, TypeScript doesn't see the usage
28
+ */
29
+ private _providedCall?;
30
+ /**
31
+ * Current remote stream value from observable
32
+ */
33
+ private _remoteStreamValue;
34
+ /**
35
+ * RxJS subscriptions for cleanup
36
+ */
37
+ private subscriptions;
38
+ /**
39
+ * ResizeObserver instance for aspect ratio management
40
+ */
41
+ private resizeObserver?;
42
+ /**
43
+ * Video resize event handler reference for cleanup
44
+ */
45
+ private videoResizeHandler?;
46
+ /**
47
+ * Window resize event handler reference for cleanup
48
+ */
49
+ private windowResizeHandler?;
50
+ /**
51
+ * Lifecycle: Component connected to DOM
52
+ */
53
+ connectedCallback(): void;
54
+ /**
55
+ * Lifecycle: React to property changes
56
+ */
57
+ protected updated(changedProperties: Map<string, unknown>): void;
58
+ /**
59
+ * Lifecycle: Component disconnected from DOM
60
+ */
61
+ disconnectedCallback(): void;
62
+ /**
63
+ * Lifecycle: First update after render
64
+ */
65
+ protected firstUpdated(): void;
66
+ /**
67
+ * Subscribe to call observables
68
+ */
69
+ private setupSubscriptions;
70
+ /**
71
+ * Cleanup all subscriptions
72
+ */
73
+ private cleanupSubscriptions;
74
+ /**
75
+ * Setup ResizeObserver for aspect ratio management
76
+ */
77
+ private setupResizeObserver;
78
+ /**
79
+ * Video element reference for dimension calculations
80
+ */
81
+ private _videoElement?;
82
+ /**
83
+ * Padding wrapper reference for dimension calculations
84
+ */
85
+ private _paddingWrapper?;
86
+ /**
87
+ * Recalculate and apply dimensions based on viewport, container, and video sizes.
88
+ * Video should never grow bigger than the visible area.
89
+ * When container bleeds viewport, scale proportionally to maintain container's aspect ratio.
90
+ * Uses "contain" fitting algorithm - compares aspect ratios to determine constraint.
91
+ */
92
+ private recalculateDimensions;
93
+ /**
94
+ * Cleanup ResizeObserver and event listeners
95
+ */
96
+ private cleanupResizeObserver;
97
+ /**
98
+ * Cleanup video element
99
+ */
100
+ private cleanupVideoElement;
101
+ /**
102
+ * Render the component
103
+ */
104
+ render(): import("lit-html").TemplateResult<1>;
105
+ }
106
+ /**
107
+ * Declare global type for TypeScript
108
+ */
109
+ declare global {
110
+ interface HTMLElementTagNameMap {
111
+ 'sw-call-media': CallMedia;
112
+ }
113
+ }
114
+ //# sourceMappingURL=call-media.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-media.d.ts","sourceRoot":"","sources":["../../src/components/call-media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAI5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAK9C,qBACa,SAAU,SAAQ,UAAU;IACvC,MAAM,CAAC,MAAM,0BA4DX;IAEF;;OAEG;IACyB,IAAI,CAAC,EAAE,IAAI,CAAC;IAExC;;;OAGG;IAGH,OAAO,CAAC,aAAa,CAAC,CAAO;IAE7B;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAA4B;IAEtD;;OAEG;IACH,OAAO,CAAC,aAAa,CAAsB;IAE3C;;OAEG;IACH,OAAO,CAAC,cAAc,CAAC,CAAiB;IAExC;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAC,CAAa;IAExC;;OAEG;IACH,OAAO,CAAC,mBAAmB,CAAC,CAAa;IAEzC;;OAEG;IACH,iBAAiB;IAMjB;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAYhE;;OAEG;IACH,oBAAoB;IAOpB;;OAEG;IACH,SAAS,CAAC,YAAY,IAAI,IAAI;IAS9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAK5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwC3B;;OAEG;IACH,OAAO,CAAC,aAAa,CAAC,CAAmB;IAEzC;;OAEG;IACH,OAAO,CAAC,eAAe,CAAC,CAAiB;IAEzC;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAgF7B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAkB7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;OAEG;IACH,MAAM;CAqBP;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,eAAe,EAAE,SAAS,CAAC;KAC5B;CACF"}
@@ -0,0 +1,215 @@
1
+ import { LitElement as E, html as M, css as q } from "lit";
2
+ import { property as D, customElement as j } from "lit/decorators.js";
3
+ import { provide as L } from "@lit/context";
4
+ import { callContext as V } from "../context/call-context.js";
5
+ import { debounce as $ } from "../utils/debounce.js";
6
+ import { waitForVideoReady as k, attachMediaStream as P, detachMediaStream as X } from "../utils/video.js";
7
+ var Y = Object.defineProperty, A = Object.getOwnPropertyDescriptor, u = (e, t, s, o) => {
8
+ for (var i = o > 1 ? void 0 : o ? A(t, s) : t, r = e.length - 1, n; r >= 0; r--)
9
+ (n = e[r]) && (i = (o ? n(t, s, i) : n(i)) || i);
10
+ return o && i && Y(t, s, i), i;
11
+ };
12
+ let a = class extends E {
13
+ constructor() {
14
+ super(...arguments), this._remoteStreamValue = null, this.subscriptions = [];
15
+ }
16
+ /**
17
+ * Lifecycle: Component connected to DOM
18
+ */
19
+ connectedCallback() {
20
+ super.connectedCallback(), this._providedCall = this.call, this.setupSubscriptions();
21
+ }
22
+ /**
23
+ * Lifecycle: React to property changes
24
+ */
25
+ updated(e) {
26
+ super.updated(e), e.has("call") && (this.cleanupSubscriptions(), this._providedCall = this.call, this.setupSubscriptions());
27
+ }
28
+ /**
29
+ * Lifecycle: Component disconnected from DOM
30
+ */
31
+ disconnectedCallback() {
32
+ super.disconnectedCallback(), this.cleanupSubscriptions(), this.cleanupResizeObserver(), this.cleanupVideoElement();
33
+ }
34
+ /**
35
+ * Lifecycle: First update after render
36
+ */
37
+ firstUpdated() {
38
+ var t;
39
+ const e = (t = this.shadowRoot) == null ? void 0 : t.querySelector("video.mcu-video");
40
+ e && k(e).then(() => {
41
+ this.setupResizeObserver();
42
+ });
43
+ }
44
+ /**
45
+ * Subscribe to call observables
46
+ */
47
+ setupSubscriptions() {
48
+ this.call && this.subscriptions.push(
49
+ this.call.remoteStream$.subscribe((e) => {
50
+ var s;
51
+ this._remoteStreamValue = e, this.requestUpdate();
52
+ const t = (s = this.shadowRoot) == null ? void 0 : s.querySelector("video.mcu-video");
53
+ t && P(t, e);
54
+ })
55
+ );
56
+ }
57
+ /**
58
+ * Cleanup all subscriptions
59
+ */
60
+ cleanupSubscriptions() {
61
+ this.subscriptions.forEach((e) => e.unsubscribe()), this.subscriptions = [];
62
+ }
63
+ /**
64
+ * Setup ResizeObserver for aspect ratio management
65
+ */
66
+ setupResizeObserver() {
67
+ var s, o;
68
+ const e = (s = this.shadowRoot) == null ? void 0 : s.querySelector("video.mcu-video"), t = (o = this.shadowRoot) == null ? void 0 : o.querySelector(".padding-wrapper");
69
+ !e || !t || (this._videoElement = e, this._paddingWrapper = t, this.resizeObserver = new ResizeObserver(
70
+ $(() => {
71
+ this.recalculateDimensions();
72
+ }, 50)
73
+ ), this.resizeObserver.observe(this), this.videoResizeHandler = () => {
74
+ this.recalculateDimensions();
75
+ }, e.addEventListener("resize", this.videoResizeHandler), this.windowResizeHandler = () => {
76
+ requestAnimationFrame(() => {
77
+ this.recalculateDimensions();
78
+ });
79
+ }, window.addEventListener("resize", this.windowResizeHandler), this.recalculateDimensions());
80
+ }
81
+ /**
82
+ * Recalculate and apply dimensions based on viewport, container, and video sizes.
83
+ * Video should never grow bigger than the visible area.
84
+ * When container bleeds viewport, scale proportionally to maintain container's aspect ratio.
85
+ * Uses "contain" fitting algorithm - compares aspect ratios to determine constraint.
86
+ */
87
+ recalculateDimensions() {
88
+ const e = this._videoElement, t = this._paddingWrapper;
89
+ if (!e || !t || !e.videoWidth || !e.videoHeight) return;
90
+ const s = window.innerWidth, o = window.innerHeight, i = this.getBoundingClientRect(), r = i.width, n = i.height;
91
+ if (r <= 0 || n <= 0) return;
92
+ const m = Math.min(1, (s - i.left) / r), b = Math.min(1, (o - i.top) / n), v = Math.min(m, b), l = r * v, h = n * v;
93
+ if (l <= 0 || h <= 0) return;
94
+ const w = e.videoWidth, f = e.videoHeight, p = w / f, g = l / h;
95
+ let d, c;
96
+ p > g ? (d = l, c = d / p) : (c = h, d = c * p);
97
+ const R = Math.max(0, i.left), y = Math.max(0, i.top), z = Math.min(s, i.right), S = Math.min(o, i.bottom), H = (R + z) / 2, C = (y + S) / 2, x = i.left + r / 2, O = i.top + n / 2, _ = H - x, W = C - O;
98
+ t.style.width = `${d}px`, t.style.height = `${c}px`, t.style.paddingBottom = "0", t.style.transform = `translate(${_}px, ${W}px)`;
99
+ }
100
+ /**
101
+ * Cleanup ResizeObserver and event listeners
102
+ */
103
+ cleanupResizeObserver() {
104
+ var t;
105
+ this.resizeObserver && (this.resizeObserver.disconnect(), this.resizeObserver = void 0);
106
+ const e = (t = this.shadowRoot) == null ? void 0 : t.querySelector("video.mcu-video");
107
+ e && this.videoResizeHandler && (e.removeEventListener("resize", this.videoResizeHandler), this.videoResizeHandler = void 0), this.windowResizeHandler && (window.removeEventListener("resize", this.windowResizeHandler), this.windowResizeHandler = void 0);
108
+ }
109
+ /**
110
+ * Cleanup video element
111
+ */
112
+ cleanupVideoElement() {
113
+ var t;
114
+ const e = (t = this.shadowRoot) == null ? void 0 : t.querySelector("video.mcu-video");
115
+ e && X(e);
116
+ }
117
+ /**
118
+ * Render the component
119
+ */
120
+ render() {
121
+ return M`
122
+ <div class="mcu-content" part="container">
123
+ <div class="padding-wrapper">
124
+ <div class="mcu-wrapper">
125
+ <video
126
+ class="mcu-video"
127
+ part="video"
128
+ autoplay
129
+ playsinline
130
+ muted
131
+ .srcObject=${this._remoteStreamValue}
132
+ ></video>
133
+ </div>
134
+ <div class="mcu-layers">
135
+ <slot></slot>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ `;
140
+ }
141
+ };
142
+ a.styles = q`
143
+ :host {
144
+ /* CSS Custom Properties for theming */
145
+ --sw-color-primary: #044cf6;
146
+ --sw-color-background: #000000;
147
+ --sw-border-radius: 0px;
148
+
149
+ display: block;
150
+ width: 100%;
151
+ height: 100%;
152
+ overflow: hidden;
153
+ }
154
+
155
+ .mcu-content {
156
+ position: relative;
157
+ width: 100%;
158
+ height: 100%;
159
+ margin: 0 auto;
160
+ display: flex;
161
+ align-items: center;
162
+ justify-content: center;
163
+ background-color: var(--sw-color-background);
164
+ border-radius: var(--sw-border-radius);
165
+ overflow: hidden;
166
+ }
167
+
168
+ .padding-wrapper {
169
+ position: relative;
170
+ max-width: 100%;
171
+ max-height: 100%;
172
+ transition:
173
+ width 0.3s ease,
174
+ height 0.3s ease;
175
+ }
176
+
177
+ .mcu-wrapper {
178
+ position: absolute;
179
+ top: 0;
180
+ left: 0;
181
+ right: 0;
182
+ bottom: 0;
183
+ border-radius: var(--sw-border-radius);
184
+ overflow: hidden;
185
+ }
186
+
187
+ .mcu-video {
188
+ width: 100%;
189
+ height: 100%;
190
+ display: block;
191
+ object-fit: contain;
192
+ }
193
+
194
+ .mcu-layers {
195
+ position: absolute;
196
+ top: 0;
197
+ left: 0;
198
+ width: 100%;
199
+ height: 100%;
200
+ pointer-events: none;
201
+ }
202
+ `;
203
+ u([
204
+ D({ type: Object })
205
+ ], a.prototype, "call", 2);
206
+ u([
207
+ L({ context: V })
208
+ ], a.prototype, "_providedCall", 2);
209
+ a = u([
210
+ j("sw-call-media")
211
+ ], a);
212
+ export {
213
+ a as CallMedia
214
+ };
215
+ //# sourceMappingURL=call-media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-media.js","sources":["../../src/components/call-media.ts"],"sourcesContent":["/**\n * Call Media Component\n *\n * Root component that renders remote video stream and provides call context\n * to child components. Manages aspect ratio with ResizeObserver and handles\n * video stream lifecycle.\n *\n * @example\n * ```html\n * <call-media .call=${call}>\n * <participants>\n * <self-media mirror=${true}></self-media>\n * </participants>\n * </call-media>\n * ```\n */\n\nimport { LitElement, html, css } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { provide } from '@lit/context';\nimport { Subscription } from 'rxjs';\nimport type { Call } from '../types/index.js';\nimport { callContext } from '../context/call-context.js';\nimport { debounce } from '../utils/debounce.js';\nimport { waitForVideoReady, attachMediaStream, detachMediaStream } from '../utils/video.js';\n\n@customElement('sw-call-media')\nexport class CallMedia extends LitElement {\n static styles = css`\n :host {\n /* CSS Custom Properties for theming */\n --sw-color-primary: #044cf6;\n --sw-color-background: #000000;\n --sw-border-radius: 0px;\n\n display: block;\n width: 100%;\n height: 100%;\n overflow: hidden;\n }\n\n .mcu-content {\n position: relative;\n width: 100%;\n height: 100%;\n margin: 0 auto;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: var(--sw-color-background);\n border-radius: var(--sw-border-radius);\n overflow: hidden;\n }\n\n .padding-wrapper {\n position: relative;\n max-width: 100%;\n max-height: 100%;\n transition:\n width 0.3s ease,\n height 0.3s ease;\n }\n\n .mcu-wrapper {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n border-radius: var(--sw-border-radius);\n overflow: hidden;\n }\n\n .mcu-video {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: contain;\n }\n\n .mcu-layers {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n }\n `;\n\n /**\n * Call object with observable streams and properties\n */\n @property({ type: Object }) call?: Call;\n\n /**\n * Provides call context to child components\n * Note: Used by @provide decorator, TypeScript doesn't see the usage\n */\n @provide({ context: callContext })\n // @ts-expect-error - Used by @provide decorator\n private _providedCall?: Call;\n\n /**\n * Current remote stream value from observable\n */\n private _remoteStreamValue: MediaStream | null = null;\n\n /**\n * RxJS subscriptions for cleanup\n */\n private subscriptions: Subscription[] = [];\n\n /**\n * ResizeObserver instance for aspect ratio management\n */\n private resizeObserver?: ResizeObserver;\n\n /**\n * Video resize event handler reference for cleanup\n */\n private videoResizeHandler?: () => void;\n\n /**\n * Window resize event handler reference for cleanup\n */\n private windowResizeHandler?: () => void;\n\n /**\n * Lifecycle: Component connected to DOM\n */\n connectedCallback() {\n super.connectedCallback();\n this._providedCall = this.call;\n this.setupSubscriptions();\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('call')) {\n // Clean up old subscriptions first\n this.cleanupSubscriptions();\n // Update context for child components\n this._providedCall = this.call;\n // Set up new subscriptions\n this.setupSubscriptions();\n }\n }\n\n /**\n * Lifecycle: Component disconnected from DOM\n */\n disconnectedCallback() {\n super.disconnectedCallback();\n this.cleanupSubscriptions();\n this.cleanupResizeObserver();\n this.cleanupVideoElement();\n }\n\n /**\n * Lifecycle: First update after render\n */\n protected firstUpdated(): void {\n const video = this.shadowRoot?.querySelector('video.mcu-video') as HTMLVideoElement;\n if (video) {\n waitForVideoReady(video).then(() => {\n this.setupResizeObserver();\n });\n }\n }\n\n /**\n * Subscribe to call observables\n */\n private setupSubscriptions(): void {\n if (!this.call) return;\n\n // Subscribe to remote stream\n this.subscriptions.push(\n this.call.remoteStream$.subscribe((stream: MediaStream | null) => {\n this._remoteStreamValue = stream;\n this.requestUpdate();\n\n // Attach stream to video element\n const video = this.shadowRoot?.querySelector('video.mcu-video') as HTMLVideoElement;\n if (video) {\n attachMediaStream(video, stream);\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 * Setup ResizeObserver for aspect ratio management\n */\n private setupResizeObserver(): void {\n const video = this.shadowRoot?.querySelector('video.mcu-video') as HTMLVideoElement;\n const paddingWrapper = this.shadowRoot?.querySelector('.padding-wrapper') as HTMLDivElement;\n\n if (!video || !paddingWrapper) return;\n\n // Store references for the update function\n this._videoElement = video;\n this._paddingWrapper = paddingWrapper;\n\n // Observe the host element for container size changes\n this.resizeObserver = new ResizeObserver(\n debounce(() => {\n this.recalculateDimensions();\n }, 50)\n );\n\n this.resizeObserver.observe(this);\n\n // Listen for video intrinsic dimension changes (when media orientation flips)\n this.videoResizeHandler = () => {\n this.recalculateDimensions();\n };\n\n video.addEventListener('resize', this.videoResizeHandler);\n\n // Listen for window/viewport resize changes\n // Use requestAnimationFrame to ensure layout has settled before reading dimensions\n this.windowResizeHandler = () => {\n requestAnimationFrame(() => {\n this.recalculateDimensions();\n });\n };\n\n window.addEventListener('resize', this.windowResizeHandler);\n\n // Initial calculation\n this.recalculateDimensions();\n }\n\n /**\n * Video element reference for dimension calculations\n */\n private _videoElement?: HTMLVideoElement;\n\n /**\n * Padding wrapper reference for dimension calculations\n */\n private _paddingWrapper?: HTMLDivElement;\n\n /**\n * Recalculate and apply dimensions based on viewport, container, and video sizes.\n * Video should never grow bigger than the visible area.\n * When container bleeds viewport, scale proportionally to maintain container's aspect ratio.\n * Uses \"contain\" fitting algorithm - compares aspect ratios to determine constraint.\n */\n private recalculateDimensions(): void {\n const video = this._videoElement;\n const paddingWrapper = this._paddingWrapper;\n\n if (!video || !paddingWrapper) return;\n if (!video.videoWidth || !video.videoHeight) return;\n\n // Get viewport dimensions\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n // Get container's bounding rect (actual rendered position and size)\n const containerRect = this.getBoundingClientRect();\n const containerWidth = containerRect.width;\n const containerHeight = containerRect.height;\n\n if (containerWidth <= 0 || containerHeight <= 0) return;\n\n // Calculate scale factors for each dimension\n // This tells us how much the container would need to shrink to fit in viewport\n const scaleX = Math.min(1, (viewportWidth - containerRect.left) / containerWidth);\n const scaleY = Math.min(1, (viewportHeight - containerRect.top) / containerHeight);\n\n // Use the minimum scale to maintain proportionality\n // This ensures the container's aspect ratio is preserved when scaling down\n const scale = Math.min(scaleX, scaleY);\n\n // Calculate available space by applying scale to container dimensions\n const maxWidth = containerWidth * scale;\n const maxHeight = containerHeight * scale;\n\n if (maxWidth <= 0 || maxHeight <= 0) return;\n\n const videoWidth = video.videoWidth;\n const videoHeight = video.videoHeight;\n\n // Calculate aspect ratios\n const videoAspectRatio = videoWidth / videoHeight;\n const availableAspectRatio = maxWidth / maxHeight;\n\n let finalWidth: number;\n let finalHeight: number;\n\n // \"Contain\" algorithm: compare aspect ratios to determine which dimension constrains\n if (videoAspectRatio > availableAspectRatio) {\n // Video is wider than available space - constrain by width\n finalWidth = maxWidth;\n finalHeight = finalWidth / videoAspectRatio;\n } else {\n // Video is taller than available space - constrain by height\n finalHeight = maxHeight;\n finalWidth = finalHeight * videoAspectRatio;\n }\n\n // Calculate offset to center video in the visible area of the container\n // When container bleeds viewport, the visible center is different from container center\n const visibleLeft = Math.max(0, containerRect.left);\n const visibleTop = Math.max(0, containerRect.top);\n const visibleRight = Math.min(viewportWidth, containerRect.right);\n const visibleBottom = Math.min(viewportHeight, containerRect.bottom);\n\n // Center of the visible area (in viewport coordinates)\n const visibleCenterX = (visibleLeft + visibleRight) / 2;\n const visibleCenterY = (visibleTop + visibleBottom) / 2;\n\n // Center of the container (in viewport coordinates)\n const containerCenterX = containerRect.left + containerWidth / 2;\n const containerCenterY = containerRect.top + containerHeight / 2;\n\n // Offset needed to shift from container center to visible center\n const offsetX = visibleCenterX - containerCenterX;\n const offsetY = visibleCenterY - containerCenterY;\n\n // Apply the calculated dimensions and offset\n paddingWrapper.style.width = `${finalWidth}px`;\n paddingWrapper.style.height = `${finalHeight}px`;\n paddingWrapper.style.paddingBottom = '0';\n paddingWrapper.style.transform = `translate(${offsetX}px, ${offsetY}px)`;\n }\n\n /**\n * Cleanup ResizeObserver and event listeners\n */\n private cleanupResizeObserver(): void {\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = undefined;\n }\n\n const video = this.shadowRoot?.querySelector('video.mcu-video') as HTMLVideoElement;\n if (video && this.videoResizeHandler) {\n video.removeEventListener('resize', this.videoResizeHandler);\n this.videoResizeHandler = undefined;\n }\n\n if (this.windowResizeHandler) {\n window.removeEventListener('resize', this.windowResizeHandler);\n this.windowResizeHandler = undefined;\n }\n }\n\n /**\n * Cleanup video element\n */\n private cleanupVideoElement(): void {\n const video = this.shadowRoot?.querySelector('video.mcu-video') as HTMLVideoElement;\n if (video) {\n detachMediaStream(video);\n }\n }\n\n /**\n * Render the component\n */\n render() {\n return html`\n <div class=\"mcu-content\" part=\"container\">\n <div class=\"padding-wrapper\">\n <div class=\"mcu-wrapper\">\n <video\n class=\"mcu-video\"\n part=\"video\"\n autoplay\n playsinline\n muted\n .srcObject=${this._remoteStreamValue}\n ></video>\n </div>\n <div class=\"mcu-layers\">\n <slot></slot>\n </div>\n </div>\n </div>\n `;\n }\n}\n\n/**\n * Declare global type for TypeScript\n */\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-call-media': CallMedia;\n }\n}\n"],"names":["CallMedia","LitElement","changedProperties","video","_a","waitForVideoReady","stream","attachMediaStream","sub","paddingWrapper","_b","debounce","viewportWidth","viewportHeight","containerRect","containerWidth","containerHeight","scaleX","scaleY","scale","maxWidth","maxHeight","videoWidth","videoHeight","videoAspectRatio","availableAspectRatio","finalWidth","finalHeight","visibleLeft","visibleTop","visibleRight","visibleBottom","visibleCenterX","visibleCenterY","containerCenterX","containerCenterY","offsetX","offsetY","detachMediaStream","html","css","__decorateClass","property","provide","callContext","customElement"],"mappings":";;;;;;;;;;;AA2BO,IAAMA,IAAN,cAAwBC,EAAW;AAAA,EAAnC,cAAA;AAAA,UAAA,GAAA,SAAA,GA+EL,KAAQ,qBAAyC,MAKjD,KAAQ,gBAAgC,CAAA;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA,EAoBzC,oBAAoB;AAClB,UAAM,kBAAA,GACN,KAAK,gBAAgB,KAAK,MAC1B,KAAK,mBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKU,QAAQC,GAA+C;AAC/D,UAAM,QAAQA,CAAiB,GAC3BA,EAAkB,IAAI,MAAM,MAE9B,KAAK,qBAAA,GAEL,KAAK,gBAAgB,KAAK,MAE1B,KAAK,mBAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB;AACrB,UAAM,qBAAA,GACN,KAAK,qBAAA,GACL,KAAK,sBAAA,GACL,KAAK,oBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKU,eAAqB;;AAC7B,UAAMC,KAAQC,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAAc;AAC7C,IAAID,KACFE,EAAkBF,CAAK,EAAE,KAAK,MAAM;AAClC,WAAK,oBAAA;AAAA,IACP,CAAC;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAA2B;AACjC,IAAK,KAAK,QAGV,KAAK,cAAc;AAAA,MACjB,KAAK,KAAK,cAAc,UAAU,CAACG,MAA+B;;AAChE,aAAK,qBAAqBA,GAC1B,KAAK,cAAA;AAGL,cAAMH,KAAQC,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAAc;AAC7C,QAAID,KACFI,EAAkBJ,GAAOG,CAAM;AAAA,MAEnC,CAAC;AAAA,IAAA;AAAA,EAEL;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAA6B;AACnC,SAAK,cAAc,QAAQ,CAACE,MAAQA,EAAI,aAAa,GACrD,KAAK,gBAAgB,CAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAA4B;;AAClC,UAAML,KAAQC,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAAc,oBACvCK,KAAiBC,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAAc;AAEtD,IAAI,CAACP,KAAS,CAACM,MAGf,KAAK,gBAAgBN,GACrB,KAAK,kBAAkBM,GAGvB,KAAK,iBAAiB,IAAI;AAAA,MACxBE,EAAS,MAAM;AACb,aAAK,sBAAA;AAAA,MACP,GAAG,EAAE;AAAA,IAAA,GAGP,KAAK,eAAe,QAAQ,IAAI,GAGhC,KAAK,qBAAqB,MAAM;AAC9B,WAAK,sBAAA;AAAA,IACP,GAEAR,EAAM,iBAAiB,UAAU,KAAK,kBAAkB,GAIxD,KAAK,sBAAsB,MAAM;AAC/B,4BAAsB,MAAM;AAC1B,aAAK,sBAAA;AAAA,MACP,CAAC;AAAA,IACH,GAEA,OAAO,iBAAiB,UAAU,KAAK,mBAAmB,GAG1D,KAAK,sBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBQ,wBAA8B;AACpC,UAAMA,IAAQ,KAAK,eACbM,IAAiB,KAAK;AAG5B,QADI,CAACN,KAAS,CAACM,KACX,CAACN,EAAM,cAAc,CAACA,EAAM,YAAa;AAG7C,UAAMS,IAAgB,OAAO,YACvBC,IAAiB,OAAO,aAGxBC,IAAgB,KAAK,sBAAA,GACrBC,IAAiBD,EAAc,OAC/BE,IAAkBF,EAAc;AAEtC,QAAIC,KAAkB,KAAKC,KAAmB,EAAG;AAIjD,UAAMC,IAAS,KAAK,IAAI,IAAIL,IAAgBE,EAAc,QAAQC,CAAc,GAC1EG,IAAS,KAAK,IAAI,IAAIL,IAAiBC,EAAc,OAAOE,CAAe,GAI3EG,IAAQ,KAAK,IAAIF,GAAQC,CAAM,GAG/BE,IAAWL,IAAiBI,GAC5BE,IAAYL,IAAkBG;AAEpC,QAAIC,KAAY,KAAKC,KAAa,EAAG;AAErC,UAAMC,IAAanB,EAAM,YACnBoB,IAAcpB,EAAM,aAGpBqB,IAAmBF,IAAaC,GAChCE,IAAuBL,IAAWC;AAExC,QAAIK,GACAC;AAGJ,IAAIH,IAAmBC,KAErBC,IAAaN,GACbO,IAAcD,IAAaF,MAG3BG,IAAcN,GACdK,IAAaC,IAAcH;AAK7B,UAAMI,IAAc,KAAK,IAAI,GAAGd,EAAc,IAAI,GAC5Ce,IAAa,KAAK,IAAI,GAAGf,EAAc,GAAG,GAC1CgB,IAAe,KAAK,IAAIlB,GAAeE,EAAc,KAAK,GAC1DiB,IAAgB,KAAK,IAAIlB,GAAgBC,EAAc,MAAM,GAG7DkB,KAAkBJ,IAAcE,KAAgB,GAChDG,KAAkBJ,IAAaE,KAAiB,GAGhDG,IAAmBpB,EAAc,OAAOC,IAAiB,GACzDoB,IAAmBrB,EAAc,MAAME,IAAkB,GAGzDoB,IAAUJ,IAAiBE,GAC3BG,IAAUJ,IAAiBE;AAGjC,IAAA1B,EAAe,MAAM,QAAQ,GAAGiB,CAAU,MAC1CjB,EAAe,MAAM,SAAS,GAAGkB,CAAW,MAC5ClB,EAAe,MAAM,gBAAgB,KACrCA,EAAe,MAAM,YAAY,aAAa2B,CAAO,OAAOC,CAAO;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKQ,wBAA8B;;AACpC,IAAI,KAAK,mBACP,KAAK,eAAe,WAAA,GACpB,KAAK,iBAAiB;AAGxB,UAAMlC,KAAQC,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAAc;AAC7C,IAAID,KAAS,KAAK,uBAChBA,EAAM,oBAAoB,UAAU,KAAK,kBAAkB,GAC3D,KAAK,qBAAqB,SAGxB,KAAK,wBACP,OAAO,oBAAoB,UAAU,KAAK,mBAAmB,GAC7D,KAAK,sBAAsB;AAAA,EAE/B;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAA4B;;AAClC,UAAMA,KAAQC,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAAc;AAC7C,IAAID,KACFmC,EAAkBnC,CAAK;AAAA,EAE3B;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS;AACP,WAAOoC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAUgB,KAAK,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAShD;AACF;AAlXavC,EACJ,SAASwC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiEYC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAlEf1C,EAkEiB,WAAA,QAAA,CAAA;AAQpByC,EAAA;AAAA,EAFPE,EAAQ,EAAE,SAASC,EAAA,CAAa;AAAA,GAxEtB5C,EA0EH,WAAA,iBAAA,CAAA;AA1EGA,IAANyC,EAAA;AAAA,EADNI,EAAc,eAAe;AAAA,GACjB7C,CAAA;"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Call Status Component
3
+ *
4
+ * Displays current call state with status text and duration timer.
5
+ * Shows animated indicators for transient states (connecting, ringing, disconnecting).
6
+ *
7
+ * @example
8
+ * ```html
9
+ * <sw-call-status .call=${call}></sw-call-status>
10
+ * ```
11
+ */
12
+ import { LitElement } from 'lit';
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';
18
+ /**
19
+ * Call interface for status component
20
+ */
21
+ export interface CallStatusCall {
22
+ status$: Observable<CallStatus>;
23
+ }
24
+ export declare class CallStatusComponent extends LitElement {
25
+ static styles: import("lit").CSSResult;
26
+ /**
27
+ * Call object with status$ observable
28
+ */
29
+ call: CallStatusCall | null;
30
+ /**
31
+ * Call from context (if nested in sw-call-media)
32
+ */
33
+ private contextCall?;
34
+ /**
35
+ * Current call status
36
+ */
37
+ private status;
38
+ /**
39
+ * Call start time for duration calculation
40
+ */
41
+ private callStartTime;
42
+ /**
43
+ * Formatted duration string
44
+ */
45
+ private duration;
46
+ /**
47
+ * RxJS subscriptions for cleanup
48
+ */
49
+ private subscriptions;
50
+ /**
51
+ * Duration timer interval
52
+ */
53
+ private durationInterval;
54
+ connectedCallback(): void;
55
+ disconnectedCallback(): void;
56
+ updated(changedProperties: Map<string, unknown>): void;
57
+ private get activeCall();
58
+ private subscribeToCall;
59
+ private startDurationTimer;
60
+ private stopDurationTimer;
61
+ private formatDuration;
62
+ private cleanup;
63
+ private getStatusText;
64
+ render(): import("lit-html").TemplateResult<1>;
65
+ }
66
+ declare global {
67
+ interface HTMLElementTagNameMap {
68
+ 'sw-call-status': CallStatusComponent;
69
+ }
70
+ }
71
+ //# sourceMappingURL=call-status.d.ts.map
@@ -0,0 +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"}