@stream-io/video-react-sdk 0.0.1-alpha.9

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 (418) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/LICENSE +219 -0
  3. package/README.md +5 -0
  4. package/dist/css/styles.css +2351 -0
  5. package/dist/css/styles.css.map +1 -0
  6. package/dist/index.d.ts +6 -0
  7. package/dist/index.js +15 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/src/components/Avatar/Avatar.d.ts +14 -0
  10. package/dist/src/components/Avatar/Avatar.js +11 -0
  11. package/dist/src/components/Avatar/Avatar.js.map +1 -0
  12. package/dist/src/components/Avatar/index.d.ts +1 -0
  13. package/dist/src/components/Avatar/index.js +2 -0
  14. package/dist/src/components/Avatar/index.js.map +1 -0
  15. package/dist/src/components/Button/CompositeButton.d.ts +16 -0
  16. package/dist/src/components/Button/CompositeButton.js +15 -0
  17. package/dist/src/components/Button/CompositeButton.js.map +1 -0
  18. package/dist/src/components/Button/CopyToClipboardButton.d.ts +27 -0
  19. package/dist/src/components/Button/CopyToClipboardButton.js +54 -0
  20. package/dist/src/components/Button/CopyToClipboardButton.js.map +1 -0
  21. package/dist/src/components/Button/IconButton.d.ts +7 -0
  22. package/dist/src/components/Button/IconButton.js +26 -0
  23. package/dist/src/components/Button/IconButton.js.map +1 -0
  24. package/dist/src/components/Button/TextButton.d.ts +2 -0
  25. package/dist/src/components/Button/TextButton.js +17 -0
  26. package/dist/src/components/Button/TextButton.js.map +1 -0
  27. package/dist/src/components/Button/index.d.ts +4 -0
  28. package/dist/src/components/Button/index.js +5 -0
  29. package/dist/src/components/Button/index.js.map +1 -0
  30. package/dist/src/components/CallControls/CallControls.d.ts +7 -0
  31. package/dist/src/components/CallControls/CallControls.js +8 -0
  32. package/dist/src/components/CallControls/CallControls.js.map +1 -0
  33. package/dist/src/components/CallControls/CallStatsButton.d.ts +6 -0
  34. package/dist/src/components/CallControls/CallStatsButton.js +10 -0
  35. package/dist/src/components/CallControls/CallStatsButton.js.map +1 -0
  36. package/dist/src/components/CallControls/CancelCallButton.d.ts +8 -0
  37. package/dist/src/components/CallControls/CancelCallButton.js +25 -0
  38. package/dist/src/components/CallControls/CancelCallButton.js.map +1 -0
  39. package/dist/src/components/CallControls/ReactionsButton.d.ts +11 -0
  40. package/dist/src/components/CallControls/ReactionsButton.js +33 -0
  41. package/dist/src/components/CallControls/ReactionsButton.js.map +1 -0
  42. package/dist/src/components/CallControls/RecordCallButton.d.ts +7 -0
  43. package/dist/src/components/CallControls/RecordCallButton.js +51 -0
  44. package/dist/src/components/CallControls/RecordCallButton.js.map +1 -0
  45. package/dist/src/components/CallControls/ScreenShareButton.d.ts +7 -0
  46. package/dist/src/components/CallControls/ScreenShareButton.js +54 -0
  47. package/dist/src/components/CallControls/ScreenShareButton.js.map +1 -0
  48. package/dist/src/components/CallControls/ToggleAudioButton.d.ts +9 -0
  49. package/dist/src/components/CallControls/ToggleAudioButton.js +66 -0
  50. package/dist/src/components/CallControls/ToggleAudioButton.js.map +1 -0
  51. package/dist/src/components/CallControls/ToggleAudioOutputButton.d.ts +5 -0
  52. package/dist/src/components/CallControls/ToggleAudioOutputButton.js +9 -0
  53. package/dist/src/components/CallControls/ToggleAudioOutputButton.js.map +1 -0
  54. package/dist/src/components/CallControls/ToggleCameraButton.d.ts +10 -0
  55. package/dist/src/components/CallControls/ToggleCameraButton.js +64 -0
  56. package/dist/src/components/CallControls/ToggleCameraButton.js.map +1 -0
  57. package/dist/src/components/CallControls/ToggleParticipantListButton.d.ts +6 -0
  58. package/dist/src/components/CallControls/ToggleParticipantListButton.js +7 -0
  59. package/dist/src/components/CallControls/ToggleParticipantListButton.js.map +1 -0
  60. package/dist/src/components/CallControls/index.d.ts +10 -0
  61. package/dist/src/components/CallControls/index.js +11 -0
  62. package/dist/src/components/CallControls/index.js.map +1 -0
  63. package/dist/src/components/CallParticipantsList/BlockedUserListing.d.ts +4 -0
  64. package/dist/src/components/CallParticipantsList/BlockedUserListing.js +19 -0
  65. package/dist/src/components/CallParticipantsList/BlockedUserListing.js.map +1 -0
  66. package/dist/src/components/CallParticipantsList/CallParticipantListHeader.d.ts +6 -0
  67. package/dist/src/components/CallParticipantsList/CallParticipantListHeader.js +7 -0
  68. package/dist/src/components/CallParticipantsList/CallParticipantListHeader.js.map +1 -0
  69. package/dist/src/components/CallParticipantsList/CallParticipantListing.d.ts +8 -0
  70. package/dist/src/components/CallParticipantsList/CallParticipantListing.js +4 -0
  71. package/dist/src/components/CallParticipantsList/CallParticipantListing.js.map +1 -0
  72. package/dist/src/components/CallParticipantsList/CallParticipantListingItem.d.ts +15 -0
  73. package/dist/src/components/CallParticipantsList/CallParticipantListingItem.js +77 -0
  74. package/dist/src/components/CallParticipantsList/CallParticipantListingItem.js.map +1 -0
  75. package/dist/src/components/CallParticipantsList/CallParticipantsList.d.ts +15 -0
  76. package/dist/src/components/CallParticipantsList/CallParticipantsList.js +82 -0
  77. package/dist/src/components/CallParticipantsList/CallParticipantsList.js.map +1 -0
  78. package/dist/src/components/CallParticipantsList/EmptyParticipantSearchList.d.ts +2 -0
  79. package/dist/src/components/CallParticipantsList/EmptyParticipantSearchList.js +5 -0
  80. package/dist/src/components/CallParticipantsList/EmptyParticipantSearchList.js.map +1 -0
  81. package/dist/src/components/CallParticipantsList/index.d.ts +3 -0
  82. package/dist/src/components/CallParticipantsList/index.js +4 -0
  83. package/dist/src/components/CallParticipantsList/index.js.map +1 -0
  84. package/dist/src/components/CallRecordingList/CallRecordingList.d.ts +20 -0
  85. package/dist/src/components/CallRecordingList/CallRecordingList.js +9 -0
  86. package/dist/src/components/CallRecordingList/CallRecordingList.js.map +1 -0
  87. package/dist/src/components/CallRecordingList/CallRecordingListHeader.d.ts +7 -0
  88. package/dist/src/components/CallRecordingList/CallRecordingListHeader.js +8 -0
  89. package/dist/src/components/CallRecordingList/CallRecordingListHeader.js.map +1 -0
  90. package/dist/src/components/CallRecordingList/CallRecordingListItem.d.ts +7 -0
  91. package/dist/src/components/CallRecordingList/CallRecordingListItem.js +11 -0
  92. package/dist/src/components/CallRecordingList/CallRecordingListItem.js.map +1 -0
  93. package/dist/src/components/CallRecordingList/EmptyCallRecordingListing.d.ts +2 -0
  94. package/dist/src/components/CallRecordingList/EmptyCallRecordingListing.js +5 -0
  95. package/dist/src/components/CallRecordingList/EmptyCallRecordingListing.js.map +1 -0
  96. package/dist/src/components/CallRecordingList/LoadingCallRecordingListing.d.ts +7 -0
  97. package/dist/src/components/CallRecordingList/LoadingCallRecordingListing.js +7 -0
  98. package/dist/src/components/CallRecordingList/LoadingCallRecordingListing.js.map +1 -0
  99. package/dist/src/components/CallRecordingList/index.d.ts +5 -0
  100. package/dist/src/components/CallRecordingList/index.js +6 -0
  101. package/dist/src/components/CallRecordingList/index.js.map +1 -0
  102. package/dist/src/components/Debug/DebugParticipantPublishQuality.d.ts +6 -0
  103. package/dist/src/components/Debug/DebugParticipantPublishQuality.js +46 -0
  104. package/dist/src/components/Debug/DebugParticipantPublishQuality.js.map +1 -0
  105. package/dist/src/components/Debug/DebugStatsView.d.ts +7 -0
  106. package/dist/src/components/Debug/DebugStatsView.js +26 -0
  107. package/dist/src/components/Debug/DebugStatsView.js.map +1 -0
  108. package/dist/src/components/Debug/useIsDebugMode.d.ts +5 -0
  109. package/dist/src/components/Debug/useIsDebugMode.js +18 -0
  110. package/dist/src/components/Debug/useIsDebugMode.js.map +1 -0
  111. package/dist/src/components/DeviceSettings/DeviceSelector.d.ts +7 -0
  112. package/dist/src/components/DeviceSettings/DeviceSelector.js +26 -0
  113. package/dist/src/components/DeviceSettings/DeviceSelector.js.map +1 -0
  114. package/dist/src/components/DeviceSettings/DeviceSelectorAudio.d.ts +9 -0
  115. package/dist/src/components/DeviceSettings/DeviceSelectorAudio.js +18 -0
  116. package/dist/src/components/DeviceSettings/DeviceSelectorAudio.js.map +1 -0
  117. package/dist/src/components/DeviceSettings/DeviceSelectorVideo.d.ts +5 -0
  118. package/dist/src/components/DeviceSettings/DeviceSelectorVideo.js +10 -0
  119. package/dist/src/components/DeviceSettings/DeviceSelectorVideo.js.map +1 -0
  120. package/dist/src/components/DeviceSettings/DeviceSettings.d.ts +2 -0
  121. package/dist/src/components/DeviceSettings/DeviceSettings.js +15 -0
  122. package/dist/src/components/DeviceSettings/DeviceSettings.js.map +1 -0
  123. package/dist/src/components/DeviceSettings/index.d.ts +4 -0
  124. package/dist/src/components/DeviceSettings/index.js +5 -0
  125. package/dist/src/components/DeviceSettings/index.js.map +1 -0
  126. package/dist/src/components/Icon/Icon.d.ts +5 -0
  127. package/dist/src/components/Icon/Icon.js +4 -0
  128. package/dist/src/components/Icon/Icon.js.map +1 -0
  129. package/dist/src/components/Icon/index.d.ts +1 -0
  130. package/dist/src/components/Icon/index.js +2 -0
  131. package/dist/src/components/Icon/index.js.map +1 -0
  132. package/dist/src/components/LoadingIndicator/LoadingIndicator.d.ts +11 -0
  133. package/dist/src/components/LoadingIndicator/LoadingIndicator.js +6 -0
  134. package/dist/src/components/LoadingIndicator/LoadingIndicator.js.map +1 -0
  135. package/dist/src/components/LoadingIndicator/index.d.ts +1 -0
  136. package/dist/src/components/LoadingIndicator/index.js +2 -0
  137. package/dist/src/components/LoadingIndicator/index.js.map +1 -0
  138. package/dist/src/components/Menu/GenericMenu.d.ts +3 -0
  139. package/dist/src/components/Menu/GenericMenu.js +20 -0
  140. package/dist/src/components/Menu/GenericMenu.js.map +1 -0
  141. package/dist/src/components/Menu/MenuToggle.d.ts +12 -0
  142. package/dist/src/components/Menu/MenuToggle.js +40 -0
  143. package/dist/src/components/Menu/MenuToggle.js.map +1 -0
  144. package/dist/src/components/Menu/index.d.ts +2 -0
  145. package/dist/src/components/Menu/index.js +3 -0
  146. package/dist/src/components/Menu/index.js.map +1 -0
  147. package/dist/src/components/Moderation/Restricted.d.ts +19 -0
  148. package/dist/src/components/Moderation/Restricted.js +13 -0
  149. package/dist/src/components/Moderation/Restricted.js.map +1 -0
  150. package/dist/src/components/Moderation/index.d.ts +1 -0
  151. package/dist/src/components/Moderation/index.js +2 -0
  152. package/dist/src/components/Moderation/index.js.map +1 -0
  153. package/dist/src/components/Notification/Notification.d.ts +11 -0
  154. package/dist/src/components/Notification/Notification.js +25 -0
  155. package/dist/src/components/Notification/Notification.js.map +1 -0
  156. package/dist/src/components/Notification/PermissionNotification.d.ts +33 -0
  157. package/dist/src/components/Notification/PermissionNotification.js +26 -0
  158. package/dist/src/components/Notification/PermissionNotification.js.map +1 -0
  159. package/dist/src/components/Notification/SpeakingWhileMutedNotification.d.ts +3 -0
  160. package/dist/src/components/Notification/SpeakingWhileMutedNotification.js +45 -0
  161. package/dist/src/components/Notification/SpeakingWhileMutedNotification.js.map +1 -0
  162. package/dist/src/components/Notification/index.d.ts +3 -0
  163. package/dist/src/components/Notification/index.js +4 -0
  164. package/dist/src/components/Notification/index.js.map +1 -0
  165. package/dist/src/components/Permissions/PermissionRequests.d.ts +8 -0
  166. package/dist/src/components/Permissions/PermissionRequests.js +109 -0
  167. package/dist/src/components/Permissions/PermissionRequests.js.map +1 -0
  168. package/dist/src/components/Permissions/index.d.ts +1 -0
  169. package/dist/src/components/Permissions/index.js +2 -0
  170. package/dist/src/components/Permissions/index.js.map +1 -0
  171. package/dist/src/components/Reaction/Reaction.d.ts +10 -0
  172. package/dist/src/components/Reaction/Reaction.js +28 -0
  173. package/dist/src/components/Reaction/Reaction.js.map +1 -0
  174. package/dist/src/components/Reaction/index.d.ts +1 -0
  175. package/dist/src/components/Reaction/index.js +2 -0
  176. package/dist/src/components/Reaction/index.js.map +1 -0
  177. package/dist/src/components/Search/SearchInput.d.ts +14 -0
  178. package/dist/src/components/Search/SearchInput.js +34 -0
  179. package/dist/src/components/Search/SearchInput.js.map +1 -0
  180. package/dist/src/components/Search/SearchResults.d.ts +14 -0
  181. package/dist/src/components/Search/SearchResults.js +12 -0
  182. package/dist/src/components/Search/SearchResults.js.map +1 -0
  183. package/dist/src/components/Search/hooks/index.d.ts +1 -0
  184. package/dist/src/components/Search/hooks/index.js +2 -0
  185. package/dist/src/components/Search/hooks/index.js.map +1 -0
  186. package/dist/src/components/Search/hooks/useSearch.d.ts +15 -0
  187. package/dist/src/components/Search/hooks/useSearch.js +39 -0
  188. package/dist/src/components/Search/hooks/useSearch.js.map +1 -0
  189. package/dist/src/components/Search/index.d.ts +2 -0
  190. package/dist/src/components/Search/index.js +3 -0
  191. package/dist/src/components/Search/index.js.map +1 -0
  192. package/dist/src/components/StreamCall/CallParticipantsScreenView.d.ts +5 -0
  193. package/dist/src/components/StreamCall/CallParticipantsScreenView.js +34 -0
  194. package/dist/src/components/StreamCall/CallParticipantsScreenView.js.map +1 -0
  195. package/dist/src/components/StreamCall/CallParticipantsView.d.ts +5 -0
  196. package/dist/src/components/StreamCall/CallParticipantsView.js +11 -0
  197. package/dist/src/components/StreamCall/CallParticipantsView.js.map +1 -0
  198. package/dist/src/components/StreamCall/CallStats.d.ts +2 -0
  199. package/dist/src/components/StreamCall/CallStats.js +69 -0
  200. package/dist/src/components/StreamCall/CallStats.js.map +1 -0
  201. package/dist/src/components/StreamCall/CallStatsLatencyChart.d.ts +7 -0
  202. package/dist/src/components/StreamCall/CallStatsLatencyChart.js +39 -0
  203. package/dist/src/components/StreamCall/CallStatsLatencyChart.js.map +1 -0
  204. package/dist/src/components/StreamCall/Stage.d.ts +8 -0
  205. package/dist/src/components/StreamCall/Stage.js +13 -0
  206. package/dist/src/components/StreamCall/Stage.js.map +1 -0
  207. package/dist/src/components/StreamCall/hooks/index.d.ts +1 -0
  208. package/dist/src/components/StreamCall/hooks/index.js +2 -0
  209. package/dist/src/components/StreamCall/hooks/index.js.map +1 -0
  210. package/dist/src/components/StreamCall/hooks/useScrollPosition.d.ts +6 -0
  211. package/dist/src/components/StreamCall/hooks/useScrollPosition.js +63 -0
  212. package/dist/src/components/StreamCall/hooks/useScrollPosition.js.map +1 -0
  213. package/dist/src/components/StreamCall/index.d.ts +3 -0
  214. package/dist/src/components/StreamCall/index.js +4 -0
  215. package/dist/src/components/StreamCall/index.js.map +1 -0
  216. package/dist/src/components/StreamMeeting/StreamMeeting.d.ts +34 -0
  217. package/dist/src/components/StreamMeeting/StreamMeeting.js +26 -0
  218. package/dist/src/components/StreamMeeting/StreamMeeting.js.map +1 -0
  219. package/dist/src/components/StreamMeeting/index.d.ts +1 -0
  220. package/dist/src/components/StreamMeeting/index.js +2 -0
  221. package/dist/src/components/StreamMeeting/index.js.map +1 -0
  222. package/dist/src/components/Tooltip/Tooltip.d.ts +15 -0
  223. package/dist/src/components/Tooltip/Tooltip.js +22 -0
  224. package/dist/src/components/Tooltip/Tooltip.js.map +1 -0
  225. package/dist/src/components/Tooltip/WithTooltip.d.ts +5 -0
  226. package/dist/src/components/Tooltip/WithTooltip.js +23 -0
  227. package/dist/src/components/Tooltip/WithTooltip.js.map +1 -0
  228. package/dist/src/components/Tooltip/hooks/index.d.ts +1 -0
  229. package/dist/src/components/Tooltip/hooks/index.js +2 -0
  230. package/dist/src/components/Tooltip/hooks/index.js.map +1 -0
  231. package/dist/src/components/Tooltip/hooks/useEnterLeaveHandlers.d.ts +6 -0
  232. package/dist/src/components/Tooltip/hooks/useEnterLeaveHandlers.js +14 -0
  233. package/dist/src/components/Tooltip/hooks/useEnterLeaveHandlers.js.map +1 -0
  234. package/dist/src/components/Tooltip/index.d.ts +2 -0
  235. package/dist/src/components/Tooltip/index.js +3 -0
  236. package/dist/src/components/Tooltip/index.js.map +1 -0
  237. package/dist/src/components/Video/VideoPreview.d.ts +13 -0
  238. package/dist/src/components/Video/VideoPreview.js +70 -0
  239. package/dist/src/components/Video/VideoPreview.js.map +1 -0
  240. package/dist/src/components/Video/index.d.ts +4 -0
  241. package/dist/src/components/Video/index.js +5 -0
  242. package/dist/src/components/Video/index.js.map +1 -0
  243. package/dist/src/components/index.d.ts +16 -0
  244. package/dist/src/components/index.js +17 -0
  245. package/dist/src/components/index.js.map +1 -0
  246. package/dist/src/core/components/Audio/Audio.d.ts +6 -0
  247. package/dist/src/core/components/Audio/Audio.js +39 -0
  248. package/dist/src/core/components/Audio/Audio.js.map +1 -0
  249. package/dist/src/core/components/Audio/index.d.ts +1 -0
  250. package/dist/src/core/components/Audio/index.js +2 -0
  251. package/dist/src/core/components/Audio/index.js.map +1 -0
  252. package/dist/src/core/components/CallLayout/PaginatedGridLayout.d.ts +21 -0
  253. package/dist/src/core/components/CallLayout/PaginatedGridLayout.js +39 -0
  254. package/dist/src/core/components/CallLayout/PaginatedGridLayout.js.map +1 -0
  255. package/dist/src/core/components/CallLayout/SpeakerLayout.d.ts +2 -0
  256. package/dist/src/core/components/CallLayout/SpeakerLayout.js +52 -0
  257. package/dist/src/core/components/CallLayout/SpeakerLayout.js.map +1 -0
  258. package/dist/src/core/components/CallLayout/index.d.ts +2 -0
  259. package/dist/src/core/components/CallLayout/index.js +3 -0
  260. package/dist/src/core/components/CallLayout/index.js.map +1 -0
  261. package/dist/src/core/components/ParticipantBox/ParticipantBox.d.ts +48 -0
  262. package/dist/src/core/components/ParticipantBox/ParticipantBox.js +58 -0
  263. package/dist/src/core/components/ParticipantBox/ParticipantBox.js.map +1 -0
  264. package/dist/src/core/components/ParticipantBox/index.d.ts +1 -0
  265. package/dist/src/core/components/ParticipantBox/index.js +2 -0
  266. package/dist/src/core/components/ParticipantBox/index.js.map +1 -0
  267. package/dist/src/core/components/Video/BaseVideo.d.ts +9 -0
  268. package/dist/src/core/components/Video/BaseVideo.js +54 -0
  269. package/dist/src/core/components/Video/BaseVideo.js.map +1 -0
  270. package/dist/src/core/components/Video/Video.d.ts +8 -0
  271. package/dist/src/core/components/Video/Video.js +151 -0
  272. package/dist/src/core/components/Video/Video.js.map +1 -0
  273. package/dist/src/core/components/Video/VideoPlaceholder.d.ts +6 -0
  274. package/dist/src/core/components/Video/VideoPlaceholder.js +12 -0
  275. package/dist/src/core/components/Video/VideoPlaceholder.js.map +1 -0
  276. package/dist/src/core/components/Video/index.d.ts +2 -0
  277. package/dist/src/core/components/Video/index.js +3 -0
  278. package/dist/src/core/components/Video/index.js.map +1 -0
  279. package/dist/src/core/components/index.d.ts +5 -0
  280. package/dist/src/core/components/index.js +5 -0
  281. package/dist/src/core/components/index.js.map +1 -0
  282. package/dist/src/core/contexts/MediaDevicesContext.d.ts +82 -0
  283. package/dist/src/core/contexts/MediaDevicesContext.js +215 -0
  284. package/dist/src/core/contexts/MediaDevicesContext.js.map +1 -0
  285. package/dist/src/core/contexts/index.d.ts +1 -0
  286. package/dist/src/core/contexts/index.js +2 -0
  287. package/dist/src/core/contexts/index.js.map +1 -0
  288. package/dist/src/core/hooks/index.d.ts +2 -0
  289. package/dist/src/core/hooks/index.js +3 -0
  290. package/dist/src/core/hooks/index.js.map +1 -0
  291. package/dist/src/core/hooks/useAudioPublisher.d.ts +12 -0
  292. package/dist/src/core/hooks/useAudioPublisher.js +89 -0
  293. package/dist/src/core/hooks/useAudioPublisher.js.map +1 -0
  294. package/dist/src/core/hooks/useVideoPublisher.d.ts +12 -0
  295. package/dist/src/core/hooks/useVideoPublisher.js +91 -0
  296. package/dist/src/core/hooks/useVideoPublisher.js.map +1 -0
  297. package/dist/src/core/index.d.ts +3 -0
  298. package/dist/src/core/index.js +4 -0
  299. package/dist/src/core/index.js.map +1 -0
  300. package/dist/src/hooks/index.d.ts +2 -0
  301. package/dist/src/hooks/index.js +3 -0
  302. package/dist/src/hooks/index.js.map +1 -0
  303. package/dist/src/hooks/useFloatingUIPreset.d.ts +9 -0
  304. package/dist/src/hooks/useFloatingUIPreset.js +29 -0
  305. package/dist/src/hooks/useFloatingUIPreset.js.map +1 -0
  306. package/dist/src/hooks/useRtcStats.d.ts +11 -0
  307. package/dist/src/hooks/useRtcStats.js +39 -0
  308. package/dist/src/hooks/useRtcStats.js.map +1 -0
  309. package/dist/src/types/components.d.ts +7 -0
  310. package/dist/src/types/components.js +2 -0
  311. package/dist/src/types/components.js.map +1 -0
  312. package/dist/src/types/index.d.ts +1 -0
  313. package/dist/src/types/index.js +2 -0
  314. package/dist/src/types/index.js.map +1 -0
  315. package/index.ts +18 -0
  316. package/package.json +49 -0
  317. package/src/components/Avatar/Avatar.tsx +45 -0
  318. package/src/components/Avatar/index.ts +1 -0
  319. package/src/components/Button/CompositeButton.tsx +59 -0
  320. package/src/components/Button/CopyToClipboardButton.tsx +129 -0
  321. package/src/components/Button/IconButton.tsx +32 -0
  322. package/src/components/Button/TextButton.tsx +12 -0
  323. package/src/components/Button/index.ts +4 -0
  324. package/src/components/CallControls/CallControls.tsx +32 -0
  325. package/src/components/CallControls/CallStatsButton.tsx +28 -0
  326. package/src/components/CallControls/CancelCallButton.tsx +28 -0
  327. package/src/components/CallControls/ReactionsButton.tsx +75 -0
  328. package/src/components/CallControls/RecordCallButton.tsx +68 -0
  329. package/src/components/CallControls/ScreenShareButton.tsx +85 -0
  330. package/src/components/CallControls/ToggleAudioButton.tsx +112 -0
  331. package/src/components/CallControls/ToggleAudioOutputButton.tsx +21 -0
  332. package/src/components/CallControls/ToggleCameraButton.tsx +109 -0
  333. package/src/components/CallControls/ToggleParticipantListButton.tsx +17 -0
  334. package/src/components/CallControls/index.ts +10 -0
  335. package/src/components/CallParticipantsList/BlockedUserListing.tsx +38 -0
  336. package/src/components/CallParticipantsList/CallParticipantListHeader.tsx +29 -0
  337. package/src/components/CallParticipantsList/CallParticipantListing.tsx +22 -0
  338. package/src/components/CallParticipantsList/CallParticipantListingItem.tsx +249 -0
  339. package/src/components/CallParticipantsList/CallParticipantsList.tsx +255 -0
  340. package/src/components/CallParticipantsList/EmptyParticipantSearchList.tsx +7 -0
  341. package/src/components/CallParticipantsList/index.ts +3 -0
  342. package/src/components/CallRecordingList/CallRecordingList.tsx +60 -0
  343. package/src/components/CallRecordingList/CallRecordingListHeader.tsx +29 -0
  344. package/src/components/CallRecordingList/CallRecordingListItem.tsx +67 -0
  345. package/src/components/CallRecordingList/EmptyCallRecordingListing.tsx +11 -0
  346. package/src/components/CallRecordingList/LoadingCallRecordingListing.tsx +21 -0
  347. package/src/components/CallRecordingList/index.ts +5 -0
  348. package/src/components/Debug/DebugParticipantPublishQuality.tsx +62 -0
  349. package/src/components/Debug/DebugStatsView.tsx +55 -0
  350. package/src/components/Debug/useIsDebugMode.ts +24 -0
  351. package/src/components/DeviceSettings/DeviceSelector.tsx +106 -0
  352. package/src/components/DeviceSettings/DeviceSelectorAudio.tsx +52 -0
  353. package/src/components/DeviceSettings/DeviceSelectorVideo.tsx +22 -0
  354. package/src/components/DeviceSettings/DeviceSettings.tsx +39 -0
  355. package/src/components/DeviceSettings/index.ts +4 -0
  356. package/src/components/Icon/Icon.tsx +11 -0
  357. package/src/components/Icon/index.ts +1 -0
  358. package/src/components/LoadingIndicator/LoadingIndicator.tsx +28 -0
  359. package/src/components/LoadingIndicator/index.ts +1 -0
  360. package/src/components/Menu/GenericMenu.tsx +16 -0
  361. package/src/components/Menu/MenuToggle.tsx +81 -0
  362. package/src/components/Menu/index.ts +2 -0
  363. package/src/components/Moderation/Restricted.tsx +38 -0
  364. package/src/components/Moderation/index.ts +1 -0
  365. package/src/components/Notification/Notification.tsx +61 -0
  366. package/src/components/Notification/PermissionNotification.tsx +97 -0
  367. package/src/components/Notification/SpeakingWhileMutedNotification.tsx +60 -0
  368. package/src/components/Notification/index.ts +3 -0
  369. package/src/components/Permissions/PermissionRequests.tsx +182 -0
  370. package/src/components/Permissions/index.ts +1 -0
  371. package/src/components/Reaction/Reaction.tsx +48 -0
  372. package/src/components/Reaction/index.ts +1 -0
  373. package/src/components/Search/SearchInput.tsx +56 -0
  374. package/src/components/Search/SearchResults.tsx +40 -0
  375. package/src/components/Search/hooks/index.ts +1 -0
  376. package/src/components/Search/hooks/useSearch.ts +52 -0
  377. package/src/components/Search/index.ts +2 -0
  378. package/src/components/StreamCall/CallParticipantsScreenView.tsx +126 -0
  379. package/src/components/StreamCall/CallParticipantsView.tsx +25 -0
  380. package/src/components/StreamCall/CallStats.tsx +162 -0
  381. package/src/components/StreamCall/CallStatsLatencyChart.tsx +58 -0
  382. package/src/components/StreamCall/Stage.tsx +22 -0
  383. package/src/components/StreamCall/hooks/index.ts +1 -0
  384. package/src/components/StreamCall/hooks/useScrollPosition.ts +95 -0
  385. package/src/components/StreamCall/index.ts +4 -0
  386. package/src/components/StreamMeeting/StreamMeeting.tsx +80 -0
  387. package/src/components/StreamMeeting/index.ts +1 -0
  388. package/src/components/Tooltip/Tooltip.tsx +51 -0
  389. package/src/components/Tooltip/WithTooltip.tsx +39 -0
  390. package/src/components/Tooltip/hooks/index.ts +1 -0
  391. package/src/components/Tooltip/hooks/useEnterLeaveHandlers.ts +28 -0
  392. package/src/components/Tooltip/index.ts +2 -0
  393. package/src/components/Video/VideoPreview.tsx +127 -0
  394. package/src/components/Video/index.ts +4 -0
  395. package/src/components/index.ts +16 -0
  396. package/src/core/components/Audio/Audio.tsx +42 -0
  397. package/src/core/components/Audio/index.ts +1 -0
  398. package/src/core/components/CallLayout/PaginatedGridLayout.tsx +163 -0
  399. package/src/core/components/CallLayout/SpeakerLayout.tsx +145 -0
  400. package/src/core/components/CallLayout/index.ts +2 -0
  401. package/src/core/components/ParticipantBox/ParticipantBox.tsx +248 -0
  402. package/src/core/components/ParticipantBox/index.ts +1 -0
  403. package/src/core/components/Video/BaseVideo.tsx +68 -0
  404. package/src/core/components/Video/Video.tsx +238 -0
  405. package/src/core/components/Video/VideoPlaceholder.tsx +40 -0
  406. package/src/core/components/Video/index.ts +2 -0
  407. package/src/core/components/index.ts +7 -0
  408. package/src/core/contexts/MediaDevicesContext.tsx +373 -0
  409. package/src/core/contexts/index.ts +1 -0
  410. package/src/core/hooks/index.ts +2 -0
  411. package/src/core/hooks/useAudioPublisher.ts +118 -0
  412. package/src/core/hooks/useVideoPublisher.ts +120 -0
  413. package/src/core/index.ts +3 -0
  414. package/src/hooks/index.ts +2 -0
  415. package/src/hooks/useFloatingUIPreset.ts +48 -0
  416. package/src/hooks/useRtcStats.ts +36 -0
  417. package/src/types/components.ts +7 -0
  418. package/src/types/index.ts +1 -0
