UNPKG

10.3 kBSource Map (JSON)View Raw
1{"version":3,"file":"v-pip.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":["onMounted","onBeforeUnmount","_normalizeClass","_toDisplayString","VPip"],"mappings":"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"}
\No newline at end of file