@100mslive/roomkit-react 0.2.8-alpha.7 → 0.2.8-alpha.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. package/dist/{HLSView-MYKM5AXS.js → HLSView-TOMPA4E4.js} +191 -188
  2. package/dist/HLSView-TOMPA4E4.js.map +7 -0
  3. package/dist/Prebuilt/components/HMSVideo/HLSQualitySelector.d.ts +3 -2
  4. package/dist/Prebuilt/components/HMSVideo/VideoProgress.d.ts +1 -3
  5. package/dist/Prebuilt/components/HMSVideo/index.d.ts +1 -3
  6. package/dist/Prebuilt/components/HMSVideo/utils.d.ts +0 -1
  7. package/dist/Prebuilt/components/Leave/DesktopLeaveRoom.d.ts +2 -1
  8. package/dist/Prebuilt/components/Leave/LeaveRoom.d.ts +2 -1
  9. package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +2 -1
  10. package/dist/Prebuilt/components/RaiseHand.d.ts +4 -1
  11. package/dist/Sheet/Sheet.d.ts +1 -0
  12. package/dist/{chunk-DRBTAFKN.js → chunk-FUDX3LDB.js} +820 -723
  13. package/dist/chunk-FUDX3LDB.js.map +7 -0
  14. package/dist/index.cjs.js +1324 -1220
  15. package/dist/index.cjs.js.map +4 -4
  16. package/dist/index.js +1 -1
  17. package/dist/meta.cjs.json +274 -209
  18. package/dist/meta.esbuild.json +283 -216
  19. package/package.json +6 -6
  20. package/src/Button/Button.tsx +4 -4
  21. package/src/Fieldset/Fieldset.tsx +1 -1
  22. package/src/Input/PasswordInput.stories.tsx +1 -1
  23. package/src/Pagination/StyledPagination.stories.tsx +2 -2
  24. package/src/Prebuilt/IconButton.tsx +1 -1
  25. package/src/Prebuilt/components/Chat/Chat.tsx +41 -1
  26. package/src/Prebuilt/components/Chat/ChatFooter.tsx +19 -15
  27. package/src/Prebuilt/components/EmojiReaction.jsx +32 -22
  28. package/src/Prebuilt/components/Footer/RoleOptions.tsx +125 -126
  29. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.tsx +85 -78
  30. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +3 -4
  31. package/src/Prebuilt/components/HMSVideo/MwebHLSViewTitle.tsx +49 -56
  32. package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +6 -6
  33. package/src/Prebuilt/components/HMSVideo/VideoTime.tsx +2 -1
  34. package/src/Prebuilt/components/HMSVideo/utils.ts +0 -8
  35. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx +1 -1
  36. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +50 -46
  37. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +10 -5
  38. package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +12 -6
  39. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +5 -2
  40. package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +4 -1
  41. package/src/Prebuilt/components/Polls/Voting/Voting.tsx +3 -2
  42. package/src/Prebuilt/components/Polls/common/OptionInputWithDelete.tsx +1 -1
  43. package/src/Prebuilt/components/Polls/common/utils.ts +2 -2
  44. package/src/Prebuilt/components/RaiseHand.tsx +8 -2
  45. package/src/Prebuilt/components/RoomDetails/RoomDetailsPane.tsx +41 -14
  46. package/src/Prebuilt/components/pdfAnnotator/shareScreenOptions.jsx +2 -2
  47. package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +1 -1
  48. package/src/Prebuilt/layouts/HLSView.jsx +58 -47
  49. package/src/Prebuilt/layouts/SidePane.tsx +1 -2
  50. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +3 -2
  51. package/src/Prebuilt/primitives/DialogContent.jsx +1 -1
  52. package/src/Sheet/Sheet.tsx +3 -3
  53. package/dist/HLSView-MYKM5AXS.js.map +0 -7
  54. package/dist/chunk-DRBTAFKN.js.map +0 -7
