@100mslive/roomkit-react 0.2.1-alpha.0 → 0.2.1-alpha.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{HLSView-GKCGIZ5F.js → HLSView-S5JHEMWJ.js} +2 -2
  3. package/dist/Prebuilt/components/Polls/Voting/PeerParticipationSummary.d.ts +2 -2
  4. package/dist/Prebuilt/components/Polls/Voting/StatisticBox.d.ts +1 -1
  5. package/dist/Prebuilt/components/Polls/Voting/useQuizSummary.d.ts +7 -0
  6. package/dist/{chunk-FTOP3RHP.js → chunk-AWWYBQSE.js} +468 -452
  7. package/dist/chunk-AWWYBQSE.js.map +7 -0
  8. package/dist/index.cjs.js +1511 -1489
  9. package/dist/index.cjs.js.map +4 -4
  10. package/dist/index.js +1 -1
  11. package/dist/meta.cjs.json +124 -70
  12. package/dist/meta.esbuild.json +137 -83
  13. package/package.json +12 -6
  14. package/src/Introduction/Integrating.stories.mdx +1 -1
  15. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +3 -3
  16. package/src/Prebuilt/components/Notifications/Notifications.tsx +14 -1
  17. package/src/Prebuilt/components/Polls/CreatePollQuiz/PollsQuizMenu.jsx +3 -4
  18. package/src/Prebuilt/components/Polls/CreateQuestions/QuestionForm.tsx +6 -5
  19. package/src/Prebuilt/components/Polls/Voting/LeaderboardSummary.tsx +7 -59
  20. package/src/Prebuilt/components/Polls/Voting/PeerParticipationSummary.tsx +40 -14
  21. package/src/Prebuilt/components/Polls/Voting/StandardVoting.tsx +1 -1
  22. package/src/Prebuilt/components/Polls/Voting/StatisticBox.tsx +16 -11
  23. package/src/Prebuilt/components/Polls/Voting/Voting.tsx +5 -7
  24. package/src/Prebuilt/components/Polls/Voting/useQuizSummary.tsx +50 -0
  25. package/src/Prebuilt/layouts/WhiteboardView.tsx +4 -1
  26. package/src/Toast/Toast.tsx +1 -0
  27. package/dist/chunk-FTOP3RHP.js.map +0 -7
  28. /package/dist/{HLSView-GKCGIZ5F.js.map → HLSView-S5JHEMWJ.js.map} +0 -0
@@ -67,7 +67,6 @@ const AddMenu = () => {
67
67
  const actions = useHMSActions();
68
68
  const [title, setTitle] = useState('');
69
69
  const localPeerRoleName = useHMSStore(selectLocalPeerRoleName);
70
- const [anonymous, setAnonymous] = useState(false);
71
70
  const [hideVoteCount, setHideVoteCount] = useState(false);
72
71
  const [error, setError] = useState();
73
72
  const [titleError, setTitleError] = useState('');
@@ -141,12 +140,12 @@ const AddMenu = () => {
141
140
  Hide Vote Count
142
141
  </Text>
143
142
  </Flex>
144
- <Flex align="center" css={{ mt: '$10' }}>
143
+ {/* <Flex align="center" css={{ mt: '$10' }}>
145
144
  <Switch onCheckedChange={value => setAnonymous(value)} css={{ mr: '$6' }} />
146
145
  <Text variant="body2" css={{ c: '$on_surface_medium' }}>
147
146
  Make Results Anonymous
148
147
  </Text>
149
- </Flex>
148
+ </Flex> */}
150
149
  {/* <Timer
151
150
  timer={timer}
152
151
  setTimer={setTimer}
@@ -164,7 +163,7 @@ const AddMenu = () => {
164
163
  .createPoll({
165
164
  id,
166
165
  title,
167
- anonymous,
166
+ anonymous: false,
168
167
  rolesThatCanViewResponses: hideVoteCount && localPeerRoleName ? [localPeerRoleName] : undefined,
169
168
  type: interactionType.toLowerCase(),
170
169
  // duration: showTimerDropDown ? timer : undefined,
@@ -6,7 +6,8 @@ import {
6
6
  HMSPollQuestionType,
7
7
  } from '@100mslive/react-sdk';
8
8
  import { AddCircleIcon, TrashIcon } from '@100mslive/react-icons';
9
- import { Button, Dropdown, Flex, IconButton, Input, Switch, Text, TextArea, Tooltip } from '../../../..';
9
+ // import { Button, Dropdown, Flex, IconButton, Input, Switch, Text, TextArea, Tooltip } from '../../../..';
10
+ import { Button, Dropdown, Flex, IconButton, Input, Text, TextArea, Tooltip } from '../../../..';
10
11
  // @ts-ignore
11
12
  import { DialogDropdownTrigger } from '../../../primitives/DropdownTrigger';
12
13
  // @ts-ignore
@@ -50,7 +51,7 @@ export const QuestionForm = ({
50
51
  { text: '', isCorrectAnswer: false },
51
52
  ],
52
53
  );
53
- const [skippable, setSkippable] = useState(false);
54
+ // const [skippable, setSkippable] = useState(false);
54
55
  const isValid = isValidQuestion({
55
56
  text,
56
57
  type,
@@ -241,12 +242,12 @@ export const QuestionForm = ({
241
242
  }}
242
243
  />
243
244
  </Flex>
244
- <Flex justify="between" css={{ mt: '$md', gap: '$6', w: '100%' }}>
245
+ {/* <Flex justify="between" css={{ mt: '$md', gap: '$6', w: '100%' }}>
245
246
  <Text variant="sm" css={{ color: '$on_surface_medium' }}>
246
247
  Allow to skip
247
248
  </Text>
248
249
  <Switch defaultChecked={skippable} onCheckedChange={checked => setSkippable(checked)} />
249
- </Flex>
250
+ </Flex> */}
250
251
  </>
251
252
  ) : null}
