@100mslive/roomkit-react 0.2.1-alpha.0 → 0.2.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/{HLSView-GKCGIZ5F.js → HLSView-S5JHEMWJ.js} +2 -2
- package/dist/Prebuilt/components/Polls/Voting/PeerParticipationSummary.d.ts +2 -2
- package/dist/Prebuilt/components/Polls/Voting/StatisticBox.d.ts +1 -1
- package/dist/Prebuilt/components/Polls/Voting/useQuizSummary.d.ts +7 -0
- package/dist/{chunk-FTOP3RHP.js → chunk-AWWYBQSE.js} +468 -452
- package/dist/chunk-AWWYBQSE.js.map +7 -0
- package/dist/index.cjs.js +1511 -1489
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +124 -70
- package/dist/meta.esbuild.json +137 -83
- package/package.json +12 -6
- package/src/Introduction/Integrating.stories.mdx +1 -1
- package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +3 -3
- package/src/Prebuilt/components/Notifications/Notifications.tsx +14 -1
- package/src/Prebuilt/components/Polls/CreatePollQuiz/PollsQuizMenu.jsx +3 -4
- package/src/Prebuilt/components/Polls/CreateQuestions/QuestionForm.tsx +6 -5
- package/src/Prebuilt/components/Polls/Voting/LeaderboardSummary.tsx +7 -59
- package/src/Prebuilt/components/Polls/Voting/PeerParticipationSummary.tsx +40 -14
- package/src/Prebuilt/components/Polls/Voting/StandardVoting.tsx +1 -1
- package/src/Prebuilt/components/Polls/Voting/StatisticBox.tsx +16 -11
- package/src/Prebuilt/components/Polls/Voting/Voting.tsx +5 -7
- package/src/Prebuilt/components/Polls/Voting/useQuizSummary.tsx +50 -0
- package/src/Prebuilt/layouts/WhiteboardView.tsx +4 -1
- package/src/Toast/Toast.tsx +1 -0
- package/dist/chunk-FTOP3RHP.js.map +0 -7
- /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, {
|
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 {
|
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
|
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,
|
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
|
-
|
7
|
-
import { getPeerParticipationSummary } from '../../../common/utils';
|
6
|
+
import { useQuizSummary } from './useQuizSummary';
|
8
7
|
|
9
|
-
export const PeerParticipationSummary = ({
|
10
|
-
const
|
11
|
-
const {
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
>
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
72
|
-
<
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
13
|
+
const isMobile = useMedia(cssConfig.media.md);
|
14
|
+
const { iframeRef } = useWhiteboard(isMobile);
|
12
15
|
|
13
16
|
return (
|
14
17
|
<Box
|
package/src/Toast/Toast.tsx
CHANGED
@@ -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',
|