@100mslive/roomkit-react 0.3.19-alpha.2 → 0.3.19-alpha.21

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 (43) hide show
  1. package/dist/{HLSView-BRZ2FW7O.js → HLSView-LQU6IEZQ.js} +2 -2
  2. package/dist/{HLSView-UXA322ED.css → HLSView-SQ7GMQJS.css} +3 -3
  3. package/dist/{HLSView-UXA322ED.css.map → HLSView-SQ7GMQJS.css.map} +1 -1
  4. package/dist/Modal/Dialog.d.ts +3 -1
  5. package/dist/Prebuilt/components/EndCallFeedback/Feedback.d.ts +2 -0
  6. package/dist/Prebuilt/components/EndCallFeedback/FeedbackForm.d.ts +28 -0
  7. package/dist/Prebuilt/components/EndCallFeedback/ThankyouView.d.ts +2 -0
  8. package/dist/Prebuilt/components/VirtualBackground/VBCollection.d.ts +1 -1
  9. package/dist/Prebuilt/components/VirtualBackground/VBHandler.d.ts +6 -6
  10. package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.d.ts +1 -0
  11. package/dist/{chunk-KR2DZJO5.js → chunk-IRF6KLC6.js} +1363 -831
  12. package/dist/chunk-IRF6KLC6.js.map +7 -0
  13. package/dist/index.cjs.css +2 -2
  14. package/dist/index.cjs.css.map +1 -1
  15. package/dist/index.cjs.js +1849 -1291
  16. package/dist/index.cjs.js.map +4 -4
  17. package/dist/index.css +2 -2
  18. package/dist/index.css.map +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/meta.cjs.json +323 -90
  21. package/dist/meta.esbuild.json +334 -101
  22. package/package.json +8 -8
  23. package/src/Modal/Dialog.tsx +13 -2
  24. package/src/Prebuilt/App.tsx +3 -0
  25. package/src/Prebuilt/AppStateContext.tsx +1 -2
  26. package/src/Prebuilt/Prebuilt.stories.tsx +1 -0
  27. package/src/Prebuilt/common/PeersSorter.ts +2 -1
  28. package/src/Prebuilt/components/EndCallFeedback/Feedback.tsx +71 -0
  29. package/src/Prebuilt/components/EndCallFeedback/FeedbackForm.tsx +381 -0
  30. package/src/Prebuilt/components/EndCallFeedback/ThankyouView.tsx +44 -0
  31. package/src/Prebuilt/components/LeaveScreen.tsx +2 -0
  32. package/src/Prebuilt/components/PIP/PIPChat.tsx +11 -4
  33. package/src/Prebuilt/components/VideoLayouts/RoleProminence.tsx +2 -9
  34. package/src/Prebuilt/components/VirtualBackground/VBCollection.tsx +3 -1
  35. package/src/Prebuilt/components/VirtualBackground/VBHandler.tsx +26 -4
  36. package/src/Prebuilt/components/VirtualBackground/VBPicker.tsx +58 -38
  37. package/src/Prebuilt/components/VirtualBackground/VBToggle.tsx +2 -1
  38. package/src/Prebuilt/plugins/CaptionsViewer.tsx +4 -1
  39. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.ts +1 -0
  40. package/dist/Prebuilt/components/VirtualBackground/util.d.ts +0 -1
  41. package/dist/chunk-KR2DZJO5.js.map +0 -7
  42. package/src/Prebuilt/components/VirtualBackground/util.tsx +0 -13
  43. /package/dist/{HLSView-BRZ2FW7O.js.map → HLSView-LQU6IEZQ.js.map} +0 -0
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.3.19-alpha.2",
13
+ "version": "0.3.19-alpha.21",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "repository": {
@@ -75,13 +75,13 @@
75
75
  "react": ">=17.0.2 <19.0.0"
76
76
  },
77
77
  "dependencies": {
78
- "@100mslive/hls-player": "0.3.19-alpha.2",
78
+ "@100mslive/hls-player": "0.3.19-alpha.21",
79
79
  "@100mslive/hms-noise-cancellation": "0.0.1",
80
- "@100mslive/hms-virtual-background": "1.13.19-alpha.2",
81
- "@100mslive/hms-whiteboard": "0.0.9-alpha.2",
82
- "@100mslive/react-icons": "0.10.19-alpha.2",
83
- "@100mslive/react-sdk": "0.10.19-alpha.2",
84
- "@100mslive/types-prebuilt": "0.12.11",
80
+ "@100mslive/hms-virtual-background": "1.13.19-alpha.21",
81
+ "@100mslive/hms-whiteboard": "0.0.9-alpha.21",
82
+ "@100mslive/react-icons": "0.10.19-alpha.21",
83
+ "@100mslive/react-sdk": "0.10.19-alpha.21",
84
+ "@100mslive/types-prebuilt": "0.12.12",
85
85
  "@emoji-mart/data": "^1.0.6",
86
86
  "@emoji-mart/react": "^1.0.1",
87
87
  "@radix-ui/react-accordion": "1.0.0",
@@ -117,5 +117,5 @@
117
117
  "uuid": "^8.3.2",
118
118
  "worker-timers": "^7.0.40"
119
119
  },
