vue-lite-youtube-embed
Version:
A private by default, faster and cleaner YouTube embed component for Vue applications.
244 lines (241 loc) • 6.97 kB
JavaScript
// src/LiteYouTubeEmbed.ts
import { computed, defineComponent, isVue2 as isVue22, ref } from "vue-demi";
// src/utils.ts
import { h as hDemi, isVue2 } from "vue-demi";
function adaptOnsV3(ons) {
if (!ons)
return null;
return Object.entries(ons).reduce((ret, [key, handler]) => {
key = key.charAt(0).toUpperCase() + key.slice(1);
key = `on${key}`;
return { ...ret, [key]: handler };
}, {});
}
function h(type, options = {}, children) {
if (isVue2)
return hDemi(type, options, children);
const { props, domProps, on, attrs, ...extraOptions } = options;
const ons = adaptOnsV3(on);
const params = { ...extraOptions, ...props, ...domProps, ...ons, ...attrs };
return hDemi(type, params, children);
}
var utils_default = h;
// src/LiteYouTubeEmbed.ts
function runCommand(iframe, func) {
if (iframe === null)
throw new Error("iframe element not instantiated.");
iframe.contentWindow?.postMessage(`{"event":"command","func":"${func}","args":""}`, "*");
}
function linkPreconnect(href) {
return utils_default("link", {
attrs: { rel: "preconnect", href }
});
}
var LiteYouTubeEmbed_default = defineComponent({
props: {
announce: {
type: String,
required: false,
default: "Watch"
},
id: {
type: String,
required: true
},
title: {
type: String,
required: true
},
activatedClass: {
type: String,
required: false,
default: "lyt-activated"
},
adNetwork: {
type: Boolean,
required: false,
default: true
},
iframeClass: {
type: String,
required: false,
default: ""
},
cookie: {
type: Boolean,
required: false,
default: false
},
params: {
type: String,
required: false,
default: ""
},
playerClass: {
type: String,
required: false,
default: "lty-playbtn"
},
playlist: {
type: Boolean,
required: false,
default: false
},
playlistCoverId: {
type: String,
required: false,
default: ""
},
poster: {
type: String,
required: false,
default: "hqdefault"
},
wrapperClass: {
type: String,
required: false,
default: "yt-lite"
},
muted: {
type: Boolean,
required: false,
default: false
},
thumbnail: {
type: String,
required: false
},
webp: {
type: Boolean,
required: false,
default: false
},
rel: {
type: String,
required: false,
default: "preload"
},
aspectHeight: {
type: Number,
required: false,
default: 9
},
aspectWidth: {
type: Number,
required: false,
default: 16
}
},
emits: ["iframeAdded"],
setup(props, { emit, expose }) {
const preconnected = ref(false);
const iframe = ref(false);
const iframeElement = ref(null);
const videoId = computed(() => encodeURIComponent(props.id));
const paramsImp = computed(() => `&${props.params}` || "");
const mutedImp = computed(() => props.muted ? "&mute=1" : "");
const format = computed(() => props.webp ? "webp" : "jpg");
const vi = computed(() => props.webp ? "vi_webp" : "vi");
const videoPlaylistCoverId = computed(() => typeof props.playlistCoverId === "string" ? encodeURIComponent(props.playlistCoverId) : null);
const posterUrl = computed(() => {
return props.thumbnail || (!props.playlist ? `https://i.ytimg.com/${vi.value}/${videoId.value}/${props.poster}.${format.value}` : `https://i.ytimg.com/${vi.value}/${videoPlaylistCoverId.value}/${props.poster}.${format.value}`);
});
const ytUrl = computed(() => props.cookie ? "https://www.youtube.com" : "https://www.youtube-nocookie.com");
const iframeSrc = computed(() => !props.playlist ? `${ytUrl.value}/embed/${videoId.value}?autoplay=1&enablejsapi=1&state=1${mutedImp.value}${paramsImp.value}` : `${ytUrl.value}/embed/videoseries?autoplay=1&enablejsapi=1&list=${videoId.value}${mutedImp.value}${paramsImp.value}`);
function addIframe() {
if (iframe.value)
return;
iframe.value = true;
emit("iframeAdded");
}
function warmConnections() {
if (preconnected.value)
return;
preconnected.value = true;
}
expose({
getPlayerInstance() {
return iframeElement.value;
},
stopVideo() {
runCommand(iframeElement.value, "stopVideo");
},
pauseVideo() {
runCommand(iframeElement.value, "pauseVideo");
},
playVideo() {
runCommand(iframeElement.value, "playVideo");
},
warmConnections,
addIframe
});
const vnodeList = () => [
utils_default("link", {
attrs: {
rel: props.rel,
href: posterUrl.value,
as: "image"
}
}),
preconnected.value ? linkPreconnect(ytUrl.value) : null,
preconnected.value ? linkPreconnect("https://www.google.com") : null,
props.adNetwork ? linkPreconnect("https://static.doubleclick.net") : null,
props.adNetwork ? linkPreconnect("https://googleads.g.doubleclick.net") : null,
utils_default(
"article",
{
on: {
pointerover: warmConnections,
click: addIframe
},
class: `${props.wrapperClass} ${iframe.value ? props.activatedClass : ""}`,
attrs: { "data-title": props.title },
style: {
"backgroundImage": `url(${posterUrl.value})`,
"--aspect-ratio": `${props.aspectHeight / props.aspectWidth * 100}%`
}
},
[
// Play button
utils_default("button", {
class: props.playerClass,
attrs: {
"type": "button",
"aria-label": `${props.announce} ${props.title}`
}
}),
// Iframe
iframe.value ? utils_default("iframe", {
ref: iframeElement,
class: props.iframeClass,
attrs: {
title: props.title,
width: 560,
height: 315,
frameborder: 0,
allow: "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture",
allowfullscreen: true,
src: iframeSrc.value
}
}) : null
]
)
];
if (isVue22)
return () => utils_default("Fragment", {}, vnodeList());
return () => vnodeList();
}
});
// src/index.ts
var src_default = LiteYouTubeEmbed_default;
export {
src_default as default
};
/*!
* Original code by Ibrahim Cesar
* MIT Licensed, Copyright 2022 Ibrahim Cesar, see https://github.com/ibrahimcesar/react-lite-youtube-embed/blob/main/LICENSE for details
*
* Credits to the team:
* https://github.com/ibrahimcesar/react-lite-youtube-embed/blob/main/src/lib/index.tsx
*/
//# sourceMappingURL=index.js.map