@xipkg/calls-compactview 0.1.54 → 0.1.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import { useDraggable, PointerSensor, useSensors, useSensor, DndContext, TouchSe
4
4
  import { useRoom, useCallsNavigation, useCalls } from '@xipkg/calls-providers';
5
5
  import { restrictToWindowEdges } from '@dnd-kit/modifiers';
6
6
  import { CSS } from '@dnd-kit/utilities';
7
- import { useTracks, usePersistentUserChoices, useLocalParticipant, useTrackToggle, useAudioWaveform } from '@livekit/components-react';
7
+ import { useTracks, usePersistentUserChoices, useLocalParticipant, useTrackToggle, useAudioWaveform, ScreenShareIcon } from '@livekit/components-react';
8
8
  import { Track, RemoteTrackPublication } from 'livekit-client';
9
9
  import { applyPinsFirst, useCallStore } from '@xipkg/calls-store';
10
10
  import { useScreenShareCleanup, useSortedTracks, useClassroomPins, useVideoBlur, useDeviceMenuGroups, useSyncModeToOthers, useParticipantJoinSync, useParticipantSounds } from '@xipkg/calls-hooks';
@@ -15,7 +15,7 @@ import { Button } from '@xipkg/button';
15
15
  import { ArrowLeft, ArrowRight, Account, SoundTwo, Users, External, ChevronUp, WhiteBoard, Maximize, MicrophoneOff, RedLine, ChevronBottom, ArrowUp } from '@xipkg/icons';
16
16
  import { cn } from '@xipkg/utils';
17
17
  import { useTranslation } from 'react-i18next';
18
- import { ParticipantTile, DevicesBar, LessonRecordButton, ScreenShareButton, DisconnectButton, ParticipantPinToggle, tileOverlayButtonClassName, PermissionsDialog, TrackMutedIndicator, ParticipantName, RaisedHandIndicator } from '@xipkg/calls-ui';
18
+ import { ParticipantTile, DevicesBar, LessonRecordButton, ScreenShareButton, DisconnectButton, ScreenShareStageToggle, ParticipantPinToggle, tileOverlayButtonClassName, PermissionsDialog, TrackMutedIndicator, ParticipantName, RaisedHandIndicator, VideoTrack, ScreenShareZoom } from '@xipkg/calls-ui';
19
19
  import { Tooltip, TooltipTrigger, TooltipContent } from '@xipkg/tooltip';
20
20
  import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem } from '@xipkg/dropdown';
21
21
  import { useChatStore, Chat, ChatButton } from '@xipkg/calls-chat';
@@ -232,8 +232,13 @@ var useCompactNavigation = () => {
232
232
  const baseSorted = useSortedTracks(participants, 1);
233
233
  const { pins } = useClassroomPins();
234
234
  const sorted = useMemo(() => applyPinsFirst(baseSorted, pins), [baseSorted, pins]);
235
- const currentParticipant = sorted[currentParticipantIndex] || null;
236
- const totalParticipants = sorted.length;
235
+ const screenShareStageIdentity = useCallStore((state) => state.screenShareStageIdentity);
236
+ const visibleSorted = useMemo(() => {
237
+ if (!screenShareStageIdentity) return sorted;
238
+ return sorted.filter((trackRef) => trackRef.source !== Track.Source.ScreenShare);
239
+ }, [screenShareStageIdentity, sorted]);
240
+ const currentParticipant = visibleSorted[currentParticipantIndex] || null;
241
+ const totalParticipants = visibleSorted.length;
237
242
  const canGoNext = currentParticipantIndex < totalParticipants - 1;
238
243
  const canGoPrev = currentParticipantIndex > 0;
239
244
  const goToNext = () => {
@@ -262,9 +267,13 @@ var useCompactNavigation = () => {
262
267
  setCurrentParticipantIndex(0);
263
268
  }
264
269
  }, [pinsKey, pins.length]);