@@ -0,0 +1,16 @@
1
+ export * from './Avatar';
2
+ export * from './Button';
3
+ export * from './CallControls';
4
+ export * from '../core/components/CallLayout';
5
+ export * from './CallParticipantsList';
6
+ export * from './CallRecordingList';
7
+ export * from './DeviceSettings';
8
+ export * from './LoadingIndicator';
9
+ export * from './Menu';
10
+ export * from './Notification';
11
+ export * from './Permissions';
12
+ export * from './StreamCall';
13
+ export * from './StreamMeeting';
14
+ export * from './Search';
15
+ export * from './Tooltip';
16
+ export * from './Video';
@@ -0,0 +1,42 @@
1
+ import {
2
+ AudioHTMLAttributes,
3
+ DetailedHTMLProps,
4
+ useEffect,
5
+ useRef,
6
+ } from 'react';
7
+ import { StreamVideoParticipant } from '@stream-io/video-client';
8
+
9
+ export type AudioProps = DetailedHTMLProps<
10
+ AudioHTMLAttributes<HTMLAudioElement>,
11
+ HTMLAudioElement
12
+ > &
13
+ Pick<StreamVideoParticipant, 'audioStream'> & {
14
+ sinkId?: string;
15
+ };
16
+
17
+ // TODO: rename to BaseAudio
18
+ export const Audio = ({ audioStream, sinkId, ...rest }: AudioProps) => {
19
+ const audioRef = useRef<HTMLAudioElement>(null);
20
+ useEffect(() => {
21
+ const $el = audioRef.current;
22
+ if (!($el && audioStream)) return;
23
+
24
+ console.log(`Attaching audio stream`, $el, audioStream);
25
+ $el.srcObject = audioStream;
26
+ return () => {
27
+ $el.srcObject = null;
28
+ };
29
+ }, [audioStream]);
30
+
31
+ useEffect(() => {
32
+ const $el = audioRef.current;
33
+ if (!$el || !sinkId) return;
34
+
35
+ console.log(`Setting sinkId`, $el, sinkId);
36
+ if (($el as any).setSinkId) {
37
+ ($el as any).setSinkId(sinkId);
38
+ }
39
+ }, [sinkId]);
40
+
41
+ return <audio autoPlay ref={audioRef} {...rest} />;
42
+ };
@@ -0,0 +1 @@
1
+ export * from './Audio';
@@ -0,0 +1,163 @@
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ import {
3
+ useCall,
4
+ useLocalParticipant,
5
+ useParticipants,
6
+ useRemoteParticipants,
7
+ } from '@stream-io/video-react-bindings';
8
+ import {
9
+ StreamVideoLocalParticipant,
10
+ StreamVideoParticipant,
11
+ } from '@stream-io/video-client';
12
+ import clsx from 'clsx';
13
+
14
+ import { ParticipantBox } from '../ParticipantBox';
15
+ import { Audio } from '../Audio';
16
+ import { IconButton } from '../../../components';
17
+
18
+ const GROUP_SIZE = 16;
19
+
20
+ type PaginatedGridLayoutGroupProps = {
21
+ /**
22
+ * The group of participants to render.
23
+ */
24
+ group: Array<StreamVideoParticipant | StreamVideoLocalParticipant>;
25
+
26
+ /**
27
+ * Turns on/off the status indicator icons (mute, connection quality, etc...)
28
+ * on the participant boxes.
29
+ */
30
+ indicatorsVisible?: boolean;
31
+ };
32
+ const PaginatedGridLayoutGroup = ({
33
+ group,
34
+ indicatorsVisible = true,
35
+ }: PaginatedGridLayoutGroupProps) => {
36
+ const call = useCall();
37
+ return (
38
+ <div
39
+ className={clsx('str-video__paginated-grid-layout--group', {
40
+ 'str-video__paginated-grid-layout--one': group.length === 1,
41
+ 'str-video__paginated-grid-layout--two-four':
42
+ group.length >= 2 && group.length <= 4,
43
+ 'str-video__paginated-grid-layout--five-nine':
44
+ group.length >= 5 && group.length <= 9,
45
+ })}
46
+ >
47
+ {group.map((participant) => (
48
+ <ParticipantBox
49
+ key={participant.sessionId}
50
+ participant={participant}
51
+ call={call!}
52
+ indicatorsVisible={indicatorsVisible}
53
+ muteAudio
54
+ />
55
+ ))}
56
+ </div>
57
+ );
58
+ };
59
+
60
+ export type PaginatedGridLayoutProps = {
61
+ /**
62
+ * The number of participants to display per page.
63
+ */
64
+ groupSize?: number;
65
+
66
+ /**
67
+ * Whether to exclude the local participant from the grid.
68
+ */
69
+ excludeLocalParticipant?: boolean;
70
+
71
+ /**
72
+ * Turns on/off the status indicator icons (mute, connection quality, etc...)
73
+ * on the participant boxes.
74
+ */
75
+ indicatorsVisible?: boolean;
76
+
77
+ /**
78
+ * Turns on/off the pagination arrows.
79
+ */
80
+ pageArrowsVisible?: boolean;
81
+ };
82
+
83
+ export const PaginatedGridLayout = ({
84
+ groupSize = GROUP_SIZE,
85
+ excludeLocalParticipant = false,
86
+ indicatorsVisible = true,
87
+ pageArrowsVisible = true,
88
+ }: PaginatedGridLayoutProps) => {
89
+ const [page, setPage] = useState(0);
90
+
91
+ const localParticipant = useLocalParticipant();
92
+ const participants = useParticipants();
93
+ // used to render audio elements
94
+ const remoteParticipants = useRemoteParticipants();
95
+
96
+ // only used to render video elements
97
+ const participantGroups = useMemo(
98
+ () =>
99
+ chunk(
100
+ excludeLocalParticipant ? remoteParticipants : participants,
101
+ groupSize,
102
+ ),
103
+ [excludeLocalParticipant, remoteParticipants, participants, groupSize],
104
+ );
105
+
106
+ const pageCount = participantGroups.length;
107
+
108
+ // update page when page count is reduced and selected page no longer exists
109
+ useEffect(() => {
110
+ if (page > pageCount - 1) setPage(pageCount - 1);
111
+ }, [page, pageCount]);
112
+
113
+ const selectedGroup = participantGroups[page];
114
+
115
+ return (
116
+ <>
117
+ {remoteParticipants.map((participant) => (
118
+ <Audio
119
+ muted={false}
120
+ key={participant.sessionId}
121
+ audioStream={participant.audioStream}
122
+ sinkId={localParticipant?.audioOutputDeviceId}
123
+ />
124
+ ))}
125
+ <div className="str-video__paginated-grid-layout--wrapper">
126
+ <div className="str-video__paginated-grid-layout">
127
+ {pageArrowsVisible && pageCount > 1 && (
128
+ <IconButton
129
+ icon="caret-left"
130
+ disabled={page === 0}
131
+ onClick={() => setPage((pv) => (pv === 0 ? pv : pv - 1))}
132
+ />
133
+ )}
134
+ {selectedGroup && (
135
+ <PaginatedGridLayoutGroup
136
+ group={participantGroups[page]}
137
+ indicatorsVisible={indicatorsVisible}
138
+ />
139
+ )}
140
+ {pageArrowsVisible && pageCount > 1 && (
141
+ <IconButton
142
+ disabled={page === pageCount - 1}
143
+ icon="caret-right"
144
+ onClick={() =>
145
+ setPage((pv) => (pv === pageCount - 1 ? pv : pv + 1))
146
+ }
147
+ />
148
+ )}
149
+ </div>
150
+ </div>
151
+ </>
152
+ );
153
+ };
154
+
155
+ // TODO: move to utilities
156
+ const chunk = <T extends unknown[]>(array: T, size = GROUP_SIZE) => {
157
+ const chunkCount = Math.ceil(array.length / size);
158
+
159
+ return Array.from(
160
+ { length: chunkCount },
161
+ (_, index) => array.slice(size * index, size * index + size) as T,
162
+ );
163
+ };
@@ -0,0 +1,145 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ import {
4
+ CallTypes,
5
+ combineComparators,
6
+ Comparator,
7
+ defaultSortPreset,
8
+ screenSharing,
9
+ SfuModels,
10
+ speakerLayoutSortPreset,
11
+ StreamVideoParticipant,
12
+ } from '@stream-io/video-client';
13
+ import {
14
+ useCall,
15
+ useLocalParticipant,
16
+ useParticipants,
17
+ } from '@stream-io/video-react-bindings';
18
+
19
+ import { ParticipantBox } from '../ParticipantBox';
20
+ import { IconButton } from '../../../components/Button';
21
+ import { useHorizontalScrollPosition } from '../../../components/StreamCall/hooks';
22
+
23
+ export const SpeakerLayout = () => {
24
+ const call = useCall()!;
25
+ const [participantInSpotlight, ...otherParticipants] = useParticipants();
26
+ const [scrollWrapper, setScrollWrapper] = useState<HTMLDivElement | null>(
27
+ null,
28
+ );
29
+ const isOneOnOneCall = otherParticipants.length === 1;
30
+ const localParticipant = useLocalParticipant();
31
+
32
+ const scrollPosition = useHorizontalScrollPosition(scrollWrapper);
33
+
34
+ const scrollStartClickHandler = () => {
35
+ scrollWrapper?.scrollBy({ left: -150, behavior: 'smooth' });
36
+ };
37
+
38
+ const scrollEndClickHandler = () => {
39
+ scrollWrapper?.scrollBy({ left: 150, behavior: 'smooth' });
40
+ };
41
+
42
+ useEffect(() => {
43
+ if (!scrollWrapper) return;
44
+
45
+ const cleanup = call.viewportTracker.setViewport(scrollWrapper);
46
+
47
+ return () => cleanup();
48
+ }, [scrollWrapper, call.viewportTracker]);
49
+
50
+ useEffect(() => {
51
+ // always show the remote participant in the spotlight
52
+ if (isOneOnOneCall) {
53
+ call.setSortParticipantsBy(combineComparators(screenSharing, loggedIn));
54
+ } else {
55
+ call.setSortParticipantsBy(speakerLayoutSortPreset);
56
+ }
57
+
58
+ return () => {
59
+ // reset the sorting to the default for the call type
60
+ const callConfig = CallTypes.get(call.type);
61
+ call.setSortParticipantsBy(
62
+ callConfig.options.sortParticipantsBy || defaultSortPreset,
63
+ );
64
+ };
65
+ }, [call, isOneOnOneCall]);
66
+
67
+ const isSpeakerScreenSharing = hasScreenShare(participantInSpotlight);
68
+ return (
69
+ <div className="str-video__speaker-layout--wrapper">
70
+ <div className="str-video__speaker-layout">
71
+ <div className="str-video__speaker-layout--spotlight">
72
+ {participantInSpotlight && (
73
+ <ParticipantBox
74
+ participant={participantInSpotlight}
75
+ call={call}
76
+ muteAudio={isSpeakerScreenSharing}
77
+ videoKind={isSpeakerScreenSharing ? 'screen' : 'video'}
78
+ sinkId={localParticipant?.audioOutputDeviceId}
79
+ />
80
+ )}
81
+ </div>
82
+ {otherParticipants.length > 0 && (
83
+ <div className="str-video__speaker-layout--participants-bar-buttons-wrapper">
84
+ {scrollPosition && scrollPosition !== 'start' && (
85
+ <IconButton
86
+ onClick={scrollStartClickHandler}
87
+ icon="caret-left"
88
+ className="str-video__speaker-layout--participants-bar-button-left"
89
+ />
90
+ )}
91
+ <div
92
+ className="str-video__speaker-layout--participants-bar-wrapper"
93
+ ref={setScrollWrapper}
94
+ >
95
+ <div className="str-video__speaker-layout--participants-bar">
96
+ {isSpeakerScreenSharing && (
97
+ <div
98
+ className="str-video__speaker-layout--participant-tile"
99
+ key={participantInSpotlight.sessionId}
100
+ >
101
+ <ParticipantBox
102
+ participant={participantInSpotlight}
103
+ call={call}
104
+ sinkId={localParticipant?.audioOutputDeviceId}
105
+ toggleMenuPosition="top"
106
+ />
107
+ </div>
108
+ )}
109
+ {otherParticipants.map((participant) => (
110
+ <div
111
+ className="str-video__speaker-layout--participant-tile"
112
+ key={participant.sessionId}
113
+ >
114
+ <ParticipantBox
115
+ participant={participant}
116
+ call={call}
117
+ sinkId={localParticipant?.audioOutputDeviceId}
118
+ toggleMenuPosition="top"
119
+ />
120
+ </div>
121
+ ))}
122
+ </div>
123
+ </div>
124
+ {scrollPosition && scrollPosition !== 'end' && (
125
+ <IconButton
126
+ onClick={scrollEndClickHandler}
127
+ icon="caret-right"
128
+ className="str-video__speaker-layout--participants-bar-button-right"
129
+ />
130
+ )}
131
+ </div>
132
+ )}
133
+ </div>
134
+ </div>
135
+ );
136
+ };
137
+
138
+ const hasScreenShare = (p: StreamVideoParticipant) =>
139
+ p.publishedTracks.includes(SfuModels.TrackType.SCREEN_SHARE);
140
+
141
+ const loggedIn: Comparator<StreamVideoParticipant> = (a, b) => {
142
+ if (a.isLoggedInUser) return 1;
143
+ if (b.isLoggedInUser) return -1;
144
+ return 0;
145
+ };
@@ -0,0 +1,2 @@
1
+ export * from './PaginatedGridLayout';
2
+ export * from './SpeakerLayout';
@@ -0,0 +1,248 @@
1
+ import { forwardRef, useEffect, useState } from 'react';
2
+ import clsx from 'clsx';
3
+ import {
4
+ Call,
5
+ SfuModels,
6
+ StreamVideoParticipant,
7
+ VisibilityState,
8
+ } from '@stream-io/video-client';
9
+ import { useIsDebugMode } from '../../../components/Debug/useIsDebugMode';
10
+ import { DebugParticipantPublishQuality } from '../../../components/Debug/DebugParticipantPublishQuality';
11
+ import { DebugStatsView } from '../../../components/Debug/DebugStatsView';
12
+ import { Audio } from '../Audio/Audio';
13
+ import { Video } from '../../../components/Video';
14
+ import { Notification } from '../../../components/Notification';
15
+ import { Reaction } from '../../../components/Reaction';
16
+ import { MenuToggle, ToggleMenuButtonProps } from '../../../components/Menu';
17
+ import { IconButton } from '../../../components/Button';
18
+ import { ParticipantActionsContextMenu } from '../../../components/CallParticipantsList';
19
+
20
+ export interface ParticipantBoxProps {
21
+ /**
22
+ * The participant bound to this component.
23
+ */
24
+ participant: StreamVideoParticipant;
25
+
26
+ /**
27
+ * The current call.
28
+ */
29
+ call: Call;
30
+
31
+ /**
32
+ * In supported browsers, this sets the default audio output.
33
+ * The value of this prop should be a valid Audio Output `deviceId`.
34
+ */
35
+ sinkId?: string;
36
+
37
+ /**
38
+ * The kind of video stream to play for the given participant.
39
+ */
40
+ videoKind?: 'video' | 'screen';
41
+
42
+ /**
43
+ * Turns on/off the status indicator icons (mute, connection quality, etc...).
44
+ */
45
+ indicatorsVisible?: boolean;
46
+
47
+ /**
48
+ * Turns on/off the audio for the participant.
49
+ */
50
+ muteAudio?: boolean;
51
+
52
+ /**
53
+ * A function meant for exposing the "native" element ref to the integrators.
54
+ * The element can either be:
55
+ * - `<video />` for participants with enabled video.
56
+ * - `<div />` for participants with disabled video. This ref would point to
57
+ * the VideoPlaceholder component.
58
+ *
59
+ * @param element the element ref.
60
+ */
61
+ setVideoElementRef?: (element: HTMLElement | null) => void;
62
+
63
+ /**
64
+ * An additional list of class names to append to the root DOM element.
65
+ */
66
+ className?: string;
67
+
68
+ /**
69
+ * The position of the toggle button menu, relative to its button element.
70
+ */
71
+ toggleMenuPosition?: 'top' | 'bottom';
72
+ }
73
+
74
+ const ToggleButton = forwardRef<HTMLButtonElement, ToggleMenuButtonProps>(
75
+ (props, ref) => {
76
+ return <IconButton enabled={props.menuShown} icon="ellipsis" ref={ref} />;
77
+ },
78
+ );
79
+
80
+ export const ParticipantBox = (props: ParticipantBoxProps) => {
81
+ const {
82
+ participant,
83
+ indicatorsVisible = true,
84
+ videoKind = 'video',
85
+ call,
86
+ sinkId,
87
+ muteAudio,
88
+ setVideoElementRef,
89
+ className,
90
+ toggleMenuPosition = 'bottom',
91
+ } = props;
92
+
93
+ const {
94
+ audioStream,
95
+ videoStream,
96
+ isLoggedInUser: isLocalParticipant,
97
+ isDominantSpeaker,
98
+ isSpeaking,
99
+ publishedTracks,
100
+ connectionQuality,
101
+ sessionId,
102
+ reaction,
103
+ } = participant;
104
+
105
+ const hasAudio = publishedTracks.includes(SfuModels.TrackType.AUDIO);
106
+ const hasVideo = publishedTracks.includes(SfuModels.TrackType.VIDEO);
107
+ const isPinned = !!participant.pinnedAt;
108
+
109
+ const [trackedElement, setTrackedElement] = useState<HTMLDivElement | null>(
110
+ null,
111
+ );
112
+
113
+ const connectionQualityAsString =
114
+ !!connectionQuality &&
115
+ String(SfuModels.ConnectionQuality[connectionQuality]).toLowerCase();
116
+
117
+ useEffect(() => {
118
+ if (!trackedElement) return;
119
+
120
+ const unobserve = call.viewportTracker.observe(trackedElement, (entry) => {
121
+ call.state.updateParticipant(sessionId, (p) => ({
122
+ ...p,
123
+ viewportVisibilityState: entry.isIntersecting
124
+ ? VisibilityState.VISIBLE
125
+ : VisibilityState.INVISIBLE,
126
+ }));
127
+ });
128
+
129
+ return () => {
130
+ unobserve();
131
+ // reset visibility state to UNKNOWN upon cleanup
132
+ // so that the layouts that are not actively observed
133
+ // can still function normally (runtime layout switching)
134
+ call.state.updateParticipant(sessionId, (p) => ({
135
+ ...p,
136
+ viewportVisibilityState: VisibilityState.UNKNOWN,
137
+ }));
138
+ };
139
+ }, [trackedElement, call.viewportTracker, call.state, sessionId]);
140
+
141
+ const isDebugMode = useIsDebugMode();
142
+ return (
143
+ <div
144
+ className={clsx(
145
+ 'str-video__participant',
146
+ isSpeaking && 'str-video__participant--speaking',
147
+ !hasVideo && 'str-video__participant--no-video',
148
+ !hasAudio && 'str-video__participant--no-audio',
149
+ className,
150
+ )}
151
+ ref={setTrackedElement}
152
+ >
153
+ <MenuToggle
154
+ strategy="fixed"
155
+ placement={toggleMenuPosition === 'top' ? 'top-end' : 'bottom-end'}
156
+ ToggleButton={ToggleButton}
157
+ >
158
+ <ParticipantActionsContextMenu participant={participant} />
159
+ </MenuToggle>
160
+
161
+ <div className="str-video__video-container">
162
+ <Audio
163
+ // mute the local participant, as we don't want to hear ourselves
164
+ muted={participant.isLoggedInUser || muteAudio}
165
+ sinkId={sinkId}
166
+ audioStream={audioStream}
167
+ />
168
+ <Video
169
+ call={call}
170
+ participant={participant}
171
+ kind={videoKind}
172
+ setVideoElementRef={setVideoElementRef}
173
+ className={clsx('str-video__remote-video', {
174
+ 'str-video__remote-video--mirror':
175
+ isLocalParticipant && videoKind === 'video',
176
+ 'str-video__screen-share': videoKind === 'screen',
177
+ })}
178
+ // mute the local participant, as we don't want to hear ourselves
179
+ muted={participant.isLoggedInUser}
180
+ autoPlay
181
+ />
182
+ {reaction && (
183
+ <Reaction reaction={reaction} sessionId={sessionId} call={call} />
184
+ )}
185
+ <div className="str-video__participant_details">
186
+ <span className="str-video__participant_name">
187
+ {participant.name || participant.userId}
188
+ {indicatorsVisible && isDominantSpeaker && (
189
+ <span
190
+ className="str-video__participant_name--dominant_speaker"
191
+ title="Dominant speaker"
192
+ />
193
+ )}
194
+ {indicatorsVisible && (
195
+ <Notification
196
+ isVisible={
197
+ isLocalParticipant &&
198
+ connectionQuality === SfuModels.ConnectionQuality.POOR
199
+ }
200
+ message="Poor connection quality. Please check your internet connection."
201
+ >
202
+ {connectionQualityAsString && (
203
+ <span
204
+ className={clsx(
205
+ 'str-video__participant__connection-quality',
206
+ `str-video__participant__connection-quality--${connectionQualityAsString}`,
207
+ )}
208
+ title={connectionQualityAsString}
209
+ />
210
+ )}
211
+ </Notification>
212
+ )}
213
+ {indicatorsVisible && !hasAudio && (
214
+ <span className="str-video__participant_name--audio-muted"></span>
215
+ )}
216
+ {indicatorsVisible && !hasVideo && (
217
+ <span className="str-video__participant_name--video-muted"></span>
218
+ )}
219
+ {indicatorsVisible && isPinned && (
220
+ // TODO: remove this monstrosity once we have a proper design
221
+ <span
222
+ title="Unpin"
223
+ onClick={() =>
224
+ call.setParticipantPinnedAt(participant.sessionId)
225
+ }
226
+ style={{ cursor: 'pointer' }}
227
+ className="str-video__participant_name--pinned"
228
+ ></span>
229
+ )}
230
+ </span>
231
+ {isDebugMode && (
232
+ <>
233
+ <DebugParticipantPublishQuality
234
+ participant={participant}
235
+ call={call}
236
+ />
237
+ <DebugStatsView
238
+ call={call}
239
+ kind={isLocalParticipant ? 'publisher' : 'subscriber'}
240
+ mediaStream={videoStream}
241
+ />
242
+ </>
243
+ )}
244
+ </div>
245
+ </div>
246
+ </div>
247
+ );
248
+ };
@@ -0,0 +1 @@
1
+ export * from './ParticipantBox';
@@ -0,0 +1,68 @@
1
+ import {
2
+ DetailedHTMLProps,
3
+ ForwardedRef,
4
+ forwardRef,
5
+ useEffect,
6
+ useState,
7
+ VideoHTMLAttributes,
8
+ } from 'react';
9
+ import clsx from 'clsx';
10
+ import { Browsers } from '@stream-io/video-client';
11
+
12
+ export type VideoProps = DetailedHTMLProps<
13
+ VideoHTMLAttributes<HTMLVideoElement>,
14
+ HTMLVideoElement
15
+ > & {
16
+ stream?: MediaStream;
17
+ };
18
+
19
+ /**
20
+ * @description Extends video element with `stream` property
21
+ * (`srcObject`) to reactively handle stream changes
22
+ */
23
+ export const BaseVideo = forwardRef<HTMLVideoElement, VideoProps>(
24
+ ({ stream, ...rest }, ref) => {
25
+ const [videoElement, setVideoElement] = useState<HTMLVideoElement | null>(
26
+ null,
27
+ );
28
+ const setRef: ForwardedRef<HTMLVideoElement> = (instance) => {
29
+ setVideoElement(instance);
30
+ if (typeof ref === 'function') {
31
+ (ref as (instance: HTMLVideoElement | null) => void)(instance);
32
+ } else if (ref) {
33
+ ref.current = instance;
34
+ }
35
+ };
36
+
37
+ useEffect(() => {
38
+ if (!videoElement || !stream) return;
39
+ if (stream === videoElement.srcObject) return;
40
+
41
+ videoElement.srcObject = stream;
42
+ if (Browsers.isSafari() || Browsers.isFirefox()) {
43
+ // Firefox and Safari have some timing issue
44
+ setTimeout(() => {
45
+ videoElement.srcObject = stream;
46
+ videoElement.play().catch((e) => {
47
+ console.error(`Failed to play stream`, e);
48
+ });
49
+ }, 0);
50
+ }
51
+
52
+ return () => {
53
+ videoElement.pause();
54
+ videoElement.srcObject = null;
55
+ };
56
+ }, [stream, videoElement]);
57
+
58
+ return (
59
+ <video
60
+ autoPlay
61
+ playsInline
62
+ {...rest}
63
+ className={clsx('str-video__base-video', rest.className)}
64
+ ref={setRef}
65
+ />
66
+ );
67
+ },
68
+ );