120
- "gitHead": "88c8ac68235961d5352322c7be3efedad27f6d92"
120
+ "gitHead": "5201ce15a559d9a81939b5752b9af73cde22c552"
121
121
  }
@@ -1,4 +1,4 @@
1
- import React, { ReactNode, useRef } from 'react';
1
+ import React, { ReactNode, useEffect, useRef } from 'react';
2
2
  import { Root } from '@radix-ui/react-dialog';
3
3
  import { styled } from '@stitches/react';
4
4
  import {
@@ -15,6 +15,17 @@ import { useDialogContainerSelector } from '../hooks/useDialogContainerSelector'
15
15
 
16
16
  const StyledDialog = styled(Root, {});
17
17
 
18
+ // Handles race conditions when multiple elements with dismissable layer are present
19
+ // https://github.com/radix-ui/primitives/issues/2122
20
+ const DialogRoot = <T extends React.ComponentProps<typeof StyledDialog>>(props: T) => {
21
+ useEffect(() => {
22
+ return () => {
23
+ if (document) setTimeout(() => (document.body.style.pointerEvents = 'auto'), 0);
24
+ };
25
+ }, []);
26
+ return <StyledDialog {...(props as object)} />;
27
+ };
28
+
18
29
  const CustomDialogPortal = ({ children, container }: { children: ReactNode; container?: HTMLElement | null }) => {
19
30
  const dialogContainerSelector = useDialogContainerSelector();
20
31
  const containerRef = useRef<HTMLElement | null>(null);
@@ -34,7 +45,7 @@ const CustomDialogPortal = ({ children, container }: { children: ReactNode; cont
34
45
  };
35
46
 
36
47
  export const Dialog = {
37
- Root: StyledDialog,
48
+ Root: DialogRoot,
38
49
  Trigger: StyledDialogTrigger,
39
50
  Overlay: CustomDialogOverlay,
40
51
  Content: CustomDialogContent,
@@ -140,10 +140,12 @@ export const HMSPrebuilt = React.forwardRef<HMSPrebuiltRefType, HMSPrebuiltProps
140
140
  init: string;
141
141
  tokenByRoomCode: string;
142
142
  roomLayout: string;
143
+ event: string;
143
144
  }
144
145
  | undefined;
145
146
  const tokenByRoomCodeEndpoint: string = endpointsObj?.tokenByRoomCode || '';
146
147
  const initEndpoint: string = endpointsObj?.init || '';
148
+ const eventEndpoint: string = endpointsObj?.event || '';
147
149
  const roomLayoutEndpoint: string = endpointsObj?.roomLayout || '';
148
150
 
149
151
  const overrideLayout: Partial<Layout> = {
@@ -182,6 +184,7 @@ export const HMSPrebuilt = React.forwardRef<HMSPrebuiltRefType, HMSPrebuiltProps
182
184
  tokenByRoomCode: tokenByRoomCodeEndpoint,
183
185
  init: initEndpoint,
184
186
  roomLayout: roomLayoutEndpoint,
187
+ event: eventEndpoint,
185
188
  },
186
189
  }}
187
190
  >
@@ -84,7 +84,6 @@ export const useAppStateManager = () => {
84
84
  .otherwise(() => {
85
85
  // do nothing
86
86
  });
87
- }, [roomLayout, roomState, isLeaveScreenEnabled, isPreviewScreenEnabled, prevRoomState, redirectToLeave, hmsActions]);
88
-
87
+ }, [roomLayout, roomState, isLeaveScreenEnabled, isPreviewScreenEnabled, prevRoomState, redirectToLeave]);
89
88
  return { activeState, rejoin };
90
89
  };
@@ -28,6 +28,7 @@ const endpoints: HMSPrebuiltOptions['endpoints'] = {
28
28
  roomLayout: process.env.STORYBOOK_ROOM_LAYOUT_ENDPOINT,
29
29
  tokenByRoomCode: process.env.STORYBOOK_TOKEN_BY_ROOM_CODE_ENDPOINT,
30
30
  init: process.env.STORYBOOK_INIT_API_ENDPOINT,
31
+ event: process.env.STORYBOOK_EVENT_API_ENDPOINT,
31
32
  };