252
253
  </>
@@ -274,7 +275,7 @@ export const QuestionForm = ({
274
275
  text,
275
276
  type,
276
277
  options,
277
- skippable,
278
+ skippable: false,
278
279
  draftID: question.draftID,
279
280
  weight,
280
281
  });
@@ -1,51 +1,27 @@
1
- import React, { useEffect, useState } from 'react';
2
- import {
3
- HMSQuizLeaderboardResponse,
4
- HMSQuizLeaderboardSummary,
5
- selectPollByID,
6
- useHMSActions,
7
- useHMSStore,
8
- } from '@100mslive/react-sdk';
1
+ import React, { useState } from 'react';
2
+ import { selectPollByID, useHMSStore } from '@100mslive/react-sdk';
9
3
  import { ChevronLeftIcon, ChevronRightIcon, CrossIcon } from '@100mslive/react-icons';
10
4
  import { Box, Flex } from '../../../../Layout';
11
5
  import { Loading } from '../../../../Loading';
12
6
  import { Text } from '../../../../Text';
13
7
  import { LeaderboardEntry } from './LeaderboardEntry';
14
- import { StatisticBox } from './StatisticBox';
8
+ import { PeerParticipationSummary } from './PeerParticipationSummary';
15
9
  // @ts-ignore
16
10
  import { useSidepaneToggle } from '../../AppData/useSidepane';
17
11
  // @ts-ignore
18
12
  import { usePollViewState } from '../../AppData/useUISettings';
13
+ import { useQuizSummary } from './useQuizSummary';
19
14
  // @ts-ignore
20
15
  import { StatusIndicator } from '../common/StatusIndicator';
21
16
  import { POLL_VIEWS } from '../../../common/constants';
22
17
 