@@ -14,6 +14,7 @@ export function HLSQualitySelector({
14
14
  onQualityChange,
15
15
  selection,
16
16
  isAuto,
17
+ containerRef,
17
18
  }: {
18
19
  open: boolean;
19
20
  onOpenChange: (value: boolean) => void;
@@ -21,9 +22,14 @@ export function HLSQualitySelector({
21
22
  onQualityChange: (quality: { [key: string]: string | number } | HMSHLSLayer) => void;
22
23
  selection: HMSHLSLayer;
23
24
  isAuto: boolean;
25
+ containerRef?: HTMLDivElement;
24
26
  }) {
25
27
  const isMobile = useMedia(config.media.md);
26
28
  const isLandscape = useIsLandscape();
29
+
30
+ if (layers.length === 0) {
31
+ return null;
32
+ }
27
33
  if (isMobile || isLandscape) {
28
34
  return (
29
35
  <Sheet.Root open={open} onOpenChange={onOpenChange}>
@@ -39,86 +45,87 @@ export function HLSQualitySelector({
39
45
  <SettingsIcon />
40
46
  </Flex>
41
47
  </Sheet.Trigger>
42
-
43
- {layers.length > 0 && (
44
- <Sheet.Content css={{ bg: '$surface_default', pb: '$1' }} onClick={() => onOpenChange(false)}>
45
- <Sheet.Title
46
- css={{
47
- display: 'flex',
48
- color: '$on_surface_high',
49
- w: '100%',
50
- justifyContent: 'space-between',
51
- mt: '$8',
52
- fontSize: '$md',
53
- px: '$10',
54
- pb: '$8',
55
- borderBottom: '1px solid $border_bright',
56
- alignItems: 'center',
57
- }}
58
- >
59
- Quality
60
- <Sheet.Close css={{ color: '$on_surface_high' }} onClick={() => onOpenChange(false)}>
61
- <CrossIcon />
62
- </Sheet.Close>
63
- </Sheet.Title>
64
- {layers.map(layer => {
65
- return (
66
- <Flex
67
- align="center"
68
- css={{
69
- w: '100%',
70
- bg: '$surface_default',
71
- '&:hover': {
72
- bg: '$surface_brighter',
73
- },
74
- cursor: 'pointer',
75
- gap: '$4',
76
- py: '$8',
77
- px: '$10',
78
- }}
79
- key={layer.width}
80
- onClick={() => onQualityChange(layer)}
81
- >
82
- <Text variant="caption" css={{ fontWeight: '$semiBold' }}>
83
- {getQualityText(layer)}
84
- </Text>
85
- <Text variant="caption" css={{ flex: '1 1 0', c: '$on_surface_low', pl: '$2' }}>
86
- {getBitrateText(layer)}
87
- </Text>
88
- {!isAuto && layer.width === selection?.width && layer.height === selection?.height && (
89
- <CheckIcon width="16px" height="16px" />
90
- )}
91
- </Flex>
92
- );
93
- })}
94
- <Flex
95
- align="center"
96
- css={{
97
- w: '100%',
98
- bg: '$surface_default',
99
- '&:hover': {
100
- bg: '$surface_brighter',
101
- },
102
- cursor: 'pointer',
103
- gap: '$4',
104
- py: '$8',
105
- px: '$10',
106
- }}
107
- key="auto"
108
- onClick={() => onQualityChange({ height: 'auto' })}
109
- >
110
- <Text variant="caption" css={{ fontWeight: '$semiBold', flex: '1 1 0' }}>
111
- Auto
112
- </Text>
113
- {isAuto && <CheckIcon width="16px" height="16px" />}
114
- </Flex>
115
- </Sheet.Content>
116
- )}
48
+ <Sheet.Content
49
+ container={containerRef}
50
+ css={{ bg: '$surface_default', pb: '$1' }}
51
+ onClick={() => onOpenChange(false)}
52
+ >
53
+ <Sheet.Title
54
+ css={{
55
+ display: 'flex',
56
+ color: '$on_surface_high',
57
+ w: '100%',
58
+ justifyContent: 'space-between',
59
+ mt: '$8',
60
+ fontSize: '$md',
61
+ px: '$10',
62
+ pb: '$8',
63
+ borderBottom: '1px solid $border_bright',
64
+ alignItems: 'center',
65
+ }}
66
+ >
67
+ Quality
68
+ <Sheet.Close css={{ color: '$on_surface_high' }} onClick={() => onOpenChange(false)}>
69
+ <CrossIcon />
70
+ </Sheet.Close>
71
+ </Sheet.Title>
72
+ {layers.map(layer => {
73
+ return (
74
+ <Flex
75
+ align="center"
76
+ css={{
77
+ w: '100%',
78
+ bg: '$surface_default',
79
+ '&:hover': {
80
+ bg: '$surface_brighter',
81
+ },
82
+ cursor: 'pointer',
83
+ gap: '$4',
84
+ py: '$8',
85
+ px: '$10',
86
+ }}
87
+ key={layer.width}
88
+ onClick={() => onQualityChange(layer)}
89
+ >
90
+ <Text variant="caption" css={{ fontWeight: '$semiBold' }}>
91
+ {getQualityText(layer)}
92
+ </Text>
93
+ <Text variant="caption" css={{ flex: '1 1 0', c: '$on_surface_low', pl: '$2' }}>
94
+ {getBitrateText(layer)}
95
+ </Text>
96
+ {!isAuto && layer.width === selection?.width && layer.height === selection?.height && (
97
+ <CheckIcon width="16px" height="16px" />
98
+ )}
99
+ </Flex>
100
+ );
101
+ })}
102
+ <Flex
103
+ align="center"
104
+ css={{
105
+ w: '100%',
106
+ bg: '$surface_default',
107
+ '&:hover': {
108
+ bg: '$surface_brighter',
109
+ },
110
+ cursor: 'pointer',
111
+ gap: '$4',
112
+ py: '$8',
113
+ px: '$10',
114
+ }}
115
+ key="auto"
116
+ onClick={() => onQualityChange({ height: 'auto' })}
117
+ >
118
+ <Text variant="caption" css={{ fontWeight: '$semiBold', flex: '1 1 0' }}>
119
+ Auto
120
+ </Text>
121
+ {isAuto && <CheckIcon width="16px" height="16px" />}
122
+ </Flex>
123
+ </Sheet.Content>
117
124
  </Sheet.Root>
118
125
  );
119
126
  }
120
127
  return (
121
- <Dropdown.Root open={open} onOpenChange={value => onOpenChange(value)}>
128
+ <Dropdown.Root open={open} onOpenChange={value => onOpenChange(value)} modal={false}>
122
129
  <Dropdown.Trigger asChild data-testid="quality_selector">
123
130
  <Flex
124
131
  css={{
@@ -169,7 +176,7 @@ export function HLSQualitySelector({
169
176
  </Tooltip>
170
177
  </Flex>
171
178
  </Dropdown.Trigger>
172
- {layers.length > 0 && (
179
+ <Dropdown.Portal container={containerRef}>
173
180
  <Dropdown.Content
174
181
  sideOffset={5}
175
182
  align="end"
@@ -232,7 +239,7 @@ export function HLSQualitySelector({
232
239
  {isAuto && <CheckIcon width="16px" height="16px" />}
233
240
  </Dropdown.Item>
234
241
  </Dropdown.Content>
235
- )}
242
+ </Dropdown.Portal>
236
243
  </Dropdown.Root>
237
244
  );
238
245
  }
@@ -14,13 +14,12 @@ export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
14
14
  position: 'relative',
15
15
  '& video::cue': {
16
16
  color: 'white',
17
- // textShadow: '0px 0px 4px #000',
18
17
  whiteSpace: 'pre-line',
19
- fontSize: '$lg',
18
+ fontSize: '$sm',
20
19
  fontStyle: 'normal',
21
- fontWeight: '$semiBold',
20
+ fontWeight: '$regular',
22
21
  lineHeight: '$sm',
23
- letterSpacing: '0.5px',
22
+ letterSpacing: '0.25px',
24
23
  },
25
24
  '& video::-webkit-media-text-track-display': {
26
25
  padding: '0 $4',
@@ -1,13 +1,14 @@
1
- import React, { useCallback, useEffect, useRef, useState } from 'react';
2
- import { selectHLSState, selectPeerCount, useHMSStore } from '@100mslive/react-sdk';
1
+ import React from 'react';
2
+ import { ChevronDownIcon } from '@100mslive/react-icons';
3
3
  import { Flex } from '../../../Layout';
4
4
  import { Text } from '../../../Text';
5
5
  // @ts-ignore: No implicit any
6
6
  import { Logo } from '../Header/HeaderComponents';
7
- import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
8
- // @ts-ignore: No implicit Any
9
- import { getFormattedCount } from '../../common/utils';
10
- import { getTime } from './utils';
7
+ import { RoomDetailsRow } from '../RoomDetails/RoomDetailsRow';
8
+ import { useRoomLayoutHeader } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
9
+ // @ts-ignore
10
+ import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane';
11
+ import { SIDE_PANE_OPTIONS } from '../../common/constants';
11
12
 
12
13
  /*
13
14
  player handler --> left -> go live with timer or live, right -> expand icon
@@ -16,39 +17,41 @@ import { getTime } from './utils';
16
17
  half page will have chat or participant view
17
18
  */
18
19
  export const HLSViewTitle = () => {
19
- const peerCount = useHMSStore(selectPeerCount);
20
- const hlsState = useHMSStore(selectHLSState);
21
- const intervalRef = useRef<NodeJS.Timeout | null>(null);
22
- const { screenType } = useRoomLayoutConferencingScreen();
23
- const [liveTime, setLiveTime] = useState(0);
24
-
25
- const startTimer = useCallback(() => {
26
- intervalRef.current = setInterval(() => {
27
- const timeStamp = hlsState?.variants[0]?.[screenType === 'hls_live_streaming' ? 'startedAt' : 'initialisedAt'];
28
- if (hlsState?.running && timeStamp) {
29
- setLiveTime(Date.now() - timeStamp.getTime());
30
- }
31
- }, 60000);
32
- }, [hlsState?.running, hlsState?.variants, screenType]);
33
-
34
- useEffect(() => {
35
- if (hlsState?.running) {
36
- startTimer();
37
- const timeStamp = hlsState?.variants[0]?.[screenType === 'hls_live_streaming' ? 'startedAt' : 'initialisedAt'];
38
- if (hlsState?.running && timeStamp) {
39
- setLiveTime(Date.now() - timeStamp.getTime());
40
- }
41
- }
42
- if (!hlsState?.running && intervalRef.current) {
43
- clearInterval(intervalRef.current);
44
- }
45
- return () => {
46
- if (intervalRef.current) {
47
- clearInterval(intervalRef.current);
48
- }
49
- };
50
- }, [hlsState?.running, hlsState?.variants, screenType, startTimer]);
20
+ const { title, details } = useRoomLayoutHeader();
21
+ const toggleDetailsPane = useSidepaneToggle(SIDE_PANE_OPTIONS.ROOM_DETAILS);
22
+ const isDetailSidepaneOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.ROOM_DETAILS);
51
23
 
24
+ if (isDetailSidepaneOpen) {
25
+ return (
26
+ <Flex
27
+ gap="4"
28
+ align="center"
29
+ justify="between"
30
+ css={{
31
+ position: 'relative',
32
+ h: 'fit-content',
33
+ w: '100%',
34
+ borderBottom: '1px solid $border_bright',
35
+ p: '$8',
36
+ backgroundColor: '$surface_dim',
37
+ }}
38
+ >
39
+ <Text variant="sub2" css={{ fontWeight: '$semiBold' }}>
40
+ About Session
41
+ </Text>
42
+ <Flex
43
+ onClick={toggleDetailsPane}
44
+ css={{
45
+ color: '$on_surface_high',
46
+ cursor: 'pointer',
47
+ '&:hover': { opacity: '0.8' },
48
+ }}
49
+ >
50
+ <ChevronDownIcon />
51
+ </Flex>
52
+ </Flex>
53
+ );
54
+ }
52
55
  return (
53
56
  <Flex
54
57
  gap="4"
@@ -64,25 +67,15 @@ export const HLSViewTitle = () => {
64
67
  >
65
68
  <Logo />
66
69
  <Flex direction="column">
67
- <Text variant="sub2" css={{ fontWeight: '$semiBold' }}>
68
- Tech Talk
69
- </Text>
70
- <Flex gap="1">
71
- <Text variant="caption" css={{ color: '$on_surface_medium' }}>
72
- {getFormattedCount(peerCount) + ' watching'}
70
+ {title ? (
71
+ <Text variant="sub2" css={{ fontWeight: '$semiBold' }}>
72
+ {title}
73
73
  </Text>
74
- <Flex
75
- direction="column"
76
- css={{
77
- w: '$3',
78
- h: '$3',
79
- backgroundColor: '$on_surface_medium',
80
- borderRadius: '50%',
81
- alignSelf: 'center',
82
- }}
83
- />
84
- <Text variant="caption" css={{ color: '$on_surface_medium' }}>
85
- {'Started ' + getTime(liveTime) + ' ago'}
74
+ ) : null}
75
+ <Flex>
76
+ <RoomDetailsRow details={details} />
77
+ <Text variant="caption" css={{ color: '$on_surface_medium' }} onClick={toggleDetailsPane}>
78
+ &nbsp;...more
86
79
  </Text>
87
80
  </Flex>
88
81
  </Flex>
@@ -3,7 +3,7 @@ import { Box, Flex, Slider } from '../../..';
3
3
  import { useHMSPlayerContext } from './PlayerContext';
4
4
  import { getPercentage } from './utils';
5
5
 
6
- export const VideoProgress = ({ isDvr = true }: { isDvr: boolean }) => {
6
+ export const VideoProgress = () => {
7
7
  const { hlsPlayer } = useHMSPlayerContext();
8
8
  const [videoProgress, setVideoProgress] = useState<number>(0);
9
9
  const [bufferProgress, setBufferProgress] = useState(0);
@@ -20,10 +20,11 @@ export const VideoProgress = ({ isDvr = true }: { isDvr: boolean }) => {
20
20
  if (!videoEl) {
21
21
  return;
22
22
  }
23
- const videoProgress = Math.floor(getPercentage(videoEl.currentTime, videoEl.duration));
23
+ const duration = isFinite(videoEl.duration) ? videoEl.duration : videoEl.seekable?.end(0) || 0;
24
+ const videoProgress = Math.floor(getPercentage(videoEl.currentTime, duration));
24
25
  let bufferProgress = 0;
25
26
  if (videoEl.buffered.length > 0) {
26
- bufferProgress = Math.floor(getPercentage(videoEl.buffered?.end(0), videoEl.duration));
27
+ bufferProgress = Math.floor(getPercentage(videoEl.buffered?.end(0), duration));
27
28
  }
28
29
 
29
30
  setVideoProgress(isNaN(videoProgress) ? 0 : videoProgress);
@@ -48,7 +49,7 @@ export const VideoProgress = ({ isDvr = true }: { isDvr: boolean }) => {
48
49
  return null;
49
50
  }
50
51
  return (
51
- <Flex align="center" css={{ cursor: 'pointer', h: '$2', alignSelf: 'stretch', pointerEvents: isDvr ? '' : 'none' }}>
52
+ <Flex align="center" css={{ cursor: 'pointer', h: '$2', alignSelf: 'stretch' }}>
52
53
  <Slider
53
54
  id="video-actual-rest"
54
55
  css={{
@@ -56,7 +57,6 @@ export const VideoProgress = ({ isDvr = true }: { isDvr: boolean }) => {
56
57
  h: '$2',
57
58
  zIndex: 1,
58
59
  transition: `all .2s ease .5s`,
59
- pointerEvents: isDvr ? '' : 'none',
60
60
  }}
61
61
  min={0}
62
62
  max={100}
@@ -64,7 +64,7 @@ export const VideoProgress = ({ isDvr = true }: { isDvr: boolean }) => {
64
64
  value={[videoProgress]}
65
65
  showTooltip={false}
66
66
  onValueChange={onProgress}
67
- thumbStyles={{ w: '$6', h: '$6', display: isDvr ? '' : 'none' }}
67
+ thumbStyles={{ w: '$6', h: '$6' }}
68
68
  />
69
69
  <Box
70
70
  id="video-buffer"
@@ -12,7 +12,8 @@ export const VideoTime = () => {
12
12
  const timeupdateHandler = (currentTime: number) => {
13
13
  const videoEl = hlsPlayer?.getVideoElement();
14
14
  if (videoEl) {
15
- setVideoTime(getDurationFromSeconds(videoEl.duration - currentTime));
15
+ const duration = isFinite(videoEl.duration) ? videoEl.duration : videoEl.seekable.end(0) || 0;
16
+ setVideoTime(getDurationFromSeconds(duration - currentTime));
16
17
  } else {
17
18
  setVideoTime(getDurationFromSeconds(currentTime));
18
19
  }
@@ -25,11 +25,3 @@ export function getDurationFromSeconds(timeInSeconds: number) {
25
25
  }
26
26
  return videoTimeStr;
27
27
  }
28
-
29
- export function getTime(timeInMilles: number) {
30
- const timeInSeconds = Math.floor(timeInMilles / 1000);
31
- const hours = Math.floor(timeInSeconds / 3600);
32
- const minutes = Math.floor((timeInSeconds % 3600) / 60);
33
- const hour = hours !== 0 ? `${hours < 10 ? '0' : ''}${hours}` : '';
34
- return hour + `${hour ? 'h:' : ''}` + minutes + 'm';
35
- }
@@ -24,7 +24,7 @@ const IconSection = styled(IconButton, {
24
24
  h: '$14',
25
25
  p: '$4',
26
26
  r: '$1',
27
- bg: '$transparent',
27
+ bg: 'transparent',
28
28
  borderTopRightRadius: 0,
29
29
  borderColor: '$border_bright',
30
30
  borderBottomRightRadius: 0,
@@ -17,10 +17,12 @@ export const DesktopLeaveRoom = ({
17
17
  leaveRoom,
18
18
  screenType,
19
19
  endRoom,
20
+ container,
20
21
  }: {
21
22
  leaveRoom: (options?: { endStream?: boolean }) => Promise<void>;
22
23
  screenType: keyof ConferencingScreen;
23
24
  endRoom: () => Promise<void>;
25
+ container?: HTMLElement;
24
26
  }) => {
25
27
  const [open, setOpen] = useState(false);
26
28
  const [showLeaveRoomAlert, setShowLeaveRoomAlert] = useState(false);
@@ -69,54 +71,56 @@ export const DesktopLeaveRoom = ({
69
71
  <VerticalMenuIcon />
70
72
  </MenuTriggerButton>
71
73
  </Dropdown.Trigger>
72
- <Dropdown.Content css={{ p: 0, w: '$100' }} alignOffset={-50} sideOffset={10}>
73
- <Dropdown.Item
74
- css={{
75
- bg: '$surface_dim',
76
- color: '$on_surface_medium',
77
- '&:hover': { bg: '$surface_default', color: '$on_surface_high' },
78
- p: '0',
79
- }}
80
- data-testid="just_leave_btn"
81
- >
82
- <LeaveCard
83
- title={showStream ? 'Leave Stream' : 'Leave Session'}
84
- subtitle={`Others will continue after you leave. You can join the ${
85
- showStream ? 'stream' : 'session'
86
- } again.`}
87
- bg=""
88
- titleColor="$on_surface_high"
89
- icon={<ExitIcon height={24} width={24} style={{ transform: 'rotate(180deg)' }} />}
90
- onClick={async () => await leaveRoom()}
91
- css={{ p: '$8 $4' }}
92
- />
93
- </Dropdown.Item>
74
+ <Dropdown.Portal container={container}>
75
+ <Dropdown.Content css={{ p: 0, w: '$100' }} alignOffset={-50} sideOffset={10}>
76
+ <Dropdown.Item
77
+ css={{
78
+ bg: '$surface_dim',
79
+ color: '$on_surface_medium',
80
+ '&:hover': { bg: '$surface_default', color: '$on_surface_high' },
81
+ p: '0',
82
+ }}
83
+ data-testid="just_leave_btn"
84
+ >
85
+ <LeaveCard
86
+ title={showStream ? 'Leave Stream' : 'Leave Session'}
87
+ subtitle={`Others will continue after you leave. You can join the ${
88
+ showStream ? 'stream' : 'session'
89
+ } again.`}
90
+ bg=""
91
+ titleColor="$on_surface_high"
92
+ icon={<ExitIcon height={24} width={24} style={{ transform: 'rotate(180deg)' }} />}
93
+ onClick={async () => await leaveRoom()}
94
+ css={{ p: '$8 $4' }}
95
+ />
96
+ </Dropdown.Item>
94
97
 
95
- <Dropdown.Item
96
- css={{
97
- bg: '$alert_error_dim',
98
- color: '$alert_error_bright',
99
- '&:hover': { bg: '$alert_error_dim', color: '$alert_error_brighter' },
100
- p: '0',
101
- }}
102
- data-testid="end_room_btn"
103
- >
104
- <LeaveCard
105
- title={showStream ? 'End Stream' : 'End Session'}
106
- subtitle={`The ${
107
- showStream ? 'stream' : 'session'
108
- } will end for everyone. You can't undo this action.`}
109
- bg=""
110
- titleColor="$alert_error_brighter"
111
- icon={<StopIcon height={24} width={24} />}
112
- onClick={() => {
113
- setOpen(false);
114
- setShowEndStreamAlert(true);
98
+ <Dropdown.Item
99
+ css={{
100
+ bg: '$alert_error_dim',
101
+ color: '$alert_error_bright',
102
+ '&:hover': { bg: '$alert_error_dim', color: '$alert_error_brighter' },
103
+ p: '0',
115
104
  }}
116
- css={{ p: '$8 $4' }}
117
- />
118
- </Dropdown.Item>
119
- </Dropdown.Content>
105
+ data-testid="end_room_btn"
106
+ >
107
+ <LeaveCard
108
+ title={showStream ? 'End Stream' : 'End Session'}
109
+ subtitle={`The ${
110
+ showStream ? 'stream' : 'session'
111
+ } will end for everyone. You can't undo this action.`}
112
+ bg=""
113
+ titleColor="$alert_error_brighter"
114
+ icon={<StopIcon height={24} width={24} />}
115
+ onClick={() => {
116
+ setOpen(false);
117
+ setShowEndStreamAlert(true);
118
+ }}
119
+ css={{ p: '$8 $4' }}
120
+ />
121
+ </Dropdown.Item>
122
+ </Dropdown.Content>
123
+ </Dropdown.Portal>
120
124
  </Dropdown.Root>
121
125
  </Flex>
122
126
  ) : (
@@ -14,13 +14,18 @@ import {
14
14
  } from '@100mslive/react-sdk';
15
15
  import { config as cssConfig } from '../../../Theme';
16
16
  // @ts-ignore: No implicit Any
17
- // @ts-ignore: No implicit Any
18
17
  import { ToastManager } from '../Toast/ToastManager';
19
18
  import { DesktopLeaveRoom } from './DesktopLeaveRoom';
20
19
  import { MwebLeaveRoom } from './MwebLeaveRoom';
21
20
  import { useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
22
21
 
23
- export const LeaveRoom = ({ screenType }: { screenType: keyof ConferencingScreen }) => {
22
+ export const LeaveRoom = ({
23
+ screenType,
24
+ container,
25
+ }: {
26
+ screenType: keyof ConferencingScreen;
27
+ container?: HTMLElement;
28
+ }) => {
24
29
  const isConnected = useHMSStore(selectIsConnectedToRoom);
25
30
  const permissions = useHMSStore(selectPermissions);
26
31
  const isMobile = useMedia(cssConfig.media.md);
@@ -65,11 +70,11 @@ export const LeaveRoom = ({ screenType }: { screenType: keyof ConferencingScreen
65
70
  return null;
66
71
  }
67
72
  if (isMobileHLSStream || isLandscapeHLSStream) {
68
- return <MwebLeaveRoom leaveRoom={leaveRoom} endRoom={endRoom} />;
73
+ return <MwebLeaveRoom leaveRoom={leaveRoom} endRoom={endRoom} container={container} />;
69
74
  }
70
75
  return isMobile ? (
71
- <MwebLeaveRoom leaveRoom={leaveRoom} endRoom={endRoom} />
76
+ <MwebLeaveRoom leaveRoom={leaveRoom} endRoom={endRoom} container={container} />
72
77
  ) : (
73
- <DesktopLeaveRoom leaveRoom={leaveRoom} screenType={screenType} endRoom={endRoom} />
78
+ <DesktopLeaveRoom leaveRoom={leaveRoom} screenType={screenType} endRoom={endRoom} container={container} />
74
79
  );
75
80
  };
@@ -19,9 +19,11 @@ import { useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
19
19
  export const MwebLeaveRoom = ({
20
20
  leaveRoom,
21
21
  endRoom,
22
+ container,
22
23
  }: {
23
24
  leaveRoom: (options?: { endStream?: boolean }) => Promise<void>;
24
25
  endRoom: () => Promise<void>;
26
+ container?: HTMLElement;
25
27
  }) => {
26
28
  const [open, setOpen] = useState(false);
27
29
  const { screenType } = useRoomLayoutConferencingScreen();
@@ -44,9 +46,13 @@ export const MwebLeaveRoom = ({
44
46
  {showLeaveOptions ? (
45
47
  <Sheet.Root open={open} onOpenChange={setOpen}>
46
48
  <Sheet.Trigger asChild>
47
- <LeaveButton onClick={() => setOpen(!open)} />
49
+ <LeaveButton
50
+ onClick={() => {
51
+ setOpen(open => !open);
52
+ }}
53
+ />
48
54
  </Sheet.Trigger>
49
- <Sheet.Content>
55
+ <Sheet.Content container={container}>
50
56
  <LeaveCard
51
57
  title={showStream ? 'Leave Stream' : 'Leave Session'}
52
58
  subtitle={`Others will continue after you leave. You can join the ${
@@ -79,7 +85,7 @@ export const MwebLeaveRoom = ({
79
85
  <LeaveButton onClick={() => setShowLeaveRoomAlert(true)} />
80
86
  )}
81
87
  <Sheet.Root open={showEndStreamAlert} onOpenChange={setShowEndStreamAlert}>
82
- <Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }}>
88
+ <Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }} container={container}>
83
89
  <EndSessionContent
84
90
  setShowEndStreamAlert={setShowEndStreamAlert}
85
91
  leaveRoom={isStreamingOn ? leaveRoom : endRoom}
@@ -89,7 +95,7 @@ export const MwebLeaveRoom = ({
89
95
  </Sheet.Root>
90
96
 
91
97
  <Sheet.Root open={showLeaveRoomAlert} onOpenChange={setShowLeaveRoomAlert}>
92
- <Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }}>
98
+ <Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }} container={container}>
93
99
  <LeaveSessionContent setShowLeaveRoomAlert={setShowLeaveRoomAlert} leaveRoom={leaveRoom} />
94
100
  </Sheet.Content>
95
101
  </Sheet.Root>
@@ -102,7 +108,7 @@ const LeaveButton = ({ onClick }: { onClick: () => void }) => {
102
108
  const isLandscapeHLSStream = useLandscapeHLSStream();
103
109
 
104
110
  return isMobileHLSStream || isLandscapeHLSStream ? (
105
- <IconButton key="LeaveRoom" data-testid="leave_room_btn" onClick={() => onClick()}>
111
+ <IconButton key="LeaveRoom" data-testid="leave_room_btn" onClick={onClick}>
106
112
  <Tooltip title="Leave Room">
107
113
  <Box>
108
114
  <CrossIcon />
@@ -117,7 +123,7 @@ const LeaveButton = ({ onClick }: { onClick: () => void }) => {
117
123
  borderTopRightRadius: '$1',
118
124
  borderBottomRightRadius: '$1',
119
125
  }}
120
- onClick={() => onClick()}
126
+ onClick={onClick}
121
127
  >
122
128
  <Tooltip title="Leave Room">
123
129
  <Box>