voicebot-react-native-expo
Version:
This is a voicebot-react-native package of Kipps AI voice bot for React Native Expo
564 lines (563 loc) • 22.4 kB
JavaScript
import * as e from "react";
import { C as K, S as re, c as oe, a as ue, M as B, w as le, b as de, T as R, m as G, d as me, e as fe, D as J, f as he, g as H, L as Q, G as pe, P as z, F as ge, h as ve, i as Ee, R as Se, j as ke, k as be, l as Ce, B as we } from "./components-Y1IPllFz.mjs";
import { w as Ie, x as ye, y as x, z as Me, A as X, t as Y, B as Ne, C as Pe } from "./hooks-C6T19zG6.mjs";
import { j as Z, an as Te, ao as De, l as P, ap as Le, a as Ae, aq as Re, ar as Ve, a1 as q, as as Oe, at as $e } from "./contexts-BggYqn0S.mjs";
import { Mutex as Ue, createLocalTracks as _e, Track as y, facingModeFromLocalTrack as Fe, createLocalVideoTrack as Be, VideoPresets as qe, createLocalAudioTrack as xe, RoomEvent as We } from "livekit-client";
import { m as je } from "./room-BeQGUa5w.mjs";
function ee({
messageFormatter: a,
messageDecoder: l,
messageEncoder: i,
channelTopic: c,
...E
}) {
const p = e.useRef(null), m = e.useRef(null), u = e.useMemo(() => ({ messageDecoder: l, messageEncoder: i, channelTopic: c }), [l, i, c]), { send: d, chatMessages: g, isSending: t } = Ie(u), r = Z(), o = e.useRef(0);
async function S(n) {
n.preventDefault(), p.current && p.current.value.trim() !== "" && d && (await d(p.current.value), p.current.value = "", p.current.focus());
}
return e.useEffect(() => {
var n;
m && ((n = m.current) == null || n.scrollTo({ top: m.current.scrollHeight }));
}, [m, g]), e.useEffect(() => {
var s, v, f, b, w;
if (!r || g.length === 0)
return;
if ((s = r.widget.state) != null && s.showChat && g.length > 0 && o.current !== ((v = g[g.length - 1]) == null ? void 0 : v.timestamp)) {
o.current = (f = g[g.length - 1]) == null ? void 0 : f.timestamp;
return;
}
const n = g.filter(
(L) => !o.current || L.timestamp > o.current
).length, { widget: h } = r;
n > 0 && ((b = h.state) == null ? void 0 : b.unreadMessages) !== n && ((w = h.dispatch) == null || w.call(h, { msg: "unread_msg", count: n }));
}, [g, r == null ? void 0 : r.widget]), /* @__PURE__ */ e.createElement("div", { ...E, className: "lk-chat" }, /* @__PURE__ */ e.createElement("div", { className: "lk-chat-header" }, "Messages", /* @__PURE__ */ e.createElement(K, { className: "lk-close-button" }, /* @__PURE__ */ e.createElement(re, null))), /* @__PURE__ */ e.createElement("ul", { className: "lk-list lk-chat-messages", ref: m }, E.children ? g.map(
(n, h) => oe(E.children, {
entry: n,
key: n.id ?? h,
messageFormatter: a
})
) : g.map((n, h, s) => {
const v = h >= 1 && s[h - 1].from === n.from, f = h >= 1 && n.timestamp - s[h - 1].timestamp < 6e4;
return /* @__PURE__ */ e.createElement(
ue,
{
key: n.id ?? h,
hideName: v,
hideTimestamp: v === !1 ? !1 : f,
entry: n,
messageFormatter: a
}
);
})), /* @__PURE__ */ e.createElement("form", { className: "lk-chat-form", onSubmit: S }, /* @__PURE__ */ e.createElement(
"input",
{
className: "lk-form-control lk-chat-form-input",
disabled: t,
ref: p,
type: "text",
placeholder: "Enter a message...",
onInput: (n) => n.stopPropagation(),
onKeyDown: (n) => n.stopPropagation(),
onKeyUp: (n) => n.stopPropagation()
}
), /* @__PURE__ */ e.createElement("button", { type: "submit", className: "lk-button lk-chat-form-button", disabled: t }, "Send")));
}
function O({
kind: a,
initialSelection: l,
onActiveDeviceChange: i,
tracks: c,
requestPermissions: E = !1,
...p
}) {
const [m, u] = e.useState(!1), [d, g] = e.useState([]), [t, r] = e.useState(!0), [o, S] = e.useState(E), n = (f, b) => {
P.debug("handle device change"), u(!1), i == null || i(f, b);
}, h = e.useRef(null), s = e.useRef(null);
e.useLayoutEffect(() => {
m && S(!0);
}, [m]), e.useLayoutEffect(() => {
h.current && s.current && (d || t) && Te(h.current, s.current).then(({ x: f, y: b }) => {
s.current && Object.assign(s.current.style, { left: `${f}px`, top: `${b}px` });
}), r(!1);
}, [h, s, d, t]);
const v = e.useCallback(
(f) => {
s.current && f.target !== h.current && m && De(s.current, f) && u(!1);
},
[m, s, h]
);
return e.useEffect(() => (document.addEventListener("click", v), window.addEventListener("resize", () => r(!0)), () => {
document.removeEventListener("click", v), window.removeEventListener("resize", () => r(!0));
}), [v, r]), /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(
"button",
{
className: "lk-button lk-button-menu",
"aria-pressed": m,
...p,
onClick: () => u(!m),
ref: h
},
p.children
), !p.disabled && /* @__PURE__ */ e.createElement(
"div",
{
className: "lk-device-menu",
ref: s,
style: { visibility: m ? "visible" : "hidden" }
},
a ? /* @__PURE__ */ e.createElement(
B,
{
initialSelection: l,
onActiveDeviceChange: (f) => n(a, f),
onDeviceListChange: g,
kind: a,
track: c == null ? void 0 : c[a],
requestPermissions: o
}
) : /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement("div", { className: "lk-device-menu-heading" }, "Audio inputs"), /* @__PURE__ */ e.createElement(
B,
{
kind: "audioinput",
onActiveDeviceChange: (f) => n("audioinput", f),
onDeviceListChange: g,
track: c == null ? void 0 : c.audioinput,
requestPermissions: o
}
), /* @__PURE__ */ e.createElement("div", { className: "lk-device-menu-heading" }, "Video inputs"), /* @__PURE__ */ e.createElement(
B,
{
kind: "videoinput",
onActiveDeviceChange: (f) => n("videoinput", f),
onDeviceListChange: g,
track: c == null ? void 0 : c.videoinput,
requestPermissions: o
}
))
));
}
function W() {
e.useEffect(() => {
le();
}, []);
}
function ze(a, l) {
const [i, c] = e.useState(), E = e.useMemo(() => new Ue(), []);
return e.useEffect(() => {
let p = !1, m = [];
return E.lock().then(async (u) => {
try {
(a.audio || a.video) && (m = await _e(a), p ? m.forEach((d) => d.stop()) : c(m));
} catch (d) {
l && d instanceof Error ? l(d) : P.error(d);
} finally {
u();
}
}), () => {
p = !0, m.forEach((u) => {
u.stop();
});
};
}, [JSON.stringify(a), l, E]), i;
}
function Ze(a, l, i) {
const [c, E] = e.useState(null), [p, m] = e.useState(!1), u = ye({ kind: i }), [d, g] = e.useState(
void 0
), [t, r] = e.useState(), [o, S] = e.useState(l);
e.useEffect(() => {
S(l);
}, [l]);
const n = async (v, f) => {
try {
const b = f === "videoinput" ? await Be({
deviceId: v,
resolution: qe.h720.resolution
}) : await xe({ deviceId: v }), w = await b.getDeviceId();
w && v !== w && (s.current = w, S(w)), r(b);
} catch (b) {
b instanceof Error && E(b);
}
}, h = async (v, f) => {
await v.setDeviceId(f), s.current = f;
}, s = e.useRef(o);
return e.useEffect(() => {
a && !t && !c && !p && (P.debug("creating track", i), m(!0), n(o, i).finally(() => {
m(!1);
}));
}, [a, t, c, p]), e.useEffect(() => {
t && (a ? d != null && d.deviceId && s.current !== (d == null ? void 0 : d.deviceId) ? (P.debug(`switching ${i} device from`, s.current, d.deviceId), h(t, d.deviceId)) : (P.debug(`unmuting local ${i} track`), t.unmute()) : (P.debug(`muting ${i} track`), t.mute().then(() => P.debug(t.mediaStreamTrack))));
}, [t, d, a, i]), e.useEffect(() => () => {
t && (P.debug(`stopping local ${i} track`), t.stop(), t.mute());
}, []), e.useEffect(() => {
g(u == null ? void 0 : u.find((v) => v.deviceId === o));
}, [o, u]), {
selectedDevice: d,
localTrack: t,
deviceError: c
};
}
function et({
defaults: a = {},
onValidate: l,
onSubmit: i,
onError: c,
debug: E,
joinLabel: p = "Join Room",
micLabel: m = "Microphone",
camLabel: u = "Camera",
userLabel: d = "Username",
persistUserChoices: g = !0,
...t
}) {
const [r, o] = e.useState(Le), S = {
...a.audioDeviceId !== void 0 && { audioDeviceId: a.audioDeviceId },
...a.videoDeviceId !== void 0 && { videoDeviceId: a.videoDeviceId },
...a.audioEnabled !== void 0 && { audioEnabled: a.audioEnabled },
...a.videoEnabled !== void 0 && { videoEnabled: a.videoEnabled },
...a.username !== void 0 && { username: a.username }
}, {
userChoices: n,
saveAudioInputDeviceId: h,
saveAudioInputEnabled: s,
saveVideoInputDeviceId: v,
saveVideoInputEnabled: f,
saveUsername: b
} = x({
defaults: S,
preventSave: !g,
preventLoad: !g
}), [w, L] = e.useState(n.audioEnabled), [I, D] = e.useState(n.videoEnabled), [T, $] = e.useState(
n.audioDeviceId
), [k, N] = e.useState(
n.videoDeviceId
), [V, ae] = e.useState(n.username);
e.useEffect(() => {
s(w);
}, [w, s]), e.useEffect(() => {
f(I);
}, [I, f]), e.useEffect(() => {
h(T);
}, [T, h]), e.useEffect(() => {
v(k);
}, [k, v]), e.useEffect(() => {
b(V);
}, [V, b]);
const A = ze(
{
audio: w ? { deviceId: n.audioDeviceId } : !1,
video: I ? { deviceId: n.videoDeviceId } : !1
},
c
), U = e.useRef(null), M = e.useMemo(
() => A == null ? void 0 : A.filter((C) => C.kind === y.Kind.Video)[0],
[A]
), ne = e.useMemo(() => {
if (M) {
const { facingMode: C } = Fe(M);
return C;
} else
return "undefined";
}, [M]), j = e.useMemo(
() => A == null ? void 0 : A.filter((C) => C.kind === y.Kind.Audio)[0],
[A]
);
e.useEffect(() => (U.current && M && (M.unmute(), M.attach(U.current)), () => {
M == null || M.detach();
}), [M]);
const [ce, se] = e.useState(), _ = e.useCallback(
(C) => typeof l == "function" ? l(C) : C.username !== "",
[l]
);
e.useEffect(() => {
const C = {
username: V,
videoEnabled: I,
videoDeviceId: k,
audioEnabled: w,
audioDeviceId: T
};
o(C), se(_(C));
}, [V, I, _, w, T, k]);
function ie(C) {
C.preventDefault(), _(r) ? typeof i == "function" && i(r) : P.warn("Validation failed with: ", r);
}
return W(), /* @__PURE__ */ e.createElement("div", { className: "lk-prejoin", ...t }, /* @__PURE__ */ e.createElement("div", { className: "lk-video-container" }, M && /* @__PURE__ */ e.createElement("video", { ref: U, width: "1280", height: "720", "data-lk-facing-mode": ne }), (!M || !I) && /* @__PURE__ */ e.createElement("div", { className: "lk-camera-off-note" }, /* @__PURE__ */ e.createElement(de, null))), /* @__PURE__ */ e.createElement("div", { className: "lk-button-group-container" }, /* @__PURE__ */ e.createElement("div", { className: "lk-button-group audio" }, /* @__PURE__ */ e.createElement(
R,
{
initialState: w,
source: y.Source.Microphone,
onChange: (C) => L(C)
},
m
), /* @__PURE__ */ e.createElement("div", { className: "lk-button-group-menu" }, /* @__PURE__ */ e.createElement(
O,
{
initialSelection: T,
kind: "audioinput",
disabled: !j,
tracks: { audioinput: j },
onActiveDeviceChange: (C, F) => $(F)
}
))), /* @__PURE__ */ e.createElement("div", { className: "lk-button-group video" }, /* @__PURE__ */ e.createElement(
R,
{
initialState: I,
source: y.Source.Camera,
onChange: (C) => D(C)
},
u
), /* @__PURE__ */ e.createElement("div", { className: "lk-button-group-menu" }, /* @__PURE__ */ e.createElement(
O,
{
initialSelection: k,
kind: "videoinput",
disabled: !M,
tracks: { videoinput: M },
onActiveDeviceChange: (C, F) => N(F)
}
)))), /* @__PURE__ */ e.createElement("form", { className: "lk-username-container" }, /* @__PURE__ */ e.createElement(
"input",
{
className: "lk-form-control",
id: "username",
name: "username",
type: "text",
defaultValue: V,
placeholder: d,
onChange: (C) => ae(C.target.value),
autoComplete: "off"
}
), /* @__PURE__ */ e.createElement(
"button",
{
className: "lk-button lk-join-button",
type: "submit",
onClick: ie,
disabled: !ce
},
p
)), E && /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement("strong", null, "User Choices:"), /* @__PURE__ */ e.createElement("ul", { className: "lk-list", style: { overflow: "hidden", maxWidth: "15rem" } }, /* @__PURE__ */ e.createElement("li", null, "Username: ", `${r.username}`), /* @__PURE__ */ e.createElement("li", null, "Video Enabled: ", `${r.videoEnabled}`), /* @__PURE__ */ e.createElement("li", null, "Audio Enabled: ", `${r.audioEnabled}`), /* @__PURE__ */ e.createElement("li", null, "Video Device: ", `${r.videoDeviceId}`), /* @__PURE__ */ e.createElement("li", null, "Audio Device: ", `${r.audioDeviceId}`))));
}
function Ke({ props: a }) {
const { dispatch: l, state: i } = Ae().widget, c = "lk-button lk-settings-toggle";
return { mergedProps: e.useMemo(() => je(a, {
className: c,
onClick: () => {
l && l({ msg: "toggle_settings" });
},
"aria-pressed": i != null && i.showSettings ? "true" : "false"
}), [a, c, l, i]) };
}
const Ge = /* @__PURE__ */ e.forwardRef(
function(l, i) {
const { mergedProps: c } = Ke({ props: l });
return /* @__PURE__ */ e.createElement("button", { ref: i, ...c }, l.children);
}
);
function te({
variation: a,
controls: l,
saveUserChoices: i = !0,
onDeviceError: c,
...E
}) {
var $;
const [p, m] = e.useState(!1), u = Z();
e.useEffect(() => {
var k, N;
((k = u == null ? void 0 : u.widget.state) == null ? void 0 : k.showChat) !== void 0 && m((N = u == null ? void 0 : u.widget.state) == null ? void 0 : N.showChat);
}, [($ = u == null ? void 0 : u.widget.state) == null ? void 0 : $.showChat]);
const g = Me(`(max-width: ${p ? 1e3 : 760}px)`) ? "minimal" : "verbose";
a ?? (a = g);
const t = { leave: !0, ...l }, r = X();
r ? (t.camera ?? (t.camera = r.canPublish), t.microphone ?? (t.microphone = r.canPublish), t.screenShare ?? (t.screenShare = r.canPublish), t.chat ?? (t.chat = r.canPublishData && (l == null ? void 0 : l.chat))) : (t.camera = !1, t.chat = !1, t.microphone = !1, t.screenShare = !1);
const o = e.useMemo(
() => a === "minimal" || a === "verbose",
[a]
), S = e.useMemo(
() => a === "textOnly" || a === "verbose",
[a]
), n = Re(), [h, s] = e.useState(!1), v = e.useCallback(
(k) => {
s(k);
},
[s]
), f = G({ className: "lk-control-bar" }, E), {
saveAudioInputEnabled: b,
saveVideoInputEnabled: w,
saveAudioInputDeviceId: L,
saveVideoInputDeviceId: I
} = x({ preventSave: !i }), D = e.useCallback(
(k, N) => N ? b(k) : null,
[b]
), T = e.useCallback(
(k, N) => N ? w(k) : null,
[w]
);
return /* @__PURE__ */ e.createElement("div", { ...f }, t.microphone && /* @__PURE__ */ e.createElement("div", { className: "lk-button-group" }, /* @__PURE__ */ e.createElement(
R,
{
source: y.Source.Microphone,
showIcon: o,
onChange: D,
onDeviceError: (k) => c == null ? void 0 : c({ source: y.Source.Microphone, error: k })
},
S && "Microphone"
), /* @__PURE__ */ e.createElement("div", { className: "lk-button-group-menu" }, /* @__PURE__ */ e.createElement(
O,
{
kind: "audioinput",
onActiveDeviceChange: (k, N) => L(N ?? "")
}
))), t.camera && /* @__PURE__ */ e.createElement("div", { className: "lk-button-group" }, /* @__PURE__ */ e.createElement(
R,
{
source: y.Source.Camera,
showIcon: o,
onChange: T,
onDeviceError: (k) => c == null ? void 0 : c({ source: y.Source.Camera, error: k })
},
S && "Camera"
), /* @__PURE__ */ e.createElement("div", { className: "lk-button-group-menu" }, /* @__PURE__ */ e.createElement(
O,
{
kind: "videoinput",
onActiveDeviceChange: (k, N) => I(N ?? "")
}
))), t.screenShare && n && /* @__PURE__ */ e.createElement(
R,
{
source: y.Source.ScreenShare,
captureOptions: { audio: !0, selfBrowserSurface: "include" },
showIcon: o,
onChange: v,
onDeviceError: (k) => c == null ? void 0 : c({ source: y.Source.ScreenShare, error: k })
},
S && (h ? "Stop screen share" : "Share screen")
), t.chat && /* @__PURE__ */ e.createElement(K, null, o && /* @__PURE__ */ e.createElement(me, null), S && "Chat"), t.settings && /* @__PURE__ */ e.createElement(Ge, null, o && /* @__PURE__ */ e.createElement(fe, null), S && "Settings"), t.leave && /* @__PURE__ */ e.createElement(J, null, o && /* @__PURE__ */ e.createElement(he, null), S && "Leave"), /* @__PURE__ */ e.createElement(H, null));
}
function tt({
chatMessageFormatter: a,
chatMessageDecoder: l,
chatMessageEncoder: i,
SettingsComponent: c,
...E
}) {
var n, h;
const [p, m] = e.useState({
showChat: !1,
unreadMessages: 0,
showSettings: !1
}), u = e.useRef(null), d = Y(
[
{ source: y.Source.Camera, withPlaceholder: !0 },
{ source: y.Source.ScreenShare, withPlaceholder: !1 }
],
{ updateOnlyOn: [We.ActiveSpeakersChanged], onlySubscribed: !1 }
), g = (s) => {
P.debug("updating widget state", s), m(s);
}, t = Ve(), r = d.filter(q).filter((s) => s.publication.source === y.Source.ScreenShare), o = (n = Ne(t)) == null ? void 0 : n[0], S = d.filter((s) => !Oe(s, o));
return e.useEffect(() => {
var s, v, f, b, w, L;
if (r.some((I) => I.publication.isSubscribed) && u.current === null ? (P.debug("Auto set screen share focus:", { newScreenShareTrack: r[0] }), (v = (s = t.pin).dispatch) == null || v.call(s, { msg: "set_pin", trackReference: r[0] }), u.current = r[0]) : u.current && !r.some(
(I) => {
var D, T;
return I.publication.trackSid === ((T = (D = u.current) == null ? void 0 : D.publication) == null ? void 0 : T.trackSid);
}
) && (P.debug("Auto clearing screen share focus."), (b = (f = t.pin).dispatch) == null || b.call(f, { msg: "clear_pin" }), u.current = null), o && !q(o)) {
const I = d.find(
(D) => D.participant.identity === o.participant.identity && D.source === o.source
);
I !== o && q(I) && ((L = (w = t.pin).dispatch) == null || L.call(w, { msg: "set_pin", trackReference: I }));
}
}, [
r.map((s) => `${s.publication.trackSid}_${s.publication.isSubscribed}`).join(),
(h = o == null ? void 0 : o.publication) == null ? void 0 : h.trackSid,
d
]), W(), /* @__PURE__ */ e.createElement("div", { className: "lk-video-conference", ...E }, $e() && /* @__PURE__ */ e.createElement(
Q,
{
value: t,
onWidgetChange: g
},
/* @__PURE__ */ e.createElement("div", { className: "lk-video-conference-inner" }, o ? /* @__PURE__ */ e.createElement("div", { className: "lk-focus-layout-wrapper" }, /* @__PURE__ */ e.createElement(ge, null, /* @__PURE__ */ e.createElement(ve, { tracks: S }, /* @__PURE__ */ e.createElement(z, null)), o && /* @__PURE__ */ e.createElement(Ee, { trackRef: o }))) : /* @__PURE__ */ e.createElement("div", { className: "lk-grid-layout-wrapper" }, /* @__PURE__ */ e.createElement(pe, { tracks: d }, /* @__PURE__ */ e.createElement(z, null))), /* @__PURE__ */ e.createElement(te, { controls: { chat: !0, settings: !!c } })),
/* @__PURE__ */ e.createElement(
ee,
{
style: { display: p.showChat ? "grid" : "none" },
messageFormatter: a,
messageEncoder: i,
messageDecoder: l
}
),
c && /* @__PURE__ */ e.createElement(
"div",
{
className: "lk-settings-menu-modal",
style: { display: p.showSettings ? "block" : "none" }
},
/* @__PURE__ */ e.createElement(c, null)
)
), /* @__PURE__ */ e.createElement(Se, null), /* @__PURE__ */ e.createElement(ke, null));
}
function at({ ...a }) {
const [l, i] = e.useState({
showChat: !1,
unreadMessages: 0
}), c = Y([y.Source.Microphone]);
return W(), /* @__PURE__ */ e.createElement(Q, { onWidgetChange: i }, /* @__PURE__ */ e.createElement("div", { className: "lk-audio-conference", ...a }, /* @__PURE__ */ e.createElement("div", { className: "lk-audio-conference-stage" }, /* @__PURE__ */ e.createElement(be, { tracks: c }, /* @__PURE__ */ e.createElement(Ce, null))), /* @__PURE__ */ e.createElement(
te,
{
controls: { microphone: !0, screenShare: !1, camera: !1, chat: !0 }
}
), l.showChat && /* @__PURE__ */ e.createElement(ee, null)));
}
function nt({
controls: a,
saveUserChoices: l = !0,
onDeviceError: i,
...c
}) {
const E = { leave: !0, microphone: !0, ...a }, p = X(), { microphoneTrack: m, localParticipant: u } = Pe(), d = e.useMemo(() => ({
participant: u,
source: y.Source.Microphone,
publication: m
}), [u, m]);
p ? E.microphone ?? (E.microphone = p.canPublish) : E.microphone = !1;
const g = G({ className: "lk-agent-control-bar" }, c), { saveAudioInputEnabled: t, saveAudioInputDeviceId: r } = x({
preventSave: !l
}), o = e.useCallback(
(S, n) => {
n && t(S);
},
[t]
);
return /* @__PURE__ */ e.createElement("div", { ...g }, E.microphone && /* @__PURE__ */ e.createElement("div", { className: "lk-button-group" }, /* @__PURE__ */ e.createElement(
R,
{
source: y.Source.Microphone,
showIcon: !0,
onChange: o,
onDeviceError: (S) => i == null ? void 0 : i({ source: y.Source.Microphone, error: S })
},
/* @__PURE__ */ e.createElement(we, { trackRef: d, barCount: 7, options: { minHeight: 5 } })
), /* @__PURE__ */ e.createElement("div", { className: "lk-button-group-menu" }, /* @__PURE__ */ e.createElement(
O,
{
kind: "audioinput",
onActiveDeviceChange: (S, n) => r(n ?? "")
}
))), E.leave && /* @__PURE__ */ e.createElement(J, null, "Disconnect"), /* @__PURE__ */ e.createElement(H, null));
}
export {
at as AudioConference,
ee as Chat,
te as ControlBar,
O as MediaDeviceMenu,
et as PreJoin,
tt as VideoConference,
nt as VoiceAssistantControlBar,
Ze as usePreviewDevice,
ze as usePreviewTracks
};
//# sourceMappingURL=prefabs.mjs.map