@stream-io/video-react-sdk 1.43.2 → 2.0.0-beta.1

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 (328) hide show
  1. package/CHANGELOG.md +18 -19
  2. package/dist/css/embedded.css +2592 -1498
  3. package/dist/css/embedded.css.map +1 -1
  4. package/dist/css/styles.css +2388 -1222
  5. package/dist/css/styles.css.map +1 -1
  6. package/dist/embedded.cjs.js +535 -476
  7. package/dist/embedded.cjs.js.map +1 -1
  8. package/dist/esm/index.js +10 -7
  9. package/dist/esm/index.js.map +1 -1
  10. package/dist/esm/src/components/Avatar/Avatar.js +13 -5
  11. package/dist/esm/src/components/Avatar/Avatar.js.map +1 -1
  12. package/dist/esm/src/components/Badge/Badge.js +21 -0
  13. package/dist/esm/src/components/Badge/Badge.js.map +1 -0
  14. package/dist/esm/src/components/Button/Button.js +10 -0
  15. package/dist/esm/src/components/Button/Button.js.map +1 -0
  16. package/dist/esm/src/components/Button/CompositeButton.js +10 -17
  17. package/dist/esm/src/components/Button/CompositeButton.js.map +1 -1
  18. package/dist/esm/src/components/Button/IconButton.js +3 -9
  19. package/dist/esm/src/components/Button/IconButton.js.map +1 -1
  20. package/dist/esm/src/components/CallControls/AcceptCallButton.js +3 -2
  21. package/dist/esm/src/components/CallControls/AcceptCallButton.js.map +1 -1
  22. package/dist/esm/src/components/CallControls/CallControls.js +3 -0
  23. package/dist/esm/src/components/CallControls/CallControls.js.map +1 -1
  24. package/dist/esm/src/components/CallControls/CancelCallButton.js +11 -6
  25. package/dist/esm/src/components/CallControls/CancelCallButton.js.map +1 -1
  26. package/dist/esm/src/components/CallControls/ReactionsButton.js +7 -3
  27. package/dist/esm/src/components/CallControls/ReactionsButton.js.map +1 -1
  28. package/dist/esm/src/components/CallControls/RecordCallButton.js +17 -11
  29. package/dist/esm/src/components/CallControls/RecordCallButton.js.map +1 -1
  30. package/dist/esm/src/components/CallControls/ScreenShareButton.js +11 -4
  31. package/dist/esm/src/components/CallControls/ScreenShareButton.js.map +1 -1
  32. package/dist/esm/src/components/CallControls/ToggleAudioButton.js +28 -17
  33. package/dist/esm/src/components/CallControls/ToggleAudioButton.js.map +1 -1
  34. package/dist/esm/src/components/CallControls/ToggleAudioOutputButton.js +9 -4
  35. package/dist/esm/src/components/CallControls/ToggleAudioOutputButton.js.map +1 -1
  36. package/dist/esm/src/components/CallControls/ToggleVideoButton.js +32 -23
  37. package/dist/esm/src/components/CallControls/ToggleVideoButton.js.map +1 -1
  38. package/dist/esm/src/components/CallParticipantsList/BlockedUserListing.js +3 -3
  39. package/dist/esm/src/components/CallParticipantsList/BlockedUserListing.js.map +1 -1
  40. package/dist/esm/src/components/CallParticipantsList/CallParticipantListHeader.js +8 -3
  41. package/dist/esm/src/components/CallParticipantsList/CallParticipantListHeader.js.map +1 -1
  42. package/dist/esm/src/components/CallParticipantsList/CallParticipantListingItem.js +20 -7
  43. package/dist/esm/src/components/CallParticipantsList/CallParticipantListingItem.js.map +1 -1
  44. package/dist/esm/src/components/CallParticipantsList/CallParticipantsList.js +8 -5
  45. package/dist/esm/src/components/CallParticipantsList/CallParticipantsList.js.map +1 -1
  46. package/dist/esm/src/components/CallParticipantsList/EmptyParticipantSearchList.js +5 -2
  47. package/dist/esm/src/components/CallParticipantsList/EmptyParticipantSearchList.js.map +1 -1
  48. package/dist/esm/src/components/CallRecordingList/CallRecordingListHeader.js +7 -3
  49. package/dist/esm/src/components/CallRecordingList/CallRecordingListHeader.js.map +1 -1
  50. package/dist/esm/src/components/DeviceSettings/DeviceAudioPreviewItem.js +1 -1
  51. package/dist/esm/src/components/DeviceSettings/DeviceAudioPreviewItem.js.map +1 -1
  52. package/dist/esm/src/components/DeviceSettings/DeviceSelector.js +1 -1
  53. package/dist/esm/src/components/DeviceSettings/DeviceSelector.js.map +1 -1
  54. package/dist/esm/src/components/DeviceSettings/DeviceSelectorAudio.js +2 -2
  55. package/dist/esm/src/components/DeviceSettings/DeviceSelectorAudio.js.map +1 -1
  56. package/dist/esm/src/components/DeviceSettings/DeviceSettings.js +8 -5
  57. package/dist/esm/src/components/DeviceSettings/DeviceSettings.js.map +1 -1
  58. package/dist/esm/src/components/DeviceSettings/SpeakerTest.js +10 -4
  59. package/dist/esm/src/components/DeviceSettings/SpeakerTest.js.map +1 -1
  60. package/dist/esm/src/components/DropdownSelect/DropdownSelect.js +1 -1
  61. package/dist/esm/src/components/DropdownSelect/DropdownSelect.js.map +1 -1
  62. package/dist/esm/src/components/Menu/GenericMenu.js +2 -1
  63. package/dist/esm/src/components/Menu/GenericMenu.js.map +1 -1
  64. package/dist/esm/src/components/Menu/MenuToggle.js +3 -0
  65. package/dist/esm/src/components/Menu/MenuToggle.js.map +1 -1
  66. package/dist/esm/src/components/Notification/MicCaptureErrorNotification.js +6 -3
  67. package/dist/esm/src/components/Notification/MicCaptureErrorNotification.js.map +1 -1
  68. package/dist/esm/src/components/Notification/Notification.js +12 -3
  69. package/dist/esm/src/components/Notification/Notification.js.map +1 -1
  70. package/dist/esm/src/components/Notification/PermissionNotification.js +2 -2
  71. package/dist/esm/src/components/Notification/PermissionNotification.js.map +1 -1
  72. package/dist/esm/src/components/Notification/RecordingInProgressNotification.js +7 -3
  73. package/dist/esm/src/components/Notification/RecordingInProgressNotification.js.map +1 -1
  74. package/dist/esm/src/components/Notification/SpeakingWhileMutedNotification.js +7 -2
  75. package/dist/esm/src/components/Notification/SpeakingWhileMutedNotification.js.map +1 -1
  76. package/dist/esm/src/components/Permissions/PermissionRequests.js +13 -12
  77. package/dist/esm/src/components/Permissions/PermissionRequests.js.map +1 -1
  78. package/dist/esm/src/components/RingingCall/RingingCall.js +38 -14
  79. package/dist/esm/src/components/RingingCall/RingingCall.js.map +1 -1
  80. package/dist/esm/src/components/RingingCall/RingingCallControls.js +7 -3
  81. package/dist/esm/src/components/RingingCall/RingingCallControls.js.map +1 -1
  82. package/dist/esm/src/components/Search/SearchInput.js +1 -1
  83. package/dist/esm/src/components/Search/SearchInput.js.map +1 -1
  84. package/dist/esm/src/components/StreamTheme/StreamTheme.js +2 -2
  85. package/dist/esm/src/components/StreamTheme/StreamTheme.js.map +1 -1
  86. package/dist/esm/src/components/Tooltip/Tooltip.js +8 -8
  87. package/dist/esm/src/components/Tooltip/Tooltip.js.map +1 -1
  88. package/dist/esm/src/components/VideoPreview/VideoPreview.js +36 -5
  89. package/dist/esm/src/components/VideoPreview/VideoPreview.js.map +1 -1
  90. package/dist/esm/src/core/components/CallLayout/LivestreamLayout.js +38 -12
  91. package/dist/esm/src/core/components/CallLayout/LivestreamLayout.js.map +1 -1
  92. package/dist/esm/src/core/components/CallLayout/PaginatedGridLayout.js +9 -5
  93. package/dist/esm/src/core/components/CallLayout/PaginatedGridLayout.js.map +1 -1
  94. package/dist/esm/src/core/components/CallLayout/PipLayout/Grid.js +9 -6
  95. package/dist/esm/src/core/components/CallLayout/PipLayout/Grid.js.map +1 -1
  96. package/dist/esm/src/core/components/CallLayout/PipLayout/Pip.js +9 -6
  97. package/dist/esm/src/core/components/CallLayout/PipLayout/Pip.js.map +1 -1
  98. package/dist/esm/src/core/components/CallLayout/SpeakerLayout.js +11 -6
  99. package/dist/esm/src/core/components/CallLayout/SpeakerLayout.js.map +1 -1
  100. package/dist/esm/src/core/components/ParticipantView/ConnectionQualityIndicator.js +25 -0
  101. package/dist/esm/src/core/components/ParticipantView/ConnectionQualityIndicator.js.map +1 -0
  102. package/dist/esm/src/core/components/ParticipantView/DefaultParticipantViewUI.js +17 -13
  103. package/dist/esm/src/core/components/ParticipantView/DefaultParticipantViewUI.js.map +1 -1
  104. package/dist/esm/src/core/components/ParticipantView/ParticipantActionsContextMenu.js +13 -8
  105. package/dist/esm/src/core/components/ParticipantView/ParticipantActionsContextMenu.js.map +1 -1
  106. package/dist/esm/src/core/components/StreamVideo/StreamVideo.js +24 -3
  107. package/dist/esm/src/core/components/StreamVideo/StreamVideo.js.map +1 -1
  108. package/dist/esm/src/core/components/Video/BaseVideoPlaceholder.js +3 -13
  109. package/dist/esm/src/core/components/Video/BaseVideoPlaceholder.js.map +1 -1
  110. package/dist/esm/src/core/components/Video/DefaultPictureInPicturePlaceholder.js +4 -2
  111. package/dist/esm/src/core/components/Video/DefaultPictureInPicturePlaceholder.js.map +1 -1
  112. package/dist/esm/src/core/components/Video/DefaultVideoPlaceholder.js +4 -2
  113. package/dist/esm/src/core/components/Video/DefaultVideoPlaceholder.js.map +1 -1
  114. package/dist/esm/src/embedded/EmbeddedClientProvider.js +7 -4
  115. package/dist/esm/src/embedded/EmbeddedClientProvider.js.map +1 -1
  116. package/dist/esm/src/embedded/call/CallControls.js +10 -6
  117. package/dist/esm/src/embedded/call/CallControls.js.map +1 -1
  118. package/dist/esm/src/embedded/call/CallHeader.js +10 -7
  119. package/dist/esm/src/embedded/call/CallHeader.js.map +1 -1
  120. package/dist/esm/src/embedded/call/CallLayout.js +8 -5
  121. package/dist/esm/src/embedded/call/CallLayout.js.map +1 -1
  122. package/dist/esm/src/embedded/call/CallStateRouter.js +7 -4
  123. package/dist/esm/src/embedded/call/CallStateRouter.js.map +1 -1
  124. package/dist/esm/src/embedded/hooks/useLayout.js +7 -4
  125. package/dist/esm/src/embedded/hooks/useLayout.js.map +1 -1
  126. package/dist/esm/src/embedded/livestream/host/HostLayout.js +12 -7
  127. package/dist/esm/src/embedded/livestream/host/HostLayout.js.map +1 -1
  128. package/dist/esm/src/embedded/livestream/host/HostStateRouter.js +12 -7
  129. package/dist/esm/src/embedded/livestream/host/HostStateRouter.js.map +1 -1
  130. package/dist/esm/src/embedded/livestream/viewer/ViewerLayout.js +9 -6
  131. package/dist/esm/src/embedded/livestream/viewer/ViewerLayout.js.map +1 -1
  132. package/dist/esm/src/embedded/livestream/viewer/ViewerLobby.js +12 -9
  133. package/dist/esm/src/embedded/livestream/viewer/ViewerLobby.js.map +1 -1
  134. package/dist/esm/src/embedded/livestream/viewer/ViewerStateRouter.js +7 -4
  135. package/dist/esm/src/embedded/livestream/viewer/ViewerStateRouter.js.map +1 -1
  136. package/dist/esm/src/embedded/shared/BlurToggleButton/BlurToggleButton.js +13 -9
  137. package/dist/esm/src/embedded/shared/BlurToggleButton/BlurToggleButton.js.map +1 -1
  138. package/dist/esm/src/embedded/shared/CallDuration/CallDuration.js +40 -0
  139. package/dist/esm/src/embedded/shared/CallDuration/CallDuration.js.map +1 -0
  140. package/dist/esm/src/embedded/shared/CallFeedback/CallEndedScreen.js +8 -6
  141. package/dist/esm/src/embedded/shared/CallFeedback/CallEndedScreen.js.map +1 -1
  142. package/dist/esm/src/embedded/shared/CallFeedback/RatingScreen.js +26 -2
  143. package/dist/esm/src/embedded/shared/CallFeedback/RatingScreen.js.map +1 -1
  144. package/dist/esm/src/embedded/shared/CallFeedback/StarRating.js +12 -6
  145. package/dist/esm/src/embedded/shared/CallFeedback/StarRating.js.map +1 -1
  146. package/dist/esm/src/embedded/shared/CallFeedback/ThankYouScreen.js +8 -6
  147. package/dist/esm/src/embedded/shared/CallFeedback/ThankYouScreen.js.map +1 -1
  148. package/dist/esm/src/embedded/shared/ConnectionNotification/ConnectionNotification.js +15 -14
  149. package/dist/esm/src/embedded/shared/ConnectionNotification/ConnectionNotification.js.map +1 -1
  150. package/dist/esm/src/embedded/shared/EmbeddedParticipantViewUI/EmbeddedParticipantViewUI.js +4 -0
  151. package/dist/esm/src/embedded/shared/EmbeddedParticipantViewUI/EmbeddedParticipantViewUI.js.map +1 -1
  152. package/dist/esm/src/embedded/shared/JoinError/JoinError.js +8 -6
  153. package/dist/esm/src/embedded/shared/JoinError/JoinError.js.map +1 -1
  154. package/dist/esm/src/embedded/shared/Lobby/DeviceControls.js +11 -7
  155. package/dist/esm/src/embedded/shared/Lobby/DeviceControls.js.map +1 -1
  156. package/dist/esm/src/embedded/shared/Lobby/DisabledDeviceButton.js +6 -4
  157. package/dist/esm/src/embedded/shared/Lobby/DisabledDeviceButton.js.map +1 -1
  158. package/dist/esm/src/embedded/shared/Lobby/Lobby.js +10 -9
  159. package/dist/esm/src/embedded/shared/Lobby/Lobby.js.map +1 -1
  160. package/dist/esm/src/embedded/shared/Lobby/ToggleCameraButton.js +6 -4
  161. package/dist/esm/src/embedded/shared/Lobby/ToggleCameraButton.js.map +1 -1
  162. package/dist/esm/src/embedded/shared/Lobby/ToggleMicButton.js +8 -6
  163. package/dist/esm/src/embedded/shared/Lobby/ToggleMicButton.js.map +1 -1
  164. package/dist/esm/src/embedded/shared/Lobby/VideoPreviewFallbacks.js +11 -9
  165. package/dist/esm/src/embedded/shared/Lobby/VideoPreviewFallbacks.js.map +1 -1
  166. package/dist/esm/src/embedded/shared/ViewersCount/ViewersCount.js +6 -4
  167. package/dist/esm/src/embedded/shared/ViewersCount/ViewersCount.js.map +1 -1
  168. package/dist/esm/src/hooks/useDeviceList.js +4 -2
  169. package/dist/esm/src/hooks/useDeviceList.js.map +1 -1
  170. package/dist/esm/src/i18n/Streami18n.js +58 -0
  171. package/dist/esm/src/i18n/Streami18n.js.map +1 -0
  172. package/dist/esm/src/i18n/TranslationContext.js +42 -0
  173. package/dist/esm/src/i18n/TranslationContext.js.map +1 -0
  174. package/dist/esm/src/i18n/runtimeDefaults.js +20 -0
  175. package/dist/esm/src/i18n/runtimeDefaults.js.map +1 -0
  176. package/dist/esm/src/i18n/useStreami18n.js +49 -0
  177. package/dist/esm/src/i18n/useStreami18n.js.map +1 -0
  178. package/dist/esm/src/wrappers/LivestreamPlayer/LivestreamPlayer.js +4 -0
  179. package/dist/esm/src/wrappers/LivestreamPlayer/LivestreamPlayer.js.map +1 -1
  180. package/dist/index.cjs.js +559 -623
  181. package/dist/index.cjs.js.map +1 -1
  182. package/dist/index.d.ts +1 -1
  183. package/dist/src/components/Avatar/Avatar.d.ts +9 -4
  184. package/dist/src/components/Badge/Badge.d.ts +23 -0
  185. package/dist/src/components/Badge/index.d.ts +1 -0
  186. package/dist/src/components/Button/Button.d.ts +16 -0
  187. package/dist/src/components/Button/CompositeButton.d.ts +6 -3
  188. package/dist/src/components/Button/IconButton.d.ts +7 -7
  189. package/dist/src/components/Button/index.d.ts +2 -2
  190. package/dist/src/components/CallControls/CancelCallButton.d.ts +3 -1
  191. package/dist/src/components/CallControls/ToggleAudioButton.d.ts +3 -3
  192. package/dist/src/components/CallControls/ToggleAudioOutputButton.d.ts +2 -2
  193. package/dist/src/components/CallControls/ToggleVideoButton.d.ts +3 -3
  194. package/dist/src/components/CallControls/index.d.ts +0 -1
  195. package/dist/src/components/Menu/GenericMenu.d.ts +1 -0
  196. package/dist/src/components/Notification/Notification.d.ts +2 -1
  197. package/dist/src/components/StreamTheme/StreamTheme.d.ts +2 -1
  198. package/dist/src/components/VideoPreview/VideoPreview.d.ts +6 -1
  199. package/dist/src/components/index.d.ts +1 -1
  200. package/dist/src/core/components/ParticipantView/ConnectionQualityIndicator.d.ts +10 -0
  201. package/dist/src/core/components/ParticipantView/index.d.ts +1 -0
  202. package/dist/src/core/components/StreamVideo/StreamVideo.d.ts +18 -2
  203. package/dist/src/embedded/shared/CallDuration/CallDuration.d.ts +9 -0
  204. package/dist/src/embedded/shared/index.d.ts +1 -0
  205. package/dist/src/i18n/Streami18n.d.ts +56 -0
  206. package/dist/src/i18n/TranslationContext.d.ts +30 -0
  207. package/dist/src/i18n/index.d.ts +16 -0
  208. package/dist/src/i18n/keys.d.ts +164 -0
  209. package/dist/src/i18n/runtimeDefaults.d.ts +17 -0
  210. package/dist/src/i18n/types.d.ts +45 -0
  211. package/dist/src/i18n/useStreami18n.d.ts +19 -0
  212. package/index.ts +1 -1
  213. package/package.json +18 -13
  214. package/src/components/Avatar/Avatar.tsx +53 -19
  215. package/src/components/Badge/Badge.tsx +48 -0
  216. package/src/components/Badge/index.ts +1 -0
  217. package/src/components/Button/Button.tsx +49 -0
  218. package/src/components/Button/CompositeButton.tsx +82 -73
  219. package/src/components/Button/IconButton.tsx +19 -29
  220. package/src/components/Button/index.ts +2 -2
  221. package/src/components/CallControls/AcceptCallButton.tsx +3 -1
  222. package/src/components/CallControls/CancelCallButton.tsx +32 -24
  223. package/src/components/CallControls/ReactionsButton.tsx +7 -3
  224. package/src/components/CallControls/RecordCallButton.tsx +50 -23
  225. package/src/components/CallControls/ScreenShareButton.tsx +27 -6
  226. package/src/components/CallControls/ToggleAudioButton.tsx +62 -61
  227. package/src/components/CallControls/ToggleAudioOutputButton.tsx +7 -4
  228. package/src/components/CallControls/ToggleVideoButton.tsx +66 -66
  229. package/src/components/CallControls/index.ts +0 -1
  230. package/src/components/CallParticipantsList/BlockedUserListing.tsx +9 -2
  231. package/src/components/CallParticipantsList/CallParticipantListHeader.tsx +10 -3
  232. package/src/components/CallParticipantsList/CallParticipantListingItem.tsx +33 -8
  233. package/src/components/CallParticipantsList/CallParticipantsList.tsx +21 -5
  234. package/src/components/CallParticipantsList/EmptyParticipantSearchList.tsx +2 -2
  235. package/src/components/CallRecordingList/CallRecordingListHeader.tsx +11 -3
  236. package/src/components/DeviceSettings/DeviceAudioPreviewItem.tsx +3 -1
  237. package/src/components/DeviceSettings/DeviceSelector.tsx +1 -1
  238. package/src/components/DeviceSettings/DeviceSelectorAudio.tsx +2 -7
  239. package/src/components/DeviceSettings/DeviceSettings.tsx +14 -5
  240. package/src/components/DeviceSettings/SpeakerTest.tsx +7 -2
  241. package/src/components/DropdownSelect/DropdownSelect.tsx +3 -1
  242. package/src/components/Menu/GenericMenu.tsx +4 -0
  243. package/src/components/Notification/MicCaptureErrorNotification.tsx +7 -2
  244. package/src/components/Notification/Notification.tsx +20 -4
  245. package/src/components/Notification/PermissionNotification.tsx +2 -0
  246. package/src/components/Notification/RecordingInProgressNotification.tsx +5 -6
  247. package/src/components/Notification/SpeakingWhileMutedNotification.tsx +8 -2
  248. package/src/components/Permissions/PermissionRequests.tsx +50 -43
  249. package/src/components/RingingCall/RingingCall.tsx +40 -14
  250. package/src/components/RingingCall/RingingCallControls.tsx +2 -1
  251. package/src/components/Search/SearchInput.tsx +2 -3
  252. package/src/components/StreamTheme/StreamTheme.tsx +3 -1
  253. package/src/components/Tooltip/Tooltip.tsx +3 -10
  254. package/src/components/VideoPreview/VideoPreview.tsx +50 -5
  255. package/src/components/index.ts +1 -1
  256. package/src/core/components/CallLayout/LivestreamLayout.tsx +48 -18
  257. package/src/core/components/CallLayout/PaginatedGridLayout.tsx +14 -0
  258. package/src/core/components/CallLayout/PipLayout/Grid.tsx +10 -2
  259. package/src/core/components/CallLayout/PipLayout/Pip.tsx +6 -2
  260. package/src/core/components/CallLayout/SpeakerLayout.tsx +27 -0
  261. package/src/core/components/CallLayout/partcipantFilter.test.ts +38 -31
  262. package/src/core/components/ParticipantView/ConnectionQualityIndicator.tsx +54 -0
  263. package/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +60 -27
  264. package/src/core/components/ParticipantView/ParticipantActionsContextMenu.tsx +63 -22
  265. package/src/core/components/ParticipantView/index.ts +1 -0
  266. package/src/core/components/StreamVideo/StreamVideo.tsx +39 -4
  267. package/src/core/components/Video/BaseVideoPlaceholder.tsx +13 -30
  268. package/src/core/components/Video/DefaultPictureInPicturePlaceholder.tsx +5 -2
  269. package/src/core/components/Video/DefaultVideoPlaceholder.tsx +2 -2
  270. package/src/embedded/call/CallControls.tsx +9 -18
  271. package/src/embedded/call/CallHeader.tsx +3 -12
  272. package/src/embedded/call/CallLayout.tsx +1 -1
  273. package/src/embedded/livestream/host/HostLayout.tsx +26 -20
  274. package/src/embedded/livestream/host/HostStateRouter.tsx +12 -8
  275. package/src/embedded/livestream/viewer/ViewerLayout.tsx +8 -11
  276. package/src/embedded/livestream/viewer/ViewerLobby.tsx +31 -15
  277. package/src/embedded/shared/BlurToggleButton/BlurToggleButton.tsx +18 -12
  278. package/src/embedded/shared/CallDuration/CallDuration.tsx +32 -0
  279. package/src/embedded/shared/CallFeedback/CallEndedScreen.tsx +27 -13
  280. package/src/embedded/shared/CallFeedback/RatingScreen.tsx +20 -12
  281. package/src/embedded/shared/CallFeedback/StarRating.tsx +10 -3
  282. package/src/embedded/shared/CallFeedback/ThankYouScreen.tsx +6 -3
  283. package/src/embedded/shared/ConnectionNotification/ConnectionNotification.tsx +21 -14
  284. package/src/embedded/shared/JoinError/JoinError.tsx +7 -6
  285. package/src/embedded/shared/Lobby/DeviceControls.tsx +25 -3
  286. package/src/embedded/shared/Lobby/Lobby.tsx +19 -22
  287. package/src/embedded/shared/Lobby/ToggleMicButton.tsx +10 -3
  288. package/src/embedded/shared/Lobby/VideoPreviewFallbacks.tsx +4 -2
  289. package/src/embedded/shared/index.ts +1 -0
  290. package/src/hooks/useDeviceList.tsx +2 -2
  291. package/src/i18n/Streami18n.ts +67 -0
  292. package/src/i18n/TranslationContext.tsx +55 -0
  293. package/src/i18n/index.ts +22 -0
  294. package/src/i18n/keys.ts +169 -0
  295. package/src/i18n/runtimeDefaults.ts +17 -0
  296. package/src/i18n/types.ts +78 -0
  297. package/src/i18n/useStreami18n.ts +66 -0
  298. package/src/utilities/filter.test.ts +132 -124
  299. package/src/utilities/normalizeString.test.ts +50 -48
  300. package/dist/embedded-CallStatsLatencyChart-CpL1M_s0.cjs.js +0 -59
  301. package/dist/embedded-CallStatsLatencyChart-CpL1M_s0.cjs.js.map +0 -1
  302. package/dist/esm/src/components/Button/TextButton.js +0 -8
  303. package/dist/esm/src/components/Button/TextButton.js.map +0 -1
  304. package/dist/esm/src/components/CallControls/CallStatsButton.js +0 -18
  305. package/dist/esm/src/components/CallControls/CallStatsButton.js.map +0 -1
  306. package/dist/esm/src/components/CallStats/CallStats.js +0 -180
  307. package/dist/esm/src/components/CallStats/CallStats.js.map +0 -1
  308. package/dist/esm/src/components/CallStats/CallStatsLatencyChart.js +0 -57
  309. package/dist/esm/src/components/CallStats/CallStatsLatencyChart.js.map +0 -1
  310. package/dist/esm/src/translations/en.json.js +0 -177
  311. package/dist/esm/src/translations/en.json.js.map +0 -1
  312. package/dist/esm/src/translations/index.js +0 -6
  313. package/dist/esm/src/translations/index.js.map +0 -1
  314. package/dist/latency-chart-CpL1M_s0.cjs.js +0 -59
  315. package/dist/latency-chart-CpL1M_s0.cjs.js.map +0 -1
  316. package/dist/src/components/Button/TextButton.d.ts +0 -2
  317. package/dist/src/components/CallControls/CallStatsButton.d.ts +0 -4
  318. package/dist/src/components/CallStats/CallStats.d.ts +0 -22
  319. package/dist/src/components/CallStats/CallStatsLatencyChart.d.ts +0 -7
  320. package/dist/src/components/CallStats/index.d.ts +0 -1
  321. package/dist/src/translations/index.d.ts +0 -146
  322. package/src/components/Button/TextButton.tsx +0 -12
  323. package/src/components/CallControls/CallStatsButton.tsx +0 -37
  324. package/src/components/CallStats/CallStats.tsx +0 -439
  325. package/src/components/CallStats/CallStatsLatencyChart.tsx +0 -76
  326. package/src/components/CallStats/index.ts +0 -1
  327. package/src/translations/en.json +0 -154
  328. package/src/translations/index.ts +0 -3
