@signalwire/web-components 4.0.0-beta.1 → 4.0.0-beta.11

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 (79) hide show
  1. package/README.md +9 -10
  2. package/dist/components/audio-level.d.ts +114 -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 +183 -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 +118 -0
  11. package/dist/components/call-media.d.ts.map +1 -0
  12. package/dist/components/call-media.js +219 -0
  13. package/dist/components/call-media.js.map +1 -0
  14. package/dist/components/call-status.d.ts +83 -0
  15. package/dist/components/call-status.d.ts.map +1 -0
  16. package/dist/components/call-status.js +255 -0
  17. package/dist/components/call-status.js.map +1 -0
  18. package/dist/components/click-to-call.d.ts +151 -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 +238 -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 +74 -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 +125 -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 +21 -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 +123 -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 +120 -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 +129 -0
  49. package/dist/components/self-media.js.map +1 -0
  50. package/dist/constants.d.ts +10 -0
  51. package/dist/constants.d.ts.map +1 -0
  52. package/dist/constants.js +5 -0
  53. package/dist/constants.js.map +1 -0
  54. package/dist/context/call-context.d.ts +13 -0
  55. package/dist/context/call-context.d.ts.map +1 -0
  56. package/dist/context/call-context.js +6 -0
  57. package/dist/context/call-context.js.map +1 -0
  58. package/dist/context/index.d.ts +2 -0
  59. package/dist/context/index.d.ts.map +1 -0
  60. package/dist/index.d.ts +29 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +35 -5644
  63. package/dist/index.js.map +1 -1
  64. package/dist/react.d.ts +122 -0
  65. package/dist/types/index.d.ts +20 -0
  66. package/dist/types/index.d.ts.map +1 -0
  67. package/dist/types/index.js +12 -0
  68. package/dist/types/index.js.map +1 -0
  69. package/dist/utils/debounce.d.ts +10 -0
  70. package/dist/utils/debounce.d.ts.map +1 -0
  71. package/dist/utils/debounce.js +13 -0
  72. package/dist/utils/debounce.js.map +1 -0
  73. package/dist/utils/index.d.ts +3 -0
  74. package/dist/utils/index.d.ts.map +1 -0
  75. package/dist/utils/video.d.ts +34 -0
  76. package/dist/utils/video.d.ts.map +1 -0
  77. package/dist/utils/video.js +26 -0
  78. package/dist/utils/video.js.map +1 -0
  79. package/package.json +70 -3
@@ -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
+ e !== void 0 && (this.participantName = e);
26
+ });
27
+ this.subscriptions.push(t);
28
+ }
29
+ if (this.participant.audioMuted$) {
30
+ const t = this.participant.audioMuted$.subscribe((e) => {
31
+ e !== void 0 && (this.audioMuted = e);
32
+ });
33
+ this.subscriptions.push(t);
34
+ }
35
+ if (this.participant.videoMuted$) {
36
+ const t = this.participant.videoMuted$.subscribe((e) => {
37
+ e !== void 0 && (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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"participant-controls.js","sources":["../../src/components/participant-controls.ts"],"sourcesContent":["/**\n * Participant Controls Component\n *\n * Individual participant control panel with actions like mute, remove,\n * volume control, and pin/spotlight.\n *\n * @example\n * ```html\n * <sw-participant-controls\n * .participant=${participant}\n * .capabilities=${['memberMuteAudio', 'memberRemove']}\n * ></sw-participant-controls>\n * ```\n *\n * @fires sw-participant-mute-audio - Fired to toggle a participant's audio. Detail: `{ participantId: string, muted: boolean }`\n * @fires sw-participant-mute-video - Fired to toggle a participant's video. Detail: `{ participantId: string, muted: boolean }`\n * @fires sw-participant-remove - Fired to remove a participant. Detail: `{ participantId: string }`\n * @fires sw-participant-volume - Fired when a participant's volume changes. Detail: `{ participantId: string, volume: number }`\n * @fires sw-participant-pin - Fired to pin/unpin a participant. Detail: `{ participantId: string, pinned: boolean }`\n *\n * @cssprop [--sw-color-primary=#044cf6] - Primary brand color\n * @cssprop [--sw-color-primary-hover=#0339c4] - Primary color on hover\n * @cssprop [--sw-color-success=#10b981] - Success/positive color\n * @cssprop [--sw-color-danger=#ef4444] - Danger/destructive color\n * @cssprop [--sw-color-danger-hover=#dc2626] - Danger color on hover\n * @cssprop [--sw-color-warning=#f59e0b] - Warning color\n * @cssprop [--sw-color-text=#1f2937] - Primary text color\n * @cssprop [--sw-color-text-muted=#6b7280] - Secondary/muted text color\n * @cssprop [--sw-color-text-inverse=#ffffff] - Inverse text color for active buttons\n * @cssprop [--sw-color-background=#ffffff] - Component background color\n * @cssprop [--sw-color-background-hover=#f3f4f6] - Background color on hover\n * @cssprop [--sw-color-background-active=#e5e7eb] - Background color on active/press\n * @cssprop [--sw-color-border=#e5e7eb] - Border color\n * @cssprop [--sw-font-family=-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif] - Font family\n * @cssprop [--sw-font-size-xs=11px] - Extra-small font size\n * @cssprop [--sw-font-size-sm=12px] - Small font size\n * @cssprop [--sw-font-size-base=14px] - Base font size\n * @cssprop [--sw-space-1=4px] - Smallest spacing unit\n * @cssprop [--sw-space-2=8px] - Small spacing unit\n * @cssprop [--sw-space-3=12px] - Medium spacing unit\n * @cssprop [--sw-space-4=16px] - Large spacing unit\n * @cssprop [--sw-border-radius=8px] - Border radius for containers and buttons\n */\n\nimport { LitElement, html, css } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { Subscription } from 'rxjs';\nimport type { Observable } from 'rxjs';\n\n/**\n * Participant interface for controls component\n */\nexport interface ControlParticipant {\n id: string;\n name$?: Observable<string | undefined>;\n audioMuted$?: Observable<boolean | undefined>;\n videoMuted$?: Observable<boolean | undefined>;\n mute?(): Promise<void>;\n unmute?(): Promise<void>;\n muteVideo?(): Promise<void>;\n unmuteVideo?(): Promise<void>;\n remove?(): Promise<void>;\n}\n\n@customElement('sw-participant-controls')\nexport class ParticipantControlsComponent extends LitElement {\n static styles = css`\n :host {\n /* CSS Custom Properties for theming */\n --sw-color-primary: #044cf6;\n --sw-color-primary-hover: #0339c4;\n --sw-color-success: #10b981;\n --sw-color-danger: #ef4444;\n --sw-color-danger-hover: #dc2626;\n --sw-color-warning: #f59e0b;\n --sw-color-text: #1f2937;\n --sw-color-text-muted: #6b7280;\n --sw-color-text-inverse: #ffffff;\n --sw-color-background: #ffffff;\n --sw-color-background-hover: #f3f4f6;\n --sw-color-background-active: #e5e7eb;\n --sw-color-border: #e5e7eb;\n --sw-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --sw-font-size-xs: 11px;\n --sw-font-size-sm: 12px;\n --sw-font-size-base: 14px;\n --sw-space-1: 4px;\n --sw-space-2: 8px;\n --sw-space-3: 12px;\n --sw-space-4: 16px;\n --sw-border-radius: 8px;\n\n display: block;\n font-family: var(--sw-font-family);\n }\n\n /* Dark mode support */\n :host([data-theme='dark']) {\n --sw-color-text: #f9fafb;\n --sw-color-text-muted: #9ca3af;\n --sw-color-background: #1f2937;\n --sw-color-background-hover: #374151;\n --sw-color-background-active: #4b5563;\n --sw-color-border: #374151;\n }\n\n @media (prefers-color-scheme: dark) {\n :host(:not([data-theme='light'])) {\n --sw-color-text: #f9fafb;\n --sw-color-text-muted: #9ca3af;\n --sw-color-background: #1f2937;\n --sw-color-background-hover: #374151;\n --sw-color-background-active: #4b5563;\n --sw-color-border: #374151;\n }\n }\n\n .container {\n display: flex;\n flex-direction: column;\n gap: var(--sw-space-2);\n padding: var(--sw-space-3);\n background: var(--sw-color-background);\n border: 1px solid var(--sw-color-border);\n border-radius: var(--sw-border-radius);\n min-width: 200px;\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n }\n\n .header {\n display: flex;\n align-items: center;\n gap: var(--sw-space-2);\n padding-bottom: var(--sw-space-2);\n border-bottom: 1px solid var(--sw-color-border);\n }\n\n .participant-name {\n flex: 1;\n font-size: var(--sw-font-size-base);\n font-weight: 500;\n color: var(--sw-color-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .actions {\n display: flex;\n flex-direction: column;\n gap: var(--sw-space-2);\n }\n\n .action-button {\n display: flex;\n align-items: center;\n gap: var(--sw-space-2);\n padding: var(--sw-space-2) var(--sw-space-3);\n background: var(--sw-color-background-hover);\n border: none;\n border-radius: var(--sw-border-radius);\n color: var(--sw-color-text);\n font-family: var(--sw-font-family);\n font-size: var(--sw-font-size-sm);\n cursor: pointer;\n transition: background-color 0.15s ease;\n text-align: left;\n }\n\n .action-button:hover {\n background: var(--sw-color-background-active);\n }\n\n .action-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .action-button.active {\n background: var(--sw-color-danger);\n color: var(--sw-color-text-inverse);\n }\n\n .action-button.active:hover {\n background: var(--sw-color-danger-hover);\n }\n\n .action-button.danger {\n color: var(--sw-color-danger);\n }\n\n .action-button.danger:hover {\n background: var(--sw-color-danger);\n color: var(--sw-color-text-inverse);\n }\n\n .action-button svg {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n }\n\n .volume-control {\n display: flex;\n flex-direction: column;\n gap: var(--sw-space-1);\n }\n\n .volume-label {\n display: flex;\n align-items: center;\n gap: var(--sw-space-2);\n font-size: var(--sw-font-size-sm);\n color: var(--sw-color-text-muted);\n }\n\n .volume-label svg {\n width: 14px;\n height: 14px;\n }\n\n .volume-slider {\n width: 100%;\n height: 4px;\n -webkit-appearance: none;\n appearance: none;\n background: var(--sw-color-border);\n border-radius: 2px;\n outline: none;\n cursor: pointer;\n }\n\n .volume-slider::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 14px;\n height: 14px;\n background: var(--sw-color-primary);\n border-radius: 50%;\n cursor: pointer;\n transition: transform 0.1s ease;\n }\n\n .volume-slider::-webkit-slider-thumb:hover {\n transform: scale(1.2);\n }\n\n .volume-slider::-moz-range-thumb {\n width: 14px;\n height: 14px;\n background: var(--sw-color-primary);\n border-radius: 50%;\n border: none;\n cursor: pointer;\n }\n\n .no-actions {\n color: var(--sw-color-text-muted);\n font-size: var(--sw-font-size-sm);\n text-align: center;\n padding: var(--sw-space-2);\n }\n `;\n\n /**\n * Participant object to control\n */\n @property({ attribute: false })\n participant: ControlParticipant | null = null;\n\n /**\n * Available capabilities (actions user can perform)\n */\n @property({ attribute: false })\n capabilities: string[] = [];\n\n /**\n * Whether to show volume slider\n */\n @property({ type: Boolean, attribute: 'show-volume' })\n showVolume: boolean = false;\n\n /**\n * Whether to show pin/spotlight button\n */\n @property({ type: Boolean, attribute: 'show-pin' })\n showPin: boolean = false;\n\n /**\n * Current volume (0-100)\n */\n @state()\n private volume: number = 100;\n\n /**\n * Participant name\n */\n @state()\n private participantName: string = 'Participant';\n\n /**\n * Audio mute state\n */\n @state()\n private audioMuted: boolean = false;\n\n /**\n * Video mute state\n */\n @state()\n private videoMuted: boolean = false;\n\n /**\n * Is pinned/spotlighted\n */\n @state()\n private isPinned: boolean = false;\n\n /**\n * RxJS subscriptions for cleanup\n */\n private subscriptions: Subscription[] = [];\n\n connectedCallback() {\n super.connectedCallback();\n this.subscribeToParticipant();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.cleanup();\n }\n\n updated(changedProperties: Map<string, unknown>) {\n if (changedProperties.has('participant')) {\n this.cleanup();\n this.subscribeToParticipant();\n }\n }\n\n private subscribeToParticipant() {\n if (!this.participant) return;\n\n if (this.participant.name$) {\n const nameSub = this.participant.name$.subscribe((name) => {\n if (name !== undefined) this.participantName = name;\n });\n this.subscriptions.push(nameSub);\n }\n\n if (this.participant.audioMuted$) {\n const audioSub = this.participant.audioMuted$.subscribe((muted) => {\n if (muted !== undefined) this.audioMuted = muted;\n });\n this.subscriptions.push(audioSub);\n }\n\n if (this.participant.videoMuted$) {\n const videoSub = this.participant.videoMuted$.subscribe((muted) => {\n if (muted !== undefined) this.videoMuted = muted;\n });\n this.subscriptions.push(videoSub);\n }\n }\n\n private cleanup() {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.subscriptions = [];\n }\n\n private get canMuteAudio(): boolean {\n return this.capabilities.includes('memberMuteAudio');\n }\n\n private get canMuteVideo(): boolean {\n return this.capabilities.includes('memberMuteVideo');\n }\n\n private get canRemove(): boolean {\n return this.capabilities.includes('memberRemove');\n }\n\n private get hasAnyCapability(): boolean {\n return (\n this.canMuteAudio || this.canMuteVideo || this.canRemove || this.showVolume || this.showPin\n );\n }\n\n private async handleToggleAudioMute() {\n if (!this.participant) return;\n\n try {\n if (this.audioMuted && this.participant.unmute) {\n await this.participant.unmute();\n } else if (!this.audioMuted && this.participant.mute) {\n await this.participant.mute();\n }\n\n this.dispatchEvent(\n new CustomEvent('sw-participant-mute-audio', {\n detail: { participant: this.participant, muted: !this.audioMuted },\n bubbles: true,\n composed: true\n })\n );\n } catch (error) {\n console.error('Failed to toggle audio mute:', error);\n }\n }\n\n private async handleToggleVideoMute() {\n if (!this.participant) return;\n\n try {\n if (this.videoMuted && this.participant.unmuteVideo) {\n await this.participant.unmuteVideo();\n } else if (!this.videoMuted && this.participant.muteVideo) {\n await this.participant.muteVideo();\n }\n\n this.dispatchEvent(\n new CustomEvent('sw-participant-mute-video', {\n detail: { participant: this.participant, muted: !this.videoMuted },\n bubbles: true,\n composed: true\n })\n );\n } catch (error) {\n console.error('Failed to toggle video mute:', error);\n }\n }\n\n private async handleRemove() {\n if (!this.participant?.remove) return;\n\n try {\n await this.participant.remove();\n\n this.dispatchEvent(\n new CustomEvent('sw-participant-remove', {\n detail: { participant: this.participant },\n bubbles: true,\n composed: true\n })\n );\n } catch (error) {\n console.error('Failed to remove participant:', error);\n }\n }\n\n private handleVolumeChange(e: Event) {\n const input = e.target as HTMLInputElement;\n this.volume = parseInt(input.value, 10);\n\n this.dispatchEvent(\n new CustomEvent('sw-participant-volume', {\n detail: { participant: this.participant, volume: this.volume },\n bubbles: true,\n composed: true\n })\n );\n }\n\n private handleTogglePin() {\n this.isPinned = !this.isPinned;\n\n this.dispatchEvent(\n new CustomEvent('sw-participant-pin', {\n detail: { participant: this.participant, pinned: this.isPinned },\n bubbles: true,\n composed: true\n })\n );\n }\n\n render() {\n return html`\n <div class=\"container\" part=\"container\">\n <div class=\"header\">\n <span class=\"participant-name\">${this.participantName}</span>\n </div>\n\n <div class=\"actions\">\n ${!this.hasAnyCapability\n ? html`<div class=\"no-actions\">No actions available</div>`\n : null}\n ${this.canMuteAudio\n ? html`\n <button\n class=\"action-button ${this.audioMuted ? 'active' : ''}\"\n part=\"action-button\"\n @click=${this.handleToggleAudioMute}\n aria-label=\"${this.audioMuted ? 'Unmute audio' : 'Mute audio'}\"\n >\n ${this.audioMuted\n ? html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <path\n 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\"\n />\n </svg>`\n : html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <path\n d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"\n />\n </svg>`}\n ${this.audioMuted ? 'Unmute' : 'Mute'}\n </button>\n `\n : null}\n ${this.canMuteVideo\n ? html`\n <button\n class=\"action-button ${this.videoMuted ? 'active' : ''}\"\n part=\"action-button\"\n @click=${this.handleToggleVideoMute}\n aria-label=\"${this.videoMuted ? 'Unmute video' : 'Mute video'}\"\n >\n ${this.videoMuted\n ? html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <path\n 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\"\n />\n </svg>`\n : html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <path\n d=\"M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z\"\n />\n </svg>`}\n ${this.videoMuted ? 'Enable video' : 'Disable video'}\n </button>\n `\n : null}\n ${this.showVolume\n ? html`\n <div class=\"volume-control\" part=\"slider\">\n <label class=\"volume-label\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z\"\n />\n </svg>\n Volume: ${this.volume}%\n </label>\n <input\n type=\"range\"\n class=\"volume-slider\"\n min=\"0\"\n max=\"100\"\n .value=${String(this.volume)}\n @input=${this.handleVolumeChange}\n aria-label=\"Participant volume\"\n />\n </div>\n `\n : null}\n ${this.showPin\n ? html`\n <button\n class=\"action-button ${this.isPinned ? 'active' : ''}\"\n part=\"action-button\"\n @click=${this.handleTogglePin}\n aria-label=\"${this.isPinned ? 'Unpin' : 'Pin'}\"\n aria-pressed=\"${this.isPinned}\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M16 12V4h1V2H7v2h1v8l-2 2v2h5.2v6h1.6v-6H18v-2l-2-2z\" />\n </svg>\n ${this.isPinned ? 'Unpin' : 'Pin'}\n </button>\n `\n : null}\n ${this.canRemove\n ? html`\n <button\n class=\"action-button danger\"\n part=\"action-button\"\n @click=${this.handleRemove}\n aria-label=\"Remove participant\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path\n 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\"\n />\n </svg>\n Remove\n </button>\n `\n : null}\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sw-participant-controls': ParticipantControlsComponent;\n }\n}\n"],"names":["ParticipantControlsComponent","LitElement","changedProperties","nameSub","name","audioSub","muted","videoSub","sub","error","_a","e","input","html","css","__decorateClass","property","state","customElement"],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Participants Component
3
+ *
4
+ * Renders member overlays based on layoutLayers from the call context.
5
+ * Excludes self member and provides slot for <self-media> child component.
6
+ *
7
+ * @example
8
+ * ```html
9
+ * <participants>
10
+ * <self-media mirror=${true}></self-media>
11
+ * </participants>
12
+ * ```
13
+ *
14
+ * @fires sw-participant-mute-audio - Fired to toggle a participant's audio. Detail: `{ participantId: string, muted: boolean }`
15
+ * @fires sw-participant-mute-video - Fired to toggle a participant's video. Detail: `{ participantId: string, muted: boolean }`
16
+ * @fires sw-participant-remove - Fired to remove a participant. Detail: `{ participantId: string }`
17
+ */
18
+ import { LitElement } from 'lit';
19
+ import type { Call } from '../types/index.js';
20
+ export declare class Participants extends LitElement {
21
+ static styles: import("lit").CSSResult;
22
+ /**
23
+ * Consumes call context from parent call-media component
24
+ */
25
+ private _call?;
26
+ /**
27
+ * Public call property for direct assignment (when not nested in sw-call-media)
28
+ */
29
+ set call(value: Call | undefined);
30
+ get call(): Call | undefined;
31
+ /**
32
+ * Current layout layers value from observable
33
+ */
34
+ private _layoutLayersValue;
35
+ /**
36
+ * Current participants from observable
37
+ */
38
+ private _participantsValue;
39
+ /**
40
+ * ID of participant with open menu
41
+ */
42
+ private _openMenuId;
43
+ /**
44
+ * RxJS subscriptions for cleanup
45
+ */
46
+ private subscriptions;
47
+ /**
48
+ * Lifecycle: Component connected to DOM
49
+ */
50
+ connectedCallback(): void;
51
+ /**
52
+ * Lifecycle: React to property/context changes
53
+ */
54
+ protected updated(changedProperties: Map<string, unknown>): void;
55
+ /**
56
+ * Lifecycle: Component disconnected from DOM
57
+ */
58
+ disconnectedCallback(): void;
59
+ /**
60
+ * Subscribe to call observables
61
+ */
62
+ private setupSubscriptions;
63
+ /**
64
+ * Handle click outside menu to close it
65
+ */
66
+ private _handleOutsideClick;
67
+ /**
68
+ * Toggle menu for a participant
69
+ */
70
+ private _toggleMenu;
71
+ /**
72
+ * Get participant by member ID
73
+ */
74
+ private _getParticipant;
75
+ /**
76
+ * Handle mute audio action
77
+ */
78
+ private _handleMuteAudio;
79
+ /**
80
+ * Handle mute video action
81
+ */
82
+ private _handleMuteVideo;
83
+ /**
84
+ * Handle remove participant action
85
+ */
86
+ private _handleRemove;
87
+ /**
88
+ * Cleanup all subscriptions
89
+ */
90
+ private cleanupSubscriptions;
91
+ /**
92
+ * Render member overlays for all participants
93
+ */
94
+ private renderMemberOverlays;
95
+ /**
96
+ * Render menu button SVG icon (three dots)
97
+ */
98
+ private renderMenuIcon;
99
+ /**
100
+ * Render menu dropdown for a participant
101
+ */
102
+ private renderMenuDropdown;
103
+ /**
104
+ * Render individual member overlay
105
+ */
106
+ private renderOverlay;
107
+ /**
108
+ * Render the component
109
+ */
110
+ render(): import("lit-html").TemplateResult<1>;
111
+ }
112
+ /**
113
+ * Declare global type for TypeScript
114
+ */
115
+ declare global {
116
+ interface HTMLElementTagNameMap {
117
+ 'sw-participants': Participants;
118
+ }
119
+ }
120
+ //# sourceMappingURL=participants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"participants.d.ts","sourceRoot":"","sources":["../../src/components/participants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAI5C,OAAO,KAAK,EAAE,IAAI,EAA4B,MAAM,mBAAmB,CAAC;AAIxE,qBACa,YAAa,SAAQ,UAAU;IAC1C,MAAM,CAAC,MAAM,0BAqHX;IAEF;;OAEG;IAGH,OAAO,CAAC,KAAK,CAAC,CAAO;IAErB;;OAEG;IACH,IACI,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,SAAS,EAI/B;IACD,IAAI,IAAI,IAAI,IAAI,GAAG,SAAS,CAE3B;IAED;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAqB;IAE/C;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAqB;IAE/C;;OAEG;IAEH,OAAO,CAAC,WAAW,CAAuB;IAE1C;;OAEG;IACH,OAAO,CAAC,aAAa,CAAsB;IAE3C;;OAEG;IACH,iBAAiB;IAKjB;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAUhE;;OAEG;IACH,oBAAoB;IAKpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;YACW,gBAAgB;IAwB9B;;OAEG;YACW,gBAAgB;IAwB9B;;OAEG;YACW,aAAa;IAoB3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAM5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAa5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA0D1B;;OAEG;IACH,OAAO,CAAC,aAAa;IA0CrB;;OAEG;IACH,MAAM;CAMP;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iBAAiB,EAAE,YAAY,CAAC;KACjC;CACF"}