@glitchlab/vue-video-player 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,356 @@
1
+ import { defineComponent as h, ref as y, onMounted as V, watch as D, onUnmounted as I, openBlock as c, createElementBlock as v, normalizeClass as f, renderSlot as H, createElementVNode as n, computed as $, normalizeStyle as T, createVNode as k, withCtx as W, createCommentVNode as M, toDisplayString as Z } from "vue";
2
+ import B from "hls.js";
3
+ const j = ["muted", "loop", "controls", "playsinline", "preload", "poster"], N = /* @__PURE__ */ h({
4
+ __name: "HLSPlayer",
5
+ props: {
6
+ src: {},
7
+ hlsConfig: {},
8
+ isHls: { type: Boolean },
9
+ muted: { type: Boolean, default: !0 },
10
+ loop: { type: Boolean, default: !1 },
11
+ controls: { type: Boolean, default: !1 },
12
+ playsInline: { type: Boolean, default: !0 },
13
+ preload: { default: "metadata" },
14
+ poster: {},
15
+ class: {}
16
+ },
17
+ emits: ["play", "pause"],
18
+ setup(t, { expose: d, emit: a }) {
19
+ const l = t, w = a, i = y(null), r = y(null), C = globalThis.window !== void 0 && B.isSupported(), m = (o) => !!l.isHls || C && o.endsWith(".m3u8");
20
+ function b() {
21
+ r.value && (r.value.destroy(), r.value = null);
22
+ const o = i.value;
23
+ if (o) {
24
+ for (o.pause(), o.removeAttribute("src"); o.firstChild; ) o.firstChild.remove();
25
+ o.load();
26
+ }
27
+ }
28
+ function x(o) {
29
+ const u = i.value;
30
+ if (!(!u || !o))
31
+ if (b(), m(o)) {
32
+ const p = new B(l.hlsConfig);
33
+ r.value = p, p.attachMedia(u), p.loadSource(o), p.on(B.Events.ERROR, (L, P) => {
34
+ P.fatal && (p.destroy(), r.value = null);
35
+ });
36
+ } else
37
+ u.src = o, u.load();
38
+ }
39
+ return V(() => {
40
+ l.src && x(l.src);
41
+ }), D(
42
+ () => l.src,
43
+ (o) => {
44
+ o && x(o);
45
+ }
46
+ ), I(b), d({ videoEl: i }), (o, u) => (c(), v("video", {
47
+ ref_key: "videoEl",
48
+ ref: i,
49
+ muted: t.muted,
50
+ loop: t.loop,
51
+ controls: t.controls,
52
+ playsinline: t.playsInline,
53
+ preload: t.preload,
54
+ poster: t.poster,
55
+ class: f(l.class),
56
+ onPlay: u[0] || (u[0] = (p) => w("play")),
57
+ onPause: u[1] || (u[1] = (p) => w("pause"))
58
+ }, [
59
+ H(o.$slots, "default")
60
+ ], 42, j));
61
+ }
62
+ }), U = { name: "IconDesktop" }, z = /* @__PURE__ */ h({
63
+ ...U,
64
+ props: {
65
+ class: {}
66
+ },
67
+ setup(t) {
68
+ const d = t;
69
+ return (a, l) => (c(), v("svg", {
70
+ class: f(["gvp-icon", d.class]),
71
+ width: "20",
72
+ height: "20",
73
+ viewBox: "0 0 24 24",
74
+ fill: "none",
75
+ xmlns: "http://www.w3.org/2000/svg",
76
+ "aria-hidden": "true"
77
+ }, [...l[0] || (l[0] = [
78
+ n("path", {
79
+ d: "M14 2H10C6.72077 2 5.08116 2 3.91891 2.81382C3.48891 3.1149 3.1149 3.48891 2.81382 3.91891C2 5.08116 2 6.72077 2 10C2 13.2792 2 14.9188 2.81382 16.0811C3.1149 16.5111 3.48891 16.8851 3.91891 17.1862C5.08116 18 6.72077 18 10 18H14C17.2792 18 18.9188 18 20.0811 17.1862C20.5111 16.8851 20.8851 16.5111 21.1862 16.0811C22 14.9188 22 13.2792 22 10C22 6.72077 22 5.08116 21.1862 3.91891C20.8851 3.48891 20.5111 3.1149 20.0811 2.81382C18.9188 2 17.2792 2 14 2Z",
80
+ stroke: "currentColor",
81
+ "stroke-width": "1.5",
82
+ "stroke-linecap": "round"
83
+ }, null, -1),
84
+ n("path", {
85
+ d: "M11 15H13",
86
+ stroke: "currentColor",
87
+ "stroke-width": "1.5",
88
+ "stroke-linecap": "round",
89
+ "stroke-linejoin": "round"
90
+ }, null, -1),
91
+ n("path", {
92
+ d: "M14.5 22L14.1845 21.5811C13.4733 20.6369 13.2969 19.1944 13.7468 18M9.5 22L9.8155 21.5811C10.5267 20.6369 10.7031 19.1944 10.2532 18",
93
+ stroke: "currentColor",
94
+ "stroke-width": "1.5",
95
+ "stroke-linecap": "round"
96
+ }, null, -1),
97
+ n("path", {
98
+ d: "M7 22H17",
99
+ stroke: "currentColor",
100
+ "stroke-width": "1.5",
101
+ "stroke-linecap": "round"
102
+ }, null, -1)
103
+ ])], 2));
104
+ }
105
+ }), A = { name: "IconMobile" }, J = /* @__PURE__ */ h({
106
+ ...A,
107
+ props: {
108
+ class: {}
109
+ },
110
+ setup(t) {
111
+ const d = t;
112
+ return (a, l) => (c(), v("svg", {
113
+ class: f(["gvp-icon", d.class]),
114
+ width: "20",
115
+ height: "20",
116
+ viewBox: "0 0 24 24",
117
+ fill: "none",
118
+ xmlns: "http://www.w3.org/2000/svg",
119
+ "aria-hidden": "true"
120
+ }, [...l[0] || (l[0] = [
121
+ n("path", {
122
+ d: "M5 9C5 5.70017 5 4.05025 6.02513 3.02513C7.05025 2 8.70017 2 12 2C15.2998 2 16.9497 2 17.9749 3.02513C19 4.05025 19 5.70017 19 9V15C19 18.2998 19 19.9497 17.9749 20.9749C16.9497 22 15.2998 22 12 22C8.70017 22 7.05025 22 6.02513 20.9749C5 19.9497 5 18.2998 5 15V9Z",
123
+ stroke: "currentColor",
124
+ "stroke-width": "2",
125
+ "stroke-linecap": "round"
126
+ }, null, -1),
127
+ n("path", {
128
+ d: "M11 19H13",
129
+ stroke: "currentColor",
130
+ "stroke-width": "2",
131
+ "stroke-linecap": "round",
132
+ "stroke-linejoin": "round"
133
+ }, null, -1),
134
+ n("path", {
135
+ d: "M9 2L9.089 2.53402C9.28188 3.69129 9.37832 4.26993 9.77519 4.62204C10.1892 4.98934 10.7761 5 12 5C13.2239 5 13.8108 4.98934 14.2248 4.62204C14.6217 4.26993 14.7181 3.69129 14.911 2.53402L15 2",
136
+ stroke: "currentColor",
137
+ "stroke-width": "2",
138
+ "stroke-linejoin": "round"
139
+ }, null, -1)
140
+ ])], 2));
141
+ }
142
+ }), O = { name: "IconPlay" }, X = /* @__PURE__ */ h({
143
+ ...O,
144
+ props: {
145
+ class: {}
146
+ },
147
+ setup(t) {
148
+ const d = t;
149
+ return (a, l) => (c(), v("svg", {
150
+ class: f(["gvp-icon", d.class]),
151
+ width: "22",
152
+ height: "22",
153
+ viewBox: "0 0 16 16",
154
+ fill: "none",
155
+ xmlns: "http://www.w3.org/2000/svg",
156
+ "aria-hidden": "true"
157
+ }, [...l[0] || (l[0] = [
158
+ n("path", {
159
+ d: "M5.3335 11.45V4.54997C5.3335 4.36108 5.40016 4.20275 5.5335 4.07497C5.66683 3.94719 5.82238 3.8833 6.00016 3.8833C6.05572 3.8833 6.11405 3.89163 6.17516 3.9083C6.23627 3.92497 6.29461 3.94997 6.35016 3.9833L11.7835 7.4333C11.8835 7.49997 11.9585 7.5833 12.0085 7.6833C12.0585 7.7833 12.0835 7.88886 12.0835 7.99997C12.0835 8.11108 12.0585 8.21663 12.0085 8.31663C11.9585 8.41663 11.8835 8.49997 11.7835 8.56663L6.35016 12.0166C6.29461 12.05 6.23627 12.075 6.17516 12.0916C6.11405 12.1083 6.05572 12.1166 6.00016 12.1166C5.82238 12.1166 5.66683 12.0527 5.5335 11.925C5.40016 11.7972 5.3335 11.6389 5.3335 11.45Z",
160
+ fill: "currentColor"
161
+ }, null, -1)
162
+ ])], 2));
163
+ }
164
+ }), q = { name: "IconX" }, F = /* @__PURE__ */ h({
165
+ ...q,
166
+ props: {
167
+ class: {}
168
+ },
169
+ setup(t) {
170
+ const d = t;
171
+ return (a, l) => (c(), v("svg", {
172
+ class: f(["gvp-icon", d.class]),
173
+ width: "14",
174
+ height: "14",
175
+ viewBox: "0 0 14 14",
176
+ fill: "none",
177
+ xmlns: "http://www.w3.org/2000/svg",
178
+ "aria-hidden": "true"
179
+ }, [...l[0] || (l[0] = [
180
+ n("path", {
181
+ d: "M6.94994 5.53594L12.1929 0.292938C12.5834 -0.0975275 13.2165 -0.0975279 13.6069 0.292938C13.9974 0.683403 13.9974 1.31647 13.6069 1.70694L8.36394 6.94994L13.6069 12.1929C13.9974 12.5834 13.9974 13.2165 13.6069 13.6069C13.2165 13.9974 12.5834 13.9974 12.1929 13.6069L6.94994 8.36394L1.70694 13.6069C1.31647 13.9974 0.683403 13.9974 0.292938 13.6069C-0.0975279 13.2165 -0.0975277 12.5834 0.292938 12.1929L5.53594 6.94994L0.292938 1.70694C-0.0975279 1.31647 -0.0975279 0.683403 0.292938 0.292938C0.683403 -0.0975279 1.31647 -0.0975277 1.70694 0.292938L6.94994 5.53594Z",
182
+ fill: "currentColor"
183
+ }, null, -1)
184
+ ])], 2));
185
+ }
186
+ }), G = {
187
+ key: 0,
188
+ class: "gvp-toggle"
189
+ }, K = { class: "gvp-toggle-pill" }, Q = ["aria-pressed"], Y = ["aria-pressed"], _ = {
190
+ key: 2,
191
+ class: "gvp-play-wrap"
192
+ }, ee = {
193
+ key: 0,
194
+ class: "gvp-tooltip",
195
+ role: "tooltip"
196
+ }, oe = /* @__PURE__ */ h({
197
+ __name: "VideoPlayer",
198
+ props: {
199
+ src: {},
200
+ poster: {},
201
+ showDeviceToggle: { type: Boolean, default: !0 },
202
+ defaultDevice: { default: "desktop" },
203
+ hoverPlay: { type: Boolean, default: !1 },
204
+ tooltipText: {},
205
+ muted: { type: Boolean, default: !0 },
206
+ loop: { type: Boolean, default: !1 },
207
+ controls: { type: Boolean, default: !1 },
208
+ frameMaxWidth: {},
209
+ aspectRatio: {},
210
+ hlsConfig: {},
211
+ isHls: { type: Boolean },
212
+ class: { default: "" },
213
+ closable: { type: Boolean, default: !1 }
214
+ },
215
+ emits: ["close", "play", "pause"],
216
+ setup(t, { emit: d }) {
217
+ const a = t, l = d, w = y(null), i = y(a.defaultDevice), r = y(!1), C = y(!1), m = y(null), b = $(
218
+ () => {
219
+ var s, e;
220
+ return i.value === "mobile" ? ((s = a.aspectRatio) == null ? void 0 : s.mobile) ?? "9/16" : ((e = a.aspectRatio) == null ? void 0 : e.desktop) ?? "16/9";
221
+ }
222
+ ), x = $(
223
+ () => {
224
+ var s, e;
225
+ return i.value === "mobile" ? ((s = a.frameMaxWidth) == null ? void 0 : s.mobile) ?? "420px" : ((e = a.frameMaxWidth) == null ? void 0 : e.desktop) ?? "960px";
226
+ }
227
+ ), o = $(() => {
228
+ var s;
229
+ return ((s = w.value) == null ? void 0 : s.videoEl) ?? null;
230
+ });
231
+ async function u() {
232
+ const s = o.value;
233
+ if (s)
234
+ try {
235
+ s.readyState < 2 && s.load();
236
+ const e = s.play();
237
+ m.value = e, await e, r.value = !0;
238
+ } catch {
239
+ r.value = !1;
240
+ } finally {
241
+ m.value = null;
242
+ }
243
+ }
244
+ async function p() {
245
+ const s = o.value;
246
+ if (s) {
247
+ if (m.value)
248
+ try {
249
+ await m.value;
250
+ } catch {
251
+ }
252
+ s.pause();
253
+ }
254
+ }
255
+ async function L() {
256
+ a.hoverPlay && await u();
257
+ }
258
+ async function P() {
259
+ a.hoverPlay && (await p(), r.value = !1);
260
+ }
261
+ async function R() {
262
+ const s = o.value;
263
+ s && (s.paused ? await u() : (await p(), r.value = !1));
264
+ }
265
+ function S() {
266
+ C.value = !0, L();
267
+ }
268
+ function E() {
269
+ C.value = !1, P();
270
+ }
271
+ return (s, e) => (c(), v("div", {
272
+ class: f(["gvp-root", a.class]),
273
+ style: T({ width: x.value, aspectRatio: b.value }),
274
+ onMouseenter: S,
275
+ onMouseleave: E
276
+ }, [
277
+ k(N, {
278
+ ref_key: "hlsPlayerRef",
279
+ ref: w,
280
+ controls: t.controls,
281
+ "hls-config": t.hlsConfig,
282
+ "is-hls": t.isHls,
283
+ loop: t.loop,
284
+ muted: t.muted,
285
+ "plays-inline": !0,
286
+ poster: t.poster,
287
+ src: t.src,
288
+ class: "gvp-video",
289
+ preload: "metadata",
290
+ onPause: e[0] || (e[0] = (g) => {
291
+ r.value = !1, l("pause");
292
+ }),
293
+ onPlay: e[1] || (e[1] = (g) => {
294
+ r.value = !0, l("play");
295
+ })
296
+ }, {
297
+ default: W(() => [
298
+ H(s.$slots, "default")
299
+ ]),
300
+ _: 3
301
+ }, 8, ["controls", "hls-config", "is-hls", "loop", "muted", "poster", "src"]),
302
+ e[8] || (e[8] = n("div", { class: "gvp-vignette" }, null, -1)),
303
+ t.showDeviceToggle ? (c(), v("div", G, [
304
+ n("div", K, [
305
+ n("button", {
306
+ "aria-pressed": i.value === "desktop",
307
+ class: f(["gvp-toggle-btn", { "is-active": i.value === "desktop" }]),
308
+ "aria-label": "Desktop view",
309
+ type: "button",
310
+ onClick: e[2] || (e[2] = (g) => i.value = "desktop")
311
+ }, [
312
+ k(z)
313
+ ], 10, Q),
314
+ e[7] || (e[7] = n("div", { class: "gvp-toggle-divider" }, null, -1)),
315
+ n("button", {
316
+ "aria-pressed": i.value === "mobile",
317
+ class: f(["gvp-toggle-btn", { "is-active": i.value === "mobile" }]),
318
+ "aria-label": "Mobile view",
319
+ type: "button",
320
+ onClick: e[3] || (e[3] = (g) => i.value = "mobile")
321
+ }, [
322
+ k(J)
323
+ ], 10, Y)
324
+ ])
325
+ ])) : M("", !0),
326
+ t.closable ? (c(), v("button", {
327
+ key: 1,
328
+ "aria-label": "Close",
329
+ class: "gvp-close",
330
+ type: "button",
331
+ onClick: e[4] || (e[4] = (g) => l("close"))
332
+ }, [
333
+ k(F)
334
+ ])) : M("", !0),
335
+ r.value ? M("", !0) : (c(), v("div", _, [
336
+ n("button", {
337
+ "aria-label": "Play",
338
+ class: "gvp-play",
339
+ type: "button",
340
+ onClick: R,
341
+ onMouseenter: e[5] || (e[5] = (g) => C.value = !0),
342
+ onMouseleave: e[6] || (e[6] = (g) => C.value = !1)
343
+ }, [
344
+ k(X),
345
+ t.tooltipText && C.value ? (c(), v("span", ee, Z(t.tooltipText), 1)) : M("", !0)
346
+ ], 32)
347
+ ])),
348
+ e[9] || (e[9] = n("div", { class: "gvp-bottom-fade" }, null, -1))
349
+ ], 38));
350
+ }
351
+ });
352
+ export {
353
+ N as HLSPlayer,
354
+ oe as VueVideoPlayer
355
+ };
356
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/HLSPlayer.vue","../src/components/IconDesktop.vue","../src/components/IconMobile.vue","../src/components/IconPlay.vue","../src/components/IconX.vue","../src/VideoPlayer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport Hls from \"hls.js\";\nimport { onMounted, onUnmounted, ref, watch } from \"vue\";\nimport type { HlsConfig } from \"hls.js\";\n\nconst props = withDefaults(\n defineProps<{\n src: string;\n hlsConfig?: HlsConfig;\n isHls?: boolean;\n muted?: boolean;\n loop?: boolean;\n controls?: boolean;\n playsInline?: boolean;\n preload?: string;\n poster?: string;\n class?: string;\n }>(),\n {\n muted: true,\n loop: false,\n controls: false,\n playsInline: true,\n preload: \"metadata\"\n }\n);\n\nconst emit = defineEmits<{\n play: [];\n pause: [];\n}>();\n\nconst videoEl = ref<HTMLVideoElement | null>(null);\nconst hlsInstance = ref<Hls | null>(null);\n\nconst canUseHlsJs = globalThis.window !== undefined && Hls.isSupported();\nconst shouldUseHls = (src: string) =>\n Boolean(props.isHls) || (canUseHlsJs && src.endsWith(\".m3u8\"));\n\nfunction cleanup() {\n if (hlsInstance.value) {\n hlsInstance.value.destroy();\n hlsInstance.value = null;\n }\n const el = videoEl.value;\n if (!el) return;\n el.pause();\n el.removeAttribute(\"src\");\n while (el.firstChild) el.firstChild.remove();\n el.load();\n}\n\nfunction initPlayer(src: string) {\n const el = videoEl.value;\n if (!el || !src) return;\n\n cleanup();\n\n if (shouldUseHls(src)) {\n const hls = new Hls(props.hlsConfig);\n hlsInstance.value = hls;\n hls.attachMedia(el);\n hls.loadSource(src);\n hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data.fatal) {\n hls.destroy();\n hlsInstance.value = null;\n }\n });\n } else {\n el.src = src;\n el.load();\n }\n}\n\nonMounted(() => {\n if (props.src) initPlayer(props.src);\n});\n\nwatch(\n () => props.src,\n (src) => {\n if (src) initPlayer(src);\n }\n);\n\nonUnmounted(cleanup);\n\ndefineExpose({ videoEl });\n</script>\n\n<template>\n <video\n ref=\"videoEl\"\n :muted=\"muted\"\n :loop=\"loop\"\n :controls=\"controls\"\n :playsinline=\"playsInline\"\n :preload=\"preload\"\n :poster=\"poster\"\n :class=\"props.class\"\n @play=\"emit('play')\"\n @pause=\"emit('pause')\"\n >\n <slot />\n </video>\n</template>\n","<script setup lang=\"ts\">\nconst props = defineProps<{ class?: string }>();\n</script>\n\n<template>\n <svg\n :class=\"['gvp-icon', props.class]\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M14 2H10C6.72077 2 5.08116 2 3.91891 2.81382C3.48891 3.1149 3.1149 3.48891 2.81382 3.91891C2 5.08116 2 6.72077 2 10C2 13.2792 2 14.9188 2.81382 16.0811C3.1149 16.5111 3.48891 16.8851 3.91891 17.1862C5.08116 18 6.72077 18 10 18H14C17.2792 18 18.9188 18 20.0811 17.1862C20.5111 16.8851 20.8851 16.5111 21.1862 16.0811C22 14.9188 22 13.2792 22 10C22 6.72077 22 5.08116 21.1862 3.91891C20.8851 3.48891 20.5111 3.1149 20.0811 2.81382C18.9188 2 17.2792 2 14 2Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n <path\n d=\"M11 15H13\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M14.5 22L14.1845 21.5811C13.4733 20.6369 13.2969 19.1944 13.7468 18M9.5 22L9.8155 21.5811C10.5267 20.6369 10.7031 19.1944 10.2532 18\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n <path\n d=\"M7 22H17\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconDesktop\" };\n</script>\n","<script setup lang=\"ts\">\nconst props = defineProps<{ class?: string }>();\n</script>\n\n<template>\n <svg\n :class=\"['gvp-icon', props.class]\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5 9C5 5.70017 5 4.05025 6.02513 3.02513C7.05025 2 8.70017 2 12 2C15.2998 2 16.9497 2 17.9749 3.02513C19 4.05025 19 5.70017 19 9V15C19 18.2998 19 19.9497 17.9749 20.9749C16.9497 22 15.2998 22 12 22C8.70017 22 7.05025 22 6.02513 20.9749C5 19.9497 5 18.2998 5 15V9Z\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n <path\n d=\"M11 19H13\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M9 2L9.089 2.53402C9.28188 3.69129 9.37832 4.26993 9.77519 4.62204C10.1892 4.98934 10.7761 5 12 5C13.2239 5 13.8108 4.98934 14.2248 4.62204C14.6217 4.26993 14.7181 3.69129 14.911 2.53402L15 2\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linejoin=\"round\"\n />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconMobile\" };\n</script>\n","<script setup lang=\"ts\">\nconst props = defineProps<{ class?: string }>();\n</script>\n\n<template>\n <svg\n :class=\"['gvp-icon', props.class]\"\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5.3335 11.45V4.54997C5.3335 4.36108 5.40016 4.20275 5.5335 4.07497C5.66683 3.94719 5.82238 3.8833 6.00016 3.8833C6.05572 3.8833 6.11405 3.89163 6.17516 3.9083C6.23627 3.92497 6.29461 3.94997 6.35016 3.9833L11.7835 7.4333C11.8835 7.49997 11.9585 7.5833 12.0085 7.6833C12.0585 7.7833 12.0835 7.88886 12.0835 7.99997C12.0835 8.11108 12.0585 8.21663 12.0085 8.31663C11.9585 8.41663 11.8835 8.49997 11.7835 8.56663L6.35016 12.0166C6.29461 12.05 6.23627 12.075 6.17516 12.0916C6.11405 12.1083 6.05572 12.1166 6.00016 12.1166C5.82238 12.1166 5.66683 12.0527 5.5335 11.925C5.40016 11.7972 5.3335 11.6389 5.3335 11.45Z\"\n fill=\"currentColor\"\n />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconPlay\" };\n</script>\n","<script setup lang=\"ts\">\nconst props = defineProps<{ class?: string }>();\n</script>\n\n<template>\n <svg\n :class=\"['gvp-icon', props.class]\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.94994 5.53594L12.1929 0.292938C12.5834 -0.0975275 13.2165 -0.0975279 13.6069 0.292938C13.9974 0.683403 13.9974 1.31647 13.6069 1.70694L8.36394 6.94994L13.6069 12.1929C13.9974 12.5834 13.9974 13.2165 13.6069 13.6069C13.2165 13.9974 12.5834 13.9974 12.1929 13.6069L6.94994 8.36394L1.70694 13.6069C1.31647 13.9974 0.683403 13.9974 0.292938 13.6069C-0.0975279 13.2165 -0.0975277 12.5834 0.292938 12.1929L5.53594 6.94994L0.292938 1.70694C-0.0975279 1.31647 -0.0975279 0.683403 0.292938 0.292938C0.683403 -0.0975279 1.31647 -0.0975277 1.70694 0.292938L6.94994 5.53594Z\"\n fill=\"currentColor\"\n />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconX\" };\n</script>\n","<script lang=\"ts\" setup>\nimport { computed, ref } from \"vue\";\nimport HLSPlayer from \"./HLSPlayer.vue\";\nimport IconDesktop from \"./components/IconDesktop.vue\";\nimport IconMobile from \"./components/IconMobile.vue\";\nimport IconPlay from \"./components/IconPlay.vue\";\nimport IconX from \"./components/IconX.vue\";\nimport type { DeviceMode, VideoPlayerProps } from \"./utils/types\";\n\nconst props = withDefaults(\n defineProps<VideoPlayerProps & { class?: string; closable?: boolean }>(),\n {\n showDeviceToggle: true,\n defaultDevice: \"desktop\",\n hoverPlay: false,\n muted: true,\n loop: false,\n controls: false,\n closable: false,\n class: \"\"\n }\n);\n\nconst emit = defineEmits<{\n close: [];\n play: [];\n pause: [];\n}>();\n\nconst hlsPlayerRef = ref<InstanceType<typeof HLSPlayer> | null>(null);\nconst device = ref<DeviceMode>(props.defaultDevice);\nconst isPlaying = ref(false);\nconst showTooltip = ref(false);\nconst playPromise = ref<Promise<void> | null>(null);\n\nconst aspectRatio = computed(() =>\n device.value === \"mobile\"\n ? (props.aspectRatio?.mobile ?? \"9/16\")\n : (props.aspectRatio?.desktop ?? \"16/9\")\n);\n\nconst frameMaxWidth = computed(() =>\n device.value === \"mobile\"\n ? (props.frameMaxWidth?.mobile ?? \"420px\")\n : (props.frameMaxWidth?.desktop ?? \"960px\")\n);\n\nconst videoEl = computed(() => hlsPlayerRef.value?.videoEl ?? null);\n\nasync function safePlay() {\n const el = videoEl.value;\n if (!el) return;\n try {\n if (el.readyState < 2) el.load();\n const p = el.play();\n playPromise.value = p;\n await p;\n isPlaying.value = true;\n } catch {\n isPlaying.value = false;\n } finally {\n playPromise.value = null;\n }\n}\n\nasync function safePause() {\n const el = videoEl.value;\n if (!el) return;\n if (playPromise.value) {\n try {\n await playPromise.value;\n } catch {\n /* play was interrupted; nothing to await */\n }\n }\n el.pause();\n}\n\nasync function hoverStart() {\n if (!props.hoverPlay) return;\n await safePlay();\n}\n\nasync function hoverStop() {\n if (!props.hoverPlay) return;\n await safePause();\n isPlaying.value = false;\n}\n\nasync function togglePlay() {\n const el = videoEl.value;\n if (!el) return;\n if (el.paused) {\n await safePlay();\n } else {\n await safePause();\n isPlaying.value = false;\n }\n}\n\nfunction onMouseEnter() {\n showTooltip.value = true;\n void hoverStart();\n}\n\nfunction onMouseLeave() {\n showTooltip.value = false;\n void hoverStop();\n}\n</script>\n\n<template>\n <div\n :class=\"['gvp-root', props.class]\"\n :style=\"{ width: frameMaxWidth, aspectRatio }\"\n @mouseenter=\"onMouseEnter\"\n @mouseleave=\"onMouseLeave\"\n >\n <HLSPlayer\n ref=\"hlsPlayerRef\"\n :controls=\"controls\"\n :hls-config=\"hlsConfig\"\n :is-hls=\"isHls\"\n :loop=\"loop\"\n :muted=\"muted\"\n :plays-inline=\"true\"\n :poster=\"poster\"\n :src=\"src\"\n class=\"gvp-video\"\n preload=\"metadata\"\n @pause=\"\n isPlaying = false;\n emit('pause');\n \"\n @play=\"\n isPlaying = true;\n emit('play');\n \"\n >\n <slot />\n </HLSPlayer>\n\n <div class=\"gvp-vignette\" />\n\n <div v-if=\"showDeviceToggle\" class=\"gvp-toggle\">\n <div class=\"gvp-toggle-pill\">\n <button\n :aria-pressed=\"device === 'desktop'\"\n :class=\"['gvp-toggle-btn', { 'is-active': device === 'desktop' }]\"\n aria-label=\"Desktop view\"\n type=\"button\"\n @click=\"device = 'desktop'\"\n >\n <IconDesktop />\n </button>\n\n <div class=\"gvp-toggle-divider\" />\n\n <button\n :aria-pressed=\"device === 'mobile'\"\n :class=\"['gvp-toggle-btn', { 'is-active': device === 'mobile' }]\"\n aria-label=\"Mobile view\"\n type=\"button\"\n @click=\"device = 'mobile'\"\n >\n <IconMobile />\n </button>\n </div>\n </div>\n\n <button\n v-if=\"closable\"\n aria-label=\"Close\"\n class=\"gvp-close\"\n type=\"button\"\n @click=\"emit('close')\"\n >\n <IconX />\n </button>\n\n <div v-if=\"!isPlaying\" class=\"gvp-play-wrap\">\n <button\n aria-label=\"Play\"\n class=\"gvp-play\"\n type=\"button\"\n @click=\"togglePlay\"\n @mouseenter=\"showTooltip = true\"\n @mouseleave=\"showTooltip = false\"\n >\n <IconPlay />\n <span v-if=\"tooltipText && showTooltip\" class=\"gvp-tooltip\" role=\"tooltip\">\n {{ tooltipText }}\n </span>\n </button>\n </div>\n\n <div class=\"gvp-bottom-fade\" />\n </div>\n</template>\n"],"names":["props","__props","emit","__emit","videoEl","ref","hlsInstance","canUseHlsJs","Hls","shouldUseHls","src","cleanup","el","initPlayer","hls","_evt","data","onMounted","watch","onUnmounted","__expose","_createElementBlock","_normalizeClass","_renderSlot","_ctx","__default__","_createElementVNode","hlsPlayerRef","device","isPlaying","showTooltip","playPromise","aspectRatio","computed","_a","_b","frameMaxWidth","safePlay","p","safePause","hoverStart","hoverStop","togglePlay","onMouseEnter","onMouseLeave","_normalizeStyle","_createVNode","HLSPlayer","_cache","$event","_openBlock","_hoisted_1","_hoisted_2","IconDesktop","IconMobile","IconX","_hoisted_5","IconPlay","_hoisted_6","_toDisplayString"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";const e=require("@nuxt/kit");var t=typeof document<"u"?document.currentScript:null;const u=e.defineNuxtModule({meta:{name:"@glitchlab/vue-video-player",configKey:"vueVideoPlayer",compatibility:{nuxt:">=3.0.0"}},setup(o,r){const n=e.createResolver(typeof document>"u"?require("url").pathToFileURL(__filename).href:t&&t.tagName.toUpperCase()==="SCRIPT"&&t.src||new URL("nuxt-module.cjs",document.baseURI).href);e.addPlugin(n.resolve("./nuxt-plugin"))}});module.exports=u;
2
+ //# sourceMappingURL=nuxt-module.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nuxt-module.cjs","sources":["../src/utils/nuxt-module.ts"],"sourcesContent":["import { addPlugin, createResolver, defineNuxtModule } from \"@nuxt/kit\";\n\nexport interface ModuleOptions {\n /** Reserved for future configuration. */\n _reserved?: never;\n}\n\nexport default defineNuxtModule<ModuleOptions>({\n meta: {\n name: \"@glitchlab/vue-video-player\",\n configKey: \"vueVideoPlayer\",\n compatibility: {\n nuxt: \">=3.0.0\"\n }\n },\n setup(_options, _nuxt) {\n const resolver = createResolver(import.meta.url);\n addPlugin(resolver.resolve(\"./nuxt-plugin\"));\n }\n});\n"],"names":["nuxtModule","defineNuxtModule","_options","_nuxt","resolver","createResolver","addPlugin"],"mappings":"gGAOA,MAAAA,EAAeC,mBAAgC,CAC7C,KAAM,CACJ,KAAM,8BACN,UAAW,iBACX,cAAe,CACb,KAAM,SAAA,CACR,EAEF,MAAMC,EAAUC,EAAO,CACrB,MAAMC,EAAWC,EAAAA,+KAA8B,EAC/CC,EAAAA,UAAUF,EAAS,QAAQ,eAAe,CAAC,CAC7C,CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './utils/nuxt-module'
2
+ import _default from './utils/nuxt-module'
3
+ export default _default
@@ -0,0 +1,18 @@
1
+ import { defineNuxtModule as t, createResolver as o, addPlugin as l } from "@nuxt/kit";
2
+ const r = t({
3
+ meta: {
4
+ name: "@glitchlab/vue-video-player",
5
+ configKey: "vueVideoPlayer",
6
+ compatibility: {
7
+ nuxt: ">=3.0.0"
8
+ }
9
+ },
10
+ setup(u, i) {
11
+ const e = o(import.meta.url);
12
+ l(e.resolve("./nuxt-plugin"));
13
+ }
14
+ });
15
+ export {
16
+ r as default
17
+ };
18
+ //# sourceMappingURL=nuxt-module.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nuxt-module.mjs","sources":["../src/utils/nuxt-module.ts"],"sourcesContent":["import { addPlugin, createResolver, defineNuxtModule } from \"@nuxt/kit\";\n\nexport interface ModuleOptions {\n /** Reserved for future configuration. */\n _reserved?: never;\n}\n\nexport default defineNuxtModule<ModuleOptions>({\n meta: {\n name: \"@glitchlab/vue-video-player\",\n configKey: \"vueVideoPlayer\",\n compatibility: {\n nuxt: \">=3.0.0\"\n }\n },\n setup(_options, _nuxt) {\n const resolver = createResolver(import.meta.url);\n addPlugin(resolver.resolve(\"./nuxt-plugin\"));\n }\n});\n"],"names":["nuxtModule","defineNuxtModule","_options","_nuxt","resolver","createResolver","addPlugin"],"mappings":";AAOA,MAAAA,IAAeC,EAAgC;AAAA,EAC7C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,WAAW;AAAA,IACX,eAAe;AAAA,MACb,MAAM;AAAA,IAAA;AAAA,EACR;AAAA,EAEF,MAAMC,GAAUC,GAAO;AACrB,UAAMC,IAAWC,EAAe,YAAY,GAAG;AAC/C,IAAAC,EAAUF,EAAS,QAAQ,eAAe,CAAC;AAAA,EAC7C;AACF,CAAC;"}
package/dist/style.css ADDED
@@ -0,0 +1,4 @@
1
+ /*!
2
+ * @glitchlab/vue-video-player styles
3
+ * Scoped under .gvp-root — no global resets, no theme tokens, safe for any host.
4
+ */.gvp-root{position:relative;overflow:hidden;border-radius:1.5rem;background-color:#1717174d;box-shadow:0 25px 50px -12px #00000040;outline:1px solid rgb(255 255 255 / .1);outline-offset:-1px;margin-left:auto;margin-right:auto;width:100%;box-sizing:border-box}.gvp-root *,.gvp-root *:before,.gvp-root *:after{box-sizing:border-box}.gvp-video{height:100%;width:100%;object-fit:cover;display:block}.gvp-vignette{pointer-events:none;position:absolute;top:0;right:0;bottom:0;left:0;background-image:linear-gradient(to top right,#00000059,#0000,#00000059)}.gvp-bottom-fade{pointer-events:none;position:absolute;bottom:0;left:0;right:0;height:4rem;background-image:linear-gradient(to top,rgb(0 0 0 / .35),transparent)}.gvp-toggle{position:absolute;left:1rem;top:1rem}.gvp-toggle-pill{display:flex;align-items:center;overflow:hidden;border-radius:1rem;background-color:#fffffff2;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;outline:1px solid rgb(0 0 0 / .05);outline-offset:-1px}.gvp-toggle-btn{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;cursor:pointer;background:transparent;border:0;color:#737373;transition:color .15s ease;font-family:inherit}.gvp-toggle-btn:hover{color:#404040}.gvp-toggle-btn.is-active{color:#5b21b6}.gvp-toggle-divider{height:1.75rem;width:1px;background-color:#e5e5e5}.gvp-close{position:absolute;right:1rem;top:1rem;display:grid;place-items:center;height:2.5rem;width:2.5rem;border:0;border-radius:9999px;background-color:#00000059;color:#fff;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);outline:1px solid rgb(255 255 255 / .15);outline-offset:-1px;cursor:pointer;z-index:10;transition:background-color .15s ease}.gvp-close:hover{background-color:#00000080}.gvp-play-wrap{position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center}.gvp-play{position:relative;display:grid;place-items:center;height:3.5rem;width:3.5rem;border:0;border-radius:9999px;cursor:pointer;outline:1px solid rgb(255 255 255 / .15);outline-offset:-1px;background-color:#5b21b680;box-shadow:0 20px 25px -5px #0000001a,0 8px 10px -6px #0000001a;transition:background-color .2s ease,opacity .2s ease;color:#fff}.gvp-play:hover{background-color:#5b21b6e6}.gvp-tooltip{position:absolute;top:-3rem;left:50%;transform:translate(-50%);white-space:nowrap;border-radius:.75rem;background-color:#000000b3;padding:.375rem .75rem;font-size:.75rem;line-height:1rem;color:#fff;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;outline:1px solid rgb(255 255 255 / .1);outline-offset:-1px;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.gvp-icon{display:block}
@@ -0,0 +1,7 @@
1
+ export interface ModuleOptions {
2
+ /** Reserved for future configuration. */
3
+ _reserved?: never;
4
+ }
5
+ declare const _default: NuxtModule<TOptions, TOptions, false>;
6
+ export default _default;
7
+ //# sourceMappingURL=nuxt-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nuxt-module.d.ts","sourceRoot":"","sources":["../../src/utils/nuxt-module.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,SAAS,CAAC,EAAE,KAAK,CAAC;CACnB;;AAED,wBAYG"}
@@ -0,0 +1,54 @@
1
+ import { HlsConfig } from 'hls.js';
2
+
3
+ export type DeviceMode = "desktop" | "mobile";
4
+ export type AspectRatio = `${number}/${number}`;
5
+ export interface VideoPlayerProps {
6
+ /** Video source URL. `.m3u8` URLs are routed through hls.js automatically. */
7
+ src: string;
8
+ /** Poster image shown before playback. */
9
+ poster?: string;
10
+ /** Show the desktop/mobile toggle pill in the top-left. Defaults to `true`. */
11
+ showDeviceToggle?: boolean;
12
+ /** Initial device mode. Defaults to `"desktop"`. */
13
+ defaultDevice?: DeviceMode;
14
+ /** Start playback on mouse enter, pause on mouse leave. Defaults to `false`. */
15
+ hoverPlay?: boolean;
16
+ /** Text shown in a tooltip above the play button. */
17
+ tooltipText?: string;
18
+ /** Mute the video. Defaults to `true`. */
19
+ muted?: boolean;
20
+ /** Loop playback. Defaults to `false`. */
21
+ loop?: boolean;
22
+ /** Show native browser controls. Defaults to `false`. */
23
+ controls?: boolean;
24
+ /** Maximum width of the player in each device mode. */
25
+ frameMaxWidth?: {
26
+ desktop?: string;
27
+ mobile?: string;
28
+ };
29
+ /** Aspect ratio in each device mode. */
30
+ aspectRatio?: {
31
+ desktop?: AspectRatio;
32
+ mobile?: AspectRatio;
33
+ };
34
+ /**
35
+ * Optional hls.js configuration. Pass a stable reference to avoid tearing
36
+ * down and rebuilding the HLS instance on each render.
37
+ */
38
+ hlsConfig?: HlsConfig;
39
+ /** Force HLS routing even when the URL doesn't end in `.m3u8`. */
40
+ isHls?: boolean;
41
+ }
42
+ export interface HLSPlayerProps {
43
+ src: string;
44
+ hlsConfig?: HlsConfig;
45
+ isHls?: boolean;
46
+ muted?: boolean;
47
+ loop?: boolean;
48
+ controls?: boolean;
49
+ playsInline?: boolean;
50
+ preload?: string;
51
+ poster?: string;
52
+ class?: string;
53
+ }
54
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE9C,MAAM,MAAM,WAAW,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,GAAG,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oDAAoD;IACpD,aAAa,CAAC,EAAE,UAAU,CAAC;IAE3B,gFAAgF;IAChF,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yDAAyD;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,uDAAuD;IACvD,aAAa,CAAC,EAAE;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF,wCAAwC;IACxC,WAAW,CAAC,EAAE;QACZ,OAAO,CAAC,EAAE,WAAW,CAAC;QACtB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,CAAC;IAEF;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
package/package.json ADDED
@@ -0,0 +1,104 @@
1
+ {
2
+ "name": "@glitchlab/vue-video-player",
3
+ "version": "1.0.0",
4
+ "description": "Vue 3 / Nuxt 3 video player with HLS support, device-mode toggle, hover-to-play, and zero global CSS side-effects.",
5
+ "license": "MIT",
6
+ "author": "im-fahad",
7
+ "type": "module",
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.mjs",
10
+ "types": "./dist/index.d.ts",
11
+ "style": "./dist/style.css",
12
+ "files": [
13
+ "dist",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.mjs",
21
+ "require": "./dist/index.cjs"
22
+ },
23
+ "./style.css": "./dist/style.css",
24
+ "./nuxt": {
25
+ "types": "./dist/nuxt-module.d.ts",
26
+ "import": "./dist/nuxt-module.mjs",
27
+ "require": "./dist/nuxt-module.cjs"
28
+ },
29
+ "./package.json": "./package.json"
30
+ },
31
+ "sideEffects": [
32
+ "**/*.css"
33
+ ],
34
+ "engines": {
35
+ "node": ">=18"
36
+ },
37
+ "keywords": [
38
+ "vue",
39
+ "vue3",
40
+ "nuxt",
41
+ "nuxt3",
42
+ "video",
43
+ "player",
44
+ "hls",
45
+ "hls.js",
46
+ "streaming",
47
+ "m3u8",
48
+ "video-player",
49
+ "vue-player",
50
+ "typescript",
51
+ "responsive",
52
+ "mobile",
53
+ "desktop",
54
+ "adaptive",
55
+ "overlay",
56
+ "hover-play",
57
+ "device-toggle"
58
+ ],
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "git+https://github.com/im-fahad/react-video-player.git",
62
+ "directory": "packages/vue-video-player"
63
+ },
64
+ "homepage": "https://github.com/im-fahad/react-video-player/tree/main/packages/vue-video-player#readme",
65
+ "bugs": {
66
+ "url": "https://github.com/im-fahad/react-video-player/issues"
67
+ },
68
+ "peerDependencies": {
69
+ "hls.js": ">=1",
70
+ "vue": ">=3"
71
+ },
72
+ "peerDependenciesMeta": {
73
+ "@nuxt/kit": {
74
+ "optional": true
75
+ }
76
+ },
77
+ "devDependencies": {
78
+ "@eslint/js": "^9",
79
+ "@nuxt/kit": "^3.0.0",
80
+ "@types/node": "^20",
81
+ "eslint": "^9",
82
+ "eslint-config-prettier": "^10.1.8",
83
+ "eslint-plugin-vue": "^9.32.0",
84
+ "@vitejs/plugin-vue": "^5",
85
+ "@vue/test-utils": "^2.4.6",
86
+ "hls.js": "^1.5.0",
87
+ "jsdom": "^25.0.1",
88
+ "typescript": "^5",
89
+ "vite": "^5",
90
+ "vite-plugin-dts": "^3",
91
+ "vitest": "^2.1.8",
92
+ "vue": "^3.4.0",
93
+ "vue-tsc": "^2",
94
+ "typescript-eslint": "^8.56.1"
95
+ },
96
+ "scripts": {
97
+ "build": "vite build",
98
+ "build:watch": "vite build --watch",
99
+ "test": "vitest run",
100
+ "test:watch": "vitest",
101
+ "lint": "eslint src",
102
+ "type-check": "vue-tsc --noEmit"
103
+ }
104
+ }