23
18
  export const LeaderboardSummary = ({ pollID }: { pollID: string }) => {
24
- const hmsActions = useHMSActions();
25
19
  const quiz = useHMSStore(selectPollByID(pollID));
26
- const [quizLeaderboard, setQuizLeaderboard] = useState<HMSQuizLeaderboardResponse | undefined>();
20
+ const { quizLeaderboard, maxPossibleScore } = useQuizSummary(pollID);
27
21
  const [viewAllEntries, setViewAllEntries] = useState(false);
28
- const summary: HMSQuizLeaderboardSummary = quizLeaderboard?.summary || {
29
- totalUsers: 0,
30
- votedUsers: 0,
31
- avgScore: 0,
32
- avgTime: 0,
33
- correctAnswers: 0,
34
- };
35
-
36
22
  const { setPollView } = usePollViewState();
37
23
  const toggleSidepane = useSidepaneToggle();
38
24
 
39
- useEffect(() => {
40
- const fetchLeaderboardData = async () => {
41
- if (!quizLeaderboard && quiz) {
42
- const leaderboardData = await hmsActions.interactivityCenter.fetchLeaderboard(quiz.id, 0, 50);
43
- setQuizLeaderboard(leaderboardData);
44
- }
45
- };
46
- fetchLeaderboardData();
47
- }, [quiz, hmsActions.interactivityCenter, quizLeaderboard]);
48
-
49
25
  if (!quiz || !quizLeaderboard)
50
26
  return (
51
27
  <Flex align="center" justify="center" css={{ size: '100%' }}>
@@ -53,14 +29,6 @@ export const LeaderboardSummary = ({ pollID }: { pollID: string }) => {
53
29
  </Flex>
54
30
  );
55
31
 
56
- const defaultCalculations = { maxPossibleScore: 0, totalResponses: 0 };
57
- const { maxPossibleScore, totalResponses } =
58
- quiz.questions?.reduce((accumulator, question) => {
59
- accumulator.maxPossibleScore += question.weight || 0;
60
- accumulator.totalResponses += question?.responses?.length || 0;
61
- return accumulator;
62
- }, defaultCalculations) || defaultCalculations;
63
-
64
32
  const questionCount = quiz.questions?.length || 0;
65
33
 
66
34
  return (
@@ -86,29 +54,9 @@ export const LeaderboardSummary = ({ pollID }: { pollID: string }) => {
86
54
  </Flex>
87
55
  </Flex>
88
56
 
89
- {!viewAllEntries ? (
90
- <Box css={{ py: '$4' }}>
91
- <Text variant="sm" css={{ fontWeight: '$semiBold' }}>
92
- Participation Summary
93
- </Text>
94
-
95
- <Box css={{ my: '$4' }}>
96
- <Flex css={{ w: '100%', gap: '$4' }}>
97
- <StatisticBox
98
- title="Voted"
99
- value={`${summary?.totalUsers ? (100 * summary?.votedUsers) / summary?.totalUsers : 0}%`}
100
- />
101
- <StatisticBox title="Correct Answers" value={`${summary?.correctAnswers}/${totalResponses}`} />
102
- </Flex>
103
- <Flex css={{ w: '100%', gap: '$4', mt: '$4' }}>
104
- {summary?.avgTime > 0 ? <StatisticBox title="Avg. Time" value={summary?.avgTime} /> : null}
105
- <StatisticBox title="Avg. Score" value={summary?.avgScore} />
106
- </Flex>
107
- </Box>
108
- </Box>
109
- ) : null}
57
+ {!viewAllEntries ? <PeerParticipationSummary quiz={quiz} /> : null}
110
58
 
111
- <Text variant="sm" css={{ fontWeight: '$semiBold' }}>
59
+ <Text variant="sm" css={{ fontWeight: '$semiBold', mt: '$4' }}>
112
60
  Leaderboard
113
61
  </Text>
114
62
  <Text variant="xs" css={{ color: '$on_surface_medium' }}>
@@ -1,23 +1,49 @@
1
1
  import React from 'react';
2
- import { HMSPoll, selectLocalPeer, useHMSStore } from '@100mslive/react-sdk';
2
+ import { HMSPoll, selectLocalPeerID, useHMSStore } from '@100mslive/react-sdk';
3
3
  import { Box } from '../../../../Layout';
4
4
  import { Text } from '../../../../Text';
5
5
  import { StatisticBox } from './StatisticBox';
6
- // @ts-ignore
7
- import { getPeerParticipationSummary } from '../../../common/utils';
6
+ import { useQuizSummary } from './useQuizSummary';
8
7
 
9
- export const PeerParticipationSummary = ({ poll }: { poll: HMSPoll }) => {
10
- const localPeer = useHMSStore(selectLocalPeer);
11
- const { totalResponses, correctResponses, score } = getPeerParticipationSummary(
12
- poll,
13
- localPeer?.id,
14
- localPeer?.customerUserId,
15
- );
8
+ export const PeerParticipationSummary = ({ quiz }: { quiz: HMSPoll }) => {
9
+ const localPeerId = useHMSStore(selectLocalPeerID);
10
+ const { quizLeaderboard, summary } = useQuizSummary(quiz.id);
11
+ if (quiz.state !== 'stopped') {
12
+ return <></>;
13
+ }
14
+ const isLocalPeerQuizCreator = localPeerId === quiz.startedBy;
15
+ const peerEntry = quizLeaderboard?.entries.find(entry => entry.peer?.peerid === localPeerId);
16
+
17
+ const boxes = isLocalPeerQuizCreator
18
+ ? [
19
+ {
20
+ title: 'Voted',
21
+ value: `${summary.totalUsers ? ((100 * summary.votedUsers) / summary.totalUsers).toFixed(0) : 0}% (${
22
+ summary.votedUsers
23
+ }/${summary.totalUsers})`,
24
+ },
25
+ {
26
+ title: 'Correct Answers',
27
+ value: `${summary.totalUsers ? ((100 * summary.correctUsers) / summary.totalUsers).toFixed(0) : 0}% (${
28
+ summary.correctUsers
29
+ }/${summary.totalUsers})`,
30
+ },
31
+ { title: 'Avg. Time Taken', value: summary.avgTime },
32
+ {
33
+ title: 'Avg. Score',
34
+ value: Number.isInteger(summary.avgScore) ? summary.avgScore : summary.avgScore.toFixed(2),
35
+ },
36
+ ]
37
+ : [
38
+ { title: 'Your rank', value: peerEntry?.position ? `${peerEntry.position}/${summary.totalUsers}` : '-' },
39
+ { title: 'Points', value: peerEntry?.score },
40
+ { title: 'Time Taken', value: peerEntry?.duration },
41
+ {
42
+ title: 'Correct Answers',
43
+ value: peerEntry?.totalResponses ? `${peerEntry?.correctResponses}/${peerEntry.totalResponses}` : '-',
44
+ },
45
+ ];
16
46
 
17
- const boxes = [
18
- { title: 'Points', value: score },
19
- { title: 'Correct Answers', value: `${correctResponses}/${totalResponses}` },
20
- ];
21
47
  return (
22
48
  <Box>
23
49
  <Text css={{ fontWeight: '$semiBold', my: '$8' }}>Participation Summary</Text>
@@ -14,7 +14,7 @@ export const StandardView = ({ poll }: { poll: HMSPoll }) => {
14
14
 
15
15
  return (
16
16
  <>
17
- {isQuiz && isStopped ? <PeerParticipationSummary poll={poll} /> : null}
17
+ {isQuiz && isStopped ? <PeerParticipationSummary quiz={poll} /> : null}
18
18
  {poll.questions?.map((question, index) => (
19
19
  <QuestionCard
20
20
  pollID={poll.id}
@@ -2,14 +2,19 @@ import React from 'react';
2
2
  import { Box } from '../../../../Layout';
3
3
  import { Text } from '../../../../Text';
4
4
 
5
- export const StatisticBox = ({ title, value = 0 }: { title: string; value: string | number }) => (
6
- <Box css={{ p: '$8', background: '$surface_default', borderRadius: '$1', w: '100%' }}>
7
- <Text
8
- variant="tiny"
9
- css={{ textTransform: 'uppercase', color: '$on_surface_medium', fontWeight: '$semiBold', my: '$4' }}
10
- >
11
- {title}
12
- </Text>
13
- <Text css={{ fontWeight: '$semiBold' }}>{value}</Text>
14
- </Box>
15
- );
5
+ export const StatisticBox = ({ title, value = 0 }: { title: string; value: string | number | undefined }) => {
6
+ if (!value) {
7
+ return <></>;
8
+ }
9
+ return (
10
+ <Box css={{ p: '$8', background: '$surface_default', borderRadius: '$1', w: '100%' }}>
11
+ <Text
12
+ variant="tiny"
13
+ css={{ textTransform: 'uppercase', color: '$on_surface_medium', fontWeight: '$semiBold', my: '$4' }}
14
+ >
15
+ {title}
16
+ </Text>
17
+ <Text css={{ fontWeight: '$semiBold' }}>{value}</Text>
18
+ </Box>
19
+ );
20
+ };
@@ -68,13 +68,11 @@ export const Voting = ({ id, toggleVoting }: { id: string; toggleVoting: () => v
68
68
  </Flex>
69
69
 
70
70
  <Flex direction="column" css={{ p: '$8 $10', overflowY: 'auto' }}>
71
- <Flex align="center">
72
- <Box css={{ flex: 'auto' }}>
73
- <Text css={{ color: '$on_surface_medium', fontWeight: '$semiBold' }}>
74
- {pollCreatorName || 'Participant'} started a {poll.type}
75
- </Text>
76
- </Box>
77
- </Flex>
71
+ {poll.state === 'started' ? (
72
+ <Text css={{ color: '$on_surface_medium', fontWeight: '$semiBold' }}>
73
+ {pollCreatorName || 'Participant'} started a {poll.type}
74
+ </Text>
75
+ ) : null}
78
76
 
79
77
  {isTimed ? <TimedView poll={poll} /> : <StandardView poll={poll} />}
80
78
 
@@ -0,0 +1,50 @@
1
+ import { useEffect, useState } from 'react';
2
+ import {
3
+ HMSQuizLeaderboardResponse,
4
+ HMSQuizLeaderboardSummary,
5
+ selectPollByID,
6
+ useHMSActions,
7
+ useHMSStore,
8
+ } from '@100mslive/react-sdk';
9
+
10
+ export const useQuizSummary = (quizID: string) => {
11
+ const hmsActions = useHMSActions();
12
+ const quiz = useHMSStore(selectPollByID(quizID));
13
+ const [quizLeaderboard, setQuizLeaderboard] = useState<HMSQuizLeaderboardResponse | undefined>();
14
+
15
+ const summary: HMSQuizLeaderboardSummary = quizLeaderboard?.summary || {
16
+ totalUsers: 0,
17
+ votedUsers: 0,
18
+ avgScore: 0,
19
+ avgTime: 0,
20
+ correctUsers: 0,
21
+ };
22
+ const [calculations, setCalculations] = useState({ maxPossibleScore: 0, totalResponses: 0 });
23
+
24
+ useEffect(() => {
25
+ const fetchLeaderboardData = async () => {
26
+ if (!quizLeaderboard && quiz && !quiz?.anonymous && quiz.state === 'stopped') {
27
+ const leaderboardData = await hmsActions.interactivityCenter.fetchLeaderboard(quiz.id, 0, 50);
28
+
29
+ const { maxPossibleScore, totalResponses } =
30
+ quiz?.questions?.reduce((accumulator, question) => {
31
+ accumulator.maxPossibleScore += question.weight || 0;
32
+ accumulator.totalResponses += question?.responses?.length || 0;
33
+ return accumulator;
34
+ }, calculations) || calculations;
35
+
36
+ setQuizLeaderboard(leaderboardData);
37
+ setCalculations({ maxPossibleScore, totalResponses });
38
+ }
39
+ };
40
+
41
+ fetchLeaderboardData();
42
+ }, [quiz, hmsActions.interactivityCenter, quizLeaderboard, calculations]);
43
+
44
+ return {
45
+ quizLeaderboard,
46
+ summary,
47
+ maxPossibleScore: calculations.maxPossibleScore,
48
+ totalResponses: calculations.totalResponses,
49
+ };
50
+ };
@@ -1,14 +1,17 @@
1
1
  import React, { useEffect, useMemo } from 'react';
2
+ import { useMedia } from 'react-use';
2
3
  import { selectPeers, selectWhiteboard, useHMSStore, useWhiteboard } from '@100mslive/react-sdk';
3
4
  import { SecondaryTiles } from '../components/SecondaryTiles';
4
5
  import { ProminenceLayout } from '../components/VideoLayouts/ProminenceLayout';
6
+ import { config as cssConfig } from '../../';
5
7
  import { Box } from '../../Layout';
6
8
  // @ts-ignore: No implicit Any
7
9
  import { useSetAppDataByKey } from '../components/AppData/useUISettings';
8
10
  import { APP_DATA } from '../common/constants';
9
11
 
10
12
  const EmbedComponent = () => {
11
- const { iframeRef } = useWhiteboard();
13
+ const isMobile = useMedia(cssConfig.media.md);
14
+ const { iframeRef } = useWhiteboard(isMobile);
12
15
 
13
16
  return (
14
17
  <Box
@@ -78,6 +78,7 @@ const ToastClose = styled(ToastPrimitives.Close, {});
78
78
  const ToastAction = styled(ToastPrimitives.Action, {
79
79
  cursor: 'pointer',
80
80
  background: 'none',
81
+ border: 'none',
81
82
  });
82
83
  const ToastViewport = styled(ToastPrimitives.Viewport, {
83
84
  position: 'fixed',