Skip to content

Commit

Permalink
feat(player): new js player constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
mihar-22 committed Mar 15, 2024
1 parent d94fe45 commit 2876c73
Show file tree
Hide file tree
Showing 24 changed files with 1,266 additions and 103 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ packages/*/local/
packages/*/dist/
packages/*/cdn/
packages/*/elements/
packages/*/enhance/
packages/*/types/
packages/*/sandbox/
packages/*/stats.html
Expand Down
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

[![package-badge]][package]
[![discord-badge]][discord]
[![jsdelivr-badge]][jsdelivr]

Build and ship a production-ready video or audio player! Robust, customizable, and accessible. The
successor to [Plyr][plyr] `3.x` and [Vime][vime] `5.x`.
Expand Down Expand Up @@ -58,8 +57,6 @@ accounts:
[docs-player]: https://www.vidstack.io/docs/player
[package]: https://www.npmjs.com/package/vidstack
[package-badge]: https://img.shields.io/npm/v/vidstack/next?style=flat-square
[jsdelivr]: https://www.jsdelivr.com/package/npm/vidstack
[jsdelivr-badge]: https://data.jsdelivr.com/v1/package/npm/vidstack/badge
[discord]: https://discord.gg/QAjfh2gZE4
[discord-badge]: https://img.shields.io/discord/742612686679965696?color=%235865F2&label=%20&logo=discord&logoColor=white&style=flat-square
[discussions]: https://github.com/vidstack/player/discussions
3 changes: 0 additions & 3 deletions packages/vidstack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

[![package-badge]][package]
[![discord-badge]][discord]
[![jsdelivr-badge]][jsdelivr]

