@stream-io/video-react-sdk 1.40.2 → 1.42.0

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 (312) hide show
  1. package/CHANGELOG.md +33 -4
  2. package/dist/embedded.cjs.js +4 -4
  3. package/dist/embedded.cjs.js.map +1 -1
  4. package/dist/esm/embedded.js +3 -0
  5. package/dist/esm/embedded.js.map +1 -0
  6. package/dist/esm/index.js +92 -0
  7. package/dist/esm/index.js.map +1 -0
  8. package/dist/esm/src/components/Avatar/Avatar.js +14 -0
  9. package/dist/esm/src/components/Avatar/Avatar.js.map +1 -0
  10. package/dist/{background-filters-D2U5UBbH.es.js → esm/src/components/BackgroundFilters/BackgroundFilters.js} +1 -1
  11. package/dist/esm/src/components/BackgroundFilters/BackgroundFilters.js.map +1 -0
  12. package/dist/esm/src/components/BackgroundFilters/BackgroundFiltersProvider.js +33 -0
  13. package/dist/esm/src/components/BackgroundFilters/BackgroundFiltersProvider.js.map +1 -0
  14. package/dist/esm/src/components/Button/CompositeButton.js +29 -0
  15. package/dist/esm/src/components/Button/CompositeButton.js.map +1 -0
  16. package/dist/esm/src/components/Button/IconButton.js +18 -0
  17. package/dist/esm/src/components/Button/IconButton.js.map +1 -0
  18. package/dist/esm/src/components/Button/TextButton.js +8 -0
  19. package/dist/esm/src/components/Button/TextButton.js.map +1 -0
  20. package/dist/esm/src/components/CallControls/AcceptCallButton.js +28 -0
  21. package/dist/esm/src/components/CallControls/AcceptCallButton.js.map +1 -0
  22. package/dist/esm/src/components/CallControls/CallControls.js +21 -0
  23. package/dist/esm/src/components/CallControls/CallControls.js.map +1 -0
  24. package/dist/esm/src/components/CallControls/CallStatsButton.js +18 -0
  25. package/dist/esm/src/components/CallControls/CallStatsButton.js.map +1 -0
  26. package/dist/esm/src/components/CallControls/CancelCallButton.js +78 -0
  27. package/dist/esm/src/components/CallControls/CancelCallButton.js.map +1 -0
  28. package/dist/esm/src/components/CallControls/ReactionsButton.js +61 -0
  29. package/dist/esm/src/components/CallControls/ReactionsButton.js.map +1 -0
  30. package/dist/esm/src/components/CallControls/RecordCallButton.js +64 -0
  31. package/dist/esm/src/components/CallControls/RecordCallButton.js.map +1 -0
  32. package/dist/esm/src/components/CallControls/ScreenShareButton.js +44 -0
  33. package/dist/esm/src/components/CallControls/ScreenShareButton.js.map +1 -0
  34. package/dist/esm/src/components/CallControls/ToggleAudioButton.js +72 -0
  35. package/dist/esm/src/components/CallControls/ToggleAudioButton.js.map +1 -0
  36. package/dist/esm/src/components/CallControls/ToggleAudioOutputButton.js +27 -0
  37. package/dist/esm/src/components/CallControls/ToggleAudioOutputButton.js.map +1 -0
  38. package/dist/esm/src/components/CallControls/ToggleVideoButton.js +81 -0
  39. package/dist/esm/src/components/CallControls/ToggleVideoButton.js.map +1 -0
  40. package/dist/esm/src/components/CallParticipantsList/BlockedUserListing.js +23 -0
  41. package/dist/esm/src/components/CallParticipantsList/BlockedUserListing.js.map +1 -0
  42. package/dist/esm/src/components/CallParticipantsList/CallParticipantListHeader.js +15 -0
  43. package/dist/esm/src/components/CallParticipantsList/CallParticipantListHeader.js.map +1 -0
  44. package/dist/esm/src/components/CallParticipantsList/CallParticipantListing.js +7 -0
  45. package/dist/esm/src/components/CallParticipantsList/CallParticipantListing.js.map +1 -0
  46. package/dist/esm/src/components/CallParticipantsList/CallParticipantListingItem.js +46 -0
  47. package/dist/esm/src/components/CallParticipantsList/CallParticipantListingItem.js.map +1 -0
  48. package/dist/esm/src/components/CallParticipantsList/CallParticipantsList.js +81 -0
  49. package/dist/esm/src/components/CallParticipantsList/CallParticipantsList.js.map +1 -0
  50. package/dist/esm/src/components/CallParticipantsList/EmptyParticipantSearchList.js +10 -0
  51. package/dist/esm/src/components/CallParticipantsList/EmptyParticipantSearchList.js.map +1 -0
  52. package/dist/esm/src/components/CallPreview/CallPreview.js +24 -0
  53. package/dist/esm/src/components/CallPreview/CallPreview.js.map +1 -0
  54. package/dist/esm/src/components/CallRecordingList/CallRecordingList.js +12 -0
  55. package/dist/esm/src/components/CallRecordingList/CallRecordingList.js.map +1 -0
  56. package/dist/esm/src/components/CallRecordingList/CallRecordingListHeader.js +12 -0
  57. package/dist/esm/src/components/CallRecordingList/CallRecordingListHeader.js.map +1 -0
  58. package/dist/esm/src/components/CallRecordingList/CallRecordingListItem.js +14 -0
  59. package/dist/esm/src/components/CallRecordingList/CallRecordingListItem.js.map +1 -0
  60. package/dist/esm/src/components/CallRecordingList/EmptyCallRecordingListing.js +8 -0
  61. package/dist/esm/src/components/CallRecordingList/EmptyCallRecordingListing.js.map +1 -0
  62. package/dist/esm/src/components/CallRecordingList/LoadingCallRecordingListing.js +10 -0
  63. package/dist/esm/src/components/CallRecordingList/LoadingCallRecordingListing.js.map +1 -0
  64. package/dist/esm/src/components/CallStats/CallStats.js +180 -0
  65. package/dist/esm/src/components/CallStats/CallStats.js.map +1 -0
  66. package/dist/{latency-chart-Bj5OSYzg.es.js → esm/src/components/CallStats/CallStatsLatencyChart.js} +1 -1
  67. package/dist/esm/src/components/CallStats/CallStatsLatencyChart.js.map +1 -0
  68. package/dist/esm/src/components/DeviceSettings/AudioVolumeIndicator.js +27 -0
  69. package/dist/esm/src/components/DeviceSettings/AudioVolumeIndicator.js.map +1 -0
  70. package/dist/esm/src/components/DeviceSettings/DeviceAudioPreviewItem.js +42 -0
  71. package/dist/esm/src/components/DeviceSettings/DeviceAudioPreviewItem.js.map +1 -0
  72. package/dist/esm/src/components/DeviceSettings/DeviceSelector.js +67 -0
  73. package/dist/esm/src/components/DeviceSettings/DeviceSelector.js.map +1 -0
  74. package/dist/esm/src/components/DeviceSettings/DeviceSelectorAudio.js +26 -0
  75. package/dist/esm/src/components/DeviceSettings/DeviceSelectorAudio.js.map +1 -0
  76. package/dist/esm/src/components/DeviceSettings/DeviceSelectorVideo.js +15 -0
  77. package/dist/esm/src/components/DeviceSettings/DeviceSelectorVideo.js.map +1 -0
  78. package/dist/esm/src/components/DeviceSettings/DeviceSettings.js +26 -0
  79. package/dist/esm/src/components/DeviceSettings/DeviceSettings.js.map +1 -0
  80. package/dist/esm/src/components/DeviceSettings/DeviceVideoPreviewItem.js +42 -0
  81. package/dist/esm/src/components/DeviceSettings/DeviceVideoPreviewItem.js.map +1 -0
  82. package/dist/esm/src/components/DeviceSettings/SpeakerTest.js +57 -0
  83. package/dist/esm/src/components/DeviceSettings/SpeakerTest.js.map +1 -0
  84. package/dist/esm/src/components/DropdownSelect/DropdownSelect.js +79 -0
  85. package/dist/esm/src/components/DropdownSelect/DropdownSelect.js.map +1 -0
  86. package/dist/esm/src/components/Icon/Icon.js +7 -0
  87. package/dist/esm/src/components/Icon/Icon.js.map +1 -0
  88. package/dist/esm/src/components/LoadingIndicator/LoadingIndicator.js +9 -0
  89. package/dist/esm/src/components/LoadingIndicator/LoadingIndicator.js.map +1 -0
  90. package/dist/esm/src/components/Menu/GenericMenu.js +19 -0
  91. package/dist/esm/src/components/Menu/GenericMenu.js.map +1 -0
  92. package/dist/esm/src/components/Menu/MenuToggle.js +75 -0
  93. package/dist/esm/src/components/Menu/MenuToggle.js.map +1 -0
  94. package/dist/esm/src/components/NoiseCancellation/NoiseCancellationProvider.js +96 -0
  95. package/dist/esm/src/components/NoiseCancellation/NoiseCancellationProvider.js.map +1 -0
  96. package/dist/esm/src/components/Notification/MicCaptureErrorNotification.js +23 -0
  97. package/dist/esm/src/components/Notification/MicCaptureErrorNotification.js.map +1 -0
  98. package/dist/esm/src/components/Notification/Notification.js +31 -0
  99. package/dist/esm/src/components/Notification/Notification.js.map +1 -0
  100. package/dist/esm/src/components/Notification/PermissionNotification.js +32 -0
  101. package/dist/esm/src/components/Notification/PermissionNotification.js.map +1 -0
  102. package/dist/esm/src/components/Notification/RecordingInProgressNotification.js +23 -0
  103. package/dist/esm/src/components/Notification/RecordingInProgressNotification.js.map +1 -0
  104. package/dist/esm/src/components/Notification/SpeakingWhileMutedNotification.js +14 -0
  105. package/dist/esm/src/components/Notification/SpeakingWhileMutedNotification.js.map +1 -0
  106. package/dist/esm/src/components/Permissions/PermissionRequests.js +99 -0
  107. package/dist/esm/src/components/Permissions/PermissionRequests.js.map +1 -0
  108. package/dist/esm/src/components/Reaction/Reaction.js +32 -0
  109. package/dist/esm/src/components/Reaction/Reaction.js.map +1 -0
  110. package/dist/esm/src/components/RingingCall/RingingCall.js +48 -0
  111. package/dist/esm/src/components/RingingCall/RingingCall.js.map +1 -0
  112. package/dist/esm/src/components/RingingCall/RingingCallControls.js +34 -0
  113. package/dist/esm/src/components/RingingCall/RingingCallControls.js.map +1 -0
  114. package/dist/esm/src/components/Search/SearchInput.js +27 -0
  115. package/dist/esm/src/components/Search/SearchInput.js.map +1 -0
  116. package/dist/esm/src/components/Search/SearchResults.js +15 -0
  117. package/dist/esm/src/components/Search/SearchResults.js.map +1 -0
  118. package/dist/esm/src/components/Search/hooks/useSearch.js +38 -0
  119. package/dist/esm/src/components/Search/hooks/useSearch.js.map +1 -0
  120. package/dist/esm/src/components/StreamTheme/StreamTheme.js +9 -0
  121. package/dist/esm/src/components/StreamTheme/StreamTheme.js.map +1 -0
  122. package/dist/esm/src/components/Tooltip/Tooltip.js +29 -0
  123. package/dist/esm/src/components/Tooltip/Tooltip.js.map +1 -0
  124. package/dist/esm/src/components/Tooltip/WithTooltip.js +15 -0
  125. package/dist/esm/src/components/Tooltip/WithTooltip.js.map +1 -0
  126. package/dist/esm/src/components/Tooltip/hooks/useEnterLeaveHandlers.js +17 -0
  127. package/dist/esm/src/components/Tooltip/hooks/useEnterLeaveHandlers.js.map +1 -0
  128. package/dist/esm/src/components/VideoPreview/VideoPreview.js +37 -0
  129. package/dist/esm/src/components/VideoPreview/VideoPreview.js.map +1 -0
  130. package/dist/esm/src/core/components/Audio/Audio.js +22 -0
  131. package/dist/esm/src/core/components/Audio/Audio.js.map +1 -0
  132. package/dist/esm/src/core/components/Audio/ParticipantsAudio.js +23 -0
  133. package/dist/esm/src/core/components/Audio/ParticipantsAudio.js.map +1 -0
  134. package/dist/esm/src/core/components/CallLayout/LivestreamLayout.js +150 -0
  135. package/dist/esm/src/core/components/CallLayout/LivestreamLayout.js.map +1 -0
  136. package/dist/esm/src/core/components/CallLayout/PaginatedGridLayout.js +79 -0
  137. package/dist/esm/src/core/components/CallLayout/PaginatedGridLayout.js.map +1 -0
  138. package/dist/esm/src/core/components/CallLayout/PipLayout/Grid.js +80 -0
  139. package/dist/esm/src/core/components/CallLayout/PipLayout/Grid.js.map +1 -0
  140. package/dist/esm/src/core/components/CallLayout/PipLayout/Host.js +13 -0
  141. package/dist/esm/src/core/components/CallLayout/PipLayout/Host.js.map +1 -0
  142. package/dist/esm/src/core/components/CallLayout/PipLayout/Pip.js +57 -0
  143. package/dist/esm/src/core/components/CallLayout/PipLayout/Pip.js.map +1 -0
  144. package/dist/esm/src/core/components/CallLayout/PipLayout/index.js +8 -0
  145. package/dist/esm/src/core/components/CallLayout/PipLayout/index.js.map +1 -0
  146. package/dist/esm/src/core/components/CallLayout/SpeakerLayout.js +103 -0
  147. package/dist/esm/src/core/components/CallLayout/SpeakerLayout.js.map +1 -0
  148. package/dist/esm/src/core/components/CallLayout/hooks.js +62 -0
  149. package/dist/esm/src/core/components/CallLayout/hooks.js.map +1 -0
  150. package/dist/esm/src/core/components/ParticipantView/DefaultParticipantViewUI.js +94 -0
  151. package/dist/esm/src/core/components/ParticipantView/DefaultParticipantViewUI.js.map +1 -0
  152. package/dist/esm/src/core/components/ParticipantView/ParticipantActionsContextMenu.js +97 -0
  153. package/dist/esm/src/core/components/ParticipantView/ParticipantActionsContextMenu.js.map +1 -0
  154. package/dist/esm/src/core/components/ParticipantView/ParticipantView.js +65 -0
  155. package/dist/esm/src/core/components/ParticipantView/ParticipantView.js.map +1 -0
  156. package/dist/esm/src/core/components/ParticipantView/ParticipantViewContext.js +7 -0
  157. package/dist/esm/src/core/components/ParticipantView/ParticipantViewContext.js.map +1 -0
  158. package/dist/esm/src/core/components/StreamCall/StreamCall.js +8 -0
  159. package/dist/esm/src/core/components/StreamCall/StreamCall.js.map +1 -0
  160. package/dist/esm/src/core/components/StreamVideo/StreamVideo.js +11 -0
  161. package/dist/esm/src/core/components/StreamVideo/StreamVideo.js.map +1 -0
  162. package/dist/esm/src/core/components/Video/BaseVideo.js +41 -0
  163. package/dist/esm/src/core/components/Video/BaseVideo.js.map +1 -0
  164. package/dist/esm/src/core/components/Video/BaseVideoPlaceholder.js +21 -0
  165. package/dist/esm/src/core/components/Video/BaseVideoPlaceholder.js.map +1 -0
  166. package/dist/esm/src/core/components/Video/DefaultPictureInPicturePlaceholder.js +12 -0
  167. package/dist/esm/src/core/components/Video/DefaultPictureInPicturePlaceholder.js.map +1 -0
  168. package/dist/esm/src/core/components/Video/DefaultVideoPlaceholder.js +12 -0
  169. package/dist/esm/src/core/components/Video/DefaultVideoPlaceholder.js.map +1 -0
  170. package/dist/esm/src/core/components/Video/Video.js +88 -0
  171. package/dist/esm/src/core/components/Video/Video.js.map +1 -0
  172. package/dist/esm/src/core/hooks/useCalculateHardLimit.js +59 -0
  173. package/dist/esm/src/core/hooks/useCalculateHardLimit.js.map +1 -0
  174. package/dist/esm/src/core/hooks/usePictureInPictureState.js +24 -0
  175. package/dist/esm/src/core/hooks/usePictureInPictureState.js.map +1 -0
  176. package/dist/esm/src/core/hooks/useTrackElementVisibility.js +14 -0
  177. package/dist/esm/src/core/hooks/useTrackElementVisibility.js.map +1 -0
  178. package/dist/esm/src/embedded/EmbeddedClientProvider.js +83 -0
  179. package/dist/esm/src/embedded/EmbeddedClientProvider.js.map +1 -0
  180. package/dist/esm/src/embedded/call/CallControls.js +65 -0
  181. package/dist/esm/src/embedded/call/CallControls.js.map +1 -0
  182. package/dist/esm/src/embedded/call/CallHeader.js +57 -0
  183. package/dist/esm/src/embedded/call/CallHeader.js.map +1 -0
  184. package/dist/esm/src/embedded/call/CallLayout.js +63 -0
  185. package/dist/esm/src/embedded/call/CallLayout.js.map +1 -0
  186. package/dist/esm/src/embedded/call/CallStateRouter.js +87 -0
  187. package/dist/esm/src/embedded/call/CallStateRouter.js.map +1 -0
  188. package/dist/esm/src/embedded/call/EmbeddedCall.js +12 -0
  189. package/dist/esm/src/embedded/call/EmbeddedCall.js.map +1 -0
  190. package/dist/esm/src/embedded/context/ConfigurationContext.js +21 -0
  191. package/dist/esm/src/embedded/context/ConfigurationContext.js.map +1 -0
  192. package/dist/esm/src/embedded/hooks/useCallDuration.js +32 -0
  193. package/dist/esm/src/embedded/hooks/useCallDuration.js.map +1 -0
  194. package/dist/esm/src/embedded/hooks/useEmbeddedClient.js +40 -0
  195. package/dist/esm/src/embedded/hooks/useEmbeddedClient.js.map +1 -0
  196. package/dist/esm/src/embedded/hooks/useInitializeCall.js +39 -0
  197. package/dist/esm/src/embedded/hooks/useInitializeCall.js.map +1 -0
  198. package/dist/esm/src/embedded/hooks/useInitializeVideoClient.js +93 -0
  199. package/dist/esm/src/embedded/hooks/useInitializeVideoClient.js.map +1 -0
  200. package/dist/esm/src/embedded/hooks/useIsLivestreamPaused.js +42 -0
  201. package/dist/esm/src/embedded/hooks/useIsLivestreamPaused.js.map +1 -0
  202. package/dist/esm/src/embedded/hooks/useLayout.js +122 -0
  203. package/dist/esm/src/embedded/hooks/useLayout.js.map +1 -0
  204. package/dist/esm/src/embedded/hooks/useNoiseCancellationLoader.js +48 -0
  205. package/dist/esm/src/embedded/hooks/useNoiseCancellationLoader.js.map +1 -0
  206. package/dist/esm/src/embedded/hooks/useWakeLock.js +34 -0
  207. package/dist/esm/src/embedded/hooks/useWakeLock.js.map +1 -0
  208. package/dist/esm/src/embedded/livestream/EmbeddedLivestream.js +11 -0
  209. package/dist/esm/src/embedded/livestream/EmbeddedLivestream.js.map +1 -0
  210. package/dist/esm/src/embedded/livestream/LivestreamUI.js +17 -0
  211. package/dist/esm/src/embedded/livestream/LivestreamUI.js.map +1 -0
  212. package/dist/esm/src/embedded/livestream/host/HostLayout.js +76 -0
  213. package/dist/esm/src/embedded/livestream/host/HostLayout.js.map +1 -0
  214. package/dist/esm/src/embedded/livestream/host/HostStateRouter.js +110 -0
  215. package/dist/esm/src/embedded/livestream/host/HostStateRouter.js.map +1 -0
  216. package/dist/esm/src/embedded/livestream/viewer/ViewerLayout.js +74 -0
  217. package/dist/esm/src/embedded/livestream/viewer/ViewerLayout.js.map +1 -0
  218. package/dist/esm/src/embedded/livestream/viewer/ViewerLobby.js +109 -0
  219. package/dist/esm/src/embedded/livestream/viewer/ViewerLobby.js.map +1 -0
  220. package/dist/esm/src/embedded/livestream/viewer/ViewerStateRouter.js +105 -0
  221. package/dist/esm/src/embedded/livestream/viewer/ViewerStateRouter.js.map +1 -0
  222. package/dist/esm/src/embedded/shared/BlurToggleButton/BlurToggleButton.js +65 -0
  223. package/dist/esm/src/embedded/shared/BlurToggleButton/BlurToggleButton.js.map +1 -0
  224. package/dist/esm/src/embedded/shared/CallFeedback/CallEndedScreen.js +34 -0
  225. package/dist/esm/src/embedded/shared/CallFeedback/CallEndedScreen.js.map +1 -0
  226. package/dist/esm/src/embedded/shared/CallFeedback/CallFeedback.js +35 -0
  227. package/dist/esm/src/embedded/shared/CallFeedback/CallFeedback.js.map +1 -0
  228. package/dist/esm/src/embedded/shared/CallFeedback/RatingScreen.js +18 -0
  229. package/dist/esm/src/embedded/shared/CallFeedback/RatingScreen.js.map +1 -0
  230. package/dist/esm/src/embedded/shared/CallFeedback/StarRating.js +37 -0
  231. package/dist/esm/src/embedded/shared/CallFeedback/StarRating.js.map +1 -0
  232. package/dist/esm/src/embedded/shared/CallFeedback/ThankYouScreen.js +34 -0
  233. package/dist/esm/src/embedded/shared/CallFeedback/ThankYouScreen.js.map +1 -0
  234. package/dist/esm/src/embedded/shared/ConnectionNotification/ConnectionNotification.js +56 -0
  235. package/dist/esm/src/embedded/shared/ConnectionNotification/ConnectionNotification.js.map +1 -0
  236. package/dist/esm/src/embedded/shared/EmbeddedParticipantViewUI/EmbeddedParticipantViewUI.js +42 -0
  237. package/dist/esm/src/embedded/shared/EmbeddedParticipantViewUI/EmbeddedParticipantViewUI.js.map +1 -0
  238. package/dist/esm/src/embedded/shared/JoinError/JoinError.js +34 -0
  239. package/dist/esm/src/embedded/shared/JoinError/JoinError.js.map +1 -0
  240. package/dist/esm/src/embedded/shared/Lobby/DeviceControls.js +44 -0
  241. package/dist/esm/src/embedded/shared/Lobby/DeviceControls.js.map +1 -0
  242. package/dist/esm/src/embedded/shared/Lobby/DisabledDeviceButton.js +31 -0
  243. package/dist/esm/src/embedded/shared/Lobby/DisabledDeviceButton.js.map +1 -0
  244. package/dist/esm/src/embedded/shared/Lobby/Lobby.js +45 -0
  245. package/dist/esm/src/embedded/shared/Lobby/Lobby.js.map +1 -0
  246. package/dist/esm/src/embedded/shared/Lobby/ToggleCameraButton.js +40 -0
  247. package/dist/esm/src/embedded/shared/Lobby/ToggleCameraButton.js.map +1 -0
  248. package/dist/esm/src/embedded/shared/Lobby/ToggleMicButton.js +41 -0
  249. package/dist/esm/src/embedded/shared/Lobby/ToggleMicButton.js.map +1 -0
  250. package/dist/esm/src/embedded/shared/Lobby/VideoPreviewFallbacks.js +50 -0
  251. package/dist/esm/src/embedded/shared/Lobby/VideoPreviewFallbacks.js.map +1 -0
  252. package/dist/esm/src/embedded/shared/ViewersCount/ViewersCount.js +31 -0
  253. package/dist/esm/src/embedded/shared/ViewersCount/ViewersCount.js.map +1 -0
  254. package/dist/esm/src/hooks/useDeviceList.js +40 -0
  255. package/dist/esm/src/hooks/useDeviceList.js.map +1 -0
  256. package/dist/esm/src/hooks/useDragToScroll.js +116 -0
  257. package/dist/esm/src/hooks/useDragToScroll.js.map +1 -0
  258. package/dist/esm/src/hooks/useFloatingUIPreset.js +34 -0
  259. package/dist/esm/src/hooks/useFloatingUIPreset.js.map +1 -0
  260. package/dist/esm/src/hooks/useLoopbackRecording.js +138 -0
  261. package/dist/esm/src/hooks/useLoopbackRecording.js.map +1 -0
  262. package/dist/esm/src/hooks/useModeration.js +135 -0
  263. package/dist/esm/src/hooks/useModeration.js.map +1 -0
  264. package/dist/esm/src/hooks/usePersistedDevicePreferences.js +16 -0
  265. package/dist/esm/src/hooks/usePersistedDevicePreferences.js.map +1 -0
  266. package/dist/esm/src/hooks/useRequestPermission.js +41 -0
  267. package/dist/esm/src/hooks/useRequestPermission.js.map +1 -0
  268. package/dist/esm/src/hooks/useScrollPosition.js +66 -0
  269. package/dist/esm/src/hooks/useScrollPosition.js.map +1 -0
  270. package/dist/esm/src/translations/en.json.js +177 -0
  271. package/dist/esm/src/translations/en.json.js.map +1 -0
  272. package/dist/esm/src/translations/index.js +6 -0
  273. package/dist/esm/src/translations/index.js.map +1 -0
  274. package/dist/esm/src/utilities/applyElementToRef.js +10 -0
  275. package/dist/esm/src/utilities/applyElementToRef.js.map +1 -0
  276. package/dist/esm/src/utilities/callControlHandler.js +29 -0
  277. package/dist/esm/src/utilities/callControlHandler.js.map +1 -0
  278. package/dist/esm/src/utilities/chunk.js +7 -0
  279. package/dist/esm/src/utilities/chunk.js.map +1 -0
  280. package/dist/esm/src/utilities/filter.js +94 -0
  281. package/dist/esm/src/utilities/filter.js.map +1 -0
  282. package/dist/esm/src/utilities/isComponentType.js +10 -0
  283. package/dist/esm/src/utilities/isComponentType.js.map +1 -0
  284. package/dist/esm/src/utilities/normalizeString.js +11 -0
  285. package/dist/esm/src/utilities/normalizeString.js.map +1 -0
  286. package/dist/esm/src/wrappers/LivestreamPlayer/LivestreamPlayer.js +105 -0
  287. package/dist/esm/src/wrappers/LivestreamPlayer/LivestreamPlayer.js.map +1 -0
  288. package/dist/index.cjs.js +138 -5
  289. package/dist/index.cjs.js.map +1 -1
  290. package/dist/index.d.ts +1 -1
  291. package/dist/src/hooks/index.d.ts +1 -0
  292. package/dist/src/hooks/useLoopbackRecording.d.ts +23 -0
  293. package/dist/src/hooks/useRequestPermission.d.ts +2 -2
  294. package/index.ts +4 -0
  295. package/package.json +14 -10
  296. package/src/components/CallControls/ScreenShareButton.tsx +5 -2
  297. package/src/components/CallControls/ToggleAudioButton.tsx +6 -2
  298. package/src/components/CallControls/ToggleVideoButton.tsx +6 -2
  299. package/src/core/components/ParticipantView/ParticipantActionsContextMenu.tsx +16 -12
  300. package/src/hooks/index.ts +1 -0
  301. package/src/hooks/useLoopbackRecording.ts +207 -0
  302. package/src/hooks/useRequestPermission.ts +4 -2
  303. package/dist/background-filters-D2U5UBbH.es.js.map +0 -1
  304. package/dist/embedded-BackgroundFilters-D2U5UBbH.es.js +0 -420
  305. package/dist/embedded-BackgroundFilters-D2U5UBbH.es.js.map +0 -1
  306. package/dist/embedded-CallStatsLatencyChart-Bj5OSYzg.es.js +0 -57
  307. package/dist/embedded-CallStatsLatencyChart-Bj5OSYzg.es.js.map +0 -1
  308. package/dist/embedded.es.js +0 -3536
  309. package/dist/embedded.es.js.map +0 -1
  310. package/dist/index.es.js +0 -3291
  311. package/dist/index.es.js.map +0 -1
  312. package/dist/latency-chart-Bj5OSYzg.es.js.map +0 -1