@@ -1,11 +1,16 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { useI18n, useCall } from '@stream-io/video-react-bindings';
2
+ import { useCall } from '@stream-io/video-react-bindings';
3
+ import '@stream-io/i18n';
4
+ import { useI18n } from '../../../../i18n/TranslationContext.js';
3
5
  import { useState, useEffect, useMemo } from 'react';
6
+ import '@stream-io/i18n/react';
4
7
  import clsx from 'clsx';
5
8
  import { hasScreenShare } from '@stream-io/video-client';
6
9
  import '../../../../components/BackgroundFilters/BackgroundFiltersProvider.js';
7
- import '../../../../components/Button/CompositeButton.js';
10
+ import '../../../../components/Badge/Badge.js';
11
+ import '../../../../components/Button/Button.js';
8
12
  import { IconButton } from '../../../../components/Button/IconButton.js';
13
+ import '../../../../components/Button/CompositeButton.js';
9
14
  import '@floating-ui/react';
10
15
  import '../../../../components/CallControls/RecordCallButton.js';
11
16
  import '../../../../components/CallControls/ReactionsButton.js';
@@ -14,12 +19,9 @@ import '../../../../components/DeviceSettings/DeviceSettings.js';
14
19
  import '../../../../components/DropdownSelect/DropdownSelect.js';
15
20
  import '../../../../components/Menu/MenuToggle.js';
16
21
  import '../../../../components/CallControls/CancelCallButton.js';
17
- import '../../../../components/CallControls/CallStatsButton.js';
18
22
  import '../../../../components/CallParticipantsList/CallParticipantsList.js';
19
23
  import '../../../../components/CallParticipantsList/CallParticipantListingItem.js';
20
- import '../../../../components/CallStats/CallStats.js';
21
24
  import '../../../../components/NoiseCancellation/NoiseCancellationProvider.js';
22
- import '../../../../components/RingingCall/RingingCall.js';
23
25
  import '../../../../components/Permissions/PermissionRequests.js';
24
26
  import '../../Video/Video.js';
25
27
  import '../../Video/BaseVideo.js';
@@ -27,6 +29,7 @@ import '../../Video/DefaultVideoPlaceholder.js';
27
29
  import '../../ParticipantView/ParticipantViewContext.js';
28
30
  import { ParticipantView } from '../../ParticipantView/ParticipantView.js';
29
31
  import { DefaultParticipantViewUI } from '../../ParticipantView/DefaultParticipantViewUI.js';
32
+ import '../../ParticipantView/ConnectionQualityIndicator.js';
30
33
  import { useFilteredParticipants, usePaginatedLayoutSortPreset } from '../hooks.js';
