@100mslive/roomkit-react 0.3.19-alpha.1 → 0.3.19-alpha.3

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 (30) hide show
  1. package/dist/{HLSView-MI7WHLIB.css → HLSView-3OIDEB7I.css} +3 -3
  2. package/dist/{HLSView-MI7WHLIB.css.map → HLSView-3OIDEB7I.css.map} +1 -1
  3. package/dist/{HLSView-6KUW45BA.js → HLSView-YQCSQSBU.js} +2 -2
  4. package/dist/Prebuilt/components/EndCallFeedback/Feedback.d.ts +2 -0
  5. package/dist/Prebuilt/components/EndCallFeedback/FeedbackForm.d.ts +28 -0
  6. package/dist/Prebuilt/components/EndCallFeedback/ThankyouView.d.ts +2 -0
  7. package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.d.ts +1 -0
  8. package/dist/{chunk-NC3PKPDD.js → chunk-SLFOQJ6P.js} +1180 -673
  9. package/dist/chunk-SLFOQJ6P.js.map +7 -0
  10. package/dist/index.cjs.css +2 -2
  11. package/dist/index.cjs.css.map +1 -1
  12. package/dist/index.cjs.js +1411 -872
  13. package/dist/index.cjs.js.map +4 -4
  14. package/dist/index.css +2 -2
  15. package/dist/index.css.map +1 -1
  16. package/dist/index.js +1 -1
  17. package/dist/meta.cjs.json +275 -33
  18. package/dist/meta.esbuild.json +285 -43
  19. package/package.json +8 -8
  20. package/src/Prebuilt/App.tsx +3 -0
  21. package/src/Prebuilt/AppStateContext.tsx +1 -2
  22. package/src/Prebuilt/Prebuilt.stories.tsx +1 -0
  23. package/src/Prebuilt/components/EndCallFeedback/Feedback.tsx +70 -0
  24. package/src/Prebuilt/components/EndCallFeedback/FeedbackForm.tsx +371 -0
  25. package/src/Prebuilt/components/EndCallFeedback/ThankyouView.tsx +44 -0
  26. package/src/Prebuilt/components/LeaveScreen.tsx +2 -0
  27. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.ts +1 -0
  28. package/src/Video/Video.tsx +1 -1
  29. package/dist/chunk-NC3PKPDD.js.map +0 -7
  30. /package/dist/{HLSView-6KUW45BA.js.map → HLSView-YQCSQSBU.js.map} +0 -0
