@whereby.com/browser-sdk 3.31.2 → 3.33.0

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.
@@ -172,7 +172,7 @@ const VideoView = React__namespace.forwardRef((_a, ref) => {
172
172
  });
173
173
  VideoView.displayName = "VideoView";
174
174
 
175
- const browserSdkVersion = "3.31.2";
175
+ const browserSdkVersion = "3.33.0";
176
176
 
177
177
  const initialState$1 = {
178
178
  chatMessages: [],
@@ -199,10 +199,19 @@ const initialState$1 = {
199
199
  participantsInCurrentGroup: [],
200
200
  broadcastingParticipants: [],
201
201
  },
202
+ isAudioOnlyModeEnabled: false,
202
203
  isCameraEnabled: false,
203
204
  isMicrophoneEnabled: false,
204
205
  localParticipant: undefined,
205
206
  remoteParticipants: [],
207
+ roomIntegrations: {
208
+ hasFetched: false,
209
+ isFetching: false,
210
+ error: null,
211
+ embeddable: [],
212
+ enabled: [],
213
+ running: [],
214
+ },
206
215
  screenshares: [],
207
216
  connectionStatus: "ready",
208
217
  connectionError: null,
@@ -264,6 +273,7 @@ function useRoomConnection(roomUrl, roomConnectionOptions = defaultRoomConnectio
264
273
  const toggleMicrophone = React__namespace.useCallback((enabled) => client.toggleMicrophone(enabled), [client]);
265
274
  const toggleHdMode = React__namespace.useCallback((enabled) => client.toggleHdMode(enabled), [client]);
266
275
  const toggleLowDataMode = React__namespace.useCallback((enabled) => client.toggleLowDataMode(enabled), [client]);
276
+ const toggleAudioOnlyMode = React__namespace.useCallback((enabled, options) => client.toggleAudioOnlyMode(enabled, options), [client]);
267
277
  const toggleWidescreenMode = React__namespace.useCallback((enabled) => client.toggleWidescreenMode(enabled), [client]);
268
278
  const toggleRaiseHand = React__namespace.useCallback((enabled) => client.toggleRaiseHand(enabled), [client]);
269
279
  const askToSpeak = React__namespace.useCallback((participantId) => client.askToSpeak(participantId), [client]);
@@ -289,6 +299,9 @@ function useRoomConnection(roomUrl, roomConnectionOptions = defaultRoomConnectio
289
299
  const endMeeting = React__namespace.useCallback((stayBehind) => client.endMeeting(stayBehind), [client]);
290
300
  const joinBreakoutGroup = React__namespace.useCallback((group) => client.joinBreakoutGroup(group), [client]);
291
301
  const joinBreakoutMainRoom = React__namespace.useCallback(() => client.joinBreakoutMainRoom(), [client]);
302
+ const startRoomIntegration = React__namespace.useCallback((options) => client.startRoomIntegration(options), [client]);
303
+ const stopRoomIntegration = React__namespace.useCallback((options) => client.stopRoomIntegration(options), [client]);
304
+ const updateRoomIntegrationProps = React__namespace.useCallback((options) => client.updateRoomIntegrationProps(options), [client]);
292
305
  const startBreakoutSession = React__namespace.useCallback((options) => client.startBreakoutSession(options), [client]);
293
306
  const updateBreakoutSession = React__namespace.useCallback((options) => client.updateBreakoutSession(options), [client]);
294
307
  const stopBreakoutSession = React__namespace.useCallback(() => client.stopBreakoutSession(), [client]);
@@ -354,11 +367,15 @@ function useRoomConnection(roomUrl, roomConnectionOptions = defaultRoomConnectio
354
367
  toggleRaiseHand,
355
368
  toggleHdMode,
356
369
  toggleLowDataMode,
370
+ toggleAudioOnlyMode,
357
371
  toggleWidescreenMode,
358
372
  spotlightParticipant,
359
373
  removeSpotlight,
360
374
  joinBreakoutGroup,
361
375
  joinBreakoutMainRoom,
376
+ startRoomIntegration,
377
+ stopRoomIntegration,
378
+ updateRoomIntegrationProps,
362
379
  startBreakoutSession,
363
380
  updateBreakoutSession,
364
381
  stopBreakoutSession,
@@ -555,6 +572,9 @@ function VideoCell(_a) {
555
572
  React__namespace.createElement("div", Object.assign({ style: contentStyle }, rest), React__namespace.cloneElement(children, { contentWidth, contentHeight, withRoundedCorners, withShadow }))));
556
573
  }
557
574
 
575
+ const IntegrationCell = ({ cellId, children, isHiddenCell = false }) => (React__namespace.createElement("div", { "data-cell-id": cellId, "aria-hidden": isHiddenCell || undefined, style: { height: "100%", width: "100%" } }, children));
576
+ IntegrationCell.displayName = "IntegrationCell";
577
+
558
578
  function generateStylesFromFrame({ origin, bounds }) {
559
579
  return {
560
580
  top: Math.round(origin.top),
@@ -570,7 +590,10 @@ function renderVideoCell({ cell, child, clientId, style = {}, withRoundedCorners
570
590
  function renderSubgridVideoCells({ content, stageLayout, withRoundedCorners, withShadow, }) {
571
591
  const cells = stageLayout.subgrid.cells;
572
592
  return content.map((child, index) => {
573
- var _a, _b, _c, _d;
593
+ var _a, _b, _c, _d, _e;
594
+ if (!child) {
595
+ return null;
596
+ }
574
597
  const cell = cells[index];
575
598
  const style = { height: Math.round(cell.bounds.height), width: Math.round(cell.bounds.width), transform: "" };
576
599
  const origin = {
@@ -578,9 +601,9 @@ function renderSubgridVideoCells({ content, stageLayout, withRoundedCorners, wit
578
601
  left: stageLayout.subgrid.origin.left + cell.origin.left,
579
602
  };
580
603
  style.transform = `translate3d(${Math.round(origin.left)}px, ${Math.round(origin.top)}px, 0)`;
581
- const clientId = (_b = (_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.participant) === null || _b === void 0 ? void 0 : _b.id;
582
- const leftPaddings = ((_c = cell.paddings) === null || _c === void 0 ? void 0 : _c.left) || 0;
583
- const rightPaddings = ((_d = cell.paddings) === null || _d === void 0 ? void 0 : _d.right) || 0;
604
+ const clientId = ((_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.cellId) || ((_c = (_b = child === null || child === void 0 ? void 0 : child.props) === null || _b === void 0 ? void 0 : _b.participant) === null || _c === void 0 ? void 0 : _c.id);
605
+ const leftPaddings = ((_d = cell.paddings) === null || _d === void 0 ? void 0 : _d.left) || 0;
606
+ const rightPaddings = ((_e = cell.paddings) === null || _e === void 0 ? void 0 : _e.right) || 0;
584
607
  const childWithProps = React__namespace.cloneElement(child, {
585
608
  avatarSize: cell.bounds.width - leftPaddings - rightPaddings,
586
609
  canZoom: false,
@@ -604,8 +627,8 @@ function renderPresentationGridVideoCells({ content, isConstrained, stageLayout,
604
627
  var _a;
605
628
  const cells = ((_a = stageLayout.presentationGrid) === null || _a === void 0 ? void 0 : _a.cells) || [];
606
629
  return content.map((child, index) => {
607
- var _a, _b;
608
- if (!stageLayout.presentationGrid) {
630
+ var _a, _b, _c, _d;
631
+ if (!child || !stageLayout.presentationGrid) {
609
632
  return null;
610
633
  }
611
634
  const cell = cells[index];
@@ -620,10 +643,10 @@ function renderPresentationGridVideoCells({ content, isConstrained, stageLayout,
620
643
  height: Math.round(cell.bounds.height),
621
644
  transform: `translate3d(${Math.round(origin.left)}px, ${Math.round(origin.top)}px, 0)`,
622
645
  };
623
- const clientId = (_b = (_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.participant) === null || _b === void 0 ? void 0 : _b.id;
646
+ const clientId = ((_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.cellId) || ((_c = (_b = child === null || child === void 0 ? void 0 : child.props) === null || _b === void 0 ? void 0 : _b.participant) === null || _c === void 0 ? void 0 : _c.id);
624
647
  const childWithProps = React__namespace.cloneElement(child, {
625
648
  isSmallCell: cell.isSmallCell,
626
- isZoomedByDefault: !!isConstrained && !(child === null || child === void 0 ? void 0 : child.props.participant.isPresentation),
649
+ isZoomedByDefault: !!isConstrained && !!((_d = child === null || child === void 0 ? void 0 : child.props) === null || _d === void 0 ? void 0 : _d.participant) && !child.props.participant.isPresentation,
627
650
  canZoom: !!isConstrained,
628
651
  key: clientId || `presentation-${index}`,
629
652
  });
@@ -641,8 +664,8 @@ function renderGridVideoCells({ content, isConstrained, stageLayout, withRounded
641
664
  var _a;
642
665
  const cells = ((_a = stageLayout.videoGrid) === null || _a === void 0 ? void 0 : _a.cells) || [];
643
666
  const gridVideoCells = content.map((child, index) => {
644
- var _a, _b;
645
- if (!stageLayout.videoGrid) {
667
+ var _a, _b, _c, _d;
668
+ if (!child || !stageLayout.videoGrid) {
646
669
  return null;
647
670
  }
648
671
  const cell = cells[index];
@@ -655,10 +678,10 @@ function renderGridVideoCells({ content, isConstrained, stageLayout, withRounded
655
678
  height: Math.round(cell.bounds.height),
656
679
  transform: `translate3d(${Math.round(origin.left)}px, ${Math.round(origin.top)}px, 0)`,
657
680
  };
658
- const clientId = (_b = (_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.participant) === null || _b === void 0 ? void 0 : _b.id;
681
+ const clientId = ((_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.cellId) || ((_c = (_b = child === null || child === void 0 ? void 0 : child.props) === null || _b === void 0 ? void 0 : _b.participant) === null || _c === void 0 ? void 0 : _c.id);
659
682
  const childWithProps = React__namespace.cloneElement(child, {
660
683
  isSmallCell: cell.isSmallCell,
661
- isZoomedByDefault: !!isConstrained && !(child === null || child === void 0 ? void 0 : child.props.participant.isPresentation),
684
+ isZoomedByDefault: !!isConstrained && !!((_d = child === null || child === void 0 ? void 0 : child.props) === null || _d === void 0 ? void 0 : _d.participant) && !child.props.participant.isPresentation,
662
685
  canZoom: !!isConstrained,
663
686
  key: clientId || `video-${index}`,
664
687
  });
@@ -706,7 +729,33 @@ function renderFloatingVideoCell({ content, containerFrame, stageLayout, withRou
706
729
  withShadow: false,
707
730
  });
708
731
  }
709
- function VideoStageLayout({ containerFrame, debug = false, featureRoundedCornersOff = false, floatingContent, gridContent = [], isConstrained = false, layoutOverflowBackdropFrame = makeFrame(), layoutVideoStage: stageLayout, presentationGridContent = [], subgridContent = [], }) {
732
+ const HIDDEN_CELL_STYLE = {
733
+ width: 1,
734
+ height: 1,
735
+ opacity: 0,
736
+ overflow: "hidden",
737
+ pointerEvents: "none",
738
+ };
739
+ function renderHiddenCells({ content }) {
740
+ const cell = { bounds: { width: 1, height: 1 }, aspectRatio: 1 };
741
+ return content.map((child, index) => {
742
+ var _a;
743
+ if (!child) {
744
+ return null;
745
+ }
746
+ const clientId = ((_a = child.props) === null || _a === void 0 ? void 0 : _a.cellId) || `hidden-${index}`;
747
+ const childWithProps = React__namespace.cloneElement(child, { isHiddenCell: true, key: clientId });
748
+ return renderVideoCell({ cell, child: childWithProps, clientId, style: HIDDEN_CELL_STYLE });
749
+ });
750
+ }
751
+ function withIntegrationCellsFirst(cells) {
752
+ const isIntegrationCell = (cell) => { var _a, _b; return ((_b = (_a = cell === null || cell === void 0 ? void 0 : cell.props) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.type) === IntegrationCell; };
753
+ const integrationCells = cells
754
+ .filter(isIntegrationCell)
755
+ .sort((a, b) => String(a === null || a === void 0 ? void 0 : a.key).localeCompare(String(b === null || b === void 0 ? void 0 : b.key)));
756
+ return [...integrationCells, ...cells.filter((cell) => !isIntegrationCell(cell))];
757
+ }
758
+ function VideoStageLayout({ containerFrame, debug = false, featureRoundedCornersOff = false, floatingContent, gridContent = [], isConstrained = false, layoutOverflowBackdropFrame = makeFrame(), layoutVideoStage: stageLayout, presentationGridContent = [], subgridContent = [], hiddenContent = [], }) {
710
759
  const withRoundedCorners = !featureRoundedCornersOff && !isConstrained;
711
760
  const cells = [];
712
761
  if (gridContent.length) {
@@ -743,16 +792,221 @@ function VideoStageLayout({ containerFrame, debug = false, featureRoundedCorners
743
792
  withShadow: true,
744
793
  }));
745
794
  }
795
+ if (hiddenContent.length) {
796
+ cells.push(...renderHiddenCells({ content: hiddenContent }));
797
+ }
746
798
  return (React__namespace.createElement("div", { key: "video-stage-layout", style: {
747
799
  width: "100%",
748
800
  height: "100%",
749
801
  position: "relative",
750
802
  } },
751
803
  hasBounds(layoutOverflowBackdropFrame.bounds) && (React__namespace.createElement("div", { style: generateStylesFromFrame(layoutOverflowBackdropFrame) })),
752
- cells,
804
+ withIntegrationCellsFirst(cells),
753
805
  debug && (React__namespace.createElement(React__namespace.Fragment, null))));
754
806
  }
755
807
 
808
+ function useIframeContract(ref, hookName, enabled) {
809
+ React__namespace.useEffect(() => {
810
+ if (!enabled) {
811
+ return;
812
+ }
813
+ const timer = setTimeout(() => {
814
+ const frame = ref.current;
815
+ if (!frame) {
816
+ console.warn(`${hookName}: iframeProps.ref was never attached. Spread iframeProps onto the ` +
817
+ `<iframe> you render — without the ref the hook cannot tell which window is ` +
818
+ `answering, so nothing will ever arrive.`);
819
+ return;
820
+ }
821
+ if (frame.hasAttribute("sandbox")) {
822
+ console.warn(`${hookName}: the iframe has a sandbox attribute. Some integrations open their ` +
823
+ `own window to sign in, which a sandbox without allow-popups blocks silently.`);
824
+ }
825
+ }, 0);
826
+ return () => clearTimeout(timer);
827
+ }, [ref, hookName, enabled]);
828
+ }
829
+
830
+ const HOST_TO_FRAME = {
831
+ PROPS: "whereby:props",
832
+ SET_VOLUME: "whereby:setVolume",
833
+ GET_VOLUME: "whereby:getVolume",
834
+ };
835
+ const FRAME_TO_HOST = {
836
+ FRAME_READY: "whereby:frameReady",
837
+ UPDATE_PROPS: "whereby:updateProps",
838
+ CONTENT_READY: "whereby:contentReady",
839
+ CLOSE: "whereby:close",
840
+ AUDIO_OVERRIDE: "whereby:audioOverride",
841
+ VOLUME: "whereby:volume",
842
+ };
843
+ const DEFAULT_ALLOW$1 = "autoplay; fullscreen; encrypted-media; picture-in-picture";
844
+ const VOLUME_REQUEST_TIMEOUT = 2000;
845
+ function outboundProps(session) {
846
+ return Object.assign(Object.assign({}, session.props), { ispresenter: session.isPresenter, presenterdisplayname: session.presenterDisplayName, roomintegrationsessionid: session.roomIntegrationSessionId, breakoutgroupid: session.breakoutGroupId });
847
+ }
848
+ function diffProps(next, previous) {
849
+ if (!previous) {
850
+ return next;
851
+ }
852
+ return Object.keys(next).reduce((patch, key) => {
853
+ if (previous[key] !== next[key]) {
854
+ patch[key] = next[key];
855
+ }
856
+ return patch;
857
+ }, {});
858
+ }
859
+ function useRoomIntegrationView({ session, onAudioOverride, onContentReady, allow = DEFAULT_ALLOW$1, title, }) {
860
+ var _a;
861
+ const client = (_a = React__namespace.useContext(WherebyContext)) === null || _a === void 0 ? void 0 : _a.getRoomConnection();
862
+ const iframeRef = React__namespace.useRef(null);
863
+ const lastSentRef = React__namespace.useRef(null);
864
+ const isFrameReadyRef = React__namespace.useRef(false);
865
+ const volumeRequestsRef = React__namespace.useRef(new Map());
866
+ const nextRequestIdRef = React__namespace.useRef(0);
867
+ const sessionRef = React__namespace.useRef(session);
868
+ const onAudioOverrideRef = React__namespace.useRef(onAudioOverride);
869
+ const onContentReadyRef = React__namespace.useRef(onContentReady);
870
+ sessionRef.current = session;
871
+ onAudioOverrideRef.current = onAudioOverride;
872
+ onContentReadyRef.current = onContentReady;
873
+ const { webview } = session.integration;
874
+ const { roomIntegrationSessionId } = session;
875
+ const frameOrigin = React__namespace.useMemo(() => {
876
+ try {
877
+ return new URL(webview).origin;
878
+ }
879
+ catch (_a) {
880
+ console.warn(`useRoomIntegrationView: unusable webview url ${webview}`);
881
+ return null;
882
+ }
883
+ }, [webview]);
884
+ const src = React__namespace.useMemo(() => {
885
+ if (!frameOrigin) {
886
+ return null;
887
+ }
888
+ const url = new URL(webview);
889
+ url.searchParams.set("parentOrigin", window.location.origin);
890
+ url.searchParams.set("roomintegrationsessionid", roomIntegrationSessionId);
891
+ return url.href;
892
+ }, [webview, frameOrigin, roomIntegrationSessionId]);
893
+ const post = React__namespace.useCallback((type, payload) => {
894
+ var _a;
895
+ const frameWindow = (_a = iframeRef.current) === null || _a === void 0 ? void 0 : _a.contentWindow;
896
+ if (!frameWindow || !frameOrigin) {
897
+ return;
898
+ }
899
+ frameWindow.postMessage({ type, payload }, frameOrigin);
900
+ }, [frameOrigin]);
901
+ React__namespace.useEffect(() => {
902
+ isFrameReadyRef.current = false;
903
+ lastSentRef.current = null;
904
+ }, [src]);
905
+ React__namespace.useEffect(() => {
906
+ if (!frameOrigin) {
907
+ return;
908
+ }
909
+ const handleMessage = (event) => {
910
+ var _a, _b, _c, _d;
911
+ if (event.origin !== frameOrigin || event.source !== ((_a = iframeRef.current) === null || _a === void 0 ? void 0 : _a.contentWindow)) {
912
+ return;
913
+ }
914
+ const { type, payload } = event.data || {};
915
+ const currentSession = sessionRef.current;
916
+ switch (type) {
917
+ case FRAME_TO_HOST.FRAME_READY: {
918
+ const props = outboundProps(currentSession);
919
+ isFrameReadyRef.current = true;
920
+ lastSentRef.current = props;
921
+ post(HOST_TO_FRAME.PROPS, props);
922
+ break;
923
+ }
924
+ case FRAME_TO_HOST.UPDATE_PROPS: {
925
+ if (payload === null || payload === void 0 ? void 0 : payload.props) {
926
+ client === null || client === void 0 ? void 0 : client.updateRoomIntegrationProps({
927
+ roomIntegrationSessionId: currentSession.roomIntegrationSessionId,
928
+ props: payload.props,
929
+ });
930
+ }
931
+ break;
932
+ }
933
+ case FRAME_TO_HOST.CLOSE: {
934
+ if (currentSession.canStop) {
935
+ client === null || client === void 0 ? void 0 : client.stopRoomIntegration({
936
+ roomIntegrationSessionId: currentSession.roomIntegrationSessionId,
937
+ intent: "end",
938
+ });
939
+ }
940
+ break;
941
+ }
942
+ case FRAME_TO_HOST.AUDIO_OVERRIDE: {
943
+ (_b = onAudioOverrideRef.current) === null || _b === void 0 ? void 0 : _b.call(onAudioOverrideRef, (_c = payload === null || payload === void 0 ? void 0 : payload.enabled) !== null && _c !== void 0 ? _c : null);
944
+ break;
945
+ }
946
+ case FRAME_TO_HOST.CONTENT_READY: {
947
+ (_d = onContentReadyRef.current) === null || _d === void 0 ? void 0 : _d.call(onContentReadyRef);
948
+ break;
949
+ }
950
+ case FRAME_TO_HOST.VOLUME: {
951
+ const resolve = volumeRequestsRef.current.get(payload === null || payload === void 0 ? void 0 : payload.requestId);
952
+ if (resolve) {
953
+ volumeRequestsRef.current.delete(payload.requestId);
954
+ resolve(payload.volume);
955
+ }
956
+ break;
957
+ }
958
+ }
959
+ };
960
+ window.addEventListener("message", handleMessage);
961
+ return () => window.removeEventListener("message", handleMessage);
962
+ }, [frameOrigin, client, post]);
963
+ const serializedProps = JSON.stringify(outboundProps(session));
964
+ React__namespace.useEffect(() => {
965
+ if (!isFrameReadyRef.current) {
966
+ return;
967
+ }
968
+ const props = outboundProps(sessionRef.current);
969
+ const patch = diffProps(props, lastSentRef.current);
970
+ lastSentRef.current = props;
971
+ if (Object.keys(patch).length) {
972
+ post(HOST_TO_FRAME.PROPS, patch);
973
+ }
974
+ }, [serializedProps, post]);
975
+ const setVolume = React__namespace.useCallback((volume) => post(HOST_TO_FRAME.SET_VOLUME, { volume }), [post]);
976
+ const getVolume = React__namespace.useCallback(() => new Promise((resolve, reject) => {
977
+ const requestId = ++nextRequestIdRef.current;
978
+ const requests = volumeRequestsRef.current;
979
+ const timer = setTimeout(() => {
980
+ requests.delete(requestId);
981
+ reject(new Error("Timed out reading volume from the room integration"));
982
+ }, VOLUME_REQUEST_TIMEOUT);
983
+ requests.set(requestId, (volume) => {
984
+ clearTimeout(timer);
985
+ resolve(volume);
986
+ });
987
+ post(HOST_TO_FRAME.GET_VOLUME, { requestId });
988
+ }), [post]);
989
+ useIframeContract(iframeRef, "useRoomIntegrationView", !!src);
990
+ return {
991
+ iframeProps: src
992
+ ? {
993
+ ref: iframeRef,
994
+ src,
995
+ title: title || session.integration.title,
996
+ allow,
997
+ }
998
+ : null,
999
+ getVolume,
1000
+ setVolume,
1001
+ };
1002
+ }
1003
+
1004
+ const IFRAME_STYLE = { border: "none", width: "100%", height: "100%" };
1005
+ function DefaultIntegrationView({ session }) {
1006
+ const { iframeProps } = useRoomIntegrationView({ session });
1007
+ return iframeProps ? React__namespace.createElement("iframe", Object.assign({}, iframeProps, { allowFullScreen: true, style: IFRAME_STYLE })) : null;
1008
+ }
1009
+
756
1010
  const WIDE_AR = 16 / 9;
757
1011
  const NORMAL_AR = 4 / 3;
758
1012
  const clamp = ({ value, min, max }) => Math.min(Math.max(value, min), max);
@@ -1808,6 +2062,7 @@ function makeVideoCellView({ aspectRatio, avatarSize, cellPaddings, client = und
1808
2062
  avatarSize,
1809
2063
  cellPaddings,
1810
2064
  client,
2065
+ cellId: (client === null || client === void 0 ? void 0 : client.id) || "",
1811
2066
  clientId: (client === null || client === void 0 ? void 0 : client.id) || "",
1812
2067
  isDraggable,
1813
2068
  isPlaceholder,
@@ -1815,20 +2070,38 @@ function makeVideoCellView({ aspectRatio, avatarSize, cellPaddings, client = und
1815
2070
  type: "video",
1816
2071
  };
1817
2072
  }
2073
+ function integrationAspectRatio(session) {
2074
+ var _a;
2075
+ const reported = Number((_a = session.props) === null || _a === void 0 ? void 0 : _a.aspectratio);
2076
+ return isFinite(reported) && reported > 0 ? reported : undefined;
2077
+ }
2078
+ function roomIntegrationCellId(session) {
2079
+ return `room-integration:${session.roomIntegrationSessionId}`;
2080
+ }
2081
+ function makeIntegrationCellView({ session, isDraggable = false, isSubgrid = false, }) {
2082
+ const cellId = roomIntegrationCellId(session);
2083
+ return {
2084
+ aspectRatio: integrationAspectRatio(session) || 16 / 9,
2085
+ cellId,
2086
+ clientId: cellId,
2087
+ isDraggable,
2088
+ isSubgrid,
2089
+ session,
2090
+ type: "integration",
2091
+ };
2092
+ }
1818
2093
 
1819
2094
  const STAGE_PARTICIPANT_LIMIT = 12;
1820
2095
  const ACTIVE_VIDEO_SUBGRID_TRIGGER = 12;
1821
2096
  const ACTIVE_VIDEOS_PHONE_LIMIT = 24;
1822
2097
 
1823
- function calculateSubgridViews({ clientViews, activeVideosSubgridTrigger, shouldShowSubgrid, spotlightedParticipants, maximizedParticipant, isPhoneResolution, }) {
2098
+ function calculateSubgridViews({ clientViews, activeVideosSubgridTrigger, shouldShowSubgrid, spotlightedParticipants, maximizedCellId, hasStagedIntegration = false, isPhoneResolution, }) {
1824
2099
  if (!shouldShowSubgrid) {
1825
2100
  return [];
1826
2101
  }
1827
2102
  const hasSpotlights = spotlightedParticipants.length > 0;
1828
- const hasPresentationStage = hasSpotlights;
1829
- const notMaximized = maximizedParticipant
1830
- ? clientViews.filter((client) => client.id !== maximizedParticipant.id)
1831
- : clientViews;
2103
+ const hasPresentationStage = hasSpotlights || hasStagedIntegration;
2104
+ const notMaximized = maximizedCellId ? clientViews.filter((client) => client.id !== maximizedCellId) : clientViews;
1832
2105
  const notSpotlighted = notMaximized.filter((client) => !client.isPresentation && !spotlightedParticipants.includes(client));
1833
2106
  const noVideoViews = notSpotlighted.filter((client) => !client.isVideoEnabled);
1834
2107
  const videoLimitReached = notSpotlighted.filter((client) => client.isVideoEnabled).length > activeVideosSubgridTrigger;
@@ -1859,7 +2132,8 @@ function calculateSubgridViews({ clientViews, activeVideosSubgridTrigger, should
1859
2132
  }
1860
2133
  return noVideoViews;
1861
2134
  }
1862
- function useGridParticipants({ activeVideosSubgridTrigger = ACTIVE_VIDEO_SUBGRID_TRIGGER, stageParticipantLimit = STAGE_PARTICIPANT_LIMIT, forceSubgrid = true, enableSubgrid = true, maximizedParticipant, floatingParticipant, isConstrained = false, } = {}) {
2135
+ const NO_INTEGRATIONS = [];
2136
+ function useGridParticipants({ activeVideosSubgridTrigger = ACTIVE_VIDEO_SUBGRID_TRIGGER, stageParticipantLimit = STAGE_PARTICIPANT_LIMIT, forceSubgrid = true, enableSubgrid = true, maximizedCellId, floatingCellId, isConstrained = false, includeIntegrations = false, } = {}) {
1863
2137
  var _a;
1864
2138
  const client = (_a = React__namespace.useContext(WherebyContext)) === null || _a === void 0 ? void 0 : _a.getGrid();
1865
2139
  if (!client) {
@@ -1872,6 +2146,9 @@ function useGridParticipants({ activeVideosSubgridTrigger = ACTIVE_VIDEO_SUBGRID
1872
2146
  const handleSpotlightedParticipantsChanged = React__namespace.useCallback((spotlighted) => {
1873
2147
  setState((prevState) => (Object.assign(Object.assign({}, prevState), { spotlightedParticipants: spotlighted })));
1874
2148
  }, [setState]);
2149
+ const handleRunningRoomIntegrationsChanged = React__namespace.useCallback((runningRoomIntegrations) => {
2150
+ setState((prevState) => (Object.assign(Object.assign({}, prevState), { runningRoomIntegrations })));
2151
+ }, [setState]);
1875
2152
  const handleNumParticipantsChanged = React__namespace.useCallback((num) => {
1876
2153
  setState((prevState) => (Object.assign(Object.assign({}, prevState), { numParticipants: num })));
1877
2154
  }, [setState]);
@@ -1879,19 +2156,21 @@ function useGridParticipants({ activeVideosSubgridTrigger = ACTIVE_VIDEO_SUBGRID
1879
2156
  const unsubscribeClientViews = client.subscribeClientViews(handleClientViewChanged);
1880
2157
  const unsubscribeSpotlighted = client.subscribeSpotlightedParticipants(handleSpotlightedParticipantsChanged);
1881
2158
  const unsubscribeNumParticipants = client.subscribeNumberOfClientViews(handleNumParticipantsChanged);
2159
+ const unsubscribeRunningRoomIntegrations = client.subscribeRunningRoomIntegrations(handleRunningRoomIntegrationsChanged);
1882
2160
  setState(client.getState());
1883
2161
  return () => {
1884
2162
  unsubscribeClientViews();
1885
2163
  unsubscribeSpotlighted();
1886
2164
  unsubscribeNumParticipants();
2165
+ unsubscribeRunningRoomIntegrations();
1887
2166
  };
1888
2167
  }, [client]);
1889
2168
  const allClientViews = React__namespace.useMemo(() => state.allClientViews, [state.allClientViews]);
1890
2169
  const spotlightedParticipants = React__namespace.useMemo(() => state.spotlightedParticipants, [state.spotlightedParticipants]);
1891
2170
  const numParticipants = React__namespace.useMemo(() => state.numParticipants, [state.numParticipants]);
1892
- const floatingClientView = React__namespace.useMemo(() => {
1893
- return floatingParticipant;
1894
- }, [floatingParticipant]);
2171
+ const runningRoomIntegrations = React__namespace.useMemo(() => (includeIntegrations ? state.runningRoomIntegrations : NO_INTEGRATIONS), [includeIntegrations, state.runningRoomIntegrations]);
2172
+ const maximizedClientView = React__namespace.useMemo(() => (maximizedCellId ? allClientViews.find((client) => client.id === maximizedCellId) || null : null), [allClientViews, maximizedCellId]);
2173
+ const floatingClientView = React__namespace.useMemo(() => (floatingCellId ? allClientViews.find((client) => client.id === floatingCellId) || null : null), [allClientViews, floatingCellId]);
1895
2174
  const clientViewsNotFloating = React__namespace.useMemo(() => {
1896
2175
  if (floatingClientView) {
1897
2176
  return allClientViews.filter((c) => c.id !== floatingClientView.id);
@@ -1904,51 +2183,84 @@ function useGridParticipants({ activeVideosSubgridTrigger = ACTIVE_VIDEO_SUBGRID
1904
2183
  }
1905
2184
  return forceSubgrid ? true : numParticipants > stageParticipantLimit;
1906
2185
  }, [forceSubgrid, numParticipants, stageParticipantLimit, enableSubgrid]);
2186
+ const integrationsInPresentationGrid = React__namespace.useMemo(() => {
2187
+ if (!runningRoomIntegrations.length || maximizedClientView) {
2188
+ return [];
2189
+ }
2190
+ return [runningRoomIntegrations[0]];
2191
+ }, [runningRoomIntegrations, maximizedClientView]);
2192
+ const integrationsInSubgrid = React__namespace.useMemo(() => {
2193
+ if (!shouldShowSubgrid) {
2194
+ return [];
2195
+ }
2196
+ return runningRoomIntegrations.filter((session) => !integrationsInPresentationGrid.some((staged) => staged.roomIntegrationSessionId === session.roomIntegrationSessionId));
2197
+ }, [runningRoomIntegrations, integrationsInPresentationGrid, shouldShowSubgrid]);
2198
+ const integrationsHidden = React__namespace.useMemo(() => {
2199
+ const visible = [...integrationsInPresentationGrid, ...integrationsInSubgrid];
2200
+ return runningRoomIntegrations.filter((session) => !visible.some((shown) => shown.roomIntegrationSessionId === session.roomIntegrationSessionId));
2201
+ }, [runningRoomIntegrations, integrationsInPresentationGrid, integrationsInSubgrid]);
1907
2202
  const clientViewsInSubgrid = React__namespace.useMemo(() => {
1908
2203
  return calculateSubgridViews({
1909
2204
  clientViews: clientViewsNotFloating,
1910
2205
  activeVideosSubgridTrigger,
1911
2206
  shouldShowSubgrid,
1912
2207
  spotlightedParticipants,
1913
- maximizedParticipant,
2208
+ maximizedCellId,
2209
+ hasStagedIntegration: integrationsInPresentationGrid.length > 0,
1914
2210
  isPhoneResolution: isConstrained,
1915
2211
  });
1916
- }, [clientViewsNotFloating, shouldShowSubgrid, activeVideosSubgridTrigger, spotlightedParticipants, isConstrained]);
2212
+ }, [
2213
+ clientViewsNotFloating,
2214
+ shouldShowSubgrid,
2215
+ activeVideosSubgridTrigger,
2216
+ spotlightedParticipants,
2217
+ maximizedCellId,
2218
+ integrationsInPresentationGrid,
2219
+ isConstrained,
2220
+ ]);
1917
2221
  const clientViewsOnStage = React__namespace.useMemo(() => {
1918
2222
  return clientViewsNotFloating.filter((client) => !clientViewsInSubgrid.includes(client));
1919
2223
  }, [clientViewsNotFloating, clientViewsInSubgrid]);
1920
2224
  const clientViewsInPresentationGrid = React__namespace.useMemo(() => {
1921
- if (maximizedParticipant) {
1922
- return [maximizedParticipant];
2225
+ if (maximizedClientView) {
2226
+ return [maximizedClientView];
1923
2227
  }
1924
- return spotlightedParticipants;
1925
- }, [spotlightedParticipants, maximizedParticipant]);
2228
+ if (integrationsInPresentationGrid.length) {
2229
+ return [];
2230
+ }
2231
+ return spotlightedParticipants.filter((client) => clientViewsOnStage.includes(client));
2232
+ }, [spotlightedParticipants, maximizedClientView, integrationsInPresentationGrid, clientViewsOnStage]);
1926
2233
  const clientViewsInGrid = React__namespace.useMemo(() => {
1927
2234
  return clientViewsOnStage.filter((client) => !clientViewsInPresentationGrid.includes(client));
1928
2235
  }, [clientViewsOnStage, clientViewsInPresentationGrid]);
1929
2236
  return {
1930
2237
  floatingClientView,
2238
+ maximizedClientView,
1931
2239
  clientViewsInGrid,
1932
2240
  clientViewsInPresentationGrid,
1933
2241
  clientViewsInSubgrid,
2242
+ integrationsInPresentationGrid,
2243
+ integrationsInSubgrid,
2244
+ integrationsHidden,
1934
2245
  spotlightedParticipants,
1935
2246
  };
1936
2247
  }
1937
2248
 
1938
- function useGrid({ activeVideosSubgridTrigger, forceSubgrid, stageParticipantLimit = STAGE_PARTICIPANT_LIMIT, gridGap = 8, videoGridGap = 8, enableSubgrid = true, enableConstrainedGrid = true, } = {}) {
2249
+ function useGrid({ activeVideosSubgridTrigger, forceSubgrid, stageParticipantLimit = STAGE_PARTICIPANT_LIMIT, gridGap = 8, videoGridGap = 8, enableSubgrid = true, enableConstrainedGrid = true, includeIntegrations = false, } = {}) {
1939
2250
  const [containerBounds, setContainerBounds] = React__namespace.useState({ width: 0, height: 0 });
1940
2251
  const [isConstrained, setIsConstrained] = React__namespace.useState(false);
1941
2252
  const [clientAspectRatios, setClientAspectRatios] = React__namespace.useState({});
1942
- const [maximizedParticipant, setMaximizedParticipant] = React__namespace.useState(null);
1943
- const [floatingParticipant, setFloatingParticipant] = React__namespace.useState(null);
1944
- const { clientViewsInGrid, clientViewsInPresentationGrid, clientViewsInSubgrid, floatingClientView } = useGridParticipants({
2253
+ const [maximizedCellId, setMaximizedCellId] = React__namespace.useState(null);
2254
+ const [floatingCellId, setFloatingCellId] = React__namespace.useState(null);
2255
+ const { clientViewsInGrid, clientViewsInPresentationGrid, clientViewsInSubgrid, floatingClientView, maximizedClientView, integrationsInPresentationGrid, integrationsInSubgrid, integrationsHidden, } = useGridParticipants({
1945
2256
  activeVideosSubgridTrigger,
1946
2257
  forceSubgrid,
1947
2258
  stageParticipantLimit,
1948
2259
  enableSubgrid,
1949
- maximizedParticipant,
1950
- floatingParticipant,
2260
+ maximizedCellId,
2261
+ floatingCellId,
1951
2262
  isConstrained: !!enableConstrainedGrid && !!isConstrained,
2263
+ includeIntegrations,
1952
2264
  });
1953
2265
  const cellViewsFloating = React__namespace.useMemo(() => {
1954
2266
  return floatingClientView
@@ -1973,26 +2285,35 @@ function useGrid({ activeVideosSubgridTrigger, forceSubgrid, stageParticipantLim
1973
2285
  });
1974
2286
  }, [clientViewsInGrid, clientAspectRatios]);
1975
2287
  const cellViewsInPresentationGrid = React__namespace.useMemo(() => {
1976
- return clientViewsInPresentationGrid.map((client) => {
1977
- return makeVideoCellView({
1978
- client,
1979
- aspectRatio: clientAspectRatios[client.id],
1980
- avatarSize: 0,
1981
- cellPaddings: { top: 0, right: 0 },
1982
- });
1983
- });
1984
- }, [clientViewsInPresentationGrid, clientAspectRatios]);
2288
+ return [
2289
+ ...integrationsInPresentationGrid.map((session) => makeIntegrationCellView({ session })),
2290
+ ...clientViewsInPresentationGrid.map((client) => {
2291
+ return makeVideoCellView({
2292
+ client,
2293
+ aspectRatio: clientAspectRatios[client.id],
2294
+ avatarSize: 0,
2295
+ cellPaddings: { top: 0, right: 0 },
2296
+ });
2297
+ }),
2298
+ ];
2299
+ }, [clientViewsInPresentationGrid, integrationsInPresentationGrid, clientAspectRatios]);
1985
2300
  const cellViewsInSubgrid = React__namespace.useMemo(() => {
1986
- return clientViewsInSubgrid.map((client) => {
1987
- return makeVideoCellView({
1988
- client,
1989
- aspectRatio: clientAspectRatios[client.id],
1990
- avatarSize: 0,
1991
- cellPaddings: { top: 0, right: 0 },
1992
- isSubgrid: true,
1993
- });
1994
- });
1995
- }, [clientViewsInSubgrid, clientAspectRatios]);
2301
+ return [
2302
+ ...clientViewsInSubgrid.map((client) => {
2303
+ return makeVideoCellView({
2304
+ client,
2305
+ aspectRatio: clientAspectRatios[client.id],
2306
+ avatarSize: 0,
2307
+ cellPaddings: { top: 0, right: 0 },
2308
+ isSubgrid: true,
2309
+ });
2310
+ }),
2311
+ ...integrationsInSubgrid.map((session) => makeIntegrationCellView({ session, isSubgrid: true })),
2312
+ ];
2313
+ }, [clientViewsInSubgrid, integrationsInSubgrid, clientAspectRatios]);
2314
+ const cellViewsHidden = React__namespace.useMemo(() => {
2315
+ return integrationsHidden.map((session) => makeIntegrationCellView({ session }));
2316
+ }, [integrationsHidden]);
1996
2317
  const containerFrame = React__namespace.useMemo(() => {
1997
2318
  return makeFrame(containerBounds);
1998
2319
  }, [containerBounds]);
@@ -2029,14 +2350,17 @@ function useGrid({ activeVideosSubgridTrigger, forceSubgrid, stageParticipantLim
2029
2350
  cellViewsVideoGrid,
2030
2351
  cellViewsInPresentationGrid,
2031
2352
  cellViewsInSubgrid,
2353
+ cellViewsHidden,
2032
2354
  clientAspectRatios,
2033
2355
  videoStage,
2034
2356
  setContainerBounds,
2035
2357
  setClientAspectRatios,
2036
- maximizedParticipant,
2037
- setMaximizedParticipant,
2038
- floatingParticipant,
2039
- setFloatingParticipant,
2358
+ maximizedCellId,
2359
+ setMaximizedCellId,
2360
+ maximizedParticipant: maximizedClientView,
2361
+ floatingCellId,
2362
+ setFloatingCellId,
2363
+ floatingParticipant: floatingClientView,
2040
2364
  isConstrained,
2041
2365
  };
2042
2366
  }
@@ -2150,22 +2474,17 @@ ParticipantMenuTrigger.displayName = PopoverTrigger.displayName;
2150
2474
  const ParticipantMenuItem = React__namespace.forwardRef((_a, ref) => {
2151
2475
  var _b;
2152
2476
  var { children, style, participantAction } = _a, props = __rest(_a, ["children", "style", "participantAction"]);
2153
- const { participant, setOpen, maximizedParticipant, setMaximizedParticipant, setFloatingParticipant, floatingParticipant, } = useParticipantMenu();
2477
+ const { participant, setOpen, maximizedCellId, setMaximizedCellId, floatingCellId, setFloatingCellId } = useParticipantMenu();
2154
2478
  const client = (_b = React__namespace.useContext(WherebyContext)) === null || _b === void 0 ? void 0 : _b.getGrid();
2155
2479
  const { spotlightedParticipants } = useGridParticipants();
2156
2480
  const isSpotlighted = spotlightedParticipants.find((p) => p.id === participant.id);
2157
- const isMaximized = (maximizedParticipant === null || maximizedParticipant === void 0 ? void 0 : maximizedParticipant.id) === participant.id;
2158
- const isFloating = (floatingParticipant === null || floatingParticipant === void 0 ? void 0 : floatingParticipant.id) === participant.id;
2481
+ const isMaximized = maximizedCellId === participant.id;
2482
+ const isFloating = floatingCellId === participant.id;
2159
2483
  let onClick;
2160
2484
  switch (participantAction) {
2161
2485
  case "maximize":
2162
2486
  onClick = () => {
2163
- if (isMaximized) {
2164
- setMaximizedParticipant(null);
2165
- }
2166
- else {
2167
- setMaximizedParticipant(participant);
2168
- }
2487
+ setMaximizedCellId(isMaximized ? null : participant.id);
2169
2488
  setOpen(false);
2170
2489
  };
2171
2490
  break;
@@ -2182,12 +2501,7 @@ const ParticipantMenuItem = React__namespace.forwardRef((_a, ref) => {
2182
2501
  break;
2183
2502
  case "float":
2184
2503
  onClick = () => {
2185
- if (isFloating) {
2186
- setFloatingParticipant(null);
2187
- }
2188
- else {
2189
- setFloatingParticipant(participant);
2190
- }
2504
+ setFloatingCellId(isFloating ? null : participant.id);
2191
2505
  setOpen(false);
2192
2506
  };
2193
2507
  break;
@@ -2304,28 +2618,35 @@ const GridVideoView = React__namespace.forwardRef((_a, ref) => {
2304
2618
  return (React__namespace.createElement(VideoView, Object.assign({ ref: videoEl, style: Object.assign(Object.assign({ borderRadius: isConstrained ? 0 : "8px" }, (isConstrained ? { objectFit: "cover" } : {})), style), muted: participant.isLocalClient }, rest, { stream: s, onVideoResize: handleResize })));
2305
2619
  });
2306
2620
  GridVideoView.displayName = "GridVideoView";
2307
- function renderCellView({ cellView, enableParticipantMenu, render }) {
2308
- const participant = cellView === null || cellView === void 0 ? void 0 : cellView.client;
2309
- if (!participant) {
2621
+ function renderCellView({ cellView, enableParticipantMenu, render, renderIntegration }) {
2622
+ if (!cellView) {
2310
2623
  return undefined;
2311
2624
  }
2312
2625
  switch (cellView.type) {
2313
- case "video":
2314
- return (React__namespace.createElement(GridCell, { participant: participant },
2626
+ case "video": {
2627
+ const participant = cellView.client;
2628
+ if (!participant) {
2629
+ return undefined;
2630
+ }
2631
+ return (React__namespace.createElement(GridCell, { participant: participant, cellId: cellView.cellId },
2315
2632
  React__namespace.createElement(React__namespace.Fragment, null, render ? (render({ participant })) : (React__namespace.createElement(React__namespace.Fragment, null,
2316
2633
  React__namespace.createElement(GridVideoView, null),
2317
2634
  enableParticipantMenu ? React__namespace.createElement(DefaultParticipantMenu, { participant: participant }) : null)))));
2635
+ }
2636
+ case "integration":
2637
+ return (React__namespace.createElement(IntegrationCell, { cellId: cellView.cellId }, renderIntegration ? (renderIntegration({ session: cellView.session })) : (React__namespace.createElement(DefaultIntegrationView, { session: cellView.session }))));
2318
2638
  }
2319
2639
  }
2320
- function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParticipant, stageParticipantLimit, gridGap, videoGridGap, enableSubgrid, enableParticipantMenu, enableConstrainedGrid, }) {
2640
+ function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParticipant, renderIntegration, stageParticipantLimit, gridGap, videoGridGap, enableSubgrid, enableParticipantMenu, enableConstrainedGrid, enableIntegrations = true, }) {
2321
2641
  const gridRef = React__namespace.useRef(null);
2322
- const { containerFrame, cellViewsFloating, cellViewsVideoGrid, cellViewsInPresentationGrid, cellViewsInSubgrid, clientAspectRatios, videoStage, setContainerBounds, setClientAspectRatios, maximizedParticipant, setMaximizedParticipant, isConstrained, floatingParticipant, setFloatingParticipant, } = useGrid({
2642
+ const { containerFrame, cellViewsFloating, cellViewsVideoGrid, cellViewsInPresentationGrid, cellViewsInSubgrid, cellViewsHidden, clientAspectRatios, videoStage, setContainerBounds, setClientAspectRatios, maximizedCellId, setMaximizedCellId, maximizedParticipant, isConstrained, floatingCellId, setFloatingCellId, floatingParticipant, } = useGrid({
2323
2643
  activeVideosSubgridTrigger: 12,
2324
2644
  stageParticipantLimit,
2325
2645
  gridGap,
2326
2646
  videoGridGap,
2327
2647
  enableSubgrid,
2328
2648
  enableConstrainedGrid,
2649
+ includeIntegrations: enableIntegrations,
2329
2650
  });
2330
2651
  const handleSetClientAspectRatio = React__namespace.useCallback(({ aspectRatio, clientId }) => {
2331
2652
  setClientAspectRatios((prev) => (Object.assign(Object.assign({}, prev), { [clientId]: aspectRatio })));
@@ -2336,13 +2657,16 @@ function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParti
2336
2657
  : {})));
2337
2658
  }, [cellViewsFloating]);
2338
2659
  const presentationGridContent = React__namespace.useMemo(() => cellViewsInPresentationGrid.map((cellView) => renderCellView(Object.assign({ cellView,
2339
- enableParticipantMenu }, (renderParticipant ? { render: ({ participant }) => renderParticipant({ participant }) } : {})))), [cellViewsInPresentationGrid]);
2660
+ enableParticipantMenu,
2661
+ renderIntegration }, (renderParticipant ? { render: ({ participant }) => renderParticipant({ participant }) } : {})))), [cellViewsInPresentationGrid, renderIntegration]);
2340
2662
  const gridContent = React__namespace.useMemo(() => cellViewsVideoGrid.map((cellView) => renderCellView(Object.assign({ cellView,
2341
2663
  enableParticipantMenu }, (renderParticipant ? { render: ({ participant }) => renderParticipant({ participant }) } : {})))), [cellViewsVideoGrid]);
2342
2664
  const subgridContent = React__namespace.useMemo(() => cellViewsInSubgrid.map((cellView) => renderCellView(Object.assign({ cellView,
2343
- enableParticipantMenu }, (renderSubgridParticipant
2665
+ enableParticipantMenu,
2666
+ renderIntegration }, (renderSubgridParticipant
2344
2667
  ? { render: ({ participant }) => renderSubgridParticipant({ participant }) }
2345
- : {})))), [cellViewsInSubgrid]);
2668
+ : {})))), [cellViewsInSubgrid, renderIntegration]);
2669
+ const hiddenContent = React__namespace.useMemo(() => cellViewsHidden.map((cellView) => renderCellView({ cellView, renderIntegration })), [cellViewsHidden, renderIntegration]);
2346
2670
  React__namespace.useEffect(() => {
2347
2671
  if (!gridRef.current) {
2348
2672
  return;
@@ -2365,10 +2689,12 @@ function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParti
2365
2689
  cellViewsInPresentationGrid,
2366
2690
  cellViewsInSubgrid,
2367
2691
  clientAspectRatios,
2692
+ maximizedCellId,
2693
+ setMaximizedCellId,
2368
2694
  maximizedParticipant,
2369
- setMaximizedParticipant,
2695
+ floatingCellId,
2696
+ setFloatingCellId,
2370
2697
  floatingParticipant,
2371
- setFloatingParticipant,
2372
2698
  isConstrained,
2373
2699
  } },
2374
2700
  React__namespace.createElement("div", { ref: gridRef, style: {
@@ -2376,7 +2702,102 @@ function Grid({ renderParticipant, renderSubgridParticipant, renderFloatingParti
2376
2702
  height: "100%",
2377
2703
  position: "relative",
2378
2704
  } },
2379
- React__namespace.createElement(VideoStageLayout, { containerFrame: containerFrame, floatingContent: floatingContent, layoutVideoStage: videoStage, presentationGridContent: presentationGridContent, gridContent: gridContent, subgridContent: subgridContent }))));
2705
+ React__namespace.createElement(VideoStageLayout, { containerFrame: containerFrame, floatingContent: floatingContent, layoutVideoStage: videoStage, presentationGridContent: presentationGridContent, gridContent: gridContent, subgridContent: subgridContent, hiddenContent: hiddenContent }))));
2706
+ }
2707
+
2708
+ function subscribeToRoomIntegrationPicker({ pickerOrigin, getSource, onOutcome, }) {
2709
+ let settled = false;
2710
+ function handleMessage(event) {
2711
+ if (settled || event.origin !== pickerOrigin || !event.source || event.source !== getSource()) {
2712
+ return;
2713
+ }
2714
+ const { type, payload } = event.data || {};
2715
+ if (type === core.ROOM_INTEGRATION_PICKER_MESSAGES.FORM_SUBMIT) {
2716
+ settle({ type: "submitted", content: payload });
2717
+ }
2718
+ else if (type === core.ROOM_INTEGRATION_PICKER_MESSAGES.FORM_CLOSE) {
2719
+ settle({ type: "cancelled" });
2720
+ }
2721
+ else if (type === core.ROOM_INTEGRATION_PICKER_MESSAGES.ERROR) {
2722
+ settle({
2723
+ type: "error",
2724
+ error: new Error((payload === null || payload === void 0 ? void 0 : payload.message) || "The room integration picker failed"),
2725
+ });
2726
+ }
2727
+ }
2728
+ const unsubscribe = () => {
2729
+ settled = true;
2730
+ window.removeEventListener("message", handleMessage);
2731
+ };
2732
+ const settle = (outcome) => {
2733
+ unsubscribe();
2734
+ onOutcome(outcome);
2735
+ };
2736
+ window.addEventListener("message", handleMessage);
2737
+ return unsubscribe;
2738
+ }
2739
+
2740
+ const DEFAULT_ALLOW = "clipboard-read; clipboard-write; fullscreen";
2741
+ function useRoomIntegrationPicker({ integration, onPicked, onCancel, onError, featureSource, allow = DEFAULT_ALLOW, title, }) {
2742
+ const iframeRef = React__namespace.useRef(null);
2743
+ const onPickedRef = React__namespace.useRef(onPicked);
2744
+ const onCancelRef = React__namespace.useRef(onCancel);
2745
+ const onErrorRef = React__namespace.useRef(onError);
2746
+ onPickedRef.current = onPicked;
2747
+ onCancelRef.current = onCancel;
2748
+ onErrorRef.current = onError;
2749
+ const { webview } = integration;
2750
+ const pickerOrigin = React__namespace.useMemo(() => {
2751
+ try {
2752
+ return new URL(webview).origin;
2753
+ }
2754
+ catch (_a) {
2755
+ console.warn(`useRoomIntegrationPicker: unusable webview url ${webview}`);
2756
+ return null;
2757
+ }
2758
+ }, [webview]);
2759
+ const src = React__namespace.useMemo(() => {
2760
+ if (!pickerOrigin) {
2761
+ return null;
2762
+ }
2763
+ return core.roomIntegrationPickerUrl({
2764
+ integration: { webview },
2765
+ parentOrigin: window.location.origin,
2766
+ featureSource,
2767
+ });
2768
+ }, [pickerOrigin, webview, featureSource]);
2769
+ React__namespace.useEffect(() => {
2770
+ if (!pickerOrigin) {
2771
+ return;
2772
+ }
2773
+ return subscribeToRoomIntegrationPicker({
2774
+ pickerOrigin,
2775
+ getSource: () => { var _a; return (_a = iframeRef.current) === null || _a === void 0 ? void 0 : _a.contentWindow; },
2776
+ onOutcome: (outcome) => {
2777
+ var _a, _b;
2778
+ if (outcome.type === "submitted") {
2779
+ onPickedRef.current(outcome.content || {});
2780
+ return;
2781
+ }
2782
+ if (outcome.type === "cancelled") {
2783
+ (_a = onCancelRef.current) === null || _a === void 0 ? void 0 : _a.call(onCancelRef);
2784
+ return;
2785
+ }
2786
+ (_b = onErrorRef.current) === null || _b === void 0 ? void 0 : _b.call(onErrorRef, outcome.error);
2787
+ },
2788
+ });
2789
+ }, [pickerOrigin, src]);
2790
+ useIframeContract(iframeRef, "useRoomIntegrationPicker", !!src);
2791
+ return {
2792
+ iframeProps: src
2793
+ ? {
2794
+ ref: iframeRef,
2795
+ src,
2796
+ title: title || `${integration.title} picker`,
2797
+ allow,
2798
+ }
2799
+ : null,
2800
+ };
2380
2801
  }
2381
2802
 
2382
2803
  Object.defineProperty(exports, "ACCEPTED_FILE_TYPES", {
@@ -2391,6 +2812,10 @@ Object.defineProperty(exports, "MAX_FILE_SIZE", {
2391
2812
  enumerable: true,
2392
2813
  get: function () { return core.MAX_FILE_SIZE; }
2393
2814
  });
2815
+ Object.defineProperty(exports, "ROOM_INTEGRATION_PICKER_MESSAGES", {
2816
+ enumerable: true,
2817
+ get: function () { return core.ROOM_INTEGRATION_PICKER_MESSAGES; }
2818
+ });
2394
2819
  Object.defineProperty(exports, "getUsableCameraEffectPresets", {
2395
2820
  enumerable: true,
2396
2821
  get: function () { return core.getUsableCameraEffectPresets; }
@@ -2399,6 +2824,18 @@ Object.defineProperty(exports, "isAudioDenoiserSupported", {
2399
2824
  enumerable: true,
2400
2825
  get: function () { return core.isAudioDenoiserSupported; }
2401
2826
  });
2827
+ Object.defineProperty(exports, "roomIntegrationContent", {
2828
+ enumerable: true,
2829
+ get: function () { return core.roomIntegrationContent; }
2830
+ });
2831
+ Object.defineProperty(exports, "roomIntegrationContentTagName", {
2832
+ enumerable: true,
2833
+ get: function () { return core.roomIntegrationContentTagName; }
2834
+ });
2835
+ Object.defineProperty(exports, "roomIntegrationPickerUrl", {
2836
+ enumerable: true,
2837
+ get: function () { return core.roomIntegrationPickerUrl; }
2838
+ });
2402
2839
  exports.GridCell = GridCell;
2403
2840
  exports.GridVideoView = GridVideoView;
2404
2841
  exports.ParticipantMenu = ParticipantMenu;
@@ -2408,5 +2845,9 @@ exports.ParticipantMenuTrigger = ParticipantMenuTrigger;
2408
2845
  exports.VideoGrid = Grid;
2409
2846
  exports.VideoView = VideoView;
2410
2847
  exports.WherebyProvider = Provider;
2848
+ exports.subscribeToRoomIntegrationPicker = subscribeToRoomIntegrationPicker;
2849
+ exports.useGrid = useGrid;
2411
2850
  exports.useLocalMedia = useLocalMedia;
2412
2851
  exports.useRoomConnection = useRoomConnection;
2852
+ exports.useRoomIntegrationPicker = useRoomIntegrationPicker;
2853
+ exports.useRoomIntegrationView = useRoomIntegrationView;