1+ import { RefObject , useCallback } from "react" ;
2+ import { UsePIPProps , UsePIPResult } from "../models" ;
3+
4+ /**
5+ * **``**: Hook to use PIP [(Picture-in-Picture API)](https://developer.mozilla.org/en-US/docs/Web/API/Picture-in-Picture_API).
6+ * @param {UsePIPProps } param - object
7+ * @param {RefObject<HTMLVideoElement>|HTMLVideoElement } param.target - element to PIP.
8+ * @param {()=>void } [param.onOpen] - function that will be executed before open PIP.
9+ * @param {(pip: PictureInPictureWindow)=>void } [param.onOpened] - function that will be executed when PIP is opened.
10+ * @param {()=>void } [param.onClosed] - function that will be executed when PIP is closed.
11+ * @param {(err: unknown)=>void } [param.onError] - function that will be executed when error is throwing.
12+ * @returns {UsePIPResult } result
13+ * Object with three properties:
14+ * - __isSupported__: boolean that indicates if PIP is supported or not.
15+ * - __openPIP__: function to open PIP.
16+ * - __closePIP__: function to close PIP.
17+ */
18+ export const usePIP = ( { onOpen, onOpened, onClosed, onError, target } : UsePIPProps ) : UsePIPResult => {
19+ const isSupported = "pictureInPictureElement" in document ;
20+
21+ const openPIP = useCallback ( ( ) => {
22+ const element = ( target as RefObject < HTMLVideoElement > ) ?. current
23+ ? ( target as RefObject < HTMLVideoElement > ) . current
24+ : target as HTMLVideoElement ;
25+ ! ! onOpen && onOpen ( ) ;
26+ if ( ! ( "pictureInPictureElement" in document ) ) {
27+ return Promise . resolve ( ) ;
28+ }
29+ return element ! . requestPictureInPicture ( )
30+ . then ( pip => {
31+ ! ! onOpened && onOpened ( pip ) ;
32+ element ! . addEventListener ( "leavepictureinpicture" , ( ) => {
33+ ! ! onClosed && onClosed ( ) ;
34+ } , false ) ;
35+ } )
36+ . catch ( err => {
37+ if ( onError ) {
38+ onError ( err ) ;
39+ } else {
40+ throw err ;
41+ }
42+ } ) ;
43+ } , [ ] ) ;
44+
45+ const closePIP = useCallback ( ( ) => {
46+ if ( ! ( "pictureInPictureElement" in document ) ) {
47+ return Promise . resolve ( ) ;
48+ }
49+ return document . exitPictureInPicture ( )
50+ . catch ( err => {
51+ if ( onError ) {
52+ onError ( err ) ;
53+ } else {
54+ throw err ;
55+ }
56+ } ) ;
57+ } , [ ] ) ;
58+
59+ return { isSupported, openPIP, closePIP } ;
60+ }
0 commit comments