@@ -0,0 +1,70 @@
1
+ import React, { useState } from 'react';
2
+ import { useMedia } from 'react-use';
3
+ import { Flex } from '../../../Layout';
4
+ import { config as cssConfig } from '../../../Theme';
5
+ import { FEEBACK_INDEX, FeedbackHeader, FeedbackModal } from './FeedbackForm';
6
+ import { ThankyouView } from './ThankyouView';
7
+ import { useRoomLayoutLeaveScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
8
+
9
+ export const Feedback = () => {
10
+ const { feedback } = useRoomLayoutLeaveScreen();
11
+ const [index, setIndex] = useState(FEEBACK_INDEX.INIT);
12
+ const isMobile = useMedia(cssConfig.media.md);
13
+
14
+ if (!feedback) {
15
+ return null;
16
+ }
17
+ const { ratings } = feedback;
18
+ if (!ratings) {
19
+ return null;
20
+ }
21
+ ratings.sort((a, b) => {
22
+ if (!a.value || !b.value) {
23
+ return 0;
24
+ }
25
+ return a.value - b.value;
26
+ });
27
+ // TO show thank ypu page
28
+ if (index === FEEBACK_INDEX.THANK_YOU) {
29
+ return (
30
+ <Flex
31
+ justify="center"
32
+ css={{
33
+ pt: '$16',
34
+ }}
35
+ >
36
+ <ThankyouView />
37
+ </Flex>
38
+ );
39
+ }
40
+ return (
41
+ <Flex
42
+ justify="center"
43
+ css={{
44
+ pt: '$16',
45
+ w: '528px',
46
+ }}
47
+ >
48
+ {index === FEEBACK_INDEX.INIT ? (
49
+ <Flex
50
+ css={{
51
+ p: '$12',
52
+ border: '1px solid $border_default',
53
+ bg: '$surface_dim',
54
+ borderRadius: !isMobile ? '$3' : '$3 $3 0 0',
55
+ gap: '$10',
56
+ '@md': {
57
+ position: 'absolute',
58
+ bottom: '0',
59
+ },
60
+ }}
61
+ direction="column"
62
+ >
63
+ <FeedbackHeader ratings={ratings} onEmojiClicked={setIndex} />
64
+ </Flex>
65
+ ) : (
66
+ <FeedbackModal ratings={ratings} index={index} setIndex={setIndex} />
67
+ )}
68
+ </Flex>
69
+ );
70
+ };
@@ -0,0 +1,371 @@
1
+ import React, { useState } from 'react';
2
+ import { useMedia } from 'react-use';
3
+ import { Rating } from '@100mslive/types-prebuilt/elements/feedback';
4
+ import { useHMSActions } from '@100mslive/react-sdk';
5
+ import { CheckIcon, CrossIcon } from '@100mslive/react-icons';
6
+ import { Button } from '../../../Button';
7
+ import { Checkbox } from '../../../Checkbox';
8
+ import { Label } from '../../../Label';
9
+ import { Flex } from '../../../Layout';
10
+ import { Dialog } from '../../../Modal';
11
+ import { Sheet } from '../../../Sheet';
12
+ import { Text } from '../../../Text';
13
+ import { TextArea } from '../../../TextArea';
14
+ import { config as cssConfig } from '../../../Theme';
15
+ import { useHMSPrebuiltContext } from '../../AppContext';
16
+ import { useRoomLayoutLeaveScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
17
+
18
+ export const FEEBACK_INDEX = {
19
+ THANK_YOU: -10,
20
+ INIT: -1,
21
+ };
22
+ export const FeedbackModal = ({
23
+ ratings,
24
+ index,
25
+ setIndex,
26
+ }: {
27
+ ratings: Rating[];
28
+ index: number;
29
+ setIndex: (index: number) => void;
30
+ }) => {
31
+ const isMobile = useMedia(cssConfig.media.md);
32
+ const onOpenChange = () => {
33
+ setIndex(FEEBACK_INDEX.INIT);
34
+ };
35
+ const avoidDefaultDomBehavior = (e: Event) => {
36
+ e.preventDefault();
37
+ };
38
+ if (isMobile) {
39
+ return (
40
+ <Sheet.Root open={index !== FEEBACK_INDEX.INIT} onOpenChange={onOpenChange}>
41
+ <Sheet.Content
42
+ css={{ bg: '$surface_dim', p: '$12' }}
43
+ onPointerDownOutside={avoidDefaultDomBehavior}
44
+ onInteractOutside={avoidDefaultDomBehavior}
45
+ >
46
+ <FeedbackContent ratings={ratings} indexSelected={index} setIndex={setIndex} />
47
+ </Sheet.Content>
48
+ </Sheet.Root>
49
+ );
50
+ }
51
+ return (
52
+ <Dialog.Root open={index !== FEEBACK_INDEX.INIT} onOpenChange={onOpenChange}>
53
+ <Dialog.Portal>
54
+ <Dialog.Overlay />
55
+ <Dialog.Content
56
+ css={{ bg: '$surface_dim', width: '528px', p: '$12' }}
57
+ onPointerDownOutside={avoidDefaultDomBehavior}
58
+ onInteractOutside={avoidDefaultDomBehavior}
59
+ >
60
+ <FeedbackContent ratings={ratings} indexSelected={index} setIndex={setIndex} />
61
+ </Dialog.Content>
62
+ </Dialog.Portal>
63
+ </Dialog.Root>
64
+ );
65
+ };
66
+
67
+ export const FeedbackContent = ({
68
+ ratings,
69
+ indexSelected,
70
+ setIndex,
71
+ }: {
72
+ ratings: Rating[];
73
+ indexSelected: number;
74
+ setIndex: (index: number) => void;
75
+ }) => {
76
+ const { feedback } = useRoomLayoutLeaveScreen();
77
+ const { endpoints } = useHMSPrebuiltContext();
78
+ const hmsActions = useHMSActions();
79
+ const [comment, setComment] = useState('');
80
+ const [selectedReasons, setSelectedReasons] = useState(new Set<number>());
81
+ const handleCheckedChange = (checked: boolean | string, index: number) => {
82
+ const newSelected = new Set(selectedReasons);
83
+ if (checked) {
84
+ newSelected.add(index);
85
+ } else {
86
+ newSelected.delete(index);
87
+ }
88
+ setSelectedReasons(newSelected);
89
+ };
90
+ const submitFeedback = async () => {
91
+ if (indexSelected < 0 || ratings.length <= indexSelected) {
92
+ return;
93
+ }
94
+ try {
95
+ const reasons = [...selectedReasons].map((value: number) => ratings[indexSelected]?.reasons?.[value] || '');
96
+ await hmsActions.submitSessionFeedback(
97
+ {
98
+ question: ratings[indexSelected].question,
99
+ rating: ratings[indexSelected].value || 1,
100
+ min_rating: 1,
101
+ max_rating: ratings.length,
102
+ reasons: selectedReasons.size === 0 ? [] : reasons,
103
+ comment: comment,
104
+ },
105
+ endpoints?.event,
106
+ );
107
+ } catch (e) {
108
+ console.error(e);
109
+ }
110
+ // always submit and take it to thankyou page
111
+ setIndex(FEEBACK_INDEX.THANK_YOU);
112
+ };
113
+ return (
114
+ <Flex
115
+ css={{
116
+ p: indexSelected === FEEBACK_INDEX.INIT ? '$12 !important' : '0',
117
+ bg: '$surface_dim',
118
+ r: '$3',
119
+ gap: '$10',
120
+ }}
121
+ direction="column"
122
+ >
123
+ <FeedbackHeader
124
+ ratings={ratings}
125
+ indexSelected={indexSelected}
126
+ onEmojiClicked={(value: number) => {
127
+ setSelectedReasons(new Set<number>());
128
+ setIndex(value);
129
+ }}
130
+ />
131
+ <FeedbackForm
132
+ rating={ratings[indexSelected]}
133
+ comment={comment}
134
+ setComment={setComment}
135
+ selectedReasons={selectedReasons}
136
+ handleCheckedChange={handleCheckedChange}
137
+ />
138
+ <Button
139
+ type="submit"
140
+ icon
141
+ css={{
142
+ alignSelf: 'end',
143
+ }}
144
+ onClick={submitFeedback}
145
+ >
146
+ {feedback?.submit_btn_label || 'Submit Feedback'}
147
+ </Button>
148
+ </Flex>
149
+ );
150
+ };
151
+ export const FeedbackHeader = ({
152
+ onEmojiClicked,
153
+ ratings,
154
+ indexSelected = FEEBACK_INDEX.INIT,
155
+ }: {
156
+ onEmojiClicked: (index: number) => void;
157
+ ratings: Rating[];
158
+ indexSelected?: number;
159
+ }) => {
160
+ const { feedback } = useRoomLayoutLeaveScreen();
161
+ return (
162
+ <>
163
+ <Flex align="center">
164
+ <Flex
165
+ direction="column"
166
+ css={{
167
+ flex: '1 1 0',
168
+ }}
169
+ >
170
+ <Text
171
+ variant="h5"
172
+ css={{
173
+ c: '$on_surface_high',
174
+ fontStyle: 'normal',
175
+ }}
176
+ >
177
+ {feedback?.title || 'How was your experience?'}
178
+ </Text>
179
+ <Text
180
+ variant="body1"
181
+ css={{
182
+ c: '$on_surface_medium',
183
+ opacity: 0.9,
184
+ fontWeight: '$regular',
185
+ }}
186
+ >
187
+ {feedback?.sub_title || 'Your answers help us improve the quality.'}
188
+ </Text>
189
+ </Flex>
190
+ {indexSelected !== FEEBACK_INDEX.INIT ? (
191
+ <CrossIcon width="24px" height="24px" color="white" onClick={() => onEmojiClicked(FEEBACK_INDEX.INIT)} />
192
+ ) : null}
193
+ </Flex>
194
+ <Flex
195
+ css={{
196
+ gap: '$17',
197
+ c: '$on_surface_high',
198
+ }}
199
+ >
200
+ {ratings.map((element, index) => {
201
+ return (
202
+ <Flex
203
+ align="center"
204
+ direction="column"
205
+ css={{
206
+ c:
207
+ indexSelected === index || indexSelected === FEEBACK_INDEX.INIT
208
+ ? '$on_surface_high'
209
+ : '$on_surface_default',
210
+ gap: '$4',
211
+ }}
212
+ onClick={() => onEmojiClicked(index)}
213
+ key={`${index}`}
214
+ >
215
+ <Text
216
+ css={{
217
+ fontWeight: '$semiBold',
218
+ fontSize: '$h4',
219
+ pb: '$1',
220
+ cursor: 'pointer',
221
+ opacity: indexSelected === index || indexSelected === FEEBACK_INDEX.INIT ? 1 : 0.2,
222
+ }}
223
+ >
224
+ {element.emoji}
225
+ </Text>
226
+ <Text
227
+ variant="body1"
228
+ css={{
229
+ c:
230
+ indexSelected === index || indexSelected === FEEBACK_INDEX.INIT
231
+ ? '$on_surface_medium'
232
+ : '$on_surface_low',
233
+ fontWeight: '$regular',
234
+ }}
235
+ >
236
+ {element.label}
237
+ </Text>
238
+ </Flex>
239
+ );
240
+ })}
241
+ </Flex>
242
+ </>
243
+ );
244
+ };
245
+ export const FeedbackForm = ({
246
+ rating,
247
+ comment,
248
+ setComment,
249
+ selectedReasons,
250
+ handleCheckedChange,
251
+ }: {
252
+ rating: Rating;
253
+ comment: string;
254
+ setComment: (value: string) => void;
255
+ selectedReasons: Set<number>;
256
+ handleCheckedChange: (checked: string | boolean, index: number) => void;
257
+ }) => {
258
+ const { feedback } = useRoomLayoutLeaveScreen();
259
+ return (
260
+ <>
261
+ {rating.reasons && rating.reasons.length > 0 && (
262
+ <Flex
263
+ direction="column"
264
+ css={{
265
+ gap: '$4',
266
+ }}
267
+ >
268
+ <Text
269
+ variant="sub2"
270
+ css={{
271
+ c: '$on_surface_high',
272
+ fontWeight: '$semiBold',
273
+ fontSize: '$sm',
274
+ px: '$2',
275
+ }}
276
+ >
277
+ {rating.question || 'What do you like/dislike here?'}
278
+ </Text>
279
+ <Flex
280
+ css={{
281
+ alignItems: 'flex-start',
282
+ alignSelf: 'stretch',
283
+ flexWrap: 'wrap',
284
+ gap: '$6',
285
+ flex: '1 1 calc(25% - 12px)',
286
+ '@md': {
287
+ flex: '1 1 calc(50% - 12px)',
288
+ },
289
+ '@sm': {
290
+ flex: '1 1 100%',
291
+ },
292
+ }}
293
+ >
294
+ {rating.reasons.map((option: string, index: number) => {
295
+ return (
296
+ <Flex
297
+ align="center"
298
+ gap="2"
299
+ key={index}
300
+ css={{
301
+ border: '1px solid $border_bright',
302
+ r: '$1',
303
+ p: '$6',
304
+ }}
305
+ >
306
+ <Checkbox.Root
307
+ id={`${option}-${index}`}
308
+ checked={selectedReasons.has(index)}
309
+ onCheckedChange={checked => handleCheckedChange(checked, index)}
310
+ css={{
311
+ cursor: 'pointer',
312
+ flexShrink: 0,
313
+ bg: '$on_secondary_low',
314
+ border: '1px solid $border_bright',
315
+ }}
316
+ >
317
+ <Checkbox.Indicator>
318
+ <CheckIcon width={12} height={12} />
319
+ </Checkbox.Indicator>
320
+ </Checkbox.Root>
321
+ <Label
322
+ css={{
323
+ color: '$on_surface_high',
324
+ fontSize: '$sm',
325
+ fontWeight: '$regular',
326
+ lineHeight: '20px' /* 142.857% */,
327
+ }}
328
+ >
329
+ {option}
330
+ </Label>
331
+ </Flex>
332
+ );
333
+ })}
334
+ </Flex>
335
+ </Flex>
336
+ )}
337
+ {feedback?.comment && (
338
+ <Flex
339
+ direction="column"
340
+ css={{
341
+ gap: '$4',
342
+ }}
343
+ >
344
+ <Text
345
+ variant="body2"
346
+ css={{
347
+ c: '$on_surface_high',
348
+ fontWeight: '$regular',
349
+ fontSize: '$sm',
350
+ }}
351
+ >
352
+ {feedback?.comment.label || 'Additional comments (optional)'}
353
+ </Text>
354
+ <TextArea
355
+ maxLength={1024}
356
+ placeholder={feedback?.comment.placeholder || 'Tell us more...'}
357
+ css={{
358
+ backgroundColor: '$surface_bright',
359
+ border: '1px solid $border_bright',
360
+ resize: 'none',
361
+ height: '$36',
362
+ display: 'flex',
363
+ }}
364
+ value={comment}
365
+ onChange={event => setComment(event.target.value.trimStart())}
366
+ />
367
+ </Flex>
368
+ )}
369
+ </>
370
+ );
371
+ };
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { useMedia } from 'react-use';
3
+ import { UserMusicIcon } from '@100mslive/react-icons';
4
+ import { Flex } from '../../../Layout';
5
+ import { Text } from '../../../Text';
6
+ import { config as cssConfig } from '../../../Theme';
7
+
8
+ export const ThankyouView = () => {
9
+ const isMobile = useMedia(cssConfig.media.md);
10
+ return (
11
+ <Flex
12
+ direction={isMobile ? 'column' : 'row'}
13
+ align="center"
14
+ css={{
15
+ gap: '$10',
16
+ border: '1px solid $border_default',
17
+ borderRadius: !isMobile ? '$3' : '$3 $3 0 0',
18
+ bg: '$surface_dim',
19
+ w: !isMobile ? '528px' : '410px',
20
+ p: '$12',
21
+ pb: isMobile ? '$16' : '$12',
22
+ '@md': {
23
+ position: 'absolute',
24
+ bottom: '0',
25
+ },
26
+ }}
27
+ >
28
+ <UserMusicIcon width="64px" height="64px" />
29
+ <Flex direction="column" align={isMobile ? 'center' : 'start'}>
30
+ <Text variant="h5">Thank you for your feedback!</Text>
31
+ <Text
32
+ variant="body1"
33
+ css={{
34
+ fontWeight: '$regular',
35
+ fontSize: '$md',
36
+ opacity: '0.9',
37
+ }}
38
+ >
39
+ Your answers help us improve.
40
+ </Text>
41
+ </Flex>
42
+ </Flex>
43
+ );
44
+ };
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { ExitIcon } from '@100mslive/react-icons';
3
+ import { Feedback } from './EndCallFeedback/Feedback';
3
4
  // @ts-ignore: No implicit Any
4
5
  import { ToastManager } from './Toast/ToastManager';
5
6
  import { Button } from '../../Button';
@@ -63,6 +64,7 @@ export const LeaveScreen = () => {
63
64
  <Text css={{ ml: '$3', fontWeight: '$semiBold', color: 'inherit' }}>Rejoin</Text>
64
65
  </Button>
65
66
  </Flex>
67
+ <Feedback />
66
68
  </Flex>
67
69
  </Flex>
68
70
  );
@@ -77,6 +77,7 @@ export function useRoomLayoutLeaveScreen() {
77
77
  const isLeaveScreenEnabled = !!screenProps;
78
78
  return {
79
79
  isLeaveScreenEnabled,
80
+ feedback: screenProps?.default?.elements?.feedback,
80
81
  };
81
82
  }
82
83
 
@@ -57,5 +57,5 @@ interface Props {
57
57
 
58
58
  export const Video: React.FC<Props & StyledProps> = ({ trackId, attach, ...props }) => {
59
59
  const { videoRef } = useVideo({ trackId, attach });
60
- return <StyledVideo autoPlay muted playsInline controls={false} ref={videoRef} {...props} />;
60
+ return <StyledVideo ref={videoRef} {...props} />;
61
61
  };