@glitchlab/vue-video-player 1.1.0 → 1.1.1
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 +13 -1
- package/dist/HLSPlayer.vue.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +122 -114
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -100,7 +100,7 @@ Then use the component anywhere — no manual import required:
|
|
|
100
100
|
| `muted` | `boolean` | `true` | Mute the video. Required for autoplay in most browsers. |
|
|
101
101
|
| `loop` | `boolean` | `false` | Loop playback. |
|
|
102
102
|
| `controls` | `boolean` | `false` | Show native browser controls. |
|
|
103
|
-
| `autoPlay` | `boolean` | `false` | Start playback as soon as the source
|
|
103
|
+
| `autoPlay` | `boolean` | `false` | Start playback as soon as the source is ready. Works for HLS (after `MANIFEST_PARSED`), native MP4/WebM (after `loadedmetadata`), and YouTube embeds. Browsers block sound-on autoplay, so this only fires when `muted` is also `true` (the default). |
|
|
104
104
|
| `frameMaxWidth` | `{ desktop?: string; mobile?: string }` | `{ desktop: "960px", mobile: "420px" }` | Max width of the player in each device mode. |
|
|
105
105
|
| `aspectRatio` | `{ desktop?: AspectRatio; mobile?: AspectRatio }` | `{ desktop: "16/9", mobile: "9/16" }` | Aspect ratio per device mode. `AspectRatio` is `` `${number}/${number}` ``. |
|
|
106
106
|
| `hlsConfig` | `Hls.HlsConfig` | — | Optional hls.js config. Use a stable reference (e.g. `shallowRef`) to avoid HLS rebuilds.|
|
|
@@ -164,10 +164,22 @@ Recognised forms: `youtube.com/watch?v=ID`, `youtu.be/ID`, `youtube.com/embed/ID
|
|
|
164
164
|
src="/videos/hero.m3u8"
|
|
165
165
|
:muted="true"
|
|
166
166
|
:loop="true"
|
|
167
|
+
:auto-play="true"
|
|
167
168
|
:show-device-toggle="false"
|
|
168
169
|
/>
|
|
169
170
|
```
|
|
170
171
|
|
|
172
|
+
### Autoplay an HLS stream
|
|
173
|
+
|
|
174
|
+
```vue
|
|
175
|
+
<VueVideoPlayer
|
|
176
|
+
src="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
|
|
177
|
+
:auto-play="true"
|
|
178
|
+
/>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
> `autoPlay` waits for the manifest to parse (HLS) or for `loadedmetadata` (native), then calls `.play()` for you. Browsers reject sound-on autoplay without a prior user gesture — `muted` (the default) is the reliable path.
|
|
182
|
+
|
|
171
183
|
### Hover-to-play with a tooltip
|
|
172
184
|
|
|
173
185
|
```vue
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HLSPlayer.vue.d.ts","sourceRoot":"","sources":["../src/HLSPlayer.vue"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"HLSPlayer.vue.d.ts","sourceRoot":"","sources":["../src/HLSPlayer.vue"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AA0HxC,iBAAS,cAAc;qBAoDO,GAAG;EAGhC;AAuBD,QAAA,MAAM,eAAe;SAOZ,MAAM;gBACC,SAAS;YACb,OAAO;YACP,OAAO;WACR,OAAO;eACH,OAAO;eACP,OAAO;kBACJ,OAAO;cACX,MAAM;aACP,MAAM;YACP,MAAM;;;;;;;;;;;;;;SAVT,MAAM;gBACC,SAAS;YACb,OAAO;YACP,OAAO;WACR,OAAO;eACH,OAAO;eACP,OAAO;kBACJ,OAAO;cACX,MAAM;aACP,MAAM;YACP,MAAM;;;;;;;;;;;;WAPN,OAAO;UACR,OAAO;cACH,OAAO;cACP,OAAO;iBACJ,OAAO;aACX,MAAM;4EAKlB,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAAvG,wBAAwG;AACxG,KAAK,sBAAsB,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC;AACjE,KAAK,6BAA6B,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,OAAO,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE;CAAE,CAAC;AAC9M,KAAK,kBAAkB,CAAC,CAAC,EAAE,CAAC,IAAI;KAE1B,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;QACxE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;KACb,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACT,CAAC;AACN,KAAK,cAAc,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG,EAAE,CAAC;AACxD,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAAE,QAAO;QAClD,MAAM,EAAE,CAAC,CAAC;KACT,CAAA;CAAE,CAAC"}
|
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,d=l,c=e.ref(null),u=e.ref(null),i=globalThis.window!==void 0&&g.isSupported(),f=r=>!!o.isHls||i&&r.endsWith(".m3u8");function y(){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 m(r){const p=c.value;if(!(!p||!r))if(y(),f(r)){const v=new g(o.hlsConfig);u.value=v,v.attachMedia(p),v.loadSource(r),v.on(g.Events.ERROR,(h,k)=>{k.fatal&&(v.destroy(),u.value=null)})}else p.src=r,p.load()}return e.onMounted(()=>{o.src&&m(o.src)}),e.watch(()=>o.src,r=>{r&&m(r)}),e.onUnmounted(y),n({videoEl:c}),(r,p)=>(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:p[0]||(p[0]=v=>d("play")),onPause:p[1]||(p[1]=v=>d("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))}}),H={name:"IconMobile"},I=e.defineComponent({...H,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))}}),z={name:"IconPlay"},R=e.defineComponent({...z,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))}}),U={name:"IconX"},Z=e.defineComponent({...U,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 B(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 d=/^\/(?:embed|shorts|v|live)\/([A-Za-z0-9_-]{11})/.exec(n.pathname);if(d)return d[1]}return null}function E(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 d=Number.parseInt(o[1]??"0",10),c=Number.parseInt(o[2]??"0",10),u=Number.parseInt(o[3]??"0",10),i=d*3600+c*60+u;return i>0?i:null}}catch{}return null}function P(t,n={}){const{autoPlay:l=!1,muted:o=!0,loop:d=!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"),d&&(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 D=["src"],Y={key:2,class:"gvp-vignette"},A={key:3,class:"gvp-toggle"},W={class:"gvp-toggle-pill"},j=["aria-pressed"],_=["aria-pressed"],q={key:5,class:"gvp-play-wrap"},O={key:0,class:"gvp-tooltip",role:"tooltip"},J={key:6,class:"gvp-bottom-fade"},X=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,d=e.ref(null),c=e.ref(l.defaultDevice),u=e.ref(!1),i=e.ref(!1),f=e.ref(null),y=e.computed(()=>B(l.src)),m=e.computed(()=>y.value!==null),r=e.computed(()=>y.value?P(y.value,{autoPlay:l.autoPlay,muted:l.muted,loop:l.loop,controls:l.controls,startSeconds:E(l.src)}):null),p=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"}),v=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"}),h=e.computed(()=>{var s;return((s=d.value)==null?void 0:s.videoEl)??null});async function k(){const s=h.value;if(s)try{s.readyState<2&&s.load();const a=s.play();f.value=a,await a,u.value=!0}catch{u.value=!1}finally{f.value=null}}async function w(){const s=h.value;if(s){if(f.value)try{await f.value}catch{}s.pause()}}async function V(){!l.hoverPlay||m.value||await k()}async function N(){!l.hoverPlay||m.value||(await w(),u.value=!1)}async function $(){const s=h.value;s&&(s.paused?await k():(await w(),u.value=!1))}function x(){i.value=!0,V()}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:v.value,aspectRatio:p.value}),onMouseenter:x,onMouseleave:M},[m.value?(e.openBlock(),e.createElementBlock("iframe",{key:0,class:"gvp-video gvp-youtube",src:r.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,D)):(e.openBlock(),e.createBlock(b,{key:1,ref_key:"hlsPlayerRef",ref:d,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]=C=>{u.value=!1,o("pause")}),onPlay:a[1]||(a[1]=C=>{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"])),m.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",Y)),t.showDeviceToggle?(e.openBlock(),e.createElementBlock("div",A,[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]=C=>c.value="desktop")},[e.createVNode(T)],10,j),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]=C=>c.value="mobile")},[e.createVNode(I)],10,_)])])):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]=C=>o("close"))},[e.createVNode(Z)])):e.createCommentVNode("",!0),!m.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]=C=>i.value=!0),onMouseleave:a[6]||(a[6]=C=>i.value=!1)},[e.createVNode(R),t.tooltipText&&i.value?(e.openBlock(),e.createElementBlock("span",O,e.toDisplayString(t.tooltipText),1)):e.createCommentVNode("",!0)],32)])):e.createCommentVNode("",!0),m.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",J))],38))}});exports.HLSPlayer=b;exports.VueVideoPlayer=X;exports.parseYouTubeId=B;exports.parseYouTubeStart=E;exports.youTubeEmbedUrl=P;
|
|
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;
|
|
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\nfunction cleanup() {\n if (hlsInstance.value) {\n hlsInstance.value.destroy();\n hlsInstance.value = null;\n }\n const el = videoEl.value;\n if (!el) return;\n el.pause();\n el.removeAttribute(\"src\");\n while (el.firstChild) el.firstChild.remove();\n el.load();\n}\n\nfunction initPlayer(src: string) {\n const el = videoEl.value;\n if (!el || !src) return;\n\n cleanup();\n\n if (shouldUseHls(src)) {\n const hls = new Hls(props.hlsConfig);\n hlsInstance.value = hls;\n hls.attachMedia(el);\n hls.loadSource(src);\n hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data.fatal) {\n hls.destroy();\n hlsInstance.value = null;\n }\n });\n } else {\n el.src = src;\n el.load();\n }\n}\n\nonMounted(() => {\n if (props.src) initPlayer(props.src);\n});\n\nwatch(\n () => props.src,\n (src) => {\n if (src) initPlayer(src);\n }\n);\n\nonUnmounted(cleanup);\n\ndefineExpose({ videoEl });\n</script>\n\n<template>\n <video\n ref=\"videoEl\"\n :muted=\"muted\"\n :loop=\"loop\"\n :controls=\"controls\"\n :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","cleanup","el","initPlayer","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/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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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defineComponent as
|
|
1
|
+
import { defineComponent as x, ref as w, onMounted as A, watch as D, onUnmounted as N, openBlock as d, createElementBlock as v, normalizeClass as C, renderSlot as T, createElementVNode as p, computed as P, normalizeStyle as Z, createBlock as U, withCtx as z, createCommentVNode as $, createVNode as B, toDisplayString as W } from "vue";
|
|
2
2
|
import L from "hls.js";
|
|
3
|
-
const
|
|
3
|
+
const _ = ["muted", "loop", "controls", "autoplay", "playsinline", "preload", "poster"], Y = /* @__PURE__ */ x({
|
|
4
4
|
__name: "HLSPlayer",
|
|
5
5
|
props: {
|
|
6
6
|
src: {},
|
|
@@ -17,34 +17,42 @@ const Y = ["muted", "loop", "controls", "autoplay", "playsinline", "preload", "p
|
|
|
17
17
|
},
|
|
18
18
|
emits: ["play", "pause"],
|
|
19
19
|
setup(e, { expose: s, emit: o }) {
|
|
20
|
-
const t = e,
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const t = e, f = o, i = w(null), r = w(null), u = globalThis.window !== void 0 && L.isSupported(), b = (n) => !!t.isHls || u && n.endsWith(".m3u8");
|
|
21
|
+
let y;
|
|
22
|
+
function m() {
|
|
23
|
+
y == null || y(), y = void 0, r.value && (r.value.destroy(), r.value = null);
|
|
23
24
|
const n = i.value;
|
|
24
25
|
if (n) {
|
|
25
26
|
for (n.pause(), n.removeAttribute("src"); n.firstChild; ) n.firstChild.remove();
|
|
26
27
|
n.load();
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
|
-
function
|
|
30
|
-
const
|
|
31
|
-
if (!
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
function M(n) {
|
|
31
|
+
const c = i.value;
|
|
32
|
+
if (!c || !n) return;
|
|
33
|
+
m();
|
|
34
|
+
const h = () => {
|
|
35
|
+
t.autoPlay && c.play().catch(() => {
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
if (b(n)) {
|
|
39
|
+
const g = new L(t.hlsConfig);
|
|
40
|
+
r.value = g, g.attachMedia(c), g.loadSource(n), g.on(L.Events.MANIFEST_PARSED, h), g.on(L.Events.ERROR, (S, E) => {
|
|
41
|
+
E.fatal && (g.destroy(), r.value = null);
|
|
42
|
+
});
|
|
43
|
+
} else
|
|
44
|
+
c.src = n, c.load(), c.addEventListener("loadedmetadata", h, { once: !0 }), y = () => {
|
|
45
|
+
c.removeEventListener("loadedmetadata", h);
|
|
46
|
+
};
|
|
39
47
|
}
|
|
40
|
-
return
|
|
41
|
-
t.src &&
|
|
48
|
+
return A(() => {
|
|
49
|
+
t.src && M(t.src);
|
|
42
50
|
}), D(
|
|
43
51
|
() => t.src,
|
|
44
52
|
(n) => {
|
|
45
|
-
n &&
|
|
53
|
+
n && M(n);
|
|
46
54
|
}
|
|
47
|
-
), N(
|
|
55
|
+
), N(m), s({ videoEl: i }), (n, c) => (d(), v("video", {
|
|
48
56
|
ref_key: "videoEl",
|
|
49
57
|
ref: i,
|
|
50
58
|
muted: e.muted,
|
|
@@ -54,22 +62,22 @@ const Y = ["muted", "loop", "controls", "autoplay", "playsinline", "preload", "p
|
|
|
54
62
|
playsinline: e.playsInline,
|
|
55
63
|
preload: e.preload,
|
|
56
64
|
poster: e.poster,
|
|
57
|
-
class:
|
|
58
|
-
onPlay:
|
|
59
|
-
onPause:
|
|
65
|
+
class: C(t.class),
|
|
66
|
+
onPlay: c[0] || (c[0] = (h) => f("play")),
|
|
67
|
+
onPause: c[1] || (c[1] = (h) => f("pause"))
|
|
60
68
|
}, [
|
|
61
|
-
|
|
62
|
-
], 42,
|
|
69
|
+
T(n.$slots, "default")
|
|
70
|
+
], 42, _));
|
|
63
71
|
}
|
|
64
|
-
}), j = { name: "IconDesktop" },
|
|
72
|
+
}), j = { name: "IconDesktop" }, F = /* @__PURE__ */ x({
|
|
65
73
|
...j,
|
|
66
74
|
props: {
|
|
67
75
|
class: {}
|
|
68
76
|
},
|
|
69
77
|
setup(e) {
|
|
70
78
|
const s = e;
|
|
71
|
-
return (o, t) => (
|
|
72
|
-
class:
|
|
79
|
+
return (o, t) => (d(), v("svg", {
|
|
80
|
+
class: C(["gvp-icon", s.class]),
|
|
73
81
|
width: "20",
|
|
74
82
|
height: "20",
|
|
75
83
|
viewBox: "0 0 24 24",
|
|
@@ -77,26 +85,26 @@ const Y = ["muted", "loop", "controls", "autoplay", "playsinline", "preload", "p
|
|
|
77
85
|
xmlns: "http://www.w3.org/2000/svg",
|
|
78
86
|
"aria-hidden": "true"
|
|
79
87
|
}, [...t[0] || (t[0] = [
|
|
80
|
-
|
|
88
|
+
p("path", {
|
|
81
89
|
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",
|
|
82
90
|
stroke: "currentColor",
|
|
83
91
|
"stroke-width": "1.5",
|
|
84
92
|
"stroke-linecap": "round"
|
|
85
93
|
}, null, -1),
|
|
86
|
-
|
|
94
|
+
p("path", {
|
|
87
95
|
d: "M11 15H13",
|
|
88
96
|
stroke: "currentColor",
|
|
89
97
|
"stroke-width": "1.5",
|
|
90
98
|
"stroke-linecap": "round",
|
|
91
99
|
"stroke-linejoin": "round"
|
|
92
100
|
}, null, -1),
|
|
93
|
-
|
|
101
|
+
p("path", {
|
|
94
102
|
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",
|
|
95
103
|
stroke: "currentColor",
|
|
96
104
|
"stroke-width": "1.5",
|
|
97
105
|
"stroke-linecap": "round"
|
|
98
106
|
}, null, -1),
|
|
99
|
-
|
|
107
|
+
p("path", {
|
|
100
108
|
d: "M7 22H17",
|
|
101
109
|
stroke: "currentColor",
|
|
102
110
|
"stroke-width": "1.5",
|
|
@@ -104,15 +112,15 @@ const Y = ["muted", "loop", "controls", "autoplay", "playsinline", "preload", "p
|
|
|
104
112
|
}, null, -1)
|
|
105
113
|
])], 2));
|
|
106
114
|
}
|
|
107
|
-
}),
|
|
108
|
-
...
|
|
115
|
+
}), J = { name: "IconMobile" }, O = /* @__PURE__ */ x({
|
|
116
|
+
...J,
|
|
109
117
|
props: {
|
|
110
118
|
class: {}
|
|
111
119
|
},
|
|
112
120
|
setup(e) {
|
|
113
121
|
const s = e;
|
|
114
|
-
return (o, t) => (
|
|
115
|
-
class:
|
|
122
|
+
return (o, t) => (d(), v("svg", {
|
|
123
|
+
class: C(["gvp-icon", s.class]),
|
|
116
124
|
width: "20",
|
|
117
125
|
height: "20",
|
|
118
126
|
viewBox: "0 0 24 24",
|
|
@@ -120,20 +128,20 @@ const Y = ["muted", "loop", "controls", "autoplay", "playsinline", "preload", "p
|
|
|
120
128
|
xmlns: "http://www.w3.org/2000/svg",
|
|
121
129
|
"aria-hidden": "true"
|
|
122
130
|
}, [...t[0] || (t[0] = [
|
|
123
|
-
|
|
131
|
+
p("path", {
|
|
124
132
|
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",
|
|
125
133
|
stroke: "currentColor",
|
|
126
134
|
"stroke-width": "2",
|
|
127
135
|
"stroke-linecap": "round"
|
|
128
136
|
}, null, -1),
|
|
129
|
-
|
|
137
|
+
p("path", {
|
|
130
138
|
d: "M11 19H13",
|
|
131
139
|
stroke: "currentColor",
|
|
132
140
|
"stroke-width": "2",
|
|
133
141
|
"stroke-linecap": "round",
|
|
134
142
|
"stroke-linejoin": "round"
|
|
135
143
|
}, null, -1),
|
|
136
|
-
|
|
144
|
+
p("path", {
|
|
137
145
|
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",
|
|
138
146
|
stroke: "currentColor",
|
|
139
147
|
"stroke-width": "2",
|
|
@@ -141,15 +149,15 @@ const Y = ["muted", "loop", "controls", "autoplay", "playsinline", "preload", "p
|
|
|
141
149
|
}, null, -1)
|
|
142
150
|
])], 2));
|
|
143
151
|
}
|
|
144
|
-
}),
|
|
145
|
-
...
|
|
152
|
+
}), X = { name: "IconPlay" }, q = /* @__PURE__ */ x({
|
|
153
|
+
...X,
|
|
146
154
|
props: {
|
|
147
155
|
class: {}
|
|
148
156
|
},
|
|
149
157
|
setup(e) {
|
|
150
158
|
const s = e;
|
|
151
|
-
return (o, t) => (
|
|
152
|
-
class:
|
|
159
|
+
return (o, t) => (d(), v("svg", {
|
|
160
|
+
class: C(["gvp-icon", s.class]),
|
|
153
161
|
width: "22",
|
|
154
162
|
height: "22",
|
|
155
163
|
viewBox: "0 0 16 16",
|
|
@@ -157,21 +165,21 @@ const Y = ["muted", "loop", "controls", "autoplay", "playsinline", "preload", "p
|
|
|
157
165
|
xmlns: "http://www.w3.org/2000/svg",
|
|
158
166
|
"aria-hidden": "true"
|
|
159
167
|
}, [...t[0] || (t[0] = [
|
|
160
|
-
|
|
168
|
+
p("path", {
|
|
161
169
|
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",
|
|
162
170
|
fill: "currentColor"
|
|
163
171
|
}, null, -1)
|
|
164
172
|
])], 2));
|
|
165
173
|
}
|
|
166
|
-
}), G = { name: "IconX" }, K = /* @__PURE__ */
|
|
174
|
+
}), G = { name: "IconX" }, K = /* @__PURE__ */ x({
|
|
167
175
|
...G,
|
|
168
176
|
props: {
|
|
169
177
|
class: {}
|
|
170
178
|
},
|
|
171
179
|
setup(e) {
|
|
172
180
|
const s = e;
|
|
173
|
-
return (o, t) => (
|
|
174
|
-
class:
|
|
181
|
+
return (o, t) => (d(), v("svg", {
|
|
182
|
+
class: C(["gvp-icon", s.class]),
|
|
175
183
|
width: "14",
|
|
176
184
|
height: "14",
|
|
177
185
|
viewBox: "0 0 14 14",
|
|
@@ -179,7 +187,7 @@ const Y = ["muted", "loop", "controls", "autoplay", "playsinline", "preload", "p
|
|
|
179
187
|
xmlns: "http://www.w3.org/2000/svg",
|
|
180
188
|
"aria-hidden": "true"
|
|
181
189
|
}, [...t[0] || (t[0] = [
|
|
182
|
-
|
|
190
|
+
p("path", {
|
|
183
191
|
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",
|
|
184
192
|
fill: "currentColor"
|
|
185
193
|
}, null, -1)
|
|
@@ -203,10 +211,10 @@ function Q(e) {
|
|
|
203
211
|
if (o === "youtube.com" || o === "m.youtube.com" || o === "music.youtube.com" || o === "youtube-nocookie.com") {
|
|
204
212
|
const t = s.searchParams.get("v");
|
|
205
213
|
if (t && /^[A-Za-z0-9_-]{11}$/.test(t)) return t;
|
|
206
|
-
const
|
|
214
|
+
const f = /^\/(?:embed|shorts|v|live)\/([A-Za-z0-9_-]{11})/.exec(
|
|
207
215
|
s.pathname
|
|
208
216
|
);
|
|
209
|
-
if (
|
|
217
|
+
if (f) return f[1];
|
|
210
218
|
}
|
|
211
219
|
return null;
|
|
212
220
|
}
|
|
@@ -217,7 +225,7 @@ function ee(e) {
|
|
|
217
225
|
if (/^\d+s?$/.test(o)) return Number.parseInt(o, 10);
|
|
218
226
|
const t = /^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/.exec(o);
|
|
219
227
|
if (t) {
|
|
220
|
-
const
|
|
228
|
+
const f = Number.parseInt(t[1] ?? "0", 10), i = Number.parseInt(t[2] ?? "0", 10), r = Number.parseInt(t[3] ?? "0", 10), u = f * 3600 + i * 60 + r;
|
|
221
229
|
return u > 0 ? u : null;
|
|
222
230
|
}
|
|
223
231
|
} catch {
|
|
@@ -228,7 +236,7 @@ function te(e, s = {}) {
|
|
|
228
236
|
const {
|
|
229
237
|
autoPlay: o = !1,
|
|
230
238
|
muted: t = !0,
|
|
231
|
-
loop:
|
|
239
|
+
loop: f = !1,
|
|
232
240
|
controls: i = !0,
|
|
233
241
|
startSeconds: r
|
|
234
242
|
} = s, u = new URLSearchParams({
|
|
@@ -237,7 +245,7 @@ function te(e, s = {}) {
|
|
|
237
245
|
playsinline: "1",
|
|
238
246
|
controls: i ? "1" : "0"
|
|
239
247
|
});
|
|
240
|
-
return o ? (u.set("autoplay", "1"), u.set("mute", "1")) : t && u.set("mute", "1"),
|
|
248
|
+
return o ? (u.set("autoplay", "1"), u.set("mute", "1")) : t && u.set("mute", "1"), f && (u.set("loop", "1"), u.set("playlist", e)), r && r > 0 && u.set("start", String(r)), `https://www.youtube-nocookie.com/embed/${e}?${u.toString()}`;
|
|
241
249
|
}
|
|
242
250
|
const oe = ["src"], le = {
|
|
243
251
|
key: 2,
|
|
@@ -255,7 +263,7 @@ const oe = ["src"], le = {
|
|
|
255
263
|
}, ce = {
|
|
256
264
|
key: 6,
|
|
257
265
|
class: "gvp-bottom-fade"
|
|
258
|
-
}, ve = /* @__PURE__ */
|
|
266
|
+
}, ve = /* @__PURE__ */ x({
|
|
259
267
|
__name: "VideoPlayer",
|
|
260
268
|
props: {
|
|
261
269
|
src: {},
|
|
@@ -277,86 +285,86 @@ const oe = ["src"], le = {
|
|
|
277
285
|
},
|
|
278
286
|
emits: ["close", "play", "pause"],
|
|
279
287
|
setup(e, { emit: s }) {
|
|
280
|
-
const o = e, t = s,
|
|
281
|
-
() =>
|
|
288
|
+
const o = e, t = s, f = w(null), i = w(o.defaultDevice), r = w(!1), u = w(!1), b = w(null), y = P(() => Q(o.src)), m = P(() => y.value !== null), M = P(
|
|
289
|
+
() => y.value ? te(y.value, {
|
|
282
290
|
autoPlay: o.autoPlay,
|
|
283
291
|
muted: o.muted,
|
|
284
292
|
loop: o.loop,
|
|
285
293
|
controls: o.controls,
|
|
286
294
|
startSeconds: ee(o.src)
|
|
287
295
|
}) : null
|
|
288
|
-
),
|
|
296
|
+
), n = P(
|
|
289
297
|
() => {
|
|
290
298
|
var a, l;
|
|
291
299
|
return i.value === "mobile" ? ((a = o.aspectRatio) == null ? void 0 : a.mobile) ?? "9/16" : ((l = o.aspectRatio) == null ? void 0 : l.desktop) ?? "16/9";
|
|
292
300
|
}
|
|
293
|
-
),
|
|
301
|
+
), c = P(
|
|
294
302
|
() => {
|
|
295
303
|
var a, l;
|
|
296
304
|
return i.value === "mobile" ? ((a = o.frameMaxWidth) == null ? void 0 : a.mobile) ?? "420px" : ((l = o.frameMaxWidth) == null ? void 0 : l.desktop) ?? "960px";
|
|
297
305
|
}
|
|
298
|
-
),
|
|
306
|
+
), h = P(() => {
|
|
299
307
|
var a;
|
|
300
|
-
return ((a =
|
|
308
|
+
return ((a = f.value) == null ? void 0 : a.videoEl) ?? null;
|
|
301
309
|
});
|
|
302
|
-
async function
|
|
303
|
-
const a =
|
|
310
|
+
async function g() {
|
|
311
|
+
const a = h.value;
|
|
304
312
|
if (a)
|
|
305
313
|
try {
|
|
306
314
|
a.readyState < 2 && a.load();
|
|
307
315
|
const l = a.play();
|
|
308
|
-
|
|
316
|
+
b.value = l, await l, r.value = !0;
|
|
309
317
|
} catch {
|
|
310
318
|
r.value = !1;
|
|
311
319
|
} finally {
|
|
312
|
-
|
|
320
|
+
b.value = null;
|
|
313
321
|
}
|
|
314
322
|
}
|
|
315
323
|
async function S() {
|
|
316
|
-
const a =
|
|
324
|
+
const a = h.value;
|
|
317
325
|
if (a) {
|
|
318
|
-
if (
|
|
326
|
+
if (b.value)
|
|
319
327
|
try {
|
|
320
|
-
await
|
|
328
|
+
await b.value;
|
|
321
329
|
} catch {
|
|
322
330
|
}
|
|
323
331
|
a.pause();
|
|
324
332
|
}
|
|
325
333
|
}
|
|
326
|
-
async function
|
|
327
|
-
!o.hoverPlay ||
|
|
334
|
+
async function E() {
|
|
335
|
+
!o.hoverPlay || m.value || await g();
|
|
328
336
|
}
|
|
329
|
-
async function
|
|
330
|
-
!o.hoverPlay ||
|
|
337
|
+
async function H() {
|
|
338
|
+
!o.hoverPlay || m.value || (await S(), r.value = !1);
|
|
331
339
|
}
|
|
332
|
-
async function
|
|
333
|
-
const a =
|
|
334
|
-
a && (a.paused ? await
|
|
340
|
+
async function I() {
|
|
341
|
+
const a = h.value;
|
|
342
|
+
a && (a.paused ? await g() : (await S(), r.value = !1));
|
|
335
343
|
}
|
|
336
|
-
function
|
|
337
|
-
u.value = !0,
|
|
344
|
+
function R() {
|
|
345
|
+
u.value = !0, E();
|
|
338
346
|
}
|
|
339
347
|
function V() {
|
|
340
|
-
u.value = !1,
|
|
348
|
+
u.value = !1, H();
|
|
341
349
|
}
|
|
342
|
-
return (a, l) => (
|
|
343
|
-
class:
|
|
344
|
-
style:
|
|
345
|
-
onMouseenter:
|
|
350
|
+
return (a, l) => (d(), v("div", {
|
|
351
|
+
class: C(["gvp-root", o.class]),
|
|
352
|
+
style: Z({ width: c.value, aspectRatio: n.value }),
|
|
353
|
+
onMouseenter: R,
|
|
346
354
|
onMouseleave: V
|
|
347
355
|
}, [
|
|
348
|
-
|
|
356
|
+
m.value ? (d(), v("iframe", {
|
|
349
357
|
key: 0,
|
|
350
358
|
class: "gvp-video gvp-youtube",
|
|
351
|
-
src:
|
|
359
|
+
src: M.value ?? void 0,
|
|
352
360
|
title: "YouTube video player",
|
|
353
361
|
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
|
|
354
362
|
allowfullscreen: "",
|
|
355
363
|
referrerpolicy: "strict-origin-when-cross-origin"
|
|
356
|
-
}, null, 8, oe)) : (
|
|
364
|
+
}, null, 8, oe)) : (d(), U(Y, {
|
|
357
365
|
key: 1,
|
|
358
366
|
ref_key: "hlsPlayerRef",
|
|
359
|
-
ref:
|
|
367
|
+
ref: f,
|
|
360
368
|
controls: e.controls,
|
|
361
369
|
"hls-config": e.hlsConfig,
|
|
362
370
|
"is-hls": e.isHls,
|
|
@@ -368,70 +376,70 @@ const oe = ["src"], le = {
|
|
|
368
376
|
src: e.src,
|
|
369
377
|
class: "gvp-video",
|
|
370
378
|
preload: "metadata",
|
|
371
|
-
onPause: l[0] || (l[0] = (
|
|
379
|
+
onPause: l[0] || (l[0] = (k) => {
|
|
372
380
|
r.value = !1, t("pause");
|
|
373
381
|
}),
|
|
374
|
-
onPlay: l[1] || (l[1] = (
|
|
382
|
+
onPlay: l[1] || (l[1] = (k) => {
|
|
375
383
|
r.value = !0, t("play");
|
|
376
384
|
})
|
|
377
385
|
}, {
|
|
378
|
-
default:
|
|
379
|
-
|
|
386
|
+
default: z(() => [
|
|
387
|
+
T(a.$slots, "default")
|
|
380
388
|
]),
|
|
381
389
|
_: 3
|
|
382
390
|
}, 8, ["controls", "hls-config", "is-hls", "loop", "muted", "auto-play", "poster", "src"])),
|
|
383
|
-
|
|
384
|
-
e.showDeviceToggle ? (
|
|
385
|
-
|
|
386
|
-
|
|
391
|
+
m.value ? $("", !0) : (d(), v("div", le)),
|
|
392
|
+
e.showDeviceToggle ? (d(), v("div", se, [
|
|
393
|
+
p("div", ae, [
|
|
394
|
+
p("button", {
|
|
387
395
|
"aria-pressed": i.value === "desktop",
|
|
388
|
-
class:
|
|
396
|
+
class: C(["gvp-toggle-btn", { "is-active": i.value === "desktop" }]),
|
|
389
397
|
"aria-label": "Desktop view",
|
|
390
398
|
type: "button",
|
|
391
|
-
onClick: l[2] || (l[2] = (
|
|
399
|
+
onClick: l[2] || (l[2] = (k) => i.value = "desktop")
|
|
392
400
|
}, [
|
|
393
|
-
B(
|
|
401
|
+
B(F)
|
|
394
402
|
], 10, ne),
|
|
395
|
-
l[7] || (l[7] =
|
|
396
|
-
|
|
403
|
+
l[7] || (l[7] = p("div", { class: "gvp-toggle-divider" }, null, -1)),
|
|
404
|
+
p("button", {
|
|
397
405
|
"aria-pressed": i.value === "mobile",
|
|
398
|
-
class:
|
|
406
|
+
class: C(["gvp-toggle-btn", { "is-active": i.value === "mobile" }]),
|
|
399
407
|
"aria-label": "Mobile view",
|
|
400
408
|
type: "button",
|
|
401
|
-
onClick: l[3] || (l[3] = (
|
|
409
|
+
onClick: l[3] || (l[3] = (k) => i.value = "mobile")
|
|
402
410
|
}, [
|
|
403
|
-
B(
|
|
411
|
+
B(O)
|
|
404
412
|
], 10, re)
|
|
405
413
|
])
|
|
406
|
-
])) :
|
|
407
|
-
e.closable ? (
|
|
414
|
+
])) : $("", !0),
|
|
415
|
+
e.closable ? (d(), v("button", {
|
|
408
416
|
key: 4,
|
|
409
417
|
"aria-label": "Close",
|
|
410
418
|
class: "gvp-close",
|
|
411
419
|
type: "button",
|
|
412
|
-
onClick: l[4] || (l[4] = (
|
|
420
|
+
onClick: l[4] || (l[4] = (k) => t("close"))
|
|
413
421
|
}, [
|
|
414
422
|
B(K)
|
|
415
|
-
])) :
|
|
416
|
-
!
|
|
417
|
-
|
|
423
|
+
])) : $("", !0),
|
|
424
|
+
!m.value && !r.value ? (d(), v("div", ue, [
|
|
425
|
+
p("button", {
|
|
418
426
|
"aria-label": "Play",
|
|
419
427
|
class: "gvp-play",
|
|
420
428
|
type: "button",
|
|
421
|
-
onClick:
|
|
422
|
-
onMouseenter: l[5] || (l[5] = (
|
|
423
|
-
onMouseleave: l[6] || (l[6] = (
|
|
429
|
+
onClick: I,
|
|
430
|
+
onMouseenter: l[5] || (l[5] = (k) => u.value = !0),
|
|
431
|
+
onMouseleave: l[6] || (l[6] = (k) => u.value = !1)
|
|
424
432
|
}, [
|
|
425
|
-
B(
|
|
426
|
-
e.tooltipText && u.value ? (
|
|
433
|
+
B(q),
|
|
434
|
+
e.tooltipText && u.value ? (d(), v("span", ie, W(e.tooltipText), 1)) : $("", !0)
|
|
427
435
|
], 32)
|
|
428
|
-
])) :
|
|
429
|
-
|
|
436
|
+
])) : $("", !0),
|
|
437
|
+
m.value ? $("", !0) : (d(), v("div", ce))
|
|
430
438
|
], 38));
|
|
431
439
|
}
|
|
432
440
|
});
|
|
433
441
|
export {
|
|
434
|
-
|
|
442
|
+
Y as HLSPlayer,
|
|
435
443
|
ve as VueVideoPlayer,
|
|
436
444
|
Q as parseYouTubeId,
|
|
437
445
|
ee as parseYouTubeStart,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/HLSPlayer.vue","../src/components/IconDesktop.vue","../src/components/IconMobile.vue","../src/components/IconPlay.vue","../src/components/IconX.vue","../src/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\nfunction cleanup() {\n if (hlsInstance.value) {\n hlsInstance.value.destroy();\n hlsInstance.value = null;\n }\n const el = videoEl.value;\n if (!el) return;\n el.pause();\n el.removeAttribute(\"src\");\n while (el.firstChild) el.firstChild.remove();\n el.load();\n}\n\nfunction initPlayer(src: string) {\n const el = videoEl.value;\n if (!el || !src) return;\n\n cleanup();\n\n if (shouldUseHls(src)) {\n const hls = new Hls(props.hlsConfig);\n hlsInstance.value = hls;\n hls.attachMedia(el);\n hls.loadSource(src);\n hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data.fatal) {\n hls.destroy();\n hlsInstance.value = null;\n }\n });\n } else {\n el.src = src;\n el.load();\n }\n}\n\nonMounted(() => {\n if (props.src) initPlayer(props.src);\n});\n\nwatch(\n () => props.src,\n (src) => {\n if (src) initPlayer(src);\n }\n);\n\nonUnmounted(cleanup);\n\ndefineExpose({ videoEl });\n</script>\n\n<template>\n <video\n ref=\"videoEl\"\n :muted=\"muted\"\n :loop=\"loop\"\n :controls=\"controls\"\n :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","cleanup","el","initPlayer","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.mjs","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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"}
|
package/package.json
CHANGED