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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. package/dist/{HLSView-DDGPZHA2.js → HLSView-U53QN3AC.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-PMLQPJB6.js} +3 -5
  25. package/dist/{VirtualBackground-UVZJVOA2.js.map → VirtualBackground-PMLQPJB6.js.map} +1 -1
  26. package/dist/chunk-ANQRGVIX.js +14441 -0
  27. package/dist/chunk-ANQRGVIX.js.map +7 -0
  28. package/dist/{chunk-6SQTFOK6.js → chunk-XQ2NRKIW.js} +66 -3
  29. package/dist/{chunk-6SQTFOK6.js.map → chunk-XQ2NRKIW.js.map} +4 -4
  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-HUMNPIYI.js +0 -70
  125. package/dist/chunk-HUMNPIYI.js.map +0 -7
  126. package/dist/chunk-PRM33R4R.js +0 -7160
  127. package/dist/chunk-PRM33R4R.js.map +0 -7
  128. package/dist/conference-N7S47TDK.js +0 -6602
  129. package/dist/conference-N7S47TDK.js.map +0 -7
  130. package/src/Prebuilt/components/GoLiveButton.jsx +0 -42
  131. package/src/Prebuilt/components/Notifications/HeadlessEndRoomListener.tsx +0 -23
  132. package/src/Prebuilt/components/PrebuiltDialogPortal.tsx +0 -6
  133. package/src/Prebuilt/components/PrebuiltTileElements.tsx +0 -5
  134. package/src/Prebuilt/components/Streaming/HLSStreaming.jsx +0 -220
  135. package/src/Prebuilt/components/Streaming/RTMPStreaming.jsx +0 -334
  136. package/src/Prebuilt/components/Streaming/StreamingLanding.jsx +0 -76
  137. /package/dist/{HLSView-DDGPZHA2.js.map → HLSView-U53QN3AC.js.map} +0 -0
  138. /package/{src/Prebuilt/components/Notifications/index.jsx → dist/Prebuilt/components/Notifications/index.d.ts} +0 -0
  139. /package/src/Prebuilt/components/Notifications/{TrackNotifications.jsx → TrackNotifications.tsx} +0 -0