Vidstack is a video/audio platform for frontend developers to build high-quality and accessible
experiences on the web.
Expand All @@ -19,7 +18,5 @@ Vidstack is [MIT licensed](./LICENSE).
[plyr]: https://github.com/sampotts/plyr
[package]: https://www.npmjs.com/package/vidstack
[package-badge]: https://img.shields.io/npm/v/vidstack/next?style=flat-square
[jsdelivr]: https://www.jsdelivr.com/package/npm/vidstack
[jsdelivr-badge]: https://data.jsdelivr.com/v1/package/npm/vidstack/badge
[discord]: https://discord.gg/QAjfh2gZE4
[discord-badge]: https://img.shields.io/discord/742612686679965696?color=%235865F2&label=%20&logo=discord&logoColor=white&style=flat-square
12 changes: 11 additions & 1 deletion packages/vidstack/mangle.json
Original file line number Diff line number Diff line change
Expand Up @@ -832,5 +832,15 @@
"_isSubmenuOpen": "zo",
"_isTransitionActive": "yo",
"_updateFocus": "Bo",
"_wasKeyboardExpand": "xo"
"_wasKeyboardExpand": "xo",
"_isIntersecting": "Do",
"_isVisible": "Co",
"_onIntersectionChange": "Eo",
"_watchToggle": "Go",
"_watchUpdates": "Fo",
"_canIdle": "Ho",
"_listeners": "Io",
"_plyr": "Lo",
"_ratio": "Ko",
"_source": "Jo"
}
19 changes: 18 additions & 1 deletion packages/vidstack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
"bugs": {
"url": "https://github.com/vidstack/player/issues"
},
"jsdelivr": "./cdn/with-layouts/vidstack.js",
"exports": {
".": {
"types": "./index.d.ts",
Expand All @@ -117,6 +116,24 @@
"development": "./dist/dev/vidstack-elements.js",
"default": "./dist/prod/vidstack-elements.js"
},
"./enhance/player": {
"types": "./enhance/player.d.ts",
"node": "./dist/server/enhance/vidstack-player.js",
"deno": "./dist/server/enhance/vidstack-player.js",
"bun": "./dist/server/enhance/vidstack-player.js",
"workerd": "./dist/server/enhance/vidstack-player.js",
"development": "./dist/dev/enhance/vidstack-player.js",
"default": "./dist/prod/enhance/vidstack-player.js"
},
"./enhance/plyr": {
"types": "./enhance/plyr.d.ts",
"node": "./dist/server/enhance/plyr.js",
"deno": "./dist/server/enhance/plyr.js",
"bun": "./dist/server/enhance/plyr.js",
"workerd": "./dist/server/enhance/plyr.js",
"development": "./dist/dev/enhance/plyr.js",
"default": "./dist/prod/enhance/plyr.js"
},
"./icons": {
"types": "./icons.d.ts",
"node": "./dist/server/define/vidstack-icons.js",
Expand Down
5 changes: 5 additions & 0 deletions packages/vidstack/player/styles/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
width: 100%;
}

:where(video:not([width]):not([height]), iframe:not([width]):not([height])) {
width: 100%;
aspect-ratio: 16 / 9;
}

:where([data-media-provider] video),
:where([data-media-provider] iframe) {
aspect-ratio: inherit;
Expand Down
155 changes: 100 additions & 55 deletions packages/vidstack/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,7 @@ const MANGLE_CACHE = !MODE_TYPES ? await buildMangleCache() : {};

const NPM_EXTERNAL_PACKAGES = ['hls.js', 'media-captions', 'media-icons'],
CDN_EXTERNAL_PACKAGES = ['media-captions', 'media-icons'],
PLUGINS_EXTERNAL_PACKAGES = ['vite', 'rollup', /webpack/, /rspack/, 'esbuild', 'unplugin'],
NPM_BUNDLES = [
defineNPMBundle({ type: 'server' }),
defineNPMBundle({ type: 'dev' }),
defineNPMBundle({ type: 'prod' }),
],
CDN_BUNDLES = [
defineCDNBundle({ dev: true }),
defineCDNBundle({ dev: false }),
defineCDNBundle({ layout: 'all' }),
defineCDNBundle({ layout: 'default' }),
defineCDNBundle({ layout: 'plyr' }),
],
PLUGIN_BUNDLES = definePluginsBundle(),
TYPES_BUNDLES = defineTypesBundle();
PLUGINS_EXTERNAL_PACKAGES = ['vite', 'rollup', /webpack/, /rspack/, 'esbuild', 'unplugin'];

// Styles
if (!MODE_TYPES) {
Expand All @@ -50,24 +36,26 @@ if (!MODE_TYPES) {

export default defineConfig(
MODE_PLUGINS
? PLUGIN_BUNDLES
? getPluginsBundles()
: MODE_CDN
? CDN_BUNDLES
? getCDNBundles()
: MODE_WATCH
? [...NPM_BUNDLES, ...TYPES_BUNDLES]
? [...getNPMBundles(), ...getTypesBundles()]
: MODE_TYPES
? TYPES_BUNDLES
: [...NPM_BUNDLES, ...CDN_BUNDLES, ...PLUGIN_BUNDLES],
? getTypesBundles()
: [...getNPMBundles(), ...getLegacyCDNBundles(), ...getPluginsBundles()],
);

/**
* @returns {import('rollup').RollupOptions[]}
* */
function defineTypesBundle() {
function getTypesBundles() {
/** @type {Record<string, string>} */
const input = {
index: 'types/index.d.ts',
elements: 'types/elements/index.d.ts',
'enhance/player': 'types/enhance/player.d.ts',
'enhance/plyr': 'types/enhance/plyr.d.ts',
icons: 'types/elements/bundles/icons.d.ts',
};

Expand Down Expand Up @@ -127,6 +115,14 @@ function defineTypesBundle() {
* }} BundleOptions
*/

function getNPMBundles() {
return [
defineNPMBundle({ type: 'server' }),
defineNPMBundle({ type: 'dev' }),
defineNPMBundle({ type: 'prod' }),
];
}

/**
* @param {BundleOptions}
* @returns {import('rollup').RollupOptions}
Expand All @@ -136,6 +132,8 @@ function defineNPMBundle({ target, type, minify }) {
let input = {
vidstack: 'src/index.ts',
'vidstack-elements': 'src/elements/index.ts',
'enhance/vidstack-player': 'src/enhance/player.ts',
'enhance/plyr': 'src/enhance/plyr.ts',
'define/vidstack-icons': 'src/elements/bundles/icons.ts',
'define/vidstack-player': 'src/elements/bundles/player.ts',
'define/vidstack-player-ui': 'src/elements/bundles/player-ui.ts',
Expand Down Expand Up @@ -189,6 +187,12 @@ function defineNPMBundle({ target, type, minify }) {
async transform(code, id) {
if (id.includes('src/elements/bundles')) return '';

if (id.includes('src/enhance')) {
return code
.replace("import '../elements/bundles/player';", '')
.replace("import '../elements/bundles/player-layouts/plyr';", '');
}

if (id.includes('src/elements/index.ts')) {
await eslexer.init;
const [_, exports] = eslexer.parse(code),
Expand Down Expand Up @@ -218,61 +222,102 @@ function defineNPMBundle({ target, type, minify }) {
};
}

function getLegacyCDNBundles() {
return [
// Prod
defineCDNBundle({
input: 'src/elements/bundles/cdn/player.ts',
dir: 'cdn',
file: 'vidstack',
}),
// All Layouts
defineCDNBundle({
input: 'src/elements/bundles/cdn/player-with-layouts.ts',
dir: 'cdn/with-layouts',
file: 'vidstack',
}),
];
}

function getCDNBundles() {
const baseDir = 'cdn',
enhanceDir = `${baseDir}/enhance`,
layoutsDir = `${baseDir}/layouts`;
return [
// cdn.vidstack.io/dev.js
defineCDNBundle({
dev: true,
input: 'src/elements/bundles/cdn/player-with-layouts.ts',
dir: baseDir,
file: 'dev',
}),
// cdn.vidstack.io/prod.js
defineCDNBundle({
input: 'src/elements/bundles/cdn/player.ts',
dir: baseDir,
file: 'prod',
}),
// cdn.vidstack.io/enhance/player.js
defineCDNBundle({
input: 'src/enhance/player.ts',
dir: enhanceDir,
file: 'player',
}),
// cdn.vidstack.io/enhance/plyr.js
defineCDNBundle({
input: 'src/enhance/plyr.ts',
dir: enhanceDir,
file: 'plyr',
}),
// cdn.vidstack.io/layouts/all.js
defineCDNBundle({
input: 'src/elements/bundles/cdn/player-with-layouts.ts',
dir: layoutsDir,
file: 'all',
}),
// cdn.vidstack.io/layouts/default.js
defineCDNBundle({
input: 'src/elements/bundles/cdn/player-with-default.ts',
dir: layoutsDir,
file: 'default',
}),
// cdn.vidstack.io/layouts/plyr.js
defineCDNBundle({
input: 'src/elements/bundles/cdn/player-with-plyr.ts',
dir: layoutsDir,
file: 'plyr',
}),
];
}

/**
* @param {{ dev?: boolean; layout?: 'all' | 'default' | 'plyr' }} options
* @param {{ dev?: boolean; input: string; dir: string; file: string }} options
* @returns {import('rollup').RollupOptions}
*/
function defineCDNBundle({ dev = false, layout } = {}) {
function getInput() {
if (!dev && !layout) {
return 'src/elements/bundles/cdn/player.ts';
} else if (dev || layout === 'all') {
return 'src/elements/bundles/cdn/player-with-layouts.ts';
} else if (layout === 'default') {
return 'src/elements/bundles/cdn/player-with-default.ts';
} else if (layout === 'plyr') {
return 'src/elements/bundles/cdn/player-with-plyr.ts';
}
}

function getOutputDir() {
if (dev || !layout) {
return 'cdn';
} else if (layout === 'all') {
return 'cdn/with-layouts';
} else if (layout === 'default') {
return 'cdn/with-layouts/default';
} else if (layout === 'plyr') {
return 'cdn/with-layouts/plyr';
}
}

const input = getInput(),
outputFile = dev ? `vidstack.dev` : `vidstack`;

function defineCDNBundle({ dev = false, input, dir, file }) {
return {
...defineNPMBundle({
type: dev ? 'dev' : 'prod',
minify: !dev,
target: 'es2020',
}),
input: {
[outputFile]: input,
[file]: input,
...getProviderInputs(),
},
output: {
format: 'esm',
dir: getOutputDir(),
dir,
chunkFileNames: `chunks/vidstack-[hash].js`,
entryFileNames: (chunk) => {
return chunk.name.startsWith('vidstack') ? `[name].js` : `[name]-[hash].js`;
return chunk.name === file ? `[name].js` : `[name]-[hash].js`;
},
paths: {
'media-icons': 'https://cdn.jsdelivr.net/npm/media-icons@next/dist/lazy.js',
'media-captions': 'https://cdn.jsdelivr.net/npm/media-captions@next/dist/prod.js',
},
manualChunks(id) {
if (dev) return outputFile; // no chunks in dev
if (dev) return file; // no chunks in dev
if (id.includes('maverick') || id.includes('@floating-ui')) return 'frameworks';
return null;
},
Expand Down Expand Up @@ -343,7 +388,7 @@ function getProviderInputs() {
}

/** @returns {import('rollup').RollupOptions[]} */
function definePluginsBundle() {
function getPluginsBundles() {
return [
{
input: 'src/plugins.ts',
Expand Down
9 changes: 7 additions & 2 deletions packages/vidstack/src/components/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ export class MediaPlayer
@prop
readonly canPlayQueue = new RequestQueue();

@prop
readonly remoteControl: MediaRemoteControl;

private get _provider() {
return this._media.$provider() as AnyMediaProvider | null;
}
Expand Down Expand Up @@ -164,7 +167,9 @@ export class MediaPlayer
}

if (__DEV__) context.logger = new Logger();
context.remote = new MediaRemoteControl(__DEV__ ? context.logger : undefined);
context.remote = this.remoteControl = new MediaRemoteControl(
__DEV__ ? context.logger : undefined,
);
context.remote.setPlayer(this);
context.$iosControls = computed(this._isIOSControls.bind(this));
context.textTracks = new TextTrackList();
Expand Down Expand Up @@ -267,7 +272,7 @@ export class MediaPlayer
setAttribute(
this.el!,
'aria-label',
`${typeText} Player` + (currentTitle ? `- ${currentTitle}` : ''),
`${typeText} Player` + (currentTitle ? ` - ${currentTitle}` : ''),
);

// Title attribute is removed to prevent popover interfering with user hovering over player.
Expand Down
1 change: 1 addition & 0 deletions packages/vidstack/src/components/provider/tracks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { effect, type ReadSignal } from 'maverick.js';

import type { MediaContext } from '../../core/api/media-context';
import { TextTrack, type TextTrackInit } from '../../core/tracks/text/text-track';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { onDispose } from 'maverick.js';
import { listenEvent } from 'maverick.js/std';

import { isElementParent } from '../../../utils/dom';
import { isElementParent, isHTMLElement } from '../../../utils/dom';

const FOCUSABLE_ELEMENTS_SELECTOR = /* #__PURE__*/ [
'a[href]',
Expand Down Expand Up @@ -162,7 +162,7 @@ export class MenuFocusController {
for (const el of focusableElements) {
// Filter out elements that belong to child submenus.
if (
el instanceof HTMLElement &&
isHTMLElement(el) &&
el.offsetParent !== null && // does not have display: none
isElementParent(this._el, el, is)
) {
Expand Down
Loading

0 comments on commit 2876c73

Please sign in to comment.