@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.
- package/README.md +3 -1
- package/dist/components/audio-level.d.ts +106 -0
- package/dist/components/audio-level.d.ts.map +1 -0
- package/dist/components/audio-level.js +203 -0
- package/dist/components/audio-level.js.map +1 -0
- package/dist/components/call-controls.d.ts +163 -0
- package/dist/components/call-controls.d.ts.map +1 -0
- package/dist/components/call-controls.js +606 -0
- package/dist/components/call-controls.js.map +1 -0
- package/dist/components/call-media.d.ts +114 -0
- package/dist/components/call-media.d.ts.map +1 -0
- package/dist/components/call-media.js +215 -0
- package/dist/components/call-media.js.map +1 -0
- package/dist/components/call-status.d.ts +71 -0
- package/dist/components/call-status.d.ts.map +1 -0
- package/dist/components/call-status.js +251 -0
- package/dist/components/call-status.js.map +1 -0
- package/dist/components/click-to-call.d.ts +123 -0
- package/dist/components/click-to-call.d.ts.map +1 -0
- package/dist/components/click-to-call.js +428 -0
- package/dist/components/click-to-call.js.map +1 -0
- package/dist/components/device-selector.d.ts +250 -0
- package/dist/components/device-selector.d.ts.map +1 -0
- package/dist/components/device-selector.js +685 -0
- package/dist/components/device-selector.js.map +1 -0
- package/dist/components/dialpad.d.ts +60 -0
- package/dist/components/dialpad.d.ts.map +1 -0
- package/dist/components/dialpad.js +372 -0
- package/dist/components/dialpad.js.map +1 -0
- package/dist/components/directory.d.ts +103 -0
- package/dist/components/directory.d.ts.map +1 -0
- package/dist/components/directory.js +503 -0
- package/dist/components/directory.js.map +1 -0
- package/dist/components/example-button.d.ts +20 -0
- package/dist/components/example-button.d.ts.map +1 -0
- package/dist/components/example-button.js +74 -0
- package/dist/components/example-button.js.map +1 -0
- package/dist/components/participant-controls.d.ts +94 -0
- package/dist/components/participant-controls.d.ts.map +1 -0
- package/dist/components/participant-controls.js +468 -0
- package/dist/components/participant-controls.js.map +1 -0
- package/dist/components/participants.d.ts +116 -0
- package/dist/components/participants.d.ts.map +1 -0
- package/dist/components/participants.js +394 -0
- package/dist/components/participants.js.map +1 -0
- package/dist/components/self-media.d.ts +78 -0
- package/dist/components/self-media.d.ts.map +1 -0
- package/dist/components/self-media.js +128 -0
- package/dist/components/self-media.js.map +1 -0
- package/dist/context/call-context.d.ts +13 -0
- package/dist/context/call-context.d.ts.map +1 -0
- package/dist/context/call-context.js +6 -0
- package/dist/context/call-context.js.map +1 -0
- package/dist/context/index.d.ts +2 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -5645
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +101 -0
- package/dist/types/index.d.ts +67 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/debounce.d.ts +10 -0
- package/dist/utils/debounce.d.ts.map +1 -0
- package/dist/utils/debounce.js +13 -0
- package/dist/utils/debounce.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/video.d.ts +34 -0
- package/dist/utils/video.d.ts.map +1 -0
- package/dist/utils/video.js +26 -0
- package/dist/utils/video.js.map +1 -0
- package/package.json +70 -3
|
@@ -0,0 +1,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":"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"}
|
|
@@ -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"}
|