Skip to content

Commit

Permalink
feat(vuetube): add vue 3 version
Browse files Browse the repository at this point in the history
  • Loading branch information
webistomin committed Apr 25, 2021
1 parent 651c2ca commit bd3c14b
Show file tree
Hide file tree
Showing 9 changed files with 1,794 additions and 1,159 deletions.
2 changes: 1 addition & 1 deletion .browserslistrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ not Edge < 79
iOS >= 10
Safari >= 10
Android >= 6
Explorer >= 11
Explorer > 11
2,576 changes: 1,591 additions & 985 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"prepare": "husky install"
},
"peerDependencies": {
"vue": "^2.6.12"
"vue": "^3.0.5"
},
"dependencies": {
"@types/youtube": "0.0.42"
Expand All @@ -92,7 +92,7 @@
"@storybook/addon-links": "^6.2.8",
"@storybook/addons": "^6.2.8",
"@storybook/theming": "^6.2.8",
"@storybook/vue": "^6.2.8",
"@storybook/vue3": "^6.2.9",
"@types/jest": "^26.0.22",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
Expand Down Expand Up @@ -123,7 +123,7 @@
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-vue": "^5.1.9",
"rollup-plugin-vue": "^6.0.0-beta.10",
"size-limit": "^4.10.2",
"stylelint": "^13.12.0",
"stylelint-config-rational-order": "^0.1.2",
Expand All @@ -132,9 +132,8 @@
"ts-jest": "^26.5.5",
"tsc-alias": "^1.2.9",
"typescript": "^4.2.4",
"vue": "^2.6.12",
"vue-loader": "^15.9.6",
"vue-template-compiler": "^2.6.12"
"vue": "^3.0.5",
"vue-loader": "^16.2.0"
},
"engines": {
"node": ">= 14.15.4",
Expand Down
133 changes: 59 additions & 74 deletions src/components/VueTube/VueTube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import {
import { createWarmLink } from '@/helpers/createWarmLink';
import { getStringifiedParams } from '@/helpers/getStringifiedParams';
import { loadYoutubeAPI } from '@/helpers/loadYoutubeAPI';
import { getNormalizeSlot } from '@/helpers/getNormalizedSlot';
import { isFunction } from '@/helpers/inspect';
import { TImageLoading } from '@/types/imageLoading';
import { TThumbnailResolution } from '@/types/thumbnailResolution';
import Vue, { PropType, VNode } from 'vue';
import {
defineComponent, h, PropType, VNode,
} from 'vue';

declare global {
interface Window {
Expand All @@ -25,7 +26,7 @@ declare global {
}
}

export default /* #__PURE__ */ Vue.extend({
export default /* #__PURE__ */ defineComponent({
name: 'VueTube',

props: {
Expand Down Expand Up @@ -94,7 +95,7 @@ export default /* #__PURE__ */ Vue.extend({
imageLoading: {
type: String as PropType<TImageLoading>,
default: 'lazy',
validator: (value) => ['lazy', 'eager', 'auto'].indexOf(value) !== -1,
validator: (value: string) => ['lazy', 'eager', 'auto'].indexOf(value) !== -1,
},
/**
* Thumbnail resolution from YouTube API
Expand All @@ -103,7 +104,7 @@ export default /* #__PURE__ */ Vue.extend({
resolution: {
type: String as PropType<TThumbnailResolution>,
default: 'sddefault',
validator: (value) => ['maxresdefault', 'sddefault', 'hqdefault', 'mqdefault', 'default'].indexOf(value) !== -1,
validator: (value: string) => ['maxresdefault', 'sddefault', 'hqdefault', 'mqdefault', 'default'].indexOf(value) !== -1,
},
/**
* Aria-label attribute for button
Expand Down Expand Up @@ -153,10 +154,21 @@ export default /* #__PURE__ */ Vue.extend({
player: null,
};
},

emits: [
'player:play',
'player:ready',
'player:statechange',
'player:playbackqualitychange',
'player:playbackratechange',
'player:error',
'player:apichange',
'player:load',
],
/**
* Clear out the reference to the destroyed player
*/
beforeDestroy() {
beforeUnmount() {
const { player } = this;

if (player !== null && typeof player.destroy === 'function') {
Expand Down Expand Up @@ -222,7 +234,6 @@ export default /* #__PURE__ */ Vue.extend({
*/
boxComponent(): VNode {
const {
$createElement,
calculatedAspectRatioPadding,
isPlayed,
iframeComponent,
Expand All @@ -232,22 +243,20 @@ export default /* #__PURE__ */ Vue.extend({
playVideo,
} = this;

const BOX_COMPONENT = $createElement(
const BOX_COMPONENT = h(
'div',
{
on: {
'~pointerover': warmConnections,
'~click': playVideo,
},
class: [
'vuetube',
{
'vuetube--played': isPlayed,
},
],
onPointerOverOnce: warmConnections,
onClickOnce: playVideo,
},
[
$createElement(
h(
'div',
{
class: 'vuetube__box',
Expand All @@ -271,8 +280,6 @@ export default /* #__PURE__ */ Vue.extend({
thumbnailComponent(): VNode | VNode[] {
const {
$slots,
$scopedSlots,
$createElement,
resolution,
videoId,
disableWebp,
Expand All @@ -283,73 +290,65 @@ export default /* #__PURE__ */ Vue.extend({
const webp = `${YTIMG_URL}/vi_webp/${videoId}/${resolution}.webp`;
const jpg = `${YTIMG_URL}/vi/${videoId}/${resolution}.jpg`;

const THUMBNAIL_COMPONENT = $createElement(
const THUMBNAIL_COMPONENT = h(
'picture',
{
class: [
'vuetube__thumbnail',
],
},
[
!disableWebp && $createElement(
!disableWebp && h(
'source',
{
attrs: {
srcset: webp,
type: 'image/webp',
},
srcset: webp,
type: 'image/webp',
},
),
$createElement(
h(
'source',
{
attrs: {
srcset: jpg,
type: 'image/jpeg',
},
srcset: jpg,
type: 'image/jpeg',
},
),
$createElement(
h(
'img',
{
class: [
'vuetube__image',
],
attrs: {
src: jpg,
alt: imageAlt,
loading: imageLoading,
},
src: jpg,
alt: imageAlt,
loading: imageLoading,
},
),
],
);

return getNormalizeSlot('thumbnail', {}, $slots, $scopedSlots) || THUMBNAIL_COMPONENT;
return $slots.thumbnail?.() || THUMBNAIL_COMPONENT;
},
/**
* Button component
*/
playBtnComponent(): VNode {
const {
$createElement,
buttonLabel,
playVideo,
playBtnIconComponent,
} = this;

const PLAY_BTN_COMPONENT = $createElement(
const PLAY_BTN_COMPONENT = h(
'button',
{
class: [
'vuetube__button',
],
attrs: {
type: 'button',
'aria-label': buttonLabel,
},
on: {
'~click': playVideo,
type: 'button',
'aria-label': buttonLabel,
onClick: {
handler: playVideo,
once: true,
},
},
[
Expand All @@ -364,74 +363,61 @@ export default /* #__PURE__ */ Vue.extend({
*/
playBtnIconComponent(): VNode | VNode[] {
const {
$createElement,
$slots,
$scopedSlots,
} = this;

const PLAY_BTN_ICON_COMPONENT = $createElement(
const PLAY_BTN_ICON_COMPONENT = h(
'svg',
{
attrs: {
xmlns: 'http://www.w3.org/2000/svg',
viewBox: '0 0 68 48',
class: 'vuetube__icon',
'aria-hidden': true,
focusable: 'false',
},
xmlns: 'http://www.w3.org/2000/svg',
viewBox: '0 0 68 48',
class: 'vuetube__icon',
'aria-hidden': true,
focusable: 'false',
},
[
$createElement(
h(
'path',
{
attrs: {
class: 'vuetube__icon-bg',
d: 'M66.52 7.74c-.78-2.93-2.49-5.41-5.42-6.19C55.79.13 34 0 34 0S12.21.13 6.9 1.55c-2.93.78-4.63 3.26-5.42 6.19C.06 13.05 0 24 0 24s.06 10.95 1.48 16.26c.78 2.93 2.49 5.41 5.42 6.19C12.21 47.87 34 48 34 48s21.79-.13 27.1-1.55c2.93-.78 4.64-3.26 5.42-6.19C67.94 34.95 68 24 68 24s-.06-10.95-1.48-16.26z',
},
class: 'vuetube__icon-bg',
d: 'M66.52 7.74c-.78-2.93-2.49-5.41-5.42-6.19C55.79.13 34 0 34 0S12.21.13 6.9 1.55c-2.93.78-4.63 3.26-5.42 6.19C.06 13.05 0 24 0 24s.06 10.95 1.48 16.26c.78 2.93 2.49 5.41 5.42 6.19C12.21 47.87 34 48 34 48s21.79-.13 27.1-1.55c2.93-.78 4.64-3.26 5.42-6.19C67.94 34.95 68 24 68 24s-.06-10.95-1.48-16.26z',
},
),
$createElement(
h(
'path',
{
attrs: {
class: 'vuetube__icon-triangle',
d: 'M45 24L27 14v20',
},
class: 'vuetube__icon-triangle',
d: 'M45 24L27 14v20',
},
),
],
);

return getNormalizeSlot('icon', {}, $slots, $scopedSlots) || PLAY_BTN_ICON_COMPONENT;
return $slots.icon?.() || PLAY_BTN_ICON_COMPONENT;
},
/**
* Iframe component
*/
iframeComponent(): VNode {
const {
$createElement,
iframeTitle,
onIframeLoad,
iframeAllow,
iframeUrl,
} = this;

const IFRAME_COMPONENT = $createElement(
const IFRAME_COMPONENT = h(
'iframe',
{
ref: 'iframe',
class: [
'vuetube__iframe',
],
attrs: {
src: iframeUrl,
allow: iframeAllow,
title: iframeTitle,
allowfullscreen: true,
},
on: {
load: onIframeLoad,
},
src: iframeUrl,
allow: iframeAllow,
title: iframeTitle,
allowfullscreen: true,
onLoad: onIframeLoad,
},
);

Expand Down Expand Up @@ -513,7 +499,6 @@ export default /* #__PURE__ */ Vue.extend({
const el = $refs.iframe as HTMLIFrameElement;
el.focus();

// @ts-expect-error check user vars
const SHOULD_LOAD_API = playerVars.enablejsapi === 1;

if (SHOULD_LOAD_API) {
Expand Down
Loading

0 comments on commit bd3c14b

Please sign in to comment.