@stream-io/video-react-sdk 1.41.0 → 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 (305) hide show
  1. package/CHANGELOG.md +22 -6
  2. package/dist/embedded.cjs.js +1 -1
  3. package/dist/esm/embedded.js +3 -0
  4. package/dist/esm/embedded.js.map +1 -0
  5. package/dist/esm/index.js +92 -0
  6. package/dist/esm/index.js.map +1 -0
  7. package/dist/esm/src/components/Avatar/Avatar.js +14 -0
  8. package/dist/esm/src/components/Avatar/Avatar.js.map +1 -0
  9. package/dist/{background-filters-D2U5UBbH.es.js → esm/src/components/BackgroundFilters/BackgroundFilters.js} +1 -1
  10. package/dist/esm/src/components/BackgroundFilters/BackgroundFilters.js.map +1 -0
  11. package/dist/esm/src/components/BackgroundFilters/BackgroundFiltersProvider.js +33 -0
  12. package/dist/esm/src/components/BackgroundFilters/BackgroundFiltersProvider.js.map +1 -0
  13. package/dist/esm/src/components/Button/CompositeButton.js +29 -0
  14. package/dist/esm/src/components/Button/CompositeButton.js.map +1 -0
  15. package/dist/esm/src/components/Button/IconButton.js +18 -0
  16. package/dist/esm/src/components/Button/IconButton.js.map +1 -0
  17. package/dist/esm/src/components/Button/TextButton.js +8 -0
  18. package/dist/esm/src/components/Button/TextButton.js.map +1 -0
  19. package/dist/esm/src/components/CallControls/AcceptCallButton.js +28 -0
  20. package/dist/esm/src/components/CallControls/AcceptCallButton.js.map +1 -0
  21. package/dist/esm/src/components/CallControls/CallControls.js +21 -0
  22. package/dist/esm/src/components/CallControls/CallControls.js.map +1 -0
  23. package/dist/esm/src/components/CallControls/CallStatsButton.js +18 -0
  24. package/dist/esm/src/components/CallControls/CallStatsButton.js.map +1 -0
  25. package/dist/esm/src/components/CallControls/CancelCallButton.js +78 -0
  26. package/dist/esm/src/components/CallControls/CancelCallButton.js.map +1 -0
  27. package/dist/esm/src/components/CallControls/ReactionsButton.js +61 -0
  28. package/dist/esm/src/components/CallControls/ReactionsButton.js.map +1 -0
  29. package/dist/esm/src/components/CallControls/RecordCallButton.js +64 -0
  30. package/dist/esm/src/components/CallControls/RecordCallButton.js.map +1 -0
  31. package/dist/esm/src/components/CallControls/ScreenShareButton.js +44 -0
  32. package/dist/esm/src/components/CallControls/ScreenShareButton.js.map +1 -0
  33. package/dist/esm/src/components/CallControls/ToggleAudioButton.js +72 -0
  34. package/dist/esm/src/components/CallControls/ToggleAudioButton.js.map +1 -0
  35. package/dist/esm/src/components/CallControls/ToggleAudioOutputButton.js +27 -0
  36. package/dist/esm/src/components/CallControls/ToggleAudioOutputButton.js.map +1 -0
  37. package/dist/esm/src/components/CallControls/ToggleVideoButton.js +81 -0
  38. package/dist/esm/src/components/CallControls/ToggleVideoButton.js.map +1 -0
  39. package/dist/esm/src/components/CallParticipantsList/BlockedUserListing.js +23 -0
  40. package/dist/esm/src/components/CallParticipantsList/BlockedUserListing.js.map +1 -0
  41. package/dist/esm/src/components/CallParticipantsList/CallParticipantListHeader.js +15 -0
  42. package/dist/esm/src/components/CallParticipantsList/CallParticipantListHeader.js.map +1 -0
  43. package/dist/esm/src/components/CallParticipantsList/CallParticipantListing.js +7 -0
  44. package/dist/esm/src/components/CallParticipantsList/CallParticipantListing.js.map +1 -0
  45. package/dist/esm/src/components/CallParticipantsList/CallParticipantListingItem.js +46 -0
  46. package/dist/esm/src/components/CallParticipantsList/CallParticipantListingItem.js.map +1 -0
  47. package/dist/esm/src/components/CallParticipantsList/CallParticipantsList.js +81 -0
  48. package/dist/esm/src/components/CallParticipantsList/CallParticipantsList.js.map +1 -0
  49. package/dist/esm/src/components/CallParticipantsList/EmptyParticipantSearchList.js +10 -0
  50. package/dist/esm/src/components/CallParticipantsList/EmptyParticipantSearchList.js.map +1 -0
  51. package/dist/esm/src/components/CallPreview/CallPreview.js +24 -0
  52. package/dist/esm/src/components/CallPreview/CallPreview.js.map +1 -0
  53. package/dist/esm/src/components/CallRecordingList/CallRecordingList.js +12 -0
  54. package/dist/esm/src/components/CallRecordingList/CallRecordingList.js.map +1 -0
  55. package/dist/esm/src/components/CallRecordingList/CallRecordingListHeader.js +12 -0
  56. package/dist/esm/src/components/CallRecordingList/CallRecordingListHeader.js.map +1 -0
  57. package/dist/esm/src/components/CallRecordingList/CallRecordingListItem.js +14 -0
  58. package/dist/esm/src/components/CallRecordingList/CallRecordingListItem.js.map +1 -0
  59. package/dist/esm/src/components/CallRecordingList/EmptyCallRecordingListing.js +8 -0
  60. package/dist/esm/src/components/CallRecordingList/EmptyCallRecordingListing.js.map +1 -0
  61. package/dist/esm/src/components/CallRecordingList/LoadingCallRecordingListing.js +10 -0
  62. package/dist/esm/src/components/CallRecordingList/LoadingCallRecordingListing.js.map +1 -0
  63. package/dist/esm/src/components/CallStats/CallStats.js +180 -0
  64. package/dist/esm/src/components/CallStats/CallStats.js.map +1 -0
  65. package/dist/{latency-chart-Bj5OSYzg.es.js → esm/src/components/CallStats/CallStatsLatencyChart.js} +1 -1
  66. package/dist/esm/src/components/CallStats/CallStatsLatencyChart.js.map +1 -0
  67. package/dist/esm/src/components/DeviceSettings/AudioVolumeIndicator.js +27 -0
  68. package/dist/esm/src/components/DeviceSettings/AudioVolumeIndicator.js.map +1 -0
  69. package/dist/esm/src/components/DeviceSettings/DeviceAudioPreviewItem.js +42 -0
  70. package/dist/esm/src/components/DeviceSettings/DeviceAudioPreviewItem.js.map +1 -0
  71. package/dist/esm/src/components/DeviceSettings/DeviceSelector.js +67 -0
  72. package/dist/esm/src/components/DeviceSettings/DeviceSelector.js.map +1 -0
  73. package/dist/esm/src/components/DeviceSettings/DeviceSelectorAudio.js +26 -0
  74. package/dist/esm/src/components/DeviceSettings/DeviceSelectorAudio.js.map +1 -0
  75. package/dist/esm/src/components/DeviceSettings/DeviceSelectorVideo.js +15 -0
  76. package/dist/esm/src/components/DeviceSettings/DeviceSelectorVideo.js.map +1 -0
  77. package/dist/esm/src/components/DeviceSettings/DeviceSettings.js +26 -0
  78. package/dist/esm/src/components/DeviceSettings/DeviceSettings.js.map +1 -0
  79. package/dist/esm/src/components/DeviceSettings/DeviceVideoPreviewItem.js +42 -0
  80. package/dist/esm/src/components/DeviceSettings/DeviceVideoPreviewItem.js.map +1 -0
  81. package/dist/esm/src/components/DeviceSettings/SpeakerTest.js +57 -0
  82. package/dist/esm/src/components/DeviceSettings/SpeakerTest.js.map +1 -0
  83. package/dist/esm/src/components/DropdownSelect/DropdownSelect.js +79 -0
  84. package/dist/esm/src/components/DropdownSelect/DropdownSelect.js.map +1 -0
  85. package/dist/esm/src/components/Icon/Icon.js +7 -0
  86. package/dist/esm/src/components/Icon/Icon.js.map +1 -0
  87. package/dist/esm/src/components/LoadingIndicator/LoadingIndicator.js +9 -0
  88. package/dist/esm/src/components/LoadingIndicator/LoadingIndicator.js.map +1 -0
  89. package/dist/esm/src/components/Menu/GenericMenu.js +19 -0
  90. package/dist/esm/src/components/Menu/GenericMenu.js.map +1 -0
  91. package/dist/esm/src/components/Menu/MenuToggle.js +75 -0
  92. package/dist/esm/src/components/Menu/MenuToggle.js.map +1 -0
  93. package/dist/esm/src/components/NoiseCancellation/NoiseCancellationProvider.js +96 -0
  94. package/dist/esm/src/components/NoiseCancellation/NoiseCancellationProvider.js.map +1 -0
  95. package/dist/esm/src/components/Notification/MicCaptureErrorNotification.js +23 -0
  96. package/dist/esm/src/components/Notification/MicCaptureErrorNotification.js.map +1 -0
  97. package/dist/esm/src/components/Notification/Notification.js +31 -0
  98. package/dist/esm/src/components/Notification/Notification.js.map +1 -0
  99. package/dist/esm/src/components/Notification/PermissionNotification.js +32 -0
  100. package/dist/esm/src/components/Notification/PermissionNotification.js.map +1 -0
  101. package/dist/esm/src/components/Notification/RecordingInProgressNotification.js +23 -0
  102. package/dist/esm/src/components/Notification/RecordingInProgressNotification.js.map +1 -0
  103. package/dist/esm/src/components/Notification/SpeakingWhileMutedNotification.js +14 -0
  104. package/dist/esm/src/components/Notification/SpeakingWhileMutedNotification.js.map +1 -0
  105. package/dist/esm/src/components/Permissions/PermissionRequests.js +99 -0
  106. package/dist/esm/src/components/Permissions/PermissionRequests.js.map +1 -0
  107. package/dist/esm/src/components/Reaction/Reaction.js +32 -0
  108. package/dist/esm/src/components/Reaction/Reaction.js.map +1 -0
  109. package/dist/esm/src/components/RingingCall/RingingCall.js +48 -0
  110. package/dist/esm/src/components/RingingCall/RingingCall.js.map +1 -0
  111. package/dist/esm/src/components/RingingCall/RingingCallControls.js +34 -0
  112. package/dist/esm/src/components/RingingCall/RingingCallControls.js.map +1 -0
  113. package/dist/esm/src/components/Search/SearchInput.js +27 -0
  114. package/dist/esm/src/components/Search/SearchInput.js.map +1 -0
  115. package/dist/esm/src/components/Search/SearchResults.js +15 -0
  116. package/dist/esm/src/components/Search/SearchResults.js.map +1 -0
  117. package/dist/esm/src/components/Search/hooks/useSearch.js +38 -0
  118. package/dist/esm/src/components/Search/hooks/useSearch.js.map +1 -0
  119. package/dist/esm/src/components/StreamTheme/StreamTheme.js +9 -0
  120. package/dist/esm/src/components/StreamTheme/StreamTheme.js.map +1 -0
  121. package/dist/esm/src/components/Tooltip/Tooltip.js +29 -0
  122. package/dist/esm/src/components/Tooltip/Tooltip.js.map +1 -0
  123. package/dist/esm/src/components/Tooltip/WithTooltip.js +15 -0
  124. package/dist/esm/src/components/Tooltip/WithTooltip.js.map +1 -0
  125. package/dist/esm/src/components/Tooltip/hooks/useEnterLeaveHandlers.js +17 -0
  126. package/dist/esm/src/components/Tooltip/hooks/useEnterLeaveHandlers.js.map +1 -0
  127. package/dist/esm/src/components/VideoPreview/VideoPreview.js +37 -0
  128. package/dist/esm/src/components/VideoPreview/VideoPreview.js.map +1 -0
  129. package/dist/esm/src/core/components/Audio/Audio.js +22 -0
  130. package/dist/esm/src/core/components/Audio/Audio.js.map +1 -0
  131. package/dist/esm/src/core/components/Audio/ParticipantsAudio.js +23 -0
  132. package/dist/esm/src/core/components/Audio/ParticipantsAudio.js.map +1 -0
  133. package/dist/esm/src/core/components/CallLayout/LivestreamLayout.js +150 -0
  134. package/dist/esm/src/core/components/CallLayout/LivestreamLayout.js.map +1 -0
  135. package/dist/esm/src/core/components/CallLayout/PaginatedGridLayout.js +79 -0
  136. package/dist/esm/src/core/components/CallLayout/PaginatedGridLayout.js.map +1 -0
  137. package/dist/esm/src/core/components/CallLayout/PipLayout/Grid.js +80 -0
  138. package/dist/esm/src/core/components/CallLayout/PipLayout/Grid.js.map +1 -0
  139. package/dist/esm/src/core/components/CallLayout/PipLayout/Host.js +13 -0
  140. package/dist/esm/src/core/components/CallLayout/PipLayout/Host.js.map +1 -0
  141. package/dist/esm/src/core/components/CallLayout/PipLayout/Pip.js +57 -0
  142. package/dist/esm/src/core/components/CallLayout/PipLayout/Pip.js.map +1 -0
  143. package/dist/esm/src/core/components/CallLayout/PipLayout/index.js +8 -0
  144. package/dist/esm/src/core/components/CallLayout/PipLayout/index.js.map +1 -0
  145. package/dist/esm/src/core/components/CallLayout/SpeakerLayout.js +103 -0
  146. package/dist/esm/src/core/components/CallLayout/SpeakerLayout.js.map +1 -0
  147. package/dist/esm/src/core/components/CallLayout/hooks.js +62 -0
  148. package/dist/esm/src/core/components/CallLayout/hooks.js.map +1 -0
  149. package/dist/esm/src/core/components/ParticipantView/DefaultParticipantViewUI.js +94 -0
  150. package/dist/esm/src/core/components/ParticipantView/DefaultParticipantViewUI.js.map +1 -0
  151. package/dist/esm/src/core/components/ParticipantView/ParticipantActionsContextMenu.js +97 -0
  152. package/dist/esm/src/core/components/ParticipantView/ParticipantActionsContextMenu.js.map +1 -0
  153. package/dist/esm/src/core/components/ParticipantView/ParticipantView.js +65 -0
  154. package/dist/esm/src/core/components/ParticipantView/ParticipantView.js.map +1 -0
  155. package/dist/esm/src/core/components/ParticipantView/ParticipantViewContext.js +7 -0
  156. package/dist/esm/src/core/components/ParticipantView/ParticipantViewContext.js.map +1 -0
  157. package/dist/esm/src/core/components/StreamCall/StreamCall.js +8 -0
  158. package/dist/esm/src/core/components/StreamCall/StreamCall.js.map +1 -0
  159. package/dist/esm/src/core/components/StreamVideo/StreamVideo.js +11 -0
  160. package/dist/esm/src/core/components/StreamVideo/StreamVideo.js.map +1 -0
  161. package/dist/esm/src/core/components/Video/BaseVideo.js +41 -0
  162. package/dist/esm/src/core/components/Video/BaseVideo.js.map +1 -0
  163. package/dist/esm/src/core/components/Video/BaseVideoPlaceholder.js +21 -0
  164. package/dist/esm/src/core/components/Video/BaseVideoPlaceholder.js.map +1 -0
  165. package/dist/esm/src/core/components/Video/DefaultPictureInPicturePlaceholder.js +12 -0
  166. package/dist/esm/src/core/components/Video/DefaultPictureInPicturePlaceholder.js.map +1 -0
  167. package/dist/esm/src/core/components/Video/DefaultVideoPlaceholder.js +12 -0
  168. package/dist/esm/src/core/components/Video/DefaultVideoPlaceholder.js.map +1 -0
  169. package/dist/esm/src/core/components/Video/Video.js +88 -0
  170. package/dist/esm/src/core/components/Video/Video.js.map +1 -0
  171. package/dist/esm/src/core/hooks/useCalculateHardLimit.js +59 -0
  172. package/dist/esm/src/core/hooks/useCalculateHardLimit.js.map +1 -0
  173. package/dist/esm/src/core/hooks/usePictureInPictureState.js +24 -0
  174. package/dist/esm/src/core/hooks/usePictureInPictureState.js.map +1 -0
  175. package/dist/esm/src/core/hooks/useTrackElementVisibility.js +14 -0
  176. package/dist/esm/src/core/hooks/useTrackElementVisibility.js.map +1 -0
  177. package/dist/esm/src/embedded/EmbeddedClientProvider.js +83 -0
  178. package/dist/esm/src/embedded/EmbeddedClientProvider.js.map +1 -0
  179. package/dist/esm/src/embedded/call/CallControls.js +65 -0
  180. package/dist/esm/src/embedded/call/CallControls.js.map +1 -0
  181. package/dist/esm/src/embedded/call/CallHeader.js +57 -0
  182. package/dist/esm/src/embedded/call/CallHeader.js.map +1 -0
  183. package/dist/esm/src/embedded/call/CallLayout.js +63 -0
  184. package/dist/esm/src/embedded/call/CallLayout.js.map +1 -0
  185. package/dist/esm/src/embedded/call/CallStateRouter.js +87 -0
  186. package/dist/esm/src/embedded/call/CallStateRouter.js.map +1 -0
  187. package/dist/esm/src/embedded/call/EmbeddedCall.js +12 -0
  188. package/dist/esm/src/embedded/call/EmbeddedCall.js.map +1 -0
  189. package/dist/esm/src/embedded/context/ConfigurationContext.js +21 -0
  190. package/dist/esm/src/embedded/context/ConfigurationContext.js.map +1 -0
  191. package/dist/esm/src/embedded/hooks/useCallDuration.js +32 -0
  192. package/dist/esm/src/embedded/hooks/useCallDuration.js.map +1 -0
  193. package/dist/esm/src/embedded/hooks/useEmbeddedClient.js +40 -0
  194. package/dist/esm/src/embedded/hooks/useEmbeddedClient.js.map +1 -0
  195. package/dist/esm/src/embedded/hooks/useInitializeCall.js +39 -0
  196. package/dist/esm/src/embedded/hooks/useInitializeCall.js.map +1 -0
  197. package/dist/esm/src/embedded/hooks/useInitializeVideoClient.js +93 -0
  198. package/dist/esm/src/embedded/hooks/useInitializeVideoClient.js.map +1 -0
  199. package/dist/esm/src/embedded/hooks/useIsLivestreamPaused.js +42 -0
  200. package/dist/esm/src/embedded/hooks/useIsLivestreamPaused.js.map +1 -0
  201. package/dist/esm/src/embedded/hooks/useLayout.js +122 -0
  202. package/dist/esm/src/embedded/hooks/useLayout.js.map +1 -0
  203. package/dist/esm/src/embedded/hooks/useNoiseCancellationLoader.js +48 -0
  204. package/dist/esm/src/embedded/hooks/useNoiseCancellationLoader.js.map +1 -0
  205. package/dist/esm/src/embedded/hooks/useWakeLock.js +34 -0
  206. package/dist/esm/src/embedded/hooks/useWakeLock.js.map +1 -0
  207. package/dist/esm/src/embedded/livestream/EmbeddedLivestream.js +11 -0
  208. package/dist/esm/src/embedded/livestream/EmbeddedLivestream.js.map +1 -0
  209. package/dist/esm/src/embedded/livestream/LivestreamUI.js +17 -0
  210. package/dist/esm/src/embedded/livestream/LivestreamUI.js.map +1 -0
  211. package/dist/esm/src/embedded/livestream/host/HostLayout.js +76 -0
  212. package/dist/esm/src/embedded/livestream/host/HostLayout.js.map +1 -0
  213. package/dist/esm/src/embedded/livestream/host/HostStateRouter.js +110 -0
  214. package/dist/esm/src/embedded/livestream/host/HostStateRouter.js.map +1 -0
  215. package/dist/esm/src/embedded/livestream/viewer/ViewerLayout.js +74 -0
  216. package/dist/esm/src/embedded/livestream/viewer/ViewerLayout.js.map +1 -0
  217. package/dist/esm/src/embedded/livestream/viewer/ViewerLobby.js +109 -0
  218. package/dist/esm/src/embedded/livestream/viewer/ViewerLobby.js.map +1 -0
  219. package/dist/esm/src/embedded/livestream/viewer/ViewerStateRouter.js +105 -0
  220. package/dist/esm/src/embedded/livestream/viewer/ViewerStateRouter.js.map +1 -0
  221. package/dist/esm/src/embedded/shared/BlurToggleButton/BlurToggleButton.js +65 -0
  222. package/dist/esm/src/embedded/shared/BlurToggleButton/BlurToggleButton.js.map +1 -0
  223. package/dist/esm/src/embedded/shared/CallFeedback/CallEndedScreen.js +34 -0
  224. package/dist/esm/src/embedded/shared/CallFeedback/CallEndedScreen.js.map +1 -0
  225. package/dist/esm/src/embedded/shared/CallFeedback/CallFeedback.js +35 -0
  226. package/dist/esm/src/embedded/shared/CallFeedback/CallFeedback.js.map +1 -0
  227. package/dist/esm/src/embedded/shared/CallFeedback/RatingScreen.js +18 -0
  228. package/dist/esm/src/embedded/shared/CallFeedback/RatingScreen.js.map +1 -0
  229. package/dist/esm/src/embedded/shared/CallFeedback/StarRating.js +37 -0
  230. package/dist/esm/src/embedded/shared/CallFeedback/StarRating.js.map +1 -0
  231. package/dist/esm/src/embedded/shared/CallFeedback/ThankYouScreen.js +34 -0
  232. package/dist/esm/src/embedded/shared/CallFeedback/ThankYouScreen.js.map +1 -0
  233. package/dist/esm/src/embedded/shared/ConnectionNotification/ConnectionNotification.js +56 -0
  234. package/dist/esm/src/embedded/shared/ConnectionNotification/ConnectionNotification.js.map +1 -0
  235. package/dist/esm/src/embedded/shared/EmbeddedParticipantViewUI/EmbeddedParticipantViewUI.js +42 -0
  236. package/dist/esm/src/embedded/shared/EmbeddedParticipantViewUI/EmbeddedParticipantViewUI.js.map +1 -0
  237. package/dist/esm/src/embedded/shared/JoinError/JoinError.js +34 -0
  238. package/dist/esm/src/embedded/shared/JoinError/JoinError.js.map +1 -0
  239. package/dist/esm/src/embedded/shared/Lobby/DeviceControls.js +44 -0
  240. package/dist/esm/src/embedded/shared/Lobby/DeviceControls.js.map +1 -0
  241. package/dist/esm/src/embedded/shared/Lobby/DisabledDeviceButton.js +31 -0
  242. package/dist/esm/src/embedded/shared/Lobby/DisabledDeviceButton.js.map +1 -0
  243. package/dist/esm/src/embedded/shared/Lobby/Lobby.js +45 -0
  244. package/dist/esm/src/embedded/shared/Lobby/Lobby.js.map +1 -0
  245. package/dist/esm/src/embedded/shared/Lobby/ToggleCameraButton.js +40 -0
  246. package/dist/esm/src/embedded/shared/Lobby/ToggleCameraButton.js.map +1 -0
  247. package/dist/esm/src/embedded/shared/Lobby/ToggleMicButton.js +41 -0
  248. package/dist/esm/src/embedded/shared/Lobby/ToggleMicButton.js.map +1 -0
  249. package/dist/esm/src/embedded/shared/Lobby/VideoPreviewFallbacks.js +50 -0
  250. package/dist/esm/src/embedded/shared/Lobby/VideoPreviewFallbacks.js.map +1 -0
  251. package/dist/esm/src/embedded/shared/ViewersCount/ViewersCount.js +31 -0
  252. package/dist/esm/src/embedded/shared/ViewersCount/ViewersCount.js.map +1 -0
  253. package/dist/esm/src/hooks/useDeviceList.js +40 -0
  254. package/dist/esm/src/hooks/useDeviceList.js.map +1 -0
  255. package/dist/esm/src/hooks/useDragToScroll.js +116 -0
  256. package/dist/esm/src/hooks/useDragToScroll.js.map +1 -0
  257. package/dist/esm/src/hooks/useFloatingUIPreset.js +34 -0
  258. package/dist/esm/src/hooks/useFloatingUIPreset.js.map +1 -0
  259. package/dist/esm/src/hooks/useLoopbackRecording.js +138 -0
  260. package/dist/esm/src/hooks/useLoopbackRecording.js.map +1 -0
  261. package/dist/esm/src/hooks/useModeration.js +135 -0
  262. package/dist/esm/src/hooks/useModeration.js.map +1 -0
  263. package/dist/esm/src/hooks/usePersistedDevicePreferences.js +16 -0
  264. package/dist/esm/src/hooks/usePersistedDevicePreferences.js.map +1 -0
  265. package/dist/esm/src/hooks/useRequestPermission.js +41 -0
  266. package/dist/esm/src/hooks/useRequestPermission.js.map +1 -0
  267. package/dist/esm/src/hooks/useScrollPosition.js +66 -0
  268. package/dist/esm/src/hooks/useScrollPosition.js.map +1 -0
  269. package/dist/esm/src/translations/en.json.js +177 -0
  270. package/dist/esm/src/translations/en.json.js.map +1 -0
  271. package/dist/esm/src/translations/index.js +6 -0
  272. package/dist/esm/src/translations/index.js.map +1 -0
  273. package/dist/esm/src/utilities/applyElementToRef.js +10 -0
  274. package/dist/esm/src/utilities/applyElementToRef.js.map +1 -0
  275. package/dist/esm/src/utilities/callControlHandler.js +29 -0
  276. package/dist/esm/src/utilities/callControlHandler.js.map +1 -0
  277. package/dist/esm/src/utilities/chunk.js +7 -0
  278. package/dist/esm/src/utilities/chunk.js.map +1 -0
  279. package/dist/esm/src/utilities/filter.js +94 -0
  280. package/dist/esm/src/utilities/filter.js.map +1 -0
  281. package/dist/esm/src/utilities/isComponentType.js +10 -0
  282. package/dist/esm/src/utilities/isComponentType.js.map +1 -0
  283. package/dist/esm/src/utilities/normalizeString.js +11 -0
  284. package/dist/esm/src/utilities/normalizeString.js.map +1 -0
  285. package/dist/esm/src/wrappers/LivestreamPlayer/LivestreamPlayer.js +105 -0
  286. package/dist/esm/src/wrappers/LivestreamPlayer/LivestreamPlayer.js.map +1 -0
  287. package/dist/index.cjs.js +135 -2
  288. package/dist/index.cjs.js.map +1 -1
  289. package/dist/index.d.ts +1 -1
  290. package/dist/src/hooks/index.d.ts +1 -0
  291. package/dist/src/hooks/useLoopbackRecording.d.ts +23 -0
  292. package/index.ts +4 -0
  293. package/package.json +14 -10
  294. package/src/hooks/index.ts +1 -0
  295. package/src/hooks/useLoopbackRecording.ts +207 -0
  296. package/dist/background-filters-D2U5UBbH.es.js.map +0 -1
  297. package/dist/embedded-BackgroundFilters-D2U5UBbH.es.js +0 -420
  298. package/dist/embedded-BackgroundFilters-D2U5UBbH.es.js.map +0 -1
  299. package/dist/embedded-CallStatsLatencyChart-Bj5OSYzg.es.js +0 -57
  300. package/dist/embedded-CallStatsLatencyChart-Bj5OSYzg.es.js.map +0 -1
  301. package/dist/embedded.es.js +0 -3536
  302. package/dist/embedded.es.js.map +0 -1
  303. package/dist/index.es.js +0 -3291
  304. package/dist/index.es.js.map +0 -1
  305. package/dist/latency-chart-Bj5OSYzg.es.js.map +0 -1
