@100mslive/roomkit-react 0.1.8 → 0.1.9-alpha.1

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 (140) hide show
  1. package/dist/{HLSView-DDGPZHA2.js → HLSView-4JC65BAY.js} +3 -3
  2. package/dist/Modal/Dialog.d.ts +402 -1706
  3. package/dist/Prebuilt/App.d.ts +5 -0
  4. package/dist/Prebuilt/AppContext.d.ts +1 -0
  5. package/dist/Prebuilt/AppStateContext.d.ts +16 -0
  6. package/dist/Prebuilt/components/ConferenceScreen.d.ts +2 -0
  7. package/dist/Prebuilt/components/Footer/PollsToggle.d.ts +2 -0
  8. package/dist/Prebuilt/components/LeaveScreen.d.ts +2 -0
  9. package/dist/Prebuilt/components/MwebLandscapePrompt.d.ts +2 -0
  10. package/dist/Prebuilt/components/Notifications/AutoplayBlockedModal.d.ts +2 -0
  11. package/dist/Prebuilt/components/Notifications/HLSFailureModal.d.ts +2 -0
  12. package/dist/Prebuilt/components/Notifications/InitErrorModal.d.ts +2 -0
  13. package/dist/Prebuilt/components/Notifications/Notifications.d.ts +2 -0
  14. package/dist/Prebuilt/components/Notifications/PeerNotifications.d.ts +1 -0
  15. package/dist/Prebuilt/components/Notifications/PermissionErrorModal.d.ts +2 -0
  16. package/dist/Prebuilt/components/Notifications/ReconnectNotifications.d.ts +2 -0
  17. package/dist/Prebuilt/components/Notifications/TrackBulkUnmuteModal.d.ts +2 -0
  18. package/dist/Prebuilt/components/Notifications/TrackNotifications.d.ts +1 -0
  19. package/dist/Prebuilt/components/Notifications/TrackUnmuteModal.d.ts +2 -0
  20. package/dist/Prebuilt/components/Polls/Polls.d.ts +2 -0
  21. package/dist/Prebuilt/components/Preview/PreviewJoin.d.ts +1 -2
  22. package/dist/Prebuilt/components/Preview/PreviewScreen.d.ts +2 -0
  23. package/dist/Prebuilt/components/hooks/useRedirectToLeave.d.ts +1 -1
  24. package/dist/{VirtualBackground-UVZJVOA2.js → VirtualBackground-MIRXD2HZ.js} +3 -5
  25. package/dist/{VirtualBackground-UVZJVOA2.js.map → VirtualBackground-MIRXD2HZ.js.map} +1 -1
  26. package/dist/chunk-322YFA55.js +14441 -0
  27. package/dist/chunk-322YFA55.js.map +7 -0
  28. package/dist/{chunk-6SQTFOK6.js → chunk-6UGU3UJL.js} +66 -3
  29. package/dist/chunk-6UGU3UJL.js.map +7 -0
  30. package/dist/context/DialogContext.d.ts +6 -0
  31. package/dist/hooks/useDialogContainerSelector.d.ts +1 -0
  32. package/dist/index.cjs.js +10944 -9974
  33. package/dist/index.cjs.js.map +4 -4
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.js +6 -2
  36. package/dist/meta.cjs.json +3871 -3188
  37. package/dist/meta.esbuild.json +4303 -3728
  38. package/dist/utils/animations.d.ts +11 -0
  39. package/package.json +6 -7
  40. package/src/Modal/Dialog.tsx +31 -3
  41. package/src/Prebuilt/App.tsx +46 -99
  42. package/src/Prebuilt/AppContext.tsx +4 -0
  43. package/src/Prebuilt/AppStateContext.tsx +71 -0
  44. package/src/Prebuilt/common/constants.js +35 -0
  45. package/src/Prebuilt/common/utils.js +47 -0
  46. package/src/Prebuilt/components/AppData/AppData.jsx +5 -0
  47. package/src/Prebuilt/components/AppData/useSidepane.js +23 -1
  48. package/src/Prebuilt/components/AppData/useUISettings.js +48 -4
  49. package/src/Prebuilt/components/{conference.jsx → ConferenceScreen.tsx} +30 -43
  50. package/src/Prebuilt/components/Footer/Footer.tsx +5 -0
  51. package/src/Prebuilt/components/Footer/PaginatedParticipants.tsx +63 -32
  52. package/src/Prebuilt/components/Footer/ParticipantList.jsx +2 -1
  53. package/src/Prebuilt/components/Footer/PollsToggle.tsx +22 -0
  54. package/src/Prebuilt/components/Footer/RoleAccordion.tsx +2 -2
  55. package/src/Prebuilt/components/Header/StreamActions.tsx +5 -3
  56. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +4 -5
  57. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +0 -4
  58. package/src/Prebuilt/components/{PostLeave.jsx → LeaveScreen.tsx} +6 -13
  59. package/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx +2 -3
  60. package/src/Prebuilt/components/MoreSettings/EmbedUrl.jsx +2 -3
  61. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +18 -1
  62. package/src/Prebuilt/components/{MwebLandscapePrompt.jsx → MwebLandscapePrompt.tsx} +10 -11
  63. package/src/Prebuilt/components/Notifications/{AutoplayBlockedModal.jsx → AutoplayBlockedModal.tsx} +2 -1
  64. package/src/Prebuilt/components/Notifications/{HLSFailureModal.jsx → HLSFailureModal.tsx} +10 -8
  65. package/src/Prebuilt/components/Notifications/{InitErrorModal.jsx → InitErrorModal.tsx} +5 -2
  66. package/src/Prebuilt/components/Notifications/{Notifications.jsx → Notifications.tsx} +41 -27
  67. package/src/Prebuilt/components/Notifications/{PeerNotifications.jsx → PeerNotifications.tsx} +3 -0
  68. package/src/Prebuilt/components/Notifications/{PermissionErrorModal.jsx → PermissionErrorModal.tsx} +6 -4
  69. package/src/Prebuilt/components/Notifications/{ReconnectNotifications.jsx → ReconnectNotifications.tsx} +11 -6
  70. package/src/Prebuilt/components/Notifications/{TrackBulkUnmuteModal.jsx → TrackBulkUnmuteModal.tsx} +9 -3
  71. package/src/Prebuilt/components/Notifications/{TrackUnmuteModal.jsx → TrackUnmuteModal.tsx} +9 -3
  72. package/src/Prebuilt/components/Notifications/index.tsx +1 -0
  73. package/src/Prebuilt/components/Polls/CreatePollQuiz/PollsQuizMenu.jsx +229 -0
  74. package/src/Prebuilt/components/Polls/CreatePollQuiz/Timer.jsx +71 -0
  75. package/src/Prebuilt/components/Polls/CreateQuestions/CreateQuestions.jsx +132 -0
  76. package/src/Prebuilt/components/Polls/CreateQuestions/DeleteQuestionModal.jsx +66 -0
  77. package/src/Prebuilt/components/Polls/CreateQuestions/QuestionForm.jsx +251 -0
  78. package/src/Prebuilt/components/Polls/CreateQuestions/SavedQuestion.jsx +57 -0
  79. package/src/Prebuilt/components/Polls/Polls.tsx +28 -0
  80. package/src/Prebuilt/components/Polls/Voting/PollResultSummary.jsx +125 -0
  81. package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +249 -0
  82. package/src/Prebuilt/components/Polls/Voting/StandardVoting.jsx +40 -0
  83. package/src/Prebuilt/components/Polls/Voting/TimedVoting.jsx +36 -0
  84. package/src/Prebuilt/components/Polls/Voting/Voting.jsx +99 -0
  85. package/src/Prebuilt/components/Polls/common/MultipleChoiceOptions.jsx +101 -0
  86. package/src/Prebuilt/components/Polls/common/OptionInputWithDelete.jsx +25 -0
  87. package/src/Prebuilt/components/Polls/common/SingleChoiceOptions.jsx +125 -0
  88. package/src/Prebuilt/components/Polls/common/StatusIndicator.jsx +47 -0
  89. package/src/Prebuilt/components/Polls/common/VoteCount.jsx +28 -0
  90. package/src/Prebuilt/components/Polls/common/VoteProgress.jsx +17 -0
  91. package/src/Prebuilt/components/Polls/common/VoterList.jsx +22 -0
  92. package/src/Prebuilt/components/Polls/common/Votes.jsx +72 -0
  93. package/src/Prebuilt/components/Preview/PreviewForm.tsx +3 -2
  94. package/src/Prebuilt/components/Preview/PreviewJoin.tsx +32 -27
  95. package/src/Prebuilt/components/Preview/{PreviewContainer.tsx → PreviewScreen.tsx} +2 -19
  96. package/src/Prebuilt/components/RaiseHand.jsx +1 -1
  97. package/src/Prebuilt/components/RoleChangeModal.jsx +2 -3
  98. package/src/Prebuilt/components/RoleChangeRequest/RequestPrompt.tsx +2 -3
  99. package/src/Prebuilt/components/Settings/SettingsModal.jsx +2 -3
  100. package/src/Prebuilt/components/Settings/StartRecording.jsx +15 -4
  101. package/src/Prebuilt/components/SidePaneTabs.tsx +1 -1
  102. package/src/Prebuilt/components/StatsForNerds.jsx +2 -3
  103. package/src/Prebuilt/components/Streaming/Common.jsx +31 -21
  104. package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +8 -9
  105. package/src/Prebuilt/components/VideoTile.jsx +37 -33
  106. package/src/Prebuilt/components/hooks/useAutoStartStreaming.tsx +3 -3
  107. package/src/Prebuilt/components/hooks/useRedirectToLeave.tsx +9 -17
  108. package/src/Prebuilt/components/pdfAnnotator/pdfFileOptions.jsx +2 -3
  109. package/src/Prebuilt/components/pdfAnnotator/submitPdf.jsx +1 -1
  110. package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +2 -3
  111. package/src/Prebuilt/layouts/EmbedView.jsx +47 -60
  112. package/src/Prebuilt/layouts/PDFView.jsx +49 -99
  113. package/src/Prebuilt/layouts/SidePane.tsx +8 -4
  114. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +2 -2
  115. package/src/Prebuilt/primitives/DialogContent.jsx +4 -5
  116. package/src/context/DialogContext.tsx +13 -0
  117. package/src/hooks/useDialogContainerSelector.tsx +7 -0
  118. package/src/index.ts +1 -0
  119. package/src/utils/animations.ts +6 -0
  120. package/dist/Prebuilt/components/Notifications/HeadlessEndRoomListener.d.ts +0 -2
  121. package/dist/Prebuilt/components/PrebuiltDialogPortal.d.ts +0 -4
  122. package/dist/Prebuilt/components/PrebuiltTileElements.d.ts +0 -2198
  123. package/dist/Prebuilt/components/Preview/PreviewContainer.d.ts +0 -3
  124. package/dist/chunk-6SQTFOK6.js.map +0 -7
  125. package/dist/chunk-HUMNPIYI.js +0 -70
  126. package/dist/chunk-HUMNPIYI.js.map +0 -7
  127. package/dist/chunk-PRM33R4R.js +0 -7160
  128. package/dist/chunk-PRM33R4R.js.map +0 -7
  129. package/dist/conference-N7S47TDK.js +0 -6602
  130. package/dist/conference-N7S47TDK.js.map +0 -7
  131. package/src/Prebuilt/components/GoLiveButton.jsx +0 -42
  132. package/src/Prebuilt/components/Notifications/HeadlessEndRoomListener.tsx +0 -23
  133. package/src/Prebuilt/components/PrebuiltDialogPortal.tsx +0 -6
  134. package/src/Prebuilt/components/PrebuiltTileElements.tsx +0 -5
  135. package/src/Prebuilt/components/Streaming/HLSStreaming.jsx +0 -220
  136. package/src/Prebuilt/components/Streaming/RTMPStreaming.jsx +0 -334
  137. package/src/Prebuilt/components/Streaming/StreamingLanding.jsx +0 -76
  138. /package/dist/{HLSView-DDGPZHA2.js.map → HLSView-4JC65BAY.js.map} +0 -0
  139. /package/{src/Prebuilt/components/Notifications/index.jsx → dist/Prebuilt/components/Notifications/index.d.ts} +0 -0
  140. /package/src/Prebuilt/components/Notifications/{TrackNotifications.jsx → TrackNotifications.tsx} +0 -0
