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

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.
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>