UNPKG

5.92 kBJavaScriptView Raw
1/*!
2* v-pip v2.3.1
3* (c) 2022 Vinayak Kulkarni
4* @license MIT
5*/
6(function (global, factory) {
7 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue')) :
8 typeof define === 'function' && define.amd ? define(['exports', 'vue'], factory) :
9 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VPip = {}, global.vue));
10})(this, (function (exports, vue) { 'use strict';
11
12 function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
13
14
15 var script = vue.defineComponent({
16 name: 'VPip',
17 props: {
18 // Video related options
19 videoOptions: {
20 type: Object ,
21 required: false,
22 default: () => ({
23 wrapper: '',
24 src: '',
25 poster: '',
26 class: '',
27 height: '100%',
28 width: '100%',
29 }),
30 },
31 // button related options
32 buttonOptions: {
33 type: Object ,
34 required: false,
35 default: () => ({
36 wrapper: '',
37 type: 'button',
38 class: '',
39 label: 'Toggle picture-in-picture',
40 }),
41 },
42 wrapper: {
43 type: String ,
44 default: '',
45 required: false,
46 },
47 },
48 emits: ['video-in-pip', 'requesting-pip-failure', 'exiting-pip-failure'],
49 setup(_, { emit }) {
50 // State
51 const state = vue.reactive({
52 video: null,
53 isPipSupported: false,
54 });
55
56 // Lifecycle Hooks
57 vue.onMounted(() => {
58 state.isPipSupported = 'pictureInPictureEnabled' in document;
59 _optionalChain([state, 'access', _2 => _2.video, 'optionalAccess', _3 => _3.addEventListener, 'call', _4 => _4('enterpictureinpicture', enteredPip)]);
60 _optionalChain([state, 'access', _5 => _5.video, 'optionalAccess', _6 => _6.addEventListener, 'call', _7 => _7('leavepictureinpicture', leftPip)]);
61 });
62 vue.onBeforeUnmount(() => {
63 _optionalChain([state, 'access', _8 => _8.video, 'optionalAccess', _9 => _9.removeEventListener, 'call', _10 => _10('enterpictureinpicture', leftPip)]);
64 _optionalChain([state, 'access', _11 => _11.video, 'optionalAccess', _12 => _12.removeEventListener, 'call', _13 => _13('leavepictureinpicture', leftPip)]);
65 });
66 /**
67 * Emit an event when entered PiP mode
68 *
69 * @returns {void}
70 */
71 function enteredPip() {
72 emit('video-in-pip', true);
73 }
74 /**
75 * Emit an event when left PiP mode
76 *
77 * @returns {void}
78 */
79 function leftPip() {
80 emit('video-in-pip', false);
81 }
82 // Methods
83 const togglePip = () => {
84 // If there is no element in Picture-in-Picture yet, let’s request
85 // Picture-in-Picture for the video, otherwise leave it.
86 const { pictureInPictureElement, exitPictureInPicture } =
87 document ;
88 if (!pictureInPictureElement && state.video) {
89 state.video.requestPictureInPicture().catch((error) => {
90 // Video failed to enter Picture-in-Picture mode.
91 emit('requesting-pip-failure', error);
92 });
93 } else {
94 exitPictureInPicture().catch((error) => {
95 // Video failed to leave Picture-in-Picture mode.
96 emit('exiting-pip-failure', error);
97 });
98 }
99 };
100
101 return {
102 state,
103 togglePip,
104 };
105 },
106 });
107
108 const _hoisted_1 = ["src", "poster", "height", "width"];
109 const _hoisted_2 = ["type"];
110
111 function render(_ctx, _cache, $props, $setup, $data, $options) {
112 return (vue.openBlock(), vue.createElementBlock("div", {
113 class: vue.normalizeClass(_ctx.wrapper)
114 }, [
115 vue.createElementVNode("div", {
116 class: vue.normalizeClass(_ctx.videoOptions.wrapper)
117 }, [
118 vue.createElementVNode("video", {
119 ref: "video",
120 src: _ctx.videoOptions.src,
121 poster: _ctx.videoOptions.poster,
122 class: vue.normalizeClass(_ctx.videoOptions.class),
123 height: _ctx.videoOptions.height,
124 width: _ctx.videoOptions.width,
125 controls: ""
126 }, null, 10 /* CLASS, PROPS */, _hoisted_1)
127 ], 2 /* CLASS */),
128 vue.createElementVNode("div", {
129 class: vue.normalizeClass(_ctx.buttonOptions.wrapper)
130 }, [
131 (_ctx.state.isPipSupported)
132 ? (vue.openBlock(), vue.createElementBlock("button", {
133 key: 0,
134 type: _ctx.buttonOptions.type,
135 class: vue.normalizeClass(_ctx.buttonOptions.class),
136 onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.togglePip && _ctx.togglePip(...args)))
137 }, vue.toDisplayString(_ctx.buttonOptions.label), 11 /* TEXT, CLASS, PROPS */, _hoisted_2))
138 : vue.createCommentVNode("v-if", true)
139 ], 2 /* CLASS */)
140 ], 2 /* CLASS */))
141 }
142
143 script.render = render;
144 script.__file = "src/VPip.vue";
145
146 let installed = false;
147
148 const install = {
149 install(app) {
150 if (installed) return;
151 app.component('VPip', script);
152 installed = true;
153 },
154 };
155
156 var install$1 = install;
157
158 exports.VPip = script;
159 exports["default"] = install$1;
160
161 Object.defineProperty(exports, '__esModule', { value: true });
162
163}));
164//# sourceMappingURL=v-pip.js.map