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

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 @@
1
+ {"version":3,"file":"example-button.d.ts","sourceRoot":"","sources":["../../src/components/example-button.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAG5C;;;;;GAKG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,MAAM,CAAC,MAAM,0BA4BX;IAGF,QAAQ,UAAS;IAGjB,OAAO,EAAE,SAAS,GAAG,WAAW,CAAa;IAE7C,OAAO,CAAC,YAAY;IAgBpB,MAAM;CAOP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,aAAa,CAAC;KACpC;CACF"}
@@ -0,0 +1,74 @@
1
+ import { LitElement as d, html as p, css as u } from "lit";
2
+ import { property as c, customElement as b } from "lit/decorators.js";
3
+ var m = Object.defineProperty, h = Object.getOwnPropertyDescriptor, i = (o, e, s, n) => {
4
+ for (var t = n > 1 ? void 0 : n ? h(e, s) : e, l = o.length - 1, a; l >= 0; l--)
5
+ (a = o[l]) && (t = (n ? a(e, s, t) : a(t)) || t);
6
+ return n && t && m(e, s, t), t;
7
+ };
8
+ let r = class extends d {
9
+ constructor() {
10
+ super(...arguments), this.disabled = !1, this.variant = "primary";
11
+ }
12
+ _handleClick(o) {
13
+ if (this.disabled) {
14
+ o.preventDefault(), o.stopPropagation();
15
+ return;
16
+ }
17
+ this.dispatchEvent(
18
+ new CustomEvent("sw-click", {
19
+ detail: { originalEvent: o },
20
+ bubbles: !0,
21
+ composed: !0
22
+ })
23
+ );
24
+ }
25
+ render() {
26
+ return p`
27
+ <button part="button" ?disabled=${this.disabled} @click=${this._handleClick}>
28
+ <slot></slot>
29
+ </button>
30
+ `;
31
+ }
32
+ };
33
+ r.styles = u`
34
+ :host {
35
+ display: inline-block;
36
+ }
37
+
38
+ button {
39
+ padding: 0.5rem 1rem;
40
+ font-size: 1rem;
41
+ border: none;
42
+ border-radius: 4px;
43
+ background-color: #0066cc;
44
+ color: white;
45
+ cursor: pointer;
46
+ transition: background-color 0.2s;
47
+ }
48
+
49
+ button:hover {
50
+ background-color: #0052a3;
51
+ }
52
+
53
+ button:active {
54
+ background-color: #003d7a;
55
+ }
56
+
57
+ button:disabled {
58
+ background-color: #cccccc;
59
+ cursor: not-allowed;
60
+ }
61
+ `;
62
+ i([
63
+ c({ type: Boolean })
64
+ ], r.prototype, "disabled", 2);
65
+ i([
66
+ c({ type: String })
67
+ ], r.prototype, "variant", 2);
68
+ r = i([
69
+ b("sw-example-button")
70
+ ], r);
71
+ export {
72
+ r as ExampleButton
73
+ };
74
+ //# sourceMappingURL=example-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example-button.js","sources":["../../src/components/example-button.ts"],"sourcesContent":["import { LitElement, html, css } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\n\n/**\n * An example button component built with Lit\n *\n * @slot - Default slot for button content\n * @csspart button - The button element\n */\n@customElement('sw-example-button')\nexport class ExampleButton extends LitElement {\n static styles = css`\n :host {\n display: inline-block;\n }\n\n button {\n padding: 0.5rem 1rem;\n font-size: 1rem;\n border: none;\n border-radius: 4px;\n background-color: #0066cc;\n color: white;\n cursor: pointer;\n transition: background-color 0.2s;\n }\n\n button:hover {\n background-color: #0052a3;\n }\n\n button:active {\n background-color: #003d7a;\n }\n\n button:disabled {\n background-color: #cccccc;\n cursor: not-allowed;\n }\n `;\n\n @property({ type: Boolean })\n disabled = false;\n\n @property({ type: String })\n variant: 'primary' | 'secondary' = 'primary';\n\n private _handleClick(e: MouseEvent) {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n this.dispatchEvent(\n new CustomEvent('sw-click', {\n detail: { originalEvent: e },\n bubbles: true,\n composed: true\n })\n );\n }\n\n render() {\n return html`\n <button part=\"button\" ?disabled=${this.disabled} @click=${this._handleClick}>\n <slot></slot>\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-example-button': ExampleButton;\n }\n}\n"],"names":["ExampleButton","LitElement","e","html","css","__decorateClass","property","customElement"],"mappings":";;;;;;;AAUO,IAAMA,IAAN,cAA4BC,EAAW;AAAA,EAAvC,cAAA;AAAA,UAAA,GAAA,SAAA,GAgCL,KAAA,WAAW,IAGX,KAAA,UAAmC;AAAA,EAAA;AAAA,EAE3B,aAAaC,GAAe;AAClC,QAAI,KAAK,UAAU;AACjB,MAAAA,EAAE,eAAA,GACFA,EAAE,gBAAA;AACF;AAAA,IACF;AAEA,SAAK;AAAA,MACH,IAAI,YAAY,YAAY;AAAA,QAC1B,QAAQ,EAAE,eAAeA,EAAA;AAAA,QACzB,SAAS;AAAA,QACT,UAAU;AAAA,MAAA,CACX;AAAA,IAAA;AAAA,EAEL;AAAA,EAEA,SAAS;AACP,WAAOC;AAAA,wCAC6B,KAAK,QAAQ,WAAW,KAAK,YAAY;AAAA;AAAA;AAAA;AAAA,EAI/E;AACF;AA5DaH,EACJ,SAASI;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;AA+BhBC,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAA,CAAS;AAAA,GA/BhBN,EAgCX,WAAA,YAAA,CAAA;AAGAK,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAlCfN,EAmCX,WAAA,WAAA,CAAA;AAnCWA,IAANK,EAAA;AAAA,EADNE,EAAc,mBAAmB;AAAA,GACrBP,CAAA;"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Participant Controls Component
3
+ *
4
+ * Individual participant control panel with actions like mute, remove,
5
+ * volume control, and pin/spotlight.
6
+ *
7
+ * @example
8
+ * ```html
9
+ * <sw-participant-controls
10
+ * .participant=${participant}
11
+ * .capabilities=${['memberMuteAudio', 'memberRemove']}
12
+ * ></sw-participant-controls>
13
+ * ```
14
+ */
15
+ import { LitElement } from 'lit';
16
+ import type { Observable } from 'rxjs';
17
+ /**
18
+ * Participant interface for controls component
19
+ */
20
+ export interface ControlParticipant {
21
+ id: string;
22
+ name$?: Observable<string>;
23
+ audioMuted$?: Observable<boolean>;
24
+ videoMuted$?: Observable<boolean>;
25
+ mute?(): Promise<void>;
26
+ unmute?(): Promise<void>;
27
+ muteVideo?(): Promise<void>;
28
+ unmuteVideo?(): Promise<void>;
29
+ remove?(): Promise<void>;
30
+ }
31
+ export declare class ParticipantControlsComponent extends LitElement {
32
+ static styles: import("lit").CSSResult;
33
+ /**
34
+ * Participant object to control
35
+ */
36
+ participant: ControlParticipant | null;
37
+ /**
38
+ * Available capabilities (actions user can perform)
39
+ */
40
+ capabilities: string[];
41
+ /**
42
+ * Whether to show volume slider
43
+ */
44
+ showVolume: boolean;
45
+ /**
46
+ * Whether to show pin/spotlight button
47
+ */
48
+ showPin: boolean;
49
+ /**
50
+ * Current volume (0-100)
51
+ */
52
+ private volume;
53
+ /**
54
+ * Participant name
55
+ */
56
+ private participantName;
57
+ /**
58
+ * Audio mute state
59
+ */
60
+ private audioMuted;
61
+ /**
62
+ * Video mute state
63
+ */
64
+ private videoMuted;
65
+ /**
66
+ * Is pinned/spotlighted
67
+ */
68
+ private isPinned;
69
+ /**
70
+ * RxJS subscriptions for cleanup
71
+ */
72
+ private subscriptions;
73
+ connectedCallback(): void;
74
+ disconnectedCallback(): void;
75
+ updated(changedProperties: Map<string, unknown>): void;
76
+ private subscribeToParticipant;
77
+ private cleanup;
78
+ private get canMuteAudio();
79
+ private get canMuteVideo();
80
+ private get canRemove();
81
+ private get hasAnyCapability();
82
+ private handleToggleAudioMute;
83
+ private handleToggleVideoMute;
84
+ private handleRemove;
85
+ private handleVolumeChange;
86
+ private handleTogglePin;
87
+ render(): import("lit-html").TemplateResult<1>;
88
+ }
89
+ declare global {
90
+ interface HTMLElementTagNameMap {
91
+ 'sw-participant-controls': ParticipantControlsComponent;
92
+ }
93
+ }
94
+ //# sourceMappingURL=participant-controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"participant-controls.d.ts","sourceRoot":"","sources":["../../src/components/participant-controls.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAG5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAClC,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,qBACa,4BAA6B,SAAQ,UAAU;IAC1D,MAAM,CAAC,MAAM,0BAoMX;IAEF;;OAEG;IAEH,WAAW,EAAE,kBAAkB,GAAG,IAAI,CAAQ;IAE9C;;OAEG;IAEH,YAAY,EAAE,MAAM,EAAE,CAAM;IAE5B;;OAEG;IAEH,UAAU,EAAE,OAAO,CAAS;IAE5B;;OAEG;IAEH,OAAO,EAAE,OAAO,CAAS;IAEzB;;OAEG;IAEH,OAAO,CAAC,MAAM,CAAe;IAE7B;;OAEG;IAEH,OAAO,CAAC,eAAe,CAAyB;IAEhD;;OAEG;IAEH,OAAO,CAAC,UAAU,CAAkB;IAEpC;;OAEG;IAEH,OAAO,CAAC,UAAU,CAAkB;IAEpC;;OAEG;IAEH,OAAO,CAAC,QAAQ,CAAkB;IAElC;;OAEG;IACH,OAAO,CAAC,aAAa,CAAsB;IAE3C,iBAAiB;IAKjB,oBAAoB;IAKpB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAO/C,OAAO,CAAC,sBAAsB;IAyB9B,OAAO,CAAC,OAAO;IAKf,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,gBAAgB,GAI3B;YAEa,qBAAqB;YAsBrB,qBAAqB;YAsBrB,YAAY;IAkB1B,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,eAAe;IAYvB,MAAM;CAqIP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,yBAAyB,EAAE,4BAA4B,CAAC;KACzD;CACF"}
@@ -0,0 +1,468 @@
1
+ import { LitElement as d, html as o, css as h } from "lit";
2
+ import { property as c, state as r, customElement as v } from "lit/decorators.js";
3
+ var b = Object.defineProperty, w = Object.getOwnPropertyDescriptor, a = (t, e, l, n) => {
4
+ for (var s = n > 1 ? void 0 : n ? w(e, l) : e, p = t.length - 1, u; p >= 0; p--)
5
+ (u = t[p]) && (s = (n ? u(e, l, s) : u(s)) || s);
6
+ return n && s && b(e, l, s), s;
7
+ };
8
+ let i = class extends d {
9
+ constructor() {
10
+ super(...arguments), this.participant = null, this.capabilities = [], this.showVolume = !1, this.showPin = !1, this.volume = 100, this.participantName = "Participant", this.audioMuted = !1, this.videoMuted = !1, this.isPinned = !1, this.subscriptions = [];
11
+ }
12
+ connectedCallback() {
13
+ super.connectedCallback(), this.subscribeToParticipant();
14
+ }
15
+ disconnectedCallback() {
16
+ super.disconnectedCallback(), this.cleanup();
17
+ }
18
+ updated(t) {
19
+ t.has("participant") && (this.cleanup(), this.subscribeToParticipant());
20
+ }
21
+ subscribeToParticipant() {
22
+ if (this.participant) {
23
+ if (this.participant.name$) {
24
+ const t = this.participant.name$.subscribe((e) => {
25
+ this.participantName = e;
26
+ });
27
+ this.subscriptions.push(t);
28
+ }
29
+ if (this.participant.audioMuted$) {
30
+ const t = this.participant.audioMuted$.subscribe((e) => {
31
+ this.audioMuted = e;
32
+ });
33
+ this.subscriptions.push(t);
34
+ }
35
+ if (this.participant.videoMuted$) {
36
+ const t = this.participant.videoMuted$.subscribe((e) => {
37
+ this.videoMuted = e;
38
+ });
39
+ this.subscriptions.push(t);
40
+ }
41
+ }
42
+ }
43
+ cleanup() {
44
+ this.subscriptions.forEach((t) => t.unsubscribe()), this.subscriptions = [];
45
+ }
46
+ get canMuteAudio() {
47
+ return this.capabilities.includes("memberMuteAudio");
48
+ }
49
+ get canMuteVideo() {
50
+ return this.capabilities.includes("memberMuteVideo");
51
+ }
52
+ get canRemove() {
53
+ return this.capabilities.includes("memberRemove");
54
+ }
55
+ get hasAnyCapability() {
56
+ return this.canMuteAudio || this.canMuteVideo || this.canRemove || this.showVolume || this.showPin;
57
+ }
58
+ async handleToggleAudioMute() {
59
+ if (this.participant)
60
+ try {
61
+ this.audioMuted && this.participant.unmute ? await this.participant.unmute() : !this.audioMuted && this.participant.mute && await this.participant.mute(), this.dispatchEvent(
62
+ new CustomEvent("sw-participant-mute-audio", {
63
+ detail: { participant: this.participant, muted: !this.audioMuted },
64
+ bubbles: !0,
65
+ composed: !0
66
+ })
67
+ );
68
+ } catch (t) {
69
+ console.error("Failed to toggle audio mute:", t);
70
+ }
71
+ }
72
+ async handleToggleVideoMute() {
73
+ if (this.participant)
74
+ try {
75
+ this.videoMuted && this.participant.unmuteVideo ? await this.participant.unmuteVideo() : !this.videoMuted && this.participant.muteVideo && await this.participant.muteVideo(), this.dispatchEvent(
76
+ new CustomEvent("sw-participant-mute-video", {
77
+ detail: { participant: this.participant, muted: !this.videoMuted },
78
+ bubbles: !0,
79
+ composed: !0
80
+ })
81
+ );
82
+ } catch (t) {
83
+ console.error("Failed to toggle video mute:", t);
84
+ }
85
+ }
86
+ async handleRemove() {
87
+ var t;
88
+ if ((t = this.participant) != null && t.remove)
89
+ try {
90
+ await this.participant.remove(), this.dispatchEvent(
91
+ new CustomEvent("sw-participant-remove", {
92
+ detail: { participant: this.participant },
93
+ bubbles: !0,
94
+ composed: !0
95
+ })
96
+ );
97
+ } catch (e) {
98
+ console.error("Failed to remove participant:", e);
99
+ }
100
+ }
101
+ handleVolumeChange(t) {
102
+ const e = t.target;
103
+ this.volume = parseInt(e.value, 10), this.dispatchEvent(
104
+ new CustomEvent("sw-participant-volume", {
105
+ detail: { participant: this.participant, volume: this.volume },
106
+ bubbles: !0,
107
+ composed: !0
108
+ })
109
+ );
110
+ }
111
+ handleTogglePin() {
112
+ this.isPinned = !this.isPinned, this.dispatchEvent(
113
+ new CustomEvent("sw-participant-pin", {
114
+ detail: { participant: this.participant, pinned: this.isPinned },
115
+ bubbles: !0,
116
+ composed: !0
117
+ })
118
+ );
119
+ }
120
+ render() {
121
+ return o`
122
+ <div class="container" part="container">
123
+ <div class="header">
124
+ <span class="participant-name">${this.participantName}</span>
125
+ </div>
126
+
127
+ <div class="actions">
128
+ ${this.hasAnyCapability ? null : o`<div class="no-actions">No actions available</div>`}
129
+ ${this.canMuteAudio ? o`
130
+ <button
131
+ class="action-button ${this.audioMuted ? "active" : ""}"
132
+ part="action-button"
133
+ @click=${this.handleToggleAudioMute}
134
+ aria-label="${this.audioMuted ? "Unmute audio" : "Mute audio"}"
135
+ >
136
+ ${this.audioMuted ? o`<svg
137
+ xmlns="http://www.w3.org/2000/svg"
138
+ viewBox="0 0 24 24"
139
+ fill="currentColor"
140
+ >
141
+ <path
142
+ d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"
143
+ />
144
+ </svg>` : o`<svg
145
+ xmlns="http://www.w3.org/2000/svg"
146
+ viewBox="0 0 24 24"
147
+ fill="currentColor"
148
+ >
149
+ <path
150
+ 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"
151
+ />
152
+ </svg>`}
153
+ ${this.audioMuted ? "Unmute" : "Mute"}
154
+ </button>
155
+ ` : null}
156
+ ${this.canMuteVideo ? o`
157
+ <button
158
+ class="action-button ${this.videoMuted ? "active" : ""}"
159
+ part="action-button"
160
+ @click=${this.handleToggleVideoMute}
161
+ aria-label="${this.videoMuted ? "Unmute video" : "Mute video"}"
162
+ >
163
+ ${this.videoMuted ? o`<svg
164
+ xmlns="http://www.w3.org/2000/svg"
165
+ viewBox="0 0 24 24"
166
+ fill="currentColor"
167
+ >
168
+ <path
169
+ d="M21 6.5l-4 4V7c0-.55-.45-1-1-1H9.82L21 17.18V6.5zM3.27 2L2 3.27 4.73 6H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.21 0 .39-.08.54-.18L19.73 21 21 19.73 3.27 2z"
170
+ />
171
+ </svg>` : o`<svg
172
+ xmlns="http://www.w3.org/2000/svg"
173
+ viewBox="0 0 24 24"
174
+ fill="currentColor"
175
+ >
176
+ <path
177
+ 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"
178
+ />
179
+ </svg>`}
180
+ ${this.videoMuted ? "Enable video" : "Disable video"}
181
+ </button>
182
+ ` : null}
183
+ ${this.showVolume ? o`
184
+ <div class="volume-control" part="slider">
185
+ <label class="volume-label">
186
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
187
+ <path
188
+ 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.02z"
189
+ />
190
+ </svg>
191
+ Volume: ${this.volume}%
192
+ </label>
193
+ <input
194
+ type="range"
195
+ class="volume-slider"
196
+ min="0"
197
+ max="100"
198
+ .value=${String(this.volume)}
199
+ @input=${this.handleVolumeChange}
200
+ aria-label="Participant volume"
201
+ />
202
+ </div>
203
+ ` : null}
204
+ ${this.showPin ? o`
205
+ <button
206
+ class="action-button ${this.isPinned ? "active" : ""}"
207
+ part="action-button"
208
+ @click=${this.handleTogglePin}
209
+ aria-label="${this.isPinned ? "Unpin" : "Pin"}"
210
+ aria-pressed="${this.isPinned}"
211
+ >
212
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
213
+ <path d="M16 12V4h1V2H7v2h1v8l-2 2v2h5.2v6h1.6v-6H18v-2l-2-2z" />
214
+ </svg>
215
+ ${this.isPinned ? "Unpin" : "Pin"}
216
+ </button>
217
+ ` : null}
218
+ ${this.canRemove ? o`
219
+ <button
220
+ class="action-button danger"
221
+ part="action-button"
222
+ @click=${this.handleRemove}
223
+ aria-label="Remove participant"
224
+ >
225
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
226
+ <path
227
+ d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
228
+ />
229
+ </svg>
230
+ Remove
231
+ </button>
232
+ ` : null}
233
+ </div>
234
+ </div>
235
+ `;
236
+ }
237
+ };
238
+ i.styles = h`
239
+ :host {
240
+ /* CSS Custom Properties for theming */
241
+ --sw-color-primary: #044cf6;
242
+ --sw-color-primary-hover: #0339c4;
243
+ --sw-color-success: #10b981;
244
+ --sw-color-danger: #ef4444;
245
+ --sw-color-danger-hover: #dc2626;
246
+ --sw-color-warning: #f59e0b;
247
+ --sw-color-text: #1f2937;
248
+ --sw-color-text-muted: #6b7280;
249
+ --sw-color-text-inverse: #ffffff;
250
+ --sw-color-background: #ffffff;
251
+ --sw-color-background-hover: #f3f4f6;
252
+ --sw-color-background-active: #e5e7eb;
253
+ --sw-color-border: #e5e7eb;
254
+ --sw-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
255
+ --sw-font-size-xs: 11px;
256
+ --sw-font-size-sm: 12px;
257
+ --sw-font-size-base: 14px;
258
+ --sw-space-1: 4px;
259
+ --sw-space-2: 8px;
260
+ --sw-space-3: 12px;
261
+ --sw-space-4: 16px;
262
+ --sw-border-radius: 8px;
263
+
264
+ display: block;
265
+ font-family: var(--sw-font-family);
266
+ }
267
+
268
+ /* Dark mode support */
269
+ :host([data-theme='dark']) {
270
+ --sw-color-text: #f9fafb;
271
+ --sw-color-text-muted: #9ca3af;
272
+ --sw-color-background: #1f2937;
273
+ --sw-color-background-hover: #374151;
274
+ --sw-color-background-active: #4b5563;
275
+ --sw-color-border: #374151;
276
+ }
277
+
278
+ @media (prefers-color-scheme: dark) {
279
+ :host(:not([data-theme='light'])) {
280
+ --sw-color-text: #f9fafb;
281
+ --sw-color-text-muted: #9ca3af;
282
+ --sw-color-background: #1f2937;
283
+ --sw-color-background-hover: #374151;
284
+ --sw-color-background-active: #4b5563;
285
+ --sw-color-border: #374151;
286
+ }
287
+ }
288
+
289
+ .container {
290
+ display: flex;
291
+ flex-direction: column;
292
+ gap: var(--sw-space-2);
293
+ padding: var(--sw-space-3);
294
+ background: var(--sw-color-background);
295
+ border: 1px solid var(--sw-color-border);
296
+ border-radius: var(--sw-border-radius);
297
+ min-width: 200px;
298
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
299
+ }
300
+
301
+ .header {
302
+ display: flex;
303
+ align-items: center;
304
+ gap: var(--sw-space-2);
305
+ padding-bottom: var(--sw-space-2);
306
+ border-bottom: 1px solid var(--sw-color-border);
307
+ }
308
+
309
+ .participant-name {
310
+ flex: 1;
311
+ font-size: var(--sw-font-size-base);
312
+ font-weight: 500;
313
+ color: var(--sw-color-text);
314
+ overflow: hidden;
315
+ text-overflow: ellipsis;
316
+ white-space: nowrap;
317
+ }
318
+
319
+ .actions {
320
+ display: flex;
321
+ flex-direction: column;
322
+ gap: var(--sw-space-2);
323
+ }
324
+
325
+ .action-button {
326
+ display: flex;
327
+ align-items: center;
328
+ gap: var(--sw-space-2);
329
+ padding: var(--sw-space-2) var(--sw-space-3);
330
+ background: var(--sw-color-background-hover);
331
+ border: none;
332
+ border-radius: var(--sw-border-radius);
333
+ color: var(--sw-color-text);
334
+ font-family: var(--sw-font-family);
335
+ font-size: var(--sw-font-size-sm);
336
+ cursor: pointer;
337
+ transition: background-color 0.15s ease;
338
+ text-align: left;
339
+ }
340
+
341
+ .action-button:hover {
342
+ background: var(--sw-color-background-active);
343
+ }
344
+
345
+ .action-button:disabled {
346
+ opacity: 0.5;
347
+ cursor: not-allowed;
348
+ }
349
+
350
+ .action-button.active {
351
+ background: var(--sw-color-danger);
352
+ color: var(--sw-color-text-inverse);
353
+ }
354
+
355
+ .action-button.active:hover {
356
+ background: var(--sw-color-danger-hover);
357
+ }
358
+
359
+ .action-button.danger {
360
+ color: var(--sw-color-danger);
361
+ }
362
+
363
+ .action-button.danger:hover {
364
+ background: var(--sw-color-danger);
365
+ color: var(--sw-color-text-inverse);
366
+ }
367
+
368
+ .action-button svg {
369
+ width: 16px;
370
+ height: 16px;
371
+ flex-shrink: 0;
372
+ }
373
+
374
+ .volume-control {
375
+ display: flex;
376
+ flex-direction: column;
377
+ gap: var(--sw-space-1);
378
+ }
379
+
380
+ .volume-label {
381
+ display: flex;
382
+ align-items: center;
383
+ gap: var(--sw-space-2);
384
+ font-size: var(--sw-font-size-sm);
385
+ color: var(--sw-color-text-muted);
386
+ }
387
+
388
+ .volume-label svg {
389
+ width: 14px;
390
+ height: 14px;
391
+ }
392
+
393
+ .volume-slider {
394
+ width: 100%;
395
+ height: 4px;
396
+ -webkit-appearance: none;
397
+ appearance: none;
398
+ background: var(--sw-color-border);
399
+ border-radius: 2px;
400
+ outline: none;
401
+ cursor: pointer;
402
+ }
403
+
404
+ .volume-slider::-webkit-slider-thumb {
405
+ -webkit-appearance: none;
406
+ appearance: none;
407
+ width: 14px;
408
+ height: 14px;
409
+ background: var(--sw-color-primary);
410
+ border-radius: 50%;
411
+ cursor: pointer;
412
+ transition: transform 0.1s ease;
413
+ }
414
+
415
+ .volume-slider::-webkit-slider-thumb:hover {
416
+ transform: scale(1.2);
417
+ }
418
+
419
+ .volume-slider::-moz-range-thumb {
420
+ width: 14px;
421
+ height: 14px;
422
+ background: var(--sw-color-primary);
423
+ border-radius: 50%;
424
+ border: none;
425
+ cursor: pointer;
426
+ }
427
+
428
+ .no-actions {
429
+ color: var(--sw-color-text-muted);
430
+ font-size: var(--sw-font-size-sm);
431
+ text-align: center;
432
+ padding: var(--sw-space-2);
433
+ }
434
+ `;
435
+ a([
436
+ c({ attribute: !1 })
437
+ ], i.prototype, "participant", 2);
438
+ a([
439
+ c({ attribute: !1 })
440
+ ], i.prototype, "capabilities", 2);
441
+ a([
442
+ c({ type: Boolean, attribute: "show-volume" })
443
+ ], i.prototype, "showVolume", 2);
444
+ a([
445
+ c({ type: Boolean, attribute: "show-pin" })
446
+ ], i.prototype, "showPin", 2);
447
+ a([
448
+ r()
449
+ ], i.prototype, "volume", 2);
450
+ a([
451
+ r()
452
+ ], i.prototype, "participantName", 2);
453
+ a([
454
+ r()
455
+ ], i.prototype, "audioMuted", 2);
456
+ a([
457
+ r()
458
+ ], i.prototype, "videoMuted", 2);
459
+ a([
460
+ r()
461
+ ], i.prototype, "isPinned", 2);
462
+ i = a([
463
+ v("sw-participant-controls")
464
+ ], i);
465
+ export {
466
+ i as ParticipantControlsComponent
467
+ };
468
+ //# sourceMappingURL=participant-controls.js.map