v-pip
Version:
Vue wrapper for native picture-in-picture (PiP)
1 lines • 6.9 kB
Source Map (JSON)
{"version":3,"file":"v-pip.umd.cjs","sources":["../src/components/VPip.vue","../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 type { ButtonHTMLAttributes } from 'vue';\n\n declare global {\n interface HTMLVideoElement {\n requestPictureInPicture(): Promise<PictureInPictureWindow>;\n }\n interface Document {\n readonly pictureInPictureElement: Element | null;\n exitPictureInPicture(): Promise<void>;\n }\n }\n\n type VideoOptionsProps = {\n wrapper: string;\n src: string;\n poster: string;\n class: string;\n height: string;\n width: string;\n };\n\n type ButtonOptionsProps = {\n wrapper: string;\n type?: ButtonHTMLAttributes['type'];\n class: string;\n label: string;\n };\n\n type State = {\n isPipSupported: boolean;\n video: null | HTMLVideoElement;\n };\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 const state: State = reactive({\n video: null,\n isPipSupported: false,\n });\n\n onMounted(() => {\n state.isPipSupported = 'pictureInPictureEnabled' in document;\n state.video?.addEventListener('enterpictureinpicture', enteredPip);\n state.video?.addEventListener('leavepictureinpicture', leftPip);\n });\n\n onBeforeUnmount(() => {\n state.video?.removeEventListener('enterpictureinpicture', leftPip);\n state.video?.removeEventListener('leavepictureinpicture', leftPip);\n });\n\n const enteredPip = (): void => {\n emit('video-in-pip', true);\n };\n\n const leftPip = (): void => {\n emit('video-in-pip', false);\n };\n\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 as Application, Plugin } from 'vue';\nimport VPip from './components/VPip.vue';\nimport { setVueInstance } from './utils/config/index';\n\nlet installed = false;\n\nconst install: Exclude<Plugin['install'], undefined> = (app: Application) => {\n if (!installed) {\n setVueInstance(app);\n app.component('VPip', VPip);\n installed = true;\n }\n};\n\nexport default install;\n"],"names":["_sfc_main","defineComponent","_","emit","state","reactive","onMounted","enteredPip","leftPip","onBeforeUnmount","pictureInPictureElement","exitPictureInPicture","error","_sfc_render","_ctx","wrapper","$props","$setup","$data","$options","_normalizeClass","videoOptions","_hoisted_1","_createElementVNode","_openBlock","_createElementBlock","buttonOptions","_cache","args","_toDisplayString","_hoisted_2","_createCommentVNode","installed","install$1","app","VPip"],"mappings":";;;;2PAmEE,MAAAA,EAAeC,kBAAgB,CAC7B,KAAM,OACN,MAAO,CAEL,aAAc,CACZ,KAAM,OACN,SAAU,GACV,QAAS,KAAO,CACd,QAAS,GACT,IAAK,GACL,OAAQ,GACR,MAAO,GACP,OAAQ,OACR,MAAO,MAAA,EAEX,EAEA,cAAe,CACb,KAAM,OACN,SAAU,GACV,QAAS,KAAO,CACd,QAAS,GACT,KAAM,SACN,MAAO,GACP,MAAO,2BAAA,EAEX,EACA,QAAS,CACP,KAAM,OACN,QAAS,GACT,SAAU,EACZ,CACF,EACA,MAAO,CAAC,eAAgB,yBAA0B,qBAAqB,EACvE,MAAMC,EAAG,CAAE,KAAAC,GAAQ,CACjB,MAAMC,EAAeC,EAAAA,SAAS,CAC5B,MAAO,KACP,eAAgB,EAAA,CACjB,EAEDC,EAAAA,UAAU,IAAM,CACdF,EAAM,eAAiB,4BAA6B,SAC9CA,EAAA,OAAO,iBAAiB,wBAAyBG,CAAU,EAC3DH,EAAA,OAAO,iBAAiB,wBAAyBI,CAAO,CAAA,CAC/D,EAEDC,EAAAA,gBAAgB,IAAM,CACdL,EAAA,OAAO,oBAAoB,wBAAyBI,CAAO,EAC3DJ,EAAA,OAAO,oBAAoB,wBAAyBI,CAAO,CAAA,CAClE,EAED,MAAMD,EAAa,IAAY,CAC7BJ,EAAK,eAAgB,EAAI,CAAA,EAGrBK,EAAU,IAAY,CAC1BL,EAAK,eAAgB,EAAK,CAAA,EAqBrB,MAAA,CACL,MAAAC,EACA,UApBgB,IAAM,CAGhB,KAAA,CAAE,wBAAAM,EAAyB,qBAAAC,CAC/B,EAAA,SACE,CAACD,GAA2BN,EAAM,MACpCA,EAAM,MAAM,wBAA0B,EAAA,MAAOQ,GAAe,CAE1DT,EAAK,yBAA0BS,CAAK,CAAA,CACrC,EAEoBD,EAAA,EAAE,MAAOC,GAAe,CAE3CT,EAAK,sBAAuBS,CAAK,CAAA,CAClC,CACH,CAKA,CAEJ,CACF,CAAC,sHApJU,SAAAC,EADbC,EACeC,EAAOC,EAAAC,EAAAC,EAAAC,EAAA,kDAClB,MAUMC,EAAAA,eAAAN,EAAA,OAAA,CAAA,EAAA,6BATJ,MAQEM,EAAA,eAAAN,EAAA,aAAA,OAAA,CAAA,EAAA,sBANMO,QAAgB,CACrB,IAAA,QACA,IAAKP,EAPd,aAOgBO,IACP,OAAQA,EAAa,aAAA,OACrB,MAAOA,mBAAa,aAAK,KAAA,EAC1B,OAAQP,EAAA,aAAA,OAVhB,MAAAA,EAAA,aAAA,MAAA,SAAA,IAsBU,KAAA,GAAAQ,CAAA,CATA,EAAA,CAAA,EAAAC,EAAAA,mBAAA,MAAA,CAEInB,MAAAA,EAAAA,eAAMU,EAAc,cAAA,OAAA,CAAA,EAAA,CAflCA,EAAA,MAAA,gBAAAU,EAAA,UAAA,EAgBiCC,EAAAA,mBAAA,SAAA,CACxB,IAAK,EACL,KAAKX,EAAA,cAAA,KAAA,MAAAM,EAAA,eAEHM,EAAmB,cAAA,KAAA,EApB9B,QAAAC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAA,IAAAC,IAAAd,EAAA,WAAAA,EAAA,UAAA,GAAAc,CAAA,EAAA,EAAAC,kBAAAf,EAAA,cAAA,KAAA,EAAA,GAAAgB,CAAA,GAAAC,EAAAA,mBAAA,GAAA,EAAA,sCCIA,IAAIC,EAAY,GAUhB,MAAAC,EARwDC,GAAqB,CACtEF,IAECE,EAAA,UAAU,OAAQC,CAAI,EACdH,EAAA,GAEhB"}