31
34
  import { chunk } from '../../../../utilities/chunk.js';
32
35
 
@@ -72,7 +75,7 @@ const Grid = (props) => {
72
75
  if (!call)
73
76
  return null;
74
77
  return (jsxs("div", { className: "str-video__pip-layout str-video__pip-layout--grid", ref: setWrapperElement, children: [screenSharingParticipant &&
75
- (screenSharingParticipant.isLocalParticipant ? (jsxs("div", { className: "str-video__pip-screen-share-local", children: [jsx(Icon, { icon: "screen-share-off" }), jsx("span", { className: "str-video__pip-screen-share-local__title", children: t('You are presenting your screen') })] })) : (jsx(ParticipantView, { participant: screenSharingParticipant, trackType: "screenShareTrack", muteAudio: true, mirror: false, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }))), jsxs("div", { className: "str-video__pip-layout__grid-container", children: [pageArrowsVisible && page > 0 && (jsx(IconButton, { icon: "caret-left", onClick: () => setPage((currentPage) => Math.max(0, currentPage - 1)), className: "str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--left" })), selectedGroup && (jsx("div", { className: clsx('str-video__pip-layout__grid', `str-video__pip-layout__grid--${getGridDensity(selectedGroup.length)}`), children: selectedGroup.map((participant) => (jsx(ParticipantView, { participant: participant, muteAudio: true, mirror: mirror, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }, participant.sessionId))) })), pageArrowsVisible && page < pageCount - 1 && (jsx(IconButton, { icon: "caret-right", onClick: () => setPage((currentPage) => Math.min(pageCount - 1, currentPage + 1)), className: "str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--right" }))] })] }));
78
+ (screenSharingParticipant.isLocalParticipant ? (jsxs("div", { className: "str-video__pip-screen-share-local", children: [jsx(Icon, { icon: "screen-share-off" }), jsx("span", { className: "str-video__pip-screen-share-local__title", children: t('common.presentingYourScreen.text', 'You are presenting your screen') })] })) : (jsx(ParticipantView, { participant: screenSharingParticipant, trackType: "screenShareTrack", muteAudio: true, mirror: false, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }))), jsxs("div", { className: "str-video__pip-layout__grid-container", children: [pageArrowsVisible && page > 0 && (jsx(IconButton, { icon: "caret-left", size: "sm", variant: "secondary", onClick: () => setPage((currentPage) => Math.max(0, currentPage - 1)), className: "str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--left" })), selectedGroup && (jsx("div", { className: clsx('str-video__pip-layout__grid', `str-video__pip-layout__grid--${getGridDensity(selectedGroup.length)}`), children: selectedGroup.map((participant) => (jsx(ParticipantView, { participant: participant, muteAudio: true, mirror: mirror, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }, participant.sessionId))) })), pageArrowsVisible && page < pageCount - 1 && (jsx(IconButton, { icon: "caret-right", size: "sm", variant: "secondary", onClick: () => setPage((currentPage) => Math.min(pageCount - 1, currentPage + 1)), className: "str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--right" }))] })] }));
76
79
  };
77
80
  Grid.displayName = 'PipLayout.Grid';
78
81
 
