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