32
33
 
33
34
  const hasEndpoints = Object.values(endpoints).some(val => !!val);
@@ -7,13 +7,14 @@ class PeersSorter {
7
7
  lruPeers: Set<HMSPeerID>;
8
8
  tilesPerPage!: number;
9
9
  speaker?: HMSPeer;
10
- listeners: Set<(peers: HMSPeer[]) => void> = new Set();
10
+ listeners: Set<(peers: HMSPeer[]) => void>;
11
11
 
12
12
  constructor(store: IStoreReadOnly<any>) {
13
13
  this.store = store;
14
14
  this.peers = new Map();
15
15
  this.lruPeers = new Set();
16
16
  this.speaker = undefined;
17
+ this.listeners = new Set();
17
18
  }
18
19
 
19
20
  setPeersAndTilesPerPage = ({ peers, tilesPerPage }: { peers: HMSPeer[]; tilesPerPage: number }) => {
@@ -0,0 +1,71 @@
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: isMobile ? '100%' : '528px',
46
+ }}
47
+ >
48
+ {index === FEEBACK_INDEX.INIT ? (
49
+ <Flex
50
+ css={{
51
+ p: isMobile ? '$10' : '$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
+ w: '100%',
60
+ },
61
+ }}
62
+ direction="column"
63
+ >
64
+ <FeedbackHeader ratings={ratings} onEmojiClicked={setIndex} />
65
+ </Flex>
66
+ ) : (
67
+ <FeedbackModal ratings={ratings} index={index} setIndex={setIndex} />
68
+ )}
69
+ </Flex>
70
+ );
71
+ };
@@ -0,0 +1,381 @@
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: '$10' }}
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 isMobile = useMedia(cssConfig.media.md);
79
+ const hmsActions = useHMSActions();
80
+ const [comment, setComment] = useState('');
81
+ const [selectedReasons, setSelectedReasons] = useState(new Set<number>());
82
+ const handleCheckedChange = (checked: boolean | string, index: number) => {
83
+ const newSelected = new Set(selectedReasons);
84
+ if (checked) {
85
+ newSelected.add(index);
86
+ } else {
87
+ newSelected.delete(index);
88
+ }
89
+ setSelectedReasons(newSelected);
90
+ };
91
+ const submitFeedback = async () => {
92
+ if (indexSelected < 0 || ratings.length <= indexSelected) {
93
+ return;
94
+ }
95
+ try {
96
+ const reasons = [...selectedReasons].map((value: number) => ratings[indexSelected]?.reasons?.[value] || '');
97
+ await hmsActions.submitSessionFeedback(
98
+ {
99
+ question: `${feedback?.title} | ${ratings[indexSelected].question || ''}`,
100
+ rating: ratings[indexSelected].value || 1,
101
+ min_rating: 1,
102
+ max_rating: ratings.length,
103
+ reasons: selectedReasons.size === 0 ? [] : reasons,
104
+ comment: comment,
105
+ },
106
+ endpoints?.event,
107
+ );
108
+ } catch (e) {
109
+ console.error(e);
110
+ }
111
+ // always submit and take it to thankyou page
112
+ setIndex(FEEBACK_INDEX.THANK_YOU);
113
+ };
114
+ return (
115
+ <Flex
116
+ css={{
117
+ p: indexSelected === FEEBACK_INDEX.INIT ? '$12 !important' : '0',
118
+ bg: '$surface_dim',
119
+ r: '$3',
120
+ gap: '$10',
121
+ }}
122
+ direction="column"
123
+ >
124
+ <FeedbackHeader
125
+ ratings={ratings}
126
+ indexSelected={indexSelected}
127
+ onEmojiClicked={(value: number) => {
128
+ setSelectedReasons(new Set<number>());
129
+ setIndex(value);
130
+ }}
131
+ />
132
+ <FeedbackForm
133
+ rating={ratings[indexSelected]}
134
+ comment={comment}
135
+ setComment={setComment}
136
+ selectedReasons={selectedReasons}
137
+ handleCheckedChange={handleCheckedChange}
138
+ />
139
+ <Button
140
+ type="submit"
141
+ icon
142
+ css={{
143
+ alignSelf: isMobile ? '' : 'end',
144
+ }}
145
+ onClick={submitFeedback}
146
+ >
147
+ {feedback?.submit_btn_label || 'Submit Feedback'}
148
+ </Button>
149
+ </Flex>
150
+ );
151
+ };
152
+ export const FeedbackHeader = ({
153
+ onEmojiClicked,
154
+ ratings,
155
+ indexSelected = FEEBACK_INDEX.INIT,
156
+ }: {
157
+ onEmojiClicked: (index: number) => void;
158
+ ratings: Rating[];
159
+ indexSelected?: number;
160
+ }) => {
161
+ const isMobile = useMedia(cssConfig.media.md);
162
+ const { feedback } = useRoomLayoutLeaveScreen();
163
+ return (
164
+ <>
165
+ <Flex align="center">
166
+ <Flex
167
+ direction="column"
168
+ css={{
169
+ flex: '1 1 0',
170
+ }}
171
+ >
172
+ <Text
173
+ variant={isMobile ? 'h6' : 'h5'}
174
+ css={{
175
+ c: '$on_surface_high',
176
+ fontStyle: 'normal',
177
+ }}
178
+ >
179
+ {feedback?.title || 'How was your experience?'}
180
+ </Text>
181
+ <Text
182
+ variant={isMobile ? 'body2' : 'body1'}
183
+ css={{
184
+ c: '$on_surface_medium',
185
+ opacity: 0.9,
186
+ fontWeight: '$regular',
187
+ }}
188
+ >
189
+ {feedback?.sub_title || 'Your answers help us improve the quality.'}
190
+ </Text>
191
+ </Flex>
192
+ {indexSelected !== FEEBACK_INDEX.INIT ? (
193
+ <CrossIcon width="24px" height="24px" color="white" onClick={() => onEmojiClicked(FEEBACK_INDEX.INIT)} />
194
+ ) : null}
195
+ </Flex>
196
+ <Flex
197
+ justify="between"
198
+ css={{
199
+ gap: '$17',
200
+ c: '$on_surface_high',
201
+ '@md': {
202
+ gap: '0',
203
+ },
204
+ }}
205
+ >
206
+ {ratings.map((element, index) => {
207
+ return (
208
+ <Flex
209
+ align="center"
210
+ direction="column"
211
+ css={{
212
+ c:
213
+ indexSelected === index || indexSelected === FEEBACK_INDEX.INIT
214
+ ? '$on_surface_high'
215
+ : '$on_surface_default',
216
+ gap: '$4',
217
+ }}
218
+ onClick={() => onEmojiClicked(index)}
219
+ key={`${index}`}
220
+ >
221
+ <Text
222
+ css={{
223
+ fontWeight: '$semiBold',
224
+ fontSize: '$h4',
225
+ pb: '$1',
226
+ cursor: 'pointer',
227
+ opacity: indexSelected === index || indexSelected === FEEBACK_INDEX.INIT ? 1 : 0.2,
228
+ '@md': {
229
+ fontSize: '$h5',
230
+ },
231
+ }}
232
+ >
233
+ {element.emoji}
234
+ </Text>
235
+ <Text
236
+ variant={isMobile ? 'body2' : 'body1'}
237
+ css={{
238
+ c:
239
+ indexSelected === index || indexSelected === FEEBACK_INDEX.INIT
240
+ ? '$on_surface_medium'
241
+ : '$on_surface_low',
242
+ fontWeight: '$regular',
243
+ }}
244
+ >
245
+ {element.label}
246
+ </Text>
247
+ </Flex>
248
+ );
249
+ })}
250
+ </Flex>
251
+ </>
252
+ );
253
+ };
254
+ export const FeedbackForm = ({
255
+ rating,
256
+ comment,
257
+ setComment,
258
+ selectedReasons,
259
+ handleCheckedChange,
260
+ }: {
261
+ rating: Rating;
262
+ comment: string;
263
+ setComment: (value: string) => void;
264
+ selectedReasons: Set<number>;
265
+ handleCheckedChange: (checked: string | boolean, index: number) => void;
266
+ }) => {
267
+ const { feedback } = useRoomLayoutLeaveScreen();
268
+ return (
269
+ <>
270
+ {rating.reasons && rating.reasons.length > 0 && (
271
+ <Flex
272
+ direction="column"
273
+ css={{
274
+ gap: '$4',
275
+ }}
276
+ >
277
+ <Text
278
+ variant="sub2"
279
+ css={{
280
+ c: '$on_surface_high',
281
+ fontWeight: '$semiBold',
282
+ fontSize: '$sm',
283
+ px: '$2',
284
+ }}
285
+ >
286
+ {rating.question || 'What do you like/dislike here?'}
287
+ </Text>
288
+ <Flex
289
+ css={{
290
+ alignItems: 'flex-start',
291
+ alignSelf: 'stretch',
292
+ flexWrap: 'wrap',
293
+ gap: '$6',
294
+ flex: '1 1 calc(25% - 12px)',
295
+ '@md': {
296
+ flex: '1 1 calc(50% - 12px)',
297
+ },
298
+ '@sm': {
299
+ flex: '1 1 100%',
300
+ },
301
+ }}
302
+ >
303
+ {rating.reasons.map((option: string, index: number) => {
304
+ return (
305
+ <Flex
306
+ align="center"
307
+ gap="2"
308
+ key={index}
309
+ css={{
310
+ border: '1px solid $border_bright',
311
+ r: '$1',
312
+ p: '$6',
313
+ }}
314
+ >
315
+ <Checkbox.Root
316
+ id={`${option}-${index}`}
317
+ checked={selectedReasons.has(index)}
318
+ onCheckedChange={checked => handleCheckedChange(checked, index)}
319
+ css={{
320
+ cursor: 'pointer',
321
+ flexShrink: 0,
322
+ bg: '$on_secondary_low',
323
+ border: '1px solid $border_bright',
324
+ }}
325
+ >
326
+ <Checkbox.Indicator>
327
+ <CheckIcon width={12} height={12} />
328
+ </Checkbox.Indicator>
329
+ </Checkbox.Root>
330
+ <Label
331
+ htmlFor={`${option}-${index}`}
332
+ css={{
333
+ color: '$on_surface_high',
334
+ fontSize: '$sm',
335
+ fontWeight: '$regular',
336
+ lineHeight: '20px' /* 142.857% */,
337
+ }}
338
+ >
339
+ {option}
340
+ </Label>
341
+ </Flex>
342
+ );
343
+ })}
344
+ </Flex>
345
+ </Flex>
346
+ )}
347
+ {feedback?.comment && (
348
+ <Flex
349
+ direction="column"
350
+ css={{
351
+ gap: '$4',
352
+ }}
353
+ >
354
+ <Text
355
+ variant="body2"
356
+ css={{
357
+ c: '$on_surface_high',
358
+ fontWeight: '$regular',
359
+ fontSize: '$sm',
360
+ }}
361
+ >
362
+ {feedback?.comment.label || 'Additional comments (optional)'}
363
+ </Text>
364
+ <TextArea
365
+ maxLength={1024}
366
+ placeholder={feedback?.comment.placeholder || 'Tell us more...'}
367
+ css={{
368
+ backgroundColor: '$surface_bright',
369
+ border: '1px solid $border_bright',
370
+ resize: 'none',
371
+ height: '$36',
372
+ display: 'flex',
373
+ }}
374
+ value={comment}
375
+ onChange={event => setComment(event.target.value.trimStart())}
376
+ />
377
+ </Flex>
378
+ )}
379
+ </>
380
+ );
381
+ };
@@ -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
  );