@@ -0,0 +1,47 @@
1
+ // @ts-check
2
+ import React from 'react';
3
+ import { Flex, Text } from '../../../../';
4
+
5
+ export const StatusIndicator = ({ isLive, shouldShowTimer }) => {
6
+ return (
7
+ <Flex align="center">
8
+ <Flex
9
+ css={{
10
+ backgroundColor: isLive ? '$alert_error_default' : '$secondary_default',
11
+ p: '$2 $4',
12
+ borderRadius: shouldShowTimer ? '$0 0 0 $0' : '$0',
13
+ }}
14
+ >
15
+ <Text
16
+ variant="caption"
17
+ css={{
18
+ fontWeight: '$semiBold',
19
+ color: '$on_surface_high',
20
+ }}
21
+ >
22
+ {isLive ? 'LIVE' : 'ENDED'}
23
+ </Text>
24
+ </Flex>
25
+
26
+ {shouldShowTimer ? (
27
+ <Flex
28
+ css={{
29
+ borderRadius: '0 $0 $0 0',
30
+ p: '$2 $4',
31
+ backgroundColor: '$background_default',
32
+ }}
33
+ >
34
+ <Text
35
+ variant="caption"
36
+ css={{
37
+ fontWeight: '$semiBold',
38
+ color: '$on_surface_high',
39
+ }}
40
+ >
41
+ 0:32
42
+ </Text>
43
+ </Flex>
44
+ ) : null}
45
+ </Flex>
46
+ );
47
+ };
@@ -0,0 +1,28 @@
1
+ // @ts-check
2
+ import React from 'react';
3
+ import { Flex, Text } from '../../../../';
4
+
5
+ export const VoteCount = ({ isQuiz, voteCount, isCorrectAnswer }) => {
6
+ return (
7
+ <Flex css={{ alignItems: 'center' }}>
8
+ {isQuiz && (
9
+ <Text
10
+ variant="xs"
11
+ css={{
12
+ p: '$2',
13
+ mr: '$2',
14
+ color: isCorrectAnswer ? '$alert_success' : '$alert_error_default',
15
+ borderRadius: '$1',
16
+ border: `1px solid ${isCorrectAnswer ? '$alert_success' : '$alert_error_default'}`,
17
+ }}
18
+ >
19
+ {isCorrectAnswer ? 'Correct' : 'Incorrect'}
20
+ </Text>
21
+ )}
22
+ <Text variant="sm" css={{ color: '$on_surface_medium' }}>
23
+ {voteCount}&nbsp;
24
+ {voteCount === 1 ? 'vote' : 'votes'}
25
+ </Text>
26
+ </Flex>
27
+ );
28
+ };
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { Progress } from '../../../../';
3
+
4
+ export const VoteProgress = ({ option, totalResponses }) => {
5
+ const showProgress = typeof option.voteCount === 'number' && typeof totalResponses === 'number' && totalResponses > 0;
6
+ const progressValue = (100 * option.voteCount) / totalResponses;
7
+
8
+ return showProgress ? (
9
+ <Progress.Root value={progressValue}>
10
+ <Progress.Content
11
+ style={{
12
+ transform: `translateX(-${100 - progressValue}%)`,
13
+ }}
14
+ />
15
+ </Progress.Root>
16
+ ) : null;
17
+ };
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { Avatar, Flex, Text } from '../../../../';
3
+
4
+ export const VoterList = ({ voters }) => {
5
+ return voters.map((voter, index) => (
6
+ <Flex align="center" key={`${voter}-${index}`} css={{ gap: '$4', py: '$2' }}>
7
+ <Avatar
8
+ name={voter}
9
+ css={{
10
+ position: 'relative',
11
+ transform: 'unset',
12
+ fontSize: '$tiny',
13
+ size: '$9',
14
+ p: '$4',
15
+ }}
16
+ />
17
+ <Text variant="xs" css={{ color: '$on_surface_medium', fontWeight: '$semiBold' }}>
18
+ {voter}
19
+ </Text>
20
+ </Flex>
21
+ ));
22
+ };
@@ -0,0 +1,72 @@
1
+ import React from 'react';
2
+ import { Avatar, Box, Flex, Text, Tooltip } from '../../../../';
3
+ import { VoterList } from './VoterList';
4
+
5
+ // Shows number of votes, avatars of voters and list of voters on hover
6
+ export const Votes = ({ voters }) => {
7
+ const hiddenVotersCount = voters.length > 2 ? voters.length - 2 : 0;
8
+
9
+ return (
10
+ <Flex align="center" css={{ gap: '$4' }}>
11
+ <Text variant="sm" css={{ color: '$on_surface_medium' }}>
12
+ {voters.length}&nbsp;
13
+ {voters.length && voters.length !== 1 ? 'votes' : 'votes'}
14
+ </Text>
15
+ <Tooltip
16
+ side="bottom"
17
+ align="start"
18
+ disabled={hiddenVotersCount === 0}
19
+ boxCss={{
20
+ backgroundColor: '$surface_brighter',
21
+ borderRadius: '$1',
22
+ p: '$4 $6',
23
+ top: '$2',
24
+ zIndex: '20',
25
+ minWidth: '$44',
26
+ }}
27
+ title={<VoterList voters={voters} />}
28
+ >
29
+ <Flex align="center">
30
+ {voters.length
31
+ ? voters.slice(0, 2).map((voter, index) => (
32
+ <Avatar
33
+ name={voter}
34
+ css={{
35
+ position: 'relative',
36
+ transform: 'unset',
37
+ left: `${index * -1}px`,
38
+ fontSize: '$tiny',
39
+ size: '$9',
40
+ p: '$4',
41
+ zIndex: '5',
42
+ }}
43
+ />
44
+ ))
45
+ : null}
46
+ {hiddenVotersCount ? (
47
+ <Box
48
+ css={{
49
+ backgroundColor: '$secondary_default',
50
+ borderRadius: '$round',
51
+ position: 'relative',
52
+ left: '-$2',
53
+ p: '$2 $3',
54
+ }}
55
+ >
56
+ <Text
57
+ variant="caption"
58
+ css={{
59
+ fontWeight: '$semiBold',
60
+ color: '$on_surface_high',
61
+ fontSize: '$tiny',
62
+ }}
63
+ >
64
+ +{hiddenVotersCount}
65
+ </Text>
66
+ </Box>
67
+ ) : null}
68
+ </Flex>
69
+ </Tooltip>
70
+ </Flex>
71
+ );
72
+ };
@@ -27,10 +27,11 @@ const PreviewForm = ({
27
27
  e.preventDefault();
28
28
  };
29
29
  const isMobile = useMedia(cssConfig.media.md);
30
- const { isHLSRunning } = useRecordingStreaming();
30
+ const { isHLSRunning, isRTMPRunning } = useRecordingStreaming();
31
31
  const layout = useRoomLayout();
32
32
  const { join_form: joinForm = {} } = layout?.screens?.preview?.default?.elements || {};
33
- const showGoLive = joinForm?.join_btn_type === JoinForm_JoinBtnType.JOIN_BTN_TYPE_JOIN_AND_GO_LIVE && !isHLSRunning;
33
+ const showGoLive =
34
+ joinForm?.join_btn_type === JoinForm_JoinBtnType.JOIN_BTN_TYPE_JOIN_AND_GO_LIVE && !isHLSRunning && !isRTMPRunning;
34
35
 
35
36
  return (
36
37
  <Form
@@ -1,5 +1,5 @@
1
- import React, { Fragment, Suspense, useCallback, useEffect, useState } from 'react';
2
- import { useMedia } from 'react-use';
1
+ import React, { Fragment, Suspense, useCallback, useEffect, useMemo, useState } from 'react';
2
+ import { useMeasure, useMedia } from 'react-use';
3
3
  import {
4
4
  HMSRoomState,
5
5
  selectIsLocalVideoEnabled,
@@ -11,9 +11,7 @@ import {
11
11
  useParticipants,
12
12
  usePreviewJoin,
13
13
  useRecordingStreaming,
14
- // @ts-ignore: No implicit Any
15
14
  } from '@100mslive/react-sdk';
16
- // @ts-ignore: No implicit Any
17
15
  import { MicOffIcon, SettingsIcon } from '@100mslive/react-icons';
18
16
  import { Avatar, Box, config as cssConfig, Flex, flexCenter, styled, StyledVideoTile, Text, Video } from '../../..';
19
17
  import { AudioLevel } from '../../../AudioLevel';
@@ -31,7 +29,6 @@ import TileConnection from '../Connection/TileConnection';
31
29
  import FullPageProgress from '../FullPageProgress';
32
30
  // @ts-ignore: No implicit Any
33
31
  import { Logo } from '../Header/HeaderComponents';
34
- import { PrebuiltAudioIndicator } from '../PrebuiltTileElements';
35
32
  // @ts-ignore: No implicit Any
36
33
  import SettingsModal from '../Settings/SettingsModal';
37
34
  // @ts-ignore: No implicit Any
@@ -41,7 +38,7 @@ import { useAuthToken, useUISettings } from '../AppData/useUISettings';
41
38
  // @ts-ignore: No implicit Any
42
39
  import { defaultPreviewPreference, UserPreferencesKeys, useUserPreferences } from '../hooks/useUserPreferences';
43
40
  // @ts-ignore: No implicit Any
44
- import { getFormattedCount } from '../../common/utils';
41
+ import { calculateAvatarAndAttribBoxSize, getFormattedCount } from '../../common/utils';
45
42
  // @ts-ignore: No implicit Any
46
43
  import { UI_SETTINGS } from '../../common/constants';
47
44
 
@@ -56,13 +53,24 @@ const getParticipantChipContent = (peerCount = 0) => {
56
53
  return `${formattedNum} other${parseInt(formattedNum) === 1 ? '' : 's'} in the session`;
57
54
  };
58
55
 
56
+ const useLocalTileAspectRatio = () => {
57
+ const localPeer = useHMSStore(selectLocalPeer);
58
+ const videoTrack = useHMSStore(selectVideoTrackByID(localPeer?.videoTrack));
59
+ const isMobile = useMedia(cssConfig.media.md);
60
+ let aspectRatio = 0;
61
+ if (videoTrack?.width && videoTrack?.height) {
62
+ aspectRatio = videoTrack.width / videoTrack.height;
63
+ } else {
64
+ aspectRatio = isMobile ? 9 / 16 : 16 / 9;
65
+ }
66
+ return aspectRatio;
67
+ };
68
+
59
69
  const PreviewJoin = ({
60
- onJoin,
61
70
  skipPreview,
62
71
  initialName,
63
72
  asRole,
64
73
  }: {
65
- onJoin: () => void;
66
74
  skipPreview?: boolean;
67
75
  initialName?: string;
68
76
  asRole?: string;
@@ -102,16 +110,11 @@ const PreviewJoin = ({
102
110
  name,
103
111
  });
104
112
  join();
105
- onJoin && onJoin();
106
- }, [join, name, setPreviewPreference, onJoin]);
113
+ }, [join, name, setPreviewPreference]);
107
114
  const roomLayout = useRoomLayout();
108
115
 
109
116
  const { preview_header: previewHeader = {} } = roomLayout?.screens?.preview?.default?.elements || {};
110
- const localPeer = useHMSStore(selectLocalPeer);
111
- const videoTrack = useHMSStore(selectVideoTrackByID(localPeer?.videoTrack));
112
- const isMobile = useMedia(cssConfig.media.md);
113
- const aspectRatio =
114
- videoTrack?.width && videoTrack?.height ? videoTrack.width / videoTrack.height : isMobile ? 9 / 16 : 16 / 9;
117
+ const aspectRatio = useLocalTileAspectRatio();
115
118
  useEffect(() => {
116
119
  if (authToken) {
117
120
  if (skipPreview) {
@@ -204,13 +207,16 @@ export const PreviewTile = ({ name, error }: { name: string; error?: boolean })
204
207
  const trackSelector = selectVideoTrackByID(localPeer?.videoTrack);
205
208
  const track = useHMSStore(trackSelector);
206
209
  const showMuteIcon = !isLocalAudioEnabled || !toggleAudio;
207
- const videoTrack = useHMSStore(selectVideoTrackByID(localPeer?.videoTrack));
208
- const isMobile = useMedia(cssConfig.media.md);
209
- const aspectRatio =
210
- videoTrack?.width && videoTrack?.height ? videoTrack.width / videoTrack.height : isMobile ? 9 / 16 : 16 / 9;
210
+ const aspectRatio = useLocalTileAspectRatio();
211
+ const [ref, { width: calculatedWidth, height: calculatedHeight }] = useMeasure<HTMLDivElement>();
212
+ const [avatarSize, attribBoxSize] = useMemo(
213
+ () => calculateAvatarAndAttribBoxSize(calculatedWidth, calculatedHeight),
214
+ [calculatedWidth, calculatedHeight],
215
+ );
211
216
 
212
217
  return (
213
218
  <StyledVideoTile.Container
219
+ ref={ref}
214
220
  css={{
215
221
  bg: '$surface_default',
216
222
  aspectRatio,
@@ -235,22 +241,21 @@ export const PreviewTile = ({ name, error }: { name: string; error?: boolean })
235
241
 
236
242
  {!isVideoOn ? (
237
243
  <StyledVideoTile.AvatarContainer>
238
- <Avatar name={name} data-testid="preview_avatar_tile" size="medium" />
244
+ <Avatar name={name} data-testid="preview_avatar_tile" size={avatarSize} />
239
245
  </StyledVideoTile.AvatarContainer>
240
246
  ) : null}
241
247
  </>
242
- ) : !error ? (
243
- <FullPageProgress />
244
248
  ) : null}
249
+ {!localPeer && !error ? <FullPageProgress /> : null}
245
250
 
246
251
  {showMuteIcon ? (
247
- <PrebuiltAudioIndicator>
248
- <MicOffIcon height={16} width={16} />
249
- </PrebuiltAudioIndicator>
252
+ <StyledVideoTile.AudioIndicator size={attribBoxSize}>
253
+ <MicOffIcon />
254
+ </StyledVideoTile.AudioIndicator>
250
255
  ) : (
251
- <PrebuiltAudioIndicator>
256
+ <StyledVideoTile.AudioIndicator size={attribBoxSize}>
252
257
  <AudioLevel trackId={localPeer?.audioTrack} />
253
- </PrebuiltAudioIndicator>
258
+ </StyledVideoTile.AudioIndicator>
254
259
  )}
255
260
  </StyledVideoTile.Container>
256
261
  );
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- import { useNavigate, useParams } from 'react-router-dom';
3
2
  import { useSearchParam } from 'react-use';
4
3
  import { Flex } from '../../..';
5
4
  import { useHMSPrebuiltContext } from '../../AppContext';
@@ -14,25 +13,16 @@ import { useAuthToken } from '../AppData/useUISettings';
14
13
  // @ts-ignore: No implicit Any
15
14
  import { QUERY_PARAM_PREVIEW_AS_ROLE } from '../../common/constants';
16
15
 
17
- const PreviewContainer = () => {
18
- const navigate = useNavigate();
16
+ export const PreviewScreen = () => {
19
17
  const { isPreviewScreenEnabled } = useRoomLayoutPreviewScreen();
20
18
  const skipPreview = !isPreviewScreenEnabled;
21
19
  const previewAsRole = useSearchParam(QUERY_PARAM_PREVIEW_AS_ROLE);
22
20
  const { userName } = useHMSPrebuiltContext();
23
21
  const initialName = userName || (skipPreview ? 'Beam' : '');
24
- const { roomId: urlRoomId, role: userRole } = useParams(); // from the url
25
22
  const authToken = useAuthToken();
26
23
  const roomLayout = useRoomLayout();
27
24
  const { preview_header: previewHeader = {} } = roomLayout?.screens?.preview?.default?.elements || {};
28
25
 
29
- const onJoin = () => {
30
- let meetingURL = `/meeting/${urlRoomId}`;
31
- if (userRole) {
32
- meetingURL += `/${userRole}`;
33
- }
34
- navigate(meetingURL);
35
- };
36
26
  return (
37
27
  <Flex direction="column" css={{ size: '100%' }}>
38
28
  <Flex
@@ -41,12 +31,7 @@ const PreviewContainer = () => {
41
31
  align="center"
42
32
  >
43
33
  {authToken && Object.keys(previewHeader).length > 0 ? (
44
- <PreviewJoin
45
- initialName={initialName}
46
- skipPreview={skipPreview}
47
- asRole={previewAsRole ?? undefined}
48
- onJoin={onJoin}
49
- />
34
+ <PreviewJoin initialName={initialName} skipPreview={skipPreview} asRole={previewAsRole ?? undefined} />
50
35
  ) : (
51
36
  <FullPageProgress />
52
37
  )}
@@ -54,5 +39,3 @@ const PreviewContainer = () => {
54
39
  </Flex>
55
40
  );
56
41
  };
57
-
58
- export default PreviewContainer;
@@ -9,7 +9,7 @@ export const RaiseHand = () => {
9
9
  const { isHandRaised, toggleHandRaise } = useMyMetadata();
10
10
  return (
11
11
  <Tooltip title={isHandRaised ? 'Lower hand' : 'Raise hand'}>
12
- <IconButton active={!isHandRaised} onClick={async () => await toggleHandRaise()}>
12
+ <IconButton data-testid="hand_raise_btn" active={!isHandRaised} onClick={async () => await toggleHandRaise()}>
13
13
  <HandIcon />
14
14
  </IconButton>
15
15
  </Tooltip>
@@ -9,7 +9,6 @@ import { Box, Flex } from '../../Layout';
9
9
  import { Dialog } from '../../Modal';
10
10
  import { Text } from '../../Text';
11
11
  import { Tooltip } from '../../Tooltip';
12
- import { PrebuiltDialogPortal } from './PrebuiltDialogPortal';
13
12
  import { useDropdownSelection } from './hooks/useDropdownSelection';
14
13
  import { useFilteredRoles } from '../common/hooks';
15
14
  import { textEllipsis } from '../../utils';
@@ -48,7 +47,7 @@ export const RoleChangeModal = ({ peerId, onOpenChange }) => {
48
47
  const peerNameMaxWidth = 200;
49
48
  return (
50
49
  <Dialog.Root defaultOpen onOpenChange={onOpenChange}>
51
- <PrebuiltDialogPortal>
50
+ <Dialog.Portal>
52
51
  <Dialog.Overlay />
53
52
  <Dialog.Content css={{ width: 'min(400px,80%)', p: '$10' }}>
54
53
  <Dialog.Title css={{ p: 0 }} asChild>
@@ -180,7 +179,7 @@ export const RoleChangeModal = ({ peerId, onOpenChange }) => {
180
179
  </Box>
181
180
  </Flex>
182
181
  </Dialog.Content>
183
- </PrebuiltDialogPortal>
182
+ </Dialog.Portal>
184
183
  </Dialog.Root>
185
184
  );
186
185
  };
@@ -2,7 +2,6 @@ import React from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import { Box, Button, config as cssConfig, Dialog, Flex, Text } from '../../..';
4
4
  import { Sheet } from '../../../Sheet';
5
- import { PrebuiltDialogPortal } from '../PrebuiltDialogPortal';
6
5
 
7
6
  export const RequestPrompt = ({
8
7
  open = true,
@@ -35,7 +34,7 @@ export const RequestPrompt = ({
35
34
 
36
35
  return (
37
36
  <Dialog.Root open={open} onOpenChange={onOpenChange}>
38
- <PrebuiltDialogPortal>
37
+ <Dialog.Portal>
39
38
  <Dialog.Overlay />
40
39
  <Dialog.Content css={{ p: '$10' }}>
41
40
  <Dialog.Title css={{ p: 0, display: 'flex', flexDirection: 'row', gap: '$md', justifyContent: 'center' }}>
@@ -44,7 +43,7 @@ export const RequestPrompt = ({
44
43
  <Box css={{ mt: '$4', mb: '$10' }}>{body}</Box>
45
44
  <RequestActions actionText={actionText} onAction={onAction} />
46
45
  </Dialog.Content>
47
- </PrebuiltDialogPortal>
46
+ </Dialog.Portal>
48
47
  </Dialog.Root>
49
48
  );
50
49
  };
@@ -9,7 +9,6 @@ import { Sheet } from '../../../Sheet';
9
9
  import { Tabs } from '../../../Tabs';
10
10
  import { Text } from '../../../Text';
11
11
  import { config as cssConfig } from '../../../Theme';
12
- import { PrebuiltDialogPortal } from '../PrebuiltDialogPortal';
13
12
  import { settingContent, settingsList } from './common.js';
14
13
 
15
14
  const SettingsModal = ({ open, onOpenChange, screenType, children = <></> }) => {
@@ -187,7 +186,7 @@ const DesktopSettingModal = ({
187
186
  return (
188
187
  <Dialog.Root open={open} onOpenChange={onOpenChange}>
189
188
  <Dialog.Trigger asChild>{children}</Dialog.Trigger>
190
- <PrebuiltDialogPortal>
189
+ <Dialog.Portal>
191
190
  <Dialog.Overlay />
192
191
  <Dialog.Content
193
192
  css={{
@@ -257,7 +256,7 @@ const DesktopSettingModal = ({
257
256
  </IconButton>
258
257
  </Dialog.Close>
259
258
  </Dialog.Content>
260
- </PrebuiltDialogPortal>
259
+ </Dialog.Portal>
261
260
  </Dialog.Root>
262
261
  );
263
262
  };
@@ -2,13 +2,24 @@ import React, { useState } from 'react';
2
2
  import { selectPermissions, useHMSActions, useHMSStore, useRecordingStreaming } from '@100mslive/react-sdk';
3
3
  import { AlertTriangleIcon } from '@100mslive/react-icons';
4
4
  import { Button, Dialog, Flex, Text } from '../../../';
5
- import { PrebuiltDialogPortal } from '../PrebuiltDialogPortal';
6
5
  import { ResolutionInput } from '../Streaming/ResolutionInput';
7
- import { getResolution } from '../Streaming/RTMPStreaming';
8
6
  import { ToastManager } from '../Toast/ToastManager';
9
7
  import { useSetAppDataByKey } from '../AppData/useUISettings';
10
8
  import { APP_DATA, RTMP_RECORD_DEFAULT_RESOLUTION } from '../../common/constants';
11
9
 
10
+ export function getResolution(recordingResolution) {
11
+ const resolution = {};
12
+ if (recordingResolution.width) {
13
+ resolution.width = recordingResolution.width;
14
+ }
15
+ if (recordingResolution.height) {
16
+ resolution.height = recordingResolution.height;
17
+ }
18
+ if (Object.keys(resolution).length > 0) {
19
+ return resolution;
20
+ }
21
+ }
22
+
12
23
  const StartRecording = ({ open, onOpenChange }) => {
13
24
  const permissions = useHMSStore(selectPermissions);
14
25
  const [resolution, setResolution] = useState(RTMP_RECORD_DEFAULT_RESOLUTION);
@@ -22,7 +33,7 @@ const StartRecording = ({ open, onOpenChange }) => {
22
33
  if (isBrowserRecordingOn) {
23
34
  return (
24
35
  <Dialog.Root open={open} onOpenChange={onOpenChange}>
25
- <PrebuiltDialogPortal>
36
+ <Dialog.Portal>
26
37
  <Dialog.Content
27
38
  css={{
28
39
  width: 'min(400px,80%)',
@@ -67,7 +78,7 @@ const StartRecording = ({ open, onOpenChange }) => {
67
78
  </Button>
68
79
  </Flex>
69
80
  </Dialog.Content>
70
- </PrebuiltDialogPortal>
81
+ </Dialog.Portal>
71
82
  </Dialog.Root>
72
83
  );
73
84
  }
@@ -151,7 +151,7 @@ export const SidePaneTabs = React.memo<{
151
151
  color: activeTab !== SIDE_PANE_OPTIONS.PARTICIPANTS ? '$on_surface_low' : '$on_surface_high',
152
152
  }}
153
153
  >
154
- Participants <ParticipantCount count={peerCount} />
154
+ Participants &nbsp; <ParticipantCount count={peerCount} />
155
155
  </Tabs.Trigger>
156
156
  </Tabs.List>
157
157
  <Tabs.Content value={SIDE_PANE_OPTIONS.PARTICIPANTS} css={{ p: 0 }}>
@@ -15,7 +15,6 @@ import { Dialog } from '../../Modal';
15
15
  import { Switch } from '../../Switch';
16
16
  import { Text } from '../../Text';
17
17
  import { DialogDropdownTrigger } from '../primitives/DropdownTrigger';
18
- import { PrebuiltDialogPortal } from './PrebuiltDialogPortal';
19
18
  import { useSetUiSettings } from './AppData/useUISettings';
20
19
  import { useDropdownSelection } from './hooks/useDropdownSelection';
21
20
  import { UI_SETTINGS } from '../common/constants';
@@ -40,7 +39,7 @@ export const StatsForNerds = ({ onOpenChange }) => {
40
39
 
41
40
  return (
42
41
  <Dialog.Root defaultOpen onOpenChange={onOpenChange}>
43
- <PrebuiltDialogPortal>
42
+ <Dialog.Portal>
44
43
  <Dialog.Overlay />
45
44
  <Dialog.Content
46
45
  css={{
@@ -119,7 +118,7 @@ export const StatsForNerds = ({ onOpenChange }) => {
119
118
  <TrackStats trackID={selectedStat.id} layer={selectedStat.layer} local={selectedStat.local} />
120
119
  )}
121
120
  </Dialog.Content>
122
- </PrebuiltDialogPortal>
121
+ </Dialog.Portal>
123
122
  </Dialog.Root>
124
123
  );
125
124
  };
@@ -37,36 +37,46 @@ export const StreamCard = ({ title, subtitle, Icon, imgSrc = '', css = {}, onCli
37
37
  );
38
38
  };
39
39
 
40
- export const ContentHeader = ({ onBack, title, content }) => {
40
+ export const ContentHeader = ({ onBack, onClose, title = '', content }) => {
41
41
  return (
42
- <Flex css={{ w: '100%', py: '$8', px: '$10', cursor: 'pointer' }}>
43
- <Text
44
- css={{ p: '$2', bg: '$surface_bright', r: '$round', alignSelf: 'center' }}
45
- onClick={onBack}
46
- data-testid="go_back"
47
- >
48
- <ChevronLeftIcon width={16} height={16} />
49
- </Text>
50
- <Box css={{ flex: '1 1 0', mx: '$8' }}>
42
+ <Flex
43
+ css={{ w: '100%', py: '$8', px: '$10', cursor: 'pointer', borderBottom: '1px solid $border_bright', mb: '$8' }}
44
+ >
45
+ {onBack ? (
51
46
  <Text
52
- variant="tiny"
53
47
  css={{
54
- textTransform: 'uppercase',
55
- fontWeight: '$semiBold',
56
- color: '$on_surface_medium',
48
+ alignSelf: 'center',
49
+ mr: '$8',
57
50
  }}
51
+ onClick={onBack}
52
+ data-testid="go_back"
58
53
  >
59
- {title}
54
+ <ChevronLeftIcon />
60
55
  </Text>
56
+ ) : null}
57
+ <Box css={{ flex: '1 1 0' }}>
58
+ {title ? (
59
+ <Text
60
+ variant="tiny"
61
+ css={{
62
+ textTransform: 'uppercase',
63
+ fontWeight: '$semiBold',
64
+ color: '$on_surface_medium',
65
+ }}
66
+ >
67
+ {title}
68
+ </Text>
69
+ ) : null}
61
70
  <Text variant="h6">{content}</Text>
62
71
  </Box>
63
- <IconButton onClick={onBack} css={{ alignSelf: 'flex-start' }} data-testid="close_stream_section">
64
- <CrossIcon width={16} height={16} />
65
- </IconButton>
72
+ {onClose ? (
73
+ <IconButton onClick={onClose} css={{ alignSelf: 'flex-start' }} data-testid="close_stream_section">
74
+ <CrossIcon />
75
+ </IconButton>
76
+ ) : null}
66
77
  </Flex>
67
78
  );
68
79
  };
69
-
70
80
  export const Container = ({ children, rounded = false }) => {
71
81
  return (
72
82
  <Box
@@ -76,7 +86,7 @@ export const Container = ({ children, rounded = false }) => {
76
86
  position: 'absolute',
77
87
  top: 0,
78
88
  left: 0,
79
- bg: '$surface_default',
89
+ bg: '$surface_dim',
80
90
  transform: 'translateX(10%)',
81
91
  animation: `${slideLeftAndFade('10%')} 100ms ease-out forwards`,
82
92
  display: 'flex',
@@ -125,7 +135,7 @@ export const ErrorText = ({ error }) => {
125
135
  return null;
126
136
  }
127
137
  return (
128
- <Text variant="sm" css={{ mb: '$8', color: '$alert_error_default' }}>
138
+ <Text variant="sm" css={{ my: '$4', color: '$alert_error_default' }}>
129
139
  {error}
130
140
  </Text>
131
141
  );
@@ -19,15 +19,14 @@ export const ScreenshareLayout = ({ peers, onPageChange, onPageSize, edgeToEdge
19
19
  const [page, setPage] = useState(0);
20
20
  const activeSharePeer = peersSharing[page];
21
21
  const isMobile = useMedia(cssConfig.media.md);
22
- const secondaryPeers = useMemo(
23
- () =>
24
- isMobile
25
- ? activeSharePeer
26
- ? [activeSharePeer, ...peers.filter(p => p.id !== activeSharePeer?.id)]
27
- : peers //keep active sharing peer as first tile
28
- : peers.filter(p => p.id !== activeSharePeer?.id),
29
- [activeSharePeer, peers, isMobile],
30
- );
22
+ const secondaryPeers = useMemo(() => {
23
+ if (isMobile) {
24
+ return activeSharePeer
25
+ ? [activeSharePeer, ...peers.filter(p => p.id !== activeSharePeer?.id)] //keep active sharing peer as first tile
26
+ : peers;
27
+ }
28
+ return peers.filter(p => p.id !== activeSharePeer?.id);
29
+ }, [activeSharePeer, peers, isMobile]);
31
30
  useEffect(() => {
32
31
  setActiveScreenSharePeer(isMobile ? '' : activeSharePeer?.id);
33
32
  return () => {