@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.
- package/CHANGELOG.md +22 -6
- package/dist/embedded.cjs.js +1 -1
- package/dist/esm/embedded.js +3 -0
- package/dist/esm/embedded.js.map +1 -0
- package/dist/esm/index.js +92 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/src/components/Avatar/Avatar.js +14 -0
- package/dist/esm/src/components/Avatar/Avatar.js.map +1 -0
- package/dist/{background-filters-D2U5UBbH.es.js → esm/src/components/BackgroundFilters/BackgroundFilters.js} +1 -1
- package/dist/esm/src/components/BackgroundFilters/BackgroundFilters.js.map +1 -0
- package/dist/esm/src/components/BackgroundFilters/BackgroundFiltersProvider.js +33 -0
- package/dist/esm/src/components/BackgroundFilters/BackgroundFiltersProvider.js.map +1 -0
- package/dist/esm/src/components/Button/CompositeButton.js +29 -0
- package/dist/esm/src/components/Button/CompositeButton.js.map +1 -0
- package/dist/esm/src/components/Button/IconButton.js +18 -0
- package/dist/esm/src/components/Button/IconButton.js.map +1 -0
- package/dist/esm/src/components/Button/TextButton.js +8 -0
- package/dist/esm/src/components/Button/TextButton.js.map +1 -0
- package/dist/esm/src/components/CallControls/AcceptCallButton.js +28 -0
- package/dist/esm/src/components/CallControls/AcceptCallButton.js.map +1 -0
- package/dist/esm/src/components/CallControls/CallControls.js +21 -0
- package/dist/esm/src/components/CallControls/CallControls.js.map +1 -0
- package/dist/esm/src/components/CallControls/CallStatsButton.js +18 -0
- package/dist/esm/src/components/CallControls/CallStatsButton.js.map +1 -0
- package/dist/esm/src/components/CallControls/CancelCallButton.js +78 -0
- package/dist/esm/src/components/CallControls/CancelCallButton.js.map +1 -0
- package/dist/esm/src/components/CallControls/ReactionsButton.js +61 -0
- package/dist/esm/src/components/CallControls/ReactionsButton.js.map +1 -0
- package/dist/esm/src/components/CallControls/RecordCallButton.js +64 -0
- package/dist/esm/src/components/CallControls/RecordCallButton.js.map +1 -0
- package/dist/esm/src/components/CallControls/ScreenShareButton.js +44 -0
- package/dist/esm/src/components/CallControls/ScreenShareButton.js.map +1 -0
- package/dist/esm/src/components/CallControls/ToggleAudioButton.js +72 -0
- package/dist/esm/src/components/CallControls/ToggleAudioButton.js.map +1 -0
- package/dist/esm/src/components/CallControls/ToggleAudioOutputButton.js +27 -0
- package/dist/esm/src/components/CallControls/ToggleAudioOutputButton.js.map +1 -0
- package/dist/esm/src/components/CallControls/ToggleVideoButton.js +81 -0
- package/dist/esm/src/components/CallControls/ToggleVideoButton.js.map +1 -0
- package/dist/esm/src/components/CallParticipantsList/BlockedUserListing.js +23 -0
- package/dist/esm/src/components/CallParticipantsList/BlockedUserListing.js.map +1 -0
- package/dist/esm/src/components/CallParticipantsList/CallParticipantListHeader.js +15 -0
- package/dist/esm/src/components/CallParticipantsList/CallParticipantListHeader.js.map +1 -0
- package/dist/esm/src/components/CallParticipantsList/CallParticipantListing.js +7 -0
- package/dist/esm/src/components/CallParticipantsList/CallParticipantListing.js.map +1 -0
- package/dist/esm/src/components/CallParticipantsList/CallParticipantListingItem.js +46 -0
- package/dist/esm/src/components/CallParticipantsList/CallParticipantListingItem.js.map +1 -0
- package/dist/esm/src/components/CallParticipantsList/CallParticipantsList.js +81 -0
- package/dist/esm/src/components/CallParticipantsList/CallParticipantsList.js.map +1 -0
- package/dist/esm/src/components/CallParticipantsList/EmptyParticipantSearchList.js +10 -0
- package/dist/esm/src/components/CallParticipantsList/EmptyParticipantSearchList.js.map +1 -0
- package/dist/esm/src/components/CallPreview/CallPreview.js +24 -0
- package/dist/esm/src/components/CallPreview/CallPreview.js.map +1 -0
- package/dist/esm/src/components/CallRecordingList/CallRecordingList.js +12 -0
- package/dist/esm/src/components/CallRecordingList/CallRecordingList.js.map +1 -0
- package/dist/esm/src/components/CallRecordingList/CallRecordingListHeader.js +12 -0
- package/dist/esm/src/components/CallRecordingList/CallRecordingListHeader.js.map +1 -0
- package/dist/esm/src/components/CallRecordingList/CallRecordingListItem.js +14 -0
- package/dist/esm/src/components/CallRecordingList/CallRecordingListItem.js.map +1 -0
- package/dist/esm/src/components/CallRecordingList/EmptyCallRecordingListing.js +8 -0
- package/dist/esm/src/components/CallRecordingList/EmptyCallRecordingListing.js.map +1 -0
- package/dist/esm/src/components/CallRecordingList/LoadingCallRecordingListing.js +10 -0
- package/dist/esm/src/components/CallRecordingList/LoadingCallRecordingListing.js.map +1 -0
- package/dist/esm/src/components/CallStats/CallStats.js +180 -0
- package/dist/esm/src/components/CallStats/CallStats.js.map +1 -0
- package/dist/{latency-chart-Bj5OSYzg.es.js → esm/src/components/CallStats/CallStatsLatencyChart.js} +1 -1
- package/dist/esm/src/components/CallStats/CallStatsLatencyChart.js.map +1 -0
- package/dist/esm/src/components/DeviceSettings/AudioVolumeIndicator.js +27 -0
- package/dist/esm/src/components/DeviceSettings/AudioVolumeIndicator.js.map +1 -0
- package/dist/esm/src/components/DeviceSettings/DeviceAudioPreviewItem.js +42 -0
- package/dist/esm/src/components/DeviceSettings/DeviceAudioPreviewItem.js.map +1 -0
- package/dist/esm/src/components/DeviceSettings/DeviceSelector.js +67 -0
- package/dist/esm/src/components/DeviceSettings/DeviceSelector.js.map +1 -0
- package/dist/esm/src/components/DeviceSettings/DeviceSelectorAudio.js +26 -0
- package/dist/esm/src/components/DeviceSettings/DeviceSelectorAudio.js.map +1 -0
- package/dist/esm/src/components/DeviceSettings/DeviceSelectorVideo.js +15 -0
- package/dist/esm/src/components/DeviceSettings/DeviceSelectorVideo.js.map +1 -0
- package/dist/esm/src/components/DeviceSettings/DeviceSettings.js +26 -0
- package/dist/esm/src/components/DeviceSettings/DeviceSettings.js.map +1 -0
- package/dist/esm/src/components/DeviceSettings/DeviceVideoPreviewItem.js +42 -0
- package/dist/esm/src/components/DeviceSettings/DeviceVideoPreviewItem.js.map +1 -0
- package/dist/esm/src/components/DeviceSettings/SpeakerTest.js +57 -0
- package/dist/esm/src/components/DeviceSettings/SpeakerTest.js.map +1 -0
- package/dist/esm/src/components/DropdownSelect/DropdownSelect.js +79 -0
- package/dist/esm/src/components/DropdownSelect/DropdownSelect.js.map +1 -0
- package/dist/esm/src/components/Icon/Icon.js +7 -0
- package/dist/esm/src/components/Icon/Icon.js.map +1 -0
- package/dist/esm/src/components/LoadingIndicator/LoadingIndicator.js +9 -0
- package/dist/esm/src/components/LoadingIndicator/LoadingIndicator.js.map +1 -0
- package/dist/esm/src/components/Menu/GenericMenu.js +19 -0
- package/dist/esm/src/components/Menu/GenericMenu.js.map +1 -0
- package/dist/esm/src/components/Menu/MenuToggle.js +75 -0
- package/dist/esm/src/components/Menu/MenuToggle.js.map +1 -0
- package/dist/esm/src/components/NoiseCancellation/NoiseCancellationProvider.js +96 -0
- package/dist/esm/src/components/NoiseCancellation/NoiseCancellationProvider.js.map +1 -0
- package/dist/esm/src/components/Notification/MicCaptureErrorNotification.js +23 -0
- package/dist/esm/src/components/Notification/MicCaptureErrorNotification.js.map +1 -0
- package/dist/esm/src/components/Notification/Notification.js +31 -0
- package/dist/esm/src/components/Notification/Notification.js.map +1 -0
- package/dist/esm/src/components/Notification/PermissionNotification.js +32 -0
- package/dist/esm/src/components/Notification/PermissionNotification.js.map +1 -0
- package/dist/esm/src/components/Notification/RecordingInProgressNotification.js +23 -0
- package/dist/esm/src/components/Notification/RecordingInProgressNotification.js.map +1 -0
- package/dist/esm/src/components/Notification/SpeakingWhileMutedNotification.js +14 -0
- package/dist/esm/src/components/Notification/SpeakingWhileMutedNotification.js.map +1 -0
- package/dist/esm/src/components/Permissions/PermissionRequests.js +99 -0
- package/dist/esm/src/components/Permissions/PermissionRequests.js.map +1 -0
- package/dist/esm/src/components/Reaction/Reaction.js +32 -0
- package/dist/esm/src/components/Reaction/Reaction.js.map +1 -0
- package/dist/esm/src/components/RingingCall/RingingCall.js +48 -0
- package/dist/esm/src/components/RingingCall/RingingCall.js.map +1 -0
- package/dist/esm/src/components/RingingCall/RingingCallControls.js +34 -0
- package/dist/esm/src/components/RingingCall/RingingCallControls.js.map +1 -0
- package/dist/esm/src/components/Search/SearchInput.js +27 -0
- package/dist/esm/src/components/Search/SearchInput.js.map +1 -0
- package/dist/esm/src/components/Search/SearchResults.js +15 -0
- package/dist/esm/src/components/Search/SearchResults.js.map +1 -0
- package/dist/esm/src/components/Search/hooks/useSearch.js +38 -0
- package/dist/esm/src/components/Search/hooks/useSearch.js.map +1 -0
- package/dist/esm/src/components/StreamTheme/StreamTheme.js +9 -0
- package/dist/esm/src/components/StreamTheme/StreamTheme.js.map +1 -0
- package/dist/esm/src/components/Tooltip/Tooltip.js +29 -0
- package/dist/esm/src/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/esm/src/components/Tooltip/WithTooltip.js +15 -0
- package/dist/esm/src/components/Tooltip/WithTooltip.js.map +1 -0
- package/dist/esm/src/components/Tooltip/hooks/useEnterLeaveHandlers.js +17 -0
- package/dist/esm/src/components/Tooltip/hooks/useEnterLeaveHandlers.js.map +1 -0
- package/dist/esm/src/components/VideoPreview/VideoPreview.js +37 -0
- package/dist/esm/src/components/VideoPreview/VideoPreview.js.map +1 -0
- package/dist/esm/src/core/components/Audio/Audio.js +22 -0
- package/dist/esm/src/core/components/Audio/Audio.js.map +1 -0
- package/dist/esm/src/core/components/Audio/ParticipantsAudio.js +23 -0
- package/dist/esm/src/core/components/Audio/ParticipantsAudio.js.map +1 -0
- package/dist/esm/src/core/components/CallLayout/LivestreamLayout.js +150 -0
- package/dist/esm/src/core/components/CallLayout/LivestreamLayout.js.map +1 -0
- package/dist/esm/src/core/components/CallLayout/PaginatedGridLayout.js +79 -0
- package/dist/esm/src/core/components/CallLayout/PaginatedGridLayout.js.map +1 -0
- package/dist/esm/src/core/components/CallLayout/PipLayout/Grid.js +80 -0
- package/dist/esm/src/core/components/CallLayout/PipLayout/Grid.js.map +1 -0
- package/dist/esm/src/core/components/CallLayout/PipLayout/Host.js +13 -0
- package/dist/esm/src/core/components/CallLayout/PipLayout/Host.js.map +1 -0
- package/dist/esm/src/core/components/CallLayout/PipLayout/Pip.js +57 -0
- package/dist/esm/src/core/components/CallLayout/PipLayout/Pip.js.map +1 -0
- package/dist/esm/src/core/components/CallLayout/PipLayout/index.js +8 -0
- package/dist/esm/src/core/components/CallLayout/PipLayout/index.js.map +1 -0
- package/dist/esm/src/core/components/CallLayout/SpeakerLayout.js +103 -0
- package/dist/esm/src/core/components/CallLayout/SpeakerLayout.js.map +1 -0
- package/dist/esm/src/core/components/CallLayout/hooks.js +62 -0
- package/dist/esm/src/core/components/CallLayout/hooks.js.map +1 -0
- package/dist/esm/src/core/components/ParticipantView/DefaultParticipantViewUI.js +94 -0
- package/dist/esm/src/core/components/ParticipantView/DefaultParticipantViewUI.js.map +1 -0
- package/dist/esm/src/core/components/ParticipantView/ParticipantActionsContextMenu.js +97 -0
- package/dist/esm/src/core/components/ParticipantView/ParticipantActionsContextMenu.js.map +1 -0
- package/dist/esm/src/core/components/ParticipantView/ParticipantView.js +65 -0
- package/dist/esm/src/core/components/ParticipantView/ParticipantView.js.map +1 -0
- package/dist/esm/src/core/components/ParticipantView/ParticipantViewContext.js +7 -0
- package/dist/esm/src/core/components/ParticipantView/ParticipantViewContext.js.map +1 -0
- package/dist/esm/src/core/components/StreamCall/StreamCall.js +8 -0
- package/dist/esm/src/core/components/StreamCall/StreamCall.js.map +1 -0
- package/dist/esm/src/core/components/StreamVideo/StreamVideo.js +11 -0
- package/dist/esm/src/core/components/StreamVideo/StreamVideo.js.map +1 -0
- package/dist/esm/src/core/components/Video/BaseVideo.js +41 -0
- package/dist/esm/src/core/components/Video/BaseVideo.js.map +1 -0
- package/dist/esm/src/core/components/Video/BaseVideoPlaceholder.js +21 -0
- package/dist/esm/src/core/components/Video/BaseVideoPlaceholder.js.map +1 -0
- package/dist/esm/src/core/components/Video/DefaultPictureInPicturePlaceholder.js +12 -0
- package/dist/esm/src/core/components/Video/DefaultPictureInPicturePlaceholder.js.map +1 -0
- package/dist/esm/src/core/components/Video/DefaultVideoPlaceholder.js +12 -0
- package/dist/esm/src/core/components/Video/DefaultVideoPlaceholder.js.map +1 -0
- package/dist/esm/src/core/components/Video/Video.js +88 -0
- package/dist/esm/src/core/components/Video/Video.js.map +1 -0
- package/dist/esm/src/core/hooks/useCalculateHardLimit.js +59 -0
- package/dist/esm/src/core/hooks/useCalculateHardLimit.js.map +1 -0
- package/dist/esm/src/core/hooks/usePictureInPictureState.js +24 -0
- package/dist/esm/src/core/hooks/usePictureInPictureState.js.map +1 -0
- package/dist/esm/src/core/hooks/useTrackElementVisibility.js +14 -0
- package/dist/esm/src/core/hooks/useTrackElementVisibility.js.map +1 -0
- package/dist/esm/src/embedded/EmbeddedClientProvider.js +83 -0
- package/dist/esm/src/embedded/EmbeddedClientProvider.js.map +1 -0
- package/dist/esm/src/embedded/call/CallControls.js +65 -0
- package/dist/esm/src/embedded/call/CallControls.js.map +1 -0
- package/dist/esm/src/embedded/call/CallHeader.js +57 -0
- package/dist/esm/src/embedded/call/CallHeader.js.map +1 -0
- package/dist/esm/src/embedded/call/CallLayout.js +63 -0
- package/dist/esm/src/embedded/call/CallLayout.js.map +1 -0
- package/dist/esm/src/embedded/call/CallStateRouter.js +87 -0
- package/dist/esm/src/embedded/call/CallStateRouter.js.map +1 -0
- package/dist/esm/src/embedded/call/EmbeddedCall.js +12 -0
- package/dist/esm/src/embedded/call/EmbeddedCall.js.map +1 -0
- package/dist/esm/src/embedded/context/ConfigurationContext.js +21 -0
- package/dist/esm/src/embedded/context/ConfigurationContext.js.map +1 -0
- package/dist/esm/src/embedded/hooks/useCallDuration.js +32 -0
- package/dist/esm/src/embedded/hooks/useCallDuration.js.map +1 -0
- package/dist/esm/src/embedded/hooks/useEmbeddedClient.js +40 -0
- package/dist/esm/src/embedded/hooks/useEmbeddedClient.js.map +1 -0
- package/dist/esm/src/embedded/hooks/useInitializeCall.js +39 -0
- package/dist/esm/src/embedded/hooks/useInitializeCall.js.map +1 -0
- package/dist/esm/src/embedded/hooks/useInitializeVideoClient.js +93 -0
- package/dist/esm/src/embedded/hooks/useInitializeVideoClient.js.map +1 -0
- package/dist/esm/src/embedded/hooks/useIsLivestreamPaused.js +42 -0
- package/dist/esm/src/embedded/hooks/useIsLivestreamPaused.js.map +1 -0
- package/dist/esm/src/embedded/hooks/useLayout.js +122 -0
- package/dist/esm/src/embedded/hooks/useLayout.js.map +1 -0
- package/dist/esm/src/embedded/hooks/useNoiseCancellationLoader.js +48 -0
- package/dist/esm/src/embedded/hooks/useNoiseCancellationLoader.js.map +1 -0
- package/dist/esm/src/embedded/hooks/useWakeLock.js +34 -0
- package/dist/esm/src/embedded/hooks/useWakeLock.js.map +1 -0
- package/dist/esm/src/embedded/livestream/EmbeddedLivestream.js +11 -0
- package/dist/esm/src/embedded/livestream/EmbeddedLivestream.js.map +1 -0
- package/dist/esm/src/embedded/livestream/LivestreamUI.js +17 -0
- package/dist/esm/src/embedded/livestream/LivestreamUI.js.map +1 -0
- package/dist/esm/src/embedded/livestream/host/HostLayout.js +76 -0
- package/dist/esm/src/embedded/livestream/host/HostLayout.js.map +1 -0
- package/dist/esm/src/embedded/livestream/host/HostStateRouter.js +110 -0
- package/dist/esm/src/embedded/livestream/host/HostStateRouter.js.map +1 -0
- package/dist/esm/src/embedded/livestream/viewer/ViewerLayout.js +74 -0
- package/dist/esm/src/embedded/livestream/viewer/ViewerLayout.js.map +1 -0
- package/dist/esm/src/embedded/livestream/viewer/ViewerLobby.js +109 -0
- package/dist/esm/src/embedded/livestream/viewer/ViewerLobby.js.map +1 -0
- package/dist/esm/src/embedded/livestream/viewer/ViewerStateRouter.js +105 -0
- package/dist/esm/src/embedded/livestream/viewer/ViewerStateRouter.js.map +1 -0
- package/dist/esm/src/embedded/shared/BlurToggleButton/BlurToggleButton.js +65 -0
- package/dist/esm/src/embedded/shared/BlurToggleButton/BlurToggleButton.js.map +1 -0
- package/dist/esm/src/embedded/shared/CallFeedback/CallEndedScreen.js +34 -0
- package/dist/esm/src/embedded/shared/CallFeedback/CallEndedScreen.js.map +1 -0
- package/dist/esm/src/embedded/shared/CallFeedback/CallFeedback.js +35 -0
- package/dist/esm/src/embedded/shared/CallFeedback/CallFeedback.js.map +1 -0
- package/dist/esm/src/embedded/shared/CallFeedback/RatingScreen.js +18 -0
- package/dist/esm/src/embedded/shared/CallFeedback/RatingScreen.js.map +1 -0
- package/dist/esm/src/embedded/shared/CallFeedback/StarRating.js +37 -0
- package/dist/esm/src/embedded/shared/CallFeedback/StarRating.js.map +1 -0
- package/dist/esm/src/embedded/shared/CallFeedback/ThankYouScreen.js +34 -0
- package/dist/esm/src/embedded/shared/CallFeedback/ThankYouScreen.js.map +1 -0
- package/dist/esm/src/embedded/shared/ConnectionNotification/ConnectionNotification.js +56 -0
- package/dist/esm/src/embedded/shared/ConnectionNotification/ConnectionNotification.js.map +1 -0
- package/dist/esm/src/embedded/shared/EmbeddedParticipantViewUI/EmbeddedParticipantViewUI.js +42 -0
- package/dist/esm/src/embedded/shared/EmbeddedParticipantViewUI/EmbeddedParticipantViewUI.js.map +1 -0
- package/dist/esm/src/embedded/shared/JoinError/JoinError.js +34 -0
- package/dist/esm/src/embedded/shared/JoinError/JoinError.js.map +1 -0
- package/dist/esm/src/embedded/shared/Lobby/DeviceControls.js +44 -0
- package/dist/esm/src/embedded/shared/Lobby/DeviceControls.js.map +1 -0
- package/dist/esm/src/embedded/shared/Lobby/DisabledDeviceButton.js +31 -0
- package/dist/esm/src/embedded/shared/Lobby/DisabledDeviceButton.js.map +1 -0
- package/dist/esm/src/embedded/shared/Lobby/Lobby.js +45 -0
- package/dist/esm/src/embedded/shared/Lobby/Lobby.js.map +1 -0
- package/dist/esm/src/embedded/shared/Lobby/ToggleCameraButton.js +40 -0
- package/dist/esm/src/embedded/shared/Lobby/ToggleCameraButton.js.map +1 -0
- package/dist/esm/src/embedded/shared/Lobby/ToggleMicButton.js +41 -0
- package/dist/esm/src/embedded/shared/Lobby/ToggleMicButton.js.map +1 -0
- package/dist/esm/src/embedded/shared/Lobby/VideoPreviewFallbacks.js +50 -0
- package/dist/esm/src/embedded/shared/Lobby/VideoPreviewFallbacks.js.map +1 -0
- package/dist/esm/src/embedded/shared/ViewersCount/ViewersCount.js +31 -0
- package/dist/esm/src/embedded/shared/ViewersCount/ViewersCount.js.map +1 -0
- package/dist/esm/src/hooks/useDeviceList.js +40 -0
- package/dist/esm/src/hooks/useDeviceList.js.map +1 -0
- package/dist/esm/src/hooks/useDragToScroll.js +116 -0
- package/dist/esm/src/hooks/useDragToScroll.js.map +1 -0
- package/dist/esm/src/hooks/useFloatingUIPreset.js +34 -0
- package/dist/esm/src/hooks/useFloatingUIPreset.js.map +1 -0
- package/dist/esm/src/hooks/useLoopbackRecording.js +138 -0
- package/dist/esm/src/hooks/useLoopbackRecording.js.map +1 -0
- package/dist/esm/src/hooks/useModeration.js +135 -0
- package/dist/esm/src/hooks/useModeration.js.map +1 -0
- package/dist/esm/src/hooks/usePersistedDevicePreferences.js +16 -0
- package/dist/esm/src/hooks/usePersistedDevicePreferences.js.map +1 -0
- package/dist/esm/src/hooks/useRequestPermission.js +41 -0
- package/dist/esm/src/hooks/useRequestPermission.js.map +1 -0
- package/dist/esm/src/hooks/useScrollPosition.js +66 -0
- package/dist/esm/src/hooks/useScrollPosition.js.map +1 -0
- package/dist/esm/src/translations/en.json.js +177 -0
- package/dist/esm/src/translations/en.json.js.map +1 -0
- package/dist/esm/src/translations/index.js +6 -0
- package/dist/esm/src/translations/index.js.map +1 -0
- package/dist/esm/src/utilities/applyElementToRef.js +10 -0
- package/dist/esm/src/utilities/applyElementToRef.js.map +1 -0
- package/dist/esm/src/utilities/callControlHandler.js +29 -0
- package/dist/esm/src/utilities/callControlHandler.js.map +1 -0
- package/dist/esm/src/utilities/chunk.js +7 -0
- package/dist/esm/src/utilities/chunk.js.map +1 -0
- package/dist/esm/src/utilities/filter.js +94 -0
- package/dist/esm/src/utilities/filter.js.map +1 -0
- package/dist/esm/src/utilities/isComponentType.js +10 -0
- package/dist/esm/src/utilities/isComponentType.js.map +1 -0
- package/dist/esm/src/utilities/normalizeString.js +11 -0
- package/dist/esm/src/utilities/normalizeString.js.map +1 -0
- package/dist/esm/src/wrappers/LivestreamPlayer/LivestreamPlayer.js +105 -0
- package/dist/esm/src/wrappers/LivestreamPlayer/LivestreamPlayer.js.map +1 -0
- package/dist/index.cjs.js +135 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/src/hooks/index.d.ts +1 -0
- package/dist/src/hooks/useLoopbackRecording.d.ts +23 -0
- package/index.ts +4 -0
- package/package.json +14 -10
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useLoopbackRecording.ts +207 -0
- package/dist/background-filters-D2U5UBbH.es.js.map +0 -1
- package/dist/embedded-BackgroundFilters-D2U5UBbH.es.js +0 -420
- package/dist/embedded-BackgroundFilters-D2U5UBbH.es.js.map +0 -1
- package/dist/embedded-CallStatsLatencyChart-Bj5OSYzg.es.js +0 -57
- package/dist/embedded-CallStatsLatencyChart-Bj5OSYzg.es.js.map +0 -1
- package/dist/embedded.es.js +0 -3536
- package/dist/embedded.es.js.map +0 -1
- package/dist/index.es.js +0 -3291
- package/dist/index.es.js.map +0 -1
- 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;;;;"}
|