@@ -50,6 +50,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
5050 onVolumeChange,
5151 onEnd,
5252 onPlaybackStateChanged,
53+ onPictureInPictureStatusChanged,
5354 } ,
5455 ref ,
5556 ) => {
@@ -180,6 +181,31 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
180181 [ setFullScreen ] ,
181182 ) ;
182183
184+ const enterPictureInPicture = useCallback ( ( ) => {
185+ try {
186+ if ( ! nativeRef . current ) {
187+ console . error ( 'Video Component is not mounted' ) ;
188+ } else {
189+ nativeRef . current . requestPictureInPicture ( ) ;
190+ }
191+ } catch ( e ) {
192+ console . error ( e ) ;
193+ }
194+ } , [ ] ) ;
195+
196+ const exitPictureInPicture = useCallback ( ( ) => {
197+ if (
198+ nativeRef . current &&
199+ nativeRef . current === document . pictureInPictureElement
200+ ) {
201+ try {
202+ document . exitPictureInPicture ( ) ;
203+ } catch ( e ) {
204+ console . error ( e ) ;
205+ }
206+ }
207+ } , [ ] ) ;
208+
183209 useImperativeHandle (
184210 ref ,
185211 ( ) => ( {
@@ -193,8 +219,8 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
193219 dismissFullscreenPlayer,
194220 setFullScreen,
195221 save : unsupported ,
196- enterPictureInPicture : unsupported ,
197- exitPictureInPicture : unsupported ,
222+ enterPictureInPicture,
223+ exitPictureInPicture,
198224 restoreUserInterfaceForPictureInPictureStopCompleted : unsupported ,
199225 nativeHtmlVideoRef : nativeRef ,
200226 } ) ,
@@ -210,6 +236,8 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
210236 presentFullscreenPlayer ,
211237 dismissFullscreenPlayer ,
212238 setFullScreen ,
239+ enterPictureInPicture ,
240+ exitPictureInPicture ,
213241 ] ,
214242 ) ;
215243
@@ -254,6 +282,27 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
254282 nativeRef . current . playbackRate = rate ;
255283 } , [ rate ] ) ;
256284
285+ useEffect ( ( ) => {
286+ if (
287+ typeof onPictureInPictureStatusChanged !== 'function' ||
288+ ! nativeRef . current
289+ ) {
290+ return ;
291+ }
292+ const onEnterPip = ( ) =>
293+ onPictureInPictureStatusChanged ( { isActive : true } ) ;
294+ const onLeavePip = ( ) =>
295+ onPictureInPictureStatusChanged ( { isActive : false } ) ;
296+
297+ const video = nativeRef . current ;
298+ video . addEventListener ( 'enterpictureinpicture' , onEnterPip ) ;
299+ video . addEventListener ( 'leavepictureinpicture' , onLeavePip ) ;
300+ return ( ) => {
301+ video . removeEventListener ( 'enterpictureinpicture' , onEnterPip ) ;
302+ video . removeEventListener ( 'leavepictureinpicture' , onLeavePip ) ;
303+ } ;
304+ } , [ onPictureInPictureStatusChanged ] ) ;
305+
257306 useMediaSession ( src ?. metadata , nativeRef , showNotificationControls ) ;
258307
259308 return (
0 commit comments