@@ -0,0 +1,97 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { useCall, useI18n, Restricted } from '@stream-io/video-react-bindings';
4
+ import { hasAudio, hasVideo, hasScreenShare, hasScreenShareAudio, OwnCapability } from '@stream-io/video-client';
5
+ import { useParticipantViewContext } from './ParticipantViewContext.js';
6
+ import { useMenuContext } from '../../../components/Menu/MenuToggle.js';
7
+ import { GenericMenu, GenericMenuButtonItem } from '../../../components/Menu/GenericMenu.js';
8
+ import { Icon } from '../../../components/Icon/Icon.js';
9
+ import { usePictureInPictureState } from '../../hooks/usePictureInPictureState.js';
10
+
11
+ const ParticipantActionsContextMenu = () => {
12
+ const { participant, participantViewElement, videoElement } = useParticipantViewContext();
13
+ const [fullscreenModeOn, setFullscreenModeOn] = useState(!!document.fullscreenElement);
14
+ const call = useCall();
15
+ const isPiP = usePictureInPictureState(videoElement ?? undefined);
16
+ const { t } = useI18n();
17
+ const { pin, sessionId, userId } = participant;
18
+ const hasAudioTrack = hasAudio(participant);
19
+ const hasVideoTrack = hasVideo(participant);
20
+ const hasScreenShareTrack = hasScreenShare(participant);
21
+ const hasScreenShareAudioTrack = hasScreenShareAudio(participant);
22
+ const blockUser = () => call?.blockUser(userId);
23
+ const kickUser = () => call?.kickUser({ user_id: userId });
24
+ const muteAudio = () => call?.muteUser(userId, 'audio');
25
+ const muteVideo = () => call?.muteUser(userId, 'video');
26
+ const muteScreenShare = () => call?.muteUser(userId, 'screenshare');
27
+ const muteScreenShareAudio = () => call?.muteUser(userId, 'screenshare_audio');
28
+ const grantPermission = (permission) => () => {
29
+ call?.updateUserPermissions({
30
+ user_id: userId,
31
+ grant_permissions: [permission],
32
+ });
33
+ };
34
+ const revokePermission = (permission) => () => {
35
+ call?.updateUserPermissions({
36
+ user_id: userId,
37
+ revoke_permissions: [permission],
38
+ });
39
+ };
40
+ const toggleParticipantPin = () => {
41
+ if (pin) {
42
+ call?.unpin(sessionId);
43
+ }
44
+ else {
45
+ call?.pin(sessionId);
46
+ }
47
+ };
48
+ const pinForEveryone = () => {
49
+ call
50
+ ?.pinForEveryone({ user_id: userId, session_id: sessionId })
51
+ .catch((err) => {
52
+ console.error(`Failed to pin participant ${userId}`, err);
53
+ });
54
+ };
55
+ const unpinForEveryone = () => {
56
+ call
57
+ ?.unpinForEveryone({ user_id: userId, session_id: sessionId })
58
+ .catch((err) => {
59
+ console.error(`Failed to unpin participant ${userId}`, err);
60
+ });
61
+ };
62
+ const toggleFullscreenMode = () => {
63
+ if (!fullscreenModeOn) {
64
+ return participantViewElement?.requestFullscreen().catch(console.error);
65
+ }
66
+ return document.exitFullscreen().catch(console.error);
67
+ };
68
+ useEffect(() => {
69
+ // handles the case when fullscreen mode is toggled externally,
70
+ // e.g., by pressing ESC key or some other keyboard shortcut
71
+ const handleFullscreenChange = () => {
72
+ setFullscreenModeOn(!!document.fullscreenElement);
73
+ };
74
+ document.addEventListener('fullscreenchange', handleFullscreenChange);
75
+ return () => {
76
+ document.removeEventListener('fullscreenchange', handleFullscreenChange);
77
+ };
78
+ }, []);
79
+ const togglePictureInPicture = () => {
80
+ if (videoElement && !isPiP) {
81
+ return videoElement
82
+ .requestPictureInPicture()
83
+ .catch(console.error);
84
+ }
85
+ return document.exitPictureInPicture().catch(console.error);
86
+ };
87
+ const { close } = useMenuContext() || {};
88
+ return (jsxs(GenericMenu, { onItemClick: close, children: [jsxs(GenericMenuButtonItem, { onClick: toggleParticipantPin, disabled: pin && !pin.isLocalPin, children: [jsx(Icon, { icon: "pin" }), pin ? t('Unpin') : t('Pin')] }), jsxs(Restricted, { requiredGrants: [OwnCapability.PIN_FOR_EVERYONE], children: [jsxs(GenericMenuButtonItem, { onClick: pinForEveryone, disabled: pin && !pin.isLocalPin, children: [jsx(Icon, { icon: "pin" }), t('Pin for everyone')] }), jsxs(GenericMenuButtonItem, { onClick: unpinForEveryone, disabled: !pin || pin.isLocalPin, children: [jsx(Icon, { icon: "pin" }), t('Unpin for everyone')] })] }), jsx(Restricted, { requiredGrants: [OwnCapability.BLOCK_USERS], children: jsxs(GenericMenuButtonItem, { onClick: blockUser, children: [jsx(Icon, { icon: "not-allowed" }), t('Block')] }) }), jsx(Restricted, { requiredGrants: [OwnCapability.KICK_USER], children: jsxs(GenericMenuButtonItem, { onClick: kickUser, children: [jsx(Icon, { icon: "kick-user" }), t('Kick')] }) }), jsxs(Restricted, { requiredGrants: [OwnCapability.MUTE_USERS], children: [hasVideoTrack && (jsxs(GenericMenuButtonItem, { onClick: muteVideo, children: [jsx(Icon, { icon: "camera-off-outline" }), t('Turn off video')] })), hasScreenShareTrack && (jsxs(GenericMenuButtonItem, { onClick: muteScreenShare, children: [jsx(Icon, { icon: "screen-share-off" }), t('Turn off screen share')] })), hasAudioTrack && (jsxs(GenericMenuButtonItem, { onClick: muteAudio, children: [jsx(Icon, { icon: "no-audio" }), t('Mute audio')] })), hasScreenShareAudioTrack && (jsxs(GenericMenuButtonItem, { onClick: muteScreenShareAudio, children: [jsx(Icon, { icon: "no-audio" }), t('Mute screen share audio')] }))] }), participantViewElement &&
89
+ typeof participantViewElement.requestFullscreen !== 'undefined' && (jsx(GenericMenuButtonItem, { onClick: toggleFullscreenMode, children: t('{{ direction }} fullscreen', {
90
+ direction: fullscreenModeOn ? t('Leave') : t('Enter'),
91
+ }) })), videoElement && document.pictureInPictureEnabled && (jsx(GenericMenuButtonItem, { onClick: togglePictureInPicture, children: t('{{ direction }} picture-in-picture', {
92
+ direction: isPiP ? t('Leave') : t('Enter'),
93
+ }) })), jsxs(Restricted, { requiredGrants: [OwnCapability.UPDATE_CALL_PERMISSIONS], children: [jsx(GenericMenuButtonItem, { onClick: grantPermission(OwnCapability.SEND_AUDIO), children: t('Allow audio') }), jsx(GenericMenuButtonItem, { onClick: grantPermission(OwnCapability.SEND_VIDEO), children: t('Allow video') }), jsx(GenericMenuButtonItem, { onClick: grantPermission(OwnCapability.SCREENSHARE), children: t('Allow screen sharing') }), jsx(GenericMenuButtonItem, { onClick: revokePermission(OwnCapability.SEND_AUDIO), children: t('Disable audio') }), jsx(GenericMenuButtonItem, { onClick: revokePermission(OwnCapability.SEND_VIDEO), children: t('Disable video') }), jsx(GenericMenuButtonItem, { onClick: revokePermission(OwnCapability.SCREENSHARE), children: t('Disable screen sharing') })] })] }));
94
+ };
95
+
96
+ export { ParticipantActionsContextMenu };
97
+ //# sourceMappingURL=ParticipantActionsContextMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParticipantActionsContextMenu.js","sources":["../../../../../../../../src/core/components/ParticipantView/ParticipantActionsContextMenu.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Restricted, useCall, useI18n } from '@stream-io/video-react-bindings';\nimport {\n hasAudio,\n hasScreenShare,\n hasScreenShareAudio,\n hasVideo,\n OwnCapability,\n UpdateUserPermissionsRequestGrantPermissionsEnum,\n UpdateUserPermissionsRequestRevokePermissionsEnum,\n} from '@stream-io/video-client';\nimport { useParticipantViewContext } from './ParticipantViewContext';\nimport {\n GenericMenu,\n GenericMenuButtonItem,\n useMenuContext,\n} from '../../../components/Menu';\nimport { Icon } from '../../../components/Icon';\nimport { usePictureInPictureState } from '../../hooks/usePictureInPictureState';\n\nexport const ParticipantActionsContextMenu = () => {\n const { participant, participantViewElement, videoElement } =\n useParticipantViewContext();\n const [fullscreenModeOn, setFullscreenModeOn] = useState(\n !!document.fullscreenElement,\n );\n const call = useCall();\n const isPiP = usePictureInPictureState(videoElement ?? undefined);\n const { t } = useI18n();\n\n const { pin, sessionId, userId } = participant;\n\n const hasAudioTrack = hasAudio(participant);\n const hasVideoTrack = hasVideo(participant);\n const hasScreenShareTrack = hasScreenShare(participant);\n const hasScreenShareAudioTrack = hasScreenShareAudio(participant);\n\n const blockUser = () => call?.blockUser(userId);\n const kickUser = () => call?.kickUser({ user_id: userId });\n const muteAudio = () => call?.muteUser(userId, 'audio');\n const muteVideo = () => call?.muteUser(userId, 'video');\n const muteScreenShare = () => call?.muteUser(userId, 'screenshare');\n const muteScreenShareAudio = () =>\n call?.muteUser(userId, 'screenshare_audio');\n\n const grantPermission =\n (permission: UpdateUserPermissionsRequestGrantPermissionsEnum) => () => {\n call?.updateUserPermissions({\n user_id: userId,\n grant_permissions: [permission],\n });\n };\n\n const revokePermission =\n (permission: UpdateUserPermissionsRequestRevokePermissionsEnum) => () => {\n call?.updateUserPermissions({\n user_id: userId,\n revoke_permissions: [permission],\n });\n };\n\n const toggleParticipantPin = () => {\n if (pin) {\n call?.unpin(sessionId);\n } else {\n call?.pin(sessionId);\n }\n };\n\n const pinForEveryone = () => {\n call\n ?.pinForEveryone({ user_id: userId, session_id: sessionId })\n .catch((err) => {\n console.error(`Failed to pin participant ${userId}`, err);\n });\n };\n\n const unpinForEveryone = () => {\n call\n ?.unpinForEveryone({ user_id: userId, session_id: sessionId })\n .catch((err) => {\n console.error(`Failed to unpin participant ${userId}`, err);\n });\n };\n\n const toggleFullscreenMode = () => {\n if (!fullscreenModeOn) {\n return participantViewElement?.requestFullscreen().catch(console.error);\n }\n return document.exitFullscreen().catch(console.error);\n };\n\n useEffect(() => {\n // handles the case when fullscreen mode is toggled externally,\n // e.g., by pressing ESC key or some other keyboard shortcut\n const handleFullscreenChange = () => {\n setFullscreenModeOn(!!document.fullscreenElement);\n };\n document.addEventListener('fullscreenchange', handleFullscreenChange);\n return () => {\n document.removeEventListener('fullscreenchange', handleFullscreenChange);\n };\n }, []);\n\n const togglePictureInPicture = () => {\n if (videoElement && !isPiP) {\n return videoElement\n .requestPictureInPicture()\n .catch(console.error) as Promise<void>;\n }\n\n return document.exitPictureInPicture().catch(console.error);\n };\n\n const { close } = useMenuContext() || {};\n return (\n <GenericMenu onItemClick={close}>\n <GenericMenuButtonItem\n onClick={toggleParticipantPin}\n disabled={pin && !pin.isLocalPin}\n >\n <Icon icon=\"pin\" />\n {pin ? t('Unpin') : t('Pin')}\n </GenericMenuButtonItem>\n <Restricted requiredGrants={[OwnCapability.PIN_FOR_EVERYONE]}>\n <GenericMenuButtonItem\n onClick={pinForEveryone}\n disabled={pin && !pin.isLocalPin}\n >\n <Icon icon=\"pin\" />\n {t('Pin for everyone')}\n </GenericMenuButtonItem>\n <GenericMenuButtonItem\n onClick={unpinForEveryone}\n disabled={!pin || pin.isLocalPin}\n >\n <Icon icon=\"pin\" />\n {t('Unpin for everyone')}\n </GenericMenuButtonItem>\n </Restricted>\n <Restricted requiredGrants={[OwnCapability.BLOCK_USERS]}>\n <GenericMenuButtonItem onClick={blockUser}>\n <Icon icon=\"not-allowed\" />\n {t('Block')}\n </GenericMenuButtonItem>\n </Restricted>\n <Restricted requiredGrants={[OwnCapability.KICK_USER]}>\n <GenericMenuButtonItem onClick={kickUser}>\n <Icon icon=\"kick-user\" />\n {t('Kick')}\n </GenericMenuButtonItem>\n </Restricted>\n <Restricted requiredGrants={[OwnCapability.MUTE_USERS]}>\n {hasVideoTrack && (\n <GenericMenuButtonItem onClick={muteVideo}>\n <Icon icon=\"camera-off-outline\" />\n {t('Turn off video')}\n </GenericMenuButtonItem>\n )}\n {hasScreenShareTrack && (\n <GenericMenuButtonItem onClick={muteScreenShare}>\n <Icon icon=\"screen-share-off\" />\n {t('Turn off screen share')}\n </GenericMenuButtonItem>\n )}\n {hasAudioTrack && (\n <GenericMenuButtonItem onClick={muteAudio}>\n <Icon icon=\"no-audio\" />\n {t('Mute audio')}\n </GenericMenuButtonItem>\n )}\n {hasScreenShareAudioTrack && (\n <GenericMenuButtonItem onClick={muteScreenShareAudio}>\n <Icon icon=\"no-audio\" />\n {t('Mute screen share audio')}\n </GenericMenuButtonItem>\n )}\n </Restricted>\n {participantViewElement &&\n typeof participantViewElement.requestFullscreen !== 'undefined' && (\n <GenericMenuButtonItem onClick={toggleFullscreenMode}>\n {t('{{ direction }} fullscreen', {\n direction: fullscreenModeOn ? t('Leave') : t('Enter'),\n })}\n </GenericMenuButtonItem>\n )}\n {videoElement && document.pictureInPictureEnabled && (\n <GenericMenuButtonItem onClick={togglePictureInPicture}>\n {t('{{ direction }} picture-in-picture', {\n direction: isPiP ? t('Leave') : t('Enter'),\n })}\n </GenericMenuButtonItem>\n )}\n <Restricted requiredGrants={[OwnCapability.UPDATE_CALL_PERMISSIONS]}>\n <GenericMenuButtonItem\n onClick={grantPermission(OwnCapability.SEND_AUDIO)}\n >\n {t('Allow audio')}\n </GenericMenuButtonItem>\n <GenericMenuButtonItem\n onClick={grantPermission(OwnCapability.SEND_VIDEO)}\n >\n {t('Allow video')}\n </GenericMenuButtonItem>\n <GenericMenuButtonItem\n onClick={grantPermission(OwnCapability.SCREENSHARE)}\n >\n {t('Allow screen sharing')}\n </GenericMenuButtonItem>\n\n <GenericMenuButtonItem\n onClick={revokePermission(OwnCapability.SEND_AUDIO)}\n >\n {t('Disable audio')}\n </GenericMenuButtonItem>\n <GenericMenuButtonItem\n onClick={revokePermission(OwnCapability.SEND_VIDEO)}\n >\n {t('Disable video')}\n </GenericMenuButtonItem>\n <GenericMenuButtonItem\n onClick={revokePermission(OwnCapability.SCREENSHARE)}\n >\n {t('Disable screen sharing')}\n </GenericMenuButtonItem>\n </Restricted>\n </GenericMenu>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { memo, forwardRef, useState, useMemo } from 'react';
3
+ import clsx from 'clsx';
4
+ import { hasAudio, hasVideo, hasScreenShareAudio } from '@stream-io/video-client';
5
+ import { useCallStateHooks } from '@stream-io/video-react-bindings';
6
+ import { Audio } from '../Audio/Audio.js';
7
+ import '../Audio/ParticipantsAudio.js';
8
+ import '../Video/BaseVideo.js';
9
+ import { Video } from '../Video/Video.js';
10
+ import { useTrackElementVisibility } from '../../hooks/useTrackElementVisibility.js';
11
+ import { DefaultParticipantViewUI } from './DefaultParticipantViewUI.js';
12
+ import { isComponentType } from '../../../utilities/isComponentType.js';
13
+ import { applyElementToRef } from '../../../utilities/applyElementToRef.js';
14
+ import { ParticipantViewContext } from './ParticipantViewContext.js';
15
+
16
+ const ParticipantView = memo(forwardRef(function ParticipantViewRender({ participant, trackType = 'videoTrack', mirror, muteAudio, refs: { setVideoElement, setVideoPlaceholderElement } = {}, className, VideoPlaceholder, PictureInPicturePlaceholder, ParticipantViewUI = DefaultParticipantViewUI, }, ref) {
17
+ const { isLocalParticipant, isSpeaking, isDominantSpeaker, sessionId } = participant;
18
+ const hasAudioTrack = hasAudio(participant);
19
+ const hasVideoTrack = hasVideo(participant);
20
+ const hasScreenShareAudioTrack = hasScreenShareAudio(participant);
21
+ const [trackedElement, setTrackedElement] = useState(null);
22
+ const [contextVideoElement, setContextVideoElement] = useState(null);
23
+ const [contextVideoPlaceholderElement, setContextVideoPlaceholderElement,] = useState(null);
24
+ useTrackElementVisibility({
25
+ sessionId,
26
+ trackedElement,
27
+ trackType,
28
+ });
29
+ const { useIncomingVideoSettings } = useCallStateHooks();
30
+ const { isParticipantVideoEnabled } = useIncomingVideoSettings();
31
+ const participantViewContextValue = useMemo(() => ({
32
+ participant,
33
+ participantViewElement: trackedElement,
34
+ videoElement: contextVideoElement,
35
+ videoPlaceholderElement: contextVideoPlaceholderElement,
36
+ trackType,
37
+ }), [
38
+ contextVideoElement,
39
+ contextVideoPlaceholderElement,
40
+ participant,
41
+ trackedElement,
42
+ trackType,
43
+ ]);
44
+ const videoRefs = useMemo(() => ({
45
+ setVideoElement: (element) => {
46
+ setVideoElement?.(element);
47
+ setContextVideoElement(element);
48
+ },
49
+ setVideoPlaceholderElement: (element) => {
50
+ setVideoPlaceholderElement?.(element);
51
+ setContextVideoPlaceholderElement(element);
52
+ },
53
+ }), [setVideoElement, setVideoPlaceholderElement]);
54
+ return (jsx("div", { "data-testid": "participant-view", ref: (element) => {
55
+ applyElementToRef(ref, element);
56
+ setTrackedElement(element);
57
+ }, className: clsx('str-video__participant-view', isDominantSpeaker &&
58
+ 'str-video__participant-view--dominant-speaker', isSpeaking && 'str-video__participant-view--speaking', !hasVideoTrack && 'str-video__participant-view--no-video', !hasAudioTrack && 'str-video__participant-view--no-audio', className), children: jsxs(ParticipantViewContext.Provider, { value: participantViewContextValue, children: [!isLocalParticipant && !muteAudio && (jsxs(Fragment, { children: [hasAudioTrack && (jsx(Audio, { participant: participant, trackType: "audioTrack" })), hasScreenShareAudioTrack && (jsx(Audio, { participant: participant, trackType: "screenShareAudioTrack" }))] })), jsx(Video, { VideoPlaceholder: VideoPlaceholder, PictureInPicturePlaceholder: PictureInPicturePlaceholder, participant: participant, trackType: trackType, refs: videoRefs, enabled: isLocalParticipant ||
59
+ trackType !== 'videoTrack' ||
60
+ isParticipantVideoEnabled(participant.sessionId), mirror: mirror, autoPlay: true }), isComponentType(ParticipantViewUI) ? (jsx(ParticipantViewUI, {})) : (ParticipantViewUI)] }) }));
61
+ }));
62
+ ParticipantView.displayName = 'ParticipantView';
63
+
64
+ export { ParticipantView };
65
+ //# sourceMappingURL=ParticipantView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParticipantView.js","sources":["../../../../../../../../src/core/components/ParticipantView/ParticipantView.tsx"],"sourcesContent":["import {\n ComponentType,\n forwardRef,\n memo,\n ReactElement,\n useMemo,\n useState,\n} from 'react';\nimport clsx from 'clsx';\nimport {\n hasAudio,\n hasScreenShareAudio,\n hasVideo,\n StreamVideoParticipant,\n VideoTrackType,\n} from '@stream-io/video-client';\nimport { useCallStateHooks } from '@stream-io/video-react-bindings';\n\nimport { Audio } from '../Audio';\nimport { Video, VideoProps } from '../Video';\nimport { useTrackElementVisibility } from '../../hooks';\nimport { DefaultParticipantViewUI } from './DefaultParticipantViewUI';\nimport { applyElementToRef, isComponentType } from '../../../utilities';\nimport { ParticipantViewContext } from './ParticipantViewContext';\n\nexport type ParticipantViewProps = {\n /**\n * The participant whose video/audio stream we want to play.\n */\n participant: StreamVideoParticipant;\n\n /**\n * Override the default UI for rendering participant information/actions.\n * pass `null` if you wish to not render anything\n * @default DefaultParticipantViewUI\n */\n ParticipantViewUI?: ComponentType | ReactElement | null;\n\n /**\n * The kind of video stream to play for the given participant.\n * The default value is `videoTrack`.\n * You can use `none` if you're building an audio-only call.\n */\n trackType?: VideoTrackType | 'none';\n\n /**\n * Forces participant's video to be mirrored or unmirrored. By default, video track\n * from the local participant is mirrored, and all other videos are not mirrored.\n */\n mirror?: boolean;\n\n /**\n * This prop is only useful for advanced use-cases (for example, building your own layout).\n * When set to `true` it will mute the give participant's audio stream on the client side.\n * The local participant is always muted.\n */\n muteAudio?: boolean;\n\n /**\n * An object with set functions meant for exposing the video\n * and video placeholder elements to the integrators.\n * It's useful when you want to attach custom event handlers to these elements.\n * - `refs.setVideoElement`\n * - `refs.setVideoPlaceholderElement`\n */\n refs?: VideoProps['refs'];\n\n /**\n * Custom class applied to the root DOM element.\n */\n className?: string;\n} & Pick<VideoProps, 'VideoPlaceholder' | 'PictureInPicturePlaceholder'>;\n\nexport const ParticipantView = memo(\n forwardRef<HTMLDivElement, ParticipantViewProps>(\n function ParticipantViewRender(\n {\n participant,\n trackType = 'videoTrack',\n mirror,\n muteAudio,\n refs: { setVideoElement, setVideoPlaceholderElement } = {},\n className,\n VideoPlaceholder,\n PictureInPicturePlaceholder,\n ParticipantViewUI = DefaultParticipantViewUI as ComponentType,\n },\n ref,\n ) {\n const { isLocalParticipant, isSpeaking, isDominantSpeaker, sessionId } =\n participant;\n\n const hasAudioTrack = hasAudio(participant);\n const hasVideoTrack = hasVideo(participant);\n const hasScreenShareAudioTrack = hasScreenShareAudio(participant);\n\n const [trackedElement, setTrackedElement] =\n useState<HTMLDivElement | null>(null);\n\n const [contextVideoElement, setContextVideoElement] =\n useState<HTMLVideoElement | null>(null);\n\n const [\n contextVideoPlaceholderElement,\n setContextVideoPlaceholderElement,\n ] = useState<HTMLDivElement | null>(null);\n\n useTrackElementVisibility({\n sessionId,\n trackedElement,\n trackType,\n });\n\n const { useIncomingVideoSettings } = useCallStateHooks();\n const { isParticipantVideoEnabled } = useIncomingVideoSettings();\n\n const participantViewContextValue = useMemo(\n () => ({\n participant,\n participantViewElement: trackedElement,\n videoElement: contextVideoElement,\n videoPlaceholderElement: contextVideoPlaceholderElement,\n trackType,\n }),\n [\n contextVideoElement,\n contextVideoPlaceholderElement,\n participant,\n trackedElement,\n trackType,\n ],\n );\n\n const videoRefs: VideoProps['refs'] = useMemo(\n () => ({\n setVideoElement: (element) => {\n setVideoElement?.(element);\n setContextVideoElement(element);\n },\n setVideoPlaceholderElement: (element) => {\n setVideoPlaceholderElement?.(element);\n setContextVideoPlaceholderElement(element);\n },\n }),\n [setVideoElement, setVideoPlaceholderElement],\n );\n\n return (\n <div\n data-testid=\"participant-view\"\n ref={(element) => {\n applyElementToRef(ref, element);\n setTrackedElement(element);\n }}\n className={clsx(\n 'str-video__participant-view',\n isDominantSpeaker &&\n 'str-video__participant-view--dominant-speaker',\n isSpeaking && 'str-video__participant-view--speaking',\n !hasVideoTrack && 'str-video__participant-view--no-video',\n !hasAudioTrack && 'str-video__participant-view--no-audio',\n className,\n )}\n >\n <ParticipantViewContext.Provider value={participantViewContextValue}>\n {/* mute the local participant, as we don't want to hear ourselves */}\n {!isLocalParticipant && !muteAudio && (\n <>\n {hasAudioTrack && (\n <Audio participant={participant} trackType=\"audioTrack\" />\n )}\n {hasScreenShareAudioTrack && (\n <Audio\n participant={participant}\n trackType=\"screenShareAudioTrack\"\n />\n )}\n </>\n )}\n <Video\n VideoPlaceholder={VideoPlaceholder}\n PictureInPicturePlaceholder={PictureInPicturePlaceholder}\n participant={participant}\n trackType={trackType}\n refs={videoRefs}\n enabled={\n isLocalParticipant ||\n trackType !== 'videoTrack' ||\n isParticipantVideoEnabled(participant.sessionId)\n }\n mirror={mirror}\n autoPlay\n />\n {isComponentType(ParticipantViewUI) ? (\n <ParticipantViewUI />\n ) : (\n ParticipantViewUI\n )}\n </ParticipantViewContext.Provider>\n </div>\n );\n },\n ),\n);\n\nParticipantView.displayName = 'ParticipantView';\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ const ParticipantViewContext = createContext(undefined);
4
+ const useParticipantViewContext = () => useContext(ParticipantViewContext);
5
+
6
+ export { ParticipantViewContext, useParticipantViewContext };
7
+ //# sourceMappingURL=ParticipantViewContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParticipantViewContext.js","sources":["../../../../../../../../src/core/components/ParticipantView/ParticipantViewContext.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\nimport { ParticipantViewProps } from './ParticipantView';\n\nexport type ParticipantViewContextValue = Required<\n Pick<ParticipantViewProps, 'participant' | 'trackType'>\n> & {\n participantViewElement?: HTMLDivElement | null;\n videoElement?: HTMLVideoElement | null;\n videoPlaceholderElement?: HTMLDivElement | null;\n};\n\nexport const ParticipantViewContext = createContext<\n ParticipantViewContextValue | undefined\n>(undefined);\n\nexport const useParticipantViewContext = () =>\n useContext(ParticipantViewContext) as ParticipantViewContextValue;\n"],"names":[],"mappings":";;MAWa,sBAAsB,GAAG,aAAa,CAEjD,SAAS;AAEJ,MAAM,yBAAyB,GAAG,MACvC,UAAU,CAAC,sBAAsB;;;;"}
@@ -0,0 +1,8 @@
1
+ import { StreamCallProvider } from '@stream-io/video-react-bindings';
2
+
3
+ // re-exporting the StreamCallProvider as StreamCall
4
+ const StreamCall = StreamCallProvider;
5
+ StreamCall.displayName = 'StreamCall';
6
+
7
+ export { StreamCall };
8
+ //# sourceMappingURL=StreamCall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamCall.js","sources":["../../../../../../../../src/core/components/StreamCall/StreamCall.tsx"],"sourcesContent":["import { ComponentType, PropsWithChildren } from 'react';\nimport {\n StreamCallProvider,\n StreamCallProviderProps,\n} from '@stream-io/video-react-bindings';\n\n// re-exporting the StreamCallProvider as StreamCall\nexport const StreamCall: ComponentType<\n PropsWithChildren<StreamCallProviderProps>\n> = StreamCallProvider;\n\nStreamCall.displayName = 'StreamCall';\n"],"names":[],"mappings":";;AAMA;AACO,MAAM,UAAU,GAEnB;AAEJ,UAAU,CAAC,WAAW,GAAG,YAAY;;;;"}
@@ -0,0 +1,11 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { StreamVideoProvider } from '@stream-io/video-react-bindings';
3
+ import { translations } from '../../../translations/index.js';
4
+
5
+ const StreamVideo = (props) => {
6
+ return (jsx(StreamVideoProvider, { translationsOverrides: translations, ...props }));
7
+ };
8
+ StreamVideo.displayName = 'StreamVideo';
9
+
10
+ export { StreamVideo };
11
+ //# sourceMappingURL=StreamVideo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamVideo.js","sources":["../../../../../../../../src/core/components/StreamVideo/StreamVideo.tsx"],"sourcesContent":["import {\n StreamVideoProps,\n StreamVideoProvider,\n} from '@stream-io/video-react-bindings';\nimport { PropsWithChildren } from 'react';\nimport { translations } from '../../../translations';\n\nexport const StreamVideo = (props: PropsWithChildren<StreamVideoProps>) => {\n return (\n <StreamVideoProvider translationsOverrides={translations} {...props} />\n );\n};\n\nStreamVideo.displayName = 'StreamVideo';\n"],"names":["_jsx"],"mappings":";;;;AAOO,MAAM,WAAW,GAAG,CAAC,KAA0C,KAAI;IACxE,QACEA,GAAA,CAAC,mBAAmB,EAAA,EAAC,qBAAqB,EAAE,YAAY,EAAA,GAAM,KAAK,EAAA,CAAI;AAE3E;AAEA,WAAW,CAAC,WAAW,GAAG,aAAa;;;;"}
@@ -0,0 +1,41 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { forwardRef, useState, useEffect } from 'react';
3
+ import { Browsers } from '@stream-io/video-client';
4
+ import { applyElementToRef } from '../../../utilities/applyElementToRef.js';
5
+
6
+ /**
7
+ * @description Extends video element with `stream` property
8
+ * (`srcObject`) to reactively handle stream changes
9
+ */
10
+ const BaseVideo = forwardRef(function BaseVideoRender({ stream, ...rest }, ref) {
11
+ const [videoElement, setVideoElement] = useState(null);
12
+ useEffect(() => {
13
+ if (!videoElement || !stream)
14
+ return;
15
+ if (stream === videoElement.srcObject)
16
+ return;
17
+ videoElement.srcObject = stream;
18
+ let timeoutId;
19
+ if (Browsers.isSafari() || Browsers.isFirefox()) {
20
+ // Firefox and Safari have some timing issue
21
+ timeoutId = setTimeout(() => {
22
+ videoElement.srcObject = stream;
23
+ videoElement.play().catch((e) => {
24
+ console.error(`Failed to play stream`, e);
25
+ });
26
+ }, 0);
27
+ }
28
+ return () => {
29
+ clearTimeout(timeoutId);
30
+ videoElement.pause();
31
+ videoElement.srcObject = null;
32
+ };
33
+ }, [stream, videoElement]);
34
+ return (jsx("video", { autoPlay: true, playsInline: true, ...rest, ref: (element) => {
35
+ applyElementToRef(ref, element);
36
+ setVideoElement(element);
37
+ } }));
38
+ });
39
+
40
+ export { BaseVideo };
41
+ //# sourceMappingURL=BaseVideo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseVideo.js","sources":["../../../../../../../../src/core/components/Video/BaseVideo.tsx"],"sourcesContent":["import { ComponentPropsWithRef, forwardRef, useEffect, useState } from 'react';\nimport { Browsers } from '@stream-io/video-client';\n\nimport { applyElementToRef } from '../../../utilities';\n\nexport type BaseVideoProps = ComponentPropsWithRef<'video'> & {\n stream?: MediaStream;\n};\n\n/**\n * @description Extends video element with `stream` property\n * (`srcObject`) to reactively handle stream changes\n */\nexport const BaseVideo = forwardRef<HTMLVideoElement, BaseVideoProps>(\n function BaseVideoRender({ stream, ...rest }, ref) {\n const [videoElement, setVideoElement] = useState<HTMLVideoElement | null>(\n null,\n );\n\n useEffect(() => {\n if (!videoElement || !stream) return;\n if (stream === videoElement.srcObject) return;\n\n videoElement.srcObject = stream;\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n if (Browsers.isSafari() || Browsers.isFirefox()) {\n // Firefox and Safari have some timing issue\n timeoutId = setTimeout(() => {\n videoElement.srcObject = stream;\n videoElement.play().catch((e) => {\n console.error(`Failed to play stream`, e);\n });\n }, 0);\n }\n\n return () => {\n clearTimeout(timeoutId);\n videoElement.pause();\n videoElement.srcObject = null;\n };\n }, [stream, videoElement]);\n\n return (\n <video\n autoPlay\n playsInline\n {...rest}\n ref={(element) => {\n applyElementToRef(ref, element);\n setVideoElement(element);\n }}\n />\n );\n },\n);\n"],"names":["_jsx"],"mappings":";;;;;AASA;;;AAGG;AACI,MAAM,SAAS,GAAG,UAAU,CACjC,SAAS,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,GAAG,EAAA;IAC/C,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAC9C,IAAI,CACL;IAED,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM;YAAE;AAC9B,QAAA,IAAI,MAAM,KAAK,YAAY,CAAC,SAAS;YAAE;AAEvC,QAAA,YAAY,CAAC,SAAS,GAAG,MAAM;AAC/B,QAAA,IAAI,SAAoD;QACxD,IAAI,QAAQ,CAAC,QAAQ,EAAE,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAE;;AAE/C,YAAA,SAAS,GAAG,UAAU,CAAC,MAAK;AAC1B,gBAAA,YAAY,CAAC,SAAS,GAAG,MAAM;gBAC/B,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAI;AAC9B,oBAAA,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,CAAC,CAAC;AAC3C,gBAAA,CAAC,CAAC;YACJ,CAAC,EAAE,CAAC,CAAC;QACP;AAEA,QAAA,OAAO,MAAK;YACV,YAAY,CAAC,SAAS,CAAC;YACvB,YAAY,CAAC,KAAK,EAAE;AACpB,YAAA,YAAY,CAAC,SAAS,GAAG,IAAI;AAC/B,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAE1B,IAAA,QACEA,GAAA,CAAA,OAAA,EAAA,EACE,QAAQ,EAAA,IAAA,EACR,WAAW,EAAA,IAAA,EAAA,GACP,IAAI,EACR,GAAG,EAAE,CAAC,OAAO,KAAI;AACf,YAAA,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC;YAC/B,eAAe,CAAC,OAAO,CAAC;QAC1B,CAAC,EAAA,CACD;AAEN,CAAC;;;;"}
@@ -0,0 +1,21 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { forwardRef, useState } from 'react';
3
+
4
+ const BaseVideoPlaceholder = forwardRef(function DefaultVideoPlaceholder({ participant, style, children }, ref) {
5
+ const [error, setError] = useState(false);
6
+ const name = participant.name || participant.userId;
7
+ return (jsxs("div", { className: "str-video__video-placeholder", style: style, ref: ref, children: [(!participant.image || error) &&
8
+ (name ? (jsx(InitialsFallback, { name: name })) : (jsx("div", { className: "str-video__video-placeholder__no-video-label", children: children }))), participant.image && !error && (jsx("img", { onError: () => setError(true), alt: name, className: "str-video__video-placeholder__avatar", src: participant.image }))] }));
9
+ });
10
+ const InitialsFallback = (props) => {
11
+ const { name } = props;
12
+ const initials = name
13
+ .split(' ')
14
+ .slice(0, 2)
15
+ .map((n) => n[0])
16
+ .join('');
17
+ return (jsx("div", { className: "str-video__video-placeholder__initials-fallback", children: initials }));
18
+ };
19
+
20
+ export { BaseVideoPlaceholder };
21
+ //# sourceMappingURL=BaseVideoPlaceholder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseVideoPlaceholder.js","sources":["../../../../../../../../src/core/components/Video/BaseVideoPlaceholder.tsx"],"sourcesContent":["import { ComponentProps, RefAttributes, forwardRef, useState } from 'react';\nimport type { StreamVideoParticipant } from '@stream-io/video-client';\n\nexport type BaseVideoPlaceholderProps = {\n participant: StreamVideoParticipant;\n} & RefAttributes<HTMLDivElement> &\n ComponentProps<'div'>;\n\nexport const BaseVideoPlaceholder = forwardRef<\n HTMLDivElement,\n BaseVideoPlaceholderProps\n>(function DefaultVideoPlaceholder({ participant, style, children }, ref) {\n const [error, setError] = useState(false);\n const name = participant.name || participant.userId;\n return (\n <div className=\"str-video__video-placeholder\" style={style} ref={ref}>\n {(!participant.image || error) &&\n (name ? (\n <InitialsFallback name={name} />\n ) : (\n <div className=\"str-video__video-placeholder__no-video-label\">\n {children}\n </div>\n ))}\n {participant.image && !error && (\n <img\n onError={() => setError(true)}\n alt={name}\n className=\"str-video__video-placeholder__avatar\"\n src={participant.image}\n />\n )}\n </div>\n );\n});\n\nconst InitialsFallback = (props: { name: string }) => {\n const { name } = props;\n const initials = name\n .split(' ')\n .slice(0, 2)\n .map((n) => n[0])\n .join('');\n return (\n <div className=\"str-video__video-placeholder__initials-fallback\">\n {initials}\n </div>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":";;;AAQO,MAAM,oBAAoB,GAAG,UAAU,CAG5C,SAAS,uBAAuB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAA;IACtE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IACzC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC,MAAM;IACnD,QACEA,cAAK,SAAS,EAAC,8BAA8B,EAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,aACjE,CAAC,CAAC,WAAW,CAAC,KAAK,IAAI,KAAK;AAC3B,iBAAC,IAAI,IACHC,GAAA,CAAC,gBAAgB,EAAA,EAAC,IAAI,EAAE,IAAI,EAAA,CAAI,KAEhCA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,8CAA8C,EAAA,QAAA,EAC1D,QAAQ,EAAA,CACL,CACP,CAAC,EACH,WAAW,CAAC,KAAK,IAAI,CAAC,KAAK,KAC1BA,GAAA,CAAA,KAAA,EAAA,EACE,OAAO,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,EAC7B,GAAG,EAAE,IAAI,EACT,SAAS,EAAC,sCAAsC,EAChD,GAAG,EAAE,WAAW,CAAC,KAAK,EAAA,CACtB,CACH,CAAA,EAAA,CACG;AAEV,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,KAAuB,KAAI;AACnD,IAAA,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK;IACtB,MAAM,QAAQ,GAAG;SACd,KAAK,CAAC,GAAG;AACT,SAAA,KAAK,CAAC,CAAC,EAAE,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACf,IAAI,CAAC,EAAE,CAAC;IACX,QACEA,aAAK,SAAS,EAAC,iDAAiD,EAAA,QAAA,EAC7D,QAAQ,EAAA,CACL;AAEV,CAAC;;;;"}
@@ -0,0 +1,12 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { forwardRef } from 'react';
3
+ import { useI18n } from '@stream-io/video-react-bindings';
4
+ import { BaseVideoPlaceholder } from './BaseVideoPlaceholder.js';
5
+
6
+ const DefaultPictureInPicturePlaceholder = forwardRef(function DefaultPictureInPicturePlaceholderRender(props, ref) {
7
+ const { t } = useI18n();
8
+ return (jsx(BaseVideoPlaceholder, { ref: ref, ...props, children: t('Video is playing in a popup') }));
9
+ });
10
+
11
+ export { DefaultPictureInPicturePlaceholder };
12
+ //# sourceMappingURL=DefaultPictureInPicturePlaceholder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultPictureInPicturePlaceholder.js","sources":["../../../../../../../../src/core/components/Video/DefaultPictureInPicturePlaceholder.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { useI18n } from '@stream-io/video-react-bindings';\nimport {\n BaseVideoPlaceholder,\n type BaseVideoPlaceholderProps,\n} from './BaseVideoPlaceholder';\n\nexport type PictureInPicturePlaceholderProps = BaseVideoPlaceholderProps;\n\nexport const DefaultPictureInPicturePlaceholder = forwardRef<\n HTMLDivElement,\n PictureInPicturePlaceholderProps\n>(function DefaultPictureInPicturePlaceholderRender(props, ref) {\n const { t } = useI18n();\n return (\n <BaseVideoPlaceholder ref={ref} {...props}>\n {t('Video is playing in a popup')}\n </BaseVideoPlaceholder>\n );\n});\n"],"names":["_jsx"],"mappings":";;;;;AASO,MAAM,kCAAkC,GAAG,UAAU,CAG1D,SAAS,wCAAwC,CAAC,KAAK,EAAE,GAAG,EAAA;AAC5D,IAAA,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE;AACvB,IAAA,QACEA,GAAA,CAAC,oBAAoB,EAAA,EAAC,GAAG,EAAE,GAAG,EAAA,GAAM,KAAK,EAAA,QAAA,EACtC,CAAC,CAAC,6BAA6B,CAAC,EAAA,CACZ;AAE3B,CAAC;;;;"}
@@ -0,0 +1,12 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { forwardRef } from 'react';
3
+ import { useI18n } from '@stream-io/video-react-bindings';
4
+ import { BaseVideoPlaceholder } from './BaseVideoPlaceholder.js';
5
+
6
+ const DefaultVideoPlaceholder = forwardRef(function DefaultVideoPlaceholderRender(props, ref) {
7
+ const { t } = useI18n();
8
+ return (jsx(BaseVideoPlaceholder, { ref: ref, ...props, children: t('Video is disabled') }));
9
+ });
10
+
11
+ export { DefaultVideoPlaceholder };
12
+ //# sourceMappingURL=DefaultVideoPlaceholder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultVideoPlaceholder.js","sources":["../../../../../../../../src/core/components/Video/DefaultVideoPlaceholder.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { useI18n } from '@stream-io/video-react-bindings';\nimport {\n BaseVideoPlaceholder,\n type BaseVideoPlaceholderProps,\n} from './BaseVideoPlaceholder';\n\nexport type VideoPlaceholderProps = BaseVideoPlaceholderProps;\n\nexport const DefaultVideoPlaceholder = forwardRef<\n HTMLDivElement,\n VideoPlaceholderProps\n>(function DefaultVideoPlaceholderRender(props, ref) {\n const { t } = useI18n();\n return (\n <BaseVideoPlaceholder ref={ref} {...props}>\n {t('Video is disabled')}\n </BaseVideoPlaceholder>\n );\n});\n"],"names":["_jsx"],"mappings":";;;;;AASO,MAAM,uBAAuB,GAAG,UAAU,CAG/C,SAAS,6BAA6B,CAAC,KAAK,EAAE,GAAG,EAAA;AACjD,IAAA,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE;AACvB,IAAA,QACEA,GAAA,CAAC,oBAAoB,EAAA,EAAC,GAAG,EAAE,GAAG,EAAA,GAAM,KAAK,EAAA,QAAA,EACtC,CAAC,CAAC,mBAAmB,CAAC,EAAA,CACF;AAE3B,CAAC;;;;"}
@@ -0,0 +1,88 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { useState, useLayoutEffect, useEffect } from 'react';
3
+ import { hasVideo, hasScreenShare, VisibilityState, hasPausedTrack } from '@stream-io/video-client';
4
+ import clsx from 'clsx';
5
+ import { DefaultVideoPlaceholder } from './DefaultVideoPlaceholder.js';
6
+ import { useCall } from '@stream-io/video-react-bindings';
7
+ import { usePictureInPictureState } from '../../hooks/usePictureInPictureState.js';
8
+ import { DefaultPictureInPicturePlaceholder } from './DefaultPictureInPicturePlaceholder.js';
9
+
10
+ const ABSOLUTE_POSITION_STYLE = { position: 'absolute' };
11
+ const Video = ({ enabled = true, mirror, trackType, participant, className, VideoPlaceholder = DefaultVideoPlaceholder, PictureInPicturePlaceholder = DefaultPictureInPicturePlaceholder, refs, ...rest }) => {
12
+ const { sessionId, videoStream, screenShareStream, viewportVisibilityState, isLocalParticipant, userId, } = participant;
13
+ const call = useCall();
14
+ const [videoElement, setVideoElement] = useState(null);
15
+ // start with true, will flip once the video starts playing
16
+ const [isVideoPaused, setIsVideoPaused] = useState(true);
17
+ const [isWideMode, setIsWideMode] = useState(true);
18
+ const isPiP = usePictureInPictureState(videoElement ?? undefined);
19
+ const stream = trackType === 'videoTrack'
20
+ ? videoStream
21
+ : trackType === 'screenShareTrack'
22
+ ? screenShareStream
23
+ : undefined;
24
+ useLayoutEffect(() => {
25
+ if (!call || !videoElement || trackType === 'none')
26
+ return;
27
+ const cleanup = call.bindVideoElement(videoElement, sessionId, trackType);
28
+ return () => {
29
+ cleanup?.();
30
+ };
31
+ }, [call, trackType, sessionId, videoElement]);
32
+ useEffect(() => {
33
+ if (!stream || !videoElement)
34
+ return;
35
+ const [track] = stream.getVideoTracks();
36
+ if (!track)
37
+ return;
38
+ const handlePlayPause = () => {
39
+ setIsVideoPaused(videoElement.paused);
40
+ const { width = 0, height = 0 } = track.getSettings();
41
+ setIsWideMode(width >= height);
42
+ };
43
+ // playback may have started before we had a chance to
44
+ // attach the 'play/pause' event listener, so we set the state
45
+ // here to make sure it's in sync
46
+ setIsVideoPaused(videoElement.paused);
47
+ videoElement.addEventListener('play', handlePlayPause);
48
+ videoElement.addEventListener('pause', handlePlayPause);
49
+ track.addEventListener('unmute', handlePlayPause);
50
+ return () => {
51
+ videoElement.removeEventListener('play', handlePlayPause);
52
+ videoElement.removeEventListener('pause', handlePlayPause);
53
+ track.removeEventListener('unmute', handlePlayPause);
54
+ // reset the 'pause' state once we unmount the video element
55
+ setIsVideoPaused(true);
56
+ };
57
+ }, [stream, videoElement]);
58
+ if (!call)
59
+ return null;
60
+ const isPublishingTrack = trackType === 'videoTrack'
61
+ ? hasVideo(participant)
62
+ : trackType === 'screenShareTrack'
63
+ ? hasScreenShare(participant)
64
+ : false;
65
+ const isInvisible = trackType === 'none' ||
66
+ viewportVisibilityState?.[trackType] === VisibilityState.INVISIBLE;
67
+ const hasNoVideoOrInvisible = !enabled ||
68
+ !isPublishingTrack ||
69
+ isInvisible ||
70
+ hasPausedTrack(participant, trackType);
71
+ const mirrorVideo = mirror === undefined
72
+ ? isLocalParticipant && trackType === 'videoTrack'
73
+ : mirror;
74
+ const isScreenShareTrack = trackType === 'screenShareTrack';
75
+ return (jsxs(Fragment, { children: [!hasNoVideoOrInvisible && (jsx("video", { ...rest, className: clsx('str-video__video', className, {
76
+ 'str-video__video--not-playing': isVideoPaused,
77
+ 'str-video__video--tall': !isWideMode,
78
+ 'str-video__video--mirror': mirrorVideo,
79
+ 'str-video__video--screen-share': isScreenShareTrack,
80
+ }), "data-user-id": userId, "data-session-id": sessionId, ref: (element) => {
81
+ setVideoElement(element);
82
+ refs?.setVideoElement?.(element);
83
+ } })), isPiP && PictureInPicturePlaceholder && (jsx(PictureInPicturePlaceholder, { style: ABSOLUTE_POSITION_STYLE, participant: participant })), (hasNoVideoOrInvisible || isVideoPaused) && VideoPlaceholder && (jsx(VideoPlaceholder, { style: ABSOLUTE_POSITION_STYLE, participant: participant, ref: refs?.setVideoPlaceholderElement }))] }));
84
+ };
85
+ Video.displayName = 'Video';
86
+
87
+ export { Video };
88
+ //# sourceMappingURL=Video.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Video.js","sources":["../../../../../../../../src/core/components/Video/Video.tsx"],"sourcesContent":["import {\n ComponentPropsWithoutRef,\n ComponentType,\n CSSProperties,\n useEffect,\n useLayoutEffect,\n useState,\n} from 'react';\nimport {\n hasPausedTrack,\n hasScreenShare,\n hasVideo,\n StreamVideoParticipant,\n VideoTrackType,\n VisibilityState,\n} from '@stream-io/video-client';\nimport clsx from 'clsx';\nimport {\n DefaultVideoPlaceholder,\n VideoPlaceholderProps,\n} from './DefaultVideoPlaceholder';\nimport { useCall } from '@stream-io/video-react-bindings';\nimport { usePictureInPictureState } from '../../hooks/usePictureInPictureState';\nimport {\n DefaultPictureInPicturePlaceholder,\n PictureInPicturePlaceholderProps,\n} from './DefaultPictureInPicturePlaceholder';\n\nconst ABSOLUTE_POSITION_STYLE: CSSProperties = { position: 'absolute' };\n\nexport type VideoProps = ComponentPropsWithoutRef<'video'> & {\n /**\n * Pass false to disable rendering video and render fallback\n * even if the participant has published video.\n * @default true\n */\n enabled?: boolean;\n /**\n * Forces the video to be mirrored or unmirrored. By default, video track\n * from the local participant is mirrored, and all other videos are not mirrored.\n */\n mirror?: boolean;\n /**\n * The track type to display.\n */\n trackType: VideoTrackType | 'none';\n /**\n * The participant represented by this video element.\n */\n participant: StreamVideoParticipant;\n /**\n * Override the default UI that's visible when a participant turned off their video.\n * Set it to `null` if you wish to disable the video placeholder.\n *\n * @default DefaultVideoPlaceholder\n */\n VideoPlaceholder?: ComponentType<VideoPlaceholderProps> | null;\n /**\n * Override the default UI that's dispayed in place of the video when it's playing\n * in picture-in-picture. Set it to `null` if you wish to display the browser's default\n * placeholder.\n *\n * @default DefaultPictureInPicturePlaceholder\n */\n PictureInPicturePlaceholder?: ComponentType<PictureInPicturePlaceholderProps> | null;\n /**\n /**\n * An object with setRef functions\n * meant for exposing some of the internal elements of this component.\n */\n refs?: {\n /**\n * The video element that's used to play the video stream.\n * @param element the video element.\n */\n setVideoElement?: (element: HTMLVideoElement | null) => void;\n /**\n * The video placeholder element that's used when the video stream is not playing.\n * @param element the video placeholder element.\n */\n setVideoPlaceholderElement?: (element: HTMLDivElement | null) => void;\n setPictureInPicturePlaceholderElement?: (\n element: HTMLDivElement | null,\n ) => void;\n };\n};\n\nexport const Video = ({\n enabled = true,\n mirror,\n trackType,\n participant,\n className,\n VideoPlaceholder = DefaultVideoPlaceholder,\n PictureInPicturePlaceholder = DefaultPictureInPicturePlaceholder,\n refs,\n ...rest\n}: VideoProps) => {\n const {\n sessionId,\n videoStream,\n screenShareStream,\n viewportVisibilityState,\n isLocalParticipant,\n userId,\n } = participant;\n\n const call = useCall();\n const [videoElement, setVideoElement] = useState<HTMLVideoElement | null>(\n null,\n );\n // start with true, will flip once the video starts playing\n const [isVideoPaused, setIsVideoPaused] = useState(true);\n const [isWideMode, setIsWideMode] = useState(true);\n const isPiP = usePictureInPictureState(videoElement ?? undefined);\n\n const stream =\n trackType === 'videoTrack'\n ? videoStream\n : trackType === 'screenShareTrack'\n ? screenShareStream\n : undefined;\n\n useLayoutEffect(() => {\n if (!call || !videoElement || trackType === 'none') return;\n\n const cleanup = call.bindVideoElement(videoElement, sessionId, trackType);\n\n return () => {\n cleanup?.();\n };\n }, [call, trackType, sessionId, videoElement]);\n\n useEffect(() => {\n if (!stream || !videoElement) return;\n\n const [track] = stream.getVideoTracks();\n if (!track) return;\n\n const handlePlayPause = () => {\n setIsVideoPaused(videoElement.paused);\n\n const { width = 0, height = 0 } = track.getSettings();\n setIsWideMode(width >= height);\n };\n\n // playback may have started before we had a chance to\n // attach the 'play/pause' event listener, so we set the state\n // here to make sure it's in sync\n setIsVideoPaused(videoElement.paused);\n\n videoElement.addEventListener('play', handlePlayPause);\n videoElement.addEventListener('pause', handlePlayPause);\n track.addEventListener('unmute', handlePlayPause);\n return () => {\n videoElement.removeEventListener('play', handlePlayPause);\n videoElement.removeEventListener('pause', handlePlayPause);\n track.removeEventListener('unmute', handlePlayPause);\n\n // reset the 'pause' state once we unmount the video element\n setIsVideoPaused(true);\n };\n }, [stream, videoElement]);\n\n if (!call) return null;\n\n const isPublishingTrack =\n trackType === 'videoTrack'\n ? hasVideo(participant)\n : trackType === 'screenShareTrack'\n ? hasScreenShare(participant)\n : false;\n\n const isInvisible =\n trackType === 'none' ||\n viewportVisibilityState?.[trackType] === VisibilityState.INVISIBLE;\n\n const hasNoVideoOrInvisible =\n !enabled ||\n !isPublishingTrack ||\n isInvisible ||\n hasPausedTrack(participant, trackType);\n const mirrorVideo =\n mirror === undefined\n ? isLocalParticipant && trackType === 'videoTrack'\n : mirror;\n const isScreenShareTrack = trackType === 'screenShareTrack';\n return (\n <>\n {!hasNoVideoOrInvisible && (\n <video\n {...rest}\n className={clsx('str-video__video', className, {\n 'str-video__video--not-playing': isVideoPaused,\n 'str-video__video--tall': !isWideMode,\n 'str-video__video--mirror': mirrorVideo,\n 'str-video__video--screen-share': isScreenShareTrack,\n })}\n data-user-id={userId}\n data-session-id={sessionId}\n ref={(element) => {\n setVideoElement(element);\n refs?.setVideoElement?.(element);\n }}\n />\n )}\n {isPiP && PictureInPicturePlaceholder && (\n <PictureInPicturePlaceholder\n style={ABSOLUTE_POSITION_STYLE}\n participant={participant}\n />\n )}\n {/* TODO: add condition to \"hold\" the placeholder until track unmutes as well */}\n {(hasNoVideoOrInvisible || isVideoPaused) && VideoPlaceholder && (\n <VideoPlaceholder\n style={ABSOLUTE_POSITION_STYLE}\n participant={participant}\n ref={refs?.setVideoPlaceholderElement}\n />\n )}\n </>\n );\n};\n\nVideo.displayName = 'Video';\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { useState, useEffect } from 'react';
2
+
3
+ const useCalculateHardLimit = (
4
+ /**
5
+ * Element that stretches to 100% of the whole layout component
6
+ */
7
+ wrapperElement,
8
+ /**
9
+ * Element that directly hosts individual `ParticipantView` (or wrapper) elements
10
+ */
11
+ hostElement, limit) => {
12
+ const [calculatedLimit, setCalculatedLimit] = useState({
13
+ vertical: typeof limit === 'number' ? limit : null,
14
+ horizontal: typeof limit === 'number' ? limit : null,
15
+ });
16
+ useEffect(() => {
17
+ if (!hostElement ||
18
+ !wrapperElement ||
19
+ typeof limit === 'number' ||
20
+ typeof limit === 'undefined')
21
+ return;
22
+ let childWidth = null;
23
+ let childHeight = null;
24
+ const resizeObserver = new ResizeObserver((entries, observer) => {
25
+ // this part should ideally run as little times as possible
26
+ // get child measurements and disconnect
27
+ // does not consider dynamically sized children
28
+ // this hook is for SpeakerLayout use only, where children in the bar are fixed size
29
+ if (entries.length > 1) {
30
+ const child = hostElement.firstChild;
31
+ if (child) {
32
+ childHeight = child.clientHeight;
33
+ childWidth = child.clientWidth;
34
+ observer.unobserve(hostElement);
35
+ }
36
+ }
37
+ // keep the state at { vertical: 1, horizontal: 1 }
38
+ // until we get the proper child measurements
39
+ if (childHeight === null || childWidth === null)
40
+ return;
41
+ const vertical = Math.floor(wrapperElement.clientHeight / childHeight);
42
+ const horizontal = Math.floor(wrapperElement.clientWidth / childWidth);
43
+ setCalculatedLimit((pv) => {
44
+ if (pv.vertical !== vertical || pv.horizontal !== horizontal)
45
+ return { vertical, horizontal };
46
+ return pv;
47
+ });
48
+ });
49
+ resizeObserver.observe(wrapperElement);
50
+ resizeObserver.observe(hostElement);
51
+ return () => {
52
+ resizeObserver.disconnect();
53
+ };
54
+ }, [hostElement, limit, wrapperElement]);
55
+ return calculatedLimit;
56
+ };
57
+
58
+ export { useCalculateHardLimit };
59
+ //# sourceMappingURL=useCalculateHardLimit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCalculateHardLimit.js","sources":["../../../../../../../src/core/hooks/useCalculateHardLimit.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nexport const useCalculateHardLimit = (\n /**\n * Element that stretches to 100% of the whole layout component\n */\n wrapperElement: HTMLDivElement | null,\n /**\n * Element that directly hosts individual `ParticipantView` (or wrapper) elements\n */\n hostElement: HTMLDivElement | null,\n limit?: 'dynamic' | number,\n) => {\n const [calculatedLimit, setCalculatedLimit] = useState<{\n vertical: number | null;\n horizontal: number | null;\n }>({\n vertical: typeof limit === 'number' ? limit : null,\n horizontal: typeof limit === 'number' ? limit : null,\n });\n\n useEffect(() => {\n if (\n !hostElement ||\n !wrapperElement ||\n typeof limit === 'number' ||\n typeof limit === 'undefined'\n )\n return;\n\n let childWidth: number | null = null;\n let childHeight: number | null = null;\n\n const resizeObserver = new ResizeObserver((entries, observer) => {\n // this part should ideally run as little times as possible\n // get child measurements and disconnect\n // does not consider dynamically sized children\n // this hook is for SpeakerLayout use only, where children in the bar are fixed size\n if (entries.length > 1) {\n const child = hostElement.firstChild as HTMLElement | null;\n\n if (child) {\n childHeight = child.clientHeight;\n childWidth = child.clientWidth;\n observer.unobserve(hostElement);\n }\n }\n\n // keep the state at { vertical: 1, horizontal: 1 }\n // until we get the proper child measurements\n if (childHeight === null || childWidth === null) return;\n\n const vertical = Math.floor(wrapperElement.clientHeight / childHeight);\n const horizontal = Math.floor(wrapperElement.clientWidth / childWidth);\n\n setCalculatedLimit((pv) => {\n if (pv.vertical !== vertical || pv.horizontal !== horizontal)\n return { vertical, horizontal };\n return pv;\n });\n });\n\n resizeObserver.observe(wrapperElement);\n resizeObserver.observe(hostElement);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [hostElement, limit, wrapperElement]);\n\n return calculatedLimit;\n};\n"],"names":[],"mappings":";;AAEO,MAAM,qBAAqB,GAAG;AACnC;;AAEG;AACH,cAAqC;AACrC;;AAEG;AACH,WAAkC,EAClC,KAA0B,KACxB;AACF,IAAA,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAGnD;AACD,QAAA,QAAQ,EAAE,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,IAAI;AAClD,QAAA,UAAU,EAAE,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,IAAI;AACrD,KAAA,CAAC;IAEF,SAAS,CAAC,MAAK;AACb,QAAA,IACE,CAAC,WAAW;AACZ,YAAA,CAAC,cAAc;YACf,OAAO,KAAK,KAAK,QAAQ;YACzB,OAAO,KAAK,KAAK,WAAW;YAE5B;QAEF,IAAI,UAAU,GAAkB,IAAI;QACpC,IAAI,WAAW,GAAkB,IAAI;QAErC,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAI;;;;;AAK9D,YAAA,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;AACtB,gBAAA,MAAM,KAAK,GAAG,WAAW,CAAC,UAAgC;gBAE1D,IAAI,KAAK,EAAE;AACT,oBAAA,WAAW,GAAG,KAAK,CAAC,YAAY;AAChC,oBAAA,UAAU,GAAG,KAAK,CAAC,WAAW;AAC9B,oBAAA,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC;gBACjC;YACF;;;AAIA,YAAA,IAAI,WAAW,KAAK,IAAI,IAAI,UAAU,KAAK,IAAI;gBAAE;AAEjD,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,GAAG,WAAW,CAAC;AACtE,YAAA,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,GAAG,UAAU,CAAC;AAEtE,YAAA,kBAAkB,CAAC,CAAC,EAAE,KAAI;gBACxB,IAAI,EAAE,CAAC,QAAQ,KAAK,QAAQ,IAAI,EAAE,CAAC,UAAU,KAAK,UAAU;AAC1D,oBAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE;AACjC,gBAAA,OAAO,EAAE;AACX,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;AAEF,QAAA,cAAc,CAAC,OAAO,CAAC,cAAc,CAAC;AACtC,QAAA,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC;AAEnC,QAAA,OAAO,MAAK;YACV,cAAc,CAAC,UAAU,EAAE;AAC7B,QAAA,CAAC;IACH,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;AAExC,IAAA,OAAO,eAAe;AACxB;;;;"}
@@ -0,0 +1,24 @@
1
+ import { useState, useEffect } from 'react';
2
+
3
+ function usePictureInPictureState(videoElement) {
4
+ const [isPiP, setIsPiP] = useState(document.pictureInPictureElement === videoElement);
5
+ if (!videoElement && isPiP)
6
+ setIsPiP(false);
7
+ useEffect(() => {
8
+ if (!videoElement)
9
+ return;
10
+ const handlePiP = () => {
11
+ setIsPiP(document.pictureInPictureElement === videoElement);
12
+ };
13
+ videoElement.addEventListener('enterpictureinpicture', handlePiP);
14
+ videoElement.addEventListener('leavepictureinpicture', handlePiP);
15
+ return () => {
16
+ videoElement.removeEventListener('enterpictureinpicture', handlePiP);
17
+ videoElement.removeEventListener('leavepictureinpicture', handlePiP);
18
+ };
19
+ }, [videoElement]);
20
+ return isPiP;
21
+ }
22
+
23
+ export { usePictureInPictureState };
24
+ //# sourceMappingURL=usePictureInPictureState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePictureInPictureState.js","sources":["../../../../../../../src/core/hooks/usePictureInPictureState.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nexport function usePictureInPictureState(videoElement?: HTMLVideoElement) {\n const [isPiP, setIsPiP] = useState(\n document.pictureInPictureElement === videoElement,\n );\n\n if (!videoElement && isPiP) setIsPiP(false);\n\n useEffect(() => {\n if (!videoElement) return;\n\n const handlePiP = () => {\n setIsPiP(document.pictureInPictureElement === videoElement);\n };\n\n videoElement.addEventListener('enterpictureinpicture', handlePiP);\n videoElement.addEventListener('leavepictureinpicture', handlePiP);\n\n return () => {\n videoElement.removeEventListener('enterpictureinpicture', handlePiP);\n videoElement.removeEventListener('leavepictureinpicture', handlePiP);\n };\n }, [videoElement]);\n\n return isPiP;\n}\n"],"names":[],"mappings":";;AAEM,SAAU,wBAAwB,CAAC,YAA+B,EAAA;AACtE,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAChC,QAAQ,CAAC,uBAAuB,KAAK,YAAY,CAClD;IAED,IAAI,CAAC,YAAY,IAAI,KAAK;QAAE,QAAQ,CAAC,KAAK,CAAC;IAE3C,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,YAAY;YAAE;QAEnB,MAAM,SAAS,GAAG,MAAK;AACrB,YAAA,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,KAAK,YAAY,CAAC;AAC7D,QAAA,CAAC;AAED,QAAA,YAAY,CAAC,gBAAgB,CAAC,uBAAuB,EAAE,SAAS,CAAC;AACjE,QAAA,YAAY,CAAC,gBAAgB,CAAC,uBAAuB,EAAE,SAAS,CAAC;AAEjE,QAAA,OAAO,MAAK;AACV,YAAA,YAAY,CAAC,mBAAmB,CAAC,uBAAuB,EAAE,SAAS,CAAC;AACpE,YAAA,YAAY,CAAC,mBAAmB,CAAC,uBAAuB,EAAE,SAAS,CAAC;AACtE,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;AAElB,IAAA,OAAO,KAAK;AACd;;;;"}