@@ -50,7 +50,10 @@ export const PIPChat = () => {
50
50
  const isLocalPeerBlacklisted = useIsPeerBlacklisted({ local: true });
51
51
  const { elements } = useRoomLayoutConferencingScreen();
52
52
  const message_placeholder = elements?.chat?.message_placeholder || 'Send a message';
53
- const canSendChatMessages = !!elements?.chat?.public_chat_enabled || !!elements?.chat?.roles_whitelist?.length;
53
+ const canSendChatMessages =
54
+ !!elements?.chat?.public_chat_enabled ||
55
+ !!elements?.chat?.roles_whitelist?.length ||
56
+ !!elements?.chat?.private_chat_enabled;
54
57
 
55
58
  const getChatStatus = useCallback(() => {
56
59
  if (isLocalPeerBlacklisted) return "You've been blocked from sending messages";
@@ -114,9 +117,13 @@ export const PIPChat = () => {
114
117
  <Text variant="h5" css={{ mt: '$8', c: '$on_surface_high' }}>
115
118
  {canSendChatMessages ? 'Start a conversation' : 'No messages yet'}
116
119
  </Text>
117
- <Text variant="sm" style={{ maxWidth: '80%', textAlign: 'center', marginTop: '4px' }}>
118
- There are no messages here yet. Start a conversation by sending a message.
119
- </Text>
120
+ {canSendChatMessages ? (
121
+ <Text variant="sm" style={{ maxWidth: '80%', textAlign: 'center', marginTop: '4px' }}>
122
+ There are no messages here yet. Start a conversation by sending a message.
123
+ </Text>
124
+ ) : (
125
+ ''
126
+ )}
120
127
  </div>
121
128
  ) : (
122
129
  filteredMessages.map(message => (