@@ -0,0 +1,229 @@
1
+ // @ts-check
2
+ import React, { useMemo, useState } from 'react';
3
+ import {
4
+ selectLocalPeerRoleName,
5
+ selectPermissions,
6
+ selectPolls,
7
+ useHMSActions,
8
+ useHMSStore,
9
+ } from '@100mslive/react-sdk';
10
+ import { QuestionIcon, StatsIcon } from '@100mslive/react-icons';
11
+ import { Button, Flex, Input, Switch, Text } from '../../../../';
12
+ import { Container, ContentHeader, ErrorText } from '../../Streaming/Common';
13
+ import { usePollViewToggle } from '../../AppData/useSidepane';
14
+ import { usePollViewState } from '../../AppData/useUISettings';
15
+ import { isValidTextInput } from '../../../common/utils';
16
+ import { StatusIndicator } from '../common/StatusIndicator';
17
+ import { INTERACTION_TYPE, POLL_STATE, POLL_VIEWS } from '../../../common/constants';
18
+
19
+ export const PollsQuizMenu = () => {
20
+ const togglePollView = usePollViewToggle();
21
+ const permissions = useHMSStore(selectPermissions);
22
+
23
+ return (
24
+ <Container rounded>
25
+ <ContentHeader content="Polls and Quizzes" onClose={togglePollView} />
26
+ <Flex direction="column" css={{ px: '$10', pb: '$10', overflowY: 'auto' }}>
27
+ {permissions?.pollWrite && <AddMenu />}
28
+ <PrevMenu />
29
+ </Flex>
30
+ </Container>
31
+ );
32
+ };
33
+
34
+ function InteractionSelectionCard({ title, icon, active, onClick }) {
35
+ const activeBorderStyle = active ? '$space$px solid $primary_default' : '$space$px solid $border_bright';
36
+ return (
37
+ <Flex
38
+ onClick={onClick}
39
+ css={{
40
+ border: activeBorderStyle,
41
+ p: '$4',
42
+ r: '$2',
43
+ w: '100%',
44
+ cursor: 'pointer',
45
+ }}
46
+ align="center"
47
+ >
48
+ <Flex
49
+ css={{
50
+ border: activeBorderStyle,
51
+ p: '$4',
52
+ bg: '$surface_bright',
53
+ c: '$on_surface_high',
54
+ r: '$0',
55
+ }}
56
+ >
57
+ {icon}
58
+ </Flex>
59
+ <Text variant="sub1" css={{ ml: '$md' }}>
60
+ {title}
61
+ </Text>
62
+ </Flex>
63
+ );
64
+ }
65
+
66
+ const AddMenu = () => {
67
+ const actions = useHMSActions();
68
+ const [title, setTitle] = useState('');
69
+ const localPeerRoleName = useHMSStore(selectLocalPeerRoleName);
70
+ const [anonymous, setAnonymous] = useState(false);
71
+ const [hideVoteCount, setHideVoteCount] = useState(false);
72
+ const [error, setError] = useState();
73
+ const [titleError, setTitleError] = useState('');
74
+ const { setPollState } = usePollViewState();
75
+ const [interactionType, setInteractionType] = useState(INTERACTION_TYPE.POLL);
76
+
77
+ const handleCreate = id => {
78
+ setPollState({
79
+ [POLL_STATE.pollInView]: id,
80
+ [POLL_STATE.view]: POLL_VIEWS.CREATE_QUESTIONS,
81
+ });
82
+ };
83
+
84
+ const validateTitle = useMemo(() => {
85
+ if (!isValidTextInput(title)) {
86
+ if (title) {
87
+ setTitleError('The title should have between 2-100 characters');
88
+ }
89
+ return true;
90
+ } else {
91
+ setTitleError('');
92
+ return false;
93
+ }
94
+ }, [title]);
95
+ // const [timer, setTimer] = useState(10);
96
+ // const [showTimerDropDown, setShowTimerDropDown] = useState(false);
97
+
98
+ return (
99
+ <>
100
+ <Text variant="caption" css={{ c: '$on_surface_medium', mb: '$md' }}>
101
+ Select the type you want to continue with
102
+ </Text>
103
+ <Flex css={{ w: '100%', gap: '$10', mb: '$md' }}>
104
+ <InteractionSelectionCard
105
+ title={INTERACTION_TYPE.POLL}
106
+ icon={<StatsIcon width={32} height={32} />}
107
+ onClick={() => setInteractionType(INTERACTION_TYPE.POLL)}
108
+ active={interactionType === INTERACTION_TYPE.POLL}
109
+ />
110
+ <InteractionSelectionCard
111
+ title={INTERACTION_TYPE.QUIZ}
112
+ icon={<QuestionIcon width={32} height={32} />}
113
+ onClick={() => setInteractionType(INTERACTION_TYPE.QUIZ)}
114
+ active={interactionType === INTERACTION_TYPE.QUIZ}
115
+ />
116
+ </Flex>
117
+ <Flex direction="column">
118
+ <Text variant="body2" css={{ mb: '$4' }}>{`Name this ${interactionType.toLowerCase()}`}</Text>
119
+ <Input
120
+ type="text"
121
+ value={title}
122
+ onChange={event => setTitle(event.target.value)}
123
+ css={{
124
+ backgroundColor: '$surface_bright',
125
+ border: '1px solid $border_default',
126
+ }}
127
+ />
128
+ <Flex align="center" css={{ mt: '$10' }}>
129
+ <Switch onCheckedChange={value => setHideVoteCount(value)} css={{ mr: '$6' }} />
130
+ <Text variant="body2" css={{ c: '$on_surface_medium' }}>
131
+ Hide Vote Count
132
+ </Text>
133
+ </Flex>
134
+ <Flex align="center" css={{ mt: '$10' }}>
135
+ <Switch onCheckedChange={value => setAnonymous(value)} css={{ mr: '$6' }} />
136
+ <Text variant="body2" css={{ c: '$on_surface_medium' }}>
137
+ Make Results Anonymous
138
+ </Text>
139
+ </Flex>
140
+ {/* <Timer
141
+ timer={timer}
142
+ setTimer={setTimer}
143
+ showTimerDropDown={showTimerDropDown}
144
+ setShowTimerDropDown={setShowTimerDropDown}
145
+ /> */}
146
+
147
+ <Button
148
+ variant="primary"
149
+ disabled={validateTitle}
150
+ css={{ mt: '$10' }}
151
+ onClick={async () => {
152
+ const id = Date.now().toString();
153
+ await actions.interactivityCenter
154
+ .createPoll({
155
+ id,
156
+ title,
157
+ anonymous,
158
+ rolesThatCanViewResponses: hideVoteCount && localPeerRoleName ? [localPeerRoleName] : undefined,
159
+ type: interactionType.toLowerCase(),
160
+ // duration: showTimerDropDown ? timer : undefined,
161
+ })
162
+ .then(() => handleCreate(id))
163
+ .catch(err => setError(err.message));
164
+ }}
165
+ >
166
+ Create {interactionType}
167
+ </Button>
168
+ <ErrorText error={error || titleError} />
169
+ </Flex>
170
+ </>
171
+ );
172
+ };
173
+
174
+ const PrevMenu = () => {
175
+ const polls = useHMSStore(selectPolls)?.filter(poll => poll.state === 'started' || poll.state === 'stopped');
176
+ return polls?.length ? (
177
+ <Flex
178
+ css={{
179
+ borderTop: '$space$px solid $border_bright',
180
+ mt: '$10',
181
+ pt: '$10',
182
+ }}
183
+ >
184
+ <Flex direction="column" css={{ w: '100%' }}>
185
+ <Text variant="h6" css={{ c: '$on_surface_high' }}>
186
+ Previous Polls and Quizzes
187
+ </Text>
188
+ <Flex direction="column" css={{ gap: '$10', mt: '$8' }}>
189
+ {polls.map(poll => (
190
+ <InteractionCard
191
+ key={poll.id}
192
+ id={poll.id}
193
+ title={poll.title}
194
+ isLive={poll.state === 'started'}
195
+ isTimed={(poll.duration || 0) > 0}
196
+ />
197
+ ))}
198
+ </Flex>
199
+ </Flex>
200
+ </Flex>
201
+ ) : null;
202
+ };
203
+
204
+ const InteractionCard = ({ id, title, isLive, isTimed }) => {
205
+ const { setPollState } = usePollViewState();
206
+
207
+ const goToVote = id => {
208
+ setPollState({
209
+ [POLL_STATE.pollInView]: id,
210
+ [POLL_STATE.view]: POLL_VIEWS.VOTE,
211
+ });
212
+ };
213
+
214
+ return (
215
+ <Flex direction="column" css={{ backgroundColor: '$surface_bright', borderRadius: '$1', p: '$8' }}>
216
+ <Flex css={{ w: '100%', justifyContent: 'space-between', mb: '$sm' }}>
217
+ <Text variant="sub1" css={{ c: '$on_surface_high', fontWeight: '$semiBold' }}>
218
+ {title}
219
+ </Text>
220
+ <StatusIndicator isLive={isLive} shouldShowTimer={isLive && isTimed} />
221
+ </Flex>
222
+ <Flex css={{ w: '100%', gap: '$4' }} justify="end">
223
+ <Button variant="primary" onClick={() => goToVote(id)}>
224
+ View
225
+ </Button>
226
+ </Flex>
227
+ </Flex>
228
+ );
229
+ };
@@ -0,0 +1,71 @@
1
+ // @ts-check
2
+ import React, { useRef, useState } from 'react';
3
+ import { Dropdown, Flex, Switch, Text } from '../../../../';
4
+ import { DialogDropdownTrigger } from '../../../primitives/DropdownTrigger';
5
+ import { useDropdownSelection } from '../../hooks/useDropdownSelection';
6
+
7
+ const timerSettings = {
8
+ 10: '10 secs',
9
+ 15: '15 secs',
10
+ 20: '20 secs',
11
+ 25: '25 secs',
12
+ 30: '30 secs',
13
+ 60: '1 min',
14
+ 120: '2 mins',
15
+ 300: '5 mins',
16
+ };
17
+
18
+ export const Timer = ({ timer, setTimer, showTimerDropDown, setShowTimerDropDown }) => {
19
+ const selectionBg = useDropdownSelection();
20
+ const [timerDropdownToggle, setTimerDropdownToggle] = useState(false);
21
+ const timerDropdownRef = useRef();
22
+
23
+ return (
24
+ <Flex justify="between" align="center" css={{ mt: '$10' }}>
25
+ <Flex align="center">
26
+ <Switch checked={showTimerDropDown} onCheckedChange={setShowTimerDropDown} css={{ mr: '$6' }} />
27
+ <Text variant="body2" css={{ c: '$on_surface_medium' }}>
28
+ Timer
29
+ </Text>
30
+ </Flex>
31
+ <Flex align="center">
32
+ {showTimerDropDown ? (
33
+ <Dropdown.Root open={timerDropdownToggle} onOpenChange={setTimerDropdownToggle}>
34
+ <DialogDropdownTrigger
35
+ ref={timerDropdownRef}
36
+ title={timerSettings[timer]}
37
+ open={timerDropdownToggle}
38
+ titleCss={{ c: '$on_surface_high', ml: '$md' }}
39
+ />
40
+ <Dropdown.Portal>
41
+ <Dropdown.Content
42
+ align="start"
43
+ sideOffset={8}
44
+ css={{
45
+ w: timerDropdownRef.current?.clientWidth,
46
+ zIndex: 1000,
47
+ }}
48
+ >
49
+ {Object.keys(timerSettings).map(value => {
50
+ const val = parseInt(value);
51
+ return (
52
+ <Dropdown.Item
53
+ key={value}
54
+ onSelect={() => setTimer(val)}
55
+ css={{
56
+ px: '$9',
57
+ bg: timer === val ? selectionBg : undefined,
58
+ }}
59
+ >
60
+ {timerSettings[val]}
61
+ </Dropdown.Item>
62
+ );
63
+ })}
64
+ </Dropdown.Content>
65
+ </Dropdown.Portal>
66
+ </Dropdown.Root>
67
+ ) : null}
68
+ </Flex>
69
+ </Flex>
70
+ );
71
+ };
@@ -0,0 +1,132 @@
1
+ // @ts-check
2
+ import React, { useMemo, useState } from 'react';
3
+ import { v4 as uuid } from 'uuid';
4
+ import { selectPollByID, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
5
+ import { AddCircleIcon } from '@100mslive/react-icons';
6
+ import { Button, Flex, Text } from '../../../../';
7
+ import { Container, ContentHeader } from '../../Streaming/Common';
8
+ import { isValidQuestion, QuestionForm } from './QuestionForm';
9
+ import { SavedQuestion } from './SavedQuestion';
10
+ import { usePollViewToggle } from '../../AppData/useSidepane';
11
+ import { usePollViewState } from '../../AppData/useUISettings';
12
+ import { POLL_VIEWS } from '../../../common/constants';
13
+
14
+ export function CreateQuestions() {
15
+ const [questions, setQuestions] = useState([{ draftID: uuid() }]);
16
+ const actions = useHMSActions();
17
+ const togglePollView = usePollViewToggle();
18
+ const { pollInView: id, setPollView } = usePollViewState();
19
+ const interaction = useHMSStore(selectPollByID(id));
20
+
21
+ const isValidPoll = useMemo(
22
+ () => questions.length > 0 && questions.every(question => isValidQuestion(question)),
23
+ [questions],
24
+ );
25
+
26
+ const launchPoll = async () => {
27
+ const validQuestions = questions
28
+ .filter(question => isValidQuestion(question))
29
+ .map(question => ({
30
+ text: question.text,
31
+ type: question.type,
32
+ options: question.options,
33
+ skippable: question.skippable,
34
+ }));
35
+ await actions.interactivityCenter.addQuestionsToPoll(id, validQuestions);
36
+ await actions.interactivityCenter.startPoll(id);
37
+ setPollView(POLL_VIEWS.VOTE);
38
+ };
39
+ const headingTitle = interaction?.type
40
+ ? interaction?.type?.[0]?.toUpperCase() + interaction?.type?.slice(1)
41
+ : 'Polls and Quizzes';
42
+ const isQuiz = interaction?.type === 'quiz';
43
+ return (
44
+ <Container rounded>
45
+ <ContentHeader
46
+ content={headingTitle}
47
+ onClose={togglePollView}
48
+ onBack={() => setPollView(POLL_VIEWS.CREATE_POLL_QUIZ)}
49
+ />
50
+ <Flex direction="column" css={{ p: '$10', overflowY: 'auto' }}>
51
+ <Flex direction="column">
52
+ {questions.map((question, index) => (
53
+ <QuestionCard
54
+ key={question.draftID}
55
+ question={question}
56
+ index={index}
57
+ length={questions.length}
58
+ onSave={questionParams => {
59
+ setQuestions(questions => [
60
+ ...questions.slice(0, index),
61
+ questionParams,
62
+ ...questions.slice(index + 1),
63
+ ]);
64
+ }}
65
+ isQuiz={isQuiz}
66
+ removeQuestion={questionID =>
67
+ setQuestions(prev => {
68
+ return prev.filter(questionFromSet => questionID !== questionFromSet.draftID);
69
+ })
70
+ }
71
+ convertToDraft={questionID =>
72
+ setQuestions(prev => {
73
+ const copyOfQuestions = [...prev];
74
+ copyOfQuestions.forEach(question => {
75
+ if (questionID && question.draftID === questionID) {
76
+ question.saved = false;
77
+ }
78
+ });
79
+ return copyOfQuestions;
80
+ })
81
+ }
82
+ />
83
+ ))}
84
+ </Flex>
85
+ <Flex
86
+ css={{
87
+ c: '$on_surface_low',
88
+ my: '$sm',
89
+ cursor: 'pointer',
90
+ '&:hover': { c: '$on_surface_medium' },
91
+ }}
92
+ onClick={() => setQuestions([...questions, { draftID: uuid() }])}
93
+ >
94
+ <AddCircleIcon />
95
+ <Text variant="body1" css={{ ml: '$md', c: '$inherit' }}>
96
+ Add another question
97
+ </Text>
98
+ </Flex>
99
+ <Flex css={{ w: '100%' }} justify="end">
100
+ <Button disabled={!isValidPoll} onClick={launchPoll}>
101
+ Launch {interaction.type}
102
+ </Button>
103
+ </Flex>
104
+ </Flex>
105
+ </Container>
106
+ );
107
+ }
108
+
109
+ const QuestionCard = ({ question, onSave, index, length, removeQuestion, isQuiz, convertToDraft }) => {
110
+ return (
111
+ <Flex direction="column" css={{ p: '$md', bg: '$surface_default', r: '$1', mb: '$sm' }}>
112
+ {question.saved ? (
113
+ <SavedQuestion
114
+ question={question}
115
+ index={index}
116
+ length={length}
117
+ convertToDraft={convertToDraft}
118
+ removeQuestion={removeQuestion}
119
+ />
120
+ ) : (
121
+ <QuestionForm
122
+ question={question}
123
+ removeQuestion={() => removeQuestion(question.draftID)}
124
+ onSave={params => onSave(params)}
125
+ index={index}
126
+ length={length}
127
+ isQuiz={isQuiz}
128
+ />
129
+ )}
130
+ </Flex>
131
+ );
132
+ };
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import { AlertTriangleIcon, CrossIcon } from '@100mslive/react-icons';
3
+ import { Button } from '../../../../Button';
4
+ import { Box, Flex } from '../../../../Layout';
5
+ import { Dialog } from '../../../../Modal';
6
+ import { Text } from '../../../../Text';
7
+
8
+ export const DeleteQuestionModal = ({ open, setOpen, removeQuestion }) => {
9
+ return (
10
+ <Dialog.Root open={open}>
11
+ <Dialog.Overlay />
12
+ <Dialog.Portal>
13
+ <Dialog.Content css={{ p: '$10' }}>
14
+ <Box>
15
+ <Flex
16
+ css={{
17
+ color: '$alert_error_default',
18
+ display: 'flex',
19
+ alignItems: 'center',
20
+ }}
21
+ >
22
+ <AlertTriangleIcon style={{ marginRight: '0.5rem' }} />
23
+ <Text variant="lg" css={{ color: 'inherit', fontWeight: '$semiBold' }}>
24
+ Delete Question?
25
+ </Text>
26
+
27
+ <Box
28
+ css={{
29
+ ml: 'auto',
30
+ color: '$on_surface_medium',
31
+ '&:hover': { color: '$on_surface_high', cursor: 'pointer' },
32
+ }}
33
+ onClick={() => setOpen(false)}
34
+ >
35
+ <CrossIcon />
36
+ </Box>
37
+ </Flex>
38
+ <Text variant="sm" css={{ color: '$on_surface_medium', mb: '$8', mt: '$4' }}>
39
+ The question will be deleted. You can't undo this action.
40
+ </Text>
41
+ <Flex css={{ w: '100%', mt: '$12', gap: '$md' }}>
42
+ <Button
43
+ variant="standard"
44
+ outlined
45
+ onClick={() => setOpen(false)}
46
+ css={{ w: '100%', fontSize: '$md', fontWeight: '$semiBold' }}
47
+ >
48
+ Cancel
49
+ </Button>
50
+ <Button
51
+ css={{ w: '100%', fontSize: '$md', fontWeight: '$semiBold' }}
52
+ variant="danger"
53
+ onClick={() => {
54
+ removeQuestion();
55
+ setOpen(false);
56
+ }}
57
+ >
58
+ Delete
59
+ </Button>
60
+ </Flex>
61
+ </Box>
62
+ </Dialog.Content>
63
+ </Dialog.Portal>
64
+ </Dialog.Root>
65
+ );
66
+ };