@glitchlab/vue-video-player 1.1.1 → 1.3.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/README.md +66 -1
- package/dist/HLSPlayer.vue.d.ts +10 -0
- package/dist/HLSPlayer.vue.d.ts.map +1 -1
- package/dist/VideoPlayer.vue.d.ts +1 -1
- package/dist/VideoPlayer.vue.d.ts.map +1 -1
- package/dist/components/AudioTrackSwitcher.vue.d.ts +24 -0
- package/dist/components/AudioTrackSwitcher.vue.d.ts.map +1 -0
- package/dist/components/CaptionsSwitcher.vue.d.ts +16 -0
- package/dist/components/CaptionsSwitcher.vue.d.ts.map +1 -0
- package/dist/components/ControlBar.vue.d.ts +22 -0
- package/dist/components/ControlBar.vue.d.ts.map +1 -0
- package/dist/components/IconAudio.vue.d.ts +16 -0
- package/dist/components/IconAudio.vue.d.ts.map +1 -0
- package/dist/components/IconCaptions.vue.d.ts +16 -0
- package/dist/components/IconCaptions.vue.d.ts.map +1 -0
- package/dist/components/IconChevron.vue.d.ts +16 -0
- package/dist/components/IconChevron.vue.d.ts.map +1 -0
- package/dist/components/IconFullscreen.vue.d.ts +16 -0
- package/dist/components/IconFullscreen.vue.d.ts.map +1 -0
- package/dist/components/IconFullscreenExit.vue.d.ts +16 -0
- package/dist/components/IconFullscreenExit.vue.d.ts.map +1 -0
- package/dist/components/IconPause.vue.d.ts +16 -0
- package/dist/components/IconPause.vue.d.ts.map +1 -0
- package/dist/components/IconPiP.vue.d.ts +16 -0
- package/dist/components/IconPiP.vue.d.ts.map +1 -0
- package/dist/components/IconPlaySolid.vue.d.ts +16 -0
- package/dist/components/IconPlaySolid.vue.d.ts.map +1 -0
- package/dist/components/IconSpeed.vue.d.ts +16 -0
- package/dist/components/IconSpeed.vue.d.ts.map +1 -0
- package/dist/components/IconVolumeHigh.vue.d.ts +16 -0
- package/dist/components/IconVolumeHigh.vue.d.ts.map +1 -0
- package/dist/components/IconVolumeLow.vue.d.ts +16 -0
- package/dist/components/IconVolumeLow.vue.d.ts.map +1 -0
- package/dist/components/IconVolumeMuted.vue.d.ts +16 -0
- package/dist/components/IconVolumeMuted.vue.d.ts.map +1 -0
- package/dist/components/SpeedSwitcher.vue.d.ts +20 -0
- package/dist/components/SpeedSwitcher.vue.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1370 -227
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/utils/audio-tracks.d.ts +15 -0
- package/dist/utils/audio-tracks.d.ts.map +1 -0
- package/dist/utils/format-time.d.ts +2 -0
- package/dist/utils/format-time.d.ts.map +1 -0
- package/dist/utils/types.d.ts +8 -2
- package/dist/utils/types.d.ts.map +1 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),g=require("hls.js"),S=["muted","loop","controls","autoplay","playsinline","preload","poster"],B=e.defineComponent({__name:"HLSPlayer",props:{src:{},hlsConfig:{},isHls:{type:Boolean},muted:{type:Boolean,default:!0},loop:{type:Boolean,default:!1},controls:{type:Boolean,default:!1},autoPlay:{type:Boolean,default:!1},playsInline:{type:Boolean,default:!0},preload:{default:"metadata"},poster:{},class:{}},emits:["play","pause"],setup(t,{expose:n,emit:l}){const o=t,p=l,c=e.ref(null),u=e.ref(null),i=globalThis.window!==void 0&&g.isSupported(),C=r=>!!o.isHls||i&&r.endsWith(".m3u8");let m;function v(){m==null||m(),m=void 0,u.value&&(u.value.destroy(),u.value=null);const r=c.value;if(r){for(r.pause(),r.removeAttribute("src");r.firstChild;)r.firstChild.remove();r.load()}}function k(r){const d=c.value;if(!d||!r)return;v();const f=()=>{o.autoPlay&&d.play().catch(()=>{})};if(C(r)){const y=new g(o.hlsConfig);u.value=y,y.attachMedia(d),y.loadSource(r),y.on(g.Events.MANIFEST_PARSED,f),y.on(g.Events.ERROR,(w,b)=>{b.fatal&&(y.destroy(),u.value=null)})}else d.src=r,d.load(),d.addEventListener("loadedmetadata",f,{once:!0}),m=()=>{d.removeEventListener("loadedmetadata",f)}}return e.onMounted(()=>{o.src&&k(o.src)}),e.watch(()=>o.src,r=>{r&&k(r)}),e.onUnmounted(v),n({videoEl:c}),(r,d)=>(e.openBlock(),e.createElementBlock("video",{ref_key:"videoEl",ref:c,muted:t.muted,loop:t.loop,controls:t.controls,autoplay:t.autoPlay,playsinline:t.playsInline,preload:t.preload,poster:t.poster,class:e.normalizeClass(o.class),onPlay:d[0]||(d[0]=f=>p("play")),onPause:d[1]||(d[1]=f=>p("pause"))},[e.renderSlot(r.$slots,"default")],42,S))}}),L={name:"IconDesktop"},T=e.defineComponent({...L,props:{class:{}},setup(t){const n=t;return(l,o)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",n.class]),width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...o[0]||(o[0]=[e.createElementVNode("path",{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",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),e.createElementVNode("path",{d:"M11 15H13",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round","stroke-linejoin":"round"},null,-1),e.createElementVNode("path",{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",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),e.createElementVNode("path",{d:"M7 22H17",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1)])],2))}}),I={name:"IconMobile"},H=e.defineComponent({...I,props:{class:{}},setup(t){const n=t;return(l,o)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",n.class]),width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...o[0]||(o[0]=[e.createElementVNode("path",{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",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"},null,-1),e.createElementVNode("path",{d:"M11 19H13",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1),e.createElementVNode("path",{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",stroke:"currentColor","stroke-width":"2","stroke-linejoin":"round"},null,-1)])],2))}}),R={name:"IconPlay"},z=e.defineComponent({...R,props:{class:{}},setup(t){const n=t;return(l,o)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",n.class]),width:"22",height:"22",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...o[0]||(o[0]=[e.createElementVNode("path",{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",fill:"currentColor"},null,-1)])],2))}}),A={name:"IconX"},D=e.defineComponent({...A,props:{class:{}},setup(t){const n=t;return(l,o)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",n.class]),width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...o[0]||(o[0]=[e.createElementVNode("path",{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",fill:"currentColor"},null,-1)])],2))}});function E(t){if(!t)return null;if(/^[A-Za-z0-9_-]{11}$/.test(t))return t;let n;try{n=new URL(t)}catch{return null}const l=n.hostname.replace(/^www\./,"");if(l==="youtu.be"){const o=n.pathname.slice(1).split("/")[0];return/^[A-Za-z0-9_-]{11}$/.test(o)?o:null}if(l==="youtube.com"||l==="m.youtube.com"||l==="music.youtube.com"||l==="youtube-nocookie.com"){const o=n.searchParams.get("v");if(o&&/^[A-Za-z0-9_-]{11}$/.test(o))return o;const p=/^\/(?:embed|shorts|v|live)\/([A-Za-z0-9_-]{11})/.exec(n.pathname);if(p)return p[1]}return null}function P(t){try{const n=new URL(t),l=n.searchParams.get("t")??n.searchParams.get("start");if(!l)return null;if(/^\d+s?$/.test(l))return Number.parseInt(l,10);const o=/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/.exec(l);if(o){const p=Number.parseInt(o[1]??"0",10),c=Number.parseInt(o[2]??"0",10),u=Number.parseInt(o[3]??"0",10),i=p*3600+c*60+u;return i>0?i:null}}catch{}return null}function V(t,n={}){const{autoPlay:l=!1,muted:o=!0,loop:p=!1,controls:c=!0,startSeconds:u}=n,i=new URLSearchParams({rel:"0",modestbranding:"1",playsinline:"1",controls:c?"1":"0"});return l?(i.set("autoplay","1"),i.set("mute","1")):o&&i.set("mute","1"),p&&(i.set("loop","1"),i.set("playlist",t)),u&&u>0&&i.set("start",String(u)),`https://www.youtube-nocookie.com/embed/${t}?${i.toString()}`}const U=["src"],Z={key:2,class:"gvp-vignette"},Y={key:3,class:"gvp-toggle"},W={class:"gvp-toggle-pill"},_=["aria-pressed"],j=["aria-pressed"],q={key:5,class:"gvp-play-wrap"},O={key:0,class:"gvp-tooltip",role:"tooltip"},F={key:6,class:"gvp-bottom-fade"},J=e.defineComponent({__name:"VideoPlayer",props:{src:{},poster:{},showDeviceToggle:{type:Boolean,default:!0},defaultDevice:{default:"desktop"},hoverPlay:{type:Boolean,default:!1},tooltipText:{},muted:{type:Boolean,default:!0},loop:{type:Boolean,default:!1},controls:{type:Boolean,default:!1},autoPlay:{type:Boolean,default:!1},frameMaxWidth:{},aspectRatio:{},hlsConfig:{},isHls:{type:Boolean},class:{default:""},closable:{type:Boolean,default:!1}},emits:["close","play","pause"],setup(t,{emit:n}){const l=t,o=n,p=e.ref(null),c=e.ref(l.defaultDevice),u=e.ref(!1),i=e.ref(!1),C=e.ref(null),m=e.computed(()=>E(l.src)),v=e.computed(()=>m.value!==null),k=e.computed(()=>m.value?V(m.value,{autoPlay:l.autoPlay,muted:l.muted,loop:l.loop,controls:l.controls,startSeconds:P(l.src)}):null),r=e.computed(()=>{var s,a;return c.value==="mobile"?((s=l.aspectRatio)==null?void 0:s.mobile)??"9/16":((a=l.aspectRatio)==null?void 0:a.desktop)??"16/9"}),d=e.computed(()=>{var s,a;return c.value==="mobile"?((s=l.frameMaxWidth)==null?void 0:s.mobile)??"420px":((a=l.frameMaxWidth)==null?void 0:a.desktop)??"960px"}),f=e.computed(()=>{var s;return((s=p.value)==null?void 0:s.videoEl)??null});async function y(){const s=f.value;if(s)try{s.readyState<2&&s.load();const a=s.play();C.value=a,await a,u.value=!0}catch{u.value=!1}finally{C.value=null}}async function w(){const s=f.value;if(s){if(C.value)try{await C.value}catch{}s.pause()}}async function b(){!l.hoverPlay||v.value||await y()}async function N(){!l.hoverPlay||v.value||(await w(),u.value=!1)}async function $(){const s=f.value;s&&(s.paused?await y():(await w(),u.value=!1))}function x(){i.value=!0,b()}function M(){i.value=!1,N()}return(s,a)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["gvp-root",l.class]),style:e.normalizeStyle({width:d.value,aspectRatio:r.value}),onMouseenter:x,onMouseleave:M},[v.value?(e.openBlock(),e.createElementBlock("iframe",{key:0,class:"gvp-video gvp-youtube",src:k.value??void 0,title:"YouTube video player",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",allowfullscreen:"",referrerpolicy:"strict-origin-when-cross-origin"},null,8,U)):(e.openBlock(),e.createBlock(B,{key:1,ref_key:"hlsPlayerRef",ref:p,controls:t.controls,"hls-config":t.hlsConfig,"is-hls":t.isHls,loop:t.loop,muted:t.muted,"auto-play":t.autoPlay,"plays-inline":!0,poster:t.poster,src:t.src,class:"gvp-video",preload:"metadata",onPause:a[0]||(a[0]=h=>{u.value=!1,o("pause")}),onPlay:a[1]||(a[1]=h=>{u.value=!0,o("play")})},{default:e.withCtx(()=>[e.renderSlot(s.$slots,"default")]),_:3},8,["controls","hls-config","is-hls","loop","muted","auto-play","poster","src"])),v.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",Z)),t.showDeviceToggle?(e.openBlock(),e.createElementBlock("div",Y,[e.createElementVNode("div",W,[e.createElementVNode("button",{"aria-pressed":c.value==="desktop",class:e.normalizeClass(["gvp-toggle-btn",{"is-active":c.value==="desktop"}]),"aria-label":"Desktop view",type:"button",onClick:a[2]||(a[2]=h=>c.value="desktop")},[e.createVNode(T)],10,_),a[7]||(a[7]=e.createElementVNode("div",{class:"gvp-toggle-divider"},null,-1)),e.createElementVNode("button",{"aria-pressed":c.value==="mobile",class:e.normalizeClass(["gvp-toggle-btn",{"is-active":c.value==="mobile"}]),"aria-label":"Mobile view",type:"button",onClick:a[3]||(a[3]=h=>c.value="mobile")},[e.createVNode(H)],10,j)])])):e.createCommentVNode("",!0),t.closable?(e.openBlock(),e.createElementBlock("button",{key:4,"aria-label":"Close",class:"gvp-close",type:"button",onClick:a[4]||(a[4]=h=>o("close"))},[e.createVNode(D)])):e.createCommentVNode("",!0),!v.value&&!u.value?(e.openBlock(),e.createElementBlock("div",q,[e.createElementVNode("button",{"aria-label":"Play",class:"gvp-play",type:"button",onClick:$,onMouseenter:a[5]||(a[5]=h=>i.value=!0),onMouseleave:a[6]||(a[6]=h=>i.value=!1)},[e.createVNode(z),t.tooltipText&&i.value?(e.openBlock(),e.createElementBlock("span",O,e.toDisplayString(t.tooltipText),1)):e.createCommentVNode("",!0)],32)])):e.createCommentVNode("",!0),v.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",F))],38))}});exports.HLSPlayer=B;exports.VueVideoPlayer=J;exports.parseYouTubeId=E;exports.parseYouTubeStart=P;exports.youTubeEmbedUrl=V;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),R=require("hls.js");function Q(n,a,r){const t=n==null?void 0:n.trim();if(t)return t;if(a){try{const p=new Intl.DisplayNames(void 0,{type:"language"}).of(a);if(p&&p!==a)return p}catch{}return a}return`Audio ${r+1}`}const ce=["muted","loop","controls","autoplay","playsinline","preload","poster"],te=e.defineComponent({__name:"HLSPlayer",props:{src:{},hlsConfig:{},isHls:{type:Boolean},muted:{type:Boolean,default:!0},loop:{type:Boolean,default:!1},controls:{type:Boolean,default:!1},autoPlay:{type:Boolean,default:!1},playsInline:{type:Boolean,default:!0},preload:{default:"metadata"},poster:{},class:{},audioTrackIndex:{default:-1}},emits:["play","pause","audio-tracks"],setup(n,{expose:a,emit:r}){const t=n,l=r,p=e.ref(null),f=e.ref(null);let d,b;const B=globalThis.window!==void 0&&R.isSupported(),C=s=>!!t.isHls||B&&s.endsWith(".m3u8");function y(){b==null||b(),b=void 0,d==null||d(),d=void 0,f.value&&(f.value.destroy(),f.value=null);const s=p.value;if(s){for(s.pause(),s.removeAttribute("src");s.firstChild;)s.firstChild.remove();s.load(),l("audio-tracks",[])}}function k(s){var M,V,L;const g=p.value;if(!g||!s)return;y();const E=()=>{t.autoPlay&&g.play().catch(()=>{})};if(C(s)){const h=new R(t.hlsConfig);f.value=h;const x=()=>{const P=h.audioTracks.map((N,S)=>({index:S,label:Q(N.name,N.lang,S),lang:N.lang||void 0}));l("audio-tracks",P)};h.on(R.Events.MANIFEST_PARSED,E),h.on(R.Events.AUDIO_TRACKS_UPDATED,x),h.on(R.Events.AUDIO_TRACK_SWITCHED,x),h.on(R.Events.ERROR,(P,N)=>{N.fatal&&(h.destroy(),f.value=null)}),h.attachMedia(g),h.loadSource(s)}else{g.src=s,g.load(),g.addEventListener("loadedmetadata",E,{once:!0}),b=()=>{g.removeEventListener("loadedmetadata",E)};const h=g.audioTracks;if(h){const x=()=>{const P=[];for(let N=0;N<h.length;N++){const S=h[N];P.push({index:N,label:Q(S.label,S.language,N),lang:S.language||void 0})}l("audio-tracks",P)};(M=h.addEventListener)==null||M.call(h,"addtrack",x),(V=h.addEventListener)==null||V.call(h,"removetrack",x),(L=h.addEventListener)==null||L.call(h,"change",x),h.length>0&&x(),d=()=>{var P,N,S;(P=h.removeEventListener)==null||P.call(h,"addtrack",x),(N=h.removeEventListener)==null||N.call(h,"removetrack",x),(S=h.removeEventListener)==null||S.call(h,"change",x)}}}}function m(s){var M;if(s==null||s<0)return;const g=f.value;if(g){g.audioTrack!==s&&(g.audioTrack=s);return}const E=(M=p.value)==null?void 0:M.audioTracks;if(E)for(let V=0;V<E.length;V++)E[V].enabled=V===s}return e.onMounted(()=>{t.src&&k(t.src)}),e.watch(()=>t.src,s=>{s&&k(s)}),e.watch(()=>t.audioTrackIndex,s=>m(s)),e.onBeforeUnmount(y),a({videoEl:p}),(s,g)=>(e.openBlock(),e.createElementBlock("video",{ref_key:"videoEl",ref:p,muted:n.muted,loop:n.loop,controls:n.controls,autoplay:n.autoPlay,playsinline:n.playsInline,preload:n.preload,poster:n.poster,class:e.normalizeClass(t.class),onPlay:g[0]||(g[0]=E=>l("play")),onPause:g[1]||(g[1]=E=>l("pause"))},[e.renderSlot(s.$slots,"default")],42,ce))}}),ue={name:"IconAudio"},de=e.defineComponent({...ue,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{d:"M3 14V10C3 9.44772 3.44772 9 4 9H6.58579C6.851 9 7.10536 8.89464 7.29289 8.70711L11.2929 4.70711C11.9229 4.07714 13 4.52331 13 5.41421V18.5858C13 19.4767 11.9229 19.9229 11.2929 19.2929L7.29289 15.2929C7.10536 15.1054 6.851 15 6.58579 15H4C3.44772 15 3 14.5523 3 14Z",stroke:"currentColor","stroke-width":"1.5","stroke-linejoin":"round"},null,-1),e.createElementVNode("path",{d:"M16.5 8C17.5 9 18 10.5 18 12C18 13.5 17.5 15 16.5 16M19 5.5C20.5 7 21.5 9.5 21.5 12C21.5 14.5 20.5 17 19 18.5",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1)])],2))}}),ve={name:"IconChevron"},ne=e.defineComponent({...ve,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{d:"M6 9L12 15L18 9",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])],2))}}),pe=["aria-expanded"],me={class:"gvp-audio-label"},fe={key:0,class:"gvp-audio-menu",role:"listbox","aria-label":"Audio tracks"},ke=["aria-selected","onClick"],he=e.defineComponent({__name:"AudioTrackSwitcher",props:{tracks:{},activeIndex:{}},emits:["select"],setup(n,{emit:a}){const r=n,t=a,l=e.ref(!1),p=e.ref(null),f=e.computed(()=>r.tracks.find(C=>C.index===r.activeIndex)??r.tracks[0]);function d(C){p.value&&!p.value.contains(C.target)&&(l.value=!1)}function b(C){C.key==="Escape"&&(l.value=!1)}e.watch(l,C=>{C?(document.addEventListener("mousedown",d),document.addEventListener("keydown",b)):(document.removeEventListener("mousedown",d),document.removeEventListener("keydown",b))}),e.onBeforeUnmount(()=>{document.removeEventListener("mousedown",d),document.removeEventListener("keydown",b)});function B(C){t("select",C),l.value=!1}return(C,y)=>{var k;return e.openBlock(),e.createElementBlock("div",{ref_key:"rootEl",ref:p,class:"gvp-audio"},[e.createElementVNode("button",{type:"button",class:"gvp-audio-btn","aria-haspopup":"listbox","aria-expanded":l.value,"aria-label":"Audio track",onClick:y[0]||(y[0]=m=>l.value=!l.value)},[e.createVNode(de),e.createElementVNode("span",me,e.toDisplayString((k=f.value)==null?void 0:k.label),1),e.createVNode(ne)],8,pe),l.value?(e.openBlock(),e.createElementBlock("ul",fe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.tracks,m=>(e.openBlock(),e.createElementBlock("li",{key:m.index},[e.createElementVNode("button",{type:"button",role:"option","aria-selected":m.index===n.activeIndex,class:e.normalizeClass(["gvp-audio-menu-item",{"is-active":m.index===n.activeIndex}]),onClick:s=>B(m.index)},e.toDisplayString(m.label),11,ke)]))),128))])):e.createCommentVNode("",!0)],512)}}}),ge={name:"IconSpeed"},oe=e.defineComponent({...ge,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{d:"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2Z",stroke:"currentColor","stroke-width":"1.5"},null,-1),e.createElementVNode("path",{d:"M12 8V12L14.5 14.5",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])],2))}}),Ce=["aria-expanded"],ye={class:"gvp-speed-label"},Ee={key:0,class:"gvp-speed-menu",role:"listbox","aria-label":"Playback speed"},we=["aria-selected","onClick"],be=e.defineComponent({__name:"SpeedSwitcher",props:{speed:{}},emits:["select"],setup(n,{emit:a}){const r=[.5,.75,1,1.25,1.5,2],t=a,l=e.ref(!1),p=e.ref(null);function f(B){p.value&&!p.value.contains(B.target)&&(l.value=!1)}function d(B){B.key==="Escape"&&(l.value=!1)}e.watch(l,B=>{B?(document.addEventListener("mousedown",f),document.addEventListener("keydown",d)):(document.removeEventListener("mousedown",f),document.removeEventListener("keydown",d))}),e.onBeforeUnmount(()=>{document.removeEventListener("mousedown",f),document.removeEventListener("keydown",d)});function b(B){t("select",B),l.value=!1}return(B,C)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"rootEl",ref:p,class:"gvp-speed"},[e.createElementVNode("button",{type:"button",class:"gvp-speed-btn","aria-haspopup":"listbox","aria-expanded":l.value,"aria-label":"`Playback speed: ${speed === 1 ? '1×' : speed + '×'}`",onClick:C[0]||(C[0]=y=>l.value=!l.value)},[e.createVNode(oe),e.createElementVNode("span",ye,e.toDisplayString(n.speed===1?"1×":`${n.speed}×`),1),e.createVNode(ne)],8,Ce),l.value?(e.openBlock(),e.createElementBlock("ul",Ee,[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(r,y=>e.createElementVNode("li",{key:y},[e.createElementVNode("button",{type:"button",role:"option","aria-selected":y===n.speed,class:e.normalizeClass(["gvp-speed-menu-item",{"is-active":y===n.speed}]),onClick:k=>b(y)},e.toDisplayString(y===1?"Normal":`${y}×`),11,we)])),64))])):e.createCommentVNode("",!0)],512))}}),Be={name:"IconCaptions"},le=e.defineComponent({...Be,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("rect",{x:"2",y:"5",width:"20",height:"14",rx:"3",stroke:"currentColor","stroke-width":"1.5"},null,-1),e.createElementVNode("path",{d:"M7 12H11M13 12H17M7 15H9M11 15H13M15 15H17",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1)])],2))}}),xe=["aria-expanded","aria-pressed"],_e={key:0,class:"gvp-captions-menu",role:"listbox","aria-label":"Captions"},Ve=["aria-selected"],Ne=["aria-selected","onClick"],$e=e.defineComponent({__name:"CaptionsSwitcher",props:{video:{}},setup(n){const a=n,r=e.ref([]),t=e.ref(-1),l=e.ref(!1),p=e.ref(null);function f(k){const m=[];for(let g=0;g<k.length;g++){const E=k[g];(E.kind==="subtitles"||E.kind==="captions")&&m.push({index:g,label:E.label||E.language||`Track ${g+1}`})}r.value=m;let s=-1;for(let g=0;g<k.length;g++)if(k[g].mode==="showing"){s=g;break}t.value=s}let d=null;e.watch(()=>a.video,k=>{if(d==null||d(),d=null,!k){r.value=[],t.value=-1;return}const m=k.textTracks;f(m);const s=()=>f(m);typeof m.addEventListener=="function"&&(m.addEventListener("addtrack",s),m.addEventListener("removetrack",s),m.addEventListener("change",s),d=()=>{m.removeEventListener("addtrack",s),m.removeEventListener("removetrack",s),m.removeEventListener("change",s)})},{immediate:!0}),e.onBeforeUnmount(()=>{d==null||d(),document.removeEventListener("mousedown",b),document.removeEventListener("keydown",B)});function b(k){p.value&&!p.value.contains(k.target)&&(l.value=!1)}function B(k){k.key==="Escape"&&(l.value=!1)}e.watch(l,k=>{k?(document.addEventListener("mousedown",b),document.addEventListener("keydown",B)):(document.removeEventListener("mousedown",b),document.removeEventListener("keydown",B))});function C(){if(!a.video)return;const k=a.video.textTracks;for(let m=0;m<k.length;m++)k[m].mode="hidden";t.value=-1,l.value=!1}function y(k){if(!a.video)return;const m=a.video.textTracks;for(let s=0;s<m.length;s++)m[s].mode=s===k?"showing":"hidden";t.value=k,l.value=!1}return(k,m)=>r.value.length>0?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"rootEl",ref:p,class:"gvp-captions"},[e.createElementVNode("button",{type:"button",class:e.normalizeClass(["gvp-captions-btn",{"is-active":t.value>=0}]),"aria-haspopup":"listbox","aria-expanded":l.value,"aria-pressed":t.value>=0,"aria-label":"Captions",onClick:m[0]||(m[0]=s=>l.value=!l.value)},[e.createVNode(le)],10,xe),l.value?(e.openBlock(),e.createElementBlock("ul",_e,[e.createElementVNode("li",null,[e.createElementVNode("button",{type:"button",role:"option","aria-selected":t.value===-1,class:e.normalizeClass(["gvp-captions-menu-item",{"is-active":t.value===-1}]),onClick:C}," Off ",10,Ve)]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(r.value,s=>(e.openBlock(),e.createElementBlock("li",{key:s.index},[e.createElementVNode("button",{type:"button",role:"option","aria-selected":s.index===t.value,class:e.normalizeClass(["gvp-captions-menu-item",{"is-active":s.index===t.value}]),onClick:g=>y(s.index)},e.toDisplayString(s.label),11,Ne)]))),128))])):e.createCommentVNode("",!0)],512)):e.createCommentVNode("",!0)}}),Le={name:"IconPause"},Pe=e.defineComponent({...Le,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("rect",{x:"6",y:"5",width:"4",height:"14",rx:"1",fill:"currentColor"},null,-1),e.createElementVNode("rect",{x:"14",y:"5",width:"4",height:"14",rx:"1",fill:"currentColor"},null,-1)])],2))}}),Me={name:"IconPlaySolid"},Se=e.defineComponent({...Me,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{d:"M7 5.5V18.5C7 19.2659 7.84856 19.7261 8.4899 19.3071L19.0801 12.4014C19.6644 12.0204 19.6644 11.9796 19.0801 11.5986L8.4899 4.69288C7.84856 4.27388 7 4.73408 7 5.5Z",fill:"currentColor"},null,-1)])],2))}}),Te={name:"IconVolumeHigh"},Ie=e.defineComponent({...Te,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{d:"M3 14V10C3 9.44772 3.44772 9 4 9H6.58579C6.851 9 7.10536 8.89464 7.29289 8.70711L11.2929 4.70711C11.9229 4.07714 13 4.52331 13 5.41421V18.5858C13 19.4767 11.9229 19.9229 11.2929 19.2929L7.29289 15.2929C7.10536 15.1054 6.851 15 6.58579 15H4C3.44772 15 3 14.5523 3 14Z",stroke:"currentColor","stroke-width":"1.5","stroke-linejoin":"round"},null,-1),e.createElementVNode("path",{d:"M16.5 8C17.5 9 18 10.5 18 12C18 13.5 17.5 15 16.5 16M19 5.5C20.5 7 21.5 9.5 21.5 12C21.5 14.5 20.5 17 19 18.5",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1)])],2))}}),He={name:"IconVolumeLow"},ze=e.defineComponent({...He,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{d:"M3 14V10C3 9.44772 3.44772 9 4 9H6.58579C6.851 9 7.10536 8.89464 7.29289 8.70711L11.2929 4.70711C11.9229 4.07714 13 4.52331 13 5.41421V18.5858C13 19.4767 11.9229 19.9229 11.2929 19.2929L7.29289 15.2929C7.10536 15.1054 6.851 15 6.58579 15H4C3.44772 15 3 14.5523 3 14Z",stroke:"currentColor","stroke-width":"1.5","stroke-linejoin":"round"},null,-1),e.createElementVNode("path",{d:"M16.5 8C17.5 9 18 10.5 18 12C18 13.5 17.5 15 16.5 16",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1)])],2))}}),De={name:"IconVolumeMuted"},Ae=e.defineComponent({...De,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{d:"M3 14V10C3 9.44772 3.44772 9 4 9H6.58579C6.851 9 7.10536 8.89464 7.29289 8.70711L11.2929 4.70711C11.9229 4.07714 13 4.52331 13 5.41421V18.5858C13 19.4767 11.9229 19.9229 11.2929 19.2929L7.29289 15.2929C7.10536 15.1054 6.851 15 6.58579 15H4C3.44772 15 3 14.5523 3 14Z",stroke:"currentColor","stroke-width":"1.5","stroke-linejoin":"round"},null,-1),e.createElementVNode("path",{d:"M16 9L22 15M22 9L16 15",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1)])],2))}}),Fe={name:"IconPiP"},ae=e.defineComponent({...Fe,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("rect",{x:"2",y:"4",width:"20",height:"16",rx:"2",stroke:"currentColor","stroke-width":"1.5"},null,-1),e.createElementVNode("rect",{x:"12",y:"12",width:"8",height:"5",rx:"1",fill:"currentColor"},null,-1)])],2))}}),Re={name:"IconFullscreen"},Ue=e.defineComponent({...Re,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{d:"M4 9V4H9M15 4H20V9M20 15V20H15M9 20H4V15",stroke:"currentColor","stroke-width":"1.75","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])],2))}}),Oe={name:"IconFullscreenExit"},je=e.defineComponent({...Oe,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{d:"M9 4V9H4M15 9V4H20M15 20V15H20M9 15H4V20",stroke:"currentColor","stroke-width":"1.75","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)])],2))}});function ee(n){if(!Number.isFinite(n)||n<0)return"--:--";const a=Math.floor(n),r=Math.floor(a/3600),t=Math.floor(a%3600/60),p=(a%60).toString().padStart(2,"0");if(r>0){const f=t.toString().padStart(2,"0");return`${r}:${f}:${p}`}return`${t}:${p}`}const Ze={class:"gvp-controls-row"},qe=["aria-label","aria-pressed"],We={class:"gvp-seek"},Ye={class:"gvp-seek-track"},Ke=["value","disabled","aria-valuemax","aria-valuenow"],Je={class:"gvp-time","aria-live":"off"},Xe=["aria-expanded","aria-label"],Ge={class:"gvp-speed-label"},Qe={key:0,class:"gvp-speed-menu",role:"listbox","aria-label":"Playback speed"},et=["aria-selected","onClick"],tt=["aria-expanded","aria-pressed"],nt={key:0,class:"gvp-captions-menu",role:"listbox","aria-label":"Captions"},ot=["aria-selected"],lt=["aria-selected","onClick"],at=["aria-label","aria-pressed"],rt={key:0,class:"gvp-volume-slider-wrap"},st={class:"gvp-volume-track"},it=["value","aria-valuenow"],ct=["aria-label","aria-pressed"],ut=["aria-label","aria-pressed"],dt=3e3,vt=e.defineComponent({__name:"ControlBar",props:{video:{},isPlaying:{type:Boolean},container:{},onTogglePlay:{type:Function}},setup(n){const a=(()=>{if(typeof navigator>"u")return!1;const o=navigator.userAgent;return/iPad|iPhone|iPod/.test(o)||o.includes("Mac")&&navigator.maxTouchPoints>1})(),r=typeof navigator>"u"?!1:/iPhone|iPod/.test(navigator.userAgent),t=[.5,.75,1,1.25,1.5,2],l=n,p=e.ref(!0);let f=null;function d(){f!==null&&(clearTimeout(f),f=null)}function b(){d(),l.isPlaying&&(f=setTimeout(()=>{p.value=!1},dt))}function B(){p.value=!0,b()}e.watch(()=>l.isPlaying,o=>{o?b():(d(),p.value=!0)},{immediate:!0}),e.watch(()=>l.container,o=>{if(!o)return;const i=()=>B();o.addEventListener("mousemove",i),o.addEventListener("touchstart",i),o.addEventListener("focusin",i)},{immediate:!0});const C=e.ref(0),y=e.ref(0),k=e.ref(0);e.watch(()=>l.video,o=>{if(!o)return;const i=()=>{C.value=o.currentTime},v=()=>{y.value=Number.isFinite(o.duration)?o.duration:0},w=()=>{const $=o.buffered;if(!$||$.length===0){k.value=0;return}let G=$.end($.length-1);for(let O=0;O<$.length;O++)if($.start(O)<=o.currentTime&&o.currentTime<=$.end(O)){G=$.end(O);break}k.value=G};i(),v(),w(),o.addEventListener("timeupdate",i),o.addEventListener("durationchange",v),o.addEventListener("loadedmetadata",v),o.addEventListener("progress",w),o.addEventListener("timeupdate",w)},{immediate:!0});const m=()=>y.value>0,s=()=>m()?C.value/y.value*100:0,g=()=>m()?k.value/y.value*100:0;function E(o){const i=l.video;if(!i||!m())return;const v=Number(o.target.value)/100*y.value;i.currentTime=v,C.value=v}const M=e.ref(1),V=e.ref(!1);e.watch(()=>l.video,o=>{if(!o)return;const i=()=>{M.value=o.volume,V.value=o.muted};i(),o.addEventListener("volumechange",i)},{immediate:!0});function L(){l.video&&(l.video.muted=!l.video.muted)}function h(o){const i=l.video;if(!i)return;const v=Number(o.target.value)/100;i.volume=v,v>0&&i.muted&&(i.muted=!1)}const x=e.ref(1),P=e.ref(!1),N=e.ref(null);e.watch(()=>l.video,o=>{if(!o)return;const i=()=>{x.value=o.playbackRate};i(),o.addEventListener("ratechange",i)},{immediate:!0});function S(o){l.video&&(l.video.playbackRate=o),x.value=o,P.value=!1}const A=e.ref([]),_=e.ref(-1),I=e.ref(!1),U=e.ref(null);function j(o){const i=[];for(let w=0;w<o.length;w++){const $=o[w];($.kind==="subtitles"||$.kind==="captions")&&i.push({index:w,label:$.label||$.language||`Track ${w+1}`})}A.value=i;let v=-1;for(let w=0;w<o.length;w++)if(o[w].mode==="showing"){v=w;break}_.value=v}e.watch(()=>l.video,o=>{if(!o){A.value=[],_.value=-1;return}const i=o.textTracks;j(i);const v=()=>j(i);typeof i.addEventListener=="function"&&(i.addEventListener("addtrack",v),i.addEventListener("removetrack",v),i.addEventListener("change",v))},{immediate:!0});function K(o){var v;const i=(v=l.video)==null?void 0:v.textTracks;if(i){for(let w=0;w<i.length;w++)i[w].mode=w===o?"showing":"hidden";_.value=o,I.value=!1}}function F(){var i;const o=(i=l.video)==null?void 0:i.textTracks;if(o){for(let v=0;v<o.length;v++)o[v].mode="hidden";_.value=-1,I.value=!1}}const z=e.ref(!1),J=typeof document<"u"&&!!document.pictureInPictureEnabled;e.watch(()=>l.video,o=>{o&&(o.addEventListener("enterpictureinpicture",()=>{z.value=!0}),o.addEventListener("leavepictureinpicture",()=>{z.value=!1}))},{immediate:!0});function X(){l.video&&(document.pictureInPictureElement?document.exitPictureInPicture().catch(()=>{}):l.video.requestPictureInPicture().catch(()=>{}))}const H=e.ref(!1),Z=typeof document>"u"?!1:!!(document.fullscreenEnabled||document.webkitFullscreenEnabled);function u(){return document.fullscreenElement??document.webkitFullscreenElement??null}function c(o){const i=o.requestFullscreen??o.webkitRequestFullscreen;return i?i.call(o):Promise.reject(new Error("unsupported"))}function T(){const o=document.exitFullscreen??document.webkitExitFullscreen;return o?o.call(document):Promise.reject(new Error("unsupported"))}function D(){H.value=u()===l.container}e.onMounted(()=>{document.addEventListener("fullscreenchange",D),document.addEventListener("webkitfullscreenchange",D)}),e.onBeforeUnmount(()=>{d(),document.removeEventListener("fullscreenchange",D),document.removeEventListener("webkitfullscreenchange",D)});function q(){var o,i;if(r){(i=(o=l.video)==null?void 0:o.webkitEnterFullscreen)==null||i.call(o);return}H.value?T().catch(()=>{}):l.container&&c(l.container).catch(()=>{})}const W=Z||r&&l.video!==null&&typeof l.video.webkitEnterFullscreen=="function";function Y(o,i){function v($){i.value&&!i.value.contains($.target)&&(o.value=!1)}function w($){$.key==="Escape"&&(o.value=!1)}e.watch(o,$=>{$?(document.addEventListener("mousedown",v),document.addEventListener("keydown",w)):(document.removeEventListener("mousedown",v),document.removeEventListener("keydown",w))}),e.onBeforeUnmount(()=>{document.removeEventListener("mousedown",v),document.removeEventListener("keydown",w)})}return Y(P,N),Y(I,U),(o,i)=>(e.openBlock(),e.createElementBlock("div",{role:"toolbar","aria-label":"Video controls",class:e.normalizeClass(["gvp-controls",!p.value&&"is-hidden"]),onMouseenter:d,onMouseleave:b},[e.createElementVNode("div",Ze,[e.createElementVNode("button",{type:"button",class:"gvp-ctrl-btn","aria-label":n.isPlaying?"Pause":"Play","aria-pressed":n.isPlaying,onClick:i[0]||(i[0]=(...v)=>n.onTogglePlay&&n.onTogglePlay(...v))},[n.isPlaying?(e.openBlock(),e.createBlock(Pe,{key:0})):(e.openBlock(),e.createBlock(Se,{key:1}))],8,qe),e.createElementVNode("div",We,[e.createElementVNode("div",Ye,[e.createElementVNode("div",{class:"gvp-seek-buffered",style:e.normalizeStyle({width:`${g()}%`})},null,4),e.createElementVNode("div",{class:"gvp-seek-progress",style:e.normalizeStyle({width:`${s()}%`})},null,4)]),e.createElementVNode("input",{type:"range",class:"gvp-seek-input",min:0,max:100,step:.1,value:s(),disabled:!m(),"aria-label":"Seek","aria-valuemin":0,"aria-valuemax":Math.floor(y.value),"aria-valuenow":Math.floor(C.value),onInput:E},null,40,Ke)]),e.createElementVNode("span",Je,e.toDisplayString(e.unref(ee)(C.value))+" / "+e.toDisplayString(e.unref(ee)(y.value)),1),e.createElementVNode("div",{ref_key:"speedRootEl",ref:N,class:"gvp-speed"},[e.createElementVNode("button",{type:"button",class:"gvp-ctrl-btn gvp-speed-btn","aria-haspopup":"listbox","aria-expanded":P.value,"aria-label":`Playback speed: ${x.value===1?"1×":x.value+"×"}`,onClick:i[1]||(i[1]=v=>P.value=!P.value)},[e.createVNode(oe),e.createElementVNode("span",Ge,e.toDisplayString(x.value===1?"1×":`${x.value}×`),1)],8,Xe),P.value?(e.openBlock(),e.createElementBlock("ul",Qe,[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(t,v=>e.createElementVNode("li",{key:v},[e.createElementVNode("button",{type:"button",role:"option","aria-selected":v===x.value,class:e.normalizeClass(["gvp-speed-menu-item",{"is-active":v===x.value}]),onClick:w=>S(v)},e.toDisplayString(v===1?"Normal":`${v}×`),11,et)])),64))])):e.createCommentVNode("",!0)],512),A.value.length>0?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"captionsRootEl",ref:U,class:"gvp-captions"},[e.createElementVNode("button",{type:"button",class:e.normalizeClass(["gvp-ctrl-btn",_.value>=0&&"is-active"]),"aria-haspopup":"listbox","aria-expanded":I.value,"aria-label":"Captions","aria-pressed":_.value>=0,onClick:i[2]||(i[2]=v=>I.value=!I.value)},[e.createVNode(le)],10,tt),I.value?(e.openBlock(),e.createElementBlock("ul",nt,[e.createElementVNode("li",null,[e.createElementVNode("button",{type:"button",role:"option","aria-selected":_.value===-1,class:e.normalizeClass(["gvp-captions-menu-item",{"is-active":_.value===-1}]),onClick:F},"Off",10,ot)]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(A.value,v=>(e.openBlock(),e.createElementBlock("li",{key:v.index},[e.createElementVNode("button",{type:"button",role:"option","aria-selected":v.index===_.value,class:e.normalizeClass(["gvp-captions-menu-item",{"is-active":v.index===_.value}]),onClick:w=>K(v.index)},e.toDisplayString(v.label),11,lt)]))),128))])):e.createCommentVNode("",!0)],512)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:e.normalizeClass(["gvp-volume",!e.unref(a)&&"is-expandable"])},[e.createElementVNode("button",{type:"button",class:"gvp-ctrl-btn","aria-label":V.value?"Unmute":"Mute","aria-pressed":V.value,onClick:L},[V.value||M.value===0?(e.openBlock(),e.createBlock(Ae,{key:0})):M.value<.5?(e.openBlock(),e.createBlock(ze,{key:1})):(e.openBlock(),e.createBlock(Ie,{key:2}))],8,at),e.unref(a)?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",rt,[e.createElementVNode("div",st,[e.createElementVNode("div",{class:"gvp-volume-fill",style:e.normalizeStyle({width:`${V.value?0:Math.round(M.value*100)}%`})},null,4)]),e.createElementVNode("input",{type:"range",class:"gvp-volume-input",min:0,max:100,step:1,value:V.value?0:Math.round(M.value*100),"aria-label":"Volume","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":V.value?0:Math.round(M.value*100),onInput:h},null,40,it)]))],2),e.unref(J)?(e.openBlock(),e.createElementBlock("button",{key:1,type:"button",class:e.normalizeClass(["gvp-ctrl-btn",z.value&&"is-active"]),"aria-label":z.value?"Exit picture-in-picture":"Picture-in-picture","aria-pressed":z.value,onClick:X},[e.createVNode(ae)],10,ct)):e.createCommentVNode("",!0),e.unref(W)?(e.openBlock(),e.createElementBlock("button",{key:2,type:"button",class:e.normalizeClass(["gvp-ctrl-btn",H.value&&"is-active"]),"aria-label":H.value?"Exit fullscreen":"Enter fullscreen","aria-pressed":H.value,onClick:q},[H.value?(e.openBlock(),e.createBlock(je,{key:0})):(e.openBlock(),e.createBlock(Ue,{key:1}))],10,ut)):e.createCommentVNode("",!0)])],34))}}),pt={name:"IconDesktop"},mt=e.defineComponent({...pt,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{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",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),e.createElementVNode("path",{d:"M11 15H13",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round","stroke-linejoin":"round"},null,-1),e.createElementVNode("path",{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",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),e.createElementVNode("path",{d:"M7 22H17",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1)])],2))}}),ft={name:"IconMobile"},kt=e.defineComponent({...ft,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{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",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"},null,-1),e.createElementVNode("path",{d:"M11 19H13",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},null,-1),e.createElementVNode("path",{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",stroke:"currentColor","stroke-width":"2","stroke-linejoin":"round"},null,-1)])],2))}}),ht={name:"IconPlay"},gt=e.defineComponent({...ht,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"22",height:"22",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{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",fill:"currentColor"},null,-1)])],2))}}),Ct={name:"IconX"},yt=e.defineComponent({...Ct,props:{class:{}},setup(n){const a=n;return(r,t)=>(e.openBlock(),e.createElementBlock("svg",{class:e.normalizeClass(["gvp-icon",a.class]),width:"14",height:"14",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},[...t[0]||(t[0]=[e.createElementVNode("path",{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",fill:"currentColor"},null,-1)])],2))}});function re(n){if(!n)return null;if(/^[A-Za-z0-9_-]{11}$/.test(n))return n;let a;try{a=new URL(n)}catch{return null}const r=a.hostname.replace(/^www\./,"");if(r==="youtu.be"){const t=a.pathname.slice(1).split("/")[0];return/^[A-Za-z0-9_-]{11}$/.test(t)?t:null}if(r==="youtube.com"||r==="m.youtube.com"||r==="music.youtube.com"||r==="youtube-nocookie.com"){const t=a.searchParams.get("v");if(t&&/^[A-Za-z0-9_-]{11}$/.test(t))return t;const l=/^\/(?:embed|shorts|v|live)\/([A-Za-z0-9_-]{11})/.exec(a.pathname);if(l)return l[1]}return null}function se(n){try{const a=new URL(n),r=a.searchParams.get("t")??a.searchParams.get("start");if(!r)return null;if(/^\d+s?$/.test(r))return Number.parseInt(r,10);const t=/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/.exec(r);if(t){const l=Number.parseInt(t[1]??"0",10),p=Number.parseInt(t[2]??"0",10),f=Number.parseInt(t[3]??"0",10),d=l*3600+p*60+f;return d>0?d:null}}catch{}return null}function ie(n,a={}){const{autoPlay:r=!1,muted:t=!0,loop:l=!1,controls:p=!0,startSeconds:f}=a,d=new URLSearchParams({rel:"0",modestbranding:"1",playsinline:"1",controls:p?"1":"0"});return r?(d.set("autoplay","1"),d.set("mute","1")):t&&d.set("mute","1"),l&&(d.set("loop","1"),d.set("playlist",n)),f&&f>0&&d.set("start",String(f)),`https://www.youtube-nocookie.com/embed/${n}?${d.toString()}`}const Et=["src"],wt={key:2,class:"gvp-vignette"},bt={key:3,class:"gvp-toggle"},Bt={class:"gvp-toggle-pill"},xt=["aria-pressed"],_t=["aria-pressed"],Vt=["aria-label","aria-pressed"],Nt=["aria-label"],$t={key:10,class:"gvp-play-wrap"},Lt={key:0,class:"gvp-tooltip",role:"tooltip"},Pt={key:12,class:"gvp-bottom-fade"},Mt=e.defineComponent({__name:"VideoPlayer",props:{src:{},poster:{},showDeviceToggle:{type:Boolean,default:!0},defaultDevice:{default:"desktop"},hoverPlay:{type:Boolean,default:!1},tooltipText:{},muted:{type:Boolean,default:!0},loop:{type:Boolean,default:!1},controls:{type:[Boolean,String],default:!0},autoPlay:{type:Boolean,default:!1},frameMaxWidth:{},aspectRatio:{},hlsConfig:{},isHls:{type:Boolean},class:{default:""},closable:{type:Boolean,default:!1}},emits:["close","play","pause"],setup(n,{emit:a}){const r=n,t=a,l=e.ref(null),p=e.ref(r.defaultDevice),f=e.ref(!1),d=e.ref(!1),b=e.ref(null),B=e.ref([]),C=e.ref(-1),y=e.ref(1),k=e.ref(!1),m=e.ref(!1),s=e.ref(null),g=typeof document<"u"&&!!document.pictureInPictureEnabled,E=e.computed(()=>r.controls===!0||r.controls==="custom"),M=e.computed(()=>r.controls==="native"),V=e.computed(()=>re(r.src)),L=e.computed(()=>V.value!==null),h=e.computed(()=>V.value?ie(V.value,{autoPlay:r.autoPlay,muted:r.muted,loop:r.loop,controls:E.value?!0:M.value,startSeconds:se(r.src)}):null);function x(u){B.value=u,C.value=-1}const P=e.computed(()=>!L.value&&B.value.length>1),N=e.computed(()=>{var u;return C.value>=0?C.value:((u=B.value[0])==null?void 0:u.index)??-1}),S=e.computed(()=>{var u,c;return p.value==="mobile"?((u=r.aspectRatio)==null?void 0:u.mobile)??"9/16":((c=r.aspectRatio)==null?void 0:c.desktop)??"16/9"}),A=e.computed(()=>{var u,c;return p.value==="mobile"?((u=r.frameMaxWidth)==null?void 0:u.mobile)??"420px":((c=r.frameMaxWidth)==null?void 0:c.desktop)??"960px"}),_=e.computed(()=>{var u;return((u=l.value)==null?void 0:u.videoEl)??null});async function I(){const u=_.value;if(u)try{u.readyState<2&&u.load();const c=u.play();b.value=c,await c,f.value=!0}catch{f.value=!1}finally{b.value=null}}async function U(){const u=_.value;if(u){if(b.value)try{await b.value}catch{}u.pause()}}async function j(){!r.hoverPlay||L.value||await I()}async function K(){!r.hoverPlay||L.value||(await U(),f.value=!1)}async function F(){const u=_.value;u&&(u.paused?await I():(await U(),f.value=!1))}function z(){d.value=!0,j()}function J(){d.value=!1,K()}function X(u){y.value=u;const c=_.value;c&&(c.playbackRate=u)}e.watch(_,u=>{u&&(u.addEventListener("ratechange",()=>{y.value=u.playbackRate}),u.addEventListener("enterpictureinpicture",()=>{k.value=!0}),u.addEventListener("leavepictureinpicture",()=>{k.value=!1}))});function H(){const u=_.value;u&&(document.pictureInPictureElement?document.exitPictureInPicture().catch(()=>{}):u.requestPictureInPicture().catch(()=>{}))}function Z(u){var D,q,W;const c=_.value;if(!(!c||!m.value&&!((D=s.value)!=null&&D.contains(document.activeElement))||u.target.tagName==="INPUT"&&u.key!==" "))switch(u.key){case" ":case"k":u.preventDefault(),F();break;case"ArrowLeft":u.preventDefault(),c.currentTime=Math.max(0,c.currentTime-5);break;case"ArrowRight":u.preventDefault(),c.currentTime=Math.min(c.duration||0,c.currentTime+5);break;case"ArrowUp":u.preventDefault(),c.volume=Math.min(1,c.volume+.1),c.muted&&(c.muted=!1);break;case"ArrowDown":u.preventDefault(),c.volume=Math.max(0,c.volume-.1);break;case"m":c.muted=!c.muted;break;case"f":{const Y=document.fullscreenElement??document.webkitFullscreenElement??null,o=((q=s.value)==null?void 0:q.requestFullscreen)??((W=s.value)==null?void 0:W.webkitRequestFullscreen),i=document.exitFullscreen??document.webkitExitFullscreen;Y===s.value?i==null||i.call(document).catch(()=>{}):o&&s.value&&o.call(s.value).catch(()=>{});break}case"p":g&&H();break}}return e.onMounted(()=>{document.addEventListener("keydown",Z)}),e.onBeforeUnmount(()=>{document.removeEventListener("keydown",Z)}),(u,c)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"rootEl",ref:s,class:e.normalizeClass(["gvp-root",r.class]),style:e.normalizeStyle({width:A.value,aspectRatio:S.value}),onMouseenter:c[8]||(c[8]=T=>{m.value=!0,z()}),onMouseleave:c[9]||(c[9]=T=>{m.value=!1,J()})},[L.value?(e.openBlock(),e.createElementBlock("iframe",{key:0,class:"gvp-video gvp-youtube",src:h.value??void 0,title:"YouTube video player",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",allowfullscreen:"",referrerpolicy:"strict-origin-when-cross-origin"},null,8,Et)):(e.openBlock(),e.createBlock(te,{key:1,ref_key:"hlsPlayerRef",ref:l,controls:M.value,"hls-config":n.hlsConfig,"is-hls":n.isHls,loop:n.loop,muted:n.muted,"auto-play":n.autoPlay,"audio-track-index":C.value,"plays-inline":!0,poster:n.poster,src:n.src,class:"gvp-video",preload:"metadata",onAudioTracks:x,onPause:c[0]||(c[0]=T=>{f.value=!1,t("pause")}),onPlay:c[1]||(c[1]=T=>{f.value=!0,t("play")})},{default:e.withCtx(()=>[e.renderSlot(u.$slots,"default")]),_:3},8,["controls","hls-config","is-hls","loop","muted","auto-play","audio-track-index","poster","src"])),L.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",wt)),n.showDeviceToggle?(e.openBlock(),e.createElementBlock("div",bt,[e.createElementVNode("div",Bt,[e.createElementVNode("button",{"aria-pressed":p.value==="desktop",class:e.normalizeClass(["gvp-toggle-btn",{"is-active":p.value==="desktop"}]),"aria-label":"Desktop view",type:"button",onClick:c[2]||(c[2]=T=>p.value="desktop")},[e.createVNode(mt)],10,xt),c[10]||(c[10]=e.createElementVNode("div",{class:"gvp-toggle-divider"},null,-1)),e.createElementVNode("button",{"aria-pressed":p.value==="mobile",class:e.normalizeClass(["gvp-toggle-btn",{"is-active":p.value==="mobile"}]),"aria-label":"Mobile view",type:"button",onClick:c[3]||(c[3]=T=>p.value="mobile")},[e.createVNode(kt)],10,_t)])])):e.createCommentVNode("",!0),n.closable?(e.openBlock(),e.createElementBlock("button",{key:4,"aria-label":"Close",class:"gvp-close",type:"button",onClick:c[4]||(c[4]=T=>t("close"))},[e.createVNode(yt)])):e.createCommentVNode("",!0),P.value&&!E.value?(e.openBlock(),e.createBlock(he,{key:5,tracks:B.value,"active-index":N.value,onSelect:c[5]||(c[5]=T=>C.value=T)},null,8,["tracks","active-index"])):e.createCommentVNode("",!0),!L.value&&!E.value?(e.openBlock(),e.createBlock(be,{key:6,speed:y.value,onSelect:X},null,8,["speed"])):e.createCommentVNode("",!0),!L.value&&!E.value?(e.openBlock(),e.createBlock($e,{key:7,video:_.value},null,8,["video"])):e.createCommentVNode("",!0),!L.value&&e.unref(g)&&!E.value?(e.openBlock(),e.createElementBlock("button",{key:8,type:"button",class:e.normalizeClass(["gvp-pip-btn",{"is-active":k.value}]),"aria-label":k.value?"Exit picture-in-picture":"Picture-in-picture","aria-pressed":k.value,onClick:H},[e.createVNode(ae)],10,Vt)):e.createCommentVNode("",!0),!L.value&&E.value?(e.openBlock(),e.createElementBlock("button",{key:9,type:"button",class:"gvp-click-layer","aria-label":f.value?"Pause":"Play",onClick:F},null,8,Nt)):e.createCommentVNode("",!0),!L.value&&!E.value&&!f.value?(e.openBlock(),e.createElementBlock("div",$t,[e.createElementVNode("button",{"aria-label":"Play",class:"gvp-play",type:"button",onClick:F,onMouseenter:c[6]||(c[6]=T=>d.value=!0),onMouseleave:c[7]||(c[7]=T=>d.value=!1)},[e.createVNode(gt),n.tooltipText&&d.value?(e.openBlock(),e.createElementBlock("span",Lt,e.toDisplayString(n.tooltipText),1)):e.createCommentVNode("",!0)],32)])):e.createCommentVNode("",!0),!L.value&&E.value?(e.openBlock(),e.createBlock(vt,{key:11,video:_.value,"is-playing":f.value,container:s.value,"on-toggle-play":F},null,8,["video","is-playing","container"])):e.createCommentVNode("",!0),!L.value&&!E.value?(e.openBlock(),e.createElementBlock("div",Pt)):e.createCommentVNode("",!0)],38))}});exports.HLSPlayer=te;exports.VueVideoPlayer=Mt;exports.parseYouTubeId=re;exports.parseYouTubeStart=se;exports.youTubeEmbedUrl=ie;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/HLSPlayer.vue","../src/components/IconDesktop.vue","../src/components/IconMobile.vue","../src/components/IconPlay.vue","../src/components/IconX.vue","../src/utils/youtube.ts","../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 autoPlay?: 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 autoPlay: 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\nlet detachLoadedMetadata: (() => void) | undefined;\n\nfunction cleanup() {\n detachLoadedMetadata?.();\n detachLoadedMetadata = undefined;\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 // Tries to start playback once the stream is ready. Browsers only honor\n // sound-on autoplay after a user gesture, so this is best effort — silently\n // swallows the NotAllowedError when blocked.\n const tryAutoPlay = () => {\n if (!props.autoPlay) return;\n el.play().catch(() => {\n /* autoplay blocked; user gesture required */\n });\n };\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.MANIFEST_PARSED, tryAutoPlay);\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 el.addEventListener(\"loadedmetadata\", tryAutoPlay, { once: true });\n detachLoadedMetadata = () => {\n el.removeEventListener(\"loadedmetadata\", tryAutoPlay);\n };\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 :autoplay=\"autoPlay\"\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","/**\n * Extract a YouTube video ID from any common URL form, or `null` if the URL\n * isn't a YouTube link.\n *\n * Recognised:\n * - https://www.youtube.com/watch?v=ID\n * - https://youtube.com/watch?v=ID&t=42\n * - https://youtu.be/ID\n * - https://youtu.be/ID?t=42\n * - https://www.youtube.com/embed/ID\n * - https://www.youtube.com/shorts/ID\n * - https://music.youtube.com/watch?v=ID\n * - bare 11-character video IDs\n */\nexport function parseYouTubeId(input: string): string | null {\n if (!input) return null;\n\n if (/^[A-Za-z0-9_-]{11}$/.test(input)) return input;\n\n let url: URL;\n try {\n url = new URL(input);\n } catch {\n return null;\n }\n\n const host = url.hostname.replace(/^www\\./, \"\");\n\n if (host === \"youtu.be\") {\n const id = url.pathname.slice(1).split(\"/\")[0];\n return /^[A-Za-z0-9_-]{11}$/.test(id) ? id : null;\n }\n\n if (\n host === \"youtube.com\" ||\n host === \"m.youtube.com\" ||\n host === \"music.youtube.com\" ||\n host === \"youtube-nocookie.com\"\n ) {\n const v = url.searchParams.get(\"v\");\n if (v && /^[A-Za-z0-9_-]{11}$/.test(v)) return v;\n\n const m = /^\\/(?:embed|shorts|v|live)\\/([A-Za-z0-9_-]{11})/.exec(\n url.pathname\n );\n if (m) return m[1];\n }\n\n return null;\n}\n\n/** Extract a `t`/`start` timestamp (in seconds) from a YouTube URL, if present. */\nexport function parseYouTubeStart(input: string): number | null {\n try {\n const url = new URL(input);\n const t = url.searchParams.get(\"t\") ?? url.searchParams.get(\"start\");\n if (!t) return null;\n if (/^\\d+s?$/.test(t)) return Number.parseInt(t, 10);\n const m = /^(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/.exec(t);\n if (m) {\n const h = Number.parseInt(m[1] ?? \"0\", 10);\n const min = Number.parseInt(m[2] ?? \"0\", 10);\n const s = Number.parseInt(m[3] ?? \"0\", 10);\n const total = h * 3600 + min * 60 + s;\n return total > 0 ? total : null;\n }\n } catch {\n /* not a URL */\n }\n return null;\n}\n\nexport interface YouTubeEmbedOptions {\n /** Start playback immediately. Forces `mute` on, since browsers block sound-on autoplay. */\n autoPlay?: boolean;\n /** Mute the player. */\n muted?: boolean;\n /** Loop the video. */\n loop?: boolean;\n /** Show YouTube's player controls. Defaults to `true`. */\n controls?: boolean;\n /** Start offset in seconds. */\n startSeconds?: number | null;\n}\n\n/**\n * Build a privacy-enhanced YouTube embed URL from a video ID and player options.\n *\n * Notes on YouTube's quirks:\n * - `autoplay=1` only takes effect if `mute=1` is also set (browser policy).\n * - single-video loop requires `loop=1` **and** `playlist=<id>`.\n */\nexport function youTubeEmbedUrl(\n id: string,\n opts: YouTubeEmbedOptions = {}\n): string {\n const {\n autoPlay = false,\n muted = true,\n loop = false,\n controls = true,\n startSeconds\n } = opts;\n\n const params = new URLSearchParams({\n rel: \"0\",\n modestbranding: \"1\",\n playsinline: \"1\",\n controls: controls ? \"1\" : \"0\"\n });\n\n if (autoPlay) {\n params.set(\"autoplay\", \"1\");\n params.set(\"mute\", \"1\"); // required for autoplay to actually fire\n } else if (muted) {\n params.set(\"mute\", \"1\");\n }\n\n if (loop) {\n params.set(\"loop\", \"1\");\n params.set(\"playlist\", id); // YouTube needs this for single-video loop\n }\n\n if (startSeconds && startSeconds > 0) {\n params.set(\"start\", String(startSeconds));\n }\n\n return `https://www.youtube-nocookie.com/embed/${id}?${params.toString()}`;\n}\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\";\nimport { parseYouTubeId, parseYouTubeStart, youTubeEmbedUrl } from \"./utils/youtube\";\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 autoPlay: 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 youTubeId = computed(() => parseYouTubeId(props.src));\nconst isYouTube = computed(() => youTubeId.value !== null);\nconst youTubeSrc = computed(() =>\n youTubeId.value\n ? youTubeEmbedUrl(youTubeId.value, {\n autoPlay: props.autoPlay,\n muted: props.muted,\n loop: props.loop,\n controls: props.controls,\n startSeconds: parseYouTubeStart(props.src)\n })\n : null\n);\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 || isYouTube.value) return;\n await safePlay();\n}\n\nasync function hoverStop() {\n if (!props.hoverPlay || isYouTube.value) 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 <iframe\n v-if=\"isYouTube\"\n class=\"gvp-video gvp-youtube\"\n :src=\"youTubeSrc ?? undefined\"\n title=\"YouTube video player\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n allowfullscreen\n referrerpolicy=\"strict-origin-when-cross-origin\"\n />\n <HLSPlayer\n v-else\n ref=\"hlsPlayerRef\"\n :controls=\"controls\"\n :hls-config=\"hlsConfig\"\n :is-hls=\"isHls\"\n :loop=\"loop\"\n :muted=\"muted\"\n :auto-play=\"autoPlay\"\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 v-if=\"!isYouTube\" 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=\"!isYouTube && !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 v-if=\"!isYouTube\" class=\"gvp-bottom-fade\" />\n </div>\n</template>\n"],"names":["props","__props","emit","__emit","videoEl","ref","hlsInstance","canUseHlsJs","Hls","shouldUseHls","src","detachLoadedMetadata","cleanup","el","initPlayer","tryAutoPlay","hls","_evt","data","onMounted","watch","onUnmounted","__expose","_createElementBlock","_normalizeClass","_renderSlot","_ctx","__default__","_createElementVNode","parseYouTubeId","input","url","host","id","v","m","parseYouTubeStart","t","h","min","s","total","youTubeEmbedUrl","opts","autoPlay","muted","loop","controls","startSeconds","params","hlsPlayerRef","device","isPlaying","showTooltip","playPromise","youTubeId","computed","isYouTube","youTubeSrc","aspectRatio","_a","_b","frameMaxWidth","safePlay","p","safePause","hoverStart","hoverStop","togglePlay","onMouseEnter","onMouseLeave","_normalizeStyle","_createBlock","HLSPlayer","_cache","$event","_openBlock","_hoisted_2","_hoisted_3","_hoisted_4","_createVNode","IconDesktop","IconMobile","IconX","_hoisted_7","IconPlay","_hoisted_8","_toDisplayString","_hoisted_9"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/utils/audio-tracks.ts","../src/HLSPlayer.vue","../src/components/IconAudio.vue","../src/components/IconChevron.vue","../src/components/AudioTrackSwitcher.vue","../src/components/IconSpeed.vue","../src/components/SpeedSwitcher.vue","../src/components/IconCaptions.vue","../src/components/CaptionsSwitcher.vue","../src/components/IconPause.vue","../src/components/IconPlaySolid.vue","../src/components/IconVolumeHigh.vue","../src/components/IconVolumeLow.vue","../src/components/IconVolumeMuted.vue","../src/components/IconPiP.vue","../src/components/IconFullscreen.vue","../src/components/IconFullscreenExit.vue","../src/utils/format-time.ts","../src/components/ControlBar.vue","../src/components/IconDesktop.vue","../src/components/IconMobile.vue","../src/components/IconPlay.vue","../src/components/IconX.vue","../src/utils/youtube.ts","../src/VideoPlayer.vue"],"sourcesContent":["/**\n * A normalized audio-track descriptor, independent of whether the source plays\n * through hls.js or the native `<video>` element.\n */\nexport interface AudioTrackInfo {\n /** Stable index into the player's track list. */\n index: number;\n /** Human-readable label, e.g. \"English\", \"Español\", or a fallback. */\n label: string;\n /** BCP-47-ish language code if the source provides one. */\n lang?: string;\n}\n\n/** Build a display label for a track, falling back to language code or \"Audio N\". */\nexport function audioTrackLabel(\n name: string | undefined,\n lang: string | undefined,\n index: number\n): string {\n const trimmed = name?.trim();\n if (trimmed) return trimmed;\n if (lang) {\n try {\n const dn = new Intl.DisplayNames(undefined, { type: \"language\" });\n const resolved = dn.of(lang);\n if (resolved && resolved !== lang) return resolved;\n } catch {\n /* Intl.DisplayNames unavailable or bad code */\n }\n return lang;\n }\n return `Audio ${index + 1}`;\n}\n","<script setup lang=\"ts\">\nimport Hls from \"hls.js\";\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport type { HlsConfig } from \"hls.js\";\nimport { audioTrackLabel, type AudioTrackInfo } from \"./utils/audio-tracks\";\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 autoPlay?: boolean;\n playsInline?: boolean;\n preload?: string;\n poster?: string;\n class?: string;\n /** Index of the audio track to activate; `-1` means \"leave at source default\". */\n audioTrackIndex?: number;\n }>(),\n {\n muted: true,\n loop: false,\n controls: false,\n autoPlay: false,\n playsInline: true,\n preload: \"metadata\",\n audioTrackIndex: -1\n }\n);\n\nconst emit = defineEmits<{\n play: [];\n pause: [];\n \"audio-tracks\": [tracks: AudioTrackInfo[]];\n}>();\n\nconst videoEl = ref<HTMLVideoElement | null>(null);\nconst hlsInstance = ref<Hls | null>(null);\nlet detachNative: (() => void) | undefined;\nlet detachLoadedMetadata: (() => void) | undefined;\n\nconst canUseHlsJs = globalThis.window !== undefined && Hls.isSupported();\nconst shouldUseHls = (src: string) =>\n Boolean(props.isHls) || (canUseHlsJs && src.endsWith(\".m3u8\"));\n\nfunction cleanup() {\n detachLoadedMetadata?.();\n detachLoadedMetadata = undefined;\n detachNative?.();\n detachNative = undefined;\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 emit(\"audio-tracks\", []);\n}\n\nfunction initPlayer(src: string) {\n const el = videoEl.value;\n if (!el || !src) return;\n\n cleanup();\n\n // Tries to start playback once the stream is ready. Browsers only honor\n // sound-on autoplay after a user gesture, so this is best effort — silently\n // swallows the NotAllowedError when blocked.\n const tryAutoPlay = () => {\n if (!props.autoPlay) return;\n el.play().catch(() => {\n /* autoplay blocked; user gesture required */\n });\n };\n\n if (shouldUseHls(src)) {\n const hls = new Hls(props.hlsConfig);\n hlsInstance.value = hls;\n\n const reportHlsTracks = () => {\n const list: AudioTrackInfo[] = hls.audioTracks.map((t, i) => ({\n index: i,\n label: audioTrackLabel(t.name, t.lang, i),\n lang: t.lang || undefined\n }));\n emit(\"audio-tracks\", list);\n };\n\n hls.on(Hls.Events.MANIFEST_PARSED, tryAutoPlay);\n hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, reportHlsTracks);\n hls.on(Hls.Events.AUDIO_TRACK_SWITCHED, reportHlsTracks);\n hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data.fatal) {\n hls.destroy();\n hlsInstance.value = null;\n }\n });\n\n hls.attachMedia(el);\n hls.loadSource(src);\n } else {\n el.src = src;\n el.load();\n\n // For a plain <video>, wait for metadata so play() has something to start.\n el.addEventListener(\"loadedmetadata\", tryAutoPlay, { once: true });\n detachLoadedMetadata = () => {\n el.removeEventListener(\"loadedmetadata\", tryAutoPlay);\n };\n\n // Native AudioTrackList (Safari, some Chromium). Most browsers don't\n // implement this, so the list stays empty and the wrapper renders no\n // switcher — no dead UI.\n const at = el.audioTracks;\n if (at) {\n const reportNativeTracks = () => {\n const list: AudioTrackInfo[] = [];\n for (let i = 0; i < at.length; i++) {\n const t = at[i];\n list.push({\n index: i,\n label: audioTrackLabel(t.label, t.language, i),\n lang: t.language || undefined\n });\n }\n emit(\"audio-tracks\", list);\n };\n at.addEventListener?.(\"addtrack\", reportNativeTracks);\n at.addEventListener?.(\"removetrack\", reportNativeTracks);\n at.addEventListener?.(\"change\", reportNativeTracks);\n if (at.length > 0) reportNativeTracks();\n detachNative = () => {\n at.removeEventListener?.(\"addtrack\", reportNativeTracks);\n at.removeEventListener?.(\"removetrack\", reportNativeTracks);\n at.removeEventListener?.(\"change\", reportNativeTracks);\n };\n }\n }\n}\n\nfunction applyAudioTrack(index: number) {\n if (index == null || index < 0) return;\n const hls = hlsInstance.value;\n if (hls) {\n if (hls.audioTrack !== index) hls.audioTrack = index;\n return;\n }\n const at = videoEl.value?.audioTracks;\n if (at) {\n for (let i = 0; i < at.length; i++) {\n at[i].enabled = i === index;\n }\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\nwatch(\n () => props.audioTrackIndex,\n (index) => applyAudioTrack(index)\n);\n\nonBeforeUnmount(cleanup);\n\ndefineExpose({ videoEl });\n</script>\n\n<template>\n <video\n ref=\"videoEl\"\n :muted=\"muted\"\n :loop=\"loop\"\n :controls=\"controls\"\n :autoplay=\"autoPlay\"\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=\"16\"\n height=\"16\"\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=\"M3 14V10C3 9.44772 3.44772 9 4 9H6.58579C6.851 9 7.10536 8.89464 7.29289 8.70711L11.2929 4.70711C11.9229 4.07714 13 4.52331 13 5.41421V18.5858C13 19.4767 11.9229 19.9229 11.2929 19.2929L7.29289 15.2929C7.10536 15.1054 6.851 15 6.58579 15H4C3.44772 15 3 14.5523 3 14Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M16.5 8C17.5 9 18 10.5 18 12C18 13.5 17.5 15 16.5 16M19 5.5C20.5 7 21.5 9.5 21.5 12C21.5 14.5 20.5 17 19 18.5\"\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: \"IconAudio\" };\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=\"12\"\n height=\"12\"\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=\"M6 9L12 15L18 9\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconChevron\" };\n</script>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\nimport IconAudio from \"./IconAudio.vue\";\nimport IconChevron from \"./IconChevron.vue\";\nimport type { AudioTrackInfo } from \"../utils/audio-tracks\";\n\nconst props = defineProps<{\n tracks: AudioTrackInfo[];\n activeIndex: number;\n}>();\n\nconst emit = defineEmits<{\n select: [index: number];\n}>();\n\nconst open = ref(false);\nconst rootEl = ref<HTMLElement | null>(null);\n\nconst active = computed(\n () => props.tracks.find((t) => t.index === props.activeIndex) ?? props.tracks[0]\n);\n\nfunction onDocClick(e: MouseEvent) {\n if (rootEl.value && !rootEl.value.contains(e.target as Node)) {\n open.value = false;\n }\n}\n\nfunction onEsc(e: KeyboardEvent) {\n if (e.key === \"Escape\") open.value = false;\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n document.addEventListener(\"mousedown\", onDocClick);\n document.addEventListener(\"keydown\", onEsc);\n } else {\n document.removeEventListener(\"mousedown\", onDocClick);\n document.removeEventListener(\"keydown\", onEsc);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener(\"mousedown\", onDocClick);\n document.removeEventListener(\"keydown\", onEsc);\n});\n\nfunction pick(index: number) {\n emit(\"select\", index);\n open.value = false;\n}\n</script>\n\n<template>\n <div ref=\"rootEl\" class=\"gvp-audio\">\n <button\n type=\"button\"\n class=\"gvp-audio-btn\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"open\"\n aria-label=\"Audio track\"\n @click=\"open = !open\"\n >\n <IconAudio />\n <span class=\"gvp-audio-label\">{{ active?.label }}</span>\n <IconChevron />\n </button>\n <!--\n A native <select> can't be styled to sit inside the player overlay\n (it renders the OS dropdown chrome), so this is a custom listbox.\n -->\n <ul\n v-if=\"open\"\n class=\"gvp-audio-menu\"\n role=\"listbox\"\n aria-label=\"Audio tracks\"\n >\n <li v-for=\"t in tracks\" :key=\"t.index\">\n <button\n type=\"button\"\n role=\"option\"\n :aria-selected=\"t.index === activeIndex\"\n :class=\"['gvp-audio-menu-item', { 'is-active': t.index === activeIndex }]\"\n @click=\"pick(t.index)\"\n >\n {{ t.label }}\n </button>\n </li>\n </ul>\n </div>\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=\"16\"\n height=\"16\"\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=\"M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n />\n <path\n d=\"M12 8V12L14.5 14.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconSpeed\" };\n</script>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, watch } from \"vue\";\nimport IconSpeed from \"./IconSpeed.vue\";\nimport IconChevron from \"./IconChevron.vue\";\n\nconst SPEED_OPTIONS = [0.5, 0.75, 1, 1.25, 1.5, 2];\n\nconst props = defineProps<{ speed: number }>();\nconst emit = defineEmits<{ select: [rate: number] }>();\n\nconst open = ref(false);\nconst rootEl = ref<HTMLElement | null>(null);\n\nfunction onDocClick(e: MouseEvent) {\n if (rootEl.value && !rootEl.value.contains(e.target as Node)) {\n open.value = false;\n }\n}\n\nfunction onEsc(e: KeyboardEvent) {\n if (e.key === \"Escape\") open.value = false;\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n document.addEventListener(\"mousedown\", onDocClick);\n document.addEventListener(\"keydown\", onEsc);\n } else {\n document.removeEventListener(\"mousedown\", onDocClick);\n document.removeEventListener(\"keydown\", onEsc);\n }\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener(\"mousedown\", onDocClick);\n document.removeEventListener(\"keydown\", onEsc);\n});\n\nfunction pick(rate: number) {\n emit(\"select\", rate);\n open.value = false;\n}\n</script>\n\n<template>\n <div ref=\"rootEl\" class=\"gvp-speed\">\n <button\n type=\"button\"\n class=\"gvp-speed-btn\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"open\"\n aria-label=\"`Playback speed: ${speed === 1 ? '1×' : speed + '×'}`\"\n @click=\"open = !open\"\n >\n <IconSpeed />\n <span class=\"gvp-speed-label\">{{ speed === 1 ? \"1×\" : `${speed}×` }}</span>\n <IconChevron />\n </button>\n <!--\n A native <select> can't be styled to sit inside the player overlay\n (it renders the OS dropdown chrome), so this is a custom listbox.\n -->\n <ul\n v-if=\"open\"\n class=\"gvp-speed-menu\"\n role=\"listbox\"\n aria-label=\"Playback speed\"\n >\n <li v-for=\"rate in SPEED_OPTIONS\" :key=\"rate\">\n <button\n type=\"button\"\n role=\"option\"\n :aria-selected=\"rate === speed\"\n :class=\"['gvp-speed-menu-item', { 'is-active': rate === speed }]\"\n @click=\"pick(rate)\"\n >\n {{ rate === 1 ? \"Normal\" : `${rate}×` }}\n </button>\n </li>\n </ul>\n </div>\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=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"3\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M7 12H11M13 12H17M7 15H9M11 15H13M15 15H17\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconCaptions\" };\n</script>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, watch } from \"vue\";\nimport IconCaptions from \"./IconCaptions.vue\";\n\ninterface TextTrackItem {\n index: number;\n label: string;\n}\n\nconst props = defineProps<{\n video: HTMLVideoElement | null;\n}>();\n\nconst tracks = ref<TextTrackItem[]>([]);\nconst activeIndex = ref(-1); // -1 = Off\nconst open = ref(false);\nconst rootEl = ref<HTMLElement | null>(null);\n\n// TextTrackList has indexed access but is not a true iterable in all envs.\nfunction snapshot(tl: TextTrackList) {\n const items: TextTrackItem[] = [];\n for (let i = 0; i < tl.length; i++) {\n const t = tl[i];\n if (t.kind === \"subtitles\" || t.kind === \"captions\") {\n items.push({ index: i, label: t.label || t.language || `Track ${i + 1}` });\n }\n }\n tracks.value = items;\n let active = -1;\n for (let i = 0; i < tl.length; i++) {\n if (tl[i].mode === \"showing\") { active = i; break; }\n }\n activeIndex.value = active;\n}\n\nlet cleanupTracks: (() => void) | null = null;\n\nwatch(() => props.video, (el) => {\n cleanupTracks?.();\n cleanupTracks = null;\n if (!el) { tracks.value = []; activeIndex.value = -1; return; }\n const tl = el.textTracks;\n snapshot(tl);\n const onChange = () => snapshot(tl);\n if (typeof tl.addEventListener === \"function\") {\n tl.addEventListener(\"addtrack\", onChange);\n tl.addEventListener(\"removetrack\", onChange);\n tl.addEventListener(\"change\", onChange);\n cleanupTracks = () => {\n tl.removeEventListener(\"addtrack\", onChange);\n tl.removeEventListener(\"removetrack\", onChange);\n tl.removeEventListener(\"change\", onChange);\n };\n }\n}, { immediate: true });\n\nonBeforeUnmount(() => {\n cleanupTracks?.();\n document.removeEventListener(\"mousedown\", onDocClick);\n document.removeEventListener(\"keydown\", onEsc);\n});\n\nfunction onDocClick(e: MouseEvent) {\n if (rootEl.value && !rootEl.value.contains(e.target as Node)) open.value = false;\n}\n\nfunction onEsc(e: KeyboardEvent) {\n if (e.key === \"Escape\") open.value = false;\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n document.addEventListener(\"mousedown\", onDocClick);\n document.addEventListener(\"keydown\", onEsc);\n } else {\n document.removeEventListener(\"mousedown\", onDocClick);\n document.removeEventListener(\"keydown\", onEsc);\n }\n});\n\nfunction pickOff() {\n if (!props.video) return;\n const tl = props.video.textTracks;\n for (let i = 0; i < tl.length; i++) tl[i].mode = \"hidden\";\n activeIndex.value = -1;\n open.value = false;\n}\n\nfunction pick(index: number) {\n if (!props.video) return;\n const tl = props.video.textTracks;\n for (let i = 0; i < tl.length; i++) {\n tl[i].mode = i === index ? \"showing\" : \"hidden\";\n }\n activeIndex.value = index;\n open.value = false;\n}\n</script>\n\n<template>\n <div v-if=\"tracks.length > 0\" ref=\"rootEl\" class=\"gvp-captions\">\n <button\n type=\"button\"\n :class=\"['gvp-captions-btn', { 'is-active': activeIndex >= 0 }]\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"open\"\n :aria-pressed=\"activeIndex >= 0\"\n aria-label=\"Captions\"\n @click=\"open = !open\"\n >\n <IconCaptions />\n </button>\n <!--\n A native <select> can't be styled to sit inside the player overlay\n (it renders the OS dropdown chrome), so this is a custom listbox.\n -->\n <ul\n v-if=\"open\"\n class=\"gvp-captions-menu\"\n role=\"listbox\"\n aria-label=\"Captions\"\n >\n <li>\n <button\n type=\"button\"\n role=\"option\"\n :aria-selected=\"activeIndex === -1\"\n :class=\"['gvp-captions-menu-item', { 'is-active': activeIndex === -1 }]\"\n @click=\"pickOff\"\n >\n Off\n </button>\n </li>\n <li v-for=\"t in tracks\" :key=\"t.index\">\n <button\n type=\"button\"\n role=\"option\"\n :aria-selected=\"t.index === activeIndex\"\n :class=\"['gvp-captions-menu-item', { 'is-active': t.index === activeIndex }]\"\n @click=\"pick(t.index)\"\n >\n {{ t.label }}\n </button>\n </li>\n </ul>\n </div>\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=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <rect x=\"6\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" fill=\"currentColor\" />\n <rect x=\"14\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" fill=\"currentColor\" />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconPause\" };\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=\"16\"\n height=\"16\"\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=\"M7 5.5V18.5C7 19.2659 7.84856 19.7261 8.4899 19.3071L19.0801 12.4014C19.6644 12.0204 19.6644 11.9796 19.0801 11.5986L8.4899 4.69288C7.84856 4.27388 7 4.73408 7 5.5Z\"\n fill=\"currentColor\"\n />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconPlaySolid\" };\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=\"18\"\n height=\"18\"\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=\"M3 14V10C3 9.44772 3.44772 9 4 9H6.58579C6.851 9 7.10536 8.89464 7.29289 8.70711L11.2929 4.70711C11.9229 4.07714 13 4.52331 13 5.41421V18.5858C13 19.4767 11.9229 19.9229 11.2929 19.2929L7.29289 15.2929C7.10536 15.1054 6.851 15 6.58579 15H4C3.44772 15 3 14.5523 3 14Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M16.5 8C17.5 9 18 10.5 18 12C18 13.5 17.5 15 16.5 16M19 5.5C20.5 7 21.5 9.5 21.5 12C21.5 14.5 20.5 17 19 18.5\"\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: \"IconVolumeHigh\" };\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=\"18\"\n height=\"18\"\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=\"M3 14V10C3 9.44772 3.44772 9 4 9H6.58579C6.851 9 7.10536 8.89464 7.29289 8.70711L11.2929 4.70711C11.9229 4.07714 13 4.52331 13 5.41421V18.5858C13 19.4767 11.9229 19.9229 11.2929 19.2929L7.29289 15.2929C7.10536 15.1054 6.851 15 6.58579 15H4C3.44772 15 3 14.5523 3 14Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M16.5 8C17.5 9 18 10.5 18 12C18 13.5 17.5 15 16.5 16\"\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: \"IconVolumeLow\" };\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=\"18\"\n height=\"18\"\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=\"M3 14V10C3 9.44772 3.44772 9 4 9H6.58579C6.851 9 7.10536 8.89464 7.29289 8.70711L11.2929 4.70711C11.9229 4.07714 13 4.52331 13 5.41421V18.5858C13 19.4767 11.9229 19.9229 11.2929 19.2929L7.29289 15.2929C7.10536 15.1054 6.851 15 6.58579 15H4C3.44772 15 3 14.5523 3 14Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M16 9L22 15M22 9L16 15\"\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: \"IconVolumeMuted\" };\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=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <rect x=\"12\" y=\"12\" width=\"8\" height=\"5\" rx=\"1\" fill=\"currentColor\" />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconPiP\" };\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=\"18\"\n height=\"18\"\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=\"M4 9V4H9M15 4H20V9M20 15V20H15M9 20H4V15\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconFullscreen\" };\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=\"18\"\n height=\"18\"\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=\"M9 4V9H4M15 9V4H20M15 20V15H20M9 15H4V20\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n</template>\n\n<script lang=\"ts\">\nexport default { name: \"IconFullscreenExit\" };\n</script>\n","export function formatTime(seconds: number): string {\n if (!Number.isFinite(seconds) || seconds < 0) return \"--:--\";\n const total = Math.floor(seconds);\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = total % 60;\n const ss = s.toString().padStart(2, \"0\");\n if (h > 0) {\n const mm = m.toString().padStart(2, \"0\");\n return `${h}:${mm}:${ss}`;\n }\n return `${m}:${ss}`;\n}\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport IconPause from \"./IconPause.vue\";\nimport IconPlaySolid from \"./IconPlaySolid.vue\";\nimport IconVolumeHigh from \"./IconVolumeHigh.vue\";\nimport IconVolumeLow from \"./IconVolumeLow.vue\";\nimport IconVolumeMuted from \"./IconVolumeMuted.vue\";\nimport IconSpeed from \"./IconSpeed.vue\";\nimport IconCaptions from \"./IconCaptions.vue\";\nimport IconPiP from \"./IconPiP.vue\";\nimport IconFullscreen from \"./IconFullscreen.vue\";\nimport IconFullscreenExit from \"./IconFullscreenExit.vue\";\nimport { formatTime } from \"../utils/format-time\";\n\n/**\n * On iOS, HTMLVideoElement.volume is read-only (hardware volume only),\n * so the slider has no effect. We detect iOS and show only the mute toggle.\n */\nconst isIOS = (() => {\n if (typeof navigator === \"undefined\") return false;\n const ua = navigator.userAgent;\n return /iPad|iPhone|iPod/.test(ua) || (ua.includes(\"Mac\") && navigator.maxTouchPoints > 1);\n})();\n\nconst isIPhone = (() => {\n if (typeof navigator === \"undefined\") return false;\n return /iPhone|iPod/.test(navigator.userAgent);\n})();\n\nconst AUTO_HIDE_MS = 3000;\nconst SPEED_OPTIONS = [0.5, 0.75, 1, 1.25, 1.5, 2];\n\nconst props = defineProps<{\n video: HTMLVideoElement | null;\n isPlaying: boolean;\n container: HTMLElement | null;\n onTogglePlay: () => void;\n}>();\n\n// ── Visibility / auto-hide ────────────────────────────────────────────────\n\nconst visible = ref(true);\nlet hideTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction clearHideTimer() {\n if (hideTimer !== null) { clearTimeout(hideTimer); hideTimer = null; }\n}\n\nfunction scheduleHide() {\n clearHideTimer();\n if (!props.isPlaying) return;\n hideTimer = setTimeout(() => { visible.value = false; }, AUTO_HIDE_MS);\n}\n\nfunction showAndScheduleHide() {\n visible.value = true;\n scheduleHide();\n}\n\nwatch(() => props.isPlaying, (playing) => {\n if (!playing) { clearHideTimer(); visible.value = true; }\n else scheduleHide();\n}, { immediate: true });\n\nwatch(() => props.container, (el) => {\n if (!el) return;\n const handler = () => showAndScheduleHide();\n el.addEventListener(\"mousemove\", handler);\n el.addEventListener(\"touchstart\", handler);\n el.addEventListener(\"focusin\", handler);\n}, { immediate: true });\n\n// ── Seek bar ──────────────────────────────────────────────────────────────\n\nconst currentTime = ref(0);\nconst duration = ref(0);\nconst buffered = ref(0);\n\nwatch(() => props.video, (el) => {\n if (!el) return;\n const onTime = () => { currentTime.value = el.currentTime; };\n const onDuration = () => { duration.value = Number.isFinite(el.duration) ? el.duration : 0; };\n const onProgress = () => {\n const ranges = el.buffered;\n if (!ranges || ranges.length === 0) { buffered.value = 0; return; }\n let end = ranges.end(ranges.length - 1);\n for (let i = 0; i < ranges.length; i++) {\n if (ranges.start(i) <= el.currentTime && el.currentTime <= ranges.end(i)) {\n end = ranges.end(i); break;\n }\n }\n buffered.value = end;\n };\n onTime(); onDuration(); onProgress();\n el.addEventListener(\"timeupdate\", onTime);\n el.addEventListener(\"durationchange\", onDuration);\n el.addEventListener(\"loadedmetadata\", onDuration);\n el.addEventListener(\"progress\", onProgress);\n el.addEventListener(\"timeupdate\", onProgress);\n}, { immediate: true });\n\nconst seekable = () => duration.value > 0;\nconst progressPct = () => seekable() ? (currentTime.value / duration.value) * 100 : 0;\nconst bufferedPct = () => seekable() ? (buffered.value / duration.value) * 100 : 0;\n\nfunction onSeekInput(e: Event) {\n const el = props.video;\n if (!el || !seekable()) return;\n const t = (Number((e.target as HTMLInputElement).value) / 100) * duration.value;\n el.currentTime = t;\n currentTime.value = t;\n}\n\n// ── Volume ────────────────────────────────────────────────────────────────\n\nconst volume = ref(1);\nconst muted = ref(false);\n\nwatch(() => props.video, (el) => {\n if (!el) return;\n const onChange = () => { volume.value = el.volume; muted.value = el.muted; };\n onChange();\n el.addEventListener(\"volumechange\", onChange);\n}, { immediate: true });\n\nfunction toggleMute() {\n if (props.video) props.video.muted = !props.video.muted;\n}\n\nfunction onVolumeInput(e: Event) {\n const el = props.video;\n if (!el) return;\n const v = Number((e.target as HTMLInputElement).value) / 100;\n el.volume = v;\n if (v > 0 && el.muted) el.muted = false;\n}\n\n// ── Speed ─────────────────────────────────────────────────────────────────\n\nconst speed = ref(1);\nconst speedOpen = ref(false);\nconst speedRootEl = ref<HTMLElement | null>(null);\n\nwatch(() => props.video, (el) => {\n if (!el) return;\n const onRate = () => { speed.value = el.playbackRate; };\n onRate();\n el.addEventListener(\"ratechange\", onRate);\n}, { immediate: true });\n\nfunction pickSpeed(rate: number) {\n if (props.video) props.video.playbackRate = rate;\n speed.value = rate;\n speedOpen.value = false;\n}\n\n// ── Captions ──────────────────────────────────────────────────────────────\n\ninterface TextTrackItem { index: number; label: string; }\n\nconst captionTracks = ref<TextTrackItem[]>([]);\nconst activeCaptionIndex = ref(-1);\nconst captionsOpen = ref(false);\nconst captionsRootEl = ref<HTMLElement | null>(null);\n\nfunction snapshotTracks(tl: TextTrackList) {\n const items: TextTrackItem[] = [];\n for (let i = 0; i < tl.length; i++) {\n const t = tl[i];\n if (t.kind === \"subtitles\" || t.kind === \"captions\") {\n items.push({ index: i, label: t.label || t.language || `Track ${i + 1}` });\n }\n }\n captionTracks.value = items;\n let active = -1;\n for (let i = 0; i < tl.length; i++) {\n if (tl[i].mode === \"showing\") { active = i; break; }\n }\n activeCaptionIndex.value = active;\n}\n\nwatch(() => props.video, (el) => {\n if (!el) { captionTracks.value = []; activeCaptionIndex.value = -1; return; }\n const tl = el.textTracks;\n snapshotTracks(tl);\n const onChange = () => snapshotTracks(tl);\n if (typeof tl.addEventListener === \"function\") {\n tl.addEventListener(\"addtrack\", onChange);\n tl.addEventListener(\"removetrack\", onChange);\n tl.addEventListener(\"change\", onChange);\n }\n}, { immediate: true });\n\nfunction pickCaption(index: number) {\n const tl = props.video?.textTracks;\n if (!tl) return;\n for (let i = 0; i < tl.length; i++) tl[i].mode = i === index ? \"showing\" : \"hidden\";\n activeCaptionIndex.value = index;\n captionsOpen.value = false;\n}\n\nfunction pickCaptionOff() {\n const tl = props.video?.textTracks;\n if (!tl) return;\n for (let i = 0; i < tl.length; i++) tl[i].mode = \"hidden\";\n activeCaptionIndex.value = -1;\n captionsOpen.value = false;\n}\n\n// ── PiP ───────────────────────────────────────────────────────────────────\n\nconst isPiP = ref(false);\nconst pipSupported = typeof document !== \"undefined\" && !!document.pictureInPictureEnabled;\n\nwatch(() => props.video, (el) => {\n if (!el) return;\n el.addEventListener(\"enterpictureinpicture\", () => { isPiP.value = true; });\n el.addEventListener(\"leavepictureinpicture\", () => { isPiP.value = false; });\n}, { immediate: true });\n\nfunction togglePiP() {\n if (!props.video) return;\n if (document.pictureInPictureElement) {\n document.exitPictureInPicture().catch(() => { /* ignore */ });\n } else {\n props.video.requestPictureInPicture().catch(() => { /* ignore */ });\n }\n}\n\n// ── Fullscreen ────────────────────────────────────────────────────────────\n\nconst isFs = ref(false);\n\nconst fullscreenSupported = (() => {\n if (typeof document === \"undefined\") return false;\n return Boolean(document.fullscreenEnabled || (document as Document & { webkitFullscreenEnabled?: boolean }).webkitFullscreenEnabled);\n})();\n\nfunction fsElement() {\n return (document.fullscreenElement ?? (document as Document & { webkitFullscreenElement?: Element | null }).webkitFullscreenElement ?? null);\n}\n\nfunction fsRequest(el: HTMLElement) {\n const r = el.requestFullscreen ?? (el as HTMLElement & { webkitRequestFullscreen?(): Promise<void> }).webkitRequestFullscreen;\n return r ? r.call(el) : Promise.reject(new Error(\"unsupported\"));\n}\n\nfunction fsExit() {\n const e = document.exitFullscreen ?? (document as Document & { webkitExitFullscreen?(): Promise<void> }).webkitExitFullscreen;\n return e ? e.call(document) : Promise.reject(new Error(\"unsupported\"));\n}\n\nfunction onFsChange() { isFs.value = fsElement() === props.container; }\n\nonMounted(() => {\n document.addEventListener(\"fullscreenchange\", onFsChange);\n document.addEventListener(\"webkitfullscreenchange\", onFsChange);\n});\nonBeforeUnmount(() => {\n clearHideTimer();\n document.removeEventListener(\"fullscreenchange\", onFsChange);\n document.removeEventListener(\"webkitfullscreenchange\", onFsChange);\n});\n\nfunction toggleFs() {\n if (isIPhone) {\n (props.video as HTMLVideoElement & { webkitEnterFullscreen?(): void })?.webkitEnterFullscreen?.();\n return;\n }\n if (isFs.value) { fsExit().catch(() => { /* ignore */ }); }\n else if (props.container) { fsRequest(props.container).catch(() => { /* ignore */ }); }\n}\n\nconst fsButtonSupported = fullscreenSupported ||\n (isIPhone && props.video !== null &&\n typeof (props.video as HTMLVideoElement & { webkitEnterFullscreen?(): void }).webkitEnterFullscreen === \"function\");\n\n// ── Click-outside for open menus ──────────────────────────────────────────\n\nfunction useClickOutside(openRef: { value: boolean }, rootRef: { value: HTMLElement | null }) {\n function onDocClick(e: MouseEvent) {\n if (rootRef.value && !rootRef.value.contains(e.target as Node)) openRef.value = false;\n }\n function onEsc(e: KeyboardEvent) { if (e.key === \"Escape\") openRef.value = false; }\n watch(openRef, (isOpen) => {\n if (isOpen) {\n document.addEventListener(\"mousedown\", onDocClick);\n document.addEventListener(\"keydown\", onEsc);\n } else {\n document.removeEventListener(\"mousedown\", onDocClick);\n document.removeEventListener(\"keydown\", onEsc);\n }\n });\n onBeforeUnmount(() => {\n document.removeEventListener(\"mousedown\", onDocClick);\n document.removeEventListener(\"keydown\", onEsc);\n });\n}\n\nuseClickOutside(speedOpen, speedRootEl);\nuseClickOutside(captionsOpen, captionsRootEl);\n</script>\n\n<template>\n <div\n role=\"toolbar\"\n aria-label=\"Video controls\"\n :class=\"['gvp-controls', !visible && 'is-hidden']\"\n @mouseenter=\"clearHideTimer\"\n @mouseleave=\"scheduleHide\"\n >\n <div class=\"gvp-controls-row\">\n\n <!-- Play / Pause -->\n <button\n type=\"button\"\n class=\"gvp-ctrl-btn\"\n :aria-label=\"isPlaying ? 'Pause' : 'Play'\"\n :aria-pressed=\"isPlaying\"\n @click=\"onTogglePlay\"\n >\n <IconPause v-if=\"isPlaying\" />\n <IconPlaySolid v-else />\n </button>\n\n <!-- Seek bar -->\n <div class=\"gvp-seek\">\n <div class=\"gvp-seek-track\">\n <div class=\"gvp-seek-buffered\" :style=\"{ width: `${bufferedPct()}%` }\" />\n <div class=\"gvp-seek-progress\" :style=\"{ width: `${progressPct()}%` }\" />\n </div>\n <input\n type=\"range\"\n class=\"gvp-seek-input\"\n :min=\"0\"\n :max=\"100\"\n :step=\"0.1\"\n :value=\"progressPct()\"\n :disabled=\"!seekable()\"\n aria-label=\"Seek\"\n :aria-valuemin=\"0\"\n :aria-valuemax=\"Math.floor(duration)\"\n :aria-valuenow=\"Math.floor(currentTime)\"\n @input=\"onSeekInput\"\n />\n </div>\n\n <!-- Time -->\n <span class=\"gvp-time\" aria-live=\"off\">\n {{ formatTime(currentTime) }} / {{ formatTime(duration) }}\n </span>\n\n <!-- Speed -->\n <div ref=\"speedRootEl\" class=\"gvp-speed\">\n <button\n type=\"button\"\n class=\"gvp-ctrl-btn gvp-speed-btn\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"speedOpen\"\n :aria-label=\"`Playback speed: ${speed === 1 ? '1×' : speed + '×'}`\"\n @click=\"speedOpen = !speedOpen\"\n >\n <IconSpeed />\n <span class=\"gvp-speed-label\">{{ speed === 1 ? \"1×\" : `${speed}×` }}</span>\n </button>\n <!-- NOSONAR: vue:S6819 -->\n <ul v-if=\"speedOpen\" class=\"gvp-speed-menu\" role=\"listbox\" aria-label=\"Playback speed\">\n <li v-for=\"rate in SPEED_OPTIONS\" :key=\"rate\">\n <button\n type=\"button\"\n role=\"option\"\n :aria-selected=\"rate === speed\"\n :class=\"['gvp-speed-menu-item', { 'is-active': rate === speed }]\"\n @click=\"pickSpeed(rate)\"\n >\n {{ rate === 1 ? \"Normal\" : `${rate}×` }}\n </button>\n </li>\n </ul>\n </div>\n\n <!-- Captions -->\n <div v-if=\"captionTracks.length > 0\" ref=\"captionsRootEl\" class=\"gvp-captions\">\n <button\n type=\"button\"\n :class=\"['gvp-ctrl-btn', activeCaptionIndex >= 0 && 'is-active']\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"captionsOpen\"\n aria-label=\"Captions\"\n :aria-pressed=\"activeCaptionIndex >= 0\"\n @click=\"captionsOpen = !captionsOpen\"\n >\n <IconCaptions />\n </button>\n <!-- NOSONAR: vue:S6819 -->\n <ul v-if=\"captionsOpen\" class=\"gvp-captions-menu\" role=\"listbox\" aria-label=\"Captions\">\n <li>\n <button\n type=\"button\"\n role=\"option\"\n :aria-selected=\"activeCaptionIndex === -1\"\n :class=\"['gvp-captions-menu-item', { 'is-active': activeCaptionIndex === -1 }]\"\n @click=\"pickCaptionOff\"\n >Off</button>\n </li>\n <li v-for=\"t in captionTracks\" :key=\"t.index\">\n <button\n type=\"button\"\n role=\"option\"\n :aria-selected=\"t.index === activeCaptionIndex\"\n :class=\"['gvp-captions-menu-item', { 'is-active': t.index === activeCaptionIndex }]\"\n @click=\"pickCaption(t.index)\"\n >{{ t.label }}</button>\n </li>\n </ul>\n </div>\n\n <!-- Volume -->\n <div :class=\"['gvp-volume', !isIOS && 'is-expandable']\">\n <button\n type=\"button\"\n class=\"gvp-ctrl-btn\"\n :aria-label=\"muted ? 'Unmute' : 'Mute'\"\n :aria-pressed=\"muted\"\n @click=\"toggleMute\"\n >\n <IconVolumeMuted v-if=\"muted || volume === 0\" />\n <IconVolumeLow v-else-if=\"volume < 0.5\" />\n <IconVolumeHigh v-else />\n </button>\n <div v-if=\"!isIOS\" class=\"gvp-volume-slider-wrap\">\n <div class=\"gvp-volume-track\">\n <div class=\"gvp-volume-fill\" :style=\"{ width: `${muted ? 0 : Math.round(volume * 100)}%` }\" />\n </div>\n <input\n type=\"range\"\n class=\"gvp-volume-input\"\n :min=\"0\"\n :max=\"100\"\n :step=\"1\"\n :value=\"muted ? 0 : Math.round(volume * 100)\"\n aria-label=\"Volume\"\n :aria-valuemin=\"0\"\n :aria-valuemax=\"100\"\n :aria-valuenow=\"muted ? 0 : Math.round(volume * 100)\"\n @input=\"onVolumeInput\"\n />\n </div>\n </div>\n\n <!-- PiP -->\n <button\n v-if=\"pipSupported\"\n type=\"button\"\n :class=\"['gvp-ctrl-btn', isPiP && 'is-active']\"\n :aria-label=\"isPiP ? 'Exit picture-in-picture' : 'Picture-in-picture'\"\n :aria-pressed=\"isPiP\"\n @click=\"togglePiP\"\n >\n <IconPiP />\n </button>\n\n <!-- Fullscreen -->\n <button\n v-if=\"fsButtonSupported\"\n type=\"button\"\n :class=\"['gvp-ctrl-btn', isFs && 'is-active']\"\n :aria-label=\"isFs ? 'Exit fullscreen' : 'Enter fullscreen'\"\n :aria-pressed=\"isFs\"\n @click=\"toggleFs\"\n >\n <IconFullscreenExit v-if=\"isFs\" />\n <IconFullscreen v-else />\n </button>\n\n </div>\n </div>\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","/**\n * Extract a YouTube video ID from any common URL form, or `null` if the URL\n * isn't a YouTube link.\n *\n * Recognised:\n * - https://www.youtube.com/watch?v=ID\n * - https://youtube.com/watch?v=ID&t=42\n * - https://youtu.be/ID\n * - https://youtu.be/ID?t=42\n * - https://www.youtube.com/embed/ID\n * - https://www.youtube.com/shorts/ID\n * - https://music.youtube.com/watch?v=ID\n * - bare 11-character video IDs\n */\nexport function parseYouTubeId(input: string): string | null {\n if (!input) return null;\n\n if (/^[A-Za-z0-9_-]{11}$/.test(input)) return input;\n\n let url: URL;\n try {\n url = new URL(input);\n } catch {\n return null;\n }\n\n const host = url.hostname.replace(/^www\\./, \"\");\n\n if (host === \"youtu.be\") {\n const id = url.pathname.slice(1).split(\"/\")[0];\n return /^[A-Za-z0-9_-]{11}$/.test(id) ? id : null;\n }\n\n if (\n host === \"youtube.com\" ||\n host === \"m.youtube.com\" ||\n host === \"music.youtube.com\" ||\n host === \"youtube-nocookie.com\"\n ) {\n const v = url.searchParams.get(\"v\");\n if (v && /^[A-Za-z0-9_-]{11}$/.test(v)) return v;\n\n const m = /^\\/(?:embed|shorts|v|live)\\/([A-Za-z0-9_-]{11})/.exec(\n url.pathname\n );\n if (m) return m[1];\n }\n\n return null;\n}\n\n/** Extract a `t`/`start` timestamp (in seconds) from a YouTube URL, if present. */\nexport function parseYouTubeStart(input: string): number | null {\n try {\n const url = new URL(input);\n const t = url.searchParams.get(\"t\") ?? url.searchParams.get(\"start\");\n if (!t) return null;\n if (/^\\d+s?$/.test(t)) return Number.parseInt(t, 10);\n const m = /^(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/.exec(t);\n if (m) {\n const h = Number.parseInt(m[1] ?? \"0\", 10);\n const min = Number.parseInt(m[2] ?? \"0\", 10);\n const s = Number.parseInt(m[3] ?? \"0\", 10);\n const total = h * 3600 + min * 60 + s;\n return total > 0 ? total : null;\n }\n } catch {\n /* not a URL */\n }\n return null;\n}\n\nexport interface YouTubeEmbedOptions {\n /** Start playback immediately. Forces `mute` on, since browsers block sound-on autoplay. */\n autoPlay?: boolean;\n /** Mute the player. */\n muted?: boolean;\n /** Loop the video. */\n loop?: boolean;\n /** Show YouTube's player controls. Defaults to `true`. */\n controls?: boolean;\n /** Start offset in seconds. */\n startSeconds?: number | null;\n}\n\n/**\n * Build a privacy-enhanced YouTube embed URL from a video ID and player options.\n *\n * Notes on YouTube's quirks:\n * - `autoplay=1` only takes effect if `mute=1` is also set (browser policy).\n * - single-video loop requires `loop=1` **and** `playlist=<id>`.\n */\nexport function youTubeEmbedUrl(\n id: string,\n opts: YouTubeEmbedOptions = {}\n): string {\n const {\n autoPlay = false,\n muted = true,\n loop = false,\n controls = true,\n startSeconds\n } = opts;\n\n const params = new URLSearchParams({\n rel: \"0\",\n modestbranding: \"1\",\n playsinline: \"1\",\n controls: controls ? \"1\" : \"0\"\n });\n\n if (autoPlay) {\n params.set(\"autoplay\", \"1\");\n params.set(\"mute\", \"1\"); // required for autoplay to actually fire\n } else if (muted) {\n params.set(\"mute\", \"1\");\n }\n\n if (loop) {\n params.set(\"loop\", \"1\");\n params.set(\"playlist\", id); // YouTube needs this for single-video loop\n }\n\n if (startSeconds && startSeconds > 0) {\n params.set(\"start\", String(startSeconds));\n }\n\n return `https://www.youtube-nocookie.com/embed/${id}?${params.toString()}`;\n}\n","<script lang=\"ts\" setup>\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport HLSPlayer from \"./HLSPlayer.vue\";\nimport AudioTrackSwitcher from \"./components/AudioTrackSwitcher.vue\";\nimport SpeedSwitcher from \"./components/SpeedSwitcher.vue\";\nimport CaptionsSwitcher from \"./components/CaptionsSwitcher.vue\";\nimport ControlBar from \"./components/ControlBar.vue\";\nimport IconDesktop from \"./components/IconDesktop.vue\";\nimport IconMobile from \"./components/IconMobile.vue\";\nimport IconPiP from \"./components/IconPiP.vue\";\nimport IconPlay from \"./components/IconPlay.vue\";\nimport IconX from \"./components/IconX.vue\";\nimport type { DeviceMode, VideoPlayerProps } from \"./utils/types\";\nimport type { AudioTrackInfo } from \"./utils/audio-tracks\";\nimport { parseYouTubeId, parseYouTubeStart, youTubeEmbedUrl } from \"./utils/youtube\";\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: true,\n autoPlay: 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);\nconst audioTracks = ref<AudioTrackInfo[]>([]);\nconst audioTrackIndex = ref(-1);\nconst playbackSpeed = ref(1);\nconst isPiP = ref(false);\nconst isHovered = ref(false);\nconst rootEl = ref<HTMLElement | null>(null);\nconst pipSupported = typeof document !== \"undefined\" && !!document.pictureInPictureEnabled;\n\n// `true` and `\"custom\"` both mean the branded control bar; `\"native\"` means\n// the browser's own controls; `false` means none.\nconst isCustomControls = computed(\n () => props.controls === true || props.controls === \"custom\"\n);\nconst isNativeControls = computed(() => props.controls === \"native\");\n\nconst youTubeId = computed(() => parseYouTubeId(props.src));\nconst isYouTube = computed(() => youTubeId.value !== null);\nconst youTubeSrc = computed(() =>\n youTubeId.value\n ? youTubeEmbedUrl(youTubeId.value, {\n autoPlay: props.autoPlay,\n muted: props.muted,\n loop: props.loop,\n controls: isCustomControls.value ? true : isNativeControls.value,\n startSeconds: parseYouTubeStart(props.src)\n })\n : null\n);\n\nfunction onAudioTracks(tracks: AudioTrackInfo[]) {\n audioTracks.value = tracks;\n audioTrackIndex.value = -1; // reset on new source / level switch\n}\n\nconst showAudioSwitcher = computed(\n () => !isYouTube.value && audioTracks.value.length > 1\n);\nconst activeAudioIndex = computed(() =>\n audioTrackIndex.value >= 0\n ? audioTrackIndex.value\n : (audioTracks.value[0]?.index ?? -1)\n);\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 || isYouTube.value) return;\n await safePlay();\n}\n\nasync function hoverStop() {\n if (!props.hoverPlay || isYouTube.value) 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\nfunction onSelectSpeed(rate: number) {\n playbackSpeed.value = rate;\n const el = videoEl.value;\n if (el) el.playbackRate = rate;\n}\n\n// Keep playbackSpeed + isPiP in sync from video element events.\nwatch(videoEl, (el) => {\n if (!el) return;\n el.addEventListener(\"ratechange\", () => { playbackSpeed.value = el.playbackRate; });\n el.addEventListener(\"enterpictureinpicture\", () => { isPiP.value = true; });\n el.addEventListener(\"leavepictureinpicture\", () => { isPiP.value = false; });\n});\n\nfunction togglePiP() {\n const el = videoEl.value;\n if (!el) return;\n if (document.pictureInPictureElement) {\n document.exitPictureInPicture().catch(() => { /* ignore */ });\n } else {\n el.requestPictureInPicture().catch(() => { /* ignore */ });\n }\n}\n\n// Keyboard shortcuts — active only while the cursor is over the player or\n// focus is inside it, so we don't steal global shortcuts from the page.\nfunction onKeyDown(e: KeyboardEvent) {\n const el = videoEl.value;\n if (!el) return;\n if (!isHovered.value && !rootEl.value?.contains(document.activeElement)) return;\n const tag = (e.target as HTMLElement).tagName;\n if (tag === \"INPUT\" && e.key !== \" \") return;\n\n switch (e.key) {\n case \" \":\n case \"k\":\n e.preventDefault();\n void togglePlay();\n break;\n case \"ArrowLeft\":\n e.preventDefault();\n el.currentTime = Math.max(0, el.currentTime - 5);\n break;\n case \"ArrowRight\":\n e.preventDefault();\n el.currentTime = Math.min(el.duration || 0, el.currentTime + 5);\n break;\n case \"ArrowUp\":\n e.preventDefault();\n el.volume = Math.min(1, el.volume + 0.1);\n if (el.muted) el.muted = false;\n break;\n case \"ArrowDown\":\n e.preventDefault();\n el.volume = Math.max(0, el.volume - 0.1);\n break;\n case \"m\":\n el.muted = !el.muted;\n break;\n case \"f\": {\n const fsEl = document.fullscreenElement ??\n (document as Document & { webkitFullscreenElement?: Element | null }).webkitFullscreenElement ?? null;\n const req = rootEl.value?.requestFullscreen ??\n (rootEl.value as HTMLElement & { webkitRequestFullscreen?(): Promise<void> })?.webkitRequestFullscreen;\n const exit = document.exitFullscreen ??\n (document as Document & { webkitExitFullscreen?(): Promise<void> }).webkitExitFullscreen;\n if (fsEl === rootEl.value) { exit?.call(document).catch(() => { /* ignore */ }); }\n else if (req && rootEl.value) { req.call(rootEl.value).catch(() => { /* ignore */ }); }\n break;\n }\n case \"p\":\n if (pipSupported) togglePiP();\n break;\n }\n}\n\nonMounted(() => { document.addEventListener(\"keydown\", onKeyDown); });\nonBeforeUnmount(() => { document.removeEventListener(\"keydown\", onKeyDown); });\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n :class=\"['gvp-root', props.class]\"\n :style=\"{ width: frameMaxWidth, aspectRatio }\"\n @mouseenter=\"isHovered = true; onMouseEnter()\"\n @mouseleave=\"isHovered = false; onMouseLeave()\"\n >\n <iframe\n v-if=\"isYouTube\"\n class=\"gvp-video gvp-youtube\"\n :src=\"youTubeSrc ?? undefined\"\n title=\"YouTube video player\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n allowfullscreen\n referrerpolicy=\"strict-origin-when-cross-origin\"\n />\n <HLSPlayer\n v-else\n ref=\"hlsPlayerRef\"\n :controls=\"isNativeControls\"\n :hls-config=\"hlsConfig\"\n :is-hls=\"isHls\"\n :loop=\"loop\"\n :muted=\"muted\"\n :auto-play=\"autoPlay\"\n :audio-track-index=\"audioTrackIndex\"\n :plays-inline=\"true\"\n :poster=\"poster\"\n :src=\"src\"\n class=\"gvp-video\"\n preload=\"metadata\"\n @audio-tracks=\"onAudioTracks\"\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 v-if=\"!isYouTube\" 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 <!-- Overlay badges — only shown outside custom-controls mode -->\n <AudioTrackSwitcher\n v-if=\"showAudioSwitcher && !isCustomControls\"\n :tracks=\"audioTracks\"\n :active-index=\"activeAudioIndex\"\n @select=\"audioTrackIndex = $event\"\n />\n\n <SpeedSwitcher\n v-if=\"!isYouTube && !isCustomControls\"\n :speed=\"playbackSpeed\"\n @select=\"onSelectSpeed\"\n />\n\n <CaptionsSwitcher v-if=\"!isYouTube && !isCustomControls\" :video=\"videoEl\" />\n\n <button\n v-if=\"!isYouTube && pipSupported && !isCustomControls\"\n type=\"button\"\n :class=\"['gvp-pip-btn', { 'is-active': isPiP }]\"\n :aria-label=\"isPiP ? 'Exit picture-in-picture' : 'Picture-in-picture'\"\n :aria-pressed=\"isPiP\"\n @click=\"togglePiP\"\n >\n <IconPiP />\n </button>\n\n <!-- Click-to-toggle layer in custom-controls mode -->\n <button\n v-if=\"!isYouTube && isCustomControls\"\n type=\"button\"\n class=\"gvp-click-layer\"\n :aria-label=\"isPlaying ? 'Pause' : 'Play'\"\n @click=\"togglePlay\"\n />\n\n <!-- Centered play button (non-custom, non-playing) -->\n <div v-if=\"!isYouTube && !isCustomControls && !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 <!-- Custom control bar -->\n <ControlBar\n v-if=\"!isYouTube && isCustomControls\"\n :video=\"videoEl\"\n :is-playing=\"isPlaying\"\n :container=\"rootEl\"\n :on-toggle-play=\"togglePlay\"\n />\n\n <div v-if=\"!isYouTube && !isCustomControls\" class=\"gvp-bottom-fade\" />\n </div>\n</template>\n"],"names":["audioTrackLabel","name","lang","index","trimmed","resolved","props","__props","emit","__emit","videoEl","ref","hlsInstance","detachNative","detachLoadedMetadata","canUseHlsJs","Hls","shouldUseHls","src","cleanup","el","initPlayer","tryAutoPlay","hls","reportHlsTracks","list","t","i","_evt","data","at","reportNativeTracks","_a","_b","_c","applyAudioTrack","onMounted","watch","onBeforeUnmount","__expose","_createElementBlock","_normalizeClass","_renderSlot","_ctx","__default__","_createElementVNode","open","rootEl","active","computed","onDocClick","e","onEsc","isOpen","pick","_cache","$event","_createVNode","IconAudio","_hoisted_2","_toDisplayString","IconChevron","_openBlock","_hoisted_3","_Fragment","_renderList","_hoisted_4","SPEED_OPTIONS","rate","IconSpeed","tracks","activeIndex","snapshot","tl","items","cleanupTracks","onChange","pickOff","IconCaptions","formatTime","seconds","total","h","m","ss","mm","AUTO_HIDE_MS","isIOS","ua","isIPhone","visible","hideTimer","clearHideTimer","scheduleHide","showAndScheduleHide","playing","handler","currentTime","duration","buffered","onTime","onDuration","onProgress","ranges","end","seekable","progressPct","bufferedPct","onSeekInput","volume","muted","toggleMute","onVolumeInput","speed","speedOpen","speedRootEl","onRate","pickSpeed","captionTracks","activeCaptionIndex","captionsOpen","captionsRootEl","snapshotTracks","pickCaption","pickCaptionOff","isPiP","pipSupported","togglePiP","isFs","fullscreenSupported","fsElement","fsRequest","r","fsExit","onFsChange","toggleFs","fsButtonSupported","useClickOutside","openRef","rootRef","_hoisted_1","args","_createBlock","IconPause","IconPlaySolid","_hoisted_6","_unref","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_12","_hoisted_13","_hoisted_14","IconVolumeMuted","IconVolumeLow","IconVolumeHigh","_hoisted_16","_hoisted_17","IconPiP","IconFullscreenExit","IconFullscreen","parseYouTubeId","input","url","host","id","v","parseYouTubeStart","min","s","youTubeEmbedUrl","opts","autoPlay","loop","controls","startSeconds","params","hlsPlayerRef","device","isPlaying","showTooltip","playPromise","audioTracks","audioTrackIndex","playbackSpeed","isHovered","isCustomControls","isNativeControls","youTubeId","isYouTube","youTubeSrc","onAudioTracks","showAudioSwitcher","activeAudioIndex","aspectRatio","frameMaxWidth","safePlay","p","safePause","hoverStart","hoverStop","togglePlay","onMouseEnter","onMouseLeave","onSelectSpeed","onKeyDown","fsEl","req","exit","_normalizeStyle","HLSPlayer","IconDesktop","IconMobile","IconX","AudioTrackSwitcher","SpeedSwitcher","CaptionsSwitcher","IconPlay","ControlBar","_hoisted_11"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,5 +2,6 @@
|
|
|
2
2
|
export { default as VueVideoPlayer } from './VideoPlayer.vue';
|
|
3
3
|
export { default as HLSPlayer } from './HLSPlayer.vue';
|
|
4
4
|
export type { VideoPlayerProps, HLSPlayerProps, DeviceMode, AspectRatio } from './utils/types';
|
|
5
|
+
export type { AudioTrackInfo } from './utils/audio-tracks';
|
|
5
6
|
export { parseYouTubeId, parseYouTubeStart, youTubeEmbedUrl } from './utils/youtube';
|
|
6
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EACV,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAC1D,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EACV,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAC1D,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
|