@@ -0,0 +1,80 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useI18n, useCall } from '@stream-io/video-react-bindings';
3
+ import { useState, useEffect, useMemo } from 'react';
4
+ import clsx from 'clsx';
5
+ import { hasScreenShare } from '@stream-io/video-client';
6
+ import '../../../../components/BackgroundFilters/BackgroundFiltersProvider.js';
7
+ import '../../../../components/Button/CompositeButton.js';
8
+ import { IconButton } from '../../../../components/Button/IconButton.js';
9
+ import '@floating-ui/react';
10
+ import '../../../../components/CallControls/RecordCallButton.js';
11
+ import '../../../../components/CallControls/ReactionsButton.js';
12
+ import { Icon } from '../../../../components/Icon/Icon.js';
13
+ import '../../../../components/DeviceSettings/DeviceSettings.js';
14
+ import '../../../../components/DropdownSelect/DropdownSelect.js';
15
+ import '../../../../components/Menu/MenuToggle.js';
16
+ import '../../../../components/CallControls/CancelCallButton.js';
17
+ import '../../../../components/CallControls/CallStatsButton.js';
18
+ import '../../../../components/CallParticipantsList/CallParticipantsList.js';
19
+ import '../../../../components/CallParticipantsList/CallParticipantListingItem.js';
20
+ import '../../../../components/CallStats/CallStats.js';
21
+ import '../../../../components/NoiseCancellation/NoiseCancellationProvider.js';
22
+ import '../../../../components/RingingCall/RingingCall.js';
23
+ import '../../../../components/Permissions/PermissionRequests.js';
24
+ import '../../Video/Video.js';
25
+ import '../../Video/BaseVideo.js';
26
+ import '../../Video/DefaultVideoPlaceholder.js';
27
+ import '../../ParticipantView/ParticipantViewContext.js';
28
+ import { ParticipantView } from '../../ParticipantView/ParticipantView.js';
29
+ import { DefaultParticipantViewUI } from '../../ParticipantView/DefaultParticipantViewUI.js';
30
+ import { useFilteredParticipants, usePaginatedLayoutSortPreset } from '../hooks.js';
31
+ import { chunk } from '../../../../utilities/chunk.js';
32
+
33
+ const getGridDensity = (count) => {
34
+ if (count === 1)
35
+ return 'single';
36
+ if (count <= 5)
37
+ return 'small';
38
+ if (count <= 9)
39
+ return 'medium';
40
+ if (count <= 16)
41
+ return 'large';
42
+ return 'overflow';
43
+ };
44
+ /**
45
+ * A grid-based PIP layout with pagination support.
46
+ * Use this when you need a more structured grid view in PIP mode.
47
+ */
48
+ const Grid = (props) => {
49
+ const { t } = useI18n();
50
+ const { excludeLocalParticipant = false, filterParticipants, mirrorLocalParticipantVideo = true, groupSize = 9, pageArrowsVisible = true, VideoPlaceholder, ParticipantViewUI = DefaultParticipantViewUI, } = props;
51
+ const [page, setPage] = useState(0);
52
+ const [wrapperElement, setWrapperElement] = useState(null);
53
+ const call = useCall();
54
+ const participants = useFilteredParticipants({
55
+ excludeLocalParticipant,
56
+ filterParticipants,
57
+ });
58
+ const screenSharingParticipant = participants.find((p) => hasScreenShare(p));
59
+ usePaginatedLayoutSortPreset(call);
60
+ useEffect(() => {
61
+ if (!wrapperElement || !call)
62
+ return;
63
+ return call.setViewport(wrapperElement);
64
+ }, [wrapperElement, call]);
65
+ const participantGroups = useMemo(() => chunk(participants, groupSize), [participants, groupSize]);
66
+ const pageCount = participantGroups.length;
67
+ if (page > pageCount - 1) {
68
+ setPage(Math.max(0, pageCount - 1));
69
+ }
70
+ const selectedGroup = participantGroups[page];
71
+ const mirror = mirrorLocalParticipantVideo ? undefined : false;
72
+ if (!call)
73
+ return null;
74
+ 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" }))] })] }));
76
+ };
77
+ Grid.displayName = 'PipLayout.Grid';
78
+
79
+ export { Grid };
80
+ //# sourceMappingURL=Grid.js.map
@@ -0,0 +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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"}
@@ -0,0 +1,13 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import '../../Audio/Audio.js';
3
+ import { ParticipantsAudio } from '../../Audio/ParticipantsAudio.js';
4
+ import { useRawRemoteParticipants } from '../hooks.js';
5
+
6
+ const Host = () => {
7
+ const remoteParticipants = useRawRemoteParticipants();
8
+ return jsx(ParticipantsAudio, { participants: remoteParticipants });
9
+ };
10
+ Host.displayName = 'PipLayout.Host';
11
+
12
+ export { Host };
13
+ //# sourceMappingURL=Host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Host.js","sources":["../../../../../../../../../src/core/components/CallLayout/PipLayout/Host.tsx"],"sourcesContent":["import { ParticipantsAudio } from '../../Audio';\nimport { useRawRemoteParticipants } from '../hooks';\n\nexport const Host = () => {\n const remoteParticipants = useRawRemoteParticipants();\n return <ParticipantsAudio participants={remoteParticipants} />;\n};\n\nHost.displayName = 'PipLayout.Host';\n"],"names":["_jsx"],"mappings":";;;;;AAGO,MAAM,IAAI,GAAG,MAAK;AACvB,IAAA,MAAM,kBAAkB,GAAG,wBAAwB,EAAE;AACrD,IAAA,OAAOA,IAAC,iBAAiB,EAAA,EAAC,YAAY,EAAE,kBAAkB,GAAI;AAChE;AAEA,IAAI,CAAC,WAAW,GAAG,gBAAgB;;;;"}
@@ -0,0 +1,57 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useI18n, useCall } from '@stream-io/video-react-bindings';
3
+ import { useState, useEffect } from 'react';
4
+ import { hasScreenShare } from '@stream-io/video-client';
5
+ import 'clsx';
6
+ import '../../../../components/BackgroundFilters/BackgroundFiltersProvider.js';
7
+ import '../../../../components/Button/CompositeButton.js';
8
+ import '../../../../components/Button/IconButton.js';
9
+ import '@floating-ui/react';
10
+ import '../../../../components/CallControls/RecordCallButton.js';
11
+ import '../../../../components/CallControls/ReactionsButton.js';
12
+ import { Icon } from '../../../../components/Icon/Icon.js';
13
+ import '../../../../components/DeviceSettings/DeviceSettings.js';
14
+ import '../../../../components/DropdownSelect/DropdownSelect.js';
15
+ import '../../../../components/Menu/MenuToggle.js';
16
+ import '../../../../components/CallControls/CancelCallButton.js';
17
+ import '../../../../components/CallControls/CallStatsButton.js';
18
+ import '../../../../components/CallParticipantsList/CallParticipantsList.js';
19
+ import '../../../../components/CallParticipantsList/CallParticipantListingItem.js';
20
+ import '../../../../components/CallStats/CallStats.js';
21
+ import '../../../../components/NoiseCancellation/NoiseCancellationProvider.js';
22
+ import '../../../../components/RingingCall/RingingCall.js';
23
+ import '../../../../components/Permissions/PermissionRequests.js';
24
+ import '../../Video/Video.js';
25
+ import '../../Video/BaseVideo.js';
26
+ import '../../Video/DefaultVideoPlaceholder.js';
27
+ import '../../ParticipantView/ParticipantViewContext.js';
28
+ import { ParticipantView } from '../../ParticipantView/ParticipantView.js';
29
+ import { DefaultParticipantViewUI } from '../../ParticipantView/DefaultParticipantViewUI.js';
30
+ import { useFilteredParticipants, usePaginatedLayoutSortPreset } from '../hooks.js';
31
+
32
+ const Pip = (props) => {
33
+ const { t } = useI18n();
34
+ const { excludeLocalParticipant = false, filterParticipants, mirrorLocalParticipantVideo = true, VideoPlaceholder, ParticipantViewUI = DefaultParticipantViewUI, } = props;
35
+ const [layoutWrapperElement, setLayoutWrapperElement] = useState(null);
36
+ const call = useCall();
37
+ const participants = useFilteredParticipants({
38
+ excludeLocalParticipant,
39
+ filterParticipants,
40
+ });
41
+ const screenSharingParticipant = participants.find((p) => hasScreenShare(p));
42
+ usePaginatedLayoutSortPreset(call);
43
+ useEffect(() => {
44
+ if (!layoutWrapperElement || !call)
45
+ return;
46
+ return call.setViewport(layoutWrapperElement);
47
+ }, [layoutWrapperElement, call]);
48
+ const mirror = mirrorLocalParticipantVideo ? undefined : false;
49
+ if (!call)
50
+ return null;
51
+ 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)))] }));
53
+ };
54
+ Pip.displayName = 'PipLayout.Pip';
55
+
56
+ export { Pip };
57
+ //# sourceMappingURL=Pip.js.map
@@ -0,0 +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;;;;"}
@@ -0,0 +1,8 @@
1
+ import { Pip } from './Pip.js';
2
+ import { Host } from './Host.js';
3
+ import { Grid } from './Grid.js';
4
+
5
+ const PipLayout = { Pip, Host, Grid };
6
+
7
+ export { PipLayout };
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../../../../../../src/core/components/CallLayout/PipLayout/index.ts"],"sourcesContent":["import { Pip } from './Pip';\nimport { Host } from './Host';\nimport { Grid } from './Grid';\n\nexport const PipLayout = { Pip, Host, Grid };\n"],"names":[],"mappings":";;;;AAIO,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI;;;;"}
@@ -0,0 +1,103 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import clsx from 'clsx';
4
+ import { hasScreenShare } from '@stream-io/video-client';
5
+ import { useCall, useCallStateHooks, useSpeakerLayoutSortPreset } from '@stream-io/video-react-bindings';
6
+ import '../ParticipantView/ParticipantViewContext.js';
7
+ import '../../../components/Menu/MenuToggle.js';
8
+ import { ParticipantView } from '../ParticipantView/ParticipantView.js';
9
+ import { DefaultParticipantViewUI } from '../ParticipantView/DefaultParticipantViewUI.js';
10
+ import '../../../components/BackgroundFilters/BackgroundFiltersProvider.js';
11
+ import '../../../components/Button/CompositeButton.js';
12
+ import { IconButton } from '../../../components/Button/IconButton.js';
13
+ import '@floating-ui/react';
14
+ import { useVerticalScrollPosition, useHorizontalScrollPosition } from '../../../hooks/useScrollPosition.js';
15
+ import { useDragToScroll } from '../../../hooks/useDragToScroll.js';
16
+ import '../../../components/CallControls/RecordCallButton.js';
17
+ import '../../../components/CallControls/ReactionsButton.js';
18
+ import '../../../components/DeviceSettings/DeviceSettings.js';
19
+ import '../../../components/DropdownSelect/DropdownSelect.js';
20
+ import '../../../components/CallControls/CancelCallButton.js';
21
+ import '../../../components/CallControls/CallStatsButton.js';
22
+ import '../../../components/CallParticipantsList/CallParticipantsList.js';
23
+ import '../../../components/CallParticipantsList/CallParticipantListingItem.js';
24
+ import '../../../components/CallStats/CallStats.js';
25
+ import '../../../components/NoiseCancellation/NoiseCancellationProvider.js';
26
+ import '../../../components/RingingCall/RingingCall.js';
27
+ import '../../../components/Permissions/PermissionRequests.js';
28
+ import '../Video/Video.js';
29
+ import '../Video/BaseVideo.js';
30
+ import '../Video/DefaultVideoPlaceholder.js';
31
+ import { useRawRemoteParticipants, useFilteredParticipants } from './hooks.js';
32
+ import { useCalculateHardLimit } from '../../hooks/useCalculateHardLimit.js';
33
+ import '../Audio/Audio.js';
34
+ import { ParticipantsAudio } from '../Audio/ParticipantsAudio.js';
35
+
36
+ const DefaultParticipantViewUIBar = () => (jsx(DefaultParticipantViewUI, { menuPlacement: "top-end" }));
37
+ const SpeakerLayout = ({ ParticipantViewUIBar = DefaultParticipantViewUIBar, ParticipantViewUISpotlight = DefaultParticipantViewUI, VideoPlaceholder, PictureInPicturePlaceholder, participantsBarPosition = 'bottom', participantsBarLimit, mirrorLocalParticipantVideo = true, excludeLocalParticipant = false, filterParticipants, pageArrowsVisible = true, muted, enableDragToScroll = false, }) => {
38
+ const call = useCall();
39
+ const { useParticipants } = useCallStateHooks();
40
+ const allParticipants = useParticipants();
41
+ const remoteParticipants = useRawRemoteParticipants();
42
+ const [participantInSpotlight, ...otherParticipants] = useFilteredParticipants({ excludeLocalParticipant, filterParticipants });
43
+ const [participantsBarWrapperElement, setParticipantsBarWrapperElement] = useState(null);
44
+ const [participantsBarElement, setParticipantsBarElement] = useState(null);
45
+ const [buttonsWrapperElement, setButtonsWrapperElement] = useState(null);
46
+ const isSpeakerScreenSharing = participantInSpotlight && hasScreenShare(participantInSpotlight);
47
+ const hardLimit = useCalculateHardLimit(buttonsWrapperElement, participantsBarElement, participantsBarLimit);
48
+ const isVertical = participantsBarPosition === 'left' || participantsBarPosition === 'right';
49
+ const isHorizontal = participantsBarPosition === 'top' || participantsBarPosition === 'bottom';
50
+ useEffect(() => {
51
+ if (!participantsBarWrapperElement || !call)
52
+ return;
53
+ const cleanup = call.setViewport(participantsBarWrapperElement);
54
+ return () => cleanup?.();
55
+ }, [participantsBarWrapperElement, call]);
56
+ const isOneOnOneCall = allParticipants.length === 2;
57
+ useSpeakerLayoutSortPreset(call, isOneOnOneCall);
58
+ useDragToScroll(participantsBarWrapperElement, {
59
+ enabled: enableDragToScroll,
60
+ });
61
+ let participantsWithAppliedLimit = otherParticipants;
62
+ const hardLimitToApply = isVertical
63
+ ? hardLimit.vertical
64
+ : hardLimit.horizontal;
65
+ if (typeof participantsBarLimit !== 'undefined' &&
66
+ hardLimitToApply !== null) {
67
+ participantsWithAppliedLimit = otherParticipants.slice(0,
68
+ // subtract 1 if speaker is sharing screen as
69
+ // that one is rendered independently from otherParticipants array
70
+ hardLimitToApply - (isSpeakerScreenSharing ? 1 : 0));
71
+ }
72
+ const mirror = mirrorLocalParticipantVideo ? undefined : false;
73
+ if (!call)
74
+ return null;
75
+ const renderParticipantsBar = participantsBarPosition &&
76
+ (participantsWithAppliedLimit.length > 0 || isSpeakerScreenSharing);
77
+ return (jsxs("div", { className: "str-video__speaker-layout__wrapper", children: [!muted && jsx(ParticipantsAudio, { participants: remoteParticipants }), jsxs("div", { className: clsx('str-video__speaker-layout', participantsBarPosition &&
78
+ `str-video__speaker-layout--variant-${participantsBarPosition}`), children: [jsx("div", { className: "str-video__speaker-layout__spotlight", children: participantInSpotlight && (jsx(ParticipantView, { participant: participantInSpotlight, muteAudio: true, mirror: mirror, trackType: isSpeakerScreenSharing ? 'screenShareTrack' : 'videoTrack', ParticipantViewUI: ParticipantViewUISpotlight, VideoPlaceholder: VideoPlaceholder, PictureInPicturePlaceholder: PictureInPicturePlaceholder })) }), renderParticipantsBar && (jsxs("div", { ref: setButtonsWrapperElement, className: "str-video__speaker-layout__participants-bar-buttons-wrapper", children: [jsx("div", { className: "str-video__speaker-layout__participants-bar-wrapper", ref: setParticipantsBarWrapperElement, children: jsxs("div", { ref: setParticipantsBarElement, className: "str-video__speaker-layout__participants-bar", children: [isSpeakerScreenSharing && (jsx("div", { className: "str-video__speaker-layout__participant-tile", children: jsx(ParticipantView, { participant: participantInSpotlight, ParticipantViewUI: ParticipantViewUIBar, VideoPlaceholder: VideoPlaceholder, PictureInPicturePlaceholder: PictureInPicturePlaceholder, mirror: mirror, muteAudio: true }) }, participantInSpotlight.sessionId)), participantsWithAppliedLimit.map((participant) => (jsx("div", { className: "str-video__speaker-layout__participant-tile", children: jsx(ParticipantView, { participant: participant, ParticipantViewUI: ParticipantViewUIBar, VideoPlaceholder: VideoPlaceholder, PictureInPicturePlaceholder: PictureInPicturePlaceholder, mirror: mirror, muteAudio: true }) }, participant.sessionId)))] }) }), pageArrowsVisible && isVertical && (jsx(VerticalScrollButtons, { scrollWrapper: participantsBarWrapperElement })), pageArrowsVisible && isHorizontal && (jsx(HorizontalScrollButtons, { scrollWrapper: participantsBarWrapperElement }))] }))] })] }));
79
+ };
80
+ SpeakerLayout.displayName = 'SpeakerLayout';
81
+ const HorizontalScrollButtons = ({ scrollWrapper, }) => {
82
+ const scrollPosition = useHorizontalScrollPosition(scrollWrapper);
83
+ const scrollStartClickHandler = () => {
84
+ scrollWrapper?.scrollBy({ left: -150, behavior: 'smooth' });
85
+ };
86
+ const scrollEndClickHandler = () => {
87
+ scrollWrapper?.scrollBy({ left: 150, behavior: 'smooth' });
88
+ };
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" }))] }));
90
+ };
91
+ const VerticalScrollButtons = ({ scrollWrapper, }) => {
92
+ const scrollPosition = useVerticalScrollPosition(scrollWrapper);
93
+ const scrollTopClickHandler = () => {
94
+ scrollWrapper?.scrollBy({ top: -150, behavior: 'smooth' });
95
+ };
96
+ const scrollBottomClickHandler = () => {
97
+ scrollWrapper?.scrollBy({ top: 150, behavior: 'smooth' });
98
+ };
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" }))] }));
100
+ };
101
+
102
+ export { SpeakerLayout };
103
+ //# sourceMappingURL=SpeakerLayout.js.map
@@ -0,0 +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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"}
@@ -0,0 +1,62 @@
1
+ import { useMemo, useEffect } from 'react';
2
+ import { paginatedLayoutSortPreset, CallTypes, defaultSortPreset, hasScreenShare, hasAudio, hasVideo, isPinned } from '@stream-io/video-client';
3
+ import { useCallStateHooks } from '@stream-io/video-react-bindings';
4
+ import { applyFilter } from '../../../utilities/filter.js';
5
+
6
+ const useFilteredParticipants = ({ excludeLocalParticipant = false, filterParticipants, }) => {
7
+ const { useParticipants, useRemoteParticipants } = useCallStateHooks();
8
+ const allParticipants = useParticipants();
9
+ const remoteParticipants = useRemoteParticipants();
10
+ return useMemo(() => {
11
+ const unfilteredParticipants = excludeLocalParticipant
12
+ ? remoteParticipants
13
+ : allParticipants;
14
+ return filterParticipants
15
+ ? applyParticipantsFilter(unfilteredParticipants, filterParticipants)
16
+ : unfilteredParticipants;
17
+ }, [
18
+ allParticipants,
19
+ remoteParticipants,
20
+ excludeLocalParticipant,
21
+ filterParticipants,
22
+ ]);
23
+ };
24
+ const applyParticipantsFilter = (participants, filter) => {
25
+ const filterCallback = typeof filter === 'function'
26
+ ? filter
27
+ : (participant) => applyFilter({
28
+ userId: participant.userId,
29
+ isSpeaking: participant.isSpeaking,
30
+ isDominantSpeaker: participant.isDominantSpeaker,
31
+ name: participant.name,
32
+ roles: participant.roles,
33
+ isPinned: isPinned(participant),
34
+ hasVideo: hasVideo(participant),
35
+ hasAudio: hasAudio(participant),
36
+ hasScreenShare: hasScreenShare(participant),
37
+ }, filter);
38
+ return participants.filter(filterCallback);
39
+ };
40
+ const usePaginatedLayoutSortPreset = (call) => {
41
+ useEffect(() => {
42
+ if (!call)
43
+ return;
44
+ call.setSortParticipantsBy(paginatedLayoutSortPreset);
45
+ return () => {
46
+ resetSortPreset(call);
47
+ };
48
+ }, [call]);
49
+ };
50
+ const useRawRemoteParticipants = () => {
51
+ const { useRawParticipants } = useCallStateHooks();
52
+ const rawParticipants = useRawParticipants();
53
+ return useMemo(() => rawParticipants.filter((p) => !p.isLocalParticipant), [rawParticipants]);
54
+ };
55
+ const resetSortPreset = (call) => {
56
+ // reset the sorting to the default for the call type
57
+ const callConfig = CallTypes.get(call.type);
58
+ call.setSortParticipantsBy(callConfig.options.sortParticipantsBy || defaultSortPreset);
59
+ };
60
+
61
+ export { applyParticipantsFilter, useFilteredParticipants, usePaginatedLayoutSortPreset, useRawRemoteParticipants };
62
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sources":["../../../../../../../../src/core/components/CallLayout/hooks.ts"],"sourcesContent":["import { useEffect, useMemo } from 'react';\nimport {\n Call,\n CallTypes,\n defaultSortPreset,\n hasAudio,\n hasScreenShare,\n hasVideo,\n isPinned,\n paginatedLayoutSortPreset,\n StreamVideoParticipant,\n} from '@stream-io/video-client';\nimport { useCallStateHooks } from '@stream-io/video-react-bindings';\nimport { applyFilter, Filter } from '../../../utilities/filter';\n\nexport type FilterableParticipant = Pick<\n StreamVideoParticipant,\n 'userId' | 'isSpeaking' | 'isDominantSpeaker' | 'name' | 'roles'\n> & {\n isPinned: boolean;\n hasVideo: boolean;\n hasAudio: boolean;\n hasScreenShare: boolean;\n};\n\nexport type ParticipantFilter = Filter<FilterableParticipant>;\nexport type ParticipantPredicate = (\n participant: StreamVideoParticipant,\n) => boolean;\n\nexport const useFilteredParticipants = ({\n excludeLocalParticipant = false,\n filterParticipants,\n}: {\n excludeLocalParticipant?: boolean;\n filterParticipants?: ParticipantFilter | ParticipantPredicate;\n}) => {\n const { useParticipants, useRemoteParticipants } = useCallStateHooks();\n const allParticipants = useParticipants();\n const remoteParticipants = useRemoteParticipants();\n return useMemo(() => {\n const unfilteredParticipants = excludeLocalParticipant\n ? remoteParticipants\n : allParticipants;\n\n return filterParticipants\n ? applyParticipantsFilter(unfilteredParticipants, filterParticipants)\n : unfilteredParticipants;\n }, [\n allParticipants,\n remoteParticipants,\n excludeLocalParticipant,\n filterParticipants,\n ]);\n};\n\nexport const applyParticipantsFilter = (\n participants: StreamVideoParticipant[],\n filter: ParticipantPredicate | ParticipantFilter,\n) => {\n const filterCallback =\n typeof filter === 'function'\n ? filter\n : (participant: StreamVideoParticipant) =>\n applyFilter(\n {\n userId: participant.userId,\n isSpeaking: participant.isSpeaking,\n isDominantSpeaker: participant.isDominantSpeaker,\n name: participant.name,\n roles: participant.roles,\n isPinned: isPinned(participant),\n hasVideo: hasVideo(participant),\n hasAudio: hasAudio(participant),\n hasScreenShare: hasScreenShare(participant),\n },\n filter,\n );\n\n return participants.filter(filterCallback);\n};\n\nexport const usePaginatedLayoutSortPreset = (call: Call | undefined) => {\n useEffect(() => {\n if (!call) return;\n call.setSortParticipantsBy(paginatedLayoutSortPreset);\n return () => {\n resetSortPreset(call);\n };\n }, [call]);\n};\n\nexport const useRawRemoteParticipants = () => {\n const { useRawParticipants } = useCallStateHooks();\n const rawParticipants = useRawParticipants();\n return useMemo(\n () => rawParticipants.filter((p) => !p.isLocalParticipant),\n [rawParticipants],\n );\n};\n\nconst resetSortPreset = (call: Call) => {\n // reset the sorting to the default for the call type\n const callConfig = CallTypes.get(call.type);\n call.setSortParticipantsBy(\n callConfig.options.sortParticipantsBy || defaultSortPreset,\n );\n};\n"],"names":[],"mappings":";;;;;AA8BO,MAAM,uBAAuB,GAAG,CAAC,EACtC,uBAAuB,GAAG,KAAK,EAC/B,kBAAkB,GAInB,KAAI;IACH,MAAM,EAAE,eAAe,EAAE,qBAAqB,EAAE,GAAG,iBAAiB,EAAE;AACtE,IAAA,MAAM,eAAe,GAAG,eAAe,EAAE;AACzC,IAAA,MAAM,kBAAkB,GAAG,qBAAqB,EAAE;IAClD,OAAO,OAAO,CAAC,MAAK;QAClB,MAAM,sBAAsB,GAAG;AAC7B,cAAE;cACA,eAAe;AAEnB,QAAA,OAAO;AACL,cAAE,uBAAuB,CAAC,sBAAsB,EAAE,kBAAkB;cAClE,sBAAsB;AAC5B,IAAA,CAAC,EAAE;QACD,eAAe;QACf,kBAAkB;QAClB,uBAAuB;QACvB,kBAAkB;AACnB,KAAA,CAAC;AACJ;MAEa,uBAAuB,GAAG,CACrC,YAAsC,EACtC,MAAgD,KAC9C;AACF,IAAA,MAAM,cAAc,GAClB,OAAO,MAAM,KAAK;AAChB,UAAE;AACF,UAAE,CAAC,WAAmC,KAClC,WAAW,CACT;YACE,MAAM,EAAE,WAAW,CAAC,MAAM;YAC1B,UAAU,EAAE,WAAW,CAAC,UAAU;YAClC,iBAAiB,EAAE,WAAW,CAAC,iBAAiB;YAChD,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,KAAK,EAAE,WAAW,CAAC,KAAK;AACxB,YAAA,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC;AAC/B,YAAA,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC;AAC/B,YAAA,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC;AAC/B,YAAA,cAAc,EAAE,cAAc,CAAC,WAAW,CAAC;SAC5C,EACD,MAAM,CACP;AAET,IAAA,OAAO,YAAY,CAAC,MAAM,CAAC,cAAc,CAAC;AAC5C;AAEO,MAAM,4BAA4B,GAAG,CAAC,IAAsB,KAAI;IACrE,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,IAAI;YAAE;AACX,QAAA,IAAI,CAAC,qBAAqB,CAAC,yBAAyB,CAAC;AACrD,QAAA,OAAO,MAAK;YACV,eAAe,CAAC,IAAI,CAAC;AACvB,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;AACZ;AAEO,MAAM,wBAAwB,GAAG,MAAK;AAC3C,IAAA,MAAM,EAAE,kBAAkB,EAAE,GAAG,iBAAiB,EAAE;AAClD,IAAA,MAAM,eAAe,GAAG,kBAAkB,EAAE;IAC5C,OAAO,OAAO,CACZ,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAC1D,CAAC,eAAe,CAAC,CAClB;AACH;AAEA,MAAM,eAAe,GAAG,CAAC,IAAU,KAAI;;IAErC,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;IAC3C,IAAI,CAAC,qBAAqB,CACxB,UAAU,CAAC,OAAO,CAAC,kBAAkB,IAAI,iBAAiB,CAC3D;AACH,CAAC;;;;"}
@@ -0,0 +1,94 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
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';
5
+ import clsx from 'clsx';
6
+ import '../../../components/BackgroundFilters/BackgroundFiltersProvider.js';
7
+ import '../../../components/Button/CompositeButton.js';
8
+ import { IconButton } from '../../../components/Button/IconButton.js';
9
+ import { Notification } from '../../../components/Notification/Notification.js';
10
+ import '../../../components/CallControls/RecordCallButton.js';
11
+ import '../../../components/CallControls/ReactionsButton.js';
12
+ import '@floating-ui/react';
13
+ import { Icon } from '../../../components/Icon/Icon.js';
14
+ import '../../../components/DeviceSettings/DeviceSettings.js';
15
+ import '../../../components/DropdownSelect/DropdownSelect.js';
16
+ import { MenuToggle } from '../../../components/Menu/MenuToggle.js';
17
+ import '../../../components/CallControls/CancelCallButton.js';
18
+ import '../../../components/CallControls/CallStatsButton.js';
19
+ import '../../../components/CallParticipantsList/CallParticipantsList.js';
20
+ import '../../../components/CallParticipantsList/CallParticipantListingItem.js';
21
+ import { LoadingIndicator } from '../../../components/LoadingIndicator/LoadingIndicator.js';
22
+ import '../../../components/CallStats/CallStats.js';
23
+ import '../../../components/NoiseCancellation/NoiseCancellationProvider.js';
24
+ import { Reaction } from '../../../components/Reaction/Reaction.js';
25
+ import '../../../components/RingingCall/RingingCall.js';
26
+ import '../../../components/Permissions/PermissionRequests.js';
27
+ import '../Video/Video.js';
28
+ import '../Video/BaseVideo.js';
29
+ import '../Video/DefaultVideoPlaceholder.js';
30
+ import { ParticipantActionsContextMenu } from './ParticipantActionsContextMenu.js';
31
+ import { useParticipantViewContext } from './ParticipantViewContext.js';
32
+
33
+ const ToggleButton = forwardRef(function ToggleButtonRender(props, ref) {
34
+ return jsx(IconButton, { enabled: props.menuShown, icon: "ellipsis", ref: ref });
35
+ });
36
+ const DefaultScreenShareOverlay = () => {
37
+ const call = useCall();
38
+ const { t } = useI18n();
39
+ const stopScreenShare = () => {
40
+ call?.screenShare.disable().catch((err) => {
41
+ console.error('Failed to stop screen sharing:', err);
42
+ });
43
+ };
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')] })] }));
45
+ };
46
+ /**
47
+ * Rendered over a remote participant's tile when the browser's autoplay policy
48
+ * has blocked their audio. Selecting it calls `call.resumeAudio()`, unblocking
49
+ * every blocked element at once.
50
+ */
51
+ const DefaultAudioBlockedNotification = () => {
52
+ const call = useCall();
53
+ 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') })] })] }) }));
55
+ };
56
+ const DefaultParticipantViewUI = ({ indicatorsVisible = true, menuPlacement = 'bottom-start', showMenuButton = true, ParticipantActionsContextMenu: ParticipantActionsContextMenu$1 = ParticipantActionsContextMenu, AudioBlockedNotification = DefaultAudioBlockedNotification, }) => {
57
+ const { participant, trackType } = useParticipantViewContext();
58
+ const { useAutoplayBlockedSessionIds } = useCallStateHooks();
59
+ const blockedSessionIds = useAutoplayBlockedSessionIds();
60
+ const isScreenSharing = hasScreenShare(participant);
61
+ const shouldShowAudioBlockedNotification = !participant.isLocalParticipant &&
62
+ trackType !== 'screenShareTrack' &&
63
+ blockedSessionIds.includes(participant.sessionId);
64
+ if (participant.isLocalParticipant &&
65
+ isScreenSharing &&
66
+ trackType === 'screenShareTrack') {
67
+ return (jsxs(Fragment, { children: [jsx(DefaultScreenShareOverlay, {}), jsx(ParticipantDetails, { indicatorsVisible: indicatorsVisible })] }));
68
+ }
69
+ return (jsxs(Fragment, { children: [showMenuButton && (jsx(MenuToggle, { strategy: "fixed", placement: menuPlacement, ToggleButton: ToggleButton, children: jsx(ParticipantActionsContextMenu$1, {}) })), jsx(Reaction, { participant: participant }), jsx(ParticipantDetails, { indicatorsVisible: indicatorsVisible }), AudioBlockedNotification && shouldShowAudioBlockedNotification && (jsx(AudioBlockedNotification, {}))] }));
70
+ };
71
+ const ParticipantDetails = ({ indicatorsVisible = true, }) => {
72
+ const { participant, trackType } = useParticipantViewContext();
73
+ const { isLocalParticipant, connectionQuality, pin, sessionId, name, userId, } = participant;
74
+ const call = useCall();
75
+ const { t } = useI18n();
76
+ const connectionQualityAsString = !!connectionQuality &&
77
+ SfuModels.ConnectionQuality[connectionQuality].toLowerCase();
78
+ const hasAudioTrack = hasAudio(participant);
79
+ const hasVideoTrack = hasVideo(participant);
80
+ const canUnpin = !!pin && pin.isLocalPin;
81
+ const isTrackPaused = trackType !== 'none' ? hasPausedTrack(participant, trackType) : false;
82
+ const isAudioConnecting = useIsAudioConnecting(participant);
83
+ 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
+ };
87
+ const SpeechIndicator = () => {
88
+ const { participant } = useParticipantViewContext();
89
+ const { isSpeaking, isDominantSpeaker } = participant;
90
+ return (jsxs("span", { className: clsx('str-video__speech-indicator', isSpeaking && 'str-video__speech-indicator--speaking', isDominantSpeaker && 'str-video__speech-indicator--dominant'), children: [jsx("span", { className: "str-video__speech-indicator__bar" }), jsx("span", { className: "str-video__speech-indicator__bar" }), jsx("span", { className: "str-video__speech-indicator__bar" })] }));
91
+ };
92
+
93
+ export { DefaultAudioBlockedNotification, DefaultParticipantViewUI, DefaultScreenShareOverlay, ParticipantDetails, SpeechIndicator };
94
+ //# sourceMappingURL=DefaultParticipantViewUI.js.map
@@ -0,0 +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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"}