@@ -1 +1 @@
1
- {"version":3,"file":"Grid.js","sources":["../../../../../../../../../src/core/components/CallLayout/PipLayout/Grid.tsx"],"sourcesContent":["import { useCall, useI18n } from '@stream-io/video-react-bindings';\nimport { useEffect, useMemo, useState } from 'react';\nimport clsx from 'clsx';\nimport { hasScreenShare } from '@stream-io/video-client';\nimport { Icon, IconButton } from '../../../../components';\nimport {\n DefaultParticipantViewUI,\n ParticipantView,\n} from '../../ParticipantView';\nimport {\n useFilteredParticipants,\n usePaginatedLayoutSortPreset,\n} from '../hooks';\nimport { chunk } from '../../../../utilities';\nimport { PipLayoutProps } from './Pip';\n\ntype GridDensity = 'single' | 'small' | 'medium' | 'large' | 'overflow';\n\nexport type PipLayoutGridProps = PipLayoutProps & {\n /**\n * The number of participants to display per page.\n * @default 9\n */\n groupSize?: number;\n\n /**\n * Whether to show pagination arrows when there are multiple pages.\n * @default true\n */\n pageArrowsVisible?: boolean;\n};\n\nconst getGridDensity = (count: number): GridDensity => {\n if (count === 1) return 'single';\n if (count <= 5) return 'small';\n if (count <= 9) return 'medium';\n if (count <= 16) return 'large';\n return 'overflow';\n};\n\n/**\n * A grid-based PIP layout with pagination support.\n * Use this when you need a more structured grid view in PIP mode.\n */\nexport const Grid = (props: PipLayoutGridProps) => {\n const { t } = useI18n();\n const {\n excludeLocalParticipant = false,\n filterParticipants,\n mirrorLocalParticipantVideo = true,\n groupSize = 9,\n pageArrowsVisible = true,\n VideoPlaceholder,\n ParticipantViewUI = DefaultParticipantViewUI,\n } = props;\n\n const [page, setPage] = useState(0);\n const [wrapperElement, setWrapperElement] = useState<HTMLDivElement | null>(\n null,\n );\n\n const call = useCall();\n const participants = useFilteredParticipants({\n excludeLocalParticipant,\n filterParticipants,\n });\n const screenSharingParticipant = participants.find((p) => hasScreenShare(p));\n\n usePaginatedLayoutSortPreset(call);\n\n useEffect(() => {\n if (!wrapperElement || !call) return;\n return call.setViewport(wrapperElement);\n }, [wrapperElement, call]);\n\n const participantGroups = useMemo(\n () => chunk(participants, groupSize),\n [participants, groupSize],\n );\n\n const pageCount = participantGroups.length;\n\n if (page > pageCount - 1) {\n setPage(Math.max(0, pageCount - 1));\n }\n\n const selectedGroup = participantGroups[page];\n const mirror = mirrorLocalParticipantVideo ? undefined : false;\n\n if (!call) return null;\n\n return (\n <div\n className=\"str-video__pip-layout str-video__pip-layout--grid\"\n ref={setWrapperElement}\n >\n {screenSharingParticipant &&\n (screenSharingParticipant.isLocalParticipant ? (\n <div className=\"str-video__pip-screen-share-local\">\n <Icon icon=\"screen-share-off\" />\n <span className=\"str-video__pip-screen-share-local__title\">\n {t('You are presenting your screen')}\n </span>\n </div>\n ) : (\n <ParticipantView\n participant={screenSharingParticipant}\n trackType=\"screenShareTrack\"\n muteAudio\n mirror={false}\n VideoPlaceholder={VideoPlaceholder}\n ParticipantViewUI={ParticipantViewUI}\n />\n ))}\n <div className=\"str-video__pip-layout__grid-container\">\n {pageArrowsVisible && page > 0 && (\n <IconButton\n icon=\"caret-left\"\n onClick={() =>\n setPage((currentPage) => Math.max(0, currentPage - 1))\n }\n className=\"str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--left\"\n />\n )}\n {selectedGroup && (\n <div\n className={clsx(\n 'str-video__pip-layout__grid',\n `str-video__pip-layout__grid--${getGridDensity(selectedGroup.length)}`,\n )}\n >\n {selectedGroup.map((participant) => (\n <ParticipantView\n key={participant.sessionId}\n participant={participant}\n muteAudio\n mirror={mirror}\n VideoPlaceholder={VideoPlaceholder}\n ParticipantViewUI={ParticipantViewUI}\n />\n ))}\n </div>\n )}\n {pageArrowsVisible && page < pageCount - 1 && (\n <IconButton\n icon=\"caret-right\"\n onClick={() =>\n setPage((currentPage) => Math.min(pageCount - 1, currentPage + 1))\n }\n className=\"str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--right\"\n />\n )}\n </div>\n </div>\n );\n};\n\nGrid.displayName = 'PipLayout.Grid';\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"Grid.js","sources":["../../../../../../../../../src/core/components/CallLayout/PipLayout/Grid.tsx"],"sourcesContent":["import { useCall } from '@stream-io/video-react-bindings';\nimport { useI18n } from '../../../../i18n';\nimport { useEffect, useMemo, useState } from 'react';\nimport clsx from 'clsx';\nimport { hasScreenShare } from '@stream-io/video-client';\nimport { Icon, IconButton } from '../../../../components';\nimport {\n DefaultParticipantViewUI,\n ParticipantView,\n} from '../../ParticipantView';\nimport {\n useFilteredParticipants,\n usePaginatedLayoutSortPreset,\n} from '../hooks';\nimport { chunk } from '../../../../utilities';\nimport { PipLayoutProps } from './Pip';\n\ntype GridDensity = 'single' | 'small' | 'medium' | 'large' | 'overflow';\n\nexport type PipLayoutGridProps = PipLayoutProps & {\n /**\n * The number of participants to display per page.\n * @default 9\n */\n groupSize?: number;\n\n /**\n * Whether to show pagination arrows when there are multiple pages.\n * @default true\n */\n pageArrowsVisible?: boolean;\n};\n\nconst getGridDensity = (count: number): GridDensity => {\n if (count === 1) return 'single';\n if (count <= 5) return 'small';\n if (count <= 9) return 'medium';\n if (count <= 16) return 'large';\n return 'overflow';\n};\n\n/**\n * A grid-based PIP layout with pagination support.\n * Use this when you need a more structured grid view in PIP mode.\n */\nexport const Grid = (props: PipLayoutGridProps) => {\n const { t } = useI18n();\n const {\n excludeLocalParticipant = false,\n filterParticipants,\n mirrorLocalParticipantVideo = true,\n groupSize = 9,\n pageArrowsVisible = true,\n VideoPlaceholder,\n ParticipantViewUI = DefaultParticipantViewUI,\n } = props;\n\n const [page, setPage] = useState(0);\n const [wrapperElement, setWrapperElement] = useState<HTMLDivElement | null>(\n null,\n );\n\n const call = useCall();\n const participants = useFilteredParticipants({\n excludeLocalParticipant,\n filterParticipants,\n });\n const screenSharingParticipant = participants.find((p) => hasScreenShare(p));\n\n usePaginatedLayoutSortPreset(call);\n\n useEffect(() => {\n if (!wrapperElement || !call) return;\n return call.setViewport(wrapperElement);\n }, [wrapperElement, call]);\n\n const participantGroups = useMemo(\n () => chunk(participants, groupSize),\n [participants, groupSize],\n );\n\n const pageCount = participantGroups.length;\n\n if (page > pageCount - 1) {\n setPage(Math.max(0, pageCount - 1));\n }\n\n const selectedGroup = participantGroups[page];\n const mirror = mirrorLocalParticipantVideo ? undefined : false;\n\n if (!call) return null;\n\n return (\n <div\n className=\"str-video__pip-layout str-video__pip-layout--grid\"\n ref={setWrapperElement}\n >\n {screenSharingParticipant &&\n (screenSharingParticipant.isLocalParticipant ? (\n <div className=\"str-video__pip-screen-share-local\">\n <Icon icon=\"screen-share-off\" />\n <span className=\"str-video__pip-screen-share-local__title\">\n {t(\n 'common.presentingYourScreen.text',\n 'You are presenting your screen',\n )}\n </span>\n </div>\n ) : (\n <ParticipantView\n participant={screenSharingParticipant}\n trackType=\"screenShareTrack\"\n muteAudio\n mirror={false}\n VideoPlaceholder={VideoPlaceholder}\n ParticipantViewUI={ParticipantViewUI}\n />\n ))}\n <div className=\"str-video__pip-layout__grid-container\">\n {pageArrowsVisible && page > 0 && (\n <IconButton\n icon=\"caret-left\"\n size=\"sm\"\n variant=\"secondary\"\n onClick={() =>\n setPage((currentPage) => Math.max(0, currentPage - 1))\n }\n className=\"str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--left\"\n />\n )}\n {selectedGroup && (\n <div\n className={clsx(\n 'str-video__pip-layout__grid',\n `str-video__pip-layout__grid--${getGridDensity(selectedGroup.length)}`,\n )}\n >\n {selectedGroup.map((participant) => (\n <ParticipantView\n key={participant.sessionId}\n participant={participant}\n muteAudio\n mirror={mirror}\n VideoPlaceholder={VideoPlaceholder}\n ParticipantViewUI={ParticipantViewUI}\n />\n ))}\n </div>\n )}\n {pageArrowsVisible && page < pageCount - 1 && (\n <IconButton\n icon=\"caret-right\"\n size=\"sm\"\n variant=\"secondary\"\n onClick={() =>\n setPage((currentPage) => Math.min(pageCount - 1, currentPage + 1))\n }\n className=\"str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--right\"\n />\n )}\n </div>\n </div>\n );\n};\n\nGrid.displayName = 'PipLayout.Grid';\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -1,11 +1,16 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { useI18n, useCall } from '@stream-io/video-react-bindings';
2
+ import { useCall } from '@stream-io/video-react-bindings';
3
+ import '@stream-io/i18n';
4
+ import { useI18n } from '../../../../i18n/TranslationContext.js';
3
5
  import { useState, useEffect } from 'react';
6
+ import '@stream-io/i18n/react';
4
7
  import { hasScreenShare } from '@stream-io/video-client';
5
8
  import 'clsx';
6
9
  import '../../../../components/BackgroundFilters/BackgroundFiltersProvider.js';
7
- import '../../../../components/Button/CompositeButton.js';
10
+ import '../../../../components/Badge/Badge.js';
11
+ import '../../../../components/Button/Button.js';
8
12
  import '../../../../components/Button/IconButton.js';
13
+ import '../../../../components/Button/CompositeButton.js';
9
14
  import '@floating-ui/react';
10
15
  import '../../../../components/CallControls/RecordCallButton.js';
11
16
  import '../../../../components/CallControls/ReactionsButton.js';
@@ -14,12 +19,9 @@ import '../../../../components/DeviceSettings/DeviceSettings.js';
14
19
  import '../../../../components/DropdownSelect/DropdownSelect.js';
15
20
  import '../../../../components/Menu/MenuToggle.js';
16
21
  import '../../../../components/CallControls/CancelCallButton.js';
17
- import '../../../../components/CallControls/CallStatsButton.js';
18
22
  import '../../../../components/CallParticipantsList/CallParticipantsList.js';
19
23
  import '../../../../components/CallParticipantsList/CallParticipantListingItem.js';
20
- import '../../../../components/CallStats/CallStats.js';
21
24
  import '../../../../components/NoiseCancellation/NoiseCancellationProvider.js';
22
- import '../../../../components/RingingCall/RingingCall.js';
23
25
  import '../../../../components/Permissions/PermissionRequests.js';
24
26
  import '../../Video/Video.js';
25
27
  import '../../Video/BaseVideo.js';
@@ -27,6 +29,7 @@ import '../../Video/DefaultVideoPlaceholder.js';
27
29
  import '../../ParticipantView/ParticipantViewContext.js';
28
30
  import { ParticipantView } from '../../ParticipantView/ParticipantView.js';
29
31
  import { DefaultParticipantViewUI } from '../../ParticipantView/DefaultParticipantViewUI.js';
32
+ import '../../ParticipantView/ConnectionQualityIndicator.js';
30
33
  import { useFilteredParticipants, usePaginatedLayoutSortPreset } from '../hooks.js';
31
34
 
32
35
  const Pip = (props) => {
@@ -49,7 +52,7 @@ const Pip = (props) => {
49
52
  if (!call)
50
53
  return null;
51
54
  return (jsxs("div", { className: "str-video__pip-layout", ref: setLayoutWrapperElement, children: [screenSharingParticipant &&
52
- (screenSharingParticipant.isLocalParticipant ? (jsxs("div", { className: "str-video__pip-screen-share-local", children: [jsx(Icon, { icon: "screen-share-off" }), jsx("span", { className: "str-video__pip-screen-share-local__title", children: t('You are presenting your screen') })] })) : (jsx(ParticipantView, { participant: screenSharingParticipant, trackType: "screenShareTrack", muteAudio: true, mirror: false, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }))), participants.map((participant) => (jsx(ParticipantView, { participant: participant, muteAudio: true, mirror: mirror, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }, participant.sessionId)))] }));
55
+ (screenSharingParticipant.isLocalParticipant ? (jsxs("div", { className: "str-video__pip-screen-share-local", children: [jsx(Icon, { icon: "screen-share-off" }), jsx("span", { className: "str-video__pip-screen-share-local__title", children: t('common.presentingYourScreen.text', 'You are presenting your screen') })] })) : (jsx(ParticipantView, { participant: screenSharingParticipant, trackType: "screenShareTrack", muteAudio: true, mirror: false, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }))), participants.map((participant) => (jsx(ParticipantView, { participant: participant, muteAudio: true, mirror: mirror, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }, participant.sessionId)))] }));
53
56
  };
54
57
  Pip.displayName = 'PipLayout.Pip';
55
58
 
@@ -1 +1 @@
1
- {"version":3,"file":"Pip.js","sources":["../../../../../../../../../src/core/components/CallLayout/PipLayout/Pip.tsx"],"sourcesContent":["import { useCall, useI18n } from '@stream-io/video-react-bindings';\nimport { useEffect, useState } from 'react';\n\nimport { hasScreenShare } from '@stream-io/video-client';\nimport { Icon } from '../../../../components';\nimport {\n DefaultParticipantViewUI,\n ParticipantView,\n ParticipantViewProps,\n} from '../../ParticipantView';\nimport {\n ParticipantFilter,\n ParticipantPredicate,\n useFilteredParticipants,\n usePaginatedLayoutSortPreset,\n} from '../hooks';\n\nexport type PipLayoutProps = {\n /**\n * Whether to exclude the local participant from the grid.\n * @default false\n */\n excludeLocalParticipant?: boolean;\n\n /**\n * Predicate to filter call participants or a filter object.\n * @example\n * // With a predicate:\n * <PipLayout\n * filterParticipants={p => p.roles.includes('student')}\n * />\n * @example\n * // With a filter object:\n * <PipLayout\n * filterParticipants={{\n * $or: [\n * { roles: { $contains: 'student' } },\n * { isPinned: true },\n * ],\n * }}\n * />\n */\n filterParticipants?: ParticipantPredicate | ParticipantFilter;\n\n /**\n * When set to `false` disables mirroring of the local partipant's video.\n * @default true\n */\n mirrorLocalParticipantVideo?: boolean;\n} & Pick<ParticipantViewProps, 'ParticipantViewUI' | 'VideoPlaceholder'>;\n\nexport const Pip = (props: PipLayoutProps) => {\n const { t } = useI18n();\n const {\n excludeLocalParticipant = false,\n filterParticipants,\n mirrorLocalParticipantVideo = true,\n VideoPlaceholder,\n ParticipantViewUI = DefaultParticipantViewUI,\n } = props;\n const [layoutWrapperElement, setLayoutWrapperElement] =\n useState<HTMLDivElement | null>(null);\n\n const call = useCall();\n const participants = useFilteredParticipants({\n excludeLocalParticipant,\n filterParticipants,\n });\n const screenSharingParticipant = participants.find((p) => hasScreenShare(p));\n\n usePaginatedLayoutSortPreset(call);\n\n useEffect(() => {\n if (!layoutWrapperElement || !call) return;\n return call.setViewport(layoutWrapperElement);\n }, [layoutWrapperElement, call]);\n\n const mirror = mirrorLocalParticipantVideo ? undefined : false;\n\n if (!call) return null;\n\n return (\n <div className=\"str-video__pip-layout\" ref={setLayoutWrapperElement}>\n {screenSharingParticipant &&\n (screenSharingParticipant.isLocalParticipant ? (\n <div className=\"str-video__pip-screen-share-local\">\n <Icon icon=\"screen-share-off\" />\n <span className=\"str-video__pip-screen-share-local__title\">\n {t('You are presenting your screen')}\n </span>\n </div>\n ) : (\n <ParticipantView\n participant={screenSharingParticipant}\n trackType=\"screenShareTrack\"\n muteAudio\n mirror={false}\n VideoPlaceholder={VideoPlaceholder}\n ParticipantViewUI={ParticipantViewUI}\n />\n ))}\n {participants.map((participant) => (\n <ParticipantView\n key={participant.sessionId}\n participant={participant}\n muteAudio\n mirror={mirror}\n VideoPlaceholder={VideoPlaceholder}\n ParticipantViewUI={ParticipantViewUI}\n />\n ))}\n </div>\n );\n};\n\nPip.displayName = 'PipLayout.Pip';\n"],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDO,MAAM,GAAG,GAAG,CAAC,KAAqB,KAAI;AAC3C,IAAA,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE;AACvB,IAAA,MAAM,EACJ,uBAAuB,GAAG,KAAK,EAC/B,kBAAkB,EAClB,2BAA2B,GAAG,IAAI,EAClC,gBAAgB,EAChB,iBAAiB,GAAG,wBAAwB,GAC7C,GAAG,KAAK;IACT,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GACnD,QAAQ,CAAwB,IAAI,CAAC;AAEvC,IAAA,MAAM,IAAI,GAAG,OAAO,EAAE;IACtB,MAAM,YAAY,GAAG,uBAAuB,CAAC;QAC3C,uBAAuB;QACvB,kBAAkB;AACnB,KAAA,CAAC;AACF,IAAA,MAAM,wBAAwB,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC;IAE5E,4BAA4B,CAAC,IAAI,CAAC;IAElC,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,oBAAoB,IAAI,CAAC,IAAI;YAAE;AACpC,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC;AAC/C,IAAA,CAAC,EAAE,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,2BAA2B,GAAG,SAAS,GAAG,KAAK;AAE9D,IAAA,IAAI,CAAC,IAAI;AAAE,QAAA,OAAO,IAAI;IAEtB,QACEA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,uBAAuB,EAAC,GAAG,EAAE,uBAAuB,EAAA,QAAA,EAAA,CAChE,wBAAwB;iBACtB,wBAAwB,CAAC,kBAAkB,IAC1CA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,mCAAmC,aAChDC,GAAA,CAAC,IAAI,IAAC,IAAI,EAAC,kBAAkB,EAAA,CAAG,EAChCA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,0CAA0C,YACvD,CAAC,CAAC,gCAAgC,CAAC,EAAA,CAC/B,IACH,KAENA,GAAA,CAAC,eAAe,EAAA,EACd,WAAW,EAAE,wBAAwB,EACrC,SAAS,EAAC,kBAAkB,EAC5B,SAAS,EAAA,IAAA,EACT,MAAM,EAAE,KAAK,EACb,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,EAAE,iBAAiB,EAAA,CACpC,CACH,CAAC,EACH,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,MAC5BA,GAAA,CAAC,eAAe,EAAA,EAEd,WAAW,EAAE,WAAW,EACxB,SAAS,EAAA,IAAA,EACT,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,EAAE,iBAAiB,EAAA,EAL/B,WAAW,CAAC,SAAS,CAM1B,CACH,CAAC,CAAA,EAAA,CACE;AAEV;AAEA,GAAG,CAAC,WAAW,GAAG,eAAe;;;;"}
1
+ {"version":3,"file":"Pip.js","sources":["../../../../../../../../../src/core/components/CallLayout/PipLayout/Pip.tsx"],"sourcesContent":["import { useCall } from '@stream-io/video-react-bindings';\nimport { useI18n } from '../../../../i18n';\nimport { useEffect, useState } from 'react';\n\nimport { hasScreenShare } from '@stream-io/video-client';\nimport { Icon } from '../../../../components';\nimport {\n DefaultParticipantViewUI,\n ParticipantView,\n ParticipantViewProps,\n} from '../../ParticipantView';\nimport {\n ParticipantFilter,\n ParticipantPredicate,\n useFilteredParticipants,\n usePaginatedLayoutSortPreset,\n} from '../hooks';\n\nexport type PipLayoutProps = {\n /**\n * Whether to exclude the local participant from the grid.\n * @default false\n */\n excludeLocalParticipant?: boolean;\n\n /**\n * Predicate to filter call participants or a filter object.\n * @example\n * // With a predicate:\n * <PipLayout\n * filterParticipants={p => p.roles.includes('student')}\n * />\n * @example\n * // With a filter object:\n * <PipLayout\n * filterParticipants={{\n * $or: [\n * { roles: { $contains: 'student' } },\n * { isPinned: true },\n * ],\n * }}\n * />\n */\n filterParticipants?: ParticipantPredicate | ParticipantFilter;\n\n /**\n * When set to `false` disables mirroring of the local partipant's video.\n * @default true\n */\n mirrorLocalParticipantVideo?: boolean;\n} & Pick<ParticipantViewProps, 'ParticipantViewUI' | 'VideoPlaceholder'>;\n\nexport const Pip = (props: PipLayoutProps) => {\n const { t } = useI18n();\n const {\n excludeLocalParticipant = false,\n filterParticipants,\n mirrorLocalParticipantVideo = true,\n VideoPlaceholder,\n ParticipantViewUI = DefaultParticipantViewUI,\n } = props;\n const [layoutWrapperElement, setLayoutWrapperElement] =\n useState<HTMLDivElement | null>(null);\n\n const call = useCall();\n const participants = useFilteredParticipants({\n excludeLocalParticipant,\n filterParticipants,\n });\n const screenSharingParticipant = participants.find((p) => hasScreenShare(p));\n\n usePaginatedLayoutSortPreset(call);\n\n useEffect(() => {\n if (!layoutWrapperElement || !call) return;\n return call.setViewport(layoutWrapperElement);\n }, [layoutWrapperElement, call]);\n\n const mirror = mirrorLocalParticipantVideo ? undefined : false;\n\n if (!call) return null;\n\n return (\n <div className=\"str-video__pip-layout\" ref={setLayoutWrapperElement}>\n {screenSharingParticipant &&\n (screenSharingParticipant.isLocalParticipant ? (\n <div className=\"str-video__pip-screen-share-local\">\n <Icon icon=\"screen-share-off\" />\n <span className=\"str-video__pip-screen-share-local__title\">\n {t(\n 'common.presentingYourScreen.text',\n 'You are presenting your screen',\n )}\n </span>\n </div>\n ) : (\n <ParticipantView\n participant={screenSharingParticipant}\n trackType=\"screenShareTrack\"\n muteAudio\n mirror={false}\n VideoPlaceholder={VideoPlaceholder}\n ParticipantViewUI={ParticipantViewUI}\n />\n ))}\n {participants.map((participant) => (\n <ParticipantView\n key={participant.sessionId}\n participant={participant}\n muteAudio\n mirror={mirror}\n VideoPlaceholder={VideoPlaceholder}\n ParticipantViewUI={ParticipantViewUI}\n />\n ))}\n </div>\n );\n};\n\nPip.displayName = 'PipLayout.Pip';\n"],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDO,MAAM,GAAG,GAAG,CAAC,KAAqB,KAAI;AAC3C,IAAA,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE;AACvB,IAAA,MAAM,EACJ,uBAAuB,GAAG,KAAK,EAC/B,kBAAkB,EAClB,2BAA2B,GAAG,IAAI,EAClC,gBAAgB,EAChB,iBAAiB,GAAG,wBAAwB,GAC7C,GAAG,KAAK;IACT,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GACnD,QAAQ,CAAwB,IAAI,CAAC;AAEvC,IAAA,MAAM,IAAI,GAAG,OAAO,EAAE;IACtB,MAAM,YAAY,GAAG,uBAAuB,CAAC;QAC3C,uBAAuB;QACvB,kBAAkB;AACnB,KAAA,CAAC;AACF,IAAA,MAAM,wBAAwB,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC;IAE5E,4BAA4B,CAAC,IAAI,CAAC;IAElC,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,oBAAoB,IAAI,CAAC,IAAI;YAAE;AACpC,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC;AAC/C,IAAA,CAAC,EAAE,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,2BAA2B,GAAG,SAAS,GAAG,KAAK;AAE9D,IAAA,IAAI,CAAC,IAAI;AAAE,QAAA,OAAO,IAAI;IAEtB,QACEA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,uBAAuB,EAAC,GAAG,EAAE,uBAAuB,EAAA,QAAA,EAAA,CAChE,wBAAwB;iBACtB,wBAAwB,CAAC,kBAAkB,IAC1CA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,mCAAmC,aAChDC,GAAA,CAAC,IAAI,EAAA,EAAC,IAAI,EAAC,kBAAkB,GAAG,EAChCA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,0CAA0C,EAAA,QAAA,EACvD,CAAC,CACA,kCAAkC,EAClC,gCAAgC,CACjC,GACI,CAAA,EAAA,CACH,KAENA,IAAC,eAAe,EAAA,EACd,WAAW,EAAE,wBAAwB,EACrC,SAAS,EAAC,kBAAkB,EAC5B,SAAS,EAAA,IAAA,EACT,MAAM,EAAE,KAAK,EACb,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,EAAE,iBAAiB,EAAA,CACpC,CACH,CAAC,EACH,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,MAC5BA,GAAA,CAAC,eAAe,EAAA,EAEd,WAAW,EAAE,WAAW,EACxB,SAAS,EAAA,IAAA,EACT,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,EAAE,iBAAiB,EAAA,EAL/B,WAAW,CAAC,SAAS,CAM1B,CACH,CAAC,CAAA,EAAA,CACE;AAEV;AAEA,GAAG,CAAC,WAAW,GAAG,eAAe;;;;"}
@@ -3,13 +3,19 @@ import { useState, useEffect } from 'react';
3
3
  import clsx from 'clsx';
4
4
  import { hasScreenShare } from '@stream-io/video-client';
5
5
  import { useCall, useCallStateHooks, useSpeakerLayoutSortPreset } from '@stream-io/video-react-bindings';
6
+ import '@stream-io/i18n';
7
+ import { useI18n } from '../../../i18n/TranslationContext.js';
8
+ import '@stream-io/i18n/react';
6
9
  import '../ParticipantView/ParticipantViewContext.js';
7
10
  import '../../../components/Menu/MenuToggle.js';
8
11
  import { ParticipantView } from '../ParticipantView/ParticipantView.js';
9
12
  import { DefaultParticipantViewUI } from '../ParticipantView/DefaultParticipantViewUI.js';
13
+ import '../ParticipantView/ConnectionQualityIndicator.js';
10
14
  import '../../../components/BackgroundFilters/BackgroundFiltersProvider.js';
11
- import '../../../components/Button/CompositeButton.js';
15
+ import '../../../components/Badge/Badge.js';
16
+ import '../../../components/Button/Button.js';
12
17
  import { IconButton } from '../../../components/Button/IconButton.js';
18
+ import '../../../components/Button/CompositeButton.js';
13
19
  import '@floating-ui/react';
14
20
  import { useVerticalScrollPosition, useHorizontalScrollPosition } from '../../../hooks/useScrollPosition.js';
15
21
  import { useDragToScroll } from '../../../hooks/useDragToScroll.js';
@@ -18,12 +24,9 @@ import '../../../components/CallControls/ReactionsButton.js';
18
24
  import '../../../components/DeviceSettings/DeviceSettings.js';
19
25
  import '../../../components/DropdownSelect/DropdownSelect.js';
20
26
  import '../../../components/CallControls/CancelCallButton.js';
21
- import '../../../components/CallControls/CallStatsButton.js';
22
27
  import '../../../components/CallParticipantsList/CallParticipantsList.js';
23
28
  import '../../../components/CallParticipantsList/CallParticipantListingItem.js';
24
- import '../../../components/CallStats/CallStats.js';
25
29
  import '../../../components/NoiseCancellation/NoiseCancellationProvider.js';
26
- import '../../../components/RingingCall/RingingCall.js';
27
30
  import '../../../components/Permissions/PermissionRequests.js';
28
31
  import '../Video/Video.js';
29
32
  import '../Video/BaseVideo.js';
@@ -79,6 +82,7 @@ const SpeakerLayout = ({ ParticipantViewUIBar = DefaultParticipantViewUIBar, Par
79
82
  };
80
83
  SpeakerLayout.displayName = 'SpeakerLayout';
81
84
  const HorizontalScrollButtons = ({ scrollWrapper, }) => {
85
+ const { t } = useI18n();
82
86
  const scrollPosition = useHorizontalScrollPosition(scrollWrapper);
83
87
  const scrollStartClickHandler = () => {
84
88
  scrollWrapper?.scrollBy({ left: -150, behavior: 'smooth' });
@@ -86,9 +90,10 @@ const HorizontalScrollButtons = ({ scrollWrapper, }) => {
86
90
  const scrollEndClickHandler = () => {
87
91
  scrollWrapper?.scrollBy({ left: 150, behavior: 'smooth' });
88
92
  };
89
- return (jsxs(Fragment, { children: [scrollPosition && scrollPosition !== 'start' && (jsx(IconButton, { onClick: scrollStartClickHandler, icon: "caret-left", className: "str-video__speaker-layout__participants-bar--button-left" })), scrollPosition && scrollPosition !== 'end' && (jsx(IconButton, { onClick: scrollEndClickHandler, icon: "caret-right", className: "str-video__speaker-layout__participants-bar--button-right" }))] }));
93
+ return (jsxs(Fragment, { children: [scrollPosition && scrollPosition !== 'start' && (jsx(IconButton, { size: "sm", variant: "secondary", onClick: scrollStartClickHandler, icon: "caret-left", "aria-label": t('callLayout.speakerLayout.scrollParticipantsLeft.ariaLabel', 'Scroll participants left'), className: "str-video__speaker-layout__participants-bar--button-left" })), scrollPosition && scrollPosition !== 'end' && (jsx(IconButton, { size: "sm", variant: "secondary", onClick: scrollEndClickHandler, icon: "caret-right", "aria-label": t('callLayout.speakerLayout.scrollParticipantsRight.ariaLabel', 'Scroll participants right'), className: "str-video__speaker-layout__participants-bar--button-right" }))] }));
90
94
  };
91
95
  const VerticalScrollButtons = ({ scrollWrapper, }) => {
96
+ const { t } = useI18n();
92
97
  const scrollPosition = useVerticalScrollPosition(scrollWrapper);
93
98
  const scrollTopClickHandler = () => {
94
99
  scrollWrapper?.scrollBy({ top: -150, behavior: 'smooth' });
@@ -96,7 +101,7 @@ const VerticalScrollButtons = ({ scrollWrapper, }) => {
96
101
  const scrollBottomClickHandler = () => {
97
102
  scrollWrapper?.scrollBy({ top: 150, behavior: 'smooth' });
98
103
  };
99
- return (jsxs(Fragment, { children: [scrollPosition && scrollPosition !== 'top' && (jsx(IconButton, { onClick: scrollTopClickHandler, icon: "caret-up", className: "str-video__speaker-layout__participants-bar--button-top" })), scrollPosition && scrollPosition !== 'bottom' && (jsx(IconButton, { onClick: scrollBottomClickHandler, icon: "caret-down", className: "str-video__speaker-layout__participants-bar--button-bottom" }))] }));
104
+ return (jsxs(Fragment, { children: [scrollPosition && scrollPosition !== 'top' && (jsx(IconButton, { size: "sm", variant: "secondary", onClick: scrollTopClickHandler, icon: "caret-up", "aria-label": t('callLayout.speakerLayout.scrollParticipantsUp.ariaLabel', 'Scroll participants up'), className: "str-video__speaker-layout__participants-bar--button-top" })), scrollPosition && scrollPosition !== 'bottom' && (jsx(IconButton, { size: "sm", variant: "secondary", onClick: scrollBottomClickHandler, icon: "caret-down", "aria-label": t('callLayout.speakerLayout.scrollParticipantsDown.ariaLabel', 'Scroll participants down'), className: "str-video__speaker-layout__participants-bar--button-bottom" }))] }));
100
105
  };
101
106
 
102
107
  export { SpeakerLayout };
@@ -1 +1 @@
1
- {"version":3,"file":"SpeakerLayout.js","sources":["../../../../../../../../src/core/components/CallLayout/SpeakerLayout.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport clsx from 'clsx';\nimport { hasScreenShare } from '@stream-io/video-client';\nimport {\n useCall,\n useCallStateHooks,\n useSpeakerLayoutSortPreset,\n} from '@stream-io/video-react-bindings';\n\nimport {\n DefaultParticipantViewUI,\n ParticipantView,\n ParticipantViewProps,\n} from '../ParticipantView';\nimport { IconButton } from '../../../components';\nimport {\n useDragToScroll,\n useHorizontalScrollPosition,\n useVerticalScrollPosition,\n} from '../../../hooks';\nimport {\n ParticipantFilter,\n ParticipantPredicate,\n useFilteredParticipants,\n useRawRemoteParticipants,\n} from './hooks';\nimport { useCalculateHardLimit } from '../../hooks/useCalculateHardLimit';\nimport { ParticipantsAudio } from '../Audio';\n\nexport type SpeakerLayoutProps = {\n /**\n * The UI to be used for the participant in the spotlight.\n */\n ParticipantViewUISpotlight?: ParticipantViewProps['ParticipantViewUI'];\n\n /**\n * The UI to be used for the participants in the participants bar.\n */\n ParticipantViewUIBar?: ParticipantViewProps['ParticipantViewUI'];\n\n /**\n * The position of the participants who are not in focus.\n * Providing `null` will hide the bar.\n */\n participantsBarPosition?: 'top' | 'bottom' | 'left' | 'right' | null;\n\n /**\n * Hard limits the number of the participants rendered in the participants bar.\n * Providing string `dynamic` will calculate hard limit based on screen width/height.\n */\n participantsBarLimit?: 'dynamic' | number;\n\n /**\n * When set to `true` will exclude the local participant from layout.\n * @default false\n */\n excludeLocalParticipant?: boolean;\n\n /**\n * Predicate to filter call participants or a filter object.\n * @example\n * // With a predicate:\n * <SpeakerLayout\n * filterParticipants={p => p.roles.includes('student')}\n * />\n * @example\n * // With a filter object:\n * <SpeakerLayout\n * filterParticipants={{\n * $or: [\n * { roles: { $contains: 'student' } },\n * { isPinned: true },\n * ],\n * }}\n * />\n */\n filterParticipants?: ParticipantPredicate | ParticipantFilter;\n\n /**\n * When set to `false` disables mirroring of the local participant's video.\n * @default true\n */\n mirrorLocalParticipantVideo?: boolean;\n\n /**\n * Turns on/off the pagination arrows.\n * @default true\n */\n pageArrowsVisible?: boolean;\n\n /**\n * Whether the layout is muted. Defaults to `false`.\n */\n muted?: boolean;\n\n /**\n * Whether to enable drag-to-scroll functionality on the participants bar.\n * @default false\n */\n enableDragToScroll?: boolean;\n} & Pick<\n ParticipantViewProps,\n 'VideoPlaceholder' | 'PictureInPicturePlaceholder'\n>;\n\nconst DefaultParticipantViewUIBar = () => (\n <DefaultParticipantViewUI menuPlacement=\"top-end\" />\n);\n\nexport const SpeakerLayout = ({\n ParticipantViewUIBar = DefaultParticipantViewUIBar,\n ParticipantViewUISpotlight = DefaultParticipantViewUI,\n VideoPlaceholder,\n PictureInPicturePlaceholder,\n participantsBarPosition = 'bottom',\n participantsBarLimit,\n mirrorLocalParticipantVideo = true,\n excludeLocalParticipant = false,\n filterParticipants,\n pageArrowsVisible = true,\n muted,\n enableDragToScroll = false,\n}: SpeakerLayoutProps) => {\n const call = useCall();\n const { useParticipants } = useCallStateHooks();\n const allParticipants = useParticipants();\n const remoteParticipants = useRawRemoteParticipants();\n const [participantInSpotlight, ...otherParticipants] =\n useFilteredParticipants({ excludeLocalParticipant, filterParticipants });\n const [participantsBarWrapperElement, setParticipantsBarWrapperElement] =\n useState<HTMLDivElement | null>(null);\n const [participantsBarElement, setParticipantsBarElement] =\n useState<HTMLDivElement | null>(null);\n const [buttonsWrapperElement, setButtonsWrapperElement] =\n useState<HTMLDivElement | null>(null);\n\n const isSpeakerScreenSharing =\n participantInSpotlight && hasScreenShare(participantInSpotlight);\n const hardLimit = useCalculateHardLimit(\n buttonsWrapperElement,\n participantsBarElement,\n participantsBarLimit,\n );\n\n const isVertical =\n participantsBarPosition === 'left' || participantsBarPosition === 'right';\n const isHorizontal =\n participantsBarPosition === 'top' || participantsBarPosition === 'bottom';\n\n useEffect(() => {\n if (!participantsBarWrapperElement || !call) return;\n\n const cleanup = call.setViewport(participantsBarWrapperElement);\n\n return () => cleanup?.();\n }, [participantsBarWrapperElement, call]);\n\n const isOneOnOneCall = allParticipants.length === 2;\n useSpeakerLayoutSortPreset(call, isOneOnOneCall);\n useDragToScroll(participantsBarWrapperElement, {\n enabled: enableDragToScroll,\n });\n\n let participantsWithAppliedLimit = otherParticipants;\n\n const hardLimitToApply = isVertical\n ? hardLimit.vertical\n : hardLimit.horizontal;\n\n if (\n typeof participantsBarLimit !== 'undefined' &&\n hardLimitToApply !== null\n ) {\n participantsWithAppliedLimit = otherParticipants.slice(\n 0,\n // subtract 1 if speaker is sharing screen as\n // that one is rendered independently from otherParticipants array\n hardLimitToApply - (isSpeakerScreenSharing ? 1 : 0),\n );\n }\n\n const mirror = mirrorLocalParticipantVideo ? undefined : false;\n\n if (!call) return null;\n\n const renderParticipantsBar =\n participantsBarPosition &&\n (participantsWithAppliedLimit.length > 0 || isSpeakerScreenSharing);\n return (\n <div className=\"str-video__speaker-layout__wrapper\">\n {!muted && <ParticipantsAudio participants={remoteParticipants} />}\n <div\n className={clsx(\n 'str-video__speaker-layout',\n participantsBarPosition &&\n `str-video__speaker-layout--variant-${participantsBarPosition}`,\n )}\n >\n <div className=\"str-video__speaker-layout__spotlight\">\n {participantInSpotlight && (\n <ParticipantView\n participant={participantInSpotlight}\n muteAudio={true}\n mirror={mirror}\n trackType={\n isSpeakerScreenSharing ? 'screenShareTrack' : 'videoTrack'\n }\n ParticipantViewUI={ParticipantViewUISpotlight}\n VideoPlaceholder={VideoPlaceholder}\n PictureInPicturePlaceholder={PictureInPicturePlaceholder}\n />\n )}\n </div>\n {renderParticipantsBar && (\n <div\n ref={setButtonsWrapperElement}\n className=\"str-video__speaker-layout__participants-bar-buttons-wrapper\"\n >\n <div\n className=\"str-video__speaker-layout__participants-bar-wrapper\"\n ref={setParticipantsBarWrapperElement}\n >\n <div\n ref={setParticipantsBarElement}\n className=\"str-video__speaker-layout__participants-bar\"\n >\n {isSpeakerScreenSharing && (\n <div\n className=\"str-video__speaker-layout__participant-tile\"\n key={participantInSpotlight.sessionId}\n >\n <ParticipantView\n participant={participantInSpotlight}\n ParticipantViewUI={ParticipantViewUIBar}\n VideoPlaceholder={VideoPlaceholder}\n PictureInPicturePlaceholder={PictureInPicturePlaceholder}\n mirror={mirror}\n muteAudio={true}\n />\n </div>\n )}\n {participantsWithAppliedLimit.map((participant) => (\n <div\n className=\"str-video__speaker-layout__participant-tile\"\n key={participant.sessionId}\n >\n <ParticipantView\n participant={participant}\n ParticipantViewUI={ParticipantViewUIBar}\n VideoPlaceholder={VideoPlaceholder}\n PictureInPicturePlaceholder={PictureInPicturePlaceholder}\n mirror={mirror}\n muteAudio={true}\n />\n </div>\n ))}\n </div>\n </div>\n {pageArrowsVisible && isVertical && (\n <VerticalScrollButtons\n scrollWrapper={participantsBarWrapperElement}\n />\n )}\n {pageArrowsVisible && isHorizontal && (\n <HorizontalScrollButtons\n scrollWrapper={participantsBarWrapperElement}\n />\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nSpeakerLayout.displayName = 'SpeakerLayout';\n\ntype ScrollButtonsProps<T extends HTMLElement> = {\n scrollWrapper: T | null;\n};\n\nconst HorizontalScrollButtons = <T extends HTMLElement>({\n scrollWrapper,\n}: ScrollButtonsProps<T>) => {\n const scrollPosition = useHorizontalScrollPosition(scrollWrapper);\n\n const scrollStartClickHandler = () => {\n scrollWrapper?.scrollBy({ left: -150, behavior: 'smooth' });\n };\n\n const scrollEndClickHandler = () => {\n scrollWrapper?.scrollBy({ left: 150, behavior: 'smooth' });\n };\n return (\n <>\n {scrollPosition && scrollPosition !== 'start' && (\n <IconButton\n onClick={scrollStartClickHandler}\n icon=\"caret-left\"\n className=\"str-video__speaker-layout__participants-bar--button-left\"\n />\n )}\n {scrollPosition && scrollPosition !== 'end' && (\n <IconButton\n onClick={scrollEndClickHandler}\n icon=\"caret-right\"\n className=\"str-video__speaker-layout__participants-bar--button-right\"\n />\n )}\n </>\n );\n};\n\nconst VerticalScrollButtons = <T extends HTMLElement>({\n scrollWrapper,\n}: ScrollButtonsProps<T>) => {\n const scrollPosition = useVerticalScrollPosition(scrollWrapper);\n\n const scrollTopClickHandler = () => {\n scrollWrapper?.scrollBy({ top: -150, behavior: 'smooth' });\n };\n\n const scrollBottomClickHandler = () => {\n scrollWrapper?.scrollBy({ top: 150, behavior: 'smooth' });\n };\n return (\n <>\n {scrollPosition && scrollPosition !== 'top' && (\n <IconButton\n onClick={scrollTopClickHandler}\n icon=\"caret-up\"\n className=\"str-video__speaker-layout__participants-bar--button-top\"\n />\n )}\n {scrollPosition && scrollPosition !== 'bottom' && (\n <IconButton\n onClick={scrollBottomClickHandler}\n icon=\"caret-down\"\n className=\"str-video__speaker-layout__participants-bar--button-bottom\"\n />\n )}\n </>\n );\n};\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"SpeakerLayout.js","sources":["../../../../../../../../src/core/components/CallLayout/SpeakerLayout.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport clsx from 'clsx';\nimport { hasScreenShare } from '@stream-io/video-client';\nimport {\n useCall,\n useCallStateHooks,\n useSpeakerLayoutSortPreset,\n} from '@stream-io/video-react-bindings';\nimport { useI18n } from '../../../i18n';\n\nimport {\n DefaultParticipantViewUI,\n ParticipantView,\n ParticipantViewProps,\n} from '../ParticipantView';\nimport { IconButton } from '../../../components';\nimport {\n useDragToScroll,\n useHorizontalScrollPosition,\n useVerticalScrollPosition,\n} from '../../../hooks';\nimport {\n ParticipantFilter,\n ParticipantPredicate,\n useFilteredParticipants,\n useRawRemoteParticipants,\n} from './hooks';\nimport { useCalculateHardLimit } from '../../hooks/useCalculateHardLimit';\nimport { ParticipantsAudio } from '../Audio';\n\nexport type SpeakerLayoutProps = {\n /**\n * The UI to be used for the participant in the spotlight.\n */\n ParticipantViewUISpotlight?: ParticipantViewProps['ParticipantViewUI'];\n\n /**\n * The UI to be used for the participants in the participants bar.\n */\n ParticipantViewUIBar?: ParticipantViewProps['ParticipantViewUI'];\n\n /**\n * The position of the participants who are not in focus.\n * Providing `null` will hide the bar.\n */\n participantsBarPosition?: 'top' | 'bottom' | 'left' | 'right' | null;\n\n /**\n * Hard limits the number of the participants rendered in the participants bar.\n * Providing string `dynamic` will calculate hard limit based on screen width/height.\n */\n participantsBarLimit?: 'dynamic' | number;\n\n /**\n * When set to `true` will exclude the local participant from layout.\n * @default false\n */\n excludeLocalParticipant?: boolean;\n\n /**\n * Predicate to filter call participants or a filter object.\n * @example\n * // With a predicate:\n * <SpeakerLayout\n * filterParticipants={p => p.roles.includes('student')}\n * />\n * @example\n * // With a filter object:\n * <SpeakerLayout\n * filterParticipants={{\n * $or: [\n * { roles: { $contains: 'student' } },\n * { isPinned: true },\n * ],\n * }}\n * />\n */\n filterParticipants?: ParticipantPredicate | ParticipantFilter;\n\n /**\n * When set to `false` disables mirroring of the local participant's video.\n * @default true\n */\n mirrorLocalParticipantVideo?: boolean;\n\n /**\n * Turns on/off the pagination arrows.\n * @default true\n */\n pageArrowsVisible?: boolean;\n\n /**\n * Whether the layout is muted. Defaults to `false`.\n */\n muted?: boolean;\n\n /**\n * Whether to enable drag-to-scroll functionality on the participants bar.\n * @default false\n */\n enableDragToScroll?: boolean;\n} & Pick<\n ParticipantViewProps,\n 'VideoPlaceholder' | 'PictureInPicturePlaceholder'\n>;\n\nconst DefaultParticipantViewUIBar = () => (\n <DefaultParticipantViewUI menuPlacement=\"top-end\" />\n);\n\nexport const SpeakerLayout = ({\n ParticipantViewUIBar = DefaultParticipantViewUIBar,\n ParticipantViewUISpotlight = DefaultParticipantViewUI,\n VideoPlaceholder,\n PictureInPicturePlaceholder,\n participantsBarPosition = 'bottom',\n participantsBarLimit,\n mirrorLocalParticipantVideo = true,\n excludeLocalParticipant = false,\n filterParticipants,\n pageArrowsVisible = true,\n muted,\n enableDragToScroll = false,\n}: SpeakerLayoutProps) => {\n const call = useCall();\n const { useParticipants } = useCallStateHooks();\n const allParticipants = useParticipants();\n const remoteParticipants = useRawRemoteParticipants();\n const [participantInSpotlight, ...otherParticipants] =\n useFilteredParticipants({ excludeLocalParticipant, filterParticipants });\n const [participantsBarWrapperElement, setParticipantsBarWrapperElement] =\n useState<HTMLDivElement | null>(null);\n const [participantsBarElement, setParticipantsBarElement] =\n useState<HTMLDivElement | null>(null);\n const [buttonsWrapperElement, setButtonsWrapperElement] =\n useState<HTMLDivElement | null>(null);\n\n const isSpeakerScreenSharing =\n participantInSpotlight && hasScreenShare(participantInSpotlight);\n const hardLimit = useCalculateHardLimit(\n buttonsWrapperElement,\n participantsBarElement,\n participantsBarLimit,\n );\n\n const isVertical =\n participantsBarPosition === 'left' || participantsBarPosition === 'right';\n const isHorizontal =\n participantsBarPosition === 'top' || participantsBarPosition === 'bottom';\n\n useEffect(() => {\n if (!participantsBarWrapperElement || !call) return;\n\n const cleanup = call.setViewport(participantsBarWrapperElement);\n\n return () => cleanup?.();\n }, [participantsBarWrapperElement, call]);\n\n const isOneOnOneCall = allParticipants.length === 2;\n useSpeakerLayoutSortPreset(call, isOneOnOneCall);\n useDragToScroll(participantsBarWrapperElement, {\n enabled: enableDragToScroll,\n });\n\n let participantsWithAppliedLimit = otherParticipants;\n\n const hardLimitToApply = isVertical\n ? hardLimit.vertical\n : hardLimit.horizontal;\n\n if (\n typeof participantsBarLimit !== 'undefined' &&\n hardLimitToApply !== null\n ) {\n participantsWithAppliedLimit = otherParticipants.slice(\n 0,\n // subtract 1 if speaker is sharing screen as\n // that one is rendered independently from otherParticipants array\n hardLimitToApply - (isSpeakerScreenSharing ? 1 : 0),\n );\n }\n\n const mirror = mirrorLocalParticipantVideo ? undefined : false;\n\n if (!call) return null;\n\n const renderParticipantsBar =\n participantsBarPosition &&\n (participantsWithAppliedLimit.length > 0 || isSpeakerScreenSharing);\n return (\n <div className=\"str-video__speaker-layout__wrapper\">\n {!muted && <ParticipantsAudio participants={remoteParticipants} />}\n <div\n className={clsx(\n 'str-video__speaker-layout',\n participantsBarPosition &&\n `str-video__speaker-layout--variant-${participantsBarPosition}`,\n )}\n >\n <div className=\"str-video__speaker-layout__spotlight\">\n {participantInSpotlight && (\n <ParticipantView\n participant={participantInSpotlight}\n muteAudio={true}\n mirror={mirror}\n trackType={\n isSpeakerScreenSharing ? 'screenShareTrack' : 'videoTrack'\n }\n ParticipantViewUI={ParticipantViewUISpotlight}\n VideoPlaceholder={VideoPlaceholder}\n PictureInPicturePlaceholder={PictureInPicturePlaceholder}\n />\n )}\n </div>\n {renderParticipantsBar && (\n <div\n ref={setButtonsWrapperElement}\n className=\"str-video__speaker-layout__participants-bar-buttons-wrapper\"\n >\n <div\n className=\"str-video__speaker-layout__participants-bar-wrapper\"\n ref={setParticipantsBarWrapperElement}\n >\n <div\n ref={setParticipantsBarElement}\n className=\"str-video__speaker-layout__participants-bar\"\n >\n {isSpeakerScreenSharing && (\n <div\n className=\"str-video__speaker-layout__participant-tile\"\n key={participantInSpotlight.sessionId}\n >\n <ParticipantView\n participant={participantInSpotlight}\n ParticipantViewUI={ParticipantViewUIBar}\n VideoPlaceholder={VideoPlaceholder}\n PictureInPicturePlaceholder={PictureInPicturePlaceholder}\n mirror={mirror}\n muteAudio={true}\n />\n </div>\n )}\n {participantsWithAppliedLimit.map((participant) => (\n <div\n className=\"str-video__speaker-layout__participant-tile\"\n key={participant.sessionId}\n >\n <ParticipantView\n participant={participant}\n ParticipantViewUI={ParticipantViewUIBar}\n VideoPlaceholder={VideoPlaceholder}\n PictureInPicturePlaceholder={PictureInPicturePlaceholder}\n mirror={mirror}\n muteAudio={true}\n />\n </div>\n ))}\n </div>\n </div>\n {pageArrowsVisible && isVertical && (\n <VerticalScrollButtons\n scrollWrapper={participantsBarWrapperElement}\n />\n )}\n {pageArrowsVisible && isHorizontal && (\n <HorizontalScrollButtons\n scrollWrapper={participantsBarWrapperElement}\n />\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nSpeakerLayout.displayName = 'SpeakerLayout';\n\ntype ScrollButtonsProps<T extends HTMLElement> = {\n scrollWrapper: T | null;\n};\n\nconst HorizontalScrollButtons = <T extends HTMLElement>({\n scrollWrapper,\n}: ScrollButtonsProps<T>) => {\n const { t } = useI18n();\n const scrollPosition = useHorizontalScrollPosition(scrollWrapper);\n\n const scrollStartClickHandler = () => {\n scrollWrapper?.scrollBy({ left: -150, behavior: 'smooth' });\n };\n\n const scrollEndClickHandler = () => {\n scrollWrapper?.scrollBy({ left: 150, behavior: 'smooth' });\n };\n return (\n <>\n {scrollPosition && scrollPosition !== 'start' && (\n <IconButton\n size=\"sm\"\n variant=\"secondary\"\n onClick={scrollStartClickHandler}\n icon=\"caret-left\"\n aria-label={t(\n 'callLayout.speakerLayout.scrollParticipantsLeft.ariaLabel',\n 'Scroll participants left',\n )}\n className=\"str-video__speaker-layout__participants-bar--button-left\"\n />\n )}\n {scrollPosition && scrollPosition !== 'end' && (\n <IconButton\n size=\"sm\"\n variant=\"secondary\"\n onClick={scrollEndClickHandler}\n icon=\"caret-right\"\n aria-label={t(\n 'callLayout.speakerLayout.scrollParticipantsRight.ariaLabel',\n 'Scroll participants right',\n )}\n className=\"str-video__speaker-layout__participants-bar--button-right\"\n />\n )}\n </>\n );\n};\n\nconst VerticalScrollButtons = <T extends HTMLElement>({\n scrollWrapper,\n}: ScrollButtonsProps<T>) => {\n const { t } = useI18n();\n const scrollPosition = useVerticalScrollPosition(scrollWrapper);\n\n const scrollTopClickHandler = () => {\n scrollWrapper?.scrollBy({ top: -150, behavior: 'smooth' });\n };\n\n const scrollBottomClickHandler = () => {\n scrollWrapper?.scrollBy({ top: 150, behavior: 'smooth' });\n };\n return (\n <>\n {scrollPosition && scrollPosition !== 'top' && (\n <IconButton\n size=\"sm\"\n variant=\"secondary\"\n onClick={scrollTopClickHandler}\n icon=\"caret-up\"\n aria-label={t(\n 'callLayout.speakerLayout.scrollParticipantsUp.ariaLabel',\n 'Scroll participants up',\n )}\n className=\"str-video__speaker-layout__participants-bar--button-top\"\n />\n )}\n {scrollPosition && scrollPosition !== 'bottom' && (\n <IconButton\n size=\"sm\"\n variant=\"secondary\"\n onClick={scrollBottomClickHandler}\n icon=\"caret-down\"\n aria-label={t(\n 'callLayout.speakerLayout.scrollParticipantsDown.ariaLabel',\n 'Scroll participants down',\n )}\n className=\"str-video__speaker-layout__participants-bar--button-bottom\"\n />\n )}\n </>\n );\n};\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import clsx from 'clsx';
3
+ import { SfuModels } from '@stream-io/video-client';
4
+
5
+ /** How many of the three bars are lit, per quality level. */
6
+ const ACTIVE_BARS = {
7
+ [SfuModels.ConnectionQuality.POOR]: 1,
8
+ [SfuModels.ConnectionQuality.GOOD]: 2,
9
+ [SfuModels.ConnectionQuality.EXCELLENT]: 3,
10
+ };
11
+ const BAR_COUNT = 3;
12
+ /**
13
+ * Three ascending bars showing a participant's connection quality.
14
+ */
15
+ const ConnectionQualityIndicator = ({ quality, title, className, }) => {
16
+ const activeBars = ACTIVE_BARS[quality];
17
+ if (!activeBars)
18
+ return null;
19
+ const level = SfuModels.ConnectionQuality[quality].toLowerCase();
20
+ return (jsx("span", { className: clsx('str-video__connection-quality-indicator', `str-video__connection-quality-indicator--${level}`, className), title: title ?? level, children: Array.from({ length: BAR_COUNT }, (_, index) => (jsx("span", { className: clsx('str-video__connection-quality-indicator__bar', index < activeBars &&
21
+ 'str-video__connection-quality-indicator__bar--active') }, index))) }));
22
+ };
23
+
24
+ export { ConnectionQualityIndicator };
25
+ //# sourceMappingURL=ConnectionQualityIndicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConnectionQualityIndicator.js","sources":["../../../../../../../../src/core/components/ParticipantView/ConnectionQualityIndicator.tsx"],"sourcesContent":["import clsx from 'clsx';\nimport { SfuModels } from '@stream-io/video-client';\n\nexport type ConnectionQualityIndicatorProps = {\n quality: SfuModels.ConnectionQuality;\n title?: string;\n className?: string;\n};\n\n/** How many of the three bars are lit, per quality level. */\nconst ACTIVE_BARS: Partial<Record<SfuModels.ConnectionQuality, number>> = {\n [SfuModels.ConnectionQuality.POOR]: 1,\n [SfuModels.ConnectionQuality.GOOD]: 2,\n [SfuModels.ConnectionQuality.EXCELLENT]: 3,\n};\n\nconst BAR_COUNT = 3;\n\n/**\n * Three ascending bars showing a participant's connection quality.\n */\nexport const ConnectionQualityIndicator = ({\n quality,\n title,\n className,\n}: ConnectionQualityIndicatorProps) => {\n const activeBars = ACTIVE_BARS[quality];\n\n if (!activeBars) return null;\n\n const level = SfuModels.ConnectionQuality[quality].toLowerCase();\n\n return (\n <span\n className={clsx(\n 'str-video__connection-quality-indicator',\n `str-video__connection-quality-indicator--${level}`,\n className,\n )}\n title={title ?? level}\n >\n {Array.from({ length: BAR_COUNT }, (_, index) => (\n <span\n key={index}\n className={clsx(\n 'str-video__connection-quality-indicator__bar',\n index < activeBars &&\n 'str-video__connection-quality-indicator__bar--active',\n )}\n />\n ))}\n </span>\n );\n};\n"],"names":["_jsx"],"mappings":";;;;AASA;AACA,MAAM,WAAW,GAAyD;AACxE,IAAA,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC;AACrC,IAAA,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC;AACrC,IAAA,CAAC,SAAS,CAAC,iBAAiB,CAAC,SAAS,GAAG,CAAC;CAC3C;AAED,MAAM,SAAS,GAAG,CAAC;AAEnB;;AAEG;AACI,MAAM,0BAA0B,GAAG,CAAC,EACzC,OAAO,EACP,KAAK,EACL,SAAS,GACuB,KAAI;AACpC,IAAA,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC;AAEvC,IAAA,IAAI,CAAC,UAAU;AAAE,QAAA,OAAO,IAAI;IAE5B,MAAM,KAAK,GAAG,SAAS,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE;IAEhE,QACEA,cACE,SAAS,EAAE,IAAI,CACb,yCAAyC,EACzC,CAAA,yCAAA,EAA4C,KAAK,CAAA,CAAE,EACnD,SAAS,CACV,EACD,KAAK,EAAE,KAAK,IAAI,KAAK,EAAA,QAAA,EAEpB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,MAC1CA,GAAA,CAAA,MAAA,EAAA,EAEE,SAAS,EAAE,IAAI,CACb,8CAA8C,EAC9C,KAAK,GAAG,UAAU;gBAChB,sDAAsD,CACzD,IALI,KAAK,CAMV,CACH,CAAC,EAAA,CACG;AAEX;;;;"}
@@ -1,11 +1,16 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { forwardRef } from 'react';
3
- import { hasScreenShare, SfuModels, hasAudio, hasVideo, hasPausedTrack } from '@stream-io/video-client';
4
- import { useCallStateHooks, useCall, useI18n, useIsAudioConnecting, useIsVideoConnecting } from '@stream-io/video-react-bindings';
3
+ import { hasScreenShare, hasAudio, hasVideo, hasPausedTrack, SfuModels } from '@stream-io/video-client';
4
+ import { useCallStateHooks, useCall, useIsAudioConnecting, useIsVideoConnecting } from '@stream-io/video-react-bindings';
5
+ import '@stream-io/i18n';
6
+ import { useI18n } from '../../../i18n/TranslationContext.js';
7
+ import '@stream-io/i18n/react';
5
8
  import clsx from 'clsx';
6
9
  import '../../../components/BackgroundFilters/BackgroundFiltersProvider.js';
7
- import '../../../components/Button/CompositeButton.js';
10
+ import '../../../components/Badge/Badge.js';
11
+ import { Button } from '../../../components/Button/Button.js';
8
12
  import { IconButton } from '../../../components/Button/IconButton.js';
13
+ import '../../../components/Button/CompositeButton.js';
9
14
  import { Notification } from '../../../components/Notification/Notification.js';
10
15
  import '../../../components/CallControls/RecordCallButton.js';
11
16
  import '../../../components/CallControls/ReactionsButton.js';
@@ -15,23 +20,22 @@ import '../../../components/DeviceSettings/DeviceSettings.js';
15
20
  import '../../../components/DropdownSelect/DropdownSelect.js';
16
21
  import { MenuToggle } from '../../../components/Menu/MenuToggle.js';
17
22
  import '../../../components/CallControls/CancelCallButton.js';
18
- import '../../../components/CallControls/CallStatsButton.js';
19
23
  import '../../../components/CallParticipantsList/CallParticipantsList.js';
20
24
  import '../../../components/CallParticipantsList/CallParticipantListingItem.js';
21
25
  import { LoadingIndicator } from '../../../components/LoadingIndicator/LoadingIndicator.js';
22
- import '../../../components/CallStats/CallStats.js';
23
26
  import '../../../components/NoiseCancellation/NoiseCancellationProvider.js';
24
27
  import { Reaction } from '../../../components/Reaction/Reaction.js';
25
- import '../../../components/RingingCall/RingingCall.js';
26
28
  import '../../../components/Permissions/PermissionRequests.js';
27
29
  import '../Video/Video.js';
28
30
  import '../Video/BaseVideo.js';
29
31
  import '../Video/DefaultVideoPlaceholder.js';
30
32
  import { ParticipantActionsContextMenu } from './ParticipantActionsContextMenu.js';
33
+ import { ConnectionQualityIndicator } from './ConnectionQualityIndicator.js';
31
34
  import { useParticipantViewContext } from './ParticipantViewContext.js';
32
35
 
33
36
  const ToggleButton = forwardRef(function ToggleButtonRender(props, ref) {
34
- return jsx(IconButton, { enabled: props.menuShown, icon: "ellipsis", ref: ref });
37
+ const { t } = useI18n();
38
+ return (jsx(IconButton, { className: "str-video__participant-view__menu-button", active: props.menuShown, size: "sm", variant: "secondary", ref: ref, title: t('participantView.moreOptions.title', 'More options'), icon: "ellipsis" }));
35
39
  });
36
40
  const DefaultScreenShareOverlay = () => {
37
41
  const call = useCall();
@@ -41,7 +45,7 @@ const DefaultScreenShareOverlay = () => {
41
45
  console.error('Failed to stop screen sharing:', err);
42
46
  });
43
47
  };
44
- return (jsxs("div", { className: "str-video__screen-share-overlay", children: [jsx(Icon, { icon: "screen-share-off" }), jsx("span", { className: "str-video__screen-share-overlay__title", children: t('You are presenting your screen') }), jsxs("button", { onClick: stopScreenShare, type: "button", className: "str-video__screen-share-overlay__button", children: [jsx(Icon, { icon: "close" }), " ", t('Stop Screen Sharing')] })] }));
48
+ return (jsxs("div", { className: "str-video__screen-share-overlay", children: [jsx(Icon, { icon: "screen-share-off" }), jsx("span", { className: "str-video__screen-share-overlay__title", children: t('common.presentingYourScreen.text', 'You are presenting your screen') }), jsxs(Button, { variant: "destructive", onClick: stopScreenShare, className: "str-video__screen-share-overlay__button", children: [jsx(Icon, { icon: "close" }), ' ', t('participantView.stopScreenSharing.label', 'Stop Screen Sharing')] })] }));
45
49
  };
46
50
  /**
47
51
  * Rendered over a remote participant's tile when the browser's autoplay policy
@@ -51,7 +55,7 @@ const DefaultScreenShareOverlay = () => {
51
55
  const DefaultAudioBlockedNotification = () => {
52
56
  const call = useCall();
53
57
  const { t } = useI18n();
54
- return (jsx("button", { type: "button", className: "str-video__audio-blocked-notification", onClick: call?.resumeAudio, "aria-live": "polite", children: jsxs("span", { className: "str-video__audio-blocked-notification__message", children: [jsx(Icon, { icon: "speaker" }), jsxs("span", { className: "str-video__audio-blocked-notification__text", children: [jsx("span", { className: "str-video__audio-blocked-notification__title", children: t('Audio is blocked by your system') }), jsx("span", { className: "str-video__audio-blocked-notification__subtitle", children: t('Click or tap to play audio') })] })] }) }));
58
+ return (jsx("button", { type: "button", className: "str-video__audio-blocked-notification", onClick: call?.resumeAudio, "aria-live": "polite", children: jsxs("span", { className: "str-video__audio-blocked-notification__message", children: [jsx(Icon, { icon: "speaker" }), jsxs("span", { className: "str-video__audio-blocked-notification__text", children: [jsx("span", { className: "str-video__audio-blocked-notification__title", children: t('participantView.audioBlocked.title', 'Audio is blocked by your system') }), jsx("span", { className: "str-video__audio-blocked-notification__subtitle", children: t('participantView.audioBlocked.description', 'Click or tap to play audio') })] })] }) }));
55
59
  };
56
60
  const DefaultParticipantViewUI = ({ indicatorsVisible = true, menuPlacement = 'bottom-start', showMenuButton = true, ParticipantActionsContextMenu: ParticipantActionsContextMenu$1 = ParticipantActionsContextMenu, AudioBlockedNotification = DefaultAudioBlockedNotification, }) => {
57
61
  const { participant, trackType } = useParticipantViewContext();
@@ -73,16 +77,16 @@ const ParticipantDetails = ({ indicatorsVisible = true, }) => {
73
77
  const { isLocalParticipant, connectionQuality, pin, sessionId, name, userId, } = participant;
74
78
  const call = useCall();
75
79
  const { t } = useI18n();
76
- const connectionQualityAsString = !!connectionQuality &&
77
- SfuModels.ConnectionQuality[connectionQuality].toLowerCase();
78
80
  const hasAudioTrack = hasAudio(participant);
79
81
  const hasVideoTrack = hasVideo(participant);
80
82
  const canUnpin = !!pin && pin.isLocalPin;
81
83
  const isTrackPaused = trackType !== 'none' ? hasPausedTrack(participant, trackType) : false;
82
84
  const isAudioConnecting = useIsAudioConnecting(participant);
83
85
  const isVideoConnecting = useIsVideoConnecting(participant);
84
- return (jsxs(Fragment, { children: [jsx("div", { className: "str-video__participant-details", children: jsxs("div", { className: "str-video__participant-details__name", children: [name || userId, indicatorsVisible && isAudioConnecting && (jsx(LoadingIndicator, { className: "str-video__participant-details__name--audio-connecting", tooltip: t('Audio is connecting...') })), indicatorsVisible && !hasAudioTrack && (jsx("span", { className: "str-video__participant-details__name--audio-muted" })), indicatorsVisible && isVideoConnecting && (jsx(LoadingIndicator, { className: "str-video__participant-details__name--video-connecting", tooltip: t('Video is connecting...') })), indicatorsVisible && !hasVideoTrack && (jsx("span", { className: "str-video__participant-details__name--video-muted" })), indicatorsVisible && isTrackPaused && (jsx("span", { title: t('Video paused due to insufficient bandwidth'), className: "str-video__participant-details__name--track-paused" })), indicatorsVisible && pin && (jsx("span", { title: canUnpin ? t('Unpin') : t('Pinned'), onClick: canUnpin ? () => call?.unpin(sessionId) : undefined, className: "str-video__participant-details__name--pinned" })), indicatorsVisible && jsx(SpeechIndicator, {})] }) }), indicatorsVisible && (jsx(Notification, { isVisible: isLocalParticipant &&
85
- connectionQuality === SfuModels.ConnectionQuality.POOR, message: t('Poor connection quality'), children: connectionQualityAsString && (jsx("span", { className: clsx('str-video__participant-details__connection-quality', `str-video__participant-details__connection-quality--${connectionQualityAsString}`), title: connectionQualityAsString })) }))] }));
86
+ return (jsxs(Fragment, { children: [jsx("div", { className: "str-video__participant-details", children: jsxs("div", { className: "str-video__participant-details__name", children: [jsx("span", { className: "str-video__participant-details__name-text", children: name || userId }), indicatorsVisible && isAudioConnecting && (jsx(LoadingIndicator, { className: "str-video__participant-details__name--audio-connecting", tooltip: t('participantView.audioConnecting.title', 'Audio is connecting...') })), indicatorsVisible && !hasAudioTrack && (jsx("span", { className: "str-video__participant-details__name--audio-muted" })), indicatorsVisible && isVideoConnecting && (jsx(LoadingIndicator, { className: "str-video__participant-details__name--video-connecting", tooltip: t('participantView.videoConnecting.title', 'Video is connecting...') })), indicatorsVisible && !hasVideoTrack && (jsx("span", { className: "str-video__participant-details__name--video-muted" })), indicatorsVisible && isTrackPaused && (jsx("span", { title: t('participantView.videoPausedInsufficientBandwidth.title', 'Video paused due to insufficient bandwidth'), className: "str-video__participant-details__name--track-paused" })), indicatorsVisible && pin && (jsx("span", { title: canUnpin
87
+ ? t('participantView.unpin.label', 'Unpin')
88
+ : t('participantList.pinned.title', 'Pinned'), onClick: canUnpin ? () => call?.unpin(sessionId) : undefined, className: "str-video__participant-details__name--pinned" })), indicatorsVisible && jsx(SpeechIndicator, {})] }) }), indicatorsVisible && (jsx(Notification, { state: "error", isVisible: isLocalParticipant &&
89
+ connectionQuality === SfuModels.ConnectionQuality.POOR, message: t('participantView.connectionQuality.poor.text', 'Poor connection quality. Please check your internet connection.'), children: connectionQuality && (jsx(ConnectionQualityIndicator, { quality: connectionQuality })) }))] }));
86
90
  };
87
91
  const SpeechIndicator = () => {
88
92
  const { participant } = useParticipantViewContext();
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultParticipantViewUI.js","sources":["../../../../../../../../src/core/components/ParticipantView/DefaultParticipantViewUI.tsx"],"sourcesContent":["import { ComponentType, forwardRef } from 'react';\nimport { Placement } from '@floating-ui/react';\nimport {\n hasAudio,\n hasPausedTrack,\n hasScreenShare,\n hasVideo,\n SfuModels,\n} from '@stream-io/video-client';\nimport {\n useCall,\n useCallStateHooks,\n useI18n,\n useIsAudioConnecting,\n useIsVideoConnecting,\n} from '@stream-io/video-react-bindings';\nimport clsx from 'clsx';\n\nimport {\n Icon,\n IconButton,\n LoadingIndicator,\n MenuToggle,\n Notification,\n ToggleMenuButtonProps,\n} from '../../../components';\nimport { ParticipantActionsContextMenu as DefaultParticipantActionsContextMenu } from './ParticipantActionsContextMenu';\nimport { Reaction } from '../../../components/Reaction';\nimport { useParticipantViewContext } from './ParticipantViewContext';\n\nexport type DefaultParticipantViewUIProps = {\n /**\n * Turns on/off the status indicator icons (mute, connection quality, etc...).\n */\n indicatorsVisible?: boolean;\n /**\n * Placement of the context menu component when opened\n */\n menuPlacement?: Placement;\n /**\n * Option to show/hide menu button component\n */\n showMenuButton?: boolean;\n /**\n * Custom component to render the context menu\n */\n ParticipantActionsContextMenu?: ComponentType;\n /**\n * Rendered over the tile when this participant's audio is blocked by the\n * browser's autoplay policy. Selecting it calls {@link Call.resumeAudio} to\n * unblock audio. Defaults to\n * {@link DefaultAudioBlockedNotification}; pass `null` to disable.\n */\n AudioBlockedNotification?: ComponentType | null;\n};\n\nconst ToggleButton = forwardRef<HTMLButtonElement, ToggleMenuButtonProps>(\n function ToggleButtonRender(props, ref) {\n return <IconButton enabled={props.menuShown} icon=\"ellipsis\" ref={ref} />;\n },\n);\n\nexport const DefaultScreenShareOverlay = () => {\n const call = useCall();\n const { t } = useI18n();\n\n const stopScreenShare = () => {\n call?.screenShare.disable().catch((err) => {\n console.error('Failed to stop screen sharing:', err);\n });\n };\n\n return (\n <div className=\"str-video__screen-share-overlay\">\n <Icon icon=\"screen-share-off\" />\n <span className=\"str-video__screen-share-overlay__title\">\n {t('You are presenting your screen')}\n </span>\n <button\n onClick={stopScreenShare}\n type=\"button\"\n className=\"str-video__screen-share-overlay__button\"\n >\n <Icon icon=\"close\" /> {t('Stop Screen Sharing')}\n </button>\n </div>\n );\n};\n\n/**\n * Rendered over a remote participant's tile when the browser's autoplay policy\n * has blocked their audio. Selecting it calls `call.resumeAudio()`, unblocking\n * every blocked element at once.\n */\nexport const DefaultAudioBlockedNotification = () => {\n const call = useCall();\n const { t } = useI18n();\n\n return (\n <button\n type=\"button\"\n className=\"str-video__audio-blocked-notification\"\n onClick={call?.resumeAudio}\n aria-live=\"polite\"\n >\n <span className=\"str-video__audio-blocked-notification__message\">\n <Icon icon=\"speaker\" />\n <span className=\"str-video__audio-blocked-notification__text\">\n <span className=\"str-video__audio-blocked-notification__title\">\n {t('Audio is blocked by your system')}\n </span>\n <span className=\"str-video__audio-blocked-notification__subtitle\">\n {t('Click or tap to play audio')}\n </span>\n </span>\n </span>\n </button>\n );\n};\n\nexport const DefaultParticipantViewUI = ({\n indicatorsVisible = true,\n menuPlacement = 'bottom-start',\n showMenuButton = true,\n ParticipantActionsContextMenu = DefaultParticipantActionsContextMenu,\n AudioBlockedNotification = DefaultAudioBlockedNotification,\n}: DefaultParticipantViewUIProps) => {\n const { participant, trackType } = useParticipantViewContext();\n const { useAutoplayBlockedSessionIds } = useCallStateHooks();\n const blockedSessionIds = useAutoplayBlockedSessionIds();\n const isScreenSharing = hasScreenShare(participant);\n const shouldShowAudioBlockedNotification =\n !participant.isLocalParticipant &&\n trackType !== 'screenShareTrack' &&\n blockedSessionIds.includes(participant.sessionId);\n\n if (\n participant.isLocalParticipant &&\n isScreenSharing &&\n trackType === 'screenShareTrack'\n ) {\n return (\n <>\n <DefaultScreenShareOverlay />\n <ParticipantDetails indicatorsVisible={indicatorsVisible} />\n </>\n );\n }\n\n return (\n <>\n {showMenuButton && (\n <MenuToggle\n strategy=\"fixed\"\n placement={menuPlacement}\n ToggleButton={ToggleButton}\n >\n <ParticipantActionsContextMenu />\n </MenuToggle>\n )}\n <Reaction participant={participant} />\n <ParticipantDetails indicatorsVisible={indicatorsVisible} />\n {AudioBlockedNotification && shouldShowAudioBlockedNotification && (\n <AudioBlockedNotification />\n )}\n </>\n );\n};\n\nexport const ParticipantDetails = ({\n indicatorsVisible = true,\n}: Pick<DefaultParticipantViewUIProps, 'indicatorsVisible'>) => {\n const { participant, trackType } = useParticipantViewContext();\n const {\n isLocalParticipant,\n connectionQuality,\n pin,\n sessionId,\n name,\n userId,\n } = participant;\n const call = useCall();\n\n const { t } = useI18n();\n const connectionQualityAsString =\n !!connectionQuality &&\n SfuModels.ConnectionQuality[connectionQuality].toLowerCase();\n\n const hasAudioTrack = hasAudio(participant);\n const hasVideoTrack = hasVideo(participant);\n const canUnpin = !!pin && pin.isLocalPin;\n const isTrackPaused =\n trackType !== 'none' ? hasPausedTrack(participant, trackType) : false;\n\n const isAudioConnecting = useIsAudioConnecting(participant);\n const isVideoConnecting = useIsVideoConnecting(participant);\n\n return (\n <>\n <div className=\"str-video__participant-details\">\n <div className=\"str-video__participant-details__name\">\n {name || userId}\n {indicatorsVisible && isAudioConnecting && (\n <LoadingIndicator\n className=\"str-video__participant-details__name--audio-connecting\"\n tooltip={t('Audio is connecting...')}\n />\n )}\n {indicatorsVisible && !hasAudioTrack && (\n <span className=\"str-video__participant-details__name--audio-muted\" />\n )}\n {indicatorsVisible && isVideoConnecting && (\n <LoadingIndicator\n className=\"str-video__participant-details__name--video-connecting\"\n tooltip={t('Video is connecting...')}\n />\n )}\n {indicatorsVisible && !hasVideoTrack && (\n <span className=\"str-video__participant-details__name--video-muted\" />\n )}\n {indicatorsVisible && isTrackPaused && (\n <span\n title={t('Video paused due to insufficient bandwidth')}\n className=\"str-video__participant-details__name--track-paused\"\n />\n )}\n {indicatorsVisible && pin && (\n <span\n title={canUnpin ? t('Unpin') : t('Pinned')}\n onClick={canUnpin ? () => call?.unpin(sessionId) : undefined}\n className=\"str-video__participant-details__name--pinned\"\n />\n )}\n {indicatorsVisible && <SpeechIndicator />}\n </div>\n </div>\n {indicatorsVisible && (\n <Notification\n isVisible={\n isLocalParticipant &&\n connectionQuality === SfuModels.ConnectionQuality.POOR\n }\n message={t('Poor connection quality')}\n >\n {connectionQualityAsString && (\n <span\n className={clsx(\n 'str-video__participant-details__connection-quality',\n `str-video__participant-details__connection-quality--${connectionQualityAsString}`,\n )}\n title={connectionQualityAsString}\n />\n )}\n </Notification>\n )}\n </>\n );\n};\n\nexport const SpeechIndicator = () => {\n const { participant } = useParticipantViewContext();\n const { isSpeaking, isDominantSpeaker } = participant;\n return (\n <span\n className={clsx(\n 'str-video__speech-indicator',\n isSpeaking && 'str-video__speech-indicator--speaking',\n isDominantSpeaker && 'str-video__speech-indicator--dominant',\n )}\n >\n <span className=\"str-video__speech-indicator__bar\" />\n <span className=\"str-video__speech-indicator__bar\" />\n <span className=\"str-video__speech-indicator__bar\" />\n </span>\n );\n};\n"],"names":["_jsx","_jsxs","ParticipantActionsContextMenu","DefaultParticipantActionsContextMenu","_Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"DefaultParticipantViewUI.js","sources":["../../../../../../../../src/core/components/ParticipantView/DefaultParticipantViewUI.tsx"],"sourcesContent":["import { ComponentType, forwardRef } from 'react';\nimport { Placement } from '@floating-ui/react';\nimport {\n hasAudio,\n hasPausedTrack,\n hasScreenShare,\n hasVideo,\n SfuModels,\n} from '@stream-io/video-client';\nimport {\n useCall,\n useCallStateHooks,\n useIsAudioConnecting,\n useIsVideoConnecting,\n} from '@stream-io/video-react-bindings';\nimport { useI18n } from '../../../i18n';\nimport clsx from 'clsx';\n\nimport {\n Button,\n Icon,\n IconButton,\n LoadingIndicator,\n MenuToggle,\n Notification,\n ToggleMenuButtonProps,\n} from '../../../components';\nimport { ParticipantActionsContextMenu as DefaultParticipantActionsContextMenu } from './ParticipantActionsContextMenu';\nimport { ConnectionQualityIndicator } from './ConnectionQualityIndicator';\nimport { Reaction } from '../../../components/Reaction';\nimport { useParticipantViewContext } from './ParticipantViewContext';\n\nexport type DefaultParticipantViewUIProps = {\n /**\n * Turns on/off the status indicator icons (mute, connection quality, etc...).\n */\n indicatorsVisible?: boolean;\n /**\n * Placement of the context menu component when opened\n */\n menuPlacement?: Placement;\n /**\n * Option to show/hide menu button component\n */\n showMenuButton?: boolean;\n /**\n * Custom component to render the context menu\n */\n ParticipantActionsContextMenu?: ComponentType;\n /**\n * Rendered over the tile when this participant's audio is blocked by the\n * browser's autoplay policy. Selecting it calls {@link Call.resumeAudio} to\n * unblock audio. Defaults to\n * {@link DefaultAudioBlockedNotification}; pass `null` to disable.\n */\n AudioBlockedNotification?: ComponentType | null;\n};\n\nconst ToggleButton = forwardRef<HTMLButtonElement, ToggleMenuButtonProps>(\n function ToggleButtonRender(props, ref) {\n const { t } = useI18n();\n\n return (\n <IconButton\n className=\"str-video__participant-view__menu-button\"\n active={props.menuShown}\n size=\"sm\"\n variant=\"secondary\"\n ref={ref}\n title={t('participantView.moreOptions.title', 'More options')}\n icon=\"ellipsis\"\n />\n );\n },\n);\n\nexport const DefaultScreenShareOverlay = () => {\n const call = useCall();\n const { t } = useI18n();\n\n const stopScreenShare = () => {\n call?.screenShare.disable().catch((err) => {\n console.error('Failed to stop screen sharing:', err);\n });\n };\n\n return (\n <div className=\"str-video__screen-share-overlay\">\n <Icon icon=\"screen-share-off\" />\n <span className=\"str-video__screen-share-overlay__title\">\n {t(\n 'common.presentingYourScreen.text',\n 'You are presenting your screen',\n )}\n </span>\n <Button\n variant=\"destructive\"\n onClick={stopScreenShare}\n className=\"str-video__screen-share-overlay__button\"\n >\n <Icon icon=\"close\" />{' '}\n {t('participantView.stopScreenSharing.label', 'Stop Screen Sharing')}\n </Button>\n </div>\n );\n};\n\n/**\n * Rendered over a remote participant's tile when the browser's autoplay policy\n * has blocked their audio. Selecting it calls `call.resumeAudio()`, unblocking\n * every blocked element at once.\n */\nexport const DefaultAudioBlockedNotification = () => {\n const call = useCall();\n const { t } = useI18n();\n\n return (\n <button\n type=\"button\"\n className=\"str-video__audio-blocked-notification\"\n onClick={call?.resumeAudio}\n aria-live=\"polite\"\n >\n <span className=\"str-video__audio-blocked-notification__message\">\n <Icon icon=\"speaker\" />\n <span className=\"str-video__audio-blocked-notification__text\">\n <span className=\"str-video__audio-blocked-notification__title\">\n {t(\n 'participantView.audioBlocked.title',\n 'Audio is blocked by your system',\n )}\n </span>\n <span className=\"str-video__audio-blocked-notification__subtitle\">\n {t(\n 'participantView.audioBlocked.description',\n 'Click or tap to play audio',\n )}\n </span>\n </span>\n </span>\n </button>\n );\n};\n\nexport const DefaultParticipantViewUI = ({\n indicatorsVisible = true,\n menuPlacement = 'bottom-start',\n showMenuButton = true,\n ParticipantActionsContextMenu = DefaultParticipantActionsContextMenu,\n AudioBlockedNotification = DefaultAudioBlockedNotification,\n}: DefaultParticipantViewUIProps) => {\n const { participant, trackType } = useParticipantViewContext();\n const { useAutoplayBlockedSessionIds } = useCallStateHooks();\n const blockedSessionIds = useAutoplayBlockedSessionIds();\n const isScreenSharing = hasScreenShare(participant);\n const shouldShowAudioBlockedNotification =\n !participant.isLocalParticipant &&\n trackType !== 'screenShareTrack' &&\n blockedSessionIds.includes(participant.sessionId);\n\n if (\n participant.isLocalParticipant &&\n isScreenSharing &&\n trackType === 'screenShareTrack'\n ) {\n return (\n <>\n <DefaultScreenShareOverlay />\n <ParticipantDetails indicatorsVisible={indicatorsVisible} />\n </>\n );\n }\n\n return (\n <>\n {showMenuButton && (\n <MenuToggle\n strategy=\"fixed\"\n placement={menuPlacement}\n ToggleButton={ToggleButton}\n >\n <ParticipantActionsContextMenu />\n </MenuToggle>\n )}\n <Reaction participant={participant} />\n <ParticipantDetails indicatorsVisible={indicatorsVisible} />\n {AudioBlockedNotification && shouldShowAudioBlockedNotification && (\n <AudioBlockedNotification />\n )}\n </>\n );\n};\n\nexport const ParticipantDetails = ({\n indicatorsVisible = true,\n}: Pick<DefaultParticipantViewUIProps, 'indicatorsVisible'>) => {\n const { participant, trackType } = useParticipantViewContext();\n const {\n isLocalParticipant,\n connectionQuality,\n pin,\n sessionId,\n name,\n userId,\n } = participant;\n const call = useCall();\n\n const { t } = useI18n();\n const hasAudioTrack = hasAudio(participant);\n const hasVideoTrack = hasVideo(participant);\n const canUnpin = !!pin && pin.isLocalPin;\n const isTrackPaused =\n trackType !== 'none' ? hasPausedTrack(participant, trackType) : false;\n\n const isAudioConnecting = useIsAudioConnecting(participant);\n const isVideoConnecting = useIsVideoConnecting(participant);\n\n return (\n <>\n <div className=\"str-video__participant-details\">\n <div className=\"str-video__participant-details__name\">\n <span className=\"str-video__participant-details__name-text\">\n {name || userId}\n </span>\n {indicatorsVisible && isAudioConnecting && (\n <LoadingIndicator\n className=\"str-video__participant-details__name--audio-connecting\"\n tooltip={t(\n 'participantView.audioConnecting.title',\n 'Audio is connecting...',\n )}\n />\n )}\n {indicatorsVisible && !hasAudioTrack && (\n <span className=\"str-video__participant-details__name--audio-muted\" />\n )}\n {indicatorsVisible && isVideoConnecting && (\n <LoadingIndicator\n className=\"str-video__participant-details__name--video-connecting\"\n tooltip={t(\n 'participantView.videoConnecting.title',\n 'Video is connecting...',\n )}\n />\n )}\n {indicatorsVisible && !hasVideoTrack && (\n <span className=\"str-video__participant-details__name--video-muted\" />\n )}\n {indicatorsVisible && isTrackPaused && (\n <span\n title={t(\n 'participantView.videoPausedInsufficientBandwidth.title',\n 'Video paused due to insufficient bandwidth',\n )}\n className=\"str-video__participant-details__name--track-paused\"\n />\n )}\n {indicatorsVisible && pin && (\n <span\n title={\n canUnpin\n ? t('participantView.unpin.label', 'Unpin')\n : t('participantList.pinned.title', 'Pinned')\n }\n onClick={canUnpin ? () => call?.unpin(sessionId) : undefined}\n className=\"str-video__participant-details__name--pinned\"\n />\n )}\n {indicatorsVisible && <SpeechIndicator />}\n </div>\n </div>\n {indicatorsVisible && (\n <Notification\n state=\"error\"\n isVisible={\n isLocalParticipant &&\n connectionQuality === SfuModels.ConnectionQuality.POOR\n }\n message={t(\n 'participantView.connectionQuality.poor.text',\n 'Poor connection quality. Please check your internet connection.',\n )}\n >\n {connectionQuality && (\n <ConnectionQualityIndicator quality={connectionQuality} />\n )}\n </Notification>\n )}\n </>\n );\n};\n\nexport const SpeechIndicator = () => {\n const { participant } = useParticipantViewContext();\n const { isSpeaking, isDominantSpeaker } = participant;\n return (\n <span\n className={clsx(\n 'str-video__speech-indicator',\n isSpeaking && 'str-video__speech-indicator--speaking',\n isDominantSpeaker && 'str-video__speech-indicator--dominant',\n )}\n >\n <span className=\"str-video__speech-indicator__bar\" />\n <span className=\"str-video__speech-indicator__bar\" />\n <span className=\"str-video__speech-indicator__bar\" />\n </span>\n );\n};\n"],"names":["_jsx","_jsxs","ParticipantActionsContextMenu","DefaultParticipantActionsContextMenu","_Fragment"],"mappings":"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"}