@meshagent/meshagent-tailwind 0.41.4 → 0.41.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.
- package/CHANGELOG.md +3 -0
- package/README.md +33 -0
- package/dist/cjs/chat/chat-thread.js +15 -10
- package/dist/cjs/chat/dataset-chat-thread.d.ts +4 -1
- package/dist/cjs/chat/dataset-chat-thread.js +130 -157
- package/dist/cjs/chat/multi-thread-view.d.ts +4 -1
- package/dist/cjs/chat/multi-thread-view.js +4 -0
- package/dist/cjs/chat/new-chat-thread.d.ts +4 -1
- package/dist/cjs/chat/new-chat-thread.js +43 -87
- package/dist/cjs/file-preview/file-preview.d.ts +6 -0
- package/dist/cjs/file-preview/file-preview.js +220 -0
- package/dist/cjs/meetings/camera-grid.d.ts +46 -0
- package/dist/cjs/meetings/camera-grid.js +435 -0
- package/dist/cjs/meetings/controls.d.ts +4 -2
- package/dist/cjs/meetings/controls.js +9 -3
- package/dist/cjs/meetings/lobby.d.ts +17 -0
- package/dist/cjs/meetings/lobby.js +595 -0
- package/dist/cjs/meetings/meeting-scope.d.ts +7 -6
- package/dist/cjs/meetings/meeting-scope.js +64 -15
- package/dist/cjs/meetings/meeting-view.d.ts +6 -0
- package/dist/cjs/meetings/meeting-view.js +635 -0
- package/dist/cjs/meetings/meetings.d.ts +3 -0
- package/dist/cjs/meetings/meetings.js +3 -0
- package/dist/cjs/meetings/wake-lock.js +2 -2
- package/dist/esm/chat/chat-thread.js +15 -10
- package/dist/esm/chat/dataset-chat-thread.d.ts +4 -1
- package/dist/esm/chat/dataset-chat-thread.js +129 -133
- package/dist/esm/chat/multi-thread-view.d.ts +4 -1
- package/dist/esm/chat/multi-thread-view.js +4 -0
- package/dist/esm/chat/new-chat-thread.d.ts +4 -1
- package/dist/esm/chat/new-chat-thread.js +43 -87
- package/dist/esm/file-preview/file-preview.d.ts +6 -0
- package/dist/esm/file-preview/file-preview.js +220 -0
- package/dist/esm/meetings/camera-grid.d.ts +46 -0
- package/dist/esm/meetings/camera-grid.js +405 -0
- package/dist/esm/meetings/controls.d.ts +4 -2
- package/dist/esm/meetings/controls.js +9 -3
- package/dist/esm/meetings/lobby.d.ts +17 -0
- package/dist/esm/meetings/lobby.js +595 -0
- package/dist/esm/meetings/meeting-scope.d.ts +7 -6
- package/dist/esm/meetings/meeting-scope.js +71 -16
- package/dist/esm/meetings/meeting-view.d.ts +6 -0
- package/dist/esm/meetings/meeting-view.js +630 -0
- package/dist/esm/meetings/meetings.d.ts +3 -0
- package/dist/esm/meetings/meetings.js +3 -0
- package/dist/esm/meetings/wake-lock.js +2 -2
- package/dist/index.css +1 -1
- package/package.json +9 -5
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useMemo, useSyncExternalStore } from "react";
|
|
3
|
+
import { Track } from "livekit-client";
|
|
4
|
+
const TrackSource = {
|
|
5
|
+
Camera: Track.Source.Camera,
|
|
6
|
+
ScreenShareVideo: Track.Source.ScreenShare
|
|
7
|
+
};
|
|
8
|
+
function useParticipantsSnapshot(participants) {
|
|
9
|
+
useSyncExternalStore(
|
|
10
|
+
(listener) => {
|
|
11
|
+
const events = [
|
|
12
|
+
"trackPublished",
|
|
13
|
+
"trackSubscribed",
|
|
14
|
+
"trackUnpublished",
|
|
15
|
+
"trackUnsubscribed",
|
|
16
|
+
"trackMuted",
|
|
17
|
+
"trackUnmuted",
|
|
18
|
+
"localTrackPublished",
|
|
19
|
+
"localTrackUnpublished",
|
|
20
|
+
"participantNameChanged",
|
|
21
|
+
"isSpeakingChanged",
|
|
22
|
+
"attributesChanged"
|
|
23
|
+
];
|
|
24
|
+
for (const participant of participants) {
|
|
25
|
+
for (const eventName of events) {
|
|
26
|
+
participant.on(eventName, listener);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return () => {
|
|
30
|
+
for (const participant of participants) {
|
|
31
|
+
for (const eventName of events) {
|
|
32
|
+
participant.off(eventName, listener);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
() => participants.map(
|
|
38
|
+
(participant) => [
|
|
39
|
+
participant.sid,
|
|
40
|
+
participant.identity,
|
|
41
|
+
participant.isCameraEnabled,
|
|
42
|
+
participant.isScreenShareEnabled,
|
|
43
|
+
participant.isMicrophoneEnabled,
|
|
44
|
+
participant.isSpeaking,
|
|
45
|
+
participant.trackPublications.size,
|
|
46
|
+
participant.name ?? ""
|
|
47
|
+
].join(":")
|
|
48
|
+
).join("|"),
|
|
49
|
+
() => ""
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
function publicationAspectRatio(publication) {
|
|
53
|
+
const dimensions = publication?.dimensions ?? { width: 640, height: 480 };
|
|
54
|
+
return dimensions.height > 0 ? dimensions.width / dimensions.height : 4 / 3;
|
|
55
|
+
}
|
|
56
|
+
function layoutCameras(publications, width, height) {
|
|
57
|
+
const slots = Math.max(publications.length, 1);
|
|
58
|
+
let bestRows = 1;
|
|
59
|
+
let bestCols = slots;
|
|
60
|
+
let minWaste = Number.POSITIVE_INFINITY;
|
|
61
|
+
for (let rows = 1; rows <= slots; rows += 1) {
|
|
62
|
+
const cols = Math.ceil(slots / rows);
|
|
63
|
+
const gridAspectRatio = width / cols / (height / rows);
|
|
64
|
+
let aspectRatioWaste = 0;
|
|
65
|
+
for (const publication of publications) {
|
|
66
|
+
aspectRatioWaste += Math.abs(
|
|
67
|
+
publicationAspectRatio(publication) - gridAspectRatio
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
if (aspectRatioWaste < minWaste) {
|
|
71
|
+
minWaste = aspectRatioWaste;
|
|
72
|
+
bestRows = rows;
|
|
73
|
+
bestCols = cols;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return [bestRows, bestCols];
|
|
77
|
+
}
|
|
78
|
+
function CameraGrid({
|
|
79
|
+
participants,
|
|
80
|
+
room,
|
|
81
|
+
spacing = 0,
|
|
82
|
+
showNames = true,
|
|
83
|
+
showAllVideos = false,
|
|
84
|
+
preferredSource,
|
|
85
|
+
rowsDesired = 0,
|
|
86
|
+
columnsDesired = 0,
|
|
87
|
+
tryFill = true,
|
|
88
|
+
activeVideoPublicationForSource,
|
|
89
|
+
activeVideoPublications,
|
|
90
|
+
renderVideoTrack,
|
|
91
|
+
renderAudioStats,
|
|
92
|
+
frameBuilder
|
|
93
|
+
}) {
|
|
94
|
+
useParticipantsSnapshot(participants);
|
|
95
|
+
const items = useMemo(() => {
|
|
96
|
+
if (!room) return [];
|
|
97
|
+
const hasShare = participants.some(
|
|
98
|
+
(participant) => activeVideoPublicationForSource(
|
|
99
|
+
participant,
|
|
100
|
+
TrackSource.ScreenShareVideo
|
|
101
|
+
) != null
|
|
102
|
+
);
|
|
103
|
+
const videoSource = preferredSource ?? (hasShare ? TrackSource.ScreenShareVideo : TrackSource.Camera);
|
|
104
|
+
const shouldShowCameraPlaceholder = videoSource === TrackSource.Camera;
|
|
105
|
+
const nextItems = [];
|
|
106
|
+
for (const participant of participants) {
|
|
107
|
+
let added = false;
|
|
108
|
+
const publications = showAllVideos ? activeVideoPublications(participant) : activeVideoPublications(participant, { source: videoSource });
|
|
109
|
+
for (const publication of publications) {
|
|
110
|
+
const track = publication.videoTrack;
|
|
111
|
+
if (track == null) continue;
|
|
112
|
+
added = true;
|
|
113
|
+
nextItems.push({
|
|
114
|
+
participant,
|
|
115
|
+
publication,
|
|
116
|
+
trackNode: /* @__PURE__ */ jsx("div", { style: { pointerEvents: "none", width: "100%", height: "100%" }, children: renderVideoTrack({
|
|
117
|
+
track,
|
|
118
|
+
fit: publication.source === TrackSource.ScreenShareVideo ? "contain" : "cover",
|
|
119
|
+
publication,
|
|
120
|
+
participant
|
|
121
|
+
}) })
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (shouldShowCameraPlaceholder && !added) {
|
|
125
|
+
nextItems.push({
|
|
126
|
+
participant,
|
|
127
|
+
publication: null,
|
|
128
|
+
trackNode: /* @__PURE__ */ jsx(
|
|
129
|
+
"div",
|
|
130
|
+
{
|
|
131
|
+
style: {
|
|
132
|
+
width: "100%",
|
|
133
|
+
height: "100%",
|
|
134
|
+
background: "#222222",
|
|
135
|
+
display: "flex",
|
|
136
|
+
alignItems: "center",
|
|
137
|
+
justifyContent: "center"
|
|
138
|
+
},
|
|
139
|
+
children: participant.identity.includes(".agent") && renderAudioStats ? renderAudioStats({ room, participant }) : null
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return nextItems;
|
|
146
|
+
}, [
|
|
147
|
+
activeVideoPublicationForSource,
|
|
148
|
+
activeVideoPublications,
|
|
149
|
+
participants,
|
|
150
|
+
preferredSource,
|
|
151
|
+
renderAudioStats,
|
|
152
|
+
renderVideoTrack,
|
|
153
|
+
room,
|
|
154
|
+
showAllVideos
|
|
155
|
+
]);
|
|
156
|
+
if (!room || items.length === 0) return null;
|
|
157
|
+
return /* @__PURE__ */ jsx("div", { style: { width: "100%", height: "100%", position: "relative" }, children: /* @__PURE__ */ jsx(
|
|
158
|
+
CameraGridLayout,
|
|
159
|
+
{
|
|
160
|
+
items,
|
|
161
|
+
spacing,
|
|
162
|
+
showNames,
|
|
163
|
+
rowsDesired,
|
|
164
|
+
columnsDesired,
|
|
165
|
+
tryFill,
|
|
166
|
+
frameBuilder
|
|
167
|
+
}
|
|
168
|
+
) });
|
|
169
|
+
}
|
|
170
|
+
function CameraGridLayout({
|
|
171
|
+
items,
|
|
172
|
+
spacing,
|
|
173
|
+
showNames,
|
|
174
|
+
rowsDesired,
|
|
175
|
+
columnsDesired,
|
|
176
|
+
tryFill,
|
|
177
|
+
frameBuilder
|
|
178
|
+
}) {
|
|
179
|
+
return /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0 }, children: /* @__PURE__ */ jsx(
|
|
180
|
+
ResponsiveAbsoluteLayout,
|
|
181
|
+
{
|
|
182
|
+
items,
|
|
183
|
+
spacing,
|
|
184
|
+
showNames,
|
|
185
|
+
rowsDesired,
|
|
186
|
+
columnsDesired,
|
|
187
|
+
tryFill,
|
|
188
|
+
frameBuilder
|
|
189
|
+
}
|
|
190
|
+
) });
|
|
191
|
+
}
|
|
192
|
+
function ResponsiveAbsoluteLayout(props) {
|
|
193
|
+
const { items } = props;
|
|
194
|
+
return /* @__PURE__ */ jsx(SizeObserver, { children: ({ width, height }) => {
|
|
195
|
+
if (width <= 0 || height <= 0) return null;
|
|
196
|
+
return renderAbsoluteItems({ ...props, width, height, slots: items.length });
|
|
197
|
+
} });
|
|
198
|
+
}
|
|
199
|
+
function renderAbsoluteItems({
|
|
200
|
+
items,
|
|
201
|
+
spacing,
|
|
202
|
+
showNames,
|
|
203
|
+
rowsDesired,
|
|
204
|
+
columnsDesired,
|
|
205
|
+
tryFill,
|
|
206
|
+
frameBuilder,
|
|
207
|
+
width,
|
|
208
|
+
height,
|
|
209
|
+
slots
|
|
210
|
+
}) {
|
|
211
|
+
const positioned = [];
|
|
212
|
+
if (rowsDesired === 0 && columnsDesired === 0) {
|
|
213
|
+
const [rows, cols] = layoutCameras(
|
|
214
|
+
items.map((item) => item.publication),
|
|
215
|
+
width,
|
|
216
|
+
height
|
|
217
|
+
);
|
|
218
|
+
const availableWidth = Math.max(width - spacing * (cols - 1), 0);
|
|
219
|
+
const availableHeight = Math.max(height - spacing * (rows - 1), 0);
|
|
220
|
+
const cellWidth = availableWidth / cols;
|
|
221
|
+
const cellHeight = availableHeight / rows;
|
|
222
|
+
for (let row = 0; row < rows; row += 1) {
|
|
223
|
+
for (let col = 0; col < cols; col += 1) {
|
|
224
|
+
const index = row * cols + col;
|
|
225
|
+
const item = items[index];
|
|
226
|
+
if (!item) break;
|
|
227
|
+
positioned.push(
|
|
228
|
+
absoluteCell({
|
|
229
|
+
key: index,
|
|
230
|
+
left: col * (cellWidth + spacing),
|
|
231
|
+
top: row * (cellHeight + spacing),
|
|
232
|
+
width: cellWidth,
|
|
233
|
+
height: cellHeight,
|
|
234
|
+
item,
|
|
235
|
+
showNames,
|
|
236
|
+
frameBuilder
|
|
237
|
+
})
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return /* @__PURE__ */ jsx(Fragment, { children: positioned });
|
|
242
|
+
}
|
|
243
|
+
let x = 0;
|
|
244
|
+
let y = 0;
|
|
245
|
+
if (rowsDesired > 0 || columnsDesired > 0 || Math.min(width / height, height / width) > 0.5 || slots < 4 && tryFill) {
|
|
246
|
+
let rows;
|
|
247
|
+
let cols;
|
|
248
|
+
if (width < height) {
|
|
249
|
+
rows = Math.trunc(
|
|
250
|
+
rowsDesired > 0 ? rowsDesired : columnsDesired > 0 ? slots / columnsDesired : Math.ceil(Math.sqrt(slots))
|
|
251
|
+
);
|
|
252
|
+
cols = columnsDesired > 0 ? columnsDesired : Math.ceil(slots / rows);
|
|
253
|
+
} else {
|
|
254
|
+
cols = Math.trunc(
|
|
255
|
+
columnsDesired > 0 ? columnsDesired : rowsDesired > 0 ? slots / rowsDesired : Math.ceil(Math.sqrt(slots))
|
|
256
|
+
);
|
|
257
|
+
rows = rowsDesired > 0 ? rowsDesired : Math.ceil(slots / cols);
|
|
258
|
+
}
|
|
259
|
+
const cellWidth = width / cols + 1 - spacing * (cols - 1) / cols;
|
|
260
|
+
const cellHeight = height / rows - spacing * (rows - 1) / rows;
|
|
261
|
+
for (let row = 0; row < rows; row += 1) {
|
|
262
|
+
for (let col = 0; col < cols; col += 1) {
|
|
263
|
+
const index = col + row * cols;
|
|
264
|
+
const item = items[index];
|
|
265
|
+
if (!item) continue;
|
|
266
|
+
positioned.push(
|
|
267
|
+
absoluteCell({
|
|
268
|
+
key: index,
|
|
269
|
+
left: col * cellWidth + spacing * col,
|
|
270
|
+
top: row * cellHeight + spacing * row,
|
|
271
|
+
width: cellWidth,
|
|
272
|
+
height: cellHeight,
|
|
273
|
+
item,
|
|
274
|
+
showNames,
|
|
275
|
+
frameBuilder
|
|
276
|
+
})
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
const totalSpace = width * height;
|
|
282
|
+
let rowUsedSpace = totalSpace;
|
|
283
|
+
let rows = 1;
|
|
284
|
+
let vertRows = false;
|
|
285
|
+
for (let i = 1; i < 10; i += 0.1) {
|
|
286
|
+
const floored = Math.floor(i);
|
|
287
|
+
const itemSize = height / i;
|
|
288
|
+
const usedSpace = itemSize * itemSize * Math.max(slots, 1);
|
|
289
|
+
if (itemSize * Math.ceil(slots / floored) <= width && itemSize * floored <= height && usedSpace <= totalSpace && totalSpace - usedSpace < rowUsedSpace) {
|
|
290
|
+
rows = i;
|
|
291
|
+
rowUsedSpace = totalSpace - usedSpace;
|
|
292
|
+
vertRows = true;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
for (let i = 1; i < 10; i += 0.1) {
|
|
296
|
+
const floored = Math.floor(i);
|
|
297
|
+
const itemSize = width / i;
|
|
298
|
+
const usedSpace = itemSize * itemSize * Math.max(slots, 1);
|
|
299
|
+
if (itemSize * Math.ceil(slots / floored) <= height && itemSize * floored <= width && usedSpace <= totalSpace && totalSpace - usedSpace < rowUsedSpace) {
|
|
300
|
+
rows = i;
|
|
301
|
+
rowUsedSpace = totalSpace - usedSpace;
|
|
302
|
+
vertRows = false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (vertRows) {
|
|
306
|
+
const itemSize = (height - spacing * rows) / rows;
|
|
307
|
+
for (let index = 0; index < items.length; index += 1) {
|
|
308
|
+
const item = items[index];
|
|
309
|
+
positioned.push(
|
|
310
|
+
absoluteCell({
|
|
311
|
+
key: index,
|
|
312
|
+
left: x,
|
|
313
|
+
top: y,
|
|
314
|
+
width: itemSize,
|
|
315
|
+
height: itemSize,
|
|
316
|
+
item,
|
|
317
|
+
showNames,
|
|
318
|
+
frameBuilder
|
|
319
|
+
})
|
|
320
|
+
);
|
|
321
|
+
x += itemSize + spacing;
|
|
322
|
+
if (x + itemSize > width) {
|
|
323
|
+
x = spacing;
|
|
324
|
+
y += itemSize + spacing;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
} else {
|
|
328
|
+
const itemSize = (width - spacing * rows) / rows;
|
|
329
|
+
for (let index = 0; index < items.length; index += 1) {
|
|
330
|
+
const item = items[index];
|
|
331
|
+
positioned.push(
|
|
332
|
+
absoluteCell({
|
|
333
|
+
key: index,
|
|
334
|
+
left: x,
|
|
335
|
+
top: y,
|
|
336
|
+
width: itemSize,
|
|
337
|
+
height: itemSize,
|
|
338
|
+
item,
|
|
339
|
+
showNames,
|
|
340
|
+
frameBuilder
|
|
341
|
+
})
|
|
342
|
+
);
|
|
343
|
+
y += itemSize + spacing;
|
|
344
|
+
if (y + itemSize > height) {
|
|
345
|
+
y = spacing;
|
|
346
|
+
x += itemSize + spacing;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return /* @__PURE__ */ jsx(Fragment, { children: positioned });
|
|
352
|
+
}
|
|
353
|
+
function absoluteCell({
|
|
354
|
+
key,
|
|
355
|
+
left,
|
|
356
|
+
top,
|
|
357
|
+
width,
|
|
358
|
+
height,
|
|
359
|
+
item,
|
|
360
|
+
showNames,
|
|
361
|
+
frameBuilder
|
|
362
|
+
}) {
|
|
363
|
+
return /* @__PURE__ */ jsx(
|
|
364
|
+
"div",
|
|
365
|
+
{
|
|
366
|
+
style: {
|
|
367
|
+
position: "absolute",
|
|
368
|
+
left,
|
|
369
|
+
top,
|
|
370
|
+
width,
|
|
371
|
+
height,
|
|
372
|
+
overflow: "hidden"
|
|
373
|
+
},
|
|
374
|
+
children: frameBuilder({
|
|
375
|
+
participant: item.participant,
|
|
376
|
+
publication: item.publication,
|
|
377
|
+
trackNode: item.trackNode,
|
|
378
|
+
showName: showNames
|
|
379
|
+
})
|
|
380
|
+
},
|
|
381
|
+
key
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
function SizeObserver({ children }) {
|
|
385
|
+
const ref = React.useRef(null);
|
|
386
|
+
const [size, setSize] = React.useState({
|
|
387
|
+
width: 0,
|
|
388
|
+
height: 0
|
|
389
|
+
});
|
|
390
|
+
React.useLayoutEffect(() => {
|
|
391
|
+
const element = ref.current;
|
|
392
|
+
if (!element) return;
|
|
393
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
394
|
+
const rect = entry.contentRect;
|
|
395
|
+
setSize({ width: rect.width, height: rect.height });
|
|
396
|
+
});
|
|
397
|
+
observer.observe(element);
|
|
398
|
+
return () => observer.disconnect();
|
|
399
|
+
}, []);
|
|
400
|
+
return /* @__PURE__ */ jsx("div", { ref, className: "absolute inset-0", children: children(size) });
|
|
401
|
+
}
|
|
402
|
+
export {
|
|
403
|
+
CameraGrid,
|
|
404
|
+
TrackSource
|
|
405
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { ReactElement } from "react";
|
|
2
2
|
import { Room } from "livekit-client";
|
|
3
3
|
import { MeetingController } from "./meeting-scope";
|
|
4
|
-
export declare function MeetingControls({ controller: providedController, spacing, }: {
|
|
4
|
+
export declare function MeetingControls({ controller: providedController, onDisconnect, spacing, }: {
|
|
5
5
|
controller?: MeetingController;
|
|
6
|
+
onDisconnect?: () => void;
|
|
6
7
|
spacing?: number;
|
|
7
8
|
}): ReactElement;
|
|
8
9
|
export declare function CameraToggle({ controller }: {
|
|
@@ -11,8 +12,9 @@ export declare function CameraToggle({ controller }: {
|
|
|
11
12
|
export declare function MicToggle({ controller }: {
|
|
12
13
|
controller?: MeetingController;
|
|
13
14
|
}): ReactElement | null;
|
|
14
|
-
export declare function ConnectionButton({ controller }: {
|
|
15
|
+
export declare function ConnectionButton({ controller, onDisconnect, }: {
|
|
15
16
|
controller?: MeetingController;
|
|
17
|
+
onDisconnect?: () => void;
|
|
16
18
|
}): ReactElement;
|
|
17
19
|
export declare function ChangeSettings({ room }: {
|
|
18
20
|
room: Room;
|
|
@@ -36,6 +36,7 @@ function useControllerVersion(controller) {
|
|
|
36
36
|
}
|
|
37
37
|
function MeetingControls({
|
|
38
38
|
controller: providedController,
|
|
39
|
+
onDisconnect,
|
|
39
40
|
spacing = 5
|
|
40
41
|
}) {
|
|
41
42
|
const controller = useMeetingController(providedController);
|
|
@@ -47,7 +48,7 @@ function MeetingControls({
|
|
|
47
48
|
className: "flex flex-wrap items-center justify-center",
|
|
48
49
|
style: { gap: spacing },
|
|
49
50
|
children: [
|
|
50
|
-
/* @__PURE__ */ jsx(ConnectionButton, { controller }),
|
|
51
|
+
/* @__PURE__ */ jsx(ConnectionButton, { controller, onDisconnect }),
|
|
51
52
|
hasLocalParticipant ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
52
53
|
/* @__PURE__ */ jsx(MicToggle, { controller }),
|
|
53
54
|
/* @__PURE__ */ jsx(CameraToggle, { controller }),
|
|
@@ -166,7 +167,10 @@ function MicToggle({ controller }) {
|
|
|
166
167
|
}
|
|
167
168
|
);
|
|
168
169
|
}
|
|
169
|
-
function ConnectionButton({
|
|
170
|
+
function ConnectionButton({
|
|
171
|
+
controller,
|
|
172
|
+
onDisconnect
|
|
173
|
+
}) {
|
|
170
174
|
const resolvedController = useMeetingController(controller);
|
|
171
175
|
useControllerVersion(resolvedController);
|
|
172
176
|
const state = resolvedController.livekitRoom.state;
|
|
@@ -178,7 +182,9 @@ function ConnectionButton({ controller }) {
|
|
|
178
182
|
destructive: true,
|
|
179
183
|
icon: /* @__PURE__ */ jsx(Phone, {}),
|
|
180
184
|
onClick: () => {
|
|
181
|
-
void resolvedController.disconnect()
|
|
185
|
+
void resolvedController.disconnect().catch((error) => {
|
|
186
|
+
console.warn("unable to disconnect meeting", error);
|
|
187
|
+
}).finally(() => onDisconnect?.());
|
|
182
188
|
}
|
|
183
189
|
}
|
|
184
190
|
);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
import { type MeetingController, type MeetingFastConnectOptions } from "./meeting-scope";
|
|
3
|
+
export interface MeetingLobbyJoinOptions {
|
|
4
|
+
enableVideo: boolean;
|
|
5
|
+
enableAudio: boolean;
|
|
6
|
+
videoUnavailable: boolean;
|
|
7
|
+
audioUnavailable: boolean;
|
|
8
|
+
videoDeviceId?: string;
|
|
9
|
+
audioDeviceId?: string;
|
|
10
|
+
audioOutputDeviceId?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function meetingFastConnectOptions(options: MeetingLobbyJoinOptions): MeetingFastConnectOptions;
|
|
13
|
+
export declare function MeetingLobby({ controller: providedController, onCancel, onJoin, }: {
|
|
14
|
+
controller?: MeetingController;
|
|
15
|
+
onCancel?: () => void;
|
|
16
|
+
onJoin?: (options: MeetingLobbyJoinOptions) => void | Promise<void>;
|
|
17
|
+
}): ReactElement;
|