270
+ useEffect(() => {
271
+ if (!screenShareStageIdentity) return;
272
+ setCurrentParticipantIndex(0);
273
+ }, [screenShareStageIdentity]);
265
274
  return {
266
275
  currentParticipant,
267
- participants: sorted,
276
+ participants: visibleSorted,
268
277
  currentIndex: currentParticipantIndex,
269
278
  totalParticipants,
270
279
  canGoNext,
@@ -554,7 +563,8 @@ function CompactCallCollapsedBar({
554
563
  participant,
555
564
  audioTrack,
556
565
  onExpand,
557
- className
566
+ className,
567
+ style
558
568
  }) {
559
569
  const { t } = useTranslation("calls");
560
570
  const { bars } = useAudioWaveform(audioTrack ?? void 0, {
@@ -565,6 +575,7 @@ function CompactCallCollapsedBar({
565
575
  return /* @__PURE__ */ jsxs(
566
576
  "div",
567
577
  {
578
+ style,
568
579
  className: cn(
569
580
  "bg-background-surface border-border-default flex items-center gap-2 rounded-2xl border px-2 py-2 shadow-lg",
570
581
  className
@@ -620,50 +631,70 @@ function CompactNavigationControls({
620
631
  onPrev,
621
632
  onNext,
622
633
  currentIndex,
623
- totalParticipants
634
+ totalParticipants,
635
+ persistent = false
624
636
  }) {
625
637
  const { t } = useTranslation("calls");
638
+ const hoverOnly = persistent ? "" : "sm:opacity-0 sm:group-hover:opacity-100";
626
639
  if (totalParticipants <= 1) {
627
640
  return null;
628
641
  }
629
642
  return /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute inset-0", children: [
630
- /* @__PURE__ */ jsx("div", { className: "pointer-events-auto absolute top-2 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx("div", { className: "bg-background-subtle/80 flex gap-1 rounded-full px-2 py-1 backdrop-blur-sm transition-opacity duration-200 sm:opacity-0 sm:group-hover:opacity-100", children: Array.from({ length: totalParticipants }, (_, index) => /* @__PURE__ */ jsx(
631
- "button",
643
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-auto absolute top-2 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx(
644
+ "div",
632
645
  {
633
- type: "button",
634
- onClick: () => {
635
- },
636
- className: `h-1.5 w-1.5 rounded-full transition-colors ${index === currentIndex ? "bg-text-primary" : "bg-text-primary/40 hover:bg-text-primary/70"}`,
637
- "aria-label": t("compactView.participant", { index: index + 1 })
638
- },
639
- index
640
- )) }) }),
641
- /* @__PURE__ */ jsx("div", { className: "pointer-events-auto absolute top-1/2 left-2 -translate-y-1/2 transition-opacity duration-200 sm:opacity-0 sm:group-hover:opacity-100", children: /* @__PURE__ */ jsxs(
642
- "button",
643
- {
644
- type: "button",
645
- disabled: !canPrev,
646
- onClick: onPrev,
647
- className: "bg-background-subtle/80 hover:bg-background-subtle fill-icon-primary z-10 flex items-center justify-center rounded-full p-2 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
648
- children: [
649
- /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" }),
650
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("compactView.prevParticipant") })
651
- ]
646
+ className: `bg-background-subtle/80 flex gap-1 rounded-full px-2 py-1 backdrop-blur-sm transition-opacity duration-200 ${hoverOnly}`,
647
+ children: Array.from({ length: totalParticipants }, (_, index) => /* @__PURE__ */ jsx(
648
+ "button",
649
+ {
650
+ type: "button",
651
+ onClick: () => {
652
+ },
653
+ className: `h-1.5 w-1.5 rounded-full transition-colors ${index === currentIndex ? "bg-text-primary" : "bg-text-primary/40 hover:bg-text-primary/70"}`,
654
+ "aria-label": t("compactView.participant", { index: index + 1 })
655
+ },
656
+ index
657
+ ))
652
658
  }
653
659
  ) }),
654
- /* @__PURE__ */ jsx("div", { className: "pointer-events-auto absolute top-1/2 right-2 -translate-y-1/2 transition-opacity duration-200 sm:opacity-0 sm:group-hover:opacity-100", children: /* @__PURE__ */ jsxs(
655
- "button",
660
+ /* @__PURE__ */ jsx(
661
+ "div",
656
662
  {
657
- type: "button",
658
- disabled: !canNext,
659
- onClick: onNext,
660
- className: "bg-background-subtle/80 hover:bg-background-subtle fill-icon-primary z-10 flex items-center justify-center rounded-full p-2 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
661
- children: [
662
- /* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4" }),
663
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("compactView.nextParticipant") })
664
- ]
663
+ className: `pointer-events-auto absolute top-1/2 left-2 -translate-y-1/2 transition-opacity duration-200 ${hoverOnly}`,
664
+ children: /* @__PURE__ */ jsxs(
665
+ "button",
666
+ {
667
+ type: "button",
668
+ disabled: !canPrev,
669
+ onClick: onPrev,
670
+ className: "bg-background-subtle/80 hover:bg-background-subtle fill-icon-primary z-10 flex items-center justify-center rounded-full p-2 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
671
+ children: [
672
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" }),
673
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("compactView.prevParticipant") })
674
+ ]
675
+ }
676
+ )
665
677
  }
666
- ) })
678
+ ),
679
+ /* @__PURE__ */ jsx(
680
+ "div",
681
+ {
682
+ className: `pointer-events-auto absolute top-1/2 right-2 -translate-y-1/2 transition-opacity duration-200 ${hoverOnly}`,
683
+ children: /* @__PURE__ */ jsxs(
684
+ "button",
685
+ {
686
+ type: "button",
687
+ disabled: !canNext,
688
+ onClick: onNext,
689
+ className: "bg-background-subtle/80 hover:bg-background-subtle fill-icon-primary z-10 flex items-center justify-center rounded-full p-2 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
690
+ children: [
691
+ /* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4" }),
692
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("compactView.nextParticipant") })
693
+ ]
694
+ }
695
+ )
696
+ }
697
+ )
667
698
  ] });
668
699
  }
669
700
  function CompactMultiViewControls({
@@ -718,7 +749,9 @@ function CompactCallVideoArea({
718
749
  multiCanNext,
719
750
  onMultiPrev,
720
751
  onMultiNext,
721
- onAudioExpand
752
+ onAudioExpand,
753
+ tileWidth,
754
+ tileHeight
722
755
  }) {
723
756
  const { t } = useTranslation("calls");
724
757
  const pip = usePiP();
@@ -764,9 +797,9 @@ function CompactCallVideoArea({
764
797
  !isMobile && compactViewMode === "expanded" && "h-auto"
765
798
  ),
766
799
  style: isMobile ? void 0 : {
767
- width: COMPACT_PANEL_WIDTH_PX,
800
+ width: tileWidth != null ? "100%" : COMPACT_PANEL_WIDTH_PX,
768
801
  touchAction: "none",
769
- ...compactViewMode === "basic" ? { height: TILE_HEIGHT_16_9_PX } : {}
802
+ ...compactViewMode === "basic" ? { height: tileHeight ?? TILE_HEIGHT_16_9_PX } : {}
770
803
  },
771
804
  children: [
772
805
  isMobile ? currentParticipant ? /* @__PURE__ */ jsx("div", { className: "relative h-full min-h-0 w-full min-w-0", children: /* @__PURE__ */ jsx(
@@ -821,6 +854,7 @@ function CompactCallVideoArea({
821
854
  }
822
855
  ) }) : emptyState,
823
856
  showPinPiPOverlay && /* @__PURE__ */ jsxs("div", { className: "absolute top-2 right-2 z-10 flex items-center gap-1", children: [
857
+ overlayTrackRef.source === Track.Source.ScreenShare ? /* @__PURE__ */ jsx(ScreenShareStageToggle, { trackRef: overlayTrackRef, inline: true }) : null,
824
858
  /* @__PURE__ */ jsx(ParticipantPinToggle, { trackRef: overlayTrackRef, inline: true }),
825
859
  showPiPButton && /* @__PURE__ */ jsxs(Tooltip, { children: [
826
860
  /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
@@ -855,7 +889,8 @@ function CompactCallVideoArea({
855
889
  onPrev,
856
890
  onNext,
857
891
  currentIndex,
858
- totalParticipants
892
+ totalParticipants,
893
+ persistent: tileHeight != null
859
894
  }
860
895
  )
861
896
  ]
@@ -871,9 +906,11 @@ function CompactCallBottomBar({
871
906
  showBackToBoardButton,
872
907
  onBackToBoard,
873
908
  onMaximize,
874
- isTutor
909
+ isTutor,
910
+ stageCompact = false
875
911
  }) {
876
912
  const { t } = useTranslation("calls");
913
+ const screenShareStage = useCallStore((state) => state.screenShareStageIdentity);
877
914
  const nextViewMode = getNextCompactViewMode(compactViewMode);
878
915
  const viewModeToggleMeta = {
879
916
  expanded: { Icon: Users, label: t("compactView.mode.expanded") },
@@ -885,110 +922,125 @@ function CompactCallBottomBar({
885
922
  "bg-background-surface border-border-default flex items-center justify-center rounded-2xl border p-1",
886
923
  withOutShadows ? "" : "shadow-lg"
887
924
  );
888
- return /* @__PURE__ */ jsxs("div", { className: "flex h-[40px] shrink-0 flex-row pb-[max(0px,env(safe-area-inset-bottom))]", children: [
889
- /* @__PURE__ */ jsx("div", { className: barCn, children: /* @__PURE__ */ jsx(
890
- DevicesBar,
891
- {
892
- className: "h-[32px] w-[32px]",
893
- microTrack: devices.microTrack,
894
- microEnabled: devices.microEnabled,
895
- microTrackToggle: devices.microTrackToggle,
896
- videoTrack: devices.videoTrack,
897
- videoEnabled: devices.videoEnabled,
898
- videoTrackToggle: devices.videoTrackToggle
899
- }
900
- ) }),
901
- !isMobile && /* @__PURE__ */ jsx("div", { className: cn(barCn, "ml-1"), children: /* @__PURE__ */ jsxs(Tooltip, { children: [
902
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
903
- Button,
904
- {
905
- size: "icon",
906
- variant: "none",
907
- onClick: onViewModeToggle,
908
- className: "hover:bg-background-page text-text-primary h-8 w-8 rounded-xl p-0",
909
- "aria-label": viewModeToggleMeta.label,
910
- children: /* @__PURE__ */ jsx(ViewModeIcon, { className: "h-6 w-6" })
911
- }
912
- ) }),
913
- /* @__PURE__ */ jsx(TooltipContent, { children: viewModeToggleMeta.label })
914
- ] }) }),
915
- showBackToBoardButton && /* @__PURE__ */ jsx("div", { className: cn(barCn, "ml-1"), children: /* @__PURE__ */ jsxs(Tooltip, { children: [
916
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
917
- Button,
918
- {
919
- size: "icon",
920
- variant: "primary",
921
- className: "h-8 w-8 rounded-xl p-0",
922
- onClick: onBackToBoard,
923
- "aria-label": t("compactView.toBoardAria"),
924
- children: /* @__PURE__ */ jsx(WhiteBoard, { className: "fill-action-primary-text h-6 w-6" })
925
- }
926
- ) }),
927
- /* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.toBoardTooltip") })
928
- ] }) }),
929
- /* @__PURE__ */ jsxs("div", { className: cn(barCn, "ml-auto"), children: [
930
- /* @__PURE__ */ jsx(LessonRecordButton, { className: "h-8 w-8" }),
931
- /* @__PURE__ */ jsx(ScreenShareButton, { className: "h-8 w-8" }),
932
- /* @__PURE__ */ jsx(ChatButton, { className: "h-8 w-8 min-w-8 rounded-xl" }),
933
- /* @__PURE__ */ jsx(RaiseHandButton, { className: "h-8 w-8 min-w-8" })
934
- ] }),
935
- /* @__PURE__ */ jsxs("div", { className: cn(barCn, "ml-1"), children: [
936
- isTutor ? /* @__PURE__ */ jsxs(DropdownMenu, { children: [
937
- /* @__PURE__ */ jsxs(Tooltip, { children: [
938
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
925
+ return /* @__PURE__ */ jsxs(
926
+ "div",
927
+ {
928
+ className: cn(
929
+ "flex h-10 shrink-0 flex-row",
930
+ stageCompact ? "max-w-full [scrollbar-width:none] overflow-x-auto [&::-webkit-scrollbar]:hidden [&>*]:shrink-0" : "pb-[max(0px,env(safe-area-inset-bottom))]"
931
+ ),
932
+ children: [
933
+ /* @__PURE__ */ jsx("div", { className: barCn, children: /* @__PURE__ */ jsx(
934
+ DevicesBar,
935
+ {
936
+ className: "h-[32px] w-[32px]",
937
+ microTrack: devices.microTrack,
938
+ microEnabled: devices.microEnabled,
939
+ microTrackToggle: devices.microTrackToggle,
940
+ videoTrack: devices.videoTrack,
941
+ videoEnabled: devices.videoEnabled,
942
+ videoTrackToggle: devices.videoTrackToggle
943
+ }
944
+ ) }),
945
+ !isMobile && /* @__PURE__ */ jsx("div", { className: cn(barCn, "ml-1"), children: /* @__PURE__ */ jsxs(Tooltip, { children: [
946
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
939
947
  Button,
940
948
  {
941
949
  size: "icon",
942
950
  variant: "none",
943
- className: "hover:bg-background-page text-text-primary relative m-0 h-8 w-8 rounded-xl p-0",
944
- children: /* @__PURE__ */ jsx(Maximize, { className: "fill-icon-primary" })
951
+ onClick: onViewModeToggle,
952
+ className: "hover:bg-background-page text-text-primary h-8 w-8 rounded-xl p-0",
953
+ "aria-label": viewModeToggleMeta.label,
954
+ children: /* @__PURE__ */ jsx(ViewModeIcon, { className: "h-6 w-6" })
945
955
  }
946
- ) }) }),
947
- /* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.returnToConference") })
948
- ] }),
949
- /* @__PURE__ */ jsxs(DropdownMenuContent, { side: "top", align: "end", className: "z-1000 min-w-[200px]", children: [
950
- /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-text-secondary text-sm", children: t("compactView.returnMenuLabel") }),
951
- /* @__PURE__ */ jsx(
952
- DropdownMenuItem,
953
- {
954
- onClick: () => onMaximize(false),
955
- className: "text-text-primary cursor-pointer text-sm",
956
- children: t("compactView.returnOnlyMe")
957
- }
958
- ),
959
- /* @__PURE__ */ jsx(
960
- DropdownMenuItem,
956
+ ) }),
957
+ /* @__PURE__ */ jsx(TooltipContent, { children: viewModeToggleMeta.label })
958
+ ] }) }),
959
+ showBackToBoardButton && /* @__PURE__ */ jsx("div", { className: cn(barCn, "ml-1"), children: /* @__PURE__ */ jsxs(Tooltip, { children: [
960
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
961
+ Button,
961
962
  {
962
- onClick: () => onMaximize(true),
963
- className: "text-text-primary cursor-pointer text-sm",
964
- children: t("compactView.returnEveryone")
963
+ size: "icon",
964
+ variant: "primary",
965
+ className: "h-8 w-8 rounded-xl p-0",
966
+ onClick: onBackToBoard,
967
+ "aria-label": t("compactView.toBoardAria"),
968
+ children: /* @__PURE__ */ jsx(WhiteBoard, { className: "fill-action-primary-text h-6 w-6" })
965
969
  }
966
- )
970
+ ) }),
971
+ /* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.toBoardTooltip") })
972
+ ] }) }),
973
+ /* @__PURE__ */ jsxs("div", { className: cn(barCn, "ml-auto"), children: [
974
+ /* @__PURE__ */ jsx(LessonRecordButton, { className: "h-8 w-8" }),
975
+ /* @__PURE__ */ jsx(ScreenShareButton, { className: "h-8 w-8" }),
976
+ /* @__PURE__ */ jsx(ChatButton, { className: "h-8 w-8 min-w-8 rounded-xl" }),
977
+ /* @__PURE__ */ jsx(RaiseHandButton, { className: "h-8 w-8 min-w-8" })
978
+ ] }),
979
+ /* @__PURE__ */ jsxs("div", { className: cn(barCn, "ml-1"), children: [
980
+ !screenShareStage && (isTutor ? /* @__PURE__ */ jsxs(DropdownMenu, { children: [
981
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
982
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
983
+ Button,
984
+ {
985
+ size: "icon",
986
+ variant: "none",
987
+ className: "hover:bg-background-page text-text-primary relative m-0 h-8 w-8 rounded-xl p-0",
988
+ children: /* @__PURE__ */ jsx(Maximize, { className: "fill-icon-primary" })
989
+ }
990
+ ) }) }),
991
+ /* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.returnToConference") })
992
+ ] }),
993
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { side: "top", align: "end", className: "z-1000 min-w-[200px]", children: [
994
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-text-secondary text-sm", children: t("compactView.returnMenuLabel") }),
995
+ /* @__PURE__ */ jsx(
996
+ DropdownMenuItem,
997
+ {
998
+ onClick: () => onMaximize(false),
999
+ className: "text-text-primary cursor-pointer text-sm",
1000
+ children: t("compactView.returnOnlyMe")
1001
+ }
1002
+ ),
1003
+ /* @__PURE__ */ jsx(
1004
+ DropdownMenuItem,
1005
+ {
1006
+ onClick: () => onMaximize(true),
1007
+ className: "text-text-primary cursor-pointer text-sm",
1008
+ children: t("compactView.returnEveryone")
1009
+ }
1010
+ )
1011
+ ] })
1012
+ ] }) : /* @__PURE__ */ jsxs(Tooltip, { children: [
1013
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1014
+ Button,
1015
+ {
1016
+ size: "icon",
1017
+ variant: "none",
1018
+ onClick: () => onMaximize(false),
1019
+ className: "hover:bg-background-page text-text-primary relative m-0 h-8 w-8 rounded-xl p-0",
1020
+ children: /* @__PURE__ */ jsx(Maximize, { className: "fill-icon-primary" })
1021
+ }
1022
+ ) }),
1023
+ /* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.returnToConference") })
1024
+ ] })),
1025
+ /* @__PURE__ */ jsx(DisconnectButton, { className: "h-[32px] w-[32px] rounded-xl" })
967
1026
  ] })
968
- ] }) : /* @__PURE__ */ jsxs(Tooltip, { children: [
969
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
970
- Button,
971
- {
972
- size: "icon",
973
- variant: "none",
974
- onClick: () => onMaximize(false),
975
- className: "hover:bg-background-page text-text-primary relative m-0 h-8 w-8 rounded-xl p-0",
976
- children: /* @__PURE__ */ jsx(Maximize, { className: "fill-icon-primary" })
977
- }
978
- ) }),
979
- /* @__PURE__ */ jsx(TooltipContent, { children: t("compactView.returnToConference") })
980
- ] }),
981
- /* @__PURE__ */ jsx(DisconnectButton, { className: "h-[32px] w-[32px] rounded-xl" })
982
- ] })
983
- ] });
1027
+ ]
1028
+ }
1029
+ );
984
1030
  }
985
- var CompactCall = ({ saveUserChoices = true, withOutShadows = false }) => {
1031
+ var CompactCall = ({
1032
+ saveUserChoices = true,
1033
+ withOutShadows = false,
1034
+ freeDrag = false,
1035
+ stageFrame = null
1036
+ }) => {
986
1037
  const isMobile = usePhoneLayout();
1038
+ const lockCompactModes = stageFrame?.lockCompactModes === true;
987
1039
  const { attributes, listeners, setNodeRef, transform } = useDraggable({
988
- id: "draggable-call",
989
- disabled: isMobile
1040
+ id: freeDrag ? "screen-share-stage-compact" : "draggable-call",
1041
+ disabled: freeDrag ? false : isMobile
990
1042
  });
991
- const style = isMobile ? void 0 : { transform: CSS.Translate.toString(transform) };
1043
+ const style = !freeDrag && isMobile ? void 0 : { transform: CSS.Translate.toString(transform) };
992
1044
  const { saveAudioInputEnabled, saveVideoInputEnabled } = usePersistentUserChoices({
993
1045
  preventSave: !saveUserChoices
994
1046
  });
@@ -1121,22 +1173,29 @@ var CompactCall = ({ saveUserChoices = true, withOutShadows = false }) => {
1121
1173
  "div",
1122
1174
  {
1123
1175
  ref: setNodeRef,
1176
+ ...freeDrag ? listeners : {},
1124
1177
  style: {
1125
1178
  ...style,
1126
- ...isMobile ? {} : { width: COMPACT_PANEL_WIDTH_PX, touchAction: "none" }
1179
+ ...isMobile && !freeDrag ? {} : {
1180
+ width: stageFrame?.width ?? COMPACT_PANEL_WIDTH_PX,
1181
+ touchAction: "none",
1182
+ maxWidth: "100%"
1183
+ }
1127
1184
  },
1128
- className: `compact-call-container flex flex-col ${isMobile ? "w-full" : "touch-none [&_video]:touch-none"}`,
1185
+ className: `compact-call-container flex flex-col ${isMobile && !freeDrag ? "w-full" : "touch-none [&_video]:touch-none"} ${freeDrag ? "cursor-grab active:cursor-grabbing" : ""}`,
1129
1186
  children: [
1130
1187
  /* @__PURE__ */ jsx(
1131
1188
  CompactCallVideoArea,
1132
1189
  {
1133
- isMobile,
1134
1190
  isCollapsed,
1135
1191
  onCollapsedChange: setIsCollapsed,
1136
1192
  withOutShadows,
1137
- dragAttributes: attributes,
1138
- dragListeners: listeners,
1139
- compactViewMode,
1193
+ dragAttributes: freeDrag ? void 0 : attributes,
1194
+ dragListeners: freeDrag ? void 0 : listeners,
1195
+ compactViewMode: lockCompactModes ? "basic" : compactViewMode,
1196
+ tileWidth: stageFrame?.width,
1197
+ tileHeight: stageFrame?.tileHeight,
1198
+ isMobile: stageFrame ? false : isMobile,
1140
1199
  currentParticipant,
1141
1200
  currentAudioTrack: currentAudioTrack ?? null,
1142
1201
  totalParticipants,
@@ -1176,7 +1235,8 @@ var CompactCall = ({ saveUserChoices = true, withOutShadows = false }) => {
1176
1235
  deviceGroups: cameraGroups
1177
1236
  }
1178
1237
  },
1179
- isMobile,
1238
+ isMobile: lockCompactModes || isMobile && stageFrame == null,
1239
+ stageCompact: lockCompactModes,
1180
1240
  compactViewMode,
1181
1241
  onViewModeToggle: () => setCompactViewMode(getNextCompactViewMode(compactViewMode)),
1182
1242
  showBackToBoardButton: !!showBackToBoardButton,
@@ -1189,6 +1249,340 @@ var CompactCall = ({ saveUserChoices = true, withOutShadows = false }) => {
1189
1249
  }
1190
1250
  );
1191
1251
  };
1252
+
1253
+ // src/ui/stageLayout.ts
1254
+ var EDGE_PX2 = 12;
1255
+ var CONTROLS_PX = 48;
1256
+ var EMPTY_INSETS = { top: 0, right: 0, bottom: 0, left: 0 };
1257
+ function viewportBox() {
1258
+ const viewport = window.visualViewport;
1259
+ return {
1260
+ width: viewport?.width ?? window.innerWidth,
1261
+ height: viewport?.height ?? window.innerHeight,
1262
+ offsetLeft: viewport?.offsetLeft ?? 0,
1263
+ offsetTop: viewport?.offsetTop ?? 0
1264
+ };
1265
+ }
1266
+ function readSafeInsets() {
1267
+ if (typeof document === "undefined") return EMPTY_INSETS;
1268
+ const probe = document.createElement("div");
1269
+ probe.style.cssText = "position:fixed;visibility:hidden;pointer-events:none;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)";
1270
+ document.body.appendChild(probe);
1271
+ const style = getComputedStyle(probe);
1272
+ const insets = {
1273
+ top: Number.parseFloat(style.paddingTop) || 0,
1274
+ right: Number.parseFloat(style.paddingRight) || 0,
1275
+ bottom: Number.parseFloat(style.paddingBottom) || 0,
1276
+ left: Number.parseFloat(style.paddingLeft) || 0
1277
+ };
1278
+ probe.remove();
1279
+ return insets;
1280
+ }
1281
+ function computeStageFrame() {
1282
+ const box = viewportBox();
1283
+ const insets = readSafeInsets();
1284
+ const landscape = box.width > box.height;
1285
+ const handheld = box.width <= 720 || box.height <= 500;
1286
+ if (!handheld) {
1287
+ const width2 = 400;
1288
+ return {
1289
+ handheld: false,
1290
+ landscape,
1291
+ lockCompactModes: false,
1292
+ width: width2,
1293
+ tileHeight: Math.round(width2 * 9 / 16),
1294
+ insets
1295
+ };
1296
+ }
1297
+ const maxWidth = Math.max(220, box.width - insets.left - insets.right - EDGE_PX2 * 2);
1298
+ const width = Math.min(400, maxWidth);
1299
+ const naturalTile = Math.round(width * 9 / 16);
1300
+ const maxPanel = box.height * 0.36;
1301
+ const tileHeight = landscape ? naturalTile : Math.max(84, Math.min(naturalTile, Math.floor(maxPanel - CONTROLS_PX)));
1302
+ return { handheld: true, landscape, lockCompactModes: !landscape, width, tileHeight, insets };
1303
+ }
1304
+ function sameStageFrame(left, right) {
1305
+ return left.handheld === right.handheld && left.landscape === right.landscape && left.lockCompactModes === right.lockCompactModes && left.width === right.width && left.tileHeight === right.tileHeight && left.insets.top === right.insets.top && left.insets.right === right.insets.right && left.insets.bottom === right.insets.bottom && left.insets.left === right.insets.left;
1306
+ }
1307
+ function clampStagePosition(x, y, width, height, insets) {
1308
+ const box = viewportBox();
1309
+ const minX = box.offsetLeft + insets.left + 8;
1310
+ const minY = box.offsetTop + insets.top + 8;
1311
+ const maxX = Math.max(minX, box.offsetLeft + box.width - insets.right - width - 8);
1312
+ const maxY = Math.max(minY, box.offsetTop + box.height - insets.bottom - height - 8);
1313
+ return {
1314
+ x: Math.min(Math.max(minX, x), maxX),
1315
+ y: Math.min(Math.max(minY, y), maxY)
1316
+ };
1317
+ }
1318
+ function defaultStagePosition(frame) {
1319
+ const box = viewportBox();
1320
+ const panelHeight = frame.tileHeight + CONTROLS_PX + 8;
1321
+ if (!frame.handheld) {
1322
+ return clampStagePosition(
1323
+ EDGE_PX2 + frame.insets.left,
1324
+ EDGE_PX2 + frame.insets.top,
1325
+ frame.width,
1326
+ panelHeight,
1327
+ frame.insets
1328
+ );
1329
+ }
1330
+ const y = box.offsetTop + box.height - frame.insets.bottom - EDGE_PX2 - panelHeight;
1331
+ const x = frame.landscape ? box.offsetLeft + frame.insets.left + EDGE_PX2 : box.offsetLeft + (box.width - frame.width) / 2;
1332
+ return clampStagePosition(x, y, frame.width, panelHeight, frame.insets);
1333
+ }
1334
+ function stagePanelHeight(frame) {
1335
+ return frame.tileHeight + CONTROLS_PX + 8;
1336
+ }
1337
+ var STAGE_GONE_MS = 500;
1338
+ function initialStageFrame() {
1339
+ if (typeof window === "undefined") {
1340
+ return {
1341
+ handheld: false,
1342
+ landscape: false,
1343
+ lockCompactModes: false,
1344
+ width: 400,
1345
+ tileHeight: 225,
1346
+ insets: { top: 0, right: 0, bottom: 0, left: 0 }
1347
+ };
1348
+ }
1349
+ return computeStageFrame();
1350
+ }
1351
+ var ScreenShareStage = ({ identity }) => {
1352
+ const { t } = useTranslation("calls");
1353
+ const updateStore = useCallStore((state) => state.updateStore);
1354
+ const closePiP = usePiP()?.closePiP;
1355
+ const overlayRef = useRef(null);
1356
+ const panelRef = useRef(null);
1357
+ const movedRef = useRef(false);
1358
+ const landscapeRef = useRef(null);
1359
+ const [frame, setFrame] = useState(initialStageFrame);
1360
+ const [position, setPosition] = useState(() => defaultStagePosition(initialStageFrame()));
1361
+ const tracks = useTracks([{ source: Track.Source.ScreenShare, withPlaceholder: false }], {
1362
+ onlySubscribed: false
1363
+ });
1364
+ const track = tracks.find((item) => item.participant.identity === identity) ?? null;
1365
+ const publication = track?.publication;
1366
+ const hasTrack = Boolean(publication);
1367
+ const sensors = useSensors(
1368
+ useSensor(CompactPointerSensor, { activationConstraint: { distance: 8 } }),
1369
+ useSensor(CompactTouchSensor, { activationConstraint: { distance: 8 } })
1370
+ );
1371
+ useEffect(() => {
1372
+ closePiP?.();
1373
+ }, [closePiP]);
1374
+ useEffect(() => {
1375
+ if (!(publication instanceof RemoteTrackPublication) || publication.isSubscribed) return;
1376
+ publication.setSubscribed(true);
1377
+ }, [publication]);
1378
+ useEffect(() => {
1379
+ if (hasTrack) return void 0;
1380
+ const timeoutId = window.setTimeout(() => {
1381
+ if (useCallStore.getState().screenShareStageIdentity === identity) {
1382
+ useCallStore.getState().updateStore("screenShareStageIdentity", null);
1383
+ }
1384
+ }, STAGE_GONE_MS);
1385
+ return () => window.clearTimeout(timeoutId);
1386
+ }, [hasTrack, identity]);
1387
+ useEffect(() => {
1388
+ const onKeyDown = (event) => {
1389
+ if (event.key !== "Escape" || event.defaultPrevented) return;
1390
+ event.preventDefault();
1391
+ updateStore("screenShareStageIdentity", null);
1392
+ };
1393
+ window.addEventListener("keydown", onKeyDown);
1394
+ return () => window.removeEventListener("keydown", onKeyDown);
1395
+ }, [updateStore]);
1396
+ useEffect(() => {
1397
+ const portalNode = overlayRef.current;
1398
+ if (!portalNode) return void 0;
1399
+ const hidden = [];
1400
+ Array.from(document.body.children).forEach((node) => {
1401
+ if (!(node instanceof HTMLElement)) return;
1402
+ if (node === portalNode || node.contains(portalNode)) return;
1403
+ if (node.hasAttribute("data-sonner-toaster")) return;
1404
+ if (node.hasAttribute("inert")) return;
1405
+ node.setAttribute("inert", "");
1406
+ hidden.push(node);
1407
+ });
1408
+ const { body, documentElement } = document;
1409
+ const previousBodyOverflow = body.style.overflow;
1410
+ const previousHtmlOverflow = documentElement.style.overflow;
1411
+ body.style.overflow = "hidden";
1412
+ documentElement.style.overflow = "hidden";
1413
+ portalNode?.focus();
1414
+ return () => {
1415
+ hidden.forEach((node) => node.removeAttribute("inert"));
1416
+ body.style.overflow = previousBodyOverflow;
1417
+ documentElement.style.overflow = previousHtmlOverflow;
1418
+ };
1419
+ }, []);
1420
+ useLayoutEffect(() => {
1421
+ const sync = () => {
1422
+ const next = computeStageFrame();
1423
+ setFrame((prev) => sameStageFrame(prev, next) ? prev : next);
1424
+ const flipped = landscapeRef.current !== null && landscapeRef.current !== next.landscape;
1425
+ landscapeRef.current = next.landscape;
1426
+ if (flipped) movedRef.current = false;
1427
+ setPosition((prev) => {
1428
+ if (!movedRef.current) {
1429
+ const placed = defaultStagePosition(next);
1430
+ if (placed.x === prev.x && placed.y === prev.y) return prev;
1431
+ return placed;
1432
+ }
1433
+ const node2 = panelRef.current;
1434
+ const clamped = clampStagePosition(
1435
+ prev.x,
1436
+ prev.y,
1437
+ node2?.offsetWidth ?? next.width,
1438
+ node2?.offsetHeight ?? stagePanelHeight(next),
1439
+ next.insets
1440
+ );
1441
+ if (clamped.x === prev.x && clamped.y === prev.y) return prev;
1442
+ return clamped;
1443
+ });
1444
+ };
1445
+ sync();
1446
+ const viewport = window.visualViewport;
1447
+ window.addEventListener("resize", sync);
1448
+ window.addEventListener("orientationchange", sync);
1449
+ viewport?.addEventListener("resize", sync);
1450
+ viewport?.addEventListener("scroll", sync);
1451
+ const node = panelRef.current;
1452
+ const observer = new ResizeObserver(sync);
1453
+ if (node) observer.observe(node);
1454
+ return () => {
1455
+ window.removeEventListener("resize", sync);
1456
+ window.removeEventListener("orientationchange", sync);
1457
+ viewport?.removeEventListener("resize", sync);
1458
+ viewport?.removeEventListener("scroll", sync);
1459
+ observer.disconnect();
1460
+ };
1461
+ }, []);
1462
+ const handleDragEnd = (event) => {
1463
+ movedRef.current = true;
1464
+ const node = panelRef.current;
1465
+ const current = computeStageFrame();
1466
+ setPosition((prev) => {
1467
+ const next = clampStagePosition(
1468
+ prev.x + event.delta.x,
1469
+ prev.y + event.delta.y,
1470
+ node?.offsetWidth ?? current.width,
1471
+ node?.offsetHeight ?? stagePanelHeight(current),
1472
+ current.insets
1473
+ );
1474
+ if (next.x === prev.x && next.y === prev.y) return prev;
1475
+ return next;
1476
+ });
1477
+ };
1478
+ if (typeof document === "undefined") return null;
1479
+ const sharerName = track?.participant.name;
1480
+ return createPortal(
1481
+ /* @__PURE__ */ jsxs(
1482
+ "div",
1483
+ {
1484
+ ref: overlayRef,
1485
+ role: "dialog",
1486
+ "aria-modal": "true",
1487
+ "aria-label": t("participant.stageTitle"),
1488
+ tabIndex: -1,
1489
+ className: "screen-share-stage fixed inset-0 z-[2100] bg-black outline-none",
1490
+ children: [
1491
+ /* @__PURE__ */ jsxs("div", { className: "relative h-full w-full", children: [
1492
+ track && publication ? frame.handheld ? /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(
1493
+ VideoTrack,
1494
+ {
1495
+ trackRef: track,
1496
+ manageSubscription: false,
1497
+ className: "h-full w-full bg-black object-contain"
1498
+ }
1499
+ ) }) : /* @__PURE__ */ jsx(ScreenShareZoom, { trackRef: track, className: "rounded-none", children: /* @__PURE__ */ jsx(
1500
+ VideoTrack,
1501
+ {
1502
+ trackRef: track,
1503
+ manageSubscription: false,
1504
+ className: "h-full w-full bg-black object-contain"
1505
+ }
1506
+ ) }) : null,
1507
+ track ? /* @__PURE__ */ jsxs(
1508
+ "div",
1509
+ {
1510
+ className: "bg-background-surface/80 pointer-events-none absolute z-20 flex h-6 max-w-[calc(100%-96px)] items-center gap-1.5 rounded-lg px-1.5 py-1 backdrop-blur",
1511
+ style: frame.handheld ? {
1512
+ top: "max(12px, env(safe-area-inset-top))",
1513
+ left: "max(12px, env(safe-area-inset-left))"
1514
+ } : {
1515
+ bottom: "max(16px, env(safe-area-inset-bottom))",
1516
+ left: "max(16px, env(safe-area-inset-left))"
1517
+ },
1518
+ children: [
1519
+ /* @__PURE__ */ jsx(ScreenShareIcon, { style: { marginRight: "0.25rem" } }),
1520
+ /* @__PURE__ */ jsxs("span", { className: "text-xs-base-size text-text-primary truncate leading-[16px]", children: [
1521
+ t("participant.screenSharePrefix"),
1522
+ sharerName ? /* @__PURE__ */ jsxs(Fragment, { children: [
1523
+ "\xA0",
1524
+ sharerName
1525
+ ] }) : null
1526
+ ] })
1527
+ ]
1528
+ }
1529
+ ) : null,
1530
+ /* @__PURE__ */ jsxs(
1531
+ "div",
1532
+ {
1533
+ className: "absolute z-40 flex items-center gap-1",
1534
+ style: {
1535
+ top: "max(12px, env(safe-area-inset-top))",
1536
+ right: "max(12px, env(safe-area-inset-right))"
1537
+ },
1538
+ children: [
1539
+ /* @__PURE__ */ jsx(ScreenShareStageToggle, { trackRef: track ?? void 0, inline: true }),
1540
+ track ? /* @__PURE__ */ jsx(ParticipantPinToggle, { trackRef: track, inline: true }) : null
1541
+ ]
1542
+ }
1543
+ )
1544
+ ] }),
1545
+ /* @__PURE__ */ jsx(
1546
+ DndContext,
1547
+ {
1548
+ sensors,
1549
+ onDragEnd: handleDragEnd,
1550
+ modifiers: [restrictToWindowEdges],
1551
+ autoScroll: false,
1552
+ children: /* @__PURE__ */ jsx(
1553
+ "div",
1554
+ {
1555
+ ref: panelRef,
1556
+ className: "absolute z-30 w-max",
1557
+ style: { left: position.x, top: position.y },
1558
+ children: /* @__PURE__ */ jsx(
1559
+ CompactCall,
1560
+ {
1561
+ freeDrag: true,
1562
+ stageFrame: frame.handheld ? {
1563
+ width: frame.width,
1564
+ tileHeight: frame.tileHeight,
1565
+ lockCompactModes: frame.lockCompactModes
1566
+ } : null
1567
+ }
1568
+ )
1569
+ }
1570
+ )
1571
+ }
1572
+ ),
1573
+ /* @__PURE__ */ jsx(
1574
+ Chat,
1575
+ {
1576
+ forceSheet: frame.handheld,
1577
+ compactPositionStyle: frame.handheld ? void 0 : { top: 56, right: 16, bottom: 16, zIndex: 20 }
1578
+ }
1579
+ )
1580
+ ]
1581
+ }
1582
+ ),
1583
+ document.body
1584
+ );
1585
+ };
1192
1586
  var useCompactDragActive = () => {
1193
1587
  const [isDragging, setIsDragging] = useState(false);
1194
1588
  useDndMonitor({
@@ -1216,7 +1610,7 @@ var DroppableCorner = ({ id, style }) => {
1216
1610
  {
1217
1611
  ref: setNodeRef,
1218
1612
  style,
1219
- className: `pointer-events-none absolute z-100 size-1/3 transition-all duration-200 ${isDragging ? "bg-status-info-background/20 ring-border-selected rounded-lg ring-2" : ""}`
1613
+ className: `pointer-events-none absolute z-20 size-1/3 transition-all duration-200 ${isDragging ? "bg-status-info-background/20 ring-border-selected rounded-lg ring-2" : ""}`
1220
1614
  }
1221
1615
  );
1222
1616
  };
@@ -1268,47 +1662,48 @@ var Compact = ({ children, hideOverlay = false }) => {
1268
1662
  const isBoardPage = navigation.pathnameIncludes("/board");
1269
1663
  const insets = useBoardChromeInsets(isBoardPage);
1270
1664
  const mobileContentMarginTop = hideOverlay || !isMobile ? 0 : (headerHeight > 0 ? headerHeight : COMPACT_MOBILE_OVERLAY_FALLBACK_PX) + COMPACT_MOBILE_CONTENT_GAP_PX;
1271
- const container = /* @__PURE__ */ jsx(
1272
- "div",
1273
- {
1274
- className: `relative flex h-dvh flex-col bg-transparent`,
1275
- "data-board-chrome-aware": "",
1276
- children: isMobile ? /* @__PURE__ */ jsxs(Fragment, { children: [
1277
- !hideOverlay && /* @__PURE__ */ jsx("div", { ref: headerRef, className: "fixed top-2 right-0 left-0 z-10 w-full px-2", children: /* @__PURE__ */ jsx(CompactCall, { withOutShadows: true }) }),
1278
- /* @__PURE__ */ jsx(
1279
- "div",
1280
- {
1281
- className: "flex min-h-0 flex-1 flex-col",
1282
- style: { marginTop: mobileContentMarginTop },
1283
- children
1284
- }
1285
- )
1286
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1287
- !hideOverlay && /* @__PURE__ */ jsxs(Fragment, { children: [
1288
- /* @__PURE__ */ jsx(DroppableAreas, { insets }),
1289
- /* @__PURE__ */ jsx(Chat, { compactPositionStyle: chatPositionStyle(activeCorner, insets) }),
1290
- /* @__PURE__ */ jsx(
1291
- "div",
1292
- {
1293
- className: "absolute z-100 transition-all duration-500 ease-out",
1294
- style: cornerStyle(activeCorner, insets),
1295
- children: /* @__PURE__ */ jsx(CompactCall, {})
1296
- }
1297
- )
1298
- ] }),
1665
+ const container = /* @__PURE__ */ jsx("div", { className: `relative flex h-dvh flex-col bg-transparent`, "data-board-chrome-aware": "", children: isMobile ? /* @__PURE__ */ jsxs(Fragment, { children: [
1666
+ !hideOverlay && /* @__PURE__ */ jsx("div", { ref: headerRef, className: "fixed top-2 right-0 left-0 z-10 w-full px-2", children: /* @__PURE__ */ jsx(CompactCall, { withOutShadows: true }) }),
1667
+ /* @__PURE__ */ jsx(
1668
+ "div",
1669
+ {
1670
+ className: "flex min-h-0 flex-1 flex-col",
1671
+ style: { marginTop: mobileContentMarginTop },
1299
1672
  children
1300
- ] })
1301
- }
1302
- );
1673
+ }
1674
+ )
1675
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1676
+ !hideOverlay && /* @__PURE__ */ jsxs(Fragment, { children: [
1677
+ /* @__PURE__ */ jsx(DroppableAreas, { insets }),
1678
+ /* @__PURE__ */ jsx(Chat, { compactPositionStyle: chatPositionStyle(activeCorner, insets) }),
1679
+ /* @__PURE__ */ jsx(
1680
+ "div",
1681
+ {
1682
+ className: "absolute z-20 transition-all duration-500 ease-out",
1683
+ style: cornerStyle(activeCorner, insets),
1684
+ children: /* @__PURE__ */ jsx(CompactCall, {})
1685
+ }
1686
+ )
1687
+ ] }),
1688
+ children
1689
+ ] }) });
1303
1690
  return /* @__PURE__ */ jsx(DndContext, { sensors, onDragEnd: handleDragEnd, modifiers: [restrictToWindowEdges], children: container });
1304
1691
  };
1305
1692
  var CompactViewInner = ({ children }) => {
1306
1693
  const { mode, token } = useCallStore();
1694
+ const screenShareStageIdentity = useCallStore((state) => state.screenShareStageIdentity);
1695
+ const isStarted = useCallStore((state) => state.isStarted);
1307
1696
  const { room } = useRoom();
1308
1697
  const pip = usePiP();
1309
1698
  const isPiPActive = !!pip?.isPiPActive;
1310
1699
  useParticipantJoinSync();
1311
1700
  useParticipantSounds();
1701
+ useEffect(() => {
1702
+ if (!screenShareStageIdentity) return;
1703
+ if (!room || !token || !isStarted) {
1704
+ useCallStore.getState().updateStore("screenShareStageIdentity", null);
1705
+ }
1706
+ }, [isStarted, room, screenShareStageIdentity, token]);
1312
1707
  const navigation = useCallsNavigation();
1313
1708
  const { updateStore: updateChatStore } = useChatStore();
1314
1709
  useEffect(() => {
@@ -1333,14 +1728,17 @@ var CompactViewInner = ({ children }) => {
1333
1728
  /* @__PURE__ */ jsx(PermissionsDialog, {})
1334
1729
  ] });
1335
1730
  }
1731
+ const stageLayer = screenShareStageIdentity && room && token && isStarted ? /* @__PURE__ */ jsx(ScreenShareStage, { identity: screenShareStageIdentity }, screenShareStageIdentity) : null;
1336
1732
  if (mode === "full") {
1337
1733
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1338
1734
  contentWrapper,
1735
+ stageLayer,
1339
1736
  /* @__PURE__ */ jsx(PermissionsDialog, {})
1340
1737
  ] });
1341
1738
  }
1342
1739
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1343
- /* @__PURE__ */ jsx(Compact, { hideOverlay: isPiPActive, children }),
1740
+ /* @__PURE__ */ jsx(Compact, { hideOverlay: isPiPActive || Boolean(screenShareStageIdentity), children }),
1741
+ stageLayer,
1344
1742
  /* @__PURE__ */ jsx(PermissionsDialog, {})
1345
1743
  ] });
1346
1744
  };