UNPKG

9.35 kBSource Map (JSON)View Raw
1{"version":3,"file":"v-pip.min.js","sources":["../src/VPip.vue","../src/VPip.vue?vue&type=template&id=63b7ba3a&lang.js","../src/install.ts"],"sourcesContent":["<template>\n <div :class=\"wrapper\">\n <div :class=\"videoOptions.wrapper\">\n <video\n ref=\"video\"\n :src=\"videoOptions.src\"\n :poster=\"videoOptions.poster\"\n :class=\"videoOptions.class\"\n :height=\"videoOptions.height\"\n :width=\"videoOptions.width\"\n controls\n />\n </div>\n <div :class=\"buttonOptions.wrapper\">\n <button\n v-if=\"state.isPipSupported\"\n :type=\"buttonOptions.type\"\n :class=\"buttonOptions.class\"\n @click=\"togglePip\"\n >\n {{ buttonOptions.label }}\n </button>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import {\n reactive,\n onMounted,\n onBeforeUnmount,\n defineComponent,\n PropType,\n } from 'vue';\n import { VideoOptionsProps, ButtonOptionsProps, State } from '../types';\n\n export default defineComponent({\n name: 'VPip',\n props: {\n // Video related options\n videoOptions: {\n type: Object as PropType<VideoOptionsProps>,\n required: false,\n default: () => ({\n wrapper: '',\n src: '',\n poster: '',\n class: '',\n height: '100%',\n width: '100%',\n }),\n },\n // button related options\n buttonOptions: {\n type: Object as PropType<ButtonOptionsProps>,\n required: false,\n default: () => ({\n wrapper: '',\n type: 'button',\n class: '',\n label: 'Toggle picture-in-picture',\n }),\n },\n wrapper: {\n type: String as PropType<string>,\n default: '',\n required: false,\n },\n },\n emits: ['video-in-pip', 'requesting-pip-failure', 'exiting-pip-failure'],\n setup(_, { emit }) {\n // State\n const state: State = reactive({\n video: null,\n isPipSupported: false,\n });\n\n // Lifecycle Hooks\n onMounted(() => {\n state.isPipSupported = 'pictureInPictureEnabled' in document;\n state.video?.addEventListener('enterpictureinpicture', enteredPip);\n state.video?.addEventListener('leavepictureinpicture', leftPip);\n });\n onBeforeUnmount(() => {\n state.video?.removeEventListener('enterpictureinpicture', leftPip);\n state.video?.removeEventListener('leavepictureinpicture', leftPip);\n });\n /**\n * Emit an event when entered PiP mode\n *\n * @returns {void}\n */\n function enteredPip(): void {\n emit('video-in-pip', true);\n }\n /**\n * Emit an event when left PiP mode\n *\n * @returns {void}\n */\n function leftPip(): void {\n emit('video-in-pip', false);\n }\n // Methods\n const togglePip = () => {\n // If there is no element in Picture-in-Picture yet, let’s request\n // Picture-in-Picture for the video, otherwise leave it.\n const { pictureInPictureElement, exitPictureInPicture } =\n document as Document;\n if (!pictureInPictureElement && state.video) {\n state.video.requestPictureInPicture().catch((error: any) => {\n // Video failed to enter Picture-in-Picture mode.\n emit('requesting-pip-failure', error);\n });\n } else {\n exitPictureInPicture().catch((error: any) => {\n // Video failed to leave Picture-in-Picture mode.\n emit('exiting-pip-failure', error);\n });\n }\n };\n\n return {\n state,\n togglePip,\n };\n },\n });\n</script>\n","<template>\n <div :class=\"wrapper\">\n <div :class=\"videoOptions.wrapper\">\n <video\n ref=\"video\"\n :src=\"videoOptions.src\"\n :poster=\"videoOptions.poster\"\n :class=\"videoOptions.class\"\n :height=\"videoOptions.height\"\n :width=\"videoOptions.width\"\n controls\n />\n </div>\n <div :class=\"buttonOptions.wrapper\">\n <button\n v-if=\"state.isPipSupported\"\n :type=\"buttonOptions.type\"\n :class=\"buttonOptions.class\"\n @click=\"togglePip\"\n >\n {{ buttonOptions.label }}\n </button>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import {\n reactive,\n onMounted,\n onBeforeUnmount,\n defineComponent,\n PropType,\n } from 'vue';\n import { VideoOptionsProps, ButtonOptionsProps, State } from '../types';\n\n export default defineComponent({\n name: 'VPip',\n props: {\n // Video related options\n videoOptions: {\n type: Object as PropType<VideoOptionsProps>,\n required: false,\n default: () => ({\n wrapper: '',\n src: '',\n poster: '',\n class: '',\n height: '100%',\n width: '100%',\n }),\n },\n // button related options\n buttonOptions: {\n type: Object as PropType<ButtonOptionsProps>,\n required: false,\n default: () => ({\n wrapper: '',\n type: 'button',\n class: '',\n label: 'Toggle picture-in-picture',\n }),\n },\n wrapper: {\n type: String as PropType<string>,\n default: '',\n required: false,\n },\n },\n emits: ['video-in-pip', 'requesting-pip-failure', 'exiting-pip-failure'],\n setup(_, { emit }) {\n // State\n const state: State = reactive({\n video: null,\n isPipSupported: false,\n });\n\n // Lifecycle Hooks\n onMounted(() => {\n state.isPipSupported = 'pictureInPictureEnabled' in document;\n state.video?.addEventListener('enterpictureinpicture', enteredPip);\n state.video?.addEventListener('leavepictureinpicture', leftPip);\n });\n onBeforeUnmount(() => {\n state.video?.removeEventListener('enterpictureinpicture', leftPip);\n state.video?.removeEventListener('leavepictureinpicture', leftPip);\n });\n /**\n * Emit an event when entered PiP mode\n *\n * @returns {void}\n */\n function enteredPip(): void {\n emit('video-in-pip', true);\n }\n /**\n * Emit an event when left PiP mode\n *\n * @returns {void}\n */\n function leftPip(): void {\n emit('video-in-pip', false);\n }\n // Methods\n const togglePip = () => {\n // If there is no element in Picture-in-Picture yet, let’s request\n // Picture-in-Picture for the video, otherwise leave it.\n const { pictureInPictureElement, exitPictureInPicture } =\n document as Document;\n if (!pictureInPictureElement && state.video) {\n state.video.requestPictureInPicture().catch((error: any) => {\n // Video failed to enter Picture-in-Picture mode.\n emit('requesting-pip-failure', error);\n });\n } else {\n exitPictureInPicture().catch((error: any) => {\n // Video failed to leave Picture-in-Picture mode.\n emit('exiting-pip-failure', error);\n });\n }\n };\n\n return {\n state,\n togglePip,\n };\n },\n });\n</script>\n","import { App } from 'vue';\nimport VPip from './VPip.vue';\n\nlet installed = false;\n\nconst install = {\n install(app: App): void {\n if (installed) return;\n app.component('VPip', VPip);\n installed = true;\n },\n};\n\nexport default install;\n"],"names":["props","type","Object","required","src","poster","class","buttonOptions","label","wrapper","emits","setup","_","emit","isPipSupported","onMounted","_optionalChain","state","_2","video","_3","addEventListener","_4","enteredPip","_5","_6","_7","leftPip","onBeforeUnmount","_8","_9","removeEventListener","_10","_11","_12","_13","togglePip","document","pictureInPictureElement","error","exitPictureInPicture","catch","_normalizeClass","_ctx","ref","controls","onClick","_cache","args","_toDisplayString","_hoisted_2","installed","install$1","install","app","component","VPip"],"mappings":";;;;;0jBAsCIA,MAAA,eAGIC,KAAAC,OACAC,UAAA,2BAGEC,IAAA,GACAC,OAAA,GACAC,MAAA,iCAMJC,cAAA,CACEN,KAAAC,OACAC,UAAA,yCAIEG,MAAA,GACAE,MAAA,+BAGJC,QAAA,wBAGEN,UAAA,IAGJO,MAAA,CAAA,eAAA,yBAAA,uBACAC,MAAAC,GAAAC,KAAAA,mCAIIC,gBAAA,wEAIFC,EAAAA,WAAA,2DAEEC,EAAA,CAAAC,EAAA,SAAAC,GAAAA,EAAAC,MAAA,iBAAAC,GAAAA,EAAAC,iBAAA,OAAAC,GAAAA,EAAA,wBAAAC,KACAP,EAAA,CAAAC,EAAA,SAAAO,GAAAA,EAAAL,MAAA,iBAAAM,GAAAA,EAAAJ,iBAAA,OAAAK,GAAAA,EAAA,wBAAAC,QAEFC,EAAAA,iBAAA,KACEZ,EAAA,CAAAC,EAAA,SAAAY,GAAAA,EAAAV,MAAA,iBAAAW,GAAAA,EAAAC,oBAAA,OAAAC,GAAAA,EAAA,wBAAAL,KACAX,EAAA,CAAAC,EAAA,SAAAgB,GAAAA,EAAAd,MAAA,iBAAAe,GAAAA,EAAAH,oBAAA,OAAAI,GAAAA,EAAA,wBAAAR,QAqCF,MAAA,SAEES,UApBF,6DAIIC,UACFC,GAAArB,EAAAE,mDAGIN,EAAA,yBAAA0B,MAGFC,IAAAC,OAAAF,IAEE1B,EAAA,sBAAA0B,gJCpHJjC,MAAAoC,EAAAA,eAAAC,EAAAlC,sHAGAmC,IAAA,iKAMAC,SAAA,iGAKMF,EAAA1B,MAAA,2IAGL6B,QAAAC,EAAA,KAAAA,EAAA,GAAA,IAAAC,IAAAL,EAAAP,WAAAO,EAAAP,aAAAY,KAEEC,EAAAA,gBAAAN,EAAApC,cAAAC,OAAA,GAAA0C,qECjBX,IAAAC,GAAA,EAUA,IAAAC,EARA,CACAC,QAAAC,GACAH,IACAG,EAAAC,UAAA,OAAAC,GACAL,GAAA